今回はClosedXMLでExcelに画像を挿入します。すでにExcelを起動しているのであれば画像をコピーしてペーストすれば簡単にできます。しかしスクレーピングで大量のデータをあつめた場合、自動で処理をしてしまいたいので、そのときについでに画像も入れたくなることもあるので、そのときの処理を考えます。
まず画像を入れるだけならこんなコードで可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
using ClosedXML.Excel; using ClosedXML.Excel.Drawings; public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { // 画像の左上が「A2」になるようにする int row = 2; int colum = 1; string imagePath = @"./abc.jpg"; // 実行ファイルと同じフォルダ内 using (XLWorkbook wb = new XLWorkbook()) { //ワークシートの設定 IXLWorksheet ws = wb.AddWorksheet("Sheet1"); // AddPictureメソッドで画像を挿入 IXLPicture image = ws.AddPicture(imagePath); // 目的の場所に移動 image.MoveTo(ws.Cell(row, colum)); // ワークブックを保存(実行ファイルと同じフォルダ) wb.SaveAs("file.xlsx"); } } } |
完成♪
とはなりません。写真だけをいれるのであればこれで終わりかもしれませんが、Excelであれば他のデータもあるはずです(むしろこっちが主役)。画像を挿入したあと入力されたデータがあるかもしれないのです。
セルの高さがすべて同じであるなら、画像の高さを調べてセルの高さで割れば画像が占める行が何行なのかわかるはずです。そこでこんなコードを書いてみます。
これだとうまくいきません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public partial class Form1 : Form { private void button2_Click(object sender, EventArgs e) { // 画像の左上が「A2」になるようにする int row = 2; int colum = 1; string imagePath = @"./abc.jpg"; // 実行ファイルと同じフォルダ内 using (XLWorkbook wb = new XLWorkbook()) { // 画像を挿入 IXLWorksheet ws = wb.AddWorksheet("Sheet1"); IXLPicture image = ws.AddPicture(imagePath); image.MoveTo(ws.Cell(row, colum)); // 画像が何行使用しているか調べているつもり? double rowHeight = ws.RowHeight; double rowCount = image.Height / rowHeight; ws.Cell(row + (int)Math.Ceiling(rowCount), colum).Value = "文字を入力する"; // ワークブックを保存(実行ファイルと同じフォルダ) wb.SaveAs("file.xlsx"); // セルの高さは? Console.WriteLine("rowHeight = " + rowHeight); } } } |
実行結果
上記のコードではセルの高さを調べていますが、ここで取得できる値の単位はピクセルではありません。
高さ:15.00(20ピクセル)と表示されていますが、ws.RowHeightで取得できるのはピクセルである20ではなく15.00です。この値の単位はポイントです。
ではこれならどうでしょうか?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public partial class Form1 : Form { private void button3_Click(object sender, EventArgs e) { // 画像の左上が「A2」になるようにする int row = 2; int colum = 1; string imagePath = @"./abc.jpg"; // 実行ファイルと同じフォルダ内 using (XLWorkbook wb = new XLWorkbook()) { // 画像を挿入 IXLWorksheet ws = wb.AddWorksheet("Sheet1"); IXLPicture image = ws.AddPicture(imagePath); image.MoveTo(ws.Cell(row, colum)); // 画像が何行使用しているか調べているつもり? // 高さ:15.00(20ピクセル)だったので・・・ double rowHeight = ws.RowHeight * 20 / 15; double rowCount = image.Height / rowHeight; ws.Cell(row + (int)Math.Ceiling(rowCount), colum).Value = "文字を入力する"; // ワークブックを保存(実行ファイルと同じフォルダ) wb.SaveAs("file.xlsx"); // セルの高さは? Console.WriteLine("rowHeight = " + rowHeight); } } } |
これだと一応うまくいきます。
問題は幅です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { private void button4_Click(object sender, EventArgs e) { using (XLWorkbook wb = new XLWorkbook()) { // ワークブックを保存(実行ファイルと同じフォルダ) wb.SaveAs("file.xlsx"); // セルの幅は? Console.WriteLine("columnWidth = " + ws.ColumnWidth); } } } |
columnWidthに格納される値の単位もピクセルではありません。「標準フォントの半角文字の文字数」です。そのため標準フォントを変更すると同じ幅でも値も変わってしまうのです。
それでも新しくファイルを作成する場合は ws.ColumnWidth * 7 + 5 とすれば単位をピクセルに変換することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public partial class Form1 : Form { private void button5_Click(object sender, EventArgs e) { // 画像の左上が「A2」になるようにする int row = 2; int colum = 1; string imagePath = @"./abc.jpg"; // 実行ファイルと同じフォルダ内 using (XLWorkbook wb = new XLWorkbook()) { // 画像を挿入 IXLWorksheet ws = wb.AddWorksheet("Sheet1"); IXLPicture image = ws.AddPicture(imagePath); image.MoveTo(ws.Cell(row, colum)); // 画像が何行使用しているか調べているつもり? double rowHeight = ws.RowHeight * 20 / 15; double rowCount = image.Height / rowHeight; //ws.Column(colum).Width = Math.Ceiling(1d * (image.Width - 5) / 7); double columnWidth = ws.ColumnWidth * 7 + 5; double columCount = image.Width / columnWidth; ws.Cell(row + (int)Math.Ceiling(rowCount), colum).Value = "文字を入力する"; ws.Cell(row, colum + (int)Math.Ceiling(columCount)).Value = "文字を入力する"; // ワークブックを保存(実行ファイルと同じフォルダ) wb.SaveAs("file.xlsx"); // セルの高さは? Console.WriteLine("rowHeight = " + rowHeight); } } } |
一応うまくできたっぽい。