csharp [Excel帐票] EXCELで帐票出力するときに使えるかも。#ClosedXML

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp [Excel帐票] EXCELで帐票出力するときに使えるかも。#ClosedXML相关的知识,希望对你有一定的参考价值。

using (var rep = new MyReport())
{
  rep.Write();
}
using ClosedXML.Excel;
using System;
using System.Data;

namespace SampleReport
{
    public class MyReport : ExcelReport, IDisposable
    {
        XLWorkbook xlBook;
        IXLWorksheet xlSheet;

        XLColor color1 = XLColor.White;
        XLColor color2 = XLColor.DarkBlue;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public MyReport()
        {
            RepCtrl.ReportHeaderRows = 14;
            RepCtrl.ReportFooterRows = 0;
            RepCtrl.PageHeaderRows = 1;
            RepCtrl.PageFooterRows = 0;
            RepCtrl.PageMaxRows = 50;
        }

        /// <summary>
        /// レポートを出力します。
        /// </summary>
        public void Write()
        {
            xlBook = new XLWorkbook();
            xlSheet = xlBook.AddWorksheet("請求書(明細)");

            SetBaseDesign();
            SetDetailRows(DetailsRowType.First);

            var dt = GetSampleDetailData();
            WriteReport(dt);

            DefingPageSetup();

            string outputPath = "./out_請求書.xlsx";
            xlBook.SaveAs(outputPath);
        }

        /// <summary>
        /// 印刷用設定
        /// </summary>
        private void DefingPageSetup()
        {
            xlSheet.PageSetup.SetPageOrientation(XLPageOrientation.Portrait);
            xlSheet.PageSetup.SetPaperSize(XLPaperSize.A4Paper);
            xlSheet.PageSetup.PrintAreas.Add(1, 1, LineNo, 28);
            xlSheet.PageSetup.AddHorizontalPageBreak(RepCtrl.PageMaxRows);
            xlSheet.PageSetup.AddVerticalPageBreak(28);
            xlSheet.PageSetup.SetPagesWide(1);
            xlSheet.PageSetup.SetShowGridlines(false);
        }

        /// <summary>
        /// 既定のデザインを設定します。
        /// </summary>
        private void SetBaseDesign()
        {
            xlSheet.ColumnWidth = 4.0;
            xlSheet.RowHeight = 18.0;

            xlSheet.Row(13).Height = 30.0;
            xlSheet.Row(13).Style.Alignment.SetVertical(XLAlignmentVerticalValues.Center);
            xlSheet.Column(21).Width = 8.0;
            xlSheet.Columns(18, 19).Width = 2.0;

            // 請求書タイトル
            xlSheet.Cell(2, 17).SetValue<string>("請 求 書");
            xlSheet.Range(2, 17, 2, 23).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);

            // 請求書No
            xlSheet.Cell(2, 25).SetValue<string>("No.").Style
                .Font.SetFontColor(color2)
                .Border.SetBottomBorder(XLBorderStyleValues.Thin)
                .Border.SetBottomBorderColor(color2);
            xlSheet.Range(2, 26, 2, 28).Merge().Style
                .Border.SetBottomBorder(XLBorderStyleValues.Thin)
                .Border.SetBottomBorderColor(color2);

            // お客様コード
            xlSheet.Cell(8, 1).SetValue<string>("お客様コード").Style
                .Font.SetFontColor(color2);

            // 文言1
            xlSheet.Cell(9, 1).SetValue<string>("毎度ありがとうございます。").Style
                .Font.SetFontColor(color2);

            // 文言2
            xlSheet.Cell(10, 1).SetValue<string>("下記の通り御請求申し上げます。").Style
                .Font.SetFontColor(color2);

            // 前回繰越金額
            xlSheet.Cell(12, 1).SetValue("前回繰越金額");
            xlSheet.Range(12, 1, 12, 3).Merge().Style
                .Font.SetFontColor(color1)
                .Font.SetBold(true)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);

            // 御入金額
            xlSheet.Cell(12, 4).SetValue<string>("御入金額");
            xlSheet.Range(12, 4, 12, 6).Merge().Style
                .Font.SetFontColor(color1)
                .Font.SetBold(true)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);

            // 今月売上金額
            xlSheet.Cell(12, 7).SetValue<string>("今月売上金額");
            xlSheet.Range(12, 7, 12, 9).Merge().Style
                .Font.SetFontColor(color1)
                .Font.SetBold(true)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);

            // 消費税等
            xlSheet.Cell(12, 10).SetValue<string>("消費税等");
            xlSheet.Range(12, 10, 12, 12).Merge().Style
                .Font.SetFontColor(color1)
                .Font.SetBold(true)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);

            // 今回御請求額
            xlSheet.Cell(12, 17).SetValue<string>("今回御請求額");
            xlSheet.Range(12, 17, 12, 20).Merge().Style
                .Font.SetFontColor(color1)
                .Font.SetBold(true)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center);

            xlSheet.Range(12, 1, 13, 12).Style
                .Border.SetTopBorder(XLBorderStyleValues.Thin)
                .Border.SetBottomBorder(XLBorderStyleValues.Thin)
                .Border.SetRightBorder(XLBorderStyleValues.Thin)
                .Border.SetLeftBorder(XLBorderStyleValues.Thin);

            xlSheet.Range(12, 17, 13, 20).Style
                .Border.SetTopBorder(XLBorderStyleValues.Thin)
                .Border.SetBottomBorder(XLBorderStyleValues.Thin)
                .Border.SetRightBorder(XLBorderStyleValues.Thin)
                .Border.SetLeftBorder(XLBorderStyleValues.Thin);

            // 捺印欄
            xlSheet.Range(12, 25, 13, 26).Style
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin)
                .Border.SetOutsideBorderColor(color2);

            xlSheet.Range(12, 27, 13, 28).Style
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin)
                .Border.SetOutsideBorderColor(color2);
        }

        /// <summary>
        /// レポートヘッダを出力します。
        /// </summary>
        protected override void WriteReportHeader()
        {
            base.WriteReportHeader();

            var data = GetSampleReportHeaderData();

            foreach (DataRow row in data.Rows)
            {
                var xlCell = xlSheet.Cell((int)row["R"], (int)row["C"]);
                xlCell.Value = row["V"].ToString();
            }

            SetReportHeaderDesign();
        }

        /// <summary>
        /// レポートヘッダのスタイルを設定します。
        /// </summary>
        private void SetReportHeaderDesign()
        {
            xlSheet.Cell(5, 1).Style
                .Font.SetBold(true)
                .Font.SetUnderline(XLFontUnderlineValues.Single);
            xlSheet.Cell(6, 28).Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Cell(8, 28).Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Cell(9, 28).Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Range(13, 1, 13, 3).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Range(13, 4, 13, 6).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Range(13, 7, 13, 9).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Range(13, 10, 13, 12).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
            xlSheet.Range(13, 17, 13, 20).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right);
        }

        /// <summary>
        /// ページヘッダを出力します。
        /// </summary>
        protected override void WritePageHeader()
        {
            base.WritePageHeader();

            xlSheet.Cell(LineNo, 1).Value = "伝票日付";
            xlSheet.Cell(LineNo, 4).Value = "伝票No.";
            xlSheet.Cell(LineNo, 7).Value = "品番・品名";
            xlSheet.Cell(LineNo, 18).Value = "数量";
            xlSheet.Cell(LineNo, 21).Value = "単位";
            xlSheet.Cell(LineNo, 22).Value = "単価";
            xlSheet.Cell(LineNo, 25).Value = "金額";

            SetPageHeaderDesign();
        }

        /// <summary>
        /// ページヘッダのスタイルを設定します。
        /// </summary>
        private void SetPageHeaderDesign()
        {
            // 伝票日付
            xlSheet.Range(LineNo, 1, LineNo, 3).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);

            // 伝票No.
            xlSheet.Range(LineNo, 4, LineNo, 6).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);

            // 品番・品名
            xlSheet.Range(LineNo, 7, LineNo, 17).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);

            // 数量
            xlSheet.Range(LineNo, 18, LineNo, 20).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);

            // 単位
            xlSheet.Cell(LineNo, 21).Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);

            // 単価
            xlSheet.Range(LineNo, 22, LineNo, 24).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);

            // 金額
            xlSheet.Range(LineNo, 25, LineNo, 28).Merge().Style
                .Font.SetFontColor(color1)
                .Fill.SetBackgroundColor(color2)
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
        }

        /// <summary>
        /// 明細1行分を出力します。
        /// </summary>
        /// <param name="row">1行データ</param>
        protected override void WriteLinePrint(DataRow row)
        {
            base.WriteLinePrint(row);

            xlSheet.Cell(LineNo, 1).Value = row["SLIP_DATE"];
            xlSheet.Cell(LineNo, 4).Value = row["SLIP_NO"];
            xlSheet.Cell(LineNo, 7).Value = row["PROD_NO"];
            xlSheet.Cell(LineNo, 18).Value = row["QT"];
            xlSheet.Cell(LineNo, 21).Value = row["UNIT"];
            xlSheet.Cell(LineNo, 22).Value = row["PRICE"];
            xlSheet.Cell(LineNo, 25).Value = row["AMT"];

            SetLinePrintDesign();
        }

        /// <summary>
        /// 明細1行のスタイルを設定します。
        /// </summary>
        private void SetLinePrintDesign()
        {
            xlSheet.Range(LineNo, 1, LineNo, 3).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
            xlSheet.Range(LineNo, 4, LineNo, 6).Merge().Style
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
            xlSheet.Range(LineNo, 7, LineNo, 17).Merge().Style
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
            xlSheet.Range(LineNo, 18, LineNo, 20).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
            xlSheet.Cell(LineNo, 21).Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Center)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
            xlSheet.Range(LineNo, 22, LineNo, 24).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
            xlSheet.Range(LineNo, 25, LineNo, 28).Merge().Style
                .Alignment.SetHorizontal(XLAlignmentHorizontalValues.Right)
                .Border.SetOutsideBorder(XLBorderStyleValues.Thin);
        }

        #region サンプルデータ作成
        private static void RegistSampleData(DataTable data, int row, int col, string value)
        {
            var r = data.NewRow();
            r["R"] = row;
            r["C"] = col;
            r["V"] = value;
            data.Rows.Add(r);
        }

        private DataTable GetSampleReportHeaderData()
        {
            var data = new DataTable();
            DataColumn[] cols = new DataColumn[]
            {
                new DataColumn("R", typeof(int)), new DataColumn("C", typeof(int)), new DataColumn("V", typeof(string))
            };
            data.Columns.AddRange(cols);

            RegistSampleData(data, 2, 26, "SK003329");                                           // 請求書No
            RegistSampleData(data, 3, 1, "〒650-0031");                                          // POST
            RegistSampleData(data, 4, 1, "兵庫県神戸市中央区東町 3-8-1 松井パークタワー1003");   // ADDRESS
            RegistSampleData(data, 5, 1, "黒渦 一朗太 様");                                      
            RegistSampleData(data, 6, 28, "アドバンスソフトウェア株式会社");
            RegistSampleData(data, 7, 22, "〒918-8239");
            RegistSampleData(data, 8, 28, "福井県福井市成和01-2816");
            RegistSampleData(data, 9, 28, "TEL:0776-21-9008/FAX:0776-21-9022");
            RegistSampleData(data, 8, 5, "U00213");
            RegistSampleData(data, 13, 1, "1,000");
            RegistSampleData(data, 13, 4, "14,800");
            RegistSampleData(data, 13, 7, "382,047");
            RegistSampleData(data, 13, 10, "2,841");
            RegistSampleData(data, 13, 17, "300,000");

            return data;
        }

        private DataTable GetSampleDetailData()
        {
            var dt = new DataTable();
            dt.Columns.Add("SLIP_DATE");
            dt.Columns.Add("SLIP_NO");
            dt.Columns.Add("PROD_NO");
            dt.Columns.Add("QT");
            dt.Columns.Add("UNIT");
            dt.Columns.Add("PRICE");
            dt.Columns.Add("AMT");

            var row = dt.NewRow();
            row["SLIP_DATE"] = "2018/05/02";
            row["SLIP_NO"] = "S010042XXX";
            row["PROD_NO"] = "PRD0012055011/テスト商品1";
            row["QT"] = "10";
            row["UNIT"] = "WTO";
            row["PRICE"] = "184";
            row["AMT"] = "88,320";
            dt.Rows.Add(row);

            row = dt.NewRow();
            row["SLIP_DATE"] = "2018/05/03";
            row["SLIP_NO"] = "S010042XYZ";
            row["PROD_NO"] = "PRD0012055011/サンプル用商品の何か";
            row["QT"] = "10";
            row["UNIT"] = "WTO";
            row["PRICE"] = "184";
            row["AMT"] = "88,320";
            dt.Rows.Add(row);

            for (int i = 0; i < 100; i++)
            {
                row = dt.NewRow();
                row["SLIP_DATE"] = "2018/05/04";
                row["SLIP_NO"] = "Z010042" + i.ToString("000");
                row["PROD_NO"] = "PRD001205TEST/商品ABCDEFGテスト";
                row["QT"] = "10";
                row["UNIT"] = "WTO";
                row["PRICE"] = "184";
                row["AMT"] = "88,320";
                dt.Rows.Add(row);
            }

            return dt;
        }
        #endregion

        #region IDisposable Support
        private bool disposedValue = false; // 重複する呼び出しを検出するには

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    if (xlBook != null) xlBook.Dispose();
                    if (xlSheet != null) xlSheet.Dispose();
                }

                disposedValue = true;
            }
        }

        ~MyReport()
        {
            // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
            Dispose(false);
        }

        // このコードは、破棄可能なパターンを正しく実装できるように追加されました。
        public void Dispose()
        {
            // このコードを変更しないでください。クリーンアップ コードを上の Dispose(bool disposing) に記述します。
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        #endregion
    }
}
using System.Data;

