【问题标题】:Copy a worksheet without copying the code复制工作表而不复制代码
【发布时间】:2015-08-14 18:40:23
【问题描述】:

我可以通过调用.Copy 方法来复制工作表。

Sheets("Example").Copy After:=Worksheets("Sheet3")

但是,这也会复制与该工作表关联的所有宏或事件处理程序。如何在不复制任何 Visual Basic 代码的情况下复制工作表?

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    复制工作表后,您可以通过名称引用它,然后从代码模块中删除所有行:

    Sheets("Example").Copy After:=Sheets("Sheet3")
    
    ' Get the code/object name of the new sheet...
    Dim strObjectName As String
    strObjectName = ActiveSheet.CodeName
    
    ' Remove all lines from its code module...
    With ThisWorkbook.VBProject.VBComponents(strObjectName).CodeModule
        .DeleteLines 1, .CountOfLines
    End With
    

    要使用项目组件,您需要确保在 Excel 的宏设置中启用了 "Trust access to the VBA project object model" 选项。

    【讨论】:

    • 请注意,您需要授予 VBA 权限以更改其他 VBA 代码才能使用此方法。 stackoverflow.com/questions/25638344/…
    • 这会在复制带有引用库的工作表时引发错误 - 错误发生在删除有问题的代码之前:9
    【解决方案2】:

    创建一个空工作表并将原始工作表的内容复制过来。

    Sub Copy_Sheet_Without_Code(original_sheet As String, copied_sheet As String)
        ' Creates a copy of original_sheet without any VBA code associated with it
        ' The copy is named copied_sheet
        Sheets(original_sheet).Cells.Copy
        Sheets.Add.Name = copied_sheet
        Sheets(copied_sheet).Cells.PasteSpecial Paste:=xlPasteAll
    End Sub
    

    【讨论】:

    • 您有没有问过一个问题然后自己马上回答? O.o
    • @findwindow 当我在 Stack Overflow 上找不到问题的答案时,我通常会在弄清楚之后尝试将它放在这里给其他任何人。见这里:stackoverflow.com/help/self-answer
    • 对。我以前自己做过。我只是不会立即这样做。我没有计划 XD 这是一个自然的过程。事实上,我害怕自己必须回答我自己的最后一个问题 XD
    • 很确定这种方法速度较慢,并且会引发更多错误(例如不可见的项目)
    【解决方案3】:

    不完全是 OP 想要的,但您也可以通过将工作表复制到新工作簿来删除工作表宏,然后使用以下代码保存该工作簿(最终将工作簿保存为 .xlsx 并将代码剥离) ...

    ActiveWorkbook.SaveAs fileName:="yourfile.xlsx", fileFormat:=51
    

    这具有持久化所有数据和格式(例如列宽)的好处,并且不需要 VBA 对象模型权限。

    当然,保存后,您可以重新打开保存的工作簿并将工作表移回原始工作簿,现在无需代码!

    【讨论】:

    • Application.DisplayAlerts = False 当不需要额外的用户操作时必须使用。更多细节在我的回答中。
    【解决方案4】:

    我之前尝试在其中一个答案中使用代码

    ActiveWorkbook.SaveAs fileName:="yourfile.xlsx", fileFormat:=51
    

    但是程序显示了警报,在这种情况下用户必须手动对此警报做出反应,所以我添加了额外的代码行:

        Application.DisplayAlerts = False
        With ActiveWorkbook
         .SaveAs Filename:=excelReportFilePath, FileFormat:=xlOpenXMLWorkbook ' this enumeration value is the same as 51
        End With
        Application.DisplayAlerts = True
    

    在这种情况下,代码块在没有警报的情况下工作,并且在使用复制工作表(其中最初是代码)形成工作簿后关闭,然后从其目录再次打开,在复制的工作表中代码不存在。在这种情况下,警报 - 对 Visual Basic 项目的编程访问不受信任 - 没有像在代码时那样在某些用户 PC 上抛出

    ' Remove all lines from its code module...
    With ThisWorkbook.VBProject.VBComponents(strObjectName).CodeModule
        .DeleteLines 1, .CountOfLines
    End With
    

    被使用了。 因此,这种方式的优势在于您无需关心用户 PC 中的安全设置以及将数据从源工作表正确复制到另外创建的空白工作表中。

    【讨论】:

      【解决方案5】:

      扩展上面的一些答案。

      我试图保存一份没有附加到电子邮件的代码的副本。但是,您不能使用ActiveWorkbook.SaveCopyAs 指定文件类型。

      通过在文件名中指定文件扩展名 .xlsx:ActiveWorkook.SaveCopyAs fileName:="my_name.xlsx" 文件将保存,但在打开文件时会抛出关于文件类型不匹配的错误。此外,当附加到电子邮件时,由于文件类型不匹配,我的邮件被垃圾邮件过滤器捕获。

      为了解决这个问题,我最终保存了一份副本,打开了副本,打开它以 .xlsx 格式保存,然后将该副本附加到电子邮件中。

        ActiveWorkbook.Save
        ActiveWorkbook.SaveCopyAs fileName:=tmpFile     
              
        'save as .xlsx with no macros, openiong and saving will throw errors, turn off alerts
         Application.DisplayAlerts = False
         With Application.Workbooks.Open(tmpFile)
           .SaveAs fileName:=Replace(tmpFile, ".xlsm", ".xlsx"), FileFormat:=51
           .Close
         End With
         Application.DisplayAlerts = True
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-11
        • 1970-01-01
        • 2018-06-07
        • 1970-01-01
        相关资源
        最近更新 更多