Help us understand the problem. What is going on with this article?

C#でのExcel読み書きライブラリのパフォーマンス比較

More than 3 years have passed since last update.

比較対象のライブラリ

すでに比較されているサイトがあり、参考にします。

C# の Excel ファイル操作ライブラリー
https://creativeweb.jp/aspnet-oss/excel-tools/

この内3つのライブラリについて読み書き性能を比較します。
- NPOI
- EPPlus
- ExcelDataReader

※有償のライブラリはこの他にもあり、性能も優秀なので予算があればそちらをどうぞ。

比較サイトのテストには気になる点があります。書き込みテストと言っても、テスト内容はテンプレート的なファイルを読み込んでからセルに値を設定しファイル出力するものです。よってこの書き込みテスト結果は読み込み性能に引きずられている可能性があります。

私の方でもテストを用意して比較してみました。テストのソースコードはこちらです。

https://github.com/shimitei/DotnetExcelExample

読み込みテスト内容

よりセル数を増やしたテストを行います。読み込ませるExcelファイルは、郵便局のサイトから郵便番号データ(CSV)をダウンロードしたものを加工して使います。CSVファイルをExcelで開き、格子の罫線も引いてXLSX形式で保存します。

データ数は123823行 x 15列 = 約186万セルです。

書き込みテスト内容

15列 x 1万行 = 15万セルをXLSXファイルに書き込みます。加えて、より実践的な書き込み処理とするために全セルに格子の罫線、全列に列幅の自動調整を行います。

セルの内容は、文字列が5列、数値が5列、日付が5列です。内容はランダムなものですが、毎回同じデータを出力するように乱数の種を設定しています。

テスト結果

ライブラリ バージョン 読込処理時間 読込処理
メモリピーク
書込
(15列 x 1万行)
1万行書込
メモリピーク
書込
(15列 x 10万行)
10万行書込
メモリピーク
ExcelDataReader 2.1.2.3 6,649 114,765,824 - - - -
NPOI 2.1.3.1 15,859 1,071,607,808 49,181 91,422,720 508,798 679,505,920
EPPlus 4.0.5 16,197 322,125,824 4,450 75,993,088 43,962 389,931,008

処理時間の単位はミリ秒、メモリピークはバイト(PeakWorkingSet)です。比較サイトでは処理時間のみ見ていましたが、データ数が多くなると使用メモリ量も気になるため計測しています。

読み込みの結果はExcelDataReaderが最速で変わらず、メモリ使用量も最も少ないです。日本語処理の問題は、XLSX形式では見られませんでした。

比較サイトと異なる結果になった要因としては、罫線と列幅の自動調整でしょうか。罫線やフォント等のスタイル設定には思いのほか処理時間がかかっています。

結論

読み込みにはExcelDataReader、書き込みにはEPPlusを使いましょう。

出力100万行突破

たかだか数十万セル程度であればなんら問題なしですが、何故Excelシートに○○○万行も書くのでしょうね? これOutOfMemoryなしに出力できたとしても読み込めないのでは...

とりあえずExcelの闇に飲まれてみます。XLSXファイルは、拡張子は.xlsxでも中身はZIPファイルと同じ形式で、データはXMLに記述されています。このExcelのXML仕様は公開されているっぽいですが、分厚い仕様書を読んでいられない。その、MSオフィスのファイル仕様(Open XML Documents)を扱うためのライブラリOpen-XML-SDKもオープンソース化されているのですが、結構プリミティブ感があってちょっと触りたくないですね。

さらに調べを進めると、Open-XML-SDKですらセル数が多くなるとファイル出力時にOutOfMemoryが出るという話らしく。これは詰んだな、と思ったところに救世主が登場。

Open-Xml-PowerTools
https://github.com/OfficeDev/Open-Xml-PowerTools

一見はPowerShellでMSオフィスファイルを扱うモジュールですが、Open-XML-SDKのサンプル的位置づけの側面もあるようです。

サポート機能の1つが神で、100万行級のXLSXファイル出力でもメモリの問題なく処理可能とあります。

Writing XLSX files using far simpler code than directly writing the markup, including a streaming approach that enables writing XLSX files with millions of rows.

この機能に対応するソースコードはSpreadsheetWriter.csです。
機能が少ないから速いわけでもなく、Open-XML-SDKを利用するものの、XMLのツリー情報を保持しないように要所をバイパスして自前処理でXML出力を行うようになっています。

それでも機能が少なくてしょぼいシートしか吐けないので、フォークして様々なスタイル設定に対応してみました。

https://github.com/shimitei/Open-Xml-PowerTools/tree/cell-style

対応しているスタイルや設定の仕方は、OpenXmlPowerToolsExamples/SpreadsheetWriterStyleプロジェクトを見てください。実行するといろいろExcelファイルが出力されます。

NPOIでも100万行?

Apache POIにはいつの間にかSXSSF (Streaming Usermodel API)というAPIが追加されていて(POI 3.8 beta3から)、このSXSSFはNPOIでもサポートされているようです。ストリーミング処理することで制約はあるものの、あまりメモリを使用せずに出力が可能なようです。

http://poi.apache.org/spreadsheet/index.html

こちらのページにPOIでのSXSSFの利点と制限事項が書かれています。NPOIでも同様かと思われます。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away