ClosedXMLの導入

ClosedXMLをPowershellで使うためのメモ

interop問題

Excel作業を自動化しようとすると、「interopサービスを使いましょう」という古い情報に当たることがあります。最近(2019年夏現在)は幸いにもそんな古い情報に当たることはそうそう無いんですが、それでも「マクロのあるファイルを操作する」とか「Web上のContents Management Service上のファイルを直接操作する」とかExcelじゃないと動かせない場合もあります。

そういった時のためにinteropサービスでExcel作業を自動化する際に当たりがちなエラーをまとめました。結構苦労します(^_^;)


https://f-journey.com/it/problem_in_using_interopservice/

ということで、Excelをオブジェクト化するのではなくxlsxファイルを直接操作するライブラリを調べると、NPOI,ClosedXML,ExcelPackagePlus,ImportExcelなんかがヒットします。

それのうち、Microsoftが作っているClosedXMLを使うためのメモ。

ライブラリの入手

まずは入手する方法から

git-hubからソースをダウンロードしてCompileする

linux環境なら常道ですが、Windowsだとあんまり無い気がします。

nugetからライブラリを入手する

コマンドラインがNuget Galleryの上の方に書かれています。
ClosedXML -Nuget Gallery
例えばこんな感じ

Install-Package ClosedXML -Version 0.94.2

Install-Packageを使ってもいいんですが「proxyを通じて社外アクセスしてる環境ではコケる」ことが多々あります。Powershell5.1以降であればProxyの内側からインストールできます。-Proxyおよび-ProxyCredentialオプションが使えます。詳しくは下記Qiita記事を参照してください。6とありますが、5.1でも使えます

PowerShell 6にプロキシ経由でモジュールインストール

ただ、こうやっても直接関係しないライブラリを大量にダウンロードします。恐らくDependencies(依存関係)に「System.IO.Packaging」が含まれているせいかと思います。

nugetのサイトからライブラリを直接ダウンロードする。

Nuget Galleryの右の方に「Download package」と書かれています。これをダウンロードするとWebから直接ダウンロードできます。2019年9月現在の安定最新版は0.94.2です。

ClosedXML 0.94.2
これをダウンロードすると、「closedxml.0.94.2.nupkg」という拡張子で落ちてきます。
「nupkgなんて拡張子知らないよ」って思うかも知れませんが、これ単にlibファイルとxmlファイルをzip圧縮しただけのものです。拡張子をzipに変えれば普通に展開できます(^_^;)

NugetのDependenciesにあるライブラリとその先のDependenciesをすべて落とします。面倒ですが、関係しないライブラリが落ちまくるよりマシでは?と思います。
v0.94.2版の.NETFramework 4.6での依存先は以下の3つです。

更に、DocumentFormat.OpenXml の依存先として以下が必要です。

最新版の依存関係はNuget Galleryを参照してください。
ClosedXML -Nuget Gallery

ライブラリのロード

今回はC:¥scropt¥にダウンロードしました。
入手できたら次はライブラリのロードです。
PowerShellだと[Reflection.Assembly]::LoadFile()という命令があります。
これは、エラーが起こりませんが、実際にはObject作成の段階で失敗します。
試してみるとAdd-Typeだと実行時にエラーが発生します。
5年くらい前の記事ですが、[Reflection.Assembly]::LoadFile()とAdd-Typeの差は下記を参照しました。

PowerShell の Add-Type と [Reflection.Assembly]

Add-Type -Path C:\script\system.io.packaging.4.5.0\lib\net46\System.IO.Packaging.dll
Add-Type -Path C:\script\documentformat.openxml.2.9.1\lib\net46\DocumentFormat.OpenXml.dll
Add-Type -Path C:\script\excelnumberformat.1.0.7\lib\net20\ExcelNumberFormat.dll
Add-Type -Path C:\script\fastmember.1.5.0\lib\net461\FastMember.dll
Add-Type -Path C:\script\closedxml.0.94.2\lib\net46\ClosedXML.dll 

これを実行すると、下記のエラーが発生します。

Add-Type : 要求された型のうち 1 つまたは複数を読み込めませんでした。詳細については、LoaderExceptions プロパティを取得してください。
発生場所 行:5 文字:1
+ Add-Type -Path C:\script\closedxml.0.94.2\lib\net46\ClosedXML.dll 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException
    + FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeCommand

…なるほど、わからん。LoaderExceptions プロパティを取得してください。ってどうやるねん?
英語で検索したら、下記で取れるとわかりました。結局英語なのね(´;ω;`)

$error[0].Exception.GetBaseException().LoaderException

これを表示した結果がこちら!

LoaderExceptionを見るとこう表示されます。
ファイルまたはアセンブリ 'DocumentFormat.OpenXml, Version=2.7.2.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
ファイルまたはアセンブリ 'DocumentFormat.OpenXml, Version=2.7.2.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
ファイルまたはアセンブリ 'DocumentFormat.OpenXml, Version=2.7.2.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
ファイルまたはアセンブリ 'DocumentFormat.OpenXml, Version=2.7.2.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
ファイルまたはアセンブリ 'DocumentFormat.OpenXml, Version=2.7.2.0, Culture=neutral, PublicKeyToken=8fb06cb64d019a17'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。
#>

え、2.7.2.0が読み込めないってどういう事。Dependenciesは、(>= 2.7.2)って書いてあるやん。最新版入手したやん。
訝しみながらもライブラリをv2.7.2にしたら…動きやがった(ー_ー;)

Hellor Worldを動かす

これでようやくClosedXMLが動かせます。一ヶ月無駄にした

A1セルにHello Worldを入力して保存するscriptがこちら

$WorkBook = new-object ClosedXML.Excel.XLWorkbook
$WorkSheet = $WorkBook.Worksheets.Add()
$Worksheet.Cell("A1").Value = "Hello world";
$WorkBook.SaveAs("$PSScriptRoot\helloworld.xlsx")

やっと動いた…(^_^;)

全体のソースのメモはこちら。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください