java匯出xlsx格式的excel
阿新 • • 發佈:2021-09-28
優化了下以前寫的工具類。
優點:
- 標題支援從實體類中直接取值
- 資料列表支援List自定義類與List String
- 工具類採用可變引數,不會過多限制資料數量與資料格式
程式碼:
工具類:
import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.hssf.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.springframework.core.annotation.AnnotationUtils; import java.lang.reflect.Field; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; @Slf4j public class MyExcelUtil { /** * 生成xlsx格式的Excel表格 * * @param sheetName sheet名稱 * @param titleList 標題列表 * @param data 資料列表,支援List<自定義類>與List<String> * @return XSSFWorkbook */ public static XSSFWorkbook getXSSFWorkbook(String sheetName, List<String> titleList, List<?>... data) throws IllegalAccessException { //建立HSSFWorkbook物件 XSSFWorkbook wb = new XSSFWorkbook(); //建立sheet物件 XSSFSheet sheet = wb.createSheet(sheetName); //在sheet裡建立第一行,這裡即是表頭 XSSFRow rowTitle = sheet.createRow(0); //寫入表頭的每一個列 for (int i = 0; i < titleList.size(); i++) { //建立單元格 rowTitle.createCell(i).setCellValue(titleList.get(i)); } //寫入每一行的記錄 int col = 1; for (List<?> dataList : data) { if (CollectionUtils.isEmpty(dataList)){ continue; }else if (dataList.get(0) instanceof String) { List<?> list = MyExcelUtil.castList(dataList, String.class); //建立新的一行,遞增 XSSFRow rowData = sheet.createRow(col++); for (int j = 0, le = list.size(); j < le; j++) { //建立單元格 Object obj = list.get(j); if (obj == null) continue; if (obj instanceof Date) { rowData.createCell(j).setCellValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(obj)); } else { rowData.createCell(j).setCellValue(String.valueOf(obj)); } } } else { for (Object o : dataList) { //建立新的一行,遞增 XSSFRow rowData = sheet.createRow(col++); { Class<?> cl = o.getClass(); Field[] fields = cl.getDeclaredFields(); for (int j = 0, le = fields.length; j < le; j++) { //設定欄位可見,否則會報錯,禁止訪問 fields[j].setAccessible(true); //建立單元格 Object obj = fields[j].get(o); if (obj == null) continue; if (obj instanceof Date) { rowData.createCell(j).setCellValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(obj)); } else { rowData.createCell(j).setCellValue(String.valueOf(obj)); } } } } } } return wb; } /** * 用反射獲取Desc註釋值,來生成標題列表titleList * * @param titleClass * @param <T> * @return */ public static <T> List<String> getTitleListByClass(Class<T> titleClass) { List<String> titleList = new ArrayList<>(); Field[] titleFields = titleClass.getDeclaredFields(); for (Field field : titleFields) { Desc desc = AnnotationUtils.findAnnotation(field, Desc.class); if (desc != null) { titleList.add(desc.value()); } } return titleList; } /** * 將List格式的object轉換為List * * @param obj * @param clazz * @param <T> * @return */ public static <T> List<T> castList(Object obj, Class<T> clazz) { List<T> result = new ArrayList<T>(); if (obj instanceof List<?>) { for (Object o : (List<?>) obj) { result.add(clazz.cast(o)); } return result; } return null; } }
註釋類:
@Retention(RetentionPolicy.RUNTIME)
public @interface Desc {
String value();
}
自義定實體類例子:
@Data
public class ExportResp {
@Desc("編號")
private Integer id;
@Desc("標題")
private String title;
@Desc("狀態")
private String status;
}
介面例子:
@RestController @RequestMapping public class TestController { @GetMapping("/getExcel") public void getExcel(HttpServletResponse response){ ServletOutputStream out = null; try { // 隨便創幾個資料 List<String> contents = new ArrayList<>(); for (int i = 0; i < 10; i++){ contents.add("test"); } ExportResp resp = new ExportResp(); resp.setId(1); resp.setTitle("標題"); resp.setStatus("熱門"); List<ExportResp> respList = new ArrayList<>(); respList.add(resp); respList.add(resp); String fileName = URLEncoder.encode("預設標題.xlsx", "UTF-8"); out = response.getOutputStream(); response.reset(); response.setContentType("application/vnd.ms-excel;charset=utf-8"); // filename*=utf-8''支援中文標題 response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ";" + "filename*=utf-8''" + fileName); MyExcelUtil.getXSSFWorkbook("bug記錄", MyExcelUtil.getTitleListByClass(BugExportResp.class), contents, respList).write(out); } catch (Exception e) { System.out.println(e); } finally { if (out != null) { try { out.close(); } catch (IOException e1) { System.out.println("關閉流報錯:"+ e1); } } } } }
呼叫介面:
http://localhost:8080/excel/getExcel