程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 一個Excel導出類的實現過程(四):格式化與若干坑 已補圖和代碼zip

一個Excel導出類的實現過程(四):格式化與若干坑 已補圖和代碼zip

編輯:C#入門知識

這是本文的第四部分也是最後部分,適合新人初步學習泛型、反射,提供了有限的業務場景分析、若干的NPOI接口使用示范,前三部分鏈接如下:

  • 一個Excel導出類的實現過程(一):泛型與反射
  • 一個Excel導出類的實現過程(二):顯示定制
  • 一個Excel導出類的實現過程(三):NPOI組件

接第三部分,由於單元格設置語句僅簡單的一句話row.CreateCell(i).SetCellValue(value.ToString()),生成的Excel仍然粗陋。

Excel導出通常會遇到若干問題:

  • 整數變字符串問題:整型值比如ID列,單元格左上角出現綠色三角符號,單元格變成了字符串類型,不夠友好;
  • 日期顯示問題:有時候需要顯示到日期如“2013-5-17”而不要帶上“16:50:13”,有時候只希望顯示“16:50”,而不是告訴使用人自己拿生成的工作薄設置格式;
  • 科學計數法問題:手機號13912345678只是列寬過短時看起來像科學計數法,但超過15位的整數像1234567890123456就真變成1.23457E+15而且最後一位6變成了零。

ICell的實現者HSSFCell有數量不少的屬性和方法幫助我們完成單元格格式設置,考慮到應用場景,創建指定類型的單元格並配合格式化選項已經能滿足要求,下文使用若干強制轉型和控制語句完成功能。

首先擴充Header類,添加一個Format參數。當使用者傳入空Format參數時由我們推斷單元格類型與值,而當使用者傳入非空的Format參數時,我們調用ToString(String format)方法進行格式化。

  String Name { ;  String PrintName { ;  String Format { ; (name, printName, ===

我們把權力交給調用者時,便認為他的參數傳遞是經過判斷且有道理的,比如純數字的條形碼顯示可能需要調用Decimal.ToString("F0")方法,,但使用者對薪水調用ToString("P2")顯示百分號就沒辦法了;另一部分是設計之初的問題,如雙精度Double型精確度,後面再說。

由於ICell.CreateCell(int column, CellType type)創建的單元格類型最終由ICell.SetCellValue()重載版本中參數類型(可以是Boolean、DateTime、Double、String及IRichTextString)決定,所以統一只使用了ICell.CreateCell(int column),必須注意的是用於存放數值的單元格類型枚舉只有CellType.NUMERIC,下文還要講到。新的Export改動點如剛才描述,舊的Person類及Export重載請見前文,實現如下:

 IWorkbook Export<T>(IList<T> records, IList<Header> (records ==   ArgumentNullException( (headers ==   ArgumentNullException(); 
=  (Int32 i = ; i < headers.Count; i++= (T).GetProperty(headers[i].Name); 
= = =  (Int32 r = ; r < records.Count; r++ ((r % RowPerSheet) == = (Int32)((Double)r / RowPerSheet) + = workbook.CreateSheet( + sheetIndex); 
            row = sheet.CreateRow(); 
             (Int32 i = ; i < headers.Count; i++= sheet.CreateRow((r % RowPerSheet) + ); 
         (Int32 i = ; i < props.Length; i++ (props[i] != ) 
= props[i].GetValue(records[r],  (value != ) 
= (props[i].PropertyType ==   (props[i].PropertyType ==   (props[i].PropertyType ==   (props[i].PropertyType == 
     (Int32 i = ; i < workbook.NumberOfSheets; i++= (Int32 h = ; h < headers.Count; h++

生日類數據顯示到年月日即可,我們使用"yyyy-MM-dd"作為格式化參數,薪水未提供格式化參數,客戶端調用代碼如下:

  Main(= <Person> persons =  List<Person> (Int32 i = ; i < records; i++= = i + =  + (i + =  Math.Abs(Guid.NewGuid().GetHashCode() % ) + =<ExcelHelper.Header> headers =  List<ExcelHelper.Header> ExcelHelper.Header( ExcelHelper.Header(,  ExcelHelper.Header(, ,  ExcelHelper.Header(, = = = = excelHelper.Export<Person> (FileStream stream =


之前提到過雙精度的問題,對某個員工的薪酬設置為1234567890123456並輸出Excel會怎麼樣,先做個測試:

Person person = new Person();
person.Salary = 1234567890123456;
Console.WriteLine(person.Salary);

輸出結果是1.23456789012346E+15也就是說Excel上不僅顯示的是科學計數法,而且數值已經變成悲了個劇的1234567890123460。粗暴地講,這是因為雙精度的Double型的有效位數造成的,並不是ToString方法或者Excel寫入時產生了變化。

要處理類似問題,僅將Person.Salary聲明為Decimal類型還不夠,因為單元格類型CellType枚舉中用來存數字的只有CellType.NUMERIC,沒辦法我們需要配合ToString("F0")(或者F2等視具體要求)把值當作字符串寫入單元格,改動部分的部分代碼如下:

 Decimal Salary { ; = ExcelHelper.Header(, , 

於是能看到Excel上顯示的1234567890123456,雖然有綠色小三角,好歹沒變成科學計數法和四捨五入。如要求更完備請自行參考NPOI相關API,代碼文件已提供,本文完。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved