繁体   English   中英

为什么在运行“For Loop”的 vba 代码复制数据时出现“脚本超出范围”错误?

[英]Why am I getting a “Script out of range” error while running the vba code for “For Loop” to copy data?

Sub GenerateProductionReport() '*Let’s define the variables* Dim GCell As Range Dim Txt$, MyPath$, MyWB$, MySheet$ Dim myValue As Integer Dim Number As Integer Dim cmdprodhrsreport As Long Dim LastRow As Long Dim r As Long Dim LastRowRpt As Long '*Search what* MyPath = "\\Mypath\xxx\xxx\xxx\" '*The name of the workbook to be searched* MyWB = "Daily Data Tracker.xlsx" Workbooks.Open FileName:=MyPath & MyWB LastRow = Worksheets("Sheet1").Range("A" & Rows.count).End(xlUp).Row '*Use the current sheet to store the found data* For r = 2 To LastRow 'In ThisWorkbook.Worksheets If Worksheets("Sheet1").Range("D" & r).Value = Adminaccess.txtstartdate.Value Then'problem here for next r Worksheets("Sheet1").Range("D" & r & ":G" & r & ",K" & r & ":Q" & r).Copy Application.ScreenUpdating = False ThisWorkbook.Worksheets("Production").Activate '*Range("A2:K99999").ClearContents* MySheet = ActiveSheet.Name '*Range("A2:K99999").ClearContents* LastRowRpt = Worksheets("Production").Range("A" & Rows.count).End(xlUp).Row Worksheets("Production").Range("A" & LastRowRpt + 1).Select ActiveSheet.Paste End If Next r 'ThisWorkbook.Worksheets("Sheet1").SetFocus '*Close data workbook; don’t save it; turn screen updating back on* ActiveWorkbook.Close savechanges:=False Application.ScreenUpdating = True Exit Sub End Sub

由于ThisWorkbook.Worksheets("Production").Activate在循环中,在下一次迭代Worksheets("Sheet1")将属于ThisWorkbook

要成为/保持属于MyWB的那个,就像我想的那样,您必须在代码的开头使用:

Dim sh1 as Worksheet

MyWB打开Set sh1 = Worksheets("Sheet1")

其次是LastRow = sh1.Range("A" & Rows.count).End(xlUp).Row

然后,将有问题的行更改为

sh1.Range("D" & r & ":G" & r & ",K" & r & ":Q" & r).Copy

“下标超出范围”(运行时错误 9)是一个常见错误,这意味着您正在尝试使用该数组/集合中不存在的下标从数组或集合中检索项目。

Dim things(0 To 9) As Long
things(10) = 42 '<~ "subscript out of range"

当您尝试按名称从Sheets集合中检索Worksheet时,Excel object model 会引发该错误,但指定的工作表在提供的Sheets集合中不存在。

ActiveWorkbook.Worksheets("boom") '<~ if sheet is not in ActiveWorkbook sheets, error 9 is raised.

诀窍是始终明确哪些对象属于什么。 例如:

 Workbooks.Open FileName:=MyPath & MyWB LastRow = Worksheets("Sheet1").Range("A" & Rows.count).End(xlUp).Row

在这里,我们明确说明了此Range调用应使用的Worksheet (但Rows隐含地使用ActiveSheet限定),但Worksheets集合隐含地引用ActiveWorkbook的任何内容。 这行得通,因为那时我们刚刚打开了一个工作簿,因此该工作簿必须处于活动状态!

Workbooks.Open是一个function ,它返回对打开的Workbook object 的引用。 考虑捕获该引用并消除对函数副作用的隐含依赖:

Dim book As Workbook
Set book = Application.Workbooks.Open(MyPath & MyWB)

所以在这里:

 '*Use the current sheet to store the found data* For r = 2 To LastRow 'In ThisWorkbook.Worksheets If Worksheets("Sheet1").Range("D" & r).Value = Adminaccess.txtstartdate.Value Then'problem here for next r Worksheets("Sheet1").Range("D" & r & ":G" & r & ",K" & r & ":Q" & r).Copy

如果意图是迭代ThisWorkbook中的行,那不是这里发生的事情,因为If Worksheets("Sheet1")...没有明确说明它正在处理的工作簿,所以如果ActiveWorkbook不是ThisWorkbook并且没有工作表在那里命名为“Sheet1”,会引发错误 9。

不合格, Worksheets指的是ActiveWorkbook.Worksheets ,除非代码是在ThisWorkbook模块中编写的(请参阅此答案了解原因)。

因此,最简单的解决方案是对事物进行限定:

'*Use the current sheet to store the found data*
For r = 2 To LastRow 'In ThisWorkbook.Worksheets
    If ThisWorkbook.Worksheets("Sheet1").Range("D" & r).Value = Adminaccess.txtstartdate.Value Then'problem here for next r
         ThisWorkbook.Worksheets("Sheet1").Range("D" & r & ":G" & r & ",K" & r & ":Q" & r).Copy

现在代码说明了它的作用,并按照它所说的去做 - 没有隐含地依赖副作用和全局 state。

如果在编译时ThisWorkbook中存在“Sheet1”( ThisWorkbook始终是包含您的 VBA 项目的工作簿),那么您可以使用工作表的CodeName定义一个编译时标识符,您可以按原样使用该标识符来引用该特定在代码中的任何地方工作- 例如,如果您在 VBE 的项目资源管理器中找到“Sheet1”,然后探索其属性 (F4),您可以将其(Name)属性从Sheet1更改为有意义的东西。

与“生产”表相同,可能只是ProductionSheet ,然后不再需要从任何Sheets集合中取消引用它,它就在那里等待使用。

避免隐式ActiveWorkbook引用——真正的解决方案是永远不要Activate任何东西; 解决方案是停止对属于 object 的隐式限定成员调用(即Worksheet -> someWorkbook.WorksheetsRange -> someSheet.Range )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM