最近做项目需要导入一部分数据, 导入的数据的中, 有部分的百分比数据使用的是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的线索, 绝对事半功倍.