所以我要做的是每年创建一个新的工作簿。如果工作簿的某个工作表中存在两个不同年份的数据,则会创建一个新工作簿。当它看到两年不同时,它会创建一个新工作簿,将.bat文件导入新工作簿,然后将新工作簿中的信息从旧工作簿粘贴到新工作簿中。然后它再添加三张纸,并按照在旧工作簿中命名的方式命名它们。我遇到的问题是当我为新工作簿运行宏时,它说“Sheet2”为空,然后抛出错误。我知道所有4张纸都在那里因为我看到它们在我修改代码时被添加了。但是当我进入VBA编辑器时,我在Microsoft Excel Objects文件夹下看到的只是“Sheet1(...)和ThisWorkbook。它应该显示”Sheet1(...)“,”Sheet2(...)“, “Sheet3(...)”和“Sheet4(...)”。因此,某些内容未从新工作簿传输到VBA编辑器中。
我已经尝试将旧数据传输到另一个工作簿并导入宏以查看它是否是特定于工作簿(它不是)。我已经尝试创建一个循环来激活每个工作表在新工作簿中运行宏以查看VBA是否会识别它,然后在使用旧工作簿添加所有工作表之后保存新工作簿之前和之后添加延迟宏:
我试图避免重大改写它。
Sub NewYearNewFile(WashN As Variant, savepathname As String, FileYearNumber As Variant) 'This sub is to avoid crossover of data from multiple years in one spreadhseet
'After copy and paste is complete, then compare the years on sheet one and copy next years data over to a new worksheet--------
Dim NextRow As Integer, FinalColumn As Integer, FinalYear As String
Dim i As Long, newworkbook As Workbook, NextRow4 As Integer
Dim VBProj As Object
Dim savepath As String
Dim FileName As String
Sheet1.Activate 'activates sheet 1
NextRow = Cells(Rows.Count, 1).End(xlUp).Row 'Find the last row# of important data
FinalColumn = Cells(1, Columns.Count).End(xlToLeft).Column 'finds the rightmost column
FinalYear = Year(Sheet1.Cells(NextRow, 1).Value) 'finds the year in the final row and uses this for the new filename
NextRow4 = Sheet4.Cells(Rows.Count, 1).End(xlUp).Row 'Find the last row# of important data
'the folderpath of the Master Macro File (used when createing a new excel file)
Dim MMacroFilePath As String 'defines and states the filepath of the stored macto to import
MMacroFilePath = "L:\MCP\Conformal Coat & Wash\Aquastorm50\DataLogs\Compiled data" & _
"\Automated Files\THE ULTIMATE MACRO.bas" 'the macro filepath
FileName = "Wash " & WashN & " Data " & FinalYear & ".xlsm" 'saved filename format
savepath = savepathname & FileName 'complete file path of the saved excel file
'Compare the final year of recorded data to the year number in the filename. If they are not the same, do the following.
'If they are the same, do nothing and finish the copy and paste portions of the code.
If FinalYear <> FileYearNumber Then
'Go to the row 200 before the last one, and begin comparing dates.
For i = NextRow - 200 To NextRow 'from 200 lines up from the bottom to the bottom row
If Year(Sheet1.Cells(i, 1).Value) <> CInt(FileYearNumber) Then 'if the year in this row doesnt match the file name year
Cells(i, 1).Resize(NextRow - i + 1, FinalColumn).Cut 'cut this row and all rows below it
Set newworkbook = Workbooks.Add 'create a new workbook
newworkbook.Activate 'activate this workbook
Set VBProj = Nothing 'clearing the variable
Set VBProj = ActiveWorkbook.VBProject 'defines the variable
VBProj.VBComponents.Import MMacroFilePath 'imports this macro into the new workbook
With newworkbook
.Sheets("Sheet1").Paste 'pastes it to the first sheet in the new file
.Sheets("Sheet1").Rows(1).EntireRow.Insert 'adds a new row for headers when they get inserted later
.Sheets(1).Name = Sheet1.Name
.Sheets.Add 'add sheet2 to the workbook
.Sheets(1).Name = Sheet2.Name
.Sheets.Add 'add sheet3 to the workbook
.Sheets(1).Name = Sheet3.Name
.Sheets.Add 'add sheet4 to the workbook
.Sheets(1).Name = Sheet4.Name
End With
GoTo CCheck: 'tells the code to skip looping and goto the end of the sub
End If
Next i
'This moves any data from the Chem Check sheet to the new workbook
CCheck: 'once the data from sheet one moves over, the code goes here
For i = NextRow4 - 8 To NextRow4 'from 8 lines up from the bottom to the bottom row
If IsDate(Sheet4.Cells(i, 1).Value) And Year(Sheet4.Cells(i, 1).Value) <> CInt(FileYearNumber) Then 'if the year in this row doesnt match the file name year
Sheet4.Cells(i, 1).Resize(NextRow4 - i + 1, FinalColumn).Cut 'cut this row and all rows below it
newworkbook.Activate 'activate the new workbook
With newworkbook
.Sheets("sheet4").Paste 'pastes it to the fourth sheet in the new file
.Sheets("Sheet4").Rows(1).EntireRow.Insert 'adds a new row for headers when they get inserted later
End With
GoTo Finish: 'tells the code to skip looping and goto the end of the sub
End If
Next i
Finish: 'the code goes here after it reachers "Goto Finish:"
Application.Wait Now + #12:00:01 AM#
newworkbook.SaveAs savepath, 52 'saves new file with the Filepath for the new spreadsheet (52 means ".xlsm")
Application.Wait Now + #12:00:01 AM#
newworkbook.Close 'closes the new workbook
End If
End Sub
.Sheets.Add 'add sheet4 to the workbook .Sheets(1).Name = Sheet4.Name
Sheets.Add
是一个函数,它返回对添加的工作表的引用 - 你要丢弃它。相反,你需要捕获它。声明Sheet4
类型的Worksheeet
变量,并设置其引用:
Dim Sheet4 As Worksheet
Set Sheet4 = .Sheets.Add
问题是您假设编译器可以理解运行时发生的情况。
它没有。编译器不关心在运行时发生的事情,它只知道编译时存在的代码和对象。 VBA运行时/解释器关心运行时。
如果Sheet4
在编译时不存在,那么VBA不会为你定义一个全局范围的Sheet4
对象变量,所以在代码中引用Sheet4
将不可避免地导致无法编译的代码(因而无法编译)被执行),至少如果指定了Option Explicit
。
没有Option Explicit
,发生的事情要复杂得多。
我假设您在第一条指令上遇到“对象所需”运行时错误,该指令引用您在运行时创建的工作表对象的任何成员。
原因是因为没有Option Explicit
,在编译时没有标识符验证,所以任何拼写错误都会被愉快地编译。在运行时,当VBA遇到一个未声明的变量时,它只是在现场定义一个,作为一个隐含的Variant
,它可以保存任何东西。除了它不会推断这个即时变量是一个成员的对象 - 所以运行时爆炸并说“我不知道这是什么,它应该是一个Object
,但我我正在寻找一个Variant/Empty
“。
TL; DR:指定Option Explicit
,并为编译器抱怨的每个标识符声明一个变量(通过Debug~> Compile VBAProject菜单),直到代码正确编译。
如果对象在编译时存在,那么您假设“随每个工作表免费”的全局对象变量(例如Sheet1
,Sheet2
等)仅存在。