namespace SampleReport
{
  public class ExcelReport
  {
    /// <summary>
    /// レポートの管理クラス
    /// </summary>
    public class ReportControl
    {
      // ページの最大行数
      public int PageMaxRows { get; set; }
      
      // レポートヘッダ行数
      public int ReportHeaderRows { get; set; }
      // レポートフッタ行数
      public int ReportFooterRows { get; set; }
      
      // ページヘッダ行数
      public int PageHeaderRows { get; set; }
      // ページフッタ行数
      public int PageFooterRows { get; set; }
    }
    
    /// <summary>
    /// 行を取得する列挙体
    /// </summary
    public enum DetailsRowType
    {
      Middle = 0,
      First,
      Final
    }
    
    // 1ページの最大明細行数
    int _rowMax;
    // 現在の印刷行位置
    int _rowPoint;
    // ページ番号
    int _pageNo;
    // 行番号(最初からの位置)
    int _lineNo;
    // レポート印刷制御データ
    ReportControl _repCtrl = new ReportControl();
   	
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public ExcelReport()
    {
      _pageNo = 1;
      _lineNo = 1;
    }
    
    /// <summary>
    /// ページ番号を取得します。
    /// </summary>
    public int PageNo
    {
      get { return _pageNo; }
    }
    
    /// <summary>
    /// 先頭行からの行番号を取得します。
    /// </summary>
    public int LineNo
    {
      get { return _lineNo; }
    }
    
