最近做項目需要導入一部分數據, 導入的數據的中, 有部分的百分比數據使用的是excel 的百分比, 有部分的數據使用的是字符串形式的格式,(數據來源於不同的人統計), 格式略微有點亂, 要求導入系統的時候, 將所有百分比的數據轉換成百分制的數據存儲起來.
因為之前項目使用的讀取excel 的組件式NPOI , 所以我也就直接使用npoi來讀, 我用的NPOI是2.0的版本的, 不算太新.
常規讀取的時候, 是按照下面的方式讀取到ICell的
IWorkbook workbook = null; var workbook = NPOI.SS.UserModel.WorkbookFactory.Create(fileStream); ISheet sheet = workbook .GetSheetAt(0); IRow firstRow = sheet.GetRow(1); ICell cell = firstRow.GetCell(0);
這樣獲取到ICell對象以后, 可以通過ICell.CellType 判斷到單元格的數據類型, 從 ICell.CellStyle.DataFormat可以去到單元格的格式, 但是問題來了: CellStyle.DataFormat只能獲取到一個格式的數字編碼(例如186), 不能獲取到具體的格式是什么(例如0.00%).
那么需要有地方完成從格式數字編碼到具體的格式之間的轉換, 我從網上找了好久, 沒有找到具體的方法, 后來想了想excel是xml格式的, 要不還是先從excel下手.
ok, 先把excel后綴改為.rar, 然后解壓, 解壓后找到\xl\styles.xml, 這個就是excel的樣式文件, 打開看看, 發現數據格式就在最開始的地方, 是個一個<numFmt numFmtId="178" formatCode="0.000%"/>的數值, 蠻清楚, 不過總不能自己去硬解碼樣式吧, 這樣也太土了點, 想想先按下不表, 還是從NPOI 下手.
后來咨詢了下同事, 同事也沒有干過這種事情, 不過給了點先線索, 他用過一個檢查單元格是否是時間格式的方法, 在NPOI的UserModel命名空間下, 不過他用的那個方法是用來檢查excel 的內置格式的, 不包含自定義格式. 我一想也許獲取樣式的代碼在其他命名空間下, 好吧, 開始翻dll吧(苦逼, 沒有找到api, 直接用vs看dll 的命名空間下有哪些類)
好在NPOI不是很大, 翻到第二個dll就找打了線索, NPOI.OOXML.dll下有個類 NPOI.XSSF.UserModel.XSSFDataFormat, 這個類有個方法NPOI.XSSF.UserModel.XSSFDataFormat.GetFormat(short) 看起來像是獲取格式的, 但是XSSFDataFormat這個類的構造函數是這樣的:XSSFDataFormat(NPOI.XSSF.Model.StylesTable), 要求傳入一個StylesTable對象, 找打這個StylesTable的類定義, 發現這個類的構造函數沒有參數, 也沒有create方法, 好像不對.
這個時候, 同事出了個主意: 這個NPOI是開源了, 把源代碼下下來, 看看有沒有StylesTable的實例, 想了下, 好主意. 幾分鍾, 代碼就下下來了, 整個項目搜索StylesTable , 馬上就發現了一行代碼
StylesTable st = ((XSSFWorkbook)workbook).GetStylesSource();
哈哈, 原來是在IWookbook的實現類了, 難怪在接口上找不到.
把上面的代碼給成這樣:
IWorkbook workbook = null; StylesTable st = ((XSSFWorkbook)workbook ).GetStylesSource(); XSSFDataFormat df = new XSSFDataFormat(st); var workbook = NPOI.SS.UserModel.WorkbookFactory.Create(fileStream); ISheet sheet = workbook .GetSheetAt(0); IRow firstRow = sheet.GetRow(1); ICell cell = firstRow.GetCell(0);
string formatCode = df.GetFormat(cell.CellStyle.DataFormat); if (formatCode.EndsWith("%")) { }
這樣獲取到的formatcode就是"0.000%" 格式的, 瞬間爽了.
最后發現: 開源的東西, 最好的辦法是去源代碼里面找你要的東西, 加上google的線索, 絕對事半功倍.
后來經 烽火情懷 提醒, 有簡單方法: ICell.CellStyle.GetDataFormatString()就能獲取到格式字符串.