我正在尝试将数据从excelsheet导出到excel发票模板。我拥有的VBA代码将每行视为不同的发票,因此为每行制作不同的工作簿。因此,如果我有1张发票,其中有3种产品,则此代码会将每个产品(行)视为单独的发票,这是不正确的。我想以一种方式修改它,如果在下一行中重复发票编号(PiNo),则意味着下一个产品(行)仅属于上述发票。我是VBA的新手,因此我从另一个站点获取了代码。
这里是代码:-
Private Sub CommandButton1_Click()
Dim customername As String
Dim customeraddress As String
Dim invoicenumber As Long
Dim r As Long
Dim mydate As String
Dim path As String
Dim myfilename As String
lastrow = Sheets(“CustomerDetails”).Range(“H” & Rows.Count).End(xlUp).Row
r = 2
For r = 2 To lastrow
ClientName = Sheets("CustomerDetails").Cells(r, 6).Value
Address = Sheets("CustomerDetails").Cells(r, 13).Value
PiNo = Sheets("CustomerDetails").Cells(r, 5).Value
Qty = Sheets("CustomerDetails").Cells(r, 9).Value
Description = Sheets("CustomerDetails").Cells(r, 12).Value
UnitPrice = Sheets("CustomerDetails").Cells(r, 10).Value
Salesperson = Sheets("CustomerDetails").Cells(r, 1).Value
PoNo = Sheets("CustomerDetails").Cells(r, 3).Value
PiDate = Sheets("CustomerDetails").Cells(r, 4).Value
Paymentterms = Sheets("CustomerDetails").Cells(r, 7).Value
PartNo = Sheets("CustomerDetails").Cells(r, 8).Value
Shipdate = Sheets("CustomerDetails").Cells(r, 14).Value
Dispatchthrough = Sheets("CustomerDetails").Cells(r, 15).Value
Modeofpayment = Sheets("CustomerDetails").Cells(r, 16).Value
VAT = Sheets("CustomerDetails").Cells(r, 17).Value
Workbooks.Open ("C:\Users\admin\Desktop\InvoiceTemplate.xlsx")
ActiveWorkbook.Sheets("InvoiceTemplate").Activate
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“Z8”).Value = PiDate
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“AG8”).Value = PiNo
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“AN8”).Value = PoNo
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“B16”).Value = ClientName
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“B17”).Value = Address
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“B21”).Value = Shipdate
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“K21”).Value = Paymentterms
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“T21”).Value = Salesperson
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“AC21”).Value = Dispatchthrough
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“AL21”).Value = Modeofpayment
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“B25”).Value = PartNo
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“J25”).Value = Description
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“Y25”).Value = Qty
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“AF25”).Value = UnitPrice
ActiveWorkbook.Sheets("InvoiceTemplate").Range(“AL39”).Value = VAT
path = "C:\Users\admin\Desktop\Invoices\"
ActiveWorkbook.SaveAs Filename:=path & PiNo & “.xlsx”
myfilename = ActiveWorkbook.FullName
ActiveWorkbook.Close SaveChanges:=True
Next r
End Sub
“ H”是产品列,数据从第2行开始。第1行是标题。
关于您要实现的功能与当前代码的关系,有几个方面需要解决。我将在下面以不特定的顺序进行概述,并提供一些示例代码来帮助您实现所需的目标。
for
循环的内部中。这意味着如果我们假设您有3种产品要添加到发票中,则您的代码将在桌面上总共打开[[3次,并保存并用InvoiceTemplate.xlsx
将其关闭名称3次。要解决此问题,您应该移动代码以在PiNo
循环开始之前打开工作簿,然后将For
代码移到循环之后,以便仅保存和关闭工作簿一次。 SaveAs
,几乎完全引用了.activate
(如果您不声明工作簿,它将假定为ActiveWorkbook
)。应该避免这种情况,而应该明确地定义要使用的对象(为什么已经进行了很长的讨论,为什么要这样做呢?您可以在此处阅读更多内容:ActiveWorkbook
。Variant
循环写入变量以设置单元格引用,这意味着即使我们解决了所有其他问题,代码也只会在每次循环迭代时覆盖相同的单元格。可以通过将行值设置为变量并在每次循环迭代中将其递增来解决(假设这是模板的完成方式)。for
OR LoopRow
代替RowCounterForLoop
,r
OR InvoiceTemplatePath
代替SavedInvoicesPath
。
path
变量(但只需将更改复制到其他每个相关变量中): PiNo
以上内容无法解决所有问题,并且有更好,更有效的方法来实现您想要的目标,但确实可以为您的问题提供答案。您可能要考虑以下内容,以进一步改进您的代码:
使用数组存储数据,然后将其写入新工作簿。 (根据使用VBA阵列的技巧,这可能会非常棘手)
Private Sub CommandButton1_Click()
Dim LastRow As Long
Dim RowCounterForLoop As Long
Dim InvoiceTemplateRowCounter as Long
Dim DesktopFilePath As String
Dim SavedInvoiceFilePath As String
Dim PiNo As String
LastRow = ThisWorkbook.Sheets("CustomerDetails").Range("H" & Rows.Count).End(xlUp).Row
InvoiceTemplateRowCounter = 8
DesktopFilePath = "C:\Users\admin\Desktop\"
SavedInvoiceFilePath = "C:\Users\admin\Desktop\Invoices\"
Workbooks.Open (DesktopFilePath & "InvoiceTemplate.xlsx")
For RowCounterForLoop = 2 To lastrow 'I've removed the previous assignment of 2 to RowCounterForLoop as it is assigned on this line.
PiNo = ThisWorkbook.Sheets("CustomerDetails").Cells(r, 5).Value 'I've added ThisWorkbook before the Sheet which explicitly defines the code to affect the workbook the code is running on. It also uses a variable instead of number to allow dynamic referencing to the range.
Workbooks("InvoiceTemplate.xlsx").Sheets("InvoiceTemplate").Range("AG" & InvoiceTemplateRowCounter).Value = PiNo 'I've added Workbooks("InvoiceTemplate.xlsx") to explicitly run this code on that workbook which avoids using ActiveWorkbook.
InvoiceTemplateRowCounter = InvoiceTemplateRowCounter + 1
Next RowCounterForLoop
Workbooks("InvoiceTemplate.xlsx").SaveAs Filename:=SavedInvoiceFilePath & PiNo & ".xlsx"
Workbooks("InvoiceTemplate.xlsx").Close SaveChanges:=False 'The file is saved on the previous line so this will avoid saving again and pop up prompts etc.
End Sub
(当有多个产品时,您可以使用PiNo
方法(取决于您的工作表的确切工作方式),您可以阅读有关Range.FillDown
的信息