Excelファイルを項目別に分割する処理をC#でやるにはどうすればよいでしょうか?
たとえば発注管理表に書かれているデータを発注先ごとにわけるにはどうすればよいでしょうか?
これを発注先の名前で複数のファイルにわける。
ここではClosedXMLというライブラリを使います。
ExcelなしでExcelファイルを操作するには?(ClosedXML編)[.NET 4.0、C#/VB]:.NET TIPS – @IT
処理の対象になるファイルを選択しそこからデータを読み取るのですが、読み取ったデータを格納するクラスをつくります。データには発注先、商品名、単価、数量があるので・・・
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 36 37 38 39 |
public class Data { public Data() { } public Data(string supplier, string product, int unitprice, int quantity) { Supplier = supplier; Product = product; Unitprice = unitprice; Quantity = quantity; } public string Supplier { get; protected set; } public string Product { get; protected set; } public int Unitprice { get; protected set; } public int Quantity { get; protected set; } } |
では引数で渡されたパスの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 34 35 36 37 38 39 40 41 42 43 44 45 |
using ClosedXML.Excel; using System.IO; public partial class Form1 : Form { List<Data> GetDatasFromExel(string filePath) { List<Data> datas = new List<Data>(); // Excelファイルを開く using(var workbook = new XLWorkbook(filePath)) { IXLWorksheet worksheet = workbook.Worksheet("発注管理表"); // 位置を指定してセルを取得する IXLCell cellSupplier = worksheet.Cell(2, "A"); IXLCell cellProduct = worksheet.Cell(2, "B"); IXLCell cellUnitprice = worksheet.Cell(2, "C"); IXLCell cellQuantity = worksheet.Cell(2, "D"); while(true) { try { string supplier = cellSupplier.GetValue<string>(); string product = cellProduct.GetValue<string>(); int unitprice = cellUnitprice.GetValue<int>(); int quantity = cellQuantity.GetValue<int>(); datas.Add(new Data(supplier, product, unitprice, quantity)); cellSupplier = cellSupplier.CellBelow(); cellProduct = cellProduct.CellBelow(); cellUnitprice = cellUnitprice.CellBelow(); cellQuantity = cellQuantity.CellBelow(); } catch { break; } } } return datas; } } |
次にGetDatasFromExel(string filePath)メソッドを実行して得られたDataのリストを発注先でグループにわけます。
1 2 3 4 5 6 7 |
List<Data> datas = GetDatasFromExel(filePath); var query = datas.GroupBy(x => x.Supplier); foreach(IGrouping<string, Data> group in query) { OutputFiles(outputFolderPath, group); // 後述 } |
分割されたデータを保存するフォルダを決めます。処理対象になったファイルが存在するフォルダのなかに現在時刻をもとに新しいフォルダを作成し、そこに出力します。フォルダ名はoutput-2020-11-15-10-30-00のような名前になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { // フォルダを作成してそのパスを返す string OutputFolderPath(string sourcePath) { FileInfo info = new FileInfo(sourcePath); DateTime dt = DateTime.Now; string folderPath = info.DirectoryName + "\\output-" + dt.ToString("yyyy-MM-dd-HH-mm-ss"); if(!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath); return folderPath; } } |
OutputFiles(string outputFolderPath, IGrouping
ここではファイル名を発注先の名前にしています。
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 36 37 38 39 40 41 42 |
public partial class Form1 : Form { void OutputFiles(string outputFolderPath, IGrouping<string, Data> group) { string ExcelFilePath = outputFolderPath + "\\" + group.Key + ".xlsx"; // Excelファイルを作る using(var workbook = new XLWorkbook()) { // ワークシートを追加する var worksheet = workbook.Worksheets.Add("発注書"); // セルに値や数式をセット worksheet.Cell(1, "A").Value = "商品名"; worksheet.Cell(1, "B").Value = "単価"; worksheet.Cell(1, "C").Value = "数量"; worksheet.Cell(1, "D").Value = "金額"; int i = 2; foreach(Data data in group) { worksheet.Cell(i, "A").Value = data.Product; // 単価 worksheet.Cell(i, "B").Value = data.Unitprice; worksheet.Cell(i, "B").Style.NumberFormat.SetFormat("#,##0"); // 数量 worksheet.Cell(i, "C").Value = data.Quantity; // 小計 worksheet.Cell(i, "D").FormulaA1 = String.Format("= B{0}*C{0}", i); worksheet.Cell(i, "D").Style.NumberFormat.SetFormat("#,##0"); i++; } // ワークブックを保存する workbook.SaveAs(ExcelFilePath); } } } |
最後に全部の処理をつなげるとこうなります。
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 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Exelファイル|*.xlsx"; dialog.DefaultExt = "xlsx"; if(dialog.ShowDialog() == DialogResult.OK) { string filePath = dialog.FileName; List<Data> datas = GetDatasFromExel(filePath); var query = datas.GroupBy(x => x.Supplier); string outputFolderPath = OutputFolderPath(filePath); foreach(IGrouping<string, Data> group in query) { OutputFiles(outputFolderPath, group); } } dialog.Dispose(); MessageBox.Show("処理は完了しました"); } } |