VBA下标超出范围 – 错误9
有人可以帮我用这个代码,我得到一个下标超出范围的错误:
“创build工作表”之后的行在debugging器中以黄色突出显示
'Validation of year If TextBox_Year.Value = Format(TextBox_Year.Value, "0000") Then 'Creating Process 'Creation of new sheet Workbooks.Add ActiveWorkbook.SaveAs FileName:= _ "" & Workbooks("Temperature Charts Sheet Creator").Sheets("MENU").Cells(4, 12).Value & "Data Sheet - " & ComboBox_Month.Value & " " & TextBox_Year.Value & ".xls", FileFormat _ :=xlNormal, Password:="", WriteResPassword:="", ReadOnlyRecommended:= _ False, CreateBackup:=False 'Creating of the sheets Windows("Data Sheet - " & ComboBox_Month.Value & " " & TextBox_Year.Value & ".xls").Activate Sheets("Sheet3").Select Sheets("Sheet3").Name = "31 " & ComboBox_Month.Value Sheets("Sheet2").Select Sheets("Sheet2").Name = "30 " & ComboBox_Month.Value Sheets("Sheet1").Select Sheets("Sheet1").Name = "29 " & ComboBox_Month.Value For i = 28 To 1 Step -1 Sheets.Add ActiveSheet.Name = i & " " & ComboBox_Month.Value Next
build议进行以下简化:从Workbooks.Add
获取返回值,而不是对Windows()
进行下标,如下所示:
Set wkb = Workbooks.Add wkb.SaveAs ... wkb.Activate ' instead of Windows(expression).Activate
一般哲学咨询:
避免使用Excel的内置插件:ActiveWorkbook,ActiveSheet和Selection:捕获返回值,并且偏好限定的expression式。
使用内置插件只有一次,只在最外面的macros(子),并在macros开始捕获,例如
Set wkb = ActiveWorkbook Set wks = ActiveSheet Set sel = Selection
在macros和macros内不要依赖这些内置的名称,而是捕获返回值,例如
Set wkb = Workbooks.Add 'instead of Workbooks.Add without return value capture wkb.Activate 'instead of Activeworkbook.Activate
另外,尝试使用限定的expression式,例如
wkb.Sheets("Sheet3").Name = "foo" ' instead of Sheets("Sheet3").Name = "foo"
要么
Set newWks = wkb.Sheets.Add newWks.Name = "bar" 'instead of ActiveSheet.Name = "bar"
使用合格的expression式,例如
newWks.Name = "bar" 'instead of `xyz.Select` followed by Selection.Name = "bar"
这些方法在一般情况下会更好地工作,给出更less的混淆结果,重构时更加健壮(例如,在方法内部和方法之间移动代码行),并且可以在各个版本的Excel中更好地工作。 例如,在从一个Excel版本到另一个版本的macros执行过程中,select会有所不同。
另外请注意,您可能会发现,您不需要使用更多限定的expression式时,几乎可以.Activate
。 (这可能意味着用户的屏幕将闪烁less)。因此,整个行Windows(expression).Activate
可以简单地被消除,而不是被wkb.Activate
所取代。
(另请注意:我认为你所显示的.Select语句没有贡献,可以省略。)
(我认为Excel的macroslogging器负责使用ActiveSheet,ActiveWorkbook,Selection和Select来推广这种更脆弱的编程风格;这种风格留下了很大的改进空间。)
当您尝试引用无效集合的索引时,会出现下标超出范围错误。
很可能,Windows中的索引实际上并不包含.xls。 窗口的索引应与Excel的标题栏中显示的工作簿的名称相同。
作为一个猜测,我会尝试使用这个:
Windows("Data Sheet - " & ComboBox_Month.Value & " " & TextBox_Year.Value).Activate
Option Explicit Private Sub CommandButton1_Click() Dim mode As String Dim RecordId As Integer Dim Resultid As Integer Dim sourcewb As Workbook Dim targetwb As Workbook Dim SourceRowCount As Long Dim TargetRowCount As Long Dim SrceFile As String Dim TrgtFile As String Dim TitleId As Integer Dim TestPassCount As Integer Dim TestFailCount As Integer Dim myWorkbook1 As Workbook Dim myWorkbook2 As Workbook TitleId = 4 Resultid = 0 Dim FileName1, FileName2 As String Dim Difference As Long 'TestPassCount = 0 'TestFailCount = 0 'Retrieve number of records in the TestData SpreadSheet Dim TestDataRowCount As Integer TestDataRowCount = Worksheets("TestData").UsedRange.Rows.Count If (TestDataRowCount <= 2) Then MsgBox "No records to validate.Please provide test data in Test Data SpreadSheet" Else For RecordId = 3 To TestDataRowCount RefreshResultSheet 'Source File row count SrceFile = Worksheets("TestData").Range("D" & RecordId).Value Set sourcewb = Workbooks.Open(SrceFile) With sourcewb.Worksheets(1) SourceRowCount = .Cells(.Rows.Count, "A").End(xlUp).row sourcewb.Close End With 'Target File row count TrgtFile = Worksheets("TestData").Range("E" & RecordId).Value Set targetwb = Workbooks.Open(TrgtFile) With targetwb.Worksheets(1) TargetRowCount = .Cells(.Rows.Count, "A").End(xlUp).row targetwb.Close End With ' Set Row Count Result Test data value TitleId = TitleId + 3 Worksheets("Result").Range("A" & TitleId).Value = Worksheets("TestData").Range("A" & RecordId).Value 'Compare Source and Target Row count Resultid = TitleId + 1 Worksheets("Result").Range("A" & Resultid).Value = "Source and Target record Count" If (SourceRowCount = TargetRowCount) Then Worksheets("Result").Range("B" & Resultid).Value = "Passed" Worksheets("Result").Range("C" & Resultid).Value = "Source Row Count: " & SourceRowCount & " & " & " Target Row Count: " & TargetRowCount TestPassCount = TestPassCount + 1 Else Worksheets("Result").Range("B" & Resultid).Value = "Failed" Worksheets("Result").Range("C" & Resultid).Value = "Source Row Count: " & SourceRowCount & " & " & " Target Row Count: " & TargetRowCount TestFailCount = TestFailCount + 1 End If 'For comparison of two files FileName1 = Worksheets("TestData").Range("D" & RecordId).Value FileName2 = Worksheets("TestData").Range("E" & RecordId).Value Set myWorkbook1 = Workbooks.Open(FileName1) Set myWorkbook2 = Workbooks.Open(FileName2) Difference = Compare2WorkSheets(myWorkbook1.Worksheets("Sheet1"), myWorkbook2.Worksheets("Sheet1")) myWorkbook1.Close myWorkbook2.Close 'MsgBox Difference 'Set Result of data validation in result sheet Resultid = Resultid + 1 Worksheets("Result").Activate Worksheets("Result").Range("A" & Resultid).Value = "Data validation of source and target File" If Difference > 0 Then Worksheets("Result").Range("B" & Resultid).Value = "Failed" Worksheets("Result").Range("C" & Resultid).Value = Difference & " cells contains different data!" TestFailCount = TestFailCount + 1 Else Worksheets("Result").Range("B" & Resultid).Value = "Passed" Worksheets("Result").Range("C" & Resultid).Value = Difference & " cells contains different data!" TestPassCount = TestPassCount + 1 End If Next RecordId End If UpdateTestExecData TestPassCount, TestFailCount End Sub Sub RefreshResultSheet() Worksheets("Result").Activate Worksheets("Result").Range("B1:B4").Select Selection.ClearContents Worksheets("Result").Range("D1:D4").Select Selection.ClearContents Worksheets("Result").Range("B1").Value = Worksheets("Instructions").Range("D3").Value Worksheets("Result").Range("B2").Value = Worksheets("Instructions").Range("D4").Value Worksheets("Result").Range("B3").Value = Worksheets("Instructions").Range("D6").Value Worksheets("Result").Range("B4").Value = Worksheets("Instructions").Range("D5").Value End Sub Sub UpdateTestExecData(TestPassCount As Integer, TestFailCount As Integer) Worksheets("Result").Range("D1").Value = TestPassCount + TestFailCount Worksheets("Result").Range("D2").Value = TestPassCount Worksheets("Result").Range("D3").Value = TestFailCount Worksheets("Result").Range("D4").Value = ((TestPassCount / (TestPassCount + TestFailCount))) End Sub