この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
昨日、「Windowsを使わないで、CSVからExcelを生成して、一部自動化」と言う事で、NPOIを紹介させて頂きました。
MacでcsvからExcelファイルを生成する(祝!本日公開のVisual Studio for Macを使ってみました)
しかし、Visual Studio for Mac 上から実行すると問題ないが、コマンドラインから実行すると、出力されるExcelファイルが、何故か0バイトになってしまうという問題に当たってしまいました。
本日は、比較試験も兼ねて、EPPulsで試してみました。 もちろん本日も、Visual Studio for Mac利用です。(今日はダークモード)
2 EPPlus
EPPlusもOpen XMLの仕様に基いてExcelデータを行うライブラリですが、Excel 2007より前のバージョン(xls)には、対応していません。
EPPlus-Create advanced Excel spreadsheets on the server
実は、ClosedXMLも試してみたのですが、こちらは、うまく動かすことが出来ませんでした。
Unhandled Exception:
System.TypeInitializationException: The type initializer for 'System.Drawing.KnownColors' threw an exception.
---> System.TypeInitializationException: The type initializer for 'System.Drawing.GDIPlus' threw an exception.
---> System.DllNotFoundException: libgdiplus.dylib
3 作成手順
(1) プロジェクト作成
メニューから、ファイル > 新しいソリューションで新しいプロジェクトを作成しました。
名前は、ExcelGenelatorByEPPlusとしました。
(2) NuGetの追加
パッケージを追加しました。
NuGetライブラリでは、EPPlusで簡単に検索できます。
依存関係はなく、EPPlusのみがインストールされます。
(3) Excelファイルの準備
出力するExcelファイルは、罫線や書式を、予め作成しています。(金額や消費税などは、式で入っています)
sample.xlsx
(4) csvファイルの準備
差し込みに使うデータ(品名、数量、単価)は、csv形式で用意しました。
sample.csv
サーモン,5000,150
いか,5,200
さば,2,190
まぐろ,4,230
いるか,1,12000
(5) 実装
実装は、次のようになりました。 テンプレートのExcelファイルを開いて、Csvからデータを移して、新しいExcelファイルとして保存しています。
ちょっと注意が必要なのは、SheetやCellの配列が0からではなく1から指定することです。 なお、NPOIの時のように、再計算の処理は必要ありませんでした。
using System;
using System.IO;
using System.Reflection;
using System.Linq;
using OfficeOpenXml;
namespace ExcelGenelator
{
class MainClass
{
public static void Main(string[] args)
{
//args = new String[] { "input.csv", "output.xlsx" };
// アプリケーションのフルパス
var appPath = Assembly.GetExecutingAssembly().Location;
if (args.Length != 2)
{
Console.WriteLine($"use: mono {Path.GetFileName(appPath)} input.csv output.xlsx");
return;
}
var appDirectory = Path.GetDirectoryName(appPath);
// テンプレートExcel
var templateExcelName = Path.Combine(appDirectory, "template.xlsx");
if (!File.Exists(templateExcelName))
{
Console.WriteLine($"ERROR {templateExcelName} not Found.");
return;
}
// 入力CSV
var inputCsvName = Path.Combine(appDirectory, args[0]);
if (!File.Exists(inputCsvName))
{
Console.WriteLine($"ERROR {inputCsvName} not Found.");
return;
}
// 出力Excel
var outputExcelName = Path.Combine(appDirectory, args[1]);
var wb = new ExcelPackage(new FileInfo(templateExcelName));
var sheet = wb.Workbook.Worksheets.First();
var lines = File.ReadAllLines(inputCsvName);
foreach (var item in lines.Select((line, row) => new { line, row }))
{
var values = item.line.Split(',');
foreach (int i in Enumerable.Range(0, 3))
{
// データを差し込むのは7行目のカラム3個目以降(セル番号は、0からではなく1から指定)
var cell = sheet.Cells[item.row + 8, i + 4];
if (i == 0) // 品名は、文字として挿入
{
cell.Value = values[i];
}
else
{ // 数量・単価は、数値として挿入
cell.Value = Int32.Parse(values[i]);
}
}
//数式の再計算は必要ありません。
wb.SaveAs(new FileInfo(outputExcelName));
}
}
}
}
4 動作確認
出力ファイルは、次のようになりました。今日も、サーモンは多い目です。
5 コマンドライン
Visual Studioで生成されるのは、exeファイルです。
コマンドラインから、次のように使用します。(第1パラメーター:入力CSV、第2パラメーター:出力ファイル)
$ mono ExcelGenelatorByEPPlus.exe input.csv output.xlsx
今回は、問題なくoutput.xlsxが出力されました。 もしかすると、MacでC#でExcelファイルを作るなら、EPPlus 一択かも知れません。>YOSHIEさん
6 最後に
NPOIの出力がmonoでうまく出せないのは、固有の問題のようです。XSSFWorkbookのWriteメソッドで直接ファイルストリームに書き出さずに、一旦、メモリ上に吐いてから、改めてファイル化したりすると上手くいくかも知れません。(すいません、未確認です)
EPPlusを使用する場合も、グラフやマクロなどは、正常に処理できません。また、残念ながら、印刷出力も出来ません。
[GitHub] https://github.com/furuya02/ExcelGenelatorByEPPlus
6 参考資料
EPPlusの基本的な使い方メモ (xlsx形式, Excelのインストール必要ない, COM使わない)
MacでcsvからExcelファイルを生成する(祝!本日公開のVisual Studio for Macを使ってみました)