新的一年,又一个开始,不见收获,却见年龄,好一个猪年,待我先来一首里尔克的诗:html
《沉重的时刻》(里尔克)java
此刻有谁在世上某处哭,平白无故在世上哭,在哭我。 此刻有谁在夜间某处笑,平白无故在夜间笑,在笑我。 此刻有谁在世上某处走,平白无故在世上走,走向我。 此刻有谁在世上某处死,平白无故在世上死,望着我。
不考虑以上所说的问题,我的花了些许时间写了两个Excel 工具类:ExcelReadUtil以及ExcelWriteUtil (代码地址见篇尾),集中处理了包含单不只限于如下问题:git
toXlsxByMap(List<Map<String,Object>> dataList, String[] headerNames, String[] cellNames, CellFmt[] cellFmts)
致使的问题是传入的dataList内部的Map的value必须是Object类型,以后钻研了下java泛型,使用这种方式轻松解决问题!github
public static <V extends Object> File toXlsxByMap(List<Map<String,V>> dataList, String[] headerNames, String[] cellNames, CellFmt[] cellFmts)
//数据分组 List<List<Map<String, V>>> mData = splitMapList(dataList); //循环每组数据 并建立sheet>写单元格 for (List<Map<String, V>> subList : mData) { //第一个sheet 参数(sheet名称,sheet的序号) sheet = workbook.createSheet(String.format("%s~%s", (dataList.size() > DATA_SPLIT_GROP_SIZE ? mData.indexOf(subList) * DATA_SPLIT_GROP_SIZE + 1 : 0) + "", (dataList.size() > DATA_SPLIT_GROP_SIZE ? (mData.size() == (mData.indexOf(subList) + 1) ? dataList.size() : DATA_SPLIT_GROP_SIZE * (mData.indexOf(subList) + 1)) : dataList.size()) + "") ); LOGGER.info(">>>sheet name : {}",sheet.getSheetName()); PoiCellProcess.writeHeaderCell(sheet,headerCellStyle,headerNames); PoiCellProcess.writeBodyCellByMap(sheet,bodyCellStyle,cellNames,subList, cellFmts); }
public static CellStyle headerCellStyle(SXSSFWorkbook wb){ CellStyle headerStyle = wb.createCellStyle(); //...some code //容许单元格内换行 headerStyle.setWrapText(true); return headerStyle; }
单元格类型及格式处理问题数据库
这个问题其实分为多个,并且密切相关,大体有这几个:
- 单元格样式类
- 单元格样式类
- 单元格数据类型
- 单元格写入数据格式apache
可是,处理了这几个问题其实还不够完美
至于不完美的缘由是什么呢,一个是Excel数据格式与java数据格式不一致(这个体如今日期,长数字,小数的处理上),好比你要格式化的日期后为“yyyy-mm-dd” 这种类型,
可是在Excel中相近的格式类型只有这样“yyyy/M/d”,若是强制单元格样式类型为“yyyy-mm-dd HH24:mi:ss” 其实也是能够的,只不过会变成自定义格式,并且是Excel的自定义格式,
具体以下图:编程
另一个问题是单元格类型与编程语言的数据类型相异同时与poi所能提供的数据类型也相异,如图:api
public static void writeHeaderCell(SXSSFSheet sheet, CellStyle headerCellStyle, String[] headerNames) { SXSSFRow row = sheet.createRow(0); row.setHeight((short) 30); row.setHeightInPoints((short) 30); SXSSFCell headerCell; for (int i = 0; i < headerNames.length; i++) { headerCell = row.createCell(i); headerCell.setCellStyle(headerCellStyle); headerCell.setCellValue(headerNames[i]); sheet.setColumnWidth(i, null == headerNames[i] ? CELL_BASE_LENGTH : (headerNames[i].contains("\r\n") ? CELL_CHARSET_LENGTH * headerNames[i].length() / 2 : CELL_CHARSET_LENGTH * headerNames[i].length())); } }这是最终处理的结果:
public static Object[] fieldValues(final Object obj, final String[] fieldNames,Object[] valueList) { for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) { try { Field[] fields = superClass.getDeclaredFields(); for(int k=0;k<fields.length;k++){ if ((!Modifier.isPublic(fields[k].getModifiers()) || !Modifier.isPublic(fields[k].getDeclaringClass().getModifiers()) || Modifier.isFinal(fields[k].getModifiers())) && !fields[k].isAccessible()) { fields[k].setAccessible(true); } /** * 须要排序,不然顺序不一致 */ for(int j=0;j<fieldNames.length;j++){ if(fields[k].getName().equals(fieldNames[j])){ valueList[j] = fields[k].get(obj); break; } } } return valueList; } catch (Exception e) { e.printStackTrace(); } } //这里新增一个,不然数组越界 return new Object[fieldNames.length]; }
先展现导出的效果:
因为导入并无作严格要求,因此将读取的数据所有放入这种对象里面 "List<Map<String,String>>",详细请看代码,这里就不作详细介绍了数组
以上写的过于粗糙,各位有更好的想法请分享下哈~多线程
如今是 2019-02-18 星期一,各位中午好~