サーバサイドでExcelブックを生成するいくつかの方法

[Excel Advent Calendar 2014](http://qiita.com/advent-calendar/2014/excel)の12/1分の記事です。

Webアプリケーションなど、サーバ側でExcelのファイルを生成したいことはたまにあるでしょうから、いくつかの方法をご紹介します。

## .xlsxを読み書きできるライブラリを使う

いろんな言語にいろんなライブラリがありますからいくつか並べてみます。

### Java →Apache POI

http://poi.apache.org/

おそらく一番実績のあるライブラリではないでしょうか。Excelのほとんどの機能をカバーしています。
Javaでしたらこれを使っておけばまず間違いないでしょうし、ほかの言語だったとしてもJavaとのブリッジとかバインディングとかが用意されていればそれを経由してPOIを呼び出すこともできたりします。

### Scala →SPOIWO

https://github.com/norbert-radyk/spoiwo

"Scala POI Wrapping Objects"の名前の通り、Scala用のPOIラッパーです。ScalaですからPOIをそのまま使うこともできるかもしれませんが、たぶんこっちを使うほうがすっきりするでしょう。

### C/C++ →libXL または libxlsxwriter または SimpleXlsxWriter

高機能なものは見つかりませんでした。

http://www.libxl.com/

libXLは有償ライブラリで、図形・チャート・VBAには対応していないですが、.xls/.xlsxの両方の読み書きができるようです。

http://libxlsxwriter.github.io/

ごく限られた機能のみ備えたxlsxファイルライターです。Excelファイルの読み取り機能は持っていませんし、図形・チャート・VBAなども出力できません。また、Windowsをサポートしてません。

http://sourceforge.net/projects/simplexlsx/

C++用ライブラリ。書き込み専用ですがチャートはサポートしているようです。図形やVBAは未対応。

### PHP →PHPExcel

https://github.com/PHPOffice/PHPExcel

図形・チャート・VBAは対象外ですが、.xlsx以外にもいろんなファイルフォーマットをサポートしています。

### Perl →Excel::Writer::XLSX

http://jmcnamara.github.io/excel-writer-xlsx/

書き込み専用ですがチャートはサポートしています。読み取りには [Spreadsheet::XLSX](https://metacpan.org/pod/Spreadsheet::XLSX) がよさそうです。

### Python →XlsxWriter または openpyxl

https://pypi.python.org/pypi/XlsxWriter/

Excel::Writer::XLSXを移植したものらしいです。チャートをサポート。

https://openpyxl.readthedocs.io/

PHPExcelを移植したものらしいです。図形・チャート・VBAは対象外のよう。

### Ruby →axlsx

https://github.com/randym/axlsx

チャートやピボットテーブルのサポートあり。また、いくつかのファイルフォーマットもサポート。

### .NET →ClosedXML または NPOI または EPPlus

https://github.com/closedxml/closedxml

C#, VB.NET, F#などで使えます。図、チャート、VBAのサポートはありません。

https://github.com/tonyqus/npoi

POIの.NET移植版がNPOIです。[IKVM.NET](http://www.ikvm.net/) を使えばPOIそのものを動かすこともできますが、ソースに手を入れたりなどしたければNPOIのほうがいい場合もあるでしょう。

https://github.com/JanKallman/EPPlus

チャート、VBA、数式などなどいろんな機能をサポートしているようです。NPOIよりいいのかも。

## Office Open XML (OOXML) を書き出す

.xlsxフォーマットの仕様は[ECMA-376標準 Office Open XML File Formats](http://www.ecma-international.org/publications/standards/Ecma-376.htm)として標準化され公開されています。端的に言えば、「データやメタデータを含むXMLファイルと、画像などのバイナリファイルを、まとめてZIPアーカイブ化したもの」です。なので、どんな言語だろうが頑張れば自力で作れないこともないです。頑張れば。

MSDNに日本語情報があります。

* [Office (2007) Open XML ファイル形式の概要](http://msdn.microsoft.com/ja-jp/library/aa338205.aspx)
* [方法 : Office オープン XML 形式のドキュメントを操作する](http://msdn.microsoft.com/ja-jp/library/aa982683.aspx)

.NET用のSDKはOSSとして公開されています。

https://github.com/OfficeDev/Open-XML-SDK

でもこのSDKはかなりローレベルなので、OOXMLの仕様を知っていないと使いこなせないでしょう。ガンバッテクダサイ。

## XML Spreadsheetを書き出す

これは.xlsxフォーマットではなくて、拡張子.xml（すなわち、単一のXMLファイル）で表現されるExcelブックのフォーマットです。このフォーマット自体はExcel 2003のころから読み書きできるようになっていて、仕様は標準化こそされていないものの[公開され](https://docs.microsoft.com/en-us/previous-versions/office/developer/office-xp/aa140066(v=office.10))ていますし、[特許侵害を主張しない約束](https://docs.microsoft.com/en-us/openspecs/dev_center/ms-devcentlp/1c24c7c8-28b0-4ce1-a47d-95fe1ff504bc)がされています。

[このフォーマットには機能制限があり](https://support.microsoft.com/ja-jp/office/8e7e858b-eda6-47eb-a1e5-b82a7bdffc3f)、図形・チャート・VBAはサポートされていませんが、それらを使わないのであればOOXMLよりずっと単純ではあります。

## Access データベースエンジンを使う (Windowsのみ)

Access 2003まではJetエンジンと言っていましたが、Access 2007以降はAccess Connectivity Engine (ACE) というものに変わっています。

- https://www.microsoft.com/ja-jp/download/details.aspx?id=13255
- https://www.microsoft.com/en-us/download/details.aspx?id=54920

特殊な接続文字列を使うことで、.xlsxファイルにSQLを発行できます。すなわち、データの読み書きができます。

`Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\myFolder\myExcel2007file.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES";`

接続できたら、あとは[Jetエンジンの時と同じ](http://support.microsoft.com/kb/316934/ja)ように操作できます。

## HTMLを拡張子 .xls で保存する

はい、Excelブックを作成しているわけではありません。HTMLをExcelで開いているだけですね。

なので、ファイルをExcelで開こうとすると警告ダイアログが出ます（「はい」を選べば開くことができます）。また、ファイルを保存すると「この形式ではブックの一部の機能が失われます。この形式でブックを保存しますか？」などと聞かれます。

あまり実用性はないですが、一応書いておきました。

## （やってはいけない）Officeのサーバサイドオートメーション

COMのインターフェースを介してExcelのプロセスを起動して通信することができます、できますがやるべきではありません。

理由は[マイクロソフトが詳しく述べています](http://support.microsoft.com/kb/257757)が、要はトラブルの元だしMSとしてもサポートしないということです。また、[クライアントPCにExcelがインストールされていなければライセンス違反になる可能性](http://blogs.msdn.com/b/office_client_development_support_blog/archive/2012/04/12/1-office.aspx)もあります。

## （どうしてもというなら）LibreOffice/OpenOfficeのサーバサイドオートメーション

LibreOffice/OpenOfficeには[Universal Network Objects (UNO)](https://www.openoffice.org/udk/common/man/uno.html) という、COM/OLEに似たインターフェースがあります。なので、LibreOffice/OpenOfficeのプロセスを起動した後、UNOを介して通信することができます、できますが大変ですよ？

Microsoft Officeと違い、ライセンスやサポートのことは考えなくてもよいと思いますが、マルチスレッド動作できないとか、デッドロックにつながりやすいといった、安定性の問題については同じようなことが当てはまります。

上に書いたような方法で解決できないのであれば、まあ仕方ないかもしれませんが……