webdevqa.jp.net

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. 新しく作成されたCSVを読み込み、$processes変数の下に保存します
  3. データを書き込むことができる新しい空のExcelワークブックを作成します
  4. すべての行(?)を反復処理し、name列とvm列のすべての値をExcelに書き込みます。

私の質問

  • 列ヘッダーがわからない場合はどうなりますか? (この例では、nameおよびvm)。ヘッダー名がわからない値に対処するにはどうすればよいですか?
  • CSVの列数をカウントするにはどうすればよいですか? (Import-Csvで読んだ後)

PowerShellを使用してCSV全体をExcelに書き込みたいだけです

4
nixda

アップス、私はこの質問を完全に忘れました。その間に私は解決策を得ました。
このPowershellスクリプトは、CSVをバックグラウンドでXLSXに変換します

ギミックは

  • すべてのCSV値を=B1+B20000001のようなプレーンテキストとして保持します。
    #Nameなどは表示されません。自動フォーマットは行われません。
  • 地域の設定に応じて、適切な区切り文字(カンマまたはセミコロン)を自動的に選択します
  • 列の自動調整

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()
7
nixda

どうしてわざわざするの?次のように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で上書きします。


編集: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 | ForEach-Object {
  $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)

明らかに、この2番目のアプローチは、各セルを個別に処理するため、あまりうまく機能しません。

2
Ansgar Wiechers

このトピックは本当に役に立ちましたので、私の改善点を共有したいと思います。すべてのクレジットはnixdaに送られます。これは、彼の回答に基づいています。

フォルダ内の複数のcsvを変換する必要がある場合は、ディレクトリを変更するだけです。出力ファイル名は入力と同じですが、拡張子が異なります。

元の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
2
obiwankoban

ExcelをインストールせずにCSVをExcelに変換する場合は、優れた.NETライブラリ EPPlus (LGPLライセンスの下)を使用してExcelシートを作成および変更し、CSVをExcelに非常に高速に変換できます。

準備

  1. 最新の安定版をダウンロード EPPlus バージョン
  2. EPPlusを希望の場所に抽出します(例:_$HOME\Documents\WindowsPowerShell\Modules\EPPlus_)
  3. EPPlus.dllを右クリックし、[プロパティ]を選択し、[全般]タブの下部にある[ブロック解除]をクリックして、このdllの読み込みを許可します。これを行う権限がない場合は、[Reflection.Assembly]::UnsafeLoadFrom($DLLPath) | Out-Nullを試してください。

CSVをExcelにインポートするための詳細なPowershellコマンド

_# 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, e.g. "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"
_
1

他の例を機能させるのに問題がありました。

EPPlusおよびその他のライブラリは、OpenDocument Xml形式を生成します。これは、Excelからxlsxとして保存した場合とは異なります。

cSVを開いて再保存しただけのマックの例は機能しませんでした。「、」区切り文字を正しく使用することができませんでした。

Ansgar Wiechersの例には、いくつかのわずかなエラーがあります。これは、開始時に答えを見つけました。

とにかく、これは完全な実例です。これをファイル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"
0
Gil Roitto

これは わずかなバリエーション で、私にとってはうまく機能しました。

$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()
0
mack