在VBA中定义LastRow

问题描述 投票:0回答:1

我正在尝试将数据从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行是标题。

enter image description here

enter image description here

enter image description here

excel vba invoice
1个回答
0
投票

关于您要实现的功能与当前代码的关系,有几个方面需要解决。我将在下面以不特定的顺序进行概述,并提供一些示例代码来帮助您实现所需的目标。

  1. 您的创建,保存和关闭新工作簿的代码包含在for循环的内部中。这意味着如果我们假设您有3种产品要添加到发票中,则您的代码将在桌面上总共打开[[3次,并保存并用InvoiceTemplate.xlsx将其关闭名称3次。要解决此问题,您应该移动代码以在PiNo循环开始之前打开工作簿,然后将For代码移到循环之后,以便仅保存和关闭工作簿一次。
  2. 您的代码使用SaveAs,几乎完全引用了.activate(如果您不声明工作簿,它将假定为ActiveWorkbook)。应该避免这种情况,而应该明确地定义要使用的对象(为什么已经进行了很长的讨论,为什么要这样做呢?您可以在此处阅读更多内容:ActiveWorkbook
  3. 您已经声明了一些实际上不使用的变量。请使用它们或将其删除以使代码混乱。
  4. 您尚未声明用于存储工作表中值的变量(在for循环的开始),这意味着它们会自动创建为How To Avoid Using Select in Excel数据类型,效率不高。
  5. Variant循环写入变量以设置单元格引用,这意味着即使我们解决了所有其他问题,代码也只会在每次循环迭代时覆盖相同的单元格。可以通过将行值设置为变量并在每次循环迭代中将其递增来解决(假设这是模板的完成方式)。
  • 作为补充;在调试错误时(尤其是当您不熟悉VBA时),使用更长但更具描述性的变量名可以使工作变得更加轻松,因此您可能需要对所有变量进行考虑。例如。for

    OR LoopRow代替RowCounterForLoopr 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的信息
  • © www.soinside.com 2019 - 2024. All rights reserved.