C#でQR画像入りExcelを作る(NPOI、ZXing)
はじめに
QRを印刷したい。印刷時の大きさや並び順を後から加工できるよう、Excel形式で欲しい。
というのが、今回の要望です。
QR画像生成、Excel作成もライブラリを使用すれば結構簡単にできてしまいます。便利なライブラリに感謝です。
概要
こんな感じのExcelを作ります。
1列目にQRにしたい文字列を設定し、2列目にQR画像を張り付けています。
以下のライブラリを使用します。
- NPOI(Excel作成に使用)
- ZXing.Net(QR画像作成に使用)
以下が今回作成したプログラムの流れです。
- NPOIを使用してExcelブックを作成
- 1行ごとにZXingを使用してQR画像を生成し、Excelに貼り付け
- ファイルを保存
それでは早速作ってみましょう。
作ってみる
Visual Studioを使用します。C#(.NET6)で開発していきます。
Windows環境を前提にしています。
プロジェクト作成
Visual Studioを起動し、「新しいプロジェクトの作成」を選択します。
新しいプロジェクトの作成では「コンソールアプリ」を選択しました。
プロジェクト名を「ExcelQr」とし「次へ」をクリック。
追加情報では「.NET 6.0」が選択されていることを確認し「作成」をクリック。
パッケージのインストール
NuGetパッケージマネージャーから下記パッケージをインストールします。
- NPOI
- ZXing.Net
- ZXing.Net.Bindings.Windows.Compatibility
QR文字列
サンプルに使用する文字列は13桁の数字、8桁の数字、URLの3つを用意しました。
// QR生成対象の文字列
var qrstrings = new[]
{
"1234567890123",
"87654321",
"https://www.google.com/?hl=ja",
};
QR画像作成
ZXingを使用してQRを生成しますが、.NETコンソールのデフォルトでは画像操作ライブラリが含まれないため次のエラーが発生します。
CS0305: ジェネリック 種類 'BarcodeWriter<TOutput>'を使用するには、1 型引数が必要です
この問題を回避するためにインストールしたパッケージZXing.Windows.Compatibility
を使用しています。
QR画像の大きさや種類(バーコードにするかQRにするか等)はBarcodeWriter
のプロパティで指定できます。
// QRコード作成
var makeQr = (string text) =>
{
// ZXing.Windows.Compatibilityを使用
var qrwriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
};
// QRコードを生成する
using var bmp = qrwriter.Write(text);
using var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Bmp);
// Excelブックに画像を挿入
return book.AddPicture(ms.GetBuffer(), PictureType.BMP);
};
Excelに画像貼り付け
NPOIを使用してExcelに画像を貼り付けます。
CreateClientAnchor()
で貼り付けセルの位置を指定します。
セルの大きさや見た目は適宜調整してください。
var writeRows = (ISheet sheet, string[] qrstrings) =>
{
// 0行目はヘッダ行に使う
var rowIndex = 0;
foreach (var qrstr in qrstrings)
{
rowIndex++;
var row = sheet.CreateRow(rowIndex);
// 行の高さ調整
row.HeightInPoints = 120;
// 0列はQR変換前の文字
row.CreateCell(0).SetCellValue(qrstr);
// QR画像を生成し、Excelに貼り付け
var pictureIdx = makeQr(qrstr);
// 1列にQR画像を配置
var anchor = book.GetCreationHelper().CreateClientAnchor();
anchor.Col1 = 1;
anchor.Row1 = rowIndex;
anchor.Col2 = 2;
anchor.Row2 = rowIndex + 1;
anchor.AnchorType = AnchorType.MoveDontResize;
var patriarch = sheet.CreateDrawingPatriarch();
patriarch.CreatePicture(anchor, pictureIdx);
}
};
完成コード
これを実行すると冒頭のExcelファイルがfilePath
に作成されます。
細かいところを補足すると、NPOIのブックインスタンスはSXSSFWorkbook
を使用しており、メモリ使用量を抑えたつもりです。(画像ファイルとExcelファイルを同時にメモリ上に展開するとメモリ消費が激しいことが予想される)SXSSFWorkbook
はメモリ使用量を抑えられる反面、複雑な操作(セルのランダムアクセスやシート操作)が苦手です。そういった要件がある場合はXSSFWorkbook
を使用する必要がありますが、メモリ消費が激しいため、大量にQRを生成する場合は注意してください。
using NPOI.SS.UserModel;
using NPOI.XSSF.Streaming;
using System.Drawing.Imaging;
using ZXing;
using ZXing.Windows.Compatibility;
// 出力ファイルパス
var filePath = @"C:\temp\qrexcel.xlsx";
// QR生成対象の文字列
var qrstrings = new[]
{
"1234567890123",
"87654321",
"https://www.google.com/?hl=ja",
};
// ブックを作成
var book = new SXSSFWorkbook();
// シートを作成
var sheet = book.CreateSheet("qrlist");
// 列幅を調整
sheet.SetColumnWidth(0, 20 * 256);
sheet.SetColumnWidth(1, 20 * 256);
// QRコード作成
var makeQr = (string text) =>
{
// ZXing.Windows.Compatibilityを使用
var qrwriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
};
// QRコードを生成する
using var bmp = qrwriter.Write(text);
using var ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Bmp);
// Excelブックに画像を挿入
return book.AddPicture(ms.GetBuffer(), PictureType.BMP);
};
// QRを含む行を作成
var writeRows = (ISheet sheet, string[] qrstrings) =>
{
// 0行目はヘッダ行に使う
var rowIndex = 0;
foreach (var qrstr in qrstrings)
{
rowIndex++;
var row = sheet.CreateRow(rowIndex);
// 行の高さ調整
row.HeightInPoints = 120;
// 0列はQR変換前の文字
row.CreateCell(0).SetCellValue(qrstr);
// QR画像を生成し、Excelに貼り付け
var pictureIdx = makeQr(qrstr);
// 1列にQR画像を配置
var anchor = book.GetCreationHelper().CreateClientAnchor();
anchor.Col1 = 1;
anchor.Row1 = rowIndex;
anchor.Col2 = 2;
anchor.Row2 = rowIndex + 1;
anchor.AnchorType = AnchorType.MoveDontResize;
var patriarch = sheet.CreateDrawingPatriarch();
patriarch.CreatePicture(anchor, pictureIdx);
}
};
// 行を作成
writeRows(sheet, qrstrings);
// ファイルに保存
using (var fs = new FileStream(filePath, FileMode.Create))
{
book.Write(fs);
}
まとめ
.NET(C#)で画像入りExcelファイルの作り方でした。
NPOI、ZXingの使用方法の参考になれば幸いです。
Discussion