簡體   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