用VBA代码打开xls文件时,判断被打开的xls文件是否含VBA代码并禁止其运行

本文为原创,引用请注明出处,谢谢!

公司在迁移质控体统的文件控件系统,新文控系统不支持老版的office文件(xls, doc, ppt等), 需要将其升版成新的xlsx, docx, pptx格式。
显然,用vba代码处理是最便捷的。只要打开原文件,另存为新格式,再删除旧文件就行了。
但是在执行时,发现一个问题,就是老版的office文件,含不含vba代码(宏macro),其文件后缀是一样的。有些文件的vba代码中文件打开、文件保存会触一些功能。因此需要禁止被打开文件中的vba被触发运行。另一方面,因为新版office中带有vba代码的文件,其后缀是不一样的(xlsm, docm, pptm), 所以需要根据原文件中是否含vba代码来决定升级成相应类型的文件。

禁止被打开文件中的vba运行

这个相对简单,只需要设置application对象的AutomationSecurity 属性就可以了,Excel, Word, PowerPoint都一样。
这个属性有3个选项:

  • msoAutomationSecurityLow
  • msoAutomationSecurityByUI
  • msoAutomationSecurityForceDisable

实际上这是预定义的常量,从上到下分别是1,2,3。
在打开文件前,将属性设为 msoAutomationSecurityForceDisable 即可.
当然,考究一点,可以先保存当前的设置,然后在最后再恢复。

处理之前:

intPreviousSetting = Application.AutomationSecurity
Application.AutomationSecurity = msoAutomationSecurityForceDisable 'Excel
objWordApp.AutomationSecurity = msoAutomationSecurityForceDisable 'Word
objPowerPointApp.AutomationSecurity = msoAutomationSecurityForceDisable 'PowerPoint```

处理完毕:

Application.AutomationSecurity = intPreviousSetting

判断打开的文件中是否含vba代码

这个略曲折。需要利用office 文件对象中VBProject对象下的VBComponents对象综合处理。

  1. 对于Excel 文件,即使完全没有VBA代码,也会有2个components:Workbook" 和"Sheet1"; 对word, 会有1个:“ThisDocument”; 对于PowerPoint, 如果没有VBA代码,则component个数为0
  2. 对于模块中的空行, CountOfLines 也会统计在内。极端情况下,用户只是输入了些回车,并没有实质性代码,用这个方法也会被判定为含宏。如果确实要求非常精确,可以用类似的手段,取得每一行代码,判断是否为空。但这样会非常耗时,对于此项目并不需要到这么精确,所以就只做简单判断了。
  3. 使用这个方法的,需要在Word/Excel/PowerPoint中开启"Trust Access to the VBA project object model". 开启的方法与允许运行宏一样,都在信任中心那里设置
    在这里插入图片描述
    否则的话,会收到如下提示:
    在这里插入图片描述

附完整代码

