0

I am looking for VBA code that will copy invoice data to a separate worksheet with a button (e.g. "Save Invoice"), a button that saves the file as .pdf and finally a button with a macro to reset the invoice sheet ("Reset invoice"). I tried some VBA solutions, but I can't seem to find a feasible solution.

  • Each new saved input should be saved in an empty row below the previous saved output
  • All inputs/rows within the invoice should be copied if they contain data
  • A button with "Save as pdf"
  • A button to "clear the sheet"

Code:

Sub InvoiceToRecords()

    LastRecordsRow = Worksheets("Invoice Data").UsedRange.Rows.Count
    'determines the # of rows used

    NewRecordsRow = LastRecordsRow + 1
    'Row for pasting latest invoice will be 1 row below the end of the last invoice

    Sheets("Invoice").Activate

    Range("Invoice").Copy Sheets("Invoice Data").Range("D" & Rows.Count).End(xlUp).Offset(1, 0)

    Range("Customer").Copy Sheets("Invoice Data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
    Range("Invoice Number").Copy Sheets("Invoice Data").Range("B" & Rows.Count).End(xlUp).Offset(1, 0)
    Range("Invoice Date").Copy Sheets("Invoice Data").Range("C" & Rows.Count).End(xlUp).Offset(1, 0)

End Sub

Invoice

Invoice Data

Highlighted code

Error message Syntax error

Lorenz
  • 13
  • 1
  • 7
  • I recommend to use any of that thousands of thousands of billing softwares out there instead of re-inventing the wheel. There are even many free and open source ones. They are secure, safe and ready to use. I think this question is too broad to answer anyway, because it is not one question is is a bunch of questions. – Pᴇʜ Feb 26 '18 at 10:59
  • A quick search of each of your questions will help you on your way, to get you started, save a sheet as PDF: https://stackoverflow.com/questions/20750854/excel-vba-to-export-selected-sheets-to-pdf There is plenty of help online regarding the rest of the questions. Try putting something together and if you get stuck, come back with what you have tried and what the problem is. – 5202456 Feb 26 '18 at 11:17
  • @Pᴇʜ thank you for the response! I am working on this for my team who all prefer excel. For ease of use I would like to stay within excel. The main goal is to copy the invoice inputs to the separate sheet. Thanks! – Lorenz Feb 26 '18 at 11:20
  • @Thom Hi Thom, thanks for the feedback. The main issue with copying the data to the other sheet is that the secondary data (company, invoice number, invoice date) is only copied once instead of the amount of copied rows. – Lorenz Feb 26 '18 at 11:22
  • @Lorenz can you show the code you are using to save the primary data (Invoice lines)? – Xabier Feb 26 '18 at 11:48
  • @Xabier Hi! "Range("Invoice").Copy Sheets("Invoice Data").Range("D" & Rows.Count).End(xlUp).Offset(1, 0). " is used to copy and paste the invoice data. "Invoice" is a named range from A9:E20, not the name of the sheet (just realized it is a bit confusing) – Lorenz Feb 26 '18 at 12:05
  • @Lorenz Might be just my opinion but: For ease of use I would definitely move over to a lightweight program designed for that purpose. In my eyes it's like using a Ferrari to carry trees out of the wood. Just the wrong tool. Even they sell it with a trailer hitch no one would call that a good idea. No one would hammer a screw into the wall (because there is a tool for it) even if it might look that a hammer is easier to use. – Pᴇʜ Feb 26 '18 at 12:50

1 Answers1

0

To copy the secondary data as many times as there are invoice details lines, you could do that as below, just replace your code with this one:

Sub InvoiceToRecords()
Dim ws As Worksheet: Set ws = Worksheets("Invoice")
Dim wsData As Worksheet: Set wsData = Worksheets("Invoice Data")
'declare and set the worksheets, amend as required
Dim i As Long, dataRows As Long

    dataRows = ws.Range("Invoice").Columns(1).SpecialCells(xlCellTypeConstants, 23).Count
    'count the number of Invoice lines with data (non-empty)
    ws.Range("Invoice").Copy wsData.Range("D" & Rows.Count).End(xlUp).Offset(1, 0)
    'copy invoice lines to Invoice Data
    For i = 1 To dataRows 'loop from 1 to however many lines your named range "Invoice" has
        ws.Range("Customer").Copy wsData.Range("A" & Rows.Count).End(xlUp).Offset(1, 0)
        ws.Range("Invoice Number").Copy wsData.Range("B" & Rows.Count).End(xlUp).Offset(1, 0)
        ws.Range("Invoice Date").Copy wsData.Range("C" & Rows.Count).End(xlUp).Offset(1, 0)
    Next i
End Sub

To save your worksheet as PDF, the following will do, I would use some sort of variable to generate the PDF filename, so you don't keep overwriting the same file, maybe a combination of company & invoice number or even a timestamp would do:

Sub foo()
    Dim ws As Worksheet: Set ws = Sheets("Sheet1")
    Filen = "C:\Users\Lorenz\Desktop\NewPdf.pdf"
    'amend filename & path to save above
    ws.ExportAsFixedFormat Type:=xlTypePDF, _
    Filename:=Filen, _
    Quality:=xlQualityStandard, _
    IncludeDocProperties:=True, _
    IgnorePrintAreas:=False, _
    OpenAfterPublish:=False
End Sub

UPDATE:

Putting it all together now:

Sub InvoiceToRecords()
Dim ws As Worksheet: Set ws = Worksheets("Invoice")
Dim wsData As Worksheet: Set wsData = Worksheets("Invoice Data")
'declare and set the worksheets, amend as required
Dim i As Long, dataRows As Long
'TRANSFER data to Invoice Data
    dataRows = ws.Range("Invoice").Columns(1).SpecialCells(xlCellTypeConstants, 23).Count
    'count the number of Invoice lines with data (non-empty)
    ws.Range("Invoice").Copy wsData.Range("D" & Rows.Count).End(xlUp).Offset(1, 0)
    'copy invoice lines to Invoice Data
    For i = 1 To dataRows 'loop from 1 to however many lines your named range "Invoice" has
        ws.Range("Customer").Copy
        wsData.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
        ws.Range("Invoice Number").Copy
        wsData.Range("B" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
        ws.Range("Invoice Date").Copy
        wsData.Range("C" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
    Next i

'SAVE Invoice as PDF
FilenameValue = ws.Range("Customer") & "_Invoice" & ws.Range("Invoice Number")
FilenameValue = Replace(FilenameValue, " ", "") 'remove spaces
FilenameValue = Replace(FilenameValue, ".", "_") 'replace dots with underscore
Filen = "C:\Users\Lorenz\Desktop\" & FilenameValue & ".pdf"
'amend filename & path to save above
ws.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=Filen, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=False

'CLEAR ranges ready for next invoice
ws.Range("Invoice").ClearContents
ws.Range("Customer").ClearContents
ws.Range("Invoice Number").ClearContents
ws.Range("Invoice Date").ClearContents
End Sub
Xabier
  • 7,587
  • 1
  • 8
  • 20
  • Thanks for the update. I tried the code but it pastes the values 12 times in columns A - C ("Customer", "Invoice Number" & "Invoice Date"). The amount of rows of the Invoice inputs is only 3. – Lorenz Feb 26 '18 at 12:32
  • @Lorenz, I've literally just updated my answer, please try now. It will count how many non-empty rows there are in your named range, and paste only that many... – Xabier Feb 26 '18 at 12:34
  • Tried out the code and it works! Thank you very much! I will now try to figure out the pdf function & clear contents macro. :) – Lorenz Feb 26 '18 at 15:26
  • @Lorenz, I've updated my answer to include a way to save your Invoice as a PDF and then clear contents of your Invoice. Hope it helps! :) – Xabier Feb 26 '18 at 15:45
  • Awesome! I tried to run the code but receive "error while printing" as output. Any suggestions? :) I added screenshots on top. – Lorenz Feb 26 '18 at 17:12
  • @Lorenz, sorry no idea, I have limited experience with exporting as PDF,... Unless you have spaces or special characters within Customer or Invoice Number, which would affect it when exporting. I will update the answer to include a way to remove them. – Xabier Feb 26 '18 at 17:17
  • @Lorenz, please also check the path, is it valid, did you amend that line? – Xabier Feb 26 '18 at 17:21
  • I put the correct path. The code is now working, however it sends the sheets to the printer and it does not show as a pdf in the desktop folder. – Lorenz Feb 26 '18 at 19:53
  • I would like to just copy the values (instead of the formulas). I tried to add ".value" but the code doesn't work... :) thanks! – Lorenz Mar 01 '18 at 16:28
  • I tried to add it to the code but I keep receiving syntax errors. Any tips? :) – Lorenz Mar 07 '18 at 14:51
  • @Lorenz which line of code is giving you the syntax error? – Xabier Mar 07 '18 at 15:24
  • the following line: ws.Range("Customer").Copy wsData.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues It directly gives the error, regardless of the position within the code. – Lorenz Mar 07 '18 at 22:42
  • @Lorenz I've tested the code and it works for me, maybe you should check that your named ranges are written accurately? I'm not sure what else to suggest as it is doing it for me.... – Xabier Mar 08 '18 at 10:10