如何使用Powershell将CSV导出到Excel

我正尝试使用Powershell将完整的CSV导出到Excel。 我坚持使用静态列名称的一点。 但是,如果我的CSV具有通用的未知标题名称,则这不起作用。

重现步骤

打开PowerShell ISE并复制并粘贴以下独立代码。 用F5运行它
“C:\ WINDOWS \ SYSTEM32 \ WindowsPowerShell \ V1.0 \ powershell_ise.exe”

Get-Process | Export-Csv -Path $env:temp\process.csv -NoTypeInformation $processes = Import-Csv -Path $env:temp\process.csv $Excel = New-Object -ComObject excel.application $workbook = $Excel.workbooks.add() $i = 1 foreach($process in $processes) { $excel.cells.item($i,1) = $process.name $excel.cells.item($i,2) = $process.vm $i++ } Remove-Item $env:temp\process.csv $Excel.visible = $true 

它能做什么

  1. 该脚本会将所有活动进程的列表以CSV格式导出到您的临时文件夹。 这个文件只用于我们的例子。 它可以是任何数据的CSV
  2. 它读入新创build的CSV并将其保存在$processesvariables下
  3. 它创build一个新的空的Excel工作簿,我们可以写数据
  4. 它遍历所有行(?),并将namevm列中的所有值写入Excel

我的问题

  • 如果我不知道列标题怎么办? (在我们的例子namevm )。 如何处理我不知道标题名称的值?
  • 我如何计算一个CSV有多less列? (在用Import-Csv阅读之后)

我只想用Powershell写一个完整的CSV到Excel

Ups,我完全忘了这个问题。 在此期间,我得到了一个解决scheme。
此Powershell脚本在后台将CSV转换为XLSX

噱头是

  • 保留所有CSV值为纯文本,如=B1+B20000001
    你没有看到#Name或类似的东西。 没有autoformating完成。
  • 根据您的区域设置自动select正确的分隔符(逗号或分号)
  • 自动调整列

PowerShell代码

 ### Set input and output path $inputCSV = "C:\somefolder\input.csv" $outputXLSX = "C:\somefolder\output.xlsx" ### Create a new Excel Workbook with one empty sheet $excel = New-Object -ComObject excel.application $workbook = $excel.Workbooks.Add(1) $worksheet = $workbook.worksheets.Item(1) ### Build the QueryTables.Add command ### QueryTables does the same as when clicking "Data » From Text" in Excel $TxtConnector = ("TEXT;" + $inputCSV) $Connector = $worksheet.QueryTables.add($TxtConnector,$worksheet.Range("A1")) $query = $worksheet.QueryTables.item($Connector.name) ### Set the delimiter (, or ;) according to your regional settings $query.TextFileOtherDelimiter = $Excel.Application.International(5) ### Set the format to delimited and text for every column ### A trick to create an array of 2s is used with the preceding comma $query.TextFileParseType = 1 $query.TextFileColumnDataTypes = ,2 * $worksheet.Cells.Columns.Count $query.AdjustColumnWidth = 1 ### Execute & delete the import query $query.Refresh() $query.Delete() ### Save & close the Workbook as XLSX. Change the output extension for Excel 2003 $Workbook.SaveAs($outputXLSX,51) $excel.Quit() 

你为什么打扰? 像这样将你的CSV加载到Excel中:

 $csv = Join-Path $env:TEMP "process.csv" $xls = Join-Path $env:TEMP "process.xlsx" $xl = New-Object -COM "Excel.Application" $xl.Visible = $true $wb = $xl.Workbooks.OpenText($csv) $wb.SaveAs($xls, 51) 

您只需确保CSV导出使用区域设置中定义的分隔符。 如果需要,用-Delimiter覆盖。


编辑:一个更一般的解决scheme,应该保持CSV作为纯文本的值。 迭代从这里取得的CSV列的代码。

 $csv = Join-Path $env:TEMP "input.csv" $xls = Join-Path $env:TEMP "output.xlsx" $xl = New-Object -COM "Excel.Application" $xl.Visible = $true $wb = $xl.Workbooks.Add() $ws = $wb.Sheets.Item(1) $ws.Cells.NumberFormat = "@" $i = 1 Import-Csv $csv | % { $j = 1 foreach ($prop in $_.PSObject.Properties) { if ($i -eq 1) { $ws.Cells.Item($i, $j++).Value = $prop.Name } else { $ws.Cells.Item($i, $j++).Value = $prop.Value } } $i++ } $wb.SaveAs($xls, 51) $wb.Close() $xl.Quit() [System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl) 

这个话题真的帮了我很大的忙,所以我想分享一下我的改进。 所有学分都去nixda ,这是基于他的答案。

对于需要在文件夹中转换多个csv的用户,只需修改目录即可。 输出文件名将与input相同,只是另一个扩展名。

最后照顾清理,如果你想保留原来的csv的,你可能不想删除这些

