简体   繁体   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

Because of ThisWorkbook.Worksheets("Production").Activate in the loop, at next iteration Worksheets("Sheet1") will belong to ThisWorkbook .由于ThisWorkbook.Worksheets("Production").Activate在循环中,在下一次迭代Worksheets("Sheet1")将属于ThisWorkbook

To be/remain the one belonging to MyWB , like I suppose, you must use at the beginning of the code:要成为/保持属于MyWB的那个,就像我想的那样,您必须在代码的开头使用:

Dim sh1 as Worksheet

and after MyWB opening Set sh1 = Worksheets("Sheet1")MyWB打开Set sh1 = Worksheets("Sheet1")

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

Then, change the problematic line in然后,将有问题的行更改为

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

"Subcript out of range" (run-time error 9) is a common error that means you're trying to retrieve an item from an array or collection, using a subscript that doesn't exist in that array/collection. “下标超出范围”(运行时错误 9)是一个常见错误,这意味着您正在尝试使用该数组/集合中不存在的下标从数组或集合中检索项目。

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

The Excel object model raises that error when you try to retrieve a Worksheet from a Sheets collection by name, but the specified sheet doesn't exist in the supplied Sheets collection.当您尝试按名称从Sheets集合中检索Worksheet时,Excel object model 会引发该错误,但指定的工作表在提供的Sheets集合中不存在。

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

The trick is to always be explicit about what objects belong to what.诀窍是始终明确哪些对象属于什么。 For example:例如:

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

Here we're explicit about what Worksheet this Range call should work with (but Rows is implicitly qualified with the ActiveSheet ), but the Worksheets collection is implicitly referring to whatever the ActiveWorkbook is.在这里,我们明确说明了此Range调用应使用的Worksheet (但Rows隐含地使用ActiveSheet限定),但Worksheets集合隐含地引用ActiveWorkbook的任何内容。 That works, because by then we've just opened a workbook so that workbook must be active!这行得通,因为那时我们刚刚打开了一个工作簿,因此该工作簿必须处于活动状态!

Workbooks.Open is a function that returns a reference to the opened Workbook object. Workbooks.Open是一个function ,它返回对打开的Workbook object 的引用。 Consider capturing that reference and removing the implicit reliance on the function's side-effects:考虑捕获该引用并消除对函数副作用的隐含依赖:

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

So here:所以在这里:

 '*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

If the intent is to iterate rows in ThisWorkbook , that's not what's happening here, because If Worksheets("Sheet1")... isn't explicit about what workbook it's working against, so if the ActiveWorkbook isn't ThisWorkbook and there's no worksheet named "Sheet1" in there, that throws error 9.如果意图是迭代ThisWorkbook中的行,那不是这里发生的事情,因为If Worksheets("Sheet1")...没有明确说明它正在处理的工作簿,所以如果ActiveWorkbook不是ThisWorkbook并且没有工作表在那里命名为“Sheet1”,会引发错误 9。

Unqualified, Worksheets refers to ActiveWorkbook.Worksheets unless the code is written in the ThisWorkbook module (see this answer for why).不合格, Worksheets指的是ActiveWorkbook.Worksheets ,除非代码是在ThisWorkbook模块中编写的(请参阅此答案了解原因)。

So the simplest solution is to just qualify things:因此,最简单的解决方案是对事物进行限定:

'*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

Now the code says what it does, and does what it says - without implicitly relying on side-effects and global state.现在代码说明了它的作用,并按照它所说的去做 - 没有隐含地依赖副作用和全局 state。

If "Sheet1" exists in ThisWorkbook at compile-time ( ThisWorkbook is always the workbook that contains your VBA project), then you can use the sheet's CodeName to define a compile-time identifier that you can use as-is to refer to that specific sheet anywhere in the code - for example if you found the "Sheet1" in the VBE's Project Explorer and then explored its properties (F4), you could change its (Name) property from Sheet1 to something meaningful.如果在编译时ThisWorkbook中存在“Sheet1”( ThisWorkbook始终是包含您的 VBA 项目的工作簿),那么您可以使用工作表的CodeName定义一个编译时标识符,您可以按原样使用该标识符来引用该特定在代码中的任何地方工作- 例如,如果您在 VBE 的项目资源管理器中找到“Sheet1”,然后探索其属性 (F4),您可以将其(Name)属性从Sheet1更改为有意义的东西。

Same with the "Production" sheet, could be just ProductionSheet , and then there's no need to dereference it from any Sheets collection anymore, it's just there waiting to be used.与“生产”表相同,可能只是ProductionSheet ,然后不再需要从任何Sheets集合中取消引用它,它就在那里等待使用。

Avoid implicit ActiveWorkbook references - the real solution is never to Activate anything;避免隐式ActiveWorkbook引用——真正的解决方案是永远不要Activate任何东西; the solution is to stop implicitly qualifying member calls (ie Worksheet -> someWorkbook.Worksheets , Range -> someSheet.Range ) that belong to an object.解决方案是停止对属于 object 的隐式限定成员调用(即Worksheet -> someWorkbook.WorksheetsRange -> someSheet.Range )。

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

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