場景
在數據庫中存儲某些個是否的字段時,有時會使用tinint進行存儲
這樣會在實體類中生成布爾類型的變量
private Boolean sfkt;
有時也會用int進行存儲是否
那么在實體類中就可能用Integer和String進行是否字段的存取
private String sfcl;
那么在使用若依自帶的導出時,如果不加修改,則會直接將對應的字段的列導出為0或者1,true或者false。
如果想要根據此列的0和1進而顯示是和否怎樣顯示。
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
如果是0和1格式化為是和否
找到對應的實體類中的屬性,在注解上添加
@Excel(name = "是否處理完成",readConverterExp = "0=否,1=是") private String sfcl;
添加讀取轉換表達式屬性readConverterExp就可以實現,具體見下面源碼分析。
如果是true和false格式化為是和否
@Excel(name = "是否跨天",readConverterExp = "false=否,true=是") private Boolean sfkt;
表達式的格式要固定如上,值可以自己根據要求去添加。
下面分析為什么這樣添加就可以。
源碼分析
在SpringbBoot后台接口中
@GetMapping("/export") public AjaxResult export(KqBcgl kqBcgl) { List<KqBcgl> list = kqBcglService.getBcListByNameToExport(kqBcgl); ExcelUtil<KqBcgl> util = new ExcelUtil<KqBcgl>(KqBcgl.class); return util.exportExcel(list, "bcgl"); }
其中list是查詢數據庫的數據。
然后調用工具類生成工具類對象,主要是調用exportExcel方法來生成Excel
在方法中
public AjaxResult exportExcel(List<T> list, String sheetName) { this.init(list, sheetName, Type.EXPORT); return exportExcel(); }
調用了init方法,生成一些工作簿以及列等相關信息的對象。
在方法createExcelField中
private void createExcelField() { this.fields = new ArrayList<Object[]>(); List<Field> tempFields = new ArrayList<>(); tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields())); tempFields.addAll(Arrays.asList(clazz.getDeclaredFields())); for (Field field : tempFields) { // 單注解 if (field.isAnnotationPresent(Excel.class)) { putToField(field, field.getAnnotation(Excel.class)); } // 多注解 if (field.isAnnotationPresent(Excels.class)) { Excels attrs = field.getAnnotation(Excels.class); Excel[] excels = attrs.value(); for (Excel excel : excels) { putToField(field, excel); } } } }
和方法createWorkbook中
public void createWorkbook() { this.wb = new SXSSFWorkbook(500); }
主要是讀取注解和調用了POI的一些方法用來初始化Excel的相關對象。
構建excel數據的方法主要是exportExcel()
public AjaxResult exportExcel() { OutputStream out = null; try { // 取出一共有多少個sheet. double sheetNo = Math.ceil(list.size() / sheetSize); for (int index = 0; index <= sheetNo; index++) { createSheet(sheetNo, index); // 產生一行 Row row = sheet.createRow(0); int column = 0; // 寫入各個字段的列頭名稱 for (Object[] os : fields) { Excel excel = (Excel) os[1]; this.createCell(excel, row, column++); } if (Type.EXPORT.equals(type)) { fillExcelData(index, row); } } String filename = encodingFilename(sheetName); out = new FileOutputStream(getAbsoluteFile(filename)); wb.write(out); return AjaxResult.success(filename); } catch (Exception e) { log.error("導出Excel異常{}", e.getMessage()); throw new CustomException("導出Excel失敗,請聯系網站管理員!"); } finally { if (wb != null) { try { wb.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e1) { e1.printStackTrace(); } } } }
這其中使用填充excel的方法fillExcelData
public void fillExcelData(int index, Row row) { int startNo = index * sheetSize; int endNo = Math.min(startNo + sheetSize, list.size()); for (int i = startNo; i < endNo; i++) { row = sheet.createRow(i + 1 - startNo); // 得到導出對象. T vo = (T) list.get(i); int column = 0; for (Object[] os : fields) { Field field = (Field) os[0]; Excel excel = (Excel) os[1]; // 設置實體類私有屬性可訪問 field.setAccessible(true); this.addCell(excel, row, vo, field, column++); } } }
上面的fields是讀取的注解列表,
/** * 注解列表 */ private List<Object[]> fields;
遍歷每個注解對象后調用addCell方法
public Cell addCell(Excel attr, Row row, T vo, Field field, int column) { Cell cell = null; try { // 設置行高 row.setHeight((short) (attr.height() * 20)); // 根據Excel中設置情況決定是否導出,有些情況需要保持為空,希望用戶填寫這一列. if (attr.isExport()) { // 創建cell cell = row.createCell(column); cell.setCellStyle(styles.get("data")); // 用於讀取對象中的屬性 Object value = getTargetValue(vo, field, attr); String dateFormat = attr.dateFormat(); String readConverterExp = attr.readConverterExp(); if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value)) { cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) value)); } else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) { cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp)); } else { // 設置列類型 setCellVo(value, attr, cell); } } } catch (Exception e) { log.error("導出Excel失敗{}", e); } return cell; }
在這里是執行填充單元格的方法,其中
String readConverterExp = attr.readConverterExp();
就是獲取上面設置的注解readConverterExp屬性
else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value)) { cell.setCellValue(convertByExp(String.valueOf(value), readConverterExp)); }
判斷如果不為空的話將單元格的值和傳遞的表達式傳遞給方法convertByExp
/** * 解析導出值 0=男,1=女,2=未知 * * @param propertyValue 參數值 * @param converterExp 翻譯注解 * @return 解析后值 * @throws Exception */ public static String convertByExp(String propertyValue, String converterExp) throws Exception { try { String[] convertSource = converterExp.split(","); for (String item : convertSource) { String[] itemArray = item.split("="); if (itemArray[0].equals(propertyValue)) { return itemArray[1]; } } } catch (Exception e) { throw e; } return propertyValue; }
首先將表達式按照逗號分隔,獲取分隔后的數組,然后遍歷數組。
再根據=分隔,如果等號左邊即分割后數組的第一個值與單元格的值相等,就返回等號右邊的值即分隔后的第二個值。
這樣就實現了按照指定表達式將單元格的值進行格式化顯示。