当我创建一个新的工作簿并使用另一个工作簿向其添加工作表时,工作表显示在工作簿窗口中但VBA无法识别它们

问题描述 投票:2回答:1

所以我要做的是每年创建一个新的工作簿。如果工作簿的某个工作表中存在两个不同年份的数据,则会创建一个新工作簿。当它看到两年不同时,它会创建一个新工作簿,将.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
excel vba excel-vba
1个回答
2
投票
        .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菜单),直到代码正确编译。

如果对象在编译时存在,那么您假设“随每个工作表免费”的全局对象变量(例如Sheet1Sheet2等)仅存在。

© www.soinside.com 2019 - 2024. All rights reserved.