    /// <summary>
    /// レポートの情報等を設定または取得します。
    /// </summary>
    public ReportControl RepCtrl
    {
      get { return _repCtrl; }
      set { _repCtrl = value; }
    }
    
    /// <summary>
    /// 1ページの最大明細行数を設定します。
    /// </summary>
    /// <param name="mode">0:通常ページ, 1:開始ページ, 2:終了ページ</param>
    protected void SetDetailRows(DetailsRowType mode = DetailsRowType.Middle)
    {
      switch (mode)
      {
        case DetailsRowType.First:
          _rowMax = RepCtrl.PageMaxRows
            	  - (RepCtrl.PageHeaderRows + RepCtrl.PageFooterRows + RepCtrl.ReportHeaderRows);
          _rowPoint = 0;
          break;
        case DetailsRowType.Final:
          _rowMax = RepCtrl.PageMaxRows;
          _rowPoint = 0;
          break;
        default:
          _rowMax = RepCtrl.PageMaxRows
                  - (RepCtrl.PageHeaderRows + RepCtrl.PageFooterRows);
          _rowPoint = 0;
          break;
      }
    }
    
    /// <summary>
    /// 改ページをします。
    /// </summary>
    protected void WrPageBreak()
    {
      _pageNo += 1;
      WritePageBreak();
      SetDetailRows();
    }
    
