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

  • 说明
  • 需求背景
  • 禁止被打开文件中的vba运行
  • 判断打开的文件中是否含vba代码
    • 先取得打开的文件中有多少个components
    • 利用取得的对象数量, 取得每个对象中的代码行数
    • 需要注意的几个问题:
  • 附完整代码
  • 结语

说明

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

需求背景

公司在迁移质控体统的文件控件系统,新文控系统不支持老版的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对象综合处理。

  • 先取得打开的文件中有多少个components

    这里的 components, 就是VBE编辑器中左侧对象列表中的对象。如下图,test.xlsx 文件有2个对象,分别是"ThisWorkbook"和"Sheet1", 另一个xlsm文件有3个对象,多了一个"Modules1"

    这个数量可以用count属性获取:

      intObjects = objExcelFile.VBProject.VBComponents.Count`
    
  • 利用取得的对象数量, 取得每个对象中的代码行数

    在VBComponents对象下, 有个Item对象,每个item就对应一个具体的Component对象。Component对象下有个CodeModule对象,可以利用它的CountOfLines属性,来取得该模块中有多少行代码。如果代码行数不为0,则说明文件中有VBA代码。

    'Has vba code or not
    blNoMacro = False
    For intTemp = 1 To objExcelFile.VBProject.VBComponents.Count   'How many objectsIf objExcelFile.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 0 ThenblNoMacro = TrueExit ForEnd IfNext
    'save file
    objExcelFile.SaveAs IIf(blNoMacro, strPath & "\" & strFileName & ".xlsm", strPath & "\" & strFileName & ".xlsx")
    
  • 需要注意的几个问题:

  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()'ExcelDim objExcelFile As Workbook'WordDim objWordApp As New Word.Application, objWordDoc As Word.Document'PowerPointDim objPptApp As New PowerPoint.Application, objPptFile As PowerPoint.PresentationDim strPath As String, strFileName As String, strNewFileName As String, intTemp As Integer, blNoMacro As BooleanobjWordApp.Visible = TrueobjPptApp.Visible = msoCTrue'Disable vba runningApplication.AutomationSecurity = msoAutomationSecurityForceDisable 'msoAutomationSecurityLow  '=msoAutomationSecurityByUI =  'msoAutomationSecurityForceDisableobjWordApp.AutomationSecurity = msoAutomationSecurityByUI ' = msoAutomationSecurityForceDisableobjPptApp.AutomationSecurity = msoAutomationSecurityForceDisable'open excel filestrPath = "C:\temp"strFileName = "test"Set objExcelFile = Application.Workbooks.Open(strPath & "\" & strFileName & ".xls")'Has vba code or notblNoMacro = FalseFor intTemp = 1 To objExcelFile.VBProject.VBComponents.Count   'How many objectsIf objExcelFile.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 0 ThenblNoMacro = TrueExit ForEnd IfNext'Save fileobjExcelFile.SaveAs IIf(blNoMacro, strPath & "\" & strFileName & ".xlsm", strPath & "\" & strFileName & ".xlsx")'......objExcelFile.Close'open word fileSet objWordDoc = objWordApp.Documents.Open(strPath & "\" & strFileName & ".doc")'Has vba code or notblNoMacro = FalseFor intTemp = 1 To objWordDoc.VBProject.VBComponents.Count   'How many objectsIf objWordDoc.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 1 ThenblNoMacro = TrueExit ForEnd IfNext'save fileobjWordDoc.SaveAs2 IIf(blNoMacro, strPath & "\" & strFileName & ".docm", strPath & "\" & strFileName & ".docx")objWordDoc.Close'open ppt fileSet objPptFile = objPptApp.Presentations.Open(strPath & "\" & strFileName & ".ppt")'Has vba code or notblNoMacro = FalseFor intTemp = 1 To objPptFile.VBProject.VBComponents.Count   'How many objectsIf objPptFile.VBProject.VBComponents.Item(intTemp).CodeModule.CountOfLines > 0 ThenblNoMacro = TrueExit ForEnd IfNext'save fileobjPptFile.SaveAs IIf(blNoMacro, strPath & "\" & strFileName & ".pptm", strPath & "\" & strFileName & ".pptx")objPptFile.CloseEXIT_SUB:Set objExcelFile = NothingSet objWordApp = NothingSet objWordDoc = NothingSet objPptApp = NothingSet objPptFile = NothingEnd Sub

结语

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

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

  1. notepadd++打开文件时保留上次打开文件的解决办法

    用notepadd++打开文件时,总是打开上一次打开的文件,弄得我很烦 自从用了度娘,心情顿时好了,解决办法是这样的:

  2. python创建文件夹 覆盖_Python 创建新文件时避免覆盖已有的同名文件的解决方法...

    思路:创建文件时,先检查是否有同名文件(使用os.path.isfile),如果有,则在文件名后加上编号n来创建. 关键点: 1. 使用os.path.isfile判断文件是否存在 2. 使用递归函数 ...

  3. ae渲染出现错误是什么问题_After Effects错误:写入文件.....时发生渲染错误.输出模块失败.文件可能已损坏。(-1610153464)...

    我来回答一下,你在电脑里安装了其他下载的aex文件格式的插件,你只要把你这些插件删除掉,问题就可以解决,(安装插件不正确,或者有相同的插件也出现提示框)其实,这个提示不重要,你正常开启AE以后,正常使 ...

  4. 服务器上文件一直被打开吗,Python: 如何判断远程服务器上Excel文件是否被人打开...

    最近工作中需要去判断远程服务器上的某个Excel文件是否被打开,如果被人打开,则等待,如果没人打开使用,则去填写数据进Excel文件. 开始想的很简单,和其他语言一样,比如C#,打开文件,如果报错说明 ...

  5. 安装文件时显示不能打开要写入的文件该如何解决?

    前情概要 原先使用这台电脑的同事把电脑c盘下的用户名改成自己的名字,本人多次使用网上的教程没能更改成功,于是被迫将就用着,在这期间也下载了一些软件.不死心的我后面又琢磨着改掉这个名字(毕竟谁也不想一直 ...

  6. catia保存成stp文件时部件丢失_在线教学文件同步神器——坚果云

    教师在线办公期间,有教研组.备课组资源共享与协同办公的需求.在此推荐一款应用--坚果云[1],可以实现市面上绝大部分设备间的文件共享和同步,极高地提高在文件管理方面的效率. 推荐指数:★★★★★ ↓教 ...

  7. Java下载文件时文件名出现乱码(但文件内容正常)

    今天写文件下载时,发现以前忽略的问题,写个小记录 我们一般使用中文操作系统,所以要求的 文件名编码最好是utf-8,国际化一点 但是,似乎实际上不是这样 1. String fileName=new ...

  8. 下载文件时,浏览器是怎么知道文件名称的?

    当你在浏览器里下载一个文件时,浏览器是如何知道你所下载的文件的名称的呢?这或许是你从未考虑过的事情,但浏览器必须知道,否则,它就不知道如何保存文件. 1. Content-Disposition 首部 ...

  9. 打开Windows Powershell时出现 :. : 无法加载文件C:\user\...\profile.ps1。未对文件profile.ps1进行数字签名。无法在当前系统上运行该脚本 的解决办法

    想使用Windows Powershell命令时,打开后出现如下报错: . : 无法加载文件 C:\Users\arxc\Documents\WindowsPowerShell\profile.ps1 ...

  10. 打开PDF文件时,出现“打开本文档时发生错误。无法找到本文件。”解决办法,亲自尝试成功

    解决办法 1.拖动该文件,硬生生拖到桌面上,然后打开对应的桌面该文件,如果桌面该文件能打开,而原来文件夹的还是不能打开,进行第二步 注:有人尝试删除之前的文件,然后打开桌面文件,另存为原来位置之后,还 ...

最新文章

  1. 访客门禁系统供应商 首选钱林厂家
  2. 深入Java中的位操作
  3. 需求分析的定义(转)
  4. Matlab 矩阵计算例子
  5. xp java配置_WinXP系统Java配置环境变量的方法
  6. gdbc 同步mysql_Jdbc数据同步
  7. 笔记2014-08-26
  8. 2018年的人工智能将如何发展?看看专家怎么说
  9. C语言学习资源汇总,史上最全面总结,没有之一
  10. imagej得到灰度图数据_【原创】imagej使用达人指南,分享给大家!
  11. qq远程控制无法连接服务器,win10系统QQ远程协助,无法控制对方电脑,怎么办?...
  12. C#读取网卡地址的几种方法
  13. 相量的瞬时功率 平均功率 无功功率 视在功率
  14. 解决css样式中first-child和last-child不生效的问题
  15. 什么是企业管理咨询服务?
  16. Microk8s单机安装
  17. 电子计算机的加减乘除叫做什么,计算机中加减乘除叫什么键
  18. ARM学习之基本概念
  19. 基于热销商品宝贝的数据调用分析
  20. 恐怖绝伦,SOPA和PIPA捅了网站窝

热门文章

  1. 智慧应急 科学管理:打造园区安全智慧大脑
  2. 《产品经理认证(NPDP)知识体系指南》
  3. idea社区版 html,利用IntelliJ IDEA社区版开发servlet
  4. radon变换的原理-通过直线方程式的计算来检测出直线
  5. JDK源代码中最重要的4646个英语单词
  6. Golang 相关 mindoc开发
  7. OSI常用网络协议(七层)
  8. 用Java写脚本,常用的一些方法
  9. 2022年N1叉车司机考试题及N1叉车司机理论考试
  10. 虚拟机下搭建一个dns服务器,虚拟机下DNS服务器配置.doc