【问题标题】:defining LastRow in VBA在 VBA 中定义最后一行
【发布时间】:2020-04-03 15:37:47
【问题描述】:

我正在尝试将数据从 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

【问题讨论】:

  • 您的第二张图片缺少链接。
  • 我将同一张图片粘贴了两次。因此删除了第二个。
  • 问题是什么?
  • 制作理想化引号“”正则引号""
  • SO 在这里回答关于您遇到的错误的具体问题。错误是您的代码有错误并且无法运行,或者它没有给出预期的结果。你的错误是什么?

标签: excel vba invoice


【解决方案1】:

当涉及到您想要实现的目标与您当前的代码时,有几个方面需要解决。我将在下面不按特定顺序概述这一点,并提供一些示例代码来帮助您实现您想要的。

  1. 您用于创建、保存和关闭新工作簿的代码包含在您的for 循环中。这意味着,如果我们假设您有 3 个产品要添加到您的发票中,您的代码将从桌面打开 InvoiceTemplate.xlsx 总共 3 次,然后保存并使用PiNo 姓名 3 次。要解决此问题,您应该在For 循环开始之前移动代码以打开工作簿,并将SaveAs 代码移动到循环之后,这样它只会保存和关闭工作簿一次。
  2. 您的代码使用.activate 并且几乎完全引用了ActiveWorkbook(如果您不声明工作簿,它将假定为ActiveWorkbook)。应该避免这种情况,您应该明确定义您正在使用的对象(为什么要这样做已经详细讨论过 - 您可以在此处阅读更多信息:How To Avoid Using Select in Excel
  3. 您已经声明了一些实际上并没有使用的变量。使用它们或删除它们以整理代码。
  4. 您尚未声明存储工作表中值的变量(在 for 循环开始时),这意味着它们会自动创建为数据类型 Variant,这不是很有效。
  5. for 循环写入变量以设置单元格引用,这意味着即使我们修复了所有其他问题,代码也会在每次循环迭代时覆盖相同的单元格。这可以通过将行值设置为变量并在每次循环迭代时递增它来解决(假设这是模板应该完成的方式)。

作为一个支点;使用更长但更具描述性的变量名称可以使调试错误时的工作更加轻松,尤其是当您是 VBA 新手时,因此您可能希望对所有变量都考虑这一点。例如。 LoopRow OR RowCounterForLoop 而不是 rInvoiceTemplatePath OR SavedInvoicesPath 而不是 path

这是一个示例代码,让您了解如何在考虑上述几点的情况下实现一些更改,其中我们将仅使用 PiNo 变量(但只需将更改复制到每个其他相关变量) :

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

以上内容并不能解决所有问题,有更好、更有效的方法来实现您想要的,但它确实为您的问题提供了答案。

您可能需要考虑以下事项以进一步改进您的代码:

  1. 使用数组存储数据,然后将其写入新工作簿。 (这可能会相当棘手,具体取决于您在 VBA 中使用数组的技能)
  2. 要在每一行中输入PiNo(当有超过 1 个产品时),您可以使用Range.FillDown 方法(取决于您的工作表的工作方式),您可以阅读有关Here. 的信息

【讨论】:

  • 您好,非常感谢您的帮助。谢谢!但我认为我应该放弃这个想法来使用 VBA,因为我遇到了错误并且我无法确定它是关于什么的。我想我应该花一些时间学习 VBA,直到那时我必须手动完成。我可以用这段代码避免 80% 的手动任务,但让我们忘记它吧。再次感谢您的帮助!
  • 我不会再问你关于代码的问题,但你能帮我提供一些好的网站/页面/书籍来参考学习 VBA(不仅是初学者,而且更高级别)。
  • 如果你让我们知道你遇到了什么错误,也许有人可以帮助你解决它。
  • @TanvirAnsari 让我知道这几个细节;它是什么类型的错误,什么数字? (例如运行时错误 91)。它什么时候发生在您的代码中? (如果您还不知道,您可以逐行通过F8 的代码来确定导致错误的行。
  • @TanvirAnsari 我不知道很多书籍或资源,但我通过搜索我遇到的错误并阅读这里的大多数其他问题和答案来学习 VBA。一旦我开始了解不同功能、方法等的基础知识。在 MSDN 网站上(VBA 的官方文档 - 在 pc 上我会发布一个链接),我在这里问了很好的问题,我还和一个人一起工作过非常擅长在 excel 中使用 VBA,他向我展示了一些东西。
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 2017-10-28
  • 2013-04-27
相关资源
最近更新 更多