package com.jtech.toa.controller.outclaim.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Slf4j
public class ExportExcelUtils
// 2007 版本以上 最大支持1048576行
public final static String EXCEl_FILE_2007 = "2007";
// 2003 版本 最大支持65536 行
public final static String EXCEL_FILE_2003 = "2003";
public static void exportExcel2browser(String title, Object data, String templatePath, HttpServletResponse response, String version) {
response.reset();
response.setContentType("application/ms-excel;charset=UTF-8");
OutputStream os = null;
try {
if (StringUtils.isEmpty(version) || EXCEL_FILE_2003.equals(version.trim())) {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(title, "UTF-8") + ".xls");
} else {
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(title, "UTF-8") + ".xlsx");
}
os = response.getOutputStream();
exportExcel(data, templatePath, version, os);
os.flush();
} catch (Exception e) {
log.error("导出excel出现异常{}", e);
} finally {
closeOutPutStream(os);
}
}
public static void exportExcel(Object data, String templatePath, String version, OutputStream out) {
if (StringUtils.isEmpty(version) || EXCEL_FILE_2003.equals(version.trim())) {
exportExcel2003(data, templatePath, out);
} else {
exportExcel2007(data, templatePath, out);
}
}
/**
* 导出2007以下
*
* @param data
* @param templatePath
* @param out
*/
private static void exportExcel2003(Object data, String templatePath, OutputStream out) {
try {
HSSFWorkbook workbook;
FileInputStream tps = new FileInputStream(new File(templatePath));
final HSSFWorkbook tpWorkbook = new HSSFWorkbook(tps);
workbook = tpWorkbook;
int numbers = workbook.getNumberOfSheets();
for (int i = 0; i < numbers; i++) {
Sheet sheet = workbook.getSheetAt(i);
addDataToSheet(data, sheet);
}
workbook.write(out);
} catch (IOException e) {
log.error("导出Excel2003出现异常");
}
}
private static void exportExcel2007(Object data, String templatePath, OutputStream out) {
try {
XSSFWorkbook workbook;
FileInputStream tps = new FileInputStream(new File(templatePath));
final XSSFWorkbook tpWorkbook = new XSSFWorkbook(tps);
workbook = tpWorkbook;
int numbers = workbook.getNumberOfSheets();
for (int i = 0; i < numbers; i++) {
Sheet sheet = workbook.getSheetAt(i);
addDataToSheet(data, sheet);
}
workbook.write(out);
} catch (IOException e) {
log.error("导出Excel2007以上出现异常");
}
}
private static void closeOutPutStream(OutputStream os) {
try {
os.close();
} catch (Exception e) {
log.error("关闭流出现异常");
}
}
/**
* 向模板内赋值
*
* @param
*/
private static void addDataToSheet(Object data, Sheet sheet) {
Map
int lastRowNum = sheet.getLastRowNum();
for (int i = lastRowNum; i >= 0; i--) {
Row row = sheet.getRow(i);
if (row == null) {
continue;
}
int lastCellNum = row.getLastCellNum();
for (int j = 0; j < lastCellNum; j++) {
Cell cell = row.getCell(j);
if (cell == null) {
continue;
}
try {
String cellValue = cell.getStringCellValue();
if (cellValue.matches(".*\\$\\{[\\w.()]+}.*")) {
fillCell(cell, cellValue, data);
} else if (cellValue.matches(".*\\$\\{[\\w.]+\\[#][\\w.]+}.*")) {
Map
rowRecord.put(j, cell);
}
} catch (Exception e) {
log.error("异常信息{}", e);
}
}
}
Map
Map
Map
listRecord.forEach((rowNum, colMap) -> {
Pattern p = Pattern.compile("\\$\\{[\\w.\\[#\\]]+}");
Set
colMap.forEach((colNum, cell) -> {
String cellValue = cell.getStringCellValue();
Matcher m = p.matcher(cellValue);
if (m.find()) {
String reg = m.group();
String regPre = reg.substring(2, reg.indexOf("["));
String regSuf = reg.substring(reg.lastIndexOf("].") + 2, reg.length() - 1);
listPath.add(regPre);
listCellStyle.put(String.format("%s.%s", regPre, regSuf), cell.getCellStyle());
listCellPath.put(cell, String.format("%s#%s", regPre, regSuf));
}
});
int maxRow = 0;
for (String s : listPath) {
Object list = getAttributeByPath(data, s);
if (list == null) {
list = new ArrayList<>();
}
if (list instanceof List) {
int len = ((List) list).size();
maxRow = maxRow > len ? maxRow : len;
listInData.put(s, ((List) list));
} else {
throw new IllegalArgumentException(String.format("%s is not a list but a %s", s, list.getClass().getSimpleName()));
}
}
});
listRecord.forEach((rowNum, colMap) -> {
colMap.forEach((colNum, cell) -> {
String path = listCellPath.get(cell);
String[] pathData = path.split("#");
List list = listInData.get(pathData[0]);
int baseRowIndex = cell.getRowIndex();
int colIndex = cell.getColumnIndex();
CellStyle style = listCellStyle.get(String.format("%s.%s", pathData[0], pathData[1]));
for (int i = 0; i < list.size(); i++) {
int rowIndex = baseRowIndex + i;
Row row = sheet.getRow(rowIndex);
if (row == null) {
row = sheet.createRow(rowIndex);
}
Boolean flag = row.getZeroHeight();
if (flag) {
row.setZeroHeight(false);
}
Cell cellToFill = row.getCell(colIndex);
if (cellToFill == null) {
cellToFill = row.createCell(colIndex);
}
cellToFill.setCellStyle(style);
setCellValue(cellToFill, getAttribute(list.get(i), pathData[1]));
}
});
});
}
/**
* @param cell 要置换的单元格
* @param expression 单元格内的置换标记
* @param data 数据源
*/
private static void fillCell(Cell cell, String expression, Object data) {
Pattern p = Pattern.compile("\\$\\{[\\w.\\[\\]()]+}");
Matcher m = p.matcher(expression);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String exp = m.group();
String path = exp.substring(2, exp.length() - 1);
Object value = getAttributeByPath(data, path);
m.appendReplacement(sb, value == null ? "" : value.toString());
}
setCellValue(cell, sb.toString());
}
/**
* @param cell 单元格
* @param value 值
*/
private static void setCellValue(Cell cell, Object value) {
if (value == null) {
cell.setCellValue("");
} else if (value instanceof Date) {
cell.setCellValue((Date) value);
} else if (value instanceof Integer) {
cell.setCellValue((Integer) value);
} else if (value instanceof Long) {
cell.setCellValue((Long) value);
} else if (value instanceof Double) {
cell.setCellValue((Double) value);
} else if (value instanceof Float) {
cell.setCellValue((Float) value);
} else if (value instanceof Character) {
cell.setCellValue((Character) value);
} else if (value instanceof BigDecimal) {
cell.setCellValue(((BigDecimal) value).doubleValue());
} else {
cell.setCellValue(value.toString());
}
}
/**
* @param obj 访问对象
* @param path 属性路径,形如(cls.type, cls.students.size())
* @return
*/
private static Object getAttributeByPath(Object obj, String path) {
String[] paths = path.split("\\.");
Object o = obj;
for (String s : paths) {
o = getAttribute(o, s);
}
return o;
}
private static Object getAttribute(Object obj, String member) {
if (obj == null) {
return null;
}
boolean isMethod = member.endsWith("()");
if (!isMethod && obj instanceof Map) {
return ((Map) obj).get(member);
}
try {
Class> cls = obj.getClass();
if (isMethod) {
Method method = cls.getDeclaredMethod(member.substring(0, member.length() - 2));
return method.invoke(obj);
} else {
Field field = cls.getDeclaredField(member);
field.setAccessible(true);
return field.get(obj);
}
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
log.error("异常信息{}",e);
}
return null;
}
}