背景:
有一個很重要的功能需要記錄日誌,在排查問題時需要將日誌內容導出Excel,並且針對不同的賬號對個別導出字段進行隱藏
準備工作:
引包
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.0</version>
</dependency>
EasyPoiUtils.java
@Component
public class EasyPoiUtils {
private final static Logger logger = LoggerFactory.getLogger(EasyPoiUtils.class);
/**
* 功能描述:複雜導出Excel,包括文件名以及表名。創建表頭
*
* @param list 導出的實體類
* @param title 表頭名稱
* @param sheetName sheet表名
* @param pojoClass 映射的實體類
* @param isCreateHeader 是否創建表頭
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
exportParams.setStyle(EasyPoiExcelStyleUtil.class);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, boolean isCreateHeader) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setCreateHeadRows(isCreateHeader);
exportParams.setStyle(EasyPoiExcelStyleUtil.class);
defaultExport(list, pojoClass, fileName, exportParams);
}
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
downLoadExcel(fileName, workbook);
}
}
/**
* 功能描述:Excel導出
*
* @param fileName 文件名稱
* @param workbook Excel對象
* @return
*/
public static void downLoadExcel(String fileName, Workbook workbook) {
try {
FileOutputStream fos = new FileOutputStream(fileName);
workbook.write(fos);
} catch (IOException e) {
System.out.println("文件打開異常,請確認是否已打開");
}
}
/**
* 功能描述:複雜導出Excel,包括文件名以及表名,不創建表頭
*
* @param list 導出的實體類
* @param title 表頭名稱
* @param sheetName sheet表名
* @param pojoClass 映射的實體類
* @param fileName
* @param response
* @return
*/
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) {
ExportParams exportParams = new ExportParams(title, sheetName);
exportParams.setStyle(EasyPoiExcelStyleUtil.class);
defaultExport(list, pojoClass, fileName, response, exportParams);
}
/**
* 功能描述:Map 集合導出
*
* @param list 實體集合
* @param fileName 導出的文件名稱
* @param response
* @return
*/
public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
defaultExport(list, fileName, response);
}
/**
* 功能描述:默認導出方法
*
* @param list 導出的實體集合
* @param fileName 導出的文件名
* @param pojoClass pojo實體
* @param exportParams ExportParams封裝實體
* @param response
* @return
*/
private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
downLoadExcel(fileName, response, workbook);
}
}
/**
* 功能描述:Excel導出
*
* @param fileName 文件名稱
* @param response
* @param workbook Excel對象
* @return
*/
public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
try {
response.setCharacterEncoding("UTF-8");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(response.getOutputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 功能描述:默認導出方法
*
* @param list 導出的實體集合
* @param fileName 導出的文件名
* @param response
* @return
*/
private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF);
if (workbook != null) {
downLoadExcel(fileName, response, workbook);
}
}
/**
* 功能描述:根據文件路徑來導入Excel
*
* @param filePath 文件路徑
* @param titleRows 表標題的行數--對應數據對象
* @param headerRows 表頭行數
* @param pojoClass Excel實體類
* @return
*/
public static <T> List<T> importExcel(String filePath, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
//判斷文件是否存在
if (StringUtils.isBlank(filePath)) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("模板不能爲空");
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 功能描述:根據接收的Excel文件來導入Excel,並封裝成實體類
*
* @param file 上傳的文件
* @param titleRows 表標題的行數
* @param headerRows 表頭行數
* @param pojoClass Excel實體類
* @return
*/
public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass) {
if (file == null) {
return null;
}
ImportParams params = new ImportParams();
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("excel文件不能爲空");
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
return list;
}
/**
* 功能描述:根據接收的Excel文件來導入多個sheet,根據索引可返回一個集合
* @param filePath 導入文件路徑
* @param sheetIndex 導入sheet索引
* @param titleRows 表標題的行數
* @param headerRows 表頭行數
* @param pojoClass Excel實體類
* @return
*/
public static <T> List<T> importExcel(String filePath,int sheetIndex,Integer titleRows, Integer headerRows, Class<T> pojoClass) {
// 根據file得到Workbook,主要是要根據這個對象獲取,傳過來的excel有幾個sheet頁
ImportParams params = new ImportParams();
// 第幾個sheet頁
params.setStartSheetIndex(sheetIndex);
params.setTitleRows(titleRows);
params.setHeadRows(headerRows);
List<T> list = null;
try {
list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params);
} catch (NoSuchElementException e) {
throw new RuntimeException("模板不能爲空");
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 功能描述:根據接收的Excel文件來導入多個sheet,根據索引可返回一個集合
* @param list 實體對象集合
* @param type 表格類型
* @return
*/
public static Workbook exportExcel(List<Map<String, Object>> list, ExcelType type) {
Workbook workbook = getWorkbook(type, 0);
Iterator var3 = list.iterator();
while(var3.hasNext()) {
Map<String, Object> map = (Map)var3.next();
ExcelExportService service = new ExcelExportService();
service.createSheet(workbook, (ExportParams)map.get("title"), (Class)map.get("entity"), (Collection)map.get("data"));
}
return workbook;
}
private static Workbook getWorkbook(ExcelType type, int size) {
if (ExcelType.HSSF.equals(type)) {
return new HSSFWorkbook();
} else {
return (Workbook)(size < USE_SXSSF_LIMIT ? new XSSFWorkbook() : new SXSSFWorkbook());
}
}
}
EasyPoiExcelStyleUtil .java
public class EasyPoiExcelStyleUtil implements IExcelExportStyler {
private static final short STRING_FORMAT = (short) BuiltinFormats.getBuiltinFormat("TEXT");
private static final short FONT_SIZE_TEN = 10;
private static final short FONT_SIZE_ELEVEN = 11;
private static final short FONT_SIZE_TWELVE = 12;
/**
* 大標題樣式
*/
private CellStyle headerStyle;
/**
* 每列標題樣式
*/
private CellStyle titleStyle;
/**
* 數據行樣式
*/
private CellStyle styles;
public EasyPoiExcelStyleUtil(Workbook workbook) {
this.init(workbook);
}
/**
* 初始化樣式
*
* @param workbook
*/
private void init(Workbook workbook) {
this.headerStyle = initHeaderStyle(workbook);
this.titleStyle = initTitleStyle(workbook);
this.styles = initStyles(workbook);
}
/**
* 大標題樣式
*
* @param color
* @return
*/
@Override
public CellStyle getHeaderStyle(short color) {
return headerStyle;
}
/**
* 每列標題樣式
*
* @param color
* @return
*/
@Override
public CellStyle getTitleStyle(short color) {
return titleStyle;
}
/**
* 數據行樣式
*
* @param parity 可以用來表示奇偶行
* @param entity 數據內容
* @return 樣式
*/
@Override
public CellStyle getStyles(boolean parity, ExcelExportEntity entity) {
return styles;
}
/**
* 獲取樣式方法
*
* @param dataRow 數據行
* @param obj 對象
* @param data 數據
*/
@Override
public CellStyle getStyles(Cell cell, int dataRow, ExcelExportEntity entity, Object obj, Object data) {
return getStyles(true, entity);
}
/**
* 模板使用的樣式設置
*/
@Override
public CellStyle getTemplateStyles(boolean isSingle, ExcelForEachParams excelForEachParams) {
return null;
}
/**
* 初始化--大標題樣式
*
* @param workbook
* @return
*/
private CellStyle initHeaderStyle(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook);
style.setFont(getFont(workbook, FONT_SIZE_TWELVE, true));
return style;
}
/**
* 初始化--每列標題樣式
*
* @param workbook
* @return
*/
private CellStyle initTitleStyle(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook);
style.setFont(getFont(workbook, FONT_SIZE_ELEVEN, false));
//背景色
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
return style;
}
/**
* 初始化--數據行樣式
*
* @param workbook
* @return
*/
private CellStyle initStyles(Workbook workbook) {
CellStyle style = getBaseCellStyle(workbook);
style.setFont(getFont(workbook, FONT_SIZE_TEN, false));
style.setDataFormat(STRING_FORMAT);
return style;
}
/**
* 基礎樣式
*
* @return
*/
private CellStyle getBaseCellStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
//下邊框
style.setBorderBottom(BorderStyle.THIN);
//左邊框
style.setBorderLeft(BorderStyle.THIN);
//上邊框
style.setBorderTop(BorderStyle.THIN);
//右邊框
style.setBorderRight(BorderStyle.THIN);
//水平居中
style.setAlignment(HorizontalAlignment.CENTER);
//上下居中
style.setVerticalAlignment(VerticalAlignment.CENTER);
//設置自動換行
style.setWrapText(true);
return style;
}
/**
* 字體樣式
*
* @param size 字體大小
* @param isBold 是否加粗
* @return
*/
private Font getFont(Workbook workbook, short size, boolean isBold) {
Font font = workbook.createFont();
//字體樣式
font.setFontName("宋體");
//是否加粗
font.setBold(isBold);
//字體大小
font.setFontHeightInPoints(size);
return font;
}
}
隱藏字段代碼 HiddenColumnUtil.java
public class HiddenColumnUtil<T> {
/**
* 需要被反射的對象,使用泛型規範傳入對象
*/
public T t;
/**
* 動態更改EasyPoi中控制列顯示的值
*
* @param columnName 需要轉換的列屬性名稱
* @param target 默認true
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public void hihdColumn(String columnName, Boolean target) throws Exception {
if (t == null) {
throw new ClassNotFoundException("TARGET OBJECT NOT FOUNT");
}
if (StringUtils.isEmpty(columnName)) {
throw new NullPointerException("COLUMN NAME NOT NULL");
}
if (target == null) {
target = true;
}
//獲取目標對象的屬性值
Field field = t.getClass().getDeclaredField(columnName);
//獲取註解反射對象
Excel excelAnnon = field.getAnnotation(Excel.class);
//獲取代理
InvocationHandler invocationHandler = Proxy.getInvocationHandler(excelAnnon);
Field excelField = invocationHandler.getClass().getDeclaredField("memberValues");
excelField.setAccessible(true);
Map memberValues = (Map) excelField.get(invocationHandler);
memberValues.put("isColumnHidden", target);
}
實體類
@Data
public class TestLogDTO {
@Excel(name = "test1",orderNum = "1",width = 20,isColumnHidden = false)
private String test1;
@Excel(name = "test2",orderNum = "2",width = 20,isColumnHidden = false)
private String test2;
@Excel(name = "test3",orderNum = "3",width = 20,isColumnHidden = false)
private String test3;
}
具體實現代碼
@Api(value = "日誌導出", tags = { "日誌導出" })
@RestController
@RequestMapping("/testExport")
public class TestLogController {
@Autowired
TestLogMapper testLogMapper;
@PostMapping("/export")
@ResponseBody
@ResponseStatus(HttpStatus.CREATED)
public String export(Long logId,String type,String excelName){
TestLogPO testLogPO = testLogMapper.getLog(logId,type);
if(StringUtils.isNullOrEmpty(testLogPO )){
throw new ServiceBizException("日誌爲空!");
}
// Feature.OrderedField 防止數據轉成map順序發生改變
Map<String,Object> logMap = JSONObject.parseObject(testLogPO.getResponseJson(), Map.class, Feature.OrderedField);
Workbook workBook = null;
try {
List<Map<String, Object>> sheetsList = new ArrayList<>();
if("0".equals(type)){
setTest1Data(logMap,sheetsList,type);
}else{
// 針對不同類型有不同處理情況,此處省略setTest2Data
setTest2Data(logMap,sheetsList,type);
}
// 執行方法
workBook = EasyPoiUtils.exportExcel(sheetsList, ExcelType.HSSF);
String name = excelName == "" ? "d:/ddd.xls" : "d:/"+excelName+".xls";
FileOutputStream fos = new FileOutputStream(name);
workBook.write(fos);
fos.close();
}catch (Exception e){
e.printStackTrace();
}finally {
if(workBook != null) {
try {
workBook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "success";
}
/**
* 創建sheet頁
* @param sheetName sheet頁名稱
* @param clazz 類
* @param list 呈現Excel具體數據
* @return sheet頁對象
*/
private Map<String, Object> setParmas(String sheetName,Object clazz,Object list){
// 創建參數對象(用來設定excel得sheet得內容等信息)
ExportParams exportParams = new ExportParams();
// 設置sheet得名稱
exportParams.setSheetName(sheetName);
// 創建sheet1使用得map
Map<String, Object> exportMap = new HashMap<>();
// title的參數爲ExportParams類型,目前僅僅在ExportParams中設置了sheetName
exportMap.put("title", exportParams);
// 模版導出對應得實體類型
exportMap.put("entity", clazz);
// sheet中要填充得數據
exportMap.put("data", list);
return exportMap;
}
/**
* 設置test1數據
* @param temporaryEndMap 日誌源
* @param sheetsList sheet頁集合
*/
private void setTest1Data(Map<String,Object> logMap,List<Map<String, Object>> sheetsList,String type){
// 需求列表
List<TestLogDTO> list = JSONArray.parseArray(JSON.toJSONString(logMap.get("list")), TestLogDTO.class);
Map<String, Object> testMap = setParmas("測試列表",TestLogDTO.class,list);
List<TestLogDTO> finalList = JSONArray.parseArray(JSON.toJSONString(logMap.get("finalList")), TestLogDTO.class);
Map<String, Object> finalResultMap= setParmas("結果列表",TestLogDTO.class,finalList);
// 處理隱藏字段
hiddenColumn(list,type);
sheetsList.add(testMap);
sheetsList.add(finalResultMap);
}
/**
* 處理不同類型隱藏字段
* @param list 數據源
* @param type
*/
private void hiddenColumn(List<TestLogDTO> list,String type){
for (TestLogDTO item : list) {
HiddenColumnUtil<TestLogDTO> easyPoiUtil = new HiddenColumnUtil<>();
easyPoiUtil.t = item;
try {
if("0".equals(type)){
easyPoiUtil.hihdColumn("test2", true);
easyPoiUtil.hihdColumn("test3", true);
}else if("1".equals(type)){
easyPoiUtil.hihdColumn("test1", true);
easyPoiUtil.hihdColumn("test3", true);
}else{
easyPoiUtil.hihdColumn("test1", true);
easyPoiUtil.hihdColumn("test2", true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
大部分代碼出自於:
網上各種找找抄抄,已經不記得瀏覽過哪些博客了