可以很容易地修改将xlsx保存在另一个目录中。

 $workingdir = "C:\data\*.csv" $csv = dir -path $workingdir foreach($inputCSV in $csv){ $outputXLSX = $inputCSV.DirectoryName + "\" + $inputCSV.Basename + ".xlsx" ### Create a new Excel Workbook with one empty sheet $excel = New-Object -ComObject excel.application $excel.DisplayAlerts = $False $workbook = $excel.Workbooks.Add(1) $worksheet = $workbook.worksheets.Item(1) ### Build the QueryTables.Add command ### QueryTables does the same as when clicking "Data » From Text" in Excel $TxtConnector = ("TEXT;" + $inputCSV) $Connector = $worksheet.QueryTables.add($TxtConnector,$worksheet.Range("A1")) $query = $worksheet.QueryTables.item($Connector.name) ### Set the delimiter (, or ;) according to your regional settings ### $Excel.Application.International(3) = , ### $Excel.Application.International(5) = ; $query.TextFileOtherDelimiter = $Excel.Application.International(5) ### Set the format to delimited and text for every column ### A trick to create an array of 2s is used with the preceding comma $query.TextFileParseType = 1 $query.TextFileColumnDataTypes = ,2 * $worksheet.Cells.Columns.Count $query.AdjustColumnWidth = 1 ### Execute & delete the import query $query.Refresh() $query.Delete() ### Save & close the Workbook as XLSX. Change the output extension for Excel 2003 $Workbook.SaveAs($outputXLSX,51) $excel.Quit() } ## To exclude an item, use the '-exclude' parameter (wildcards if needed) remove-item -path $workingdir -exclude *Crab4dq.csv 

如果您想要在没有安装Excel的情况下将CSV转换为Excel,您可以使用伟大的.NET库EPPlus (在LGPL许可证下)创build和修改Excel表格,并将CSV转换成Excel真的很快!

制备

  1. 下载最新的稳定EPPlus版本
  2. 将EPPlus提取到您的首选位置(例如,到$HOME\Documents\WindowsPowerShell\Modules\EPPlus
  3. 右键单击EPPlus.dll,select“属性”,然后在“常规”选项卡的底部单击“取消阻止”以允许加载此dll。 如果您没有权限执行此操作,请尝试[Reflection.Assembly]::UnsafeLoadFrom($DLLPath) | Out-Null [Reflection.Assembly]::UnsafeLoadFrom($DLLPath) | Out-Null

详细的Powershell命令将CSV导入到Excel

 # Create temporary CSV and Excel file names $FileNameCSV = "$HOME\Downloads\test.csv" $FileNameExcel = "$HOME\Downloads\test.xlsx" # Create CSV File (with first line containing type information and empty last line) Get-Process | Export-Csv -Delimiter ';' -Encoding UTF8 -Path $FileNameCSV # Load EPPlus $DLLPath = "$HOME\Documents\WindowsPowerShell\Modules\EPPlus\EPPlus.dll" [Reflection.Assembly]::LoadFile($DLLPath) | Out-Null # Set CSV Format $Format = New-object -TypeName OfficeOpenXml.ExcelTextFormat $Format.Delimiter = ";" # use Text Qualifier if your CSV entries are quoted, eg "Cell1","Cell2" $Format.TextQualifier = '"' $Format.Encoding = [System.Text.Encoding]::UTF8 $Format.SkipLinesBeginning = '1' $Format.SkipLinesEnd = '1' # Set Preferred Table Style $TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium1 # Create Excel File $ExcelPackage = New-Object OfficeOpenXml.ExcelPackage $Worksheet = $ExcelPackage.Workbook.Worksheets.Add("FromCSV") # Load CSV File with first row as heads using a table style $null=$Worksheet.Cells.LoadFromText((Get-Item $FileNameCSV),$Format,$TableStyle,$true) # Load CSV File without table style #$null=$Worksheet.Cells.LoadFromText($file,$format) # Fit Column Size to Size of Content $Worksheet.Cells[$Worksheet.Dimension.Address].AutoFitColumns() # Save Excel File $ExcelPackage.SaveAs($FileNameExcel) Write-Host "CSV File $FileNameCSV converted to Excel file $FileNameExcel" 

这是一个稍微的变化 ,对我来说效果更好。

 $csv = Join-Path $env:TEMP "input.csv" $xls = Join-Path $env:TEMP "output.xlsx" $xl = new-object -comobject excel.application $xl.visible = $false $Workbook = $xl.workbooks.open($CSV) $Worksheets = $Workbooks.worksheets $Workbook.SaveAs($XLS,1) $Workbook.Saved = $True $xl.Quit() 

我有一些问题让其他例子工作。

EPPlus和其他库生成OpenDocument Xml格式,这与从Excel以xlsx保存时所得到的格式不同。

马克斯与开放CSV的例子,只是重新保存没有工作,我从来没有设法得到','分隔符正确使用。

Ansgar Wiechers的例子有一些轻微的错误,我在评论中find了答案。

无论如何,这是一个完整的工作例子。 将其保存在文件CsvToExcel.ps1中

 param ( [Parameter(Mandatory=$true)][string]$inputfile, [Parameter(Mandatory=$true)][string]$outputfile ) $excel = New-Object -ComObject Excel.Application $excel.Visible = $false $wb = $excel.Workbooks.Add() $ws = $wb.Sheets.Item(1) $ws.Cells.NumberFormat = "@" write-output "Opening $inputfile" $i = 1 Import-Csv $inputfile | Foreach-Object { $j = 1 foreach ($prop in $_.PSObject.Properties) { if ($i -eq 1) { $ws.Cells.Item($i, $j) = $prop.Name } else { $ws.Cells.Item($i, $j) = $prop.Value } $j++ } $i++ } $wb.SaveAs($outputfile,51) $wb.Close() $excel.Quit() write-output "Success" 

执行:

 .\CsvToExcel.ps1 -inputfile "C:\Temp\X\data.csv" -outputfile "C:\Temp\X\data.xlsx"