我正在制定一个过程来清理我们网络上启用宏的文件。我将 PowerShell 与 excel 和 word comObjects 一起使用,并且一直在朝着正确的方向前进,但 vb 项目启用的文件除外。该代码当前适用于所有标准的启用宏的文件,但在使用 vb 项目的文件上的 .saveas 方法期间会出现消息提示(到目前为止仅适用于 Excel)。目标是成功地对数千个文件运行此命令,并出于记录目的删除对它们的宏启用。即保留数据而不是代码。
这是我当前正在使用的功能(使用PowerShell)
function Process-ExcelFile {
param (
[string]$FullPath,
[string]$DestinationFile
)
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$excel.DisplayAlerts = 0 # Disable display alerts
#$excel.DisplayAlerts = $false # Disable display alerts works the same as 0
$excel.AlertBeforeOverwriting = 0
$workbook = $excel.Workbooks.Open($FullPath)
# Save the file as non-macro enabled workbook with appropriate extension
$destinationFile = [System.IO.Path]::ChangeExtension($destinationFile, "xlsx")
$workbook.SaveAs($destinationFile, 51) # 51 = Excel File Format for non-macro workbook
$workbook.Close($false) # Close the workbook without saving changes
$excel.Quit()
}
我尝试使用删除 VB 项目的方法,但效果有限,但与这些文件相关的另存为对话框并未被抑制。该对话框是 saveAs 方法的结果,它阻止我编写对对话框的响应,因为当前进程正在等待 saveas 完成。
目标是保留尽可能多的原始文件,但从文件中删除所有 VB/宏内容。手动方式是通过将文件另存为非启用宏的文件 (xslx) 来实现。我们已经考虑过传输文件的内容,但这并不是我们所希望的,因为这种方法会丢失原始文件的关系,而保存会保留所需的详细信息。
寻找任何可能有助于解决此问题的想法。
我要感谢@Doofus 对我的问题的答复。它促使我看一些东西,从而找到答案。
vb 项目文件具有事件触发器,包括 onsave 事件。这是导致我的问题的通知的一部分。我在代码中进行了以下更改,目前已解决此问题。
对于应用程序,我将 .EnableEvents 设置为 False。
对于工作簿,我迭代 .VBComponents 并删除所有类型 1 模块。
这 2 个操作导致这些文件被抑制并成功处理。
更新了以下功能。
function Process-ExcelFile {
param (
[string]$FullPath,
[string]$DestinationFile
)
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$excel.DisplayAlerts = 0 # Disable display alerts (e.g., VBA project prompt)
$excel.EnableEvents = $false # Disable Event hooks in Excel
$excel.AlertBeforeOverwriting = 0
$workbook = $excel.Workbooks.Open($FullPath)
# Check if the workbook has a VB project
if ($workbook.HasVBProject) {
# Save the workbook without macros
$destinationFile = [System.IO.Path]::ChangeExtension($destinationFile, "xlsx")
# Access the VBA project
$vbaProject = $workbook.VBProject
# Remove the BuildFileName property by setting it to an empty string
$vbaProject.BuildFileName = ""
foreach ($module in $vbaProject.VBComponents) {
if ($module.Type -eq 1) { # Check if it's a standard module (Type 1)
$vbaProject.VBComponents.Remove($module)
}
}
$workbook.SaveAs($destinationFile, 51) # 51 = Excel File Format for non-macro workbook
}else {
# Save the workbook as is (without macros)
$destinationFile = [System.IO.Path]::ChangeExtension($destinationFile, "xlsx")
$workbook.SaveAs($destinationFile, 51) # 51 = Excel File Format for non-macro workbook
}
# Close the workbook and quit Excel
$workbook.Close($false)
$excel.Quit()
}