首页 > 解决方案 > 使用Powershell打开受密码保护的Excel xlsx文件并保存为没有密码的csv

问题描述

我有一个受密码保护的 Excel 文件(Office 2019,xlsx 文件)。我想创建一个 Powershell 脚本来使用密码打开文件,然后将其另存为 csv,而无需在新目录中输入密码。我试图在这里关注这个问题,但这对我不起作用。我对Powershell没有很多经验,任何见解都值得赞赏。

我想在这里为任何寻找类似解决方案的人更新此内容,解决方案如下。我很惊讶我在任何地方都找不到一个简单的操作方法。

对于我原来的帖子的批评者——如果你过去写过这样的东西,答案就是简单地复制和粘贴你可能使用过的现有脚本。我自己拥有这些类型的脚本的大型存储库,并经常与同事和社区共享它们,因此我正在寻找可能有类似内容的人来共享。你显然没有,所以你的回答没有意义。

$filepath = "C:\MyDailyFile\Blah.xlsx"
$password = "omgpassword"

try {
    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $true
    $excel.DisplayAlerts = $true

## Open target password protected workbook
## [Type}::Missing are placeholders for positional parameters. See the Workbook class for more detail.

$wb = $excel.Workbooks.Open($filepath, [Type]::Missing, [Type]::Missing, [Type]::Missing, $password)
$sheet = $wb.ActiveSheet

## Save the open workbook in a new directory without a password
## and change the file type to CSV

$wb.SaveAs("C:\MyDailyFile\BlahCommaDelim",6,"")

## The second property of the SaveAs class (6) corresponds to a type "csv". The above results in the following SaveAs path: 
## C:\MyDailyFile\BlahCommaDelim.csv
## More information on XlFileFormat parameters https://docs.microsoft.com/en-us/office/vba/api/Excel.XlFileFormat

$excel.Quit()

} finally {
    $sheet, $wb, $excel | ForEach-Object {
        if ($_ -ne $null) {
            [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($_)
        }
    }
}

标签: excelpowershell

解决方案


始终一次一个块地单步执行您的代码,以确保您得到预期的结果。

我正在使用我穷人的调试用例,利用 变量挤压,这意味着将结果分配给变量,同时自动输出到屏幕。您会注意到这一切都按预期进行,Lee 询问您遇到了什么错误是一个谨慎的问题。

您的声明:

我试图在这里关注这个问题,但这对我不起作用。

......并不是一个真正的澄清声明。

($XlsFiles = Get-ChildItem -Path 'D:\Temp' -Filter 'File*.xl*')
<#
# Results

    Directory: D:\Temp

Mode                LastWriteTime         Length Name        
----                -------------         ------ ----        
-a----        28-Apr-20     15:49           9811 FileData.xlsx                                                                                                      
-a----        28-Apr-20     15:50          16384 FileDataProtected.xlsx 
#>

($XlsFiles = Get-ChildItem -Path 'D:\Temp' -Filter 'File*.csv')
<#
# Results

    Directory: D:\Temp

Mode                LastWriteTime         Length Name        
----                -------------         ------ ----        
-a----        06-Apr-20     00:54            260 FileData.csv  
#>

($filepath = 'D:\Temp\FileDataProtected.xlsx')
($password = 'omgpassword')
<#
# Results

D:\Temp\FileDataProtected.xlsx
omgpassword
#>


$excel               = New-Object -ComObject Excel.Application
$excel.Visible       = $true
$excel.DisplayAlerts = $true

你为什么在这里打字?这真的没有保证。

# ($wb = $excel.Workbooks.Open($filepath, [Type]::Missing, [Type]::Missing, [Type]::Missing, $password))
<#
# Results

Application                      : Microsoft.Office.Interop.Excel.ApplicationClass
Creator                          : 1480803660
Parent                           : Microsoft.Office.Interop.Excel.ApplicationClass
AcceptLabelsInFormulas           : False
ActiveChart                      : 
ActiveSheet                      : System.__ComObject
Author                           : 
AutoUpdateFrequency              : 0
AutoUpdateSaveChanges            : 
ChangeHistoryDuration            : 0
BuiltinDocumentProperties        : System.__ComObject
Charts                           : System.__ComObject
CodeName                         : 
_CodeName                        : 
CommandBars                      : 
Comments                         : 
ConflictResolution               : 1
Container                        : 
CreateBackup                     : False
CustomDocumentProperties         : System.__ComObject
Date1904                         : False
DialogSheets                     : System.__ComObject
DisplayDrawingObjects            : -4104
FileFormat                       : 51
FullName                         : D:\Temp\FileDataProtected.xlsx
...
#>

($wb    = $excel.Workbooks.Open($filepath,0,0,5,$password))
<#
# Results

Application                      : Microsoft.Office.Interop.Excel.ApplicationClass
Creator                          : 1480803660
Parent                           : Microsoft.Office.Interop.Excel.ApplicationClass
AcceptLabelsInFormulas           : False
ActiveChart                      : 
ActiveSheet                      : System.__ComObject
Author                           : 
AutoUpdateFrequency              : 0
AutoUpdateSaveChanges            : 
ChangeHistoryDuration            : 0
BuiltinDocumentProperties        : System.__ComObject
Charts                           : System.__ComObject
CodeName                         : 
_CodeName                        : 
CommandBars                      : 
Comments                         : 
ConflictResolution               : 1
Container                        : 
CreateBackup                     : False
CustomDocumentProperties         : System.__ComObject
Date1904                         : False
DialogSheets                     : System.__ComObject
DisplayDrawingObjects            : -4104
FileFormat                       : 51
FullName                         : D:\Temp\FileDataProtected.xlsx
...
#>

您在发布的任何地方都没有使用它,所以,为什么要这样做?您不使用的东西也需要很长时间才能完成。

#>
($sheet = $wb.ActiveSheet) 
<#
# Results

Application                       : Microsoft.Office.Interop.Excel.ApplicationClass
Creator                           : 1480803660
Parent                            : System.__ComObject
CodeName                          : 
_CodeName                         : 
Index                             : 1
Name                              : FileData
...
#>



$wb.SaveAs('D:\Temp\FileDataUnProtected.csv',6,'')
<#
# Results

当然,当你这样做时,Excel 会通过从 Xlsx 切换到 CSV 来对你大喊数据丢失。

# Clean-up
$excel.Quit()
[System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
<#
# Results

6
#>


($XlsFiles = Get-ChildItem -Path 'D:\Temp' -Filter 'File*.csv')
<#
# Results


    Directory: D:\Temp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        06-Apr-20     00:54            260 FileData.csv
-a----        28-Apr-20     16:21            129 FileDataUnProtected.csv
#>

Get-Content -Path 'D:\Temp\FileDataUnProtected.csv'
<#
# Results

0 minutes
0 minutes
1 day and 19 hours
1 day and 2 hours
1 day and 20 hours
1 day and 23 hours
13 hours
2 days
20 hours
#>

Import-Csv -Path 'D:\Temp\FileDataUnProtected.csv'
<#
# Results

0 minutes         
1 day and 19 hours
1 day and 2 hours 
1 day and 20 hours
1 day and 23 hours
13 hours          
2 days            
20 hours 
#>

最后,这样做没有什么意义,因为您只有一个 COM 对象要处理,其他只是变量,应该使用 Remove-Variable cmdlet 清理

finally {
$sheet, $wb, $excel | ForEach-Object {
    if ($_ -ne $null) {
        [void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($_)
    }
}

推荐阅读