    /// <summary>
    /// ページヘッダが必要なら出力します。
    /// </summary>
    protected void WrNeedPageHeader()
    {
      if (_rowPoint == 0)
      {
        WrPageHeader();
      }
    }
    
    /// <summary>
    /// 次行に進み、ページフッタが必要なら出力して改ページします。
    /// </summary>
    protected void WrNextLine()
    {
      _rowPoint += 1;
      _lineNo += 1;
      
      if (_rowMax <= _rowPoint)
      {
        WrPageFooter();
        WrPageBreak();
      }
    }
    
    /// <summary>
    /// レポートヘッダを出力します。
    /// </summary>
    protected void WrReportHeader()
    {
      if (RepCtrl.ReportHeaderRows <= 0)
      {
        return;
      }
      
      WriteReportHeader();
      _lineNo += RepCtrl.ReportHeaderRows;
    }
    
    /// <summary>
    /// レポートフッタを出力します。
    /// </summary>
    protected void WrReportFooter()
    {
      if (RepCtrl.ReportFooterRows <= 0)
      {
        return;
      }
      
      WriteReportFooter();
      _lineNo += RepCtrl.ReportFooterRows;
      
      int n = _rowMax - _rowPoint;
      
      if (n < RepCtrl.ReportFooterRows)
      {
        WritePageBreak();
      }
    }
    
    /// <summary>
    /// ページヘッダを出力します。
    /// </summary>
    protected void WrPageHeader()
    {
      if (RepCtrl.PageHeaderRows <= 0)
      {
        return;
      }
      
      WritePageHeader();
      _lineNo += RepCtrl.PageHeaderRows;
    }
    
    /// <summary>
    /// ページフッタを出力します。
    /// </summary>
    protected void WrPageFooter()
    {
      if (RepCtrl.PageFooterRows <= 0)
      {
         return;
      }
      
      WritePageFooter();
      _lineNo += RepCtrl.PageFooterRows;
    }
    
    /// <summary>
    /// 明細の1行を出力します。
    /// </summary>
    protected void WrLinePrint(DataRow row)
    {
      WriteLinePrint(row);
    }
    
    /// <summary>
    /// 明細内容を出力します。
    /// </summary>
    protected void WrDetail(DataTable table)
    {
      WriteDetail(table);
    }
    
    /// <summary>
    /// レポートを出力します。
    /// </summary>
    protected void WrReport(DataTable table)
    {
      WriteReport(table);
    }

	#region 継承側で出力するコードを記述する関数
    protected virtual void WritePageBreak() { }
    protected virtual void WriteReportHeader() { }
    protected virtual void WriteReportFooter() { }
    protected virtual void WritePageHeader() { }
    protected virtual void WritePageFooter() { }
    protected virtual void WriteLinePrint(DataRow row) { }
    protected virtual void WriteDetail(DataTable table)
    {
      if (table.Rows.Count == 0)
      {
        return;
      }
      
      foreach(DataRow row in table.Rows)
      {
        WrNeedPageHeader();
        WrLinePrint(row);
        WrNextLine();
      }
      
      if (0 < _rowPoint)
      {
        WrPageFooter();
      }
    }
    protected virtual void WriteReport(DataTable table)
    {
      WrReportHeader();
      WrDetail(table);
      WrReportFooter();
    }
    #endregion
  }
}

以上是关于csharp [Excel帐票] EXCELで帐票出力するときに使えるかも。#ClosedXML的主要内容,如果未能解决你的问题,请参考以下文章

csharp 的Microsoft.Office.Interop.Excelを使って的Excelを操作する。

csharp leer excel

csharp .Net Excel导出

csharp 阅读Excel文件

csharp Excel阅读器

csharp leer excel