Excel 为什么PowerShell不想将我的文件另存为CSV

Excel 为什么PowerShell不想将我的文件另存为CSV,excel,powershell,csv,Excel,Powershell,Csv,我正试图这样做,但出于某种原因,SaveAs()不起作用。这给了我一个错误 无法访问文件“D://ETL_Data/E567DF00” 我要做什么才能将此保存到CSV 编辑: 没有注释中建议的fileformat参数6的确切错误: $Path = 'D:/ETL_Data/TwitchTVData.xlsx' $csvPath = 'D:/ETL_Data/TwitchTVData2.csv' # Open the Excel document and pull in the 'Sheet1'

我正试图这样做,但出于某种原因,
SaveAs()
不起作用。这给了我一个错误

无法访问文件“D://ETL_Data/E567DF00”

我要做什么才能将此保存到CSV

编辑:

没有注释中建议的fileformat参数
6
的确切错误:

$Path = 'D:/ETL_Data/TwitchTVData.xlsx'
$csvPath = 'D:/ETL_Data/TwitchTVData2.csv'

# Open the Excel document and pull in the 'Sheet1' worksheet
$Excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($Path)
$page = 'Sheet1'
$ws = $Workbook.Worksheets | Where-Object {$_.Name -eq $page}
$Excel.Visible = $true
$Excel.DisplayAlerts = $false

# Set variables for the worksheet cells, and for navigation
$cells = $ws.Cells
$row = 1
$col = 4
$formula = @"
=NOW()
"@

# Add the formula to the worksheet
$range = $ws.UsedRange
$rows = $range.Rows.Count
for ($i=0; $i -ne $rows; $i++) {
    $cells.Item($row, $col) = $formula
    $row++
}

$ws.Columns.Item("A:D").EntireColumn.AutoFit() | Out-Null
$ws.Columns.Range("D1:D$rows").NumberFormat = "yyyy-MM-dd hh:mm"

$Excel.ActiveWorkbook.SaveAs($csvPath)
$Excel.Quit()

[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

当谈到路径分隔符时,PowerShell非常宽容,但COM+服务器(如
Excel.Application
)可能不是

$csvPath
变量值更改为使用
\
而不是
/

The file could not be accessed. Try one of the following: o Make sure the specified folder exists. o Make sure the folder that contains the file is not read-only. o Make sure the file name does not contain any of the following characters: < > ? [ ] : | or * o Make sure the file/path name doesn't contain more than 218 characters. At D:\PS_Scripts\twitchExcelAddSnapShot.ps1:32 char:1 + $Excel.ActiveWorkbook.SaveAs($csvPath,6) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : OperationStopped: (:) [], COMException + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException 要补充背景信息,请执行以下操作:

# PS: OK
# Should output c:\windows\win.ini
(Get-Item c:/windows/win.ini).FullName

# .NET: OK
# Should return the 1st child dir.'s path.
# Note that the child directory names will be appended with "\", not "/"
[System.IO.Directory]::GetDirectories('c:/windows/system32') | Select-Object -First 1

# COM (see Excel exception below): OK
# Should return $true
(New-Object -ComObject Scripting.FileSystemObject).FileExists('c:/windows/win.ini')

# Windows API: OK
# Should return a value such as 32.
(Add-Type -PassThru WinApiHelper -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint GetFileAttributes(string lpFileName);')::GetFileAttributes('c:/windows/win.ini')

# cmd.exe: INCONSISTENTLY SUPPORTED
# Note: *quoting matters* here, so that tokens with / aren't mistaken for options.
#     attrib: works
cmd /c 'attrib "c:/windows/win.ini"'  
#     dir: works with DIRECTORIES, but fails with FILES
cmd /c 'dir /b "c:/windows/system32"'  # OK
cmd /c 'dir /b "c:/windows/win.ini"'  # FAILS with 'File not found'
cmd /c 'dir /b "c:/windows\win.ini"'  # Using \ for the FILE component (only) works.
看来,Excel特定于应用程序的行为是问题的原因,与所使用的基础子系统或API无关。
(Excel的自动化API恰好是一个COM服务器。)
我不清楚Excel为什么会这样做——它在交互使用中也会这样做,尽管您可能会争辩说,至少在编程使用中,它也应该允许
/

提供一般性建议:

  • 在Windows上,为了安全起见,请使用
    \
    ,尤其是在处理应用程序级自动化API时,尽管在系统级API上
    /
    也应起作用-见下文

  • 在跨平台代码中,使用
    /
    (但要注意上面的异常;
    [System.IO.Path]::directorySpeparatorChar
    报告平台相应的(主)字符)

尽管很少使用,API级别的Windows允许互换使用
\
/
(这显然是在引入目录支持时),这也反映在更高级别的子系统中,如下例所示

$csvPath = 'D:\ETL_Data\TwitchTVData2.csv'

下面是一个最小示例,演示了Excel在
/
方面的问题:

# PS: OK
# Should output c:\windows\win.ini
(Get-Item c:/windows/win.ini).FullName

# .NET: OK
# Should return the 1st child dir.'s path.
# Note that the child directory names will be appended with "\", not "/"
[System.IO.Directory]::GetDirectories('c:/windows/system32') | Select-Object -First 1

# COM (see Excel exception below): OK
# Should return $true
(New-Object -ComObject Scripting.FileSystemObject).FileExists('c:/windows/win.ini')

# Windows API: OK
# Should return a value such as 32.
(Add-Type -PassThru WinApiHelper -MemberDefinition '[DllImport("kernel32.dll")] public static extern uint GetFileAttributes(string lpFileName);')::GetFileAttributes('c:/windows/win.ini')

# cmd.exe: INCONSISTENTLY SUPPORTED
# Note: *quoting matters* here, so that tokens with / aren't mistaken for options.
#     attrib: works
cmd /c 'attrib "c:/windows/win.ini"'  
#     dir: works with DIRECTORIES, but fails with FILES
cmd /c 'dir /b "c:/windows/system32"'  # OK
cmd /c 'dir /b "c:/windows/win.ini"'  # FAILS with 'File not found'
cmd /c 'dir /b "c:/windows\win.ini"'  # Using \ for the FILE component (only) works.
# Create temporary dir.
$null = mkdir c:\tmp -force

$xl=New-Object -Com Excel.Application
$wb = $xl.Workbooks.Add()

# OK - with "\"
$wb.SaveAs('c:\tmp\t1.xlsx')

# FAILS - with "/":
# "Microsoft Excel cannot access the file 'C:\//tmp/F5D39400'"
$wb.SaveAs('c:/tmp/t2.xlsx')

$xl.Quit()

# Clean up temp. dir.