[.NET][C#]NPOI產生Excel報表(一)列印表頭資訊(xlsx)

同事剛加入急急如律令的專案幫忙開發報表,使用者有一項需求是列印報表時,表頭要出現頁數、標題、欄位名稱等,專案中使用的是NPOI,之前自己參加專案時都是同事寫好了元件,對NPOI操作不太熟悉,這次捲起袖子來試試。

同事的任務會讀取報表範本,然後把Row Data塞到Excel上(xlsx)。待會我們依序安裝NPOI、撰寫測試程式、製作報表範本,最後依序執行對照組及實驗組的測試。

 


What's NPOI

NPOI是Java POI的.NET版本,作者是對岸上海的Tony,使用的版權是Apache License 2.0 (Apache),可以商業使用。

This project is the .NET version of POI Java project at http://poi.apache.org/. POI is an open source project which can help you read/write xls, doc, ppt files. It has a wide application.

 


NPOI安裝

先新增一個測試專案,接著到Nuget套件管理員安裝NPOI。

配合專案,我們選2.1.3.1版本

 


撰寫測試程式

新增Poker.cs類別,待會測試丟這個Entity產表。

public class Poker
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Title { get; set; }
    public string Color { get; set; }
    public Decimal Balance { get; set; }
}

 

打開UnitTest1.cs程式

簡單寫一段使用NPOI產生報表的方法,因為要接不同的Entity,用一點反射來處理。另外因為報表中數值,方法只先處理金額和字串。

public void Generate<T>(string TemplatePath, string ReportPath, List<T> entities, int Offset, int PageSize)
{
    using (FileStream fileStream = new FileStream(TemplatePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        IWorkbook workbook = WorkbookFactory.Create(fileStream);
        ISheet sheet = workbook.GetSheetAt(0);
        List<ICell> TemplateCells = new List<ICell>();
        for (int i = 0; i < sheet.GetRow(Offset).Cells.Count; i++)
        {
            TemplateCells.Add(sheet.GetRow(Offset).GetCell(i));
        }

        PropertyInfo[] properties = typeof(T).GetProperties();
        foreach (var entity in entities)
        {
            sheet.CreateRow(Offset);
            int CellInRow = 0;
            foreach (var property in properties)
            {
                ICell cell = sheet.GetRow(Offset).CreateCell(CellInRow);
                cell.CellStyle = TemplateCells[CellInRow].CellStyle;
                cell.SetCellType(TemplateCells[CellInRow].CellType);
                if (TemplateCells[CellInRow].CellType.Equals(CellType.Numeric))
                {
                    cell.SetCellValue(Convert.ToDouble(property.GetValue(entity, null)));
                }
                else
                {
                    cell.SetCellValue(Convert.ToString(property.GetValue(entity, null)));
                }
                CellInRow++;
            }
            Offset++;
        }
        using (FileStream fileOut = new FileStream(ReportPath, FileMode.Create))
        {
            workbook.Write(fileOut);
        }
    }
}

 

繼續在測試類別UnitTest1.cs加入以下測試程式碼

[TestMethod]
public void TestGererate()
{
    //(1)製造測試資料
    List<Poker> Pokers = new List<Poker>();
    for (int i = 0; i < 10; i++)
    {
        Pokers.Add(new Poker { Id = 1, Name = "David", Title = "King", Color = "Spades", Balance = 1000 });
        Pokers.Add(new Poker { Id = 2, Name = "Charlemagne", Title = "King", Color = "Hearts", Balance = 2000 });
        Pokers.Add(new Poker { Id = 3, Name = "Caesar", Title = "King", Color = "Diamonds", Balance = 3000 });
        Pokers.Add(new Poker { Id = 4, Name = "Alexander", Title = "King", Color = "Clubs", Balance = 4000 });
        Pokers.Add(new Poker { Id = 5, Name = "Athena", Title = "Queen", Color = "Spades", Balance = 5000 });
        Pokers.Add(new Poker { Id = 6, Name = "Judith", Title = "Queen", Color = "Hearts", Balance = 6000 });
        Pokers.Add(new Poker { Id = 7, Name = "Rachel", Title = "Queen", Color = "Diamonds", Balance = 7000 });
        Pokers.Add(new Poker { Id = 8, Name = "Argine", Title = "Queen", Color = "Clubs", Balance = 8000 });
    }

    //(2)產生報表
    string TemplatePath = @"D:\AP\Report\template\pokers.xlsx";
    string ReportPath = @"D:\AP\Report\pokers.xlsx";
    Generate(TemplatePath, ReportPath, Pokers, 1, 25);

    Assert.AreEqual(true, File.Exists(ReportPath));
}

 


建立Excel範本

打開Excel,新增5個欄位,然後第二行放明細資料,最後儲存成Pokers.xlsx作為報表範本。

 


對照組測試

在測試總管執行選取的測試,或直接在測試方法TestGenerate按CTRL + R + T

測試成功!

報表檔案產生!

Excel預覽列印(CTRL + P)

出現幾個呈現面的問題: 表頭沒有頁數、沒有報表名稱、產表時間,第二頁缺欄位名稱等。

 


實驗組

簡單用Excel的版面配置設定來解題。

打開剛剛製作好的Excel範本檔案,版面配置 > 列印標題 > 頁尾頁首 > 自訂頁首

利用左中右上方的小icon插入日期、時間、頁碼及總頁數,並在畫面中央有自信的輸入

IT’S NOT A BUG,IT’S A FEATURE

版面設定的工作表處,設定標題列為第一行

 

Excel預覽列印(CTRL + P),重新產表後,該有的表頭、頁數、總頁數及重複的欄位名稱都給他補上了。

同事後來增加了固定每頁列印筆數、分組小計及總計的需求,今晚先掛帳,有空繼續筆記。

今天的口號是 IT'S NOT A BUG,IT'S A FEATURE! 

 

2011.9 義大利羅馬 圓形競技場,建於公元72年至82 年

 


參考

https://npoi.codeplex.com/