从文件中批量删除Excel宏

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

我正在制定一个过程来清理我们网络上启用宏的文件。我将 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) 来实现。我们已经考虑过传输文件的内容,但这并不是我们所希望的,因为这种方法会丢失原始文件的关系,而保存会保留所需的详细信息。

寻找任何可能有助于解决此问题的想法。

excel vba powershell excel-interop word-interop
1个回答
0
投票

我要感谢@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()
}
© www.soinside.com 2019 - 2024. All rights reserved.