java动态导出Excle模板
实际开发中很多时候都需要导出Excle模板文件,而且是根据不同的需求需要导出不同的模板,在这里简单记录一下使用java实现普通的动态Excle模板导出功能。
1.添加maven依赖:
<dependency> <groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.8</version>
</dependency>
- 编写导出工具类:
import java.io.OutputStream;import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFDataValidationConstraint;
import org.apache.poi.xssf.usermodel.XSSFDataValidationHelper;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelDownloadUtil {
/**
* 标题单元格默认长度
*/
private static final int DEFAULT_COLUMN_SIZE = 20;
/**
* EXCEL含有下拉列表默认受影响行数
*/
private static final int SELECT_HEIGHT = 300;
/**
* 用于动态生成导出模板
*
* @param response 用于下载
* @param sheetName 工作表空间名称
* @param columnNames
* @param title Excle模板标题,不需要则传null
* @throws Exception
*/
public static void getExcelTitleTemplate(HttpServletResponse response, String sheetName,
List<Map<String, Object>> columnNames, String title) throws Exception {
Workbook workBook = new XSSFWorkbook();
// 生成一个表格
Sheet sheet = workBook.getSheet(sheetName);
if (sheet == null) {
sheet = workBook.createSheet(sheetName);
}
// 最新Excel列索引,从0开始
int lastRowIndex = sheet.getLastRowNum();
if (lastRowIndex > 0) {
lastRowIndex++;// 如果已经存在了工作表空间则从下一行开始
}
if (!StringUtils.isBlank(title)) {
// 如果需要合并单元格显示一个大的title
Row titleRow = sheet.createRow(lastRowIndex);
//参数说明:1.起始行号 2.终止行号 3.起始列号 4.终止列号
//这个需要实际情况自定义,我这里测试就写死0 0 0 4 了
CellRangeAddress region = new CellRangeAddress(0, 0, 0, 4);
sheet.addMergedRegion(region);// 合并单元格
Cell cellTiltle = titleRow.createCell(0);
// 设置样式
cellTiltle.setCellStyle(createCellHeadStyle(workBook, false));
// 单元格设置值
cellTiltle.setCellValue(title);
lastRowIndex++;
}
// 设置表格默认列宽度
sheet.setDefaultColumnWidth(DEFAULT_COLUMN_SIZE);
// 产生表格表头列标题行
Row row = sheet.createRow(lastRowIndex);
for (int i = 0; i < columnNames.size(); i++) {
Map<String, Object> map = columnNames.get(i);
Cell cell = row.createCell(i);
// 设置单元格类型
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
// 设置单元格样式
cell.setCellStyle(createCellHeadStyle(workBook, (boolean)map.get("isSpecial")));
// 填充表头文本
RichTextString text = new XSSFRichTextString((String)map.get("columnname"));
cell.setCellValue(text);
String[] selectValue = (String[])map.get("selectValue");
// 如果需要有下拉列表则显示
if (selectValue != null && selectValue.length != 0) {
// 准备下拉列表数据
CellRangeAddressList regions = new CellRangeAddressList(1, SELECT_HEIGHT, i, i);
// 创建下拉列表数据
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet);
XSSFDataValidationConstraint dvConstraint =
(XSSFDataValidationConstraint)dvHelper.createExplicitListConstraint(selectValue);
XSSFDataValidation validation = (XSSFDataValidation)dvHelper.createValidation(dvConstraint, regions);
validation.setSuppressDropDownArrow(true);
validation.setShowErrorBox(true);
sheet.addValidationData(validation);
}
}
OutputStream outputStream = response.getOutputStream();
workBook.write(outputStream);// HSSFWorkbook写入流,下载
outputStream.flush();// 刷新流
outputStream.close();// 关闭流
}
/**
* 创建单元格表头样式
*
* @param workbook 工作薄
* @param bgColorYellow true-背景使用黄色
* @return
*/
private static CellStyle createCellHeadStyle(Workbook workbook, boolean bgColorYellow) {
CellStyle style = workbook.createCellStyle();
// 设置边框样式
style.setBorderBottom(XSSFCellStyle.BORDER_THIN);
style.setBorderLeft(XSSFCellStyle.BORDER_THIN);
style.setBorderRight(XSSFCellStyle.BORDER_THIN);
style.setBorderTop(XSSFCellStyle.BORDER_THIN);
// 设置对齐样式
style.setAlignment(XSSFCellStyle.ALIGN_CENTER);
// 生成字体
Font font = workbook.createFont();
// 表头样式
style.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND);
// 如果是true,则显示黄色背景色
style.setFillForegroundColor(bgColorYellow ? HSSFColor.YELLOW.index : HSSFColor.GREY_25_PERCENT.index);
font.setFontHeightInPoints((short)12);
font.setBoldweight(XSSFFont.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
style.setFont(font);
return style;
}
/**
* 得到有效的Excel文件列有效数据
*
* @param xianShiList
* @param biTianList
* @param jiGouId
* @return
*/
public static List<Map<String, Object>> getColumnNames(List<String> xianShiList, List<String> biTianList,
String condition) {
List<Map<String, Object>> columnNames = new ArrayList<Map<String, Object>>();
Map<String, Object> resultMap = null;
List<String> selectValues = null;
boolean validaBiTianList = biTianList != null && !biTianList.isEmpty();
for (int i = 0, len = xianShiList.size(); i < len; i++) {
resultMap = new HashMap<String, Object>();
// 得到下载的字段名称
String columnName = xianShiList.get(i);
// 判断该字段是否是字典类型,如果是字典类型的字段则需要显示下拉列表
// 我这里用了一个枚举类涵盖所有的可能涉及的下载字段,每次判断一下是否需要获取字典值
FieldEnum field = FieldEnum.getFieldEnum(columnName);
if (field != null) {
resultMap.put("columnname", columnName);
// 判断字段是否是必填字段
if (validaBiTianList && biTianList.contains(columnName)) {
resultMap.put("isSpecial", true);// 如果是必填则标识为true
} else {
resultMap.put("isSpecial", false);
}
if (field.isZiDian()) {// 如果是字典值
// 获取字典内容
// ZiDianEntity ziDian = ZiDianUtil.getZiDian(columnName, condition);
// List<ZiDianZhiEntity> ziDianZhiEntityList = ziDian.getZiDianZhiList();
selectValues = new ArrayList<>();
// 添加字典值到下拉列表
/*for (int j = 0, lenx = ziDianZhiEntityList.size(); j < lenx; j++) {
selectValues.add(ziDianZhiEntityList.get(j).getZiDianZhi());
}*/
// 这里为了测试直接写死了
selectValues.add("男");
selectValues.add("女");
selectValues.add("未知");
resultMap.put("selectValue", selectValues.toArray(new String[selectValues.size()]));
}
columnNames.add(resultMap);
}
}
return columnNames;
}
/**
* 得到EXCEL模板下载时的显示字段
*
* @param condition
* @return
* @throws Exception
*/
public static List<String> listXianShiField(String condition) throws Exception {
List<String> resultList = listExcelField("EXCEL下载时显示字段", condition);
resultList = resultList != null && resultList.size() != 0 ? resultList
: Arrays.asList(new String[] {"姓名", "身份证号", "性别", "联系电话", "联系地址"});
return resultList;
}
/**
* 得到EXCEL模板下载时的必填字段
*
* @param jiGouId
* @return
* @throws Exception
*/
public static List<String> listBiTianField(String jiGouId) throws Exception {
List<String> resultList = listExcelField("EXCEL必填字段", jiGouId);
resultList =
resultList != null && resultList.size() != 0 ? resultList : Arrays.asList(new String[] {"姓名", "性别"});
return resultList;
}
/**
* 通过设置名称获取显示list集合
*
* @param sheZhiMingCheng
* @param condition
* @return
* @throws Exception
*/
public static List<String> listExcelField(String sheZhiMingCheng, String condition) throws Exception {
List<String> list = null;
// 可以从数据库中动态获取,或者从程序中动态拼接出想要导出的字段
//do something
return list;
}
}
枚举类补充:
public enum FieldEnum { /**
* 姓名
*/
XING_MING("姓名", false),
/**
* 身份证号
*/
SHEN_FEN_ZHENG_HAO("身份证号", false),
/**
* 性别
*/
XING_BIE("性别", true),
/**
* 婚姻状况
*/
HUN_YING_ZHUANG_KUANG("婚姻状况", true),
/**
* 联系人
*/
LIAN_XI_REN("联系人", false),
/**
* 联系电话
*/
LIAN_XI_DIAN_HUA("联系电话", false),
/**
* 联系地址
*/
LIAN_XI_DI_ZHI("联系地址", false);
/* 省略其他可能的属性 */
private String name;
private boolean isZiDian;
private FieldEnum(String name, boolean isZiDian) {
this.name = name;
this.isZiDian = isZiDian;
}
/**
* 通过name获取枚举类
*
* @param name
* @return
*/
public static FieldEnum getFieldEnum(String name) {
FieldEnum[] values = FieldEnum.values();
for (int i = 0; i < values.length; i++) {
if (values[i].getName().equals(name)) {
return values[i];
}
}
return null;
}
public String getName() {
return name;
}
public boolean isZiDian() {
return isZiDian;
}
}
3.实现下载:
/** * 下载动态模板
*
* @param request
* @param response
*/
@RequestMapping(value = "/downloadDongTaiMuBan.do")
public void downloadDongTaiMuBan(HttpServletRequest request, HttpServletResponse response) {
try {
// 这里只是模仿一种条件,真正的条件需要根据实际情况传入
String condition = request.getRequestURL().toString();
System.out.println(condition);
// 根据条件从数据库动态获取需要导出的EXCEL字段
List<String> xianShiList = ExcelDownloadUtil.listXianShiField(condition);
if (xianShiList != null && !xianShiList.isEmpty()) {
// 根据条件从数据库动态获取必填的EXCEL字段
List<String> biTianList = ExcelDownloadUtil.listBiTianField(condition);
// 文件名编码,解决乱码问题
String fileName = "登记.xlsx";
String userAgentString = request.getHeader("User-Agent");
String browser = UserAgent.parseUserAgentString(userAgentString).getBrowser().getGroup().getName();
if (browser.equals("Chrome") || browser.equals("Internet Exploer") || browser.equals("Safari")) {
fileName = URLEncoder.encode(fileName, "utf-8").replaceAll("\\+", "%20");
} else {
fileName = MimeUtility.decodeText(fileName);
}
// 设置请求
response.setCharacterEncoding("UTF-8");
response.setContentType("application/x-download");
response.addHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", fileName));
response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.addHeader("Pragma", "no-cache");
response.addHeader("Expires", "0");
final String sheetName = "第一分组";// 设置EXCEL默认工作表空间名称
// 处理EXCEL字段,标识出需要必填的字段,有下拉列表的字段,获取下拉列表的值
List<Map<String, Object>> columnNames =
ExcelDownloadUtil.getColumnNames(xianShiList, biTianList, condition);
if (columnNames != null && !columnNames.isEmpty()) {
ExcelDownloadUtil.getExcelTitleTemplate(response, sheetName, columnNames, "登记信息");
}
}
} catch (Exception e) {
e.printStackTrace();
logger.error("生成下载动态模板异常!", e);
}
}
4.效果预览:
通过以上代码就简单实现Excle模板动态导出功能啦。
以上是 java动态导出Excle模板 的全部内容, 来源链接: utcz.com/z/390531.html