Option Explicit
Sub test()
    'Excel
    Dim objExcelFile As Workbook
    'Word
    Dim objWordApp As New Word.Application, objWordDoc As Word.Document
    'PowerPoint
    Dim objPptApp As New PowerPoint.Application, objPptFile As PowerPoint.Presentation
    Dim strPath As String, strFileName As String, strNewFileName As String, intTemp As Integer, blNoMacro As Boolean
    objWordApp.Visible = True
    objPptApp.Visible = msoCTrue
    'Disable vba running
    Application.AutomationSecurity = msoAutomationSecurityForceDisable 'msoAutomationSecurityLow  '=msoAutomationSecurityByUI =  'msoAutomationSecurityForceDisable
    objWordApp.AutomationSecurity = msoAutomationSecurityByUI ' = msoAutomationSecurityForceDisable
    objPptApp.AutomationSecurity = msoAutomationSecurityForceDisable
    'open excel file
    strPath = "C:\temp"
    strFileName = "test"
    Set objExcelFile = Application.Workbooks.Open(strPath & "\" & strFileName & ".xls")
    'Has vba code or not
    blNoMacro = False
    For intTemp = 1 To objExcelFile.VBProject.VBComponents.Count   'How many objects
        If objExcelFile.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 0 Then
            blNoMacro = True
            Exit For
        End If
    'Save file
    objExcelFile.SaveAs IIf(blNoMacro, strPath & "\" & strFileName & ".xlsm", strPath & "\" & strFileName & ".xlsx")
    '......
    objExcelFile.Close
    'open word file
    Set objWordDoc = objWordApp.Documents.Open(strPath & "\" & strFileName & ".doc")
    'Has vba code or not
    blNoMacro = False
    For intTemp = 1 To objWordDoc.VBProject.VBComponents.Count   'How many objects
        If objWordDoc.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 1 Then
            blNoMacro = True
            Exit For
        End If
    'save file
    objWordDoc.SaveAs2 IIf(blNoMacro, strPath & "\" & strFileName & ".docm", strPath & "\" & strFileName & ".docx")
    objWordDoc.Close
    'open ppt file
    Set objPptFile = objPptApp.Presentations.Open(strPath & "\" & strFileName & ".ppt")
    'Has vba code or not
    blNoMacro = False
    For intTemp = 1 To objPptFile.VBProject.VBComponents.Count   'How many objects
        If objPptFile.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 0 Then
            blNoMacro = True
            Exit For
        End If
    'save file
    objPptFile.SaveAs IIf(blNoMacro, strPath & "\" & strFileName & ".pptm", strPath & "\" & strFileName & ".pptx")
    objPptFile.Close
EXIT_SUB:
    Set objExcelFile = Nothing
    Set objWordApp = Nothing
    Set objWordDoc = Nothing
    Set objPptApp = Nothing
    Set objPptFile = Nothing
End Sub

VBA目前已经势微,准确地说,可能从来没有火过。但是事实上,这真的是一门极其有用的语言。如果能够掌握,在日常工作中会带来巨大的便利。相信你能看到这里,说明你正在使用它并遇到了困难要解决,希望此文能帮上。

用VBA代码打开xls文件时,判断被打开的xls文件是否含VBA代码并禁止其运行说明需求背景禁止被打开文件中的vba运行判断打开的文件中是否含vba代码先取得打开的文件中有多少个components利用取得的对象数量, 取得每个对象中的代码行数需要注意的几个问题:附完整代码结语说明本文为原创,引用请注明出处,谢谢!需求背景公司在迁移质控体统的文件控件系统,新文控系统不支持老版的office文件(xls, doc, ppt等), 需要将其升版成新的xlsx, docx, pptx格式。显然,用vba
代码操作代码,倒是挺高级的。至少在学习C、Java等其他语言没有这样玩过。事实上,今天使用VBA删除了待交付文件中的VBA代码,技术水平有了进一步的提高!这节的内容感觉挺充实,认真学习,会有收获的。'VBE对象是根对象,表示在VBA编辑器中存在的所有对象的最上层对象 '一 VBAproject对象: VBE编辑器中的工程 '1 VBComponents对象:表示工...
添加一个新的工作簿, Application.Add   Application.WorkBooks.Open ("C:\book.xlsx") '打开工作簿 book.xlsx Sub 合并文件() Dim 文件目录 As String, 文件名 As String, 文件扩展名 As String Dim 打开文件 As Workbook, 目标文件 As Workbook Dim 目标工作表 As Worksheet, 工作表 As Worksheet Dim 最后一行 As Long, 目标行 As Long '设置文件目录 文件目录 = "C:\Users\UserName\Documents\Files\" '设置目标文件 Set 目标文件 = Workbooks.Add(xlWBATWorksheet) Set 目标工作表 = 目标文件.Worksheets(1) 目标行 = 1 '获取目录中的所有 Excel 文件 文件名 = Dir(文件目录 & "*.xls*") '循环打开文件并复制数据到目标文件中 Do While 文件名 <> "" Set 打开文件 = Workbooks.Open(文件目录 & 文件名) For Each 工作表 In 打开文件.Worksheets 最后一行 = 工作表.Cells(Rows.Count, 1).End(xlUp).Row 工作表.Range("A1:Z" & 最后一行).Copy 目标工作表.Range("A" & 目标行).PasteSpecial xlPasteValues 目标行 = 目标行 + 最后一行 打开文件.Close False 文件名 = Dir '保存目标文件 目标文件.SaveAs 文件目录 & "合并文件.xlsx" 目标文件.Close MsgBox "已完成合并。" End Sub 这个代码将会打开一个指定目录下的所有 Excel 文件,然后将每个文件中所有工作表的数据复制到一个新的 Excel 文件中,最后保存该文件