https://github.com/dfinke/ImportExcel
エクセルファイルのデータをPowerShellに取り込む - Qiita
以下は、PowerShellを使用して、COMオブジェクトを使わずにExcelファイルをXML解析し、新しいXMLファイルを作成して保存するスクリプトです。
# Excelファイルのパスを指定
$excelFilePath = "C:\\path\\to\\your\\file.xlsx"
# 出力するXMLファイルのパスを指定
$outputXmlPath = "C:\\path\\to\\your\\output.xml"
# 一時フォルダを作成
$tempFolderPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory -Path $tempFolderPath | Out-Null
# 他のユーザーがファイルを開いていても読み取れるようにファイルストリームを作成
$stream = [System.IO.File]::Open($excelFilePath, 'Open', 'Read', 'ReadWrite')
# ZipArchiveを使用してExcelファイル(ZIP形式)を読み込む
$zipArchive = New-Object System.IO.Compression.ZipArchive($stream, [System.IO.Compression.ZipArchiveMode]::Read)
# 必要なファイルを一時フォルダに解凍
foreach ($entry in $zipArchive.Entries) {
$destinationPath = Join-Path $tempFolderPath $entry.FullName
$destinationDir = [System.IO.Path]::GetDirectoryName($destinationPath)
if (!(Test-Path $destinationDir)) {
New-Item -ItemType Directory -Path $destinationDir | Out-Null
}
if ($entry.Name) {
$entryStream = $entry.Open()
$fileStream = [System.IO.File]::Create($destinationPath)
$entryStream.CopyTo($fileStream)
$entryStream.Close()
$fileStream.Close()
}
}
$zipArchive.Dispose()
$stream.Close()
# sharedStrings.xmlを読み込む(共有文字列の取得用)
$sharedStringsPath = Join-Path $tempFolderPath "xl\\sharedStrings.xml"
if (Test-Path $sharedStringsPath) {
[xml]$sharedStringsXml = Get-Content -Path $sharedStringsPath -Raw -Encoding UTF8
# 名前空間マネージャを作成
$namespaceManager = New-Object System.Xml.XmlNamespaceManager($sharedStringsXml.NameTable)
$namespaceManager.AddNamespace("x", '<http://schemas.openxmlformats.org/spreadsheetml/2006/main>')
$sharedStrings = @{}
$index = 0
foreach ($si in $sharedStringsXml.SelectNodes('//x:si', $namespaceManager)) {
if ($si.t) {
$sharedStrings[$index] = $si.t.'#text'
} elseif ($si.r) {
# リッチテキストの場合、全てのテキストノードを連結
$text = ""
foreach ($r in $si.r) {
$text += $r.t.'#text'
}
$sharedStrings[$index] = $text
}
$index++
}
}
# シートのXMLファイルを読み込む
$sheetFiles = Get-ChildItem -Path (Join-Path $tempFolderPath "xl\\worksheets") -Filter "sheet*.xml"
$newXml = New-Object System.Xml.XmlDocument
$root = $newXml.CreateElement("Workbook")
$newXml.AppendChild($root) | Out-Null
foreach ($sheetFile in $sheetFiles) {
[xml]$sheetXml = Get-Content -Path $sheetFile.FullName -Raw -Encoding UTF8
# 名前空間マネージャを作成
$namespaceManager = New-Object System.Xml.XmlNamespaceManager($sheetXml.NameTable)
$namespaceManager.AddNamespace("x", '<http://schemas.openxmlformats.org/spreadsheetml/2006/main>')
# シート要素を作成
$sheetElement = $newXml.CreateElement("Sheet")
$sheetName = [System.IO.Path]::GetFileNameWithoutExtension($sheetFile.Name)
$sheetElement.SetAttribute("Name", $sheetName)
$root.AppendChild($sheetElement) | Out-Null
# セルの値を取得
$cells = $sheetXml.SelectNodes('//x:sheetData/x:row/x:c', $namespaceManager)
foreach ($cell in $cells) {
$cellRef = $cell.r
$cellValueType = $cell.t
$cellValue = $cell.v
# セルに値がない場合はスキップ
if (-not $cellValue) {
continue
}
# 共有文字列の場合の処理
if ($cellValueType -eq "s") {
$cellText = $sharedStrings[$cellValue]
} else {
$cellText = $cellValue
}
$cellElement = $newXml.CreateElement("Cell")
$cellElement.SetAttribute("Reference", $cellRef)
$cellElement.InnerText = $cellText
$sheetElement.AppendChild($cellElement) | Out-Null
}
}
# 新しいXMLファイルを保存
$newXml.Save($outputXmlPath)
# 一時フォルダを削除
Remove-Item -Recurse -Force $tempFolderPath
説明:
Excelファイルのパスを指定
$excelFilePath
に解析したいExcelファイルのパスを指定します。
出力するXMLファイルのパスを指定
$outputXmlPath
に保存したいXMLファイルのパスを指定します。
一時フォルダを作成
一時的な作業フォルダを作成します。
Excelファイルを解凍
System.IO.Compression.ZipFile
クラスを使用して、Excelファイル(実際にはZIP形式)を一時フォルダに解凍します。
共有文字列の読み込み
共有文字列を格納している sharedStrings.xml
を読み込み、インデックスと文字列のハッシュテーブルを作成します。
シートのXMLファイルを読み込む
解凍したフォルダ内の xl\\\\worksheets
ディレクトリからシートのXMLファイル(例:sheet1.xml)を取得します。
新しいXMLドキュメントを作成
Workbook
ルート要素を持つ新しいXMLドキュメントを作成します。
各シートの処理
XMLファイルを保存
最終的に作成したXMLドキュメントを指定したパスに保存します。
一時フォルダを削除
作業で使用した一時フォルダを削除してクリーンアップします。
注意点: