この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
1 はじめに
「Windowsを使わないで、CSVからExcelファイルを生成して、一部自動化」と言う事で、NPOIやEPPulusを使用してみましたが、色々と制約を実感しました。
MacでcsvからExcelファイルを生成する(祝!本日公開のVisual Studio for Macを使ってみました)
MacでcsvからExcelファイルを生成する(その2)EPPlus編
という事で、ストレス解消?のため、COMを使ったExcelファイルの生成をやってみました。
2 作成手順
(1) プロジェクト作成
ファイル > 新規作成 > プロジェクト から、C#のコンソールアプリケーションを作成します。(名前は、ExcelGenelatorByComとしました)
(2) 参照の追加
作成されたプロジェクトの参照を追加します。
カテゴリでCOMから、Microsoft.Office.Interop.Excelを追加しますが、、キーワードExcelで検索すると簡単に見つけることが出来ます。
依存関係から、Microsoft.Office.Coreも同時に追加されます。
(3) Excelファイルの準備
元となるExcelファイルは、テンプレートから「四半期売上レポート」を使用しました。(template.xlsxとして保存しました)
このテンプレートでは、製品名と売上金額を入力すると、グラフが完成するようになっています。そして、この製品名と売上金額をCSVから取り込んで差し込むことにします。
(4) csvファイルの準備
差し込むデータは、csv形式で準備しました。
input.csv
サーモン,702938,787362,612250,901011
はまち,182733,384766,192033,302988
さんま,162222,198726,162738,229870
いか,287635,118172,181811,109988
いるか,192822,172655,192888,109892
(5) 実装
実装は、次のようになりました。 テンプレートのExcelファイルを開いて、Csvからデータを移して、新しいExcelファイルとして保存しています。 なお、COMオブジェクトを扱う場合は、参照カウントの解放に注意が必要です。正しくデクリメントされていないと、GCでプロセスが解放されず、残り続けることになってしまいます。
using System;
using System.Linq;
using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Reflection;
using System.IO;
namespace ExcelGenelatorByCom {
class Program {
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]);
if (File.Exists(outputExcelName)) {
File.Delete(outputExcelName);
}
// 入力データ
object[,] datas = new object[29, 5]; // データを差し込む範囲は、B35~F63
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, 5)) {
datas[item.row, i] = values[i];
}
}
Application excel = null;
Workbooks workBooks = null;
Workbook workBook = null;
Worksheet sheet = null;
Range range = null;
try {
excel = new Application();
excel.Visible = false;
workBooks = excel.Workbooks;
workBook = workBooks.Open(templateExcelName);
sheet = workBook.Sheets[1];
range = sheet.Range["B35","F63"];
range.Value2 = datas; // データをコピーする
workBook.SaveAs(outputExcelName); // 出力ファイル名で保存する
excel.Quit();
} finally {
Marshal.ReleaseComObject(range);
Marshal.ReleaseComObject(sheet);
Marshal.ReleaseComObject(workBook);
Marshal.ReleaseComObject(workBooks);
Marshal.ReleaseComObject(excel);
}
}
}
}
3 動作確認
出力ファイルは、次のようになりました。今日もサーモンは多いかも・・・(デフォルト)
4 コマンドライン
コマンドラインから、次のように使用します。(第1パラメーター:入力CSV、第2パラメーター:出力ファイル)
C:¥>ExcelGenelatorByCom.exe input.csv output.xlsx
5 印刷出力
COMで作業する場合、Excelの機能は、殆ど全て利用可能だと思います。 下記は、プログラムの中からワークシートをpdf形式で印刷出力している例です。
// PDF出力
var pdfName = Path.Combine(appDirectory, "sample.pdf");
workBook.ExportAsFixedFormat(
XlFixedFormatType.xlTypePDF,
pdfName,
XlFixedFormatQuality.xlQualityStandard,
true,
true,
Type.Missing,
Type.Missing,
false,
Type.Missing);
出力されたPDFは次のとおりです。グラフだけが表示されているのは、印刷範囲に設定されているためです。
6 最後に
ExcelファイルをOpenXMLのドキュメントとしてだけ扱うのであれば、Windowsは無くても大丈夫ですが、色々な機能をフルに活用するには、やはりWindowsでやるしか有りません。 ということで、ストレス解消編でした。