新的一年,又一個開始,不見收穫,卻見年齡,好一個豬年,待我先來一首里爾克的詩: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 星期一,各位中午好~