コピペでできる、C#で完全自動でExcelシートからWordの請求書をつくる
請求書の数字変えるだけ、たかが数分ですが毎月となると面倒ですよね。さらっと自動化しましょう。
C#からMS Officeを叩く方法はいくつかあるのですが、COMを使ったやり方が一番気軽に行えます。(MS Officeがインストールされている限定)今回は365のVer1809を使っています。
COMとは?
COMはWindowsのAPIの利用プロトコルみたいなものでこの規約に沿った形で様々なアプリケーションが機能を提供していて、プログラマーはそれらを利用できます。(CeVIO Creative StudioとかもCOM提供してる、ボイロはしてないから裏で苦労してる人が居る)
アプローチ
【手動、1回のみ】テンプレートとなるWord文章を作成
【手動、1回のみ】テンプレート内の毎回変わる部分をメタ文書(「%HOGEHOGE%」など)に変更
Excelの指定セルの数値を取得
テンプレートのメタ文字を置換
ライブラリなど
MS OfficeのCOMを使うために次の参照を追加します
次の2クラスを作成
適当なラッパです。コピペでOKですが、usingの関係でWordとExcelの名前がぶつかるので別のファイルにした方がいいです。using
using System; using System.Collections.Generic; using Microsoft.Office.Interop.Excel; class Excel : IDisposable { public Dictionary<string, Worksheet> Sheets = new Dictionary<string, Worksheet>(); private Application excel; private Workbook workbook; public Excel(string filePath) { excel = new Application { Visible = false }; workbook = excel.Workbooks.Open(filePath); for(int i = 0; i < workbook.Sheets.Count; i++) { Worksheet sheet = workbook.Sheets.Item[i+1]; Sheets.Add(sheet.Name, sheet); } } public void Dispose() { workbook.Close(); workbook = null; excel.Quit(); excel = null; } public int ReadCellInt(string sheetKey, string address) { var value = ReadCell(sheetKey, address); var integer = (int)(Math.Round(float.Parse(value))); return integer; } public string ReadCell(string sheetKey, string address) { var range = Sheets[sheetKey].get_Range(address); var cell = range.Cells[1,1]; return cell.Value.ToString(); } }
using System; using Microsoft.Office.Interop.Word; class Word : IDisposable { private Application word; private Document document; public Word(string filePath) { word = new Application { Visible = false }; document = word.Documents.Open(filePath, ReadOnly:true); } public void Dispose() { document.Close(); document = null; word.Quit(); word = null; } public void Replace(string search, string replace) { Find find = word.Selection.Find; find.ClearFormatting(); find.Text = search; find.Replacement.ClearFormatting(); find.Replacement.Text = replace; find.Execute(Replace: WdReplace.wdReplaceAll); } public void SaveAs(string savePath) { document.SaveAs2(savePath); } public void SavePdf(string savePath) { document.SaveAs2(savePath, FileFormat: WdSaveFormat.wdFormatPDF); } }
置換してみる
Excel.ReadCellInt
と Word.Replace
を毎回変わる部分の数だけ繰り返せばOKです。
using(var excel = new Excel("読み込むエクセルシートのパス.xlsx")){ var cellAddress = "P15とかA7みたいなエクセルのセルアドレス"; var price = excel.ReadCellInt("シートの名前", cellAddress); using(var word = new Word("テンプレートのWord文書のパス.docx")){ word.Replace("%値段%", prive.ToString()); word.SaveAs("保存するパス.docx"); word.SavePdf("PDFでも保存できるよ.pdf"); } }