文章来源地址https://www.toymoban.com/news/detail-457651.html
一、POI 表格框架
1.POI : POI提供API给Java程序对Microsoft Office格式档案读和写的功能
2.HSSF:Horrible SpreadSheet Format,为读取操作提供了两类API:usermodel和eventusermodel,即“用户模型”和“事件-用户模型”
3.POI 文档结构类
HSSFWorkbook 文档对象,HSSFSheet 页,HSSFRow 行,HSSFCell 单元格,HSSFFont 字体, HSSFName 名称,HSSFDataFormat 日期格式
HSSFHeader 表头,HSSFFooter 表尾,HSSFCellStyle 单元格样式,HSSFDateUtil 日期,HSSFPrintSetup 打印, HSSFErrorConstants 错误信息表
二、POI 文件类型
类 文件 jar
HSSF -- 提供读写Microsoft Excel XLS格式档案的功能 poi
XSSF -- 提供读写Microsoft Excel OOXML XLSX格式档案的功能 poi--ooxml
HWPF -- 提供读写Microsoft Word DOC格式档案的功能 poi-scratchpad
HSLF -- 提供读写Microsoft PowerPoint格式档案的功能 poi-scratchpad
HDGF -- 提供读Microsoft Visio格式档案的功能 poi-scratchpad
HPBF -- 提供读Microsoft Publisher格式档案的功能 poi-scratchpad
HSMF -- 提供读Microsoft Outlook格式档案的功能 poi-scratchpad
原Excel模板 脱产培训与网络培训两个列表不相同,并且为动态,数据条数未知,所以要动态添加数据与动态合并单元格。
需求如此,多以抛弃使用模板填充方式,改为从第一行构建到最后一行,并且将excel添加水印转换成pdf。
POI Jar包 版本之间差异看官网,尽量用新的
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.15</version>
</dependency>
PDF转换Jar包 了解工具直接搜索jar包名称就行
<dependency>
<groupId>com.bc.ext</groupId>
<artifactId>spire.xls.free</artifactId>
<version>5.1.0</version>
</dependency>
业务代码,具体行都有注释。
public File createExcel(HashMap<String, Object> resultMap, List<Map<String, Object>> actualList, List<Map<String, Object>> netWorkList, HttpServletResponse response){
/** 第一步,创建一个Workbook,对应一个Excel文件 */
XSSFWorkbook wb = new XSSFWorkbook();
/** 第二步,在Workbook中添加一个sheet,对应Excel文件中的sheet */
XSSFSheet sheet = wb.createSheet("sheet1");
//设置每个列有多宽 100为单位好计算
sheet.setColumnWidth(0,100 * 12);
sheet.setColumnWidth(1,100 * 19);
sheet.setColumnWidth(2,100 * 38);
sheet.setColumnWidth(3,100 * 38);
sheet.setColumnWidth(4,100 * 38);
sheet.setColumnWidth(5,100 * 38);
sheet.setColumnWidth(6,100 * 38);
/** 第三步,设置样式以及字体样式*/
XSSFCellStyle titleStyle = createTitleCellStyle(wb);
XSSFCellStyle headerStyle = createHeadCellStyle(wb);
XSSFCellStyle contentStyle = createContentCellStyle(wb);
/** 第四步,创建标题 ,合并标题单元格 */
// 行号
int rowNum = 0;
// 创建第一页的第一行,索引从0开始
XSSFRow row0 = sheet.createRow(rowNum++);
row0.setHeight((short) 800);// 设置行高
String title = "公务员培训情况备案表";
XSSFCell c00 = row0.createCell(0);
c00.setCellValue(title);
c00.setCellStyle(titleStyle);
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 6));//标题合并单元格操作,6为总列数
// 第二行
XSSFRow row1 = sheet.createRow(rowNum++);
row1.setHeight((short) 700);
String[] row_first = {"年度","", "", "", "", "", ""};
for (int i = 0; i < row_first.length; i++) {
XSSFCell tempCell = row1.createCell(i);
tempCell.setCellStyle(headerStyle);
if (i == 0) {
tempCell.setCellValue(Convert.toStr(resultMap.get("year")) + row_first[i]);
}else {
tempCell.setCellValue(row_first[i]);
}
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 6));//标题合并单元格操作,7为总列数
//第三行
XSSFRow row2 = sheet.createRow(rowNum++);
row2.setHeight((short) 700);
String[] row_2_str = {"姓名","", Convert.toStr(resultMap.get("name")), "性别", Convert.toStr(resultMap.get("sex")), "政治面貌", Convert.toStr(resultMap.get("politicVal"))};
for (int i = 0; i < row_2_str.length; i++) {
XSSFCell tempCell = row2.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_2_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 1));//标题合并单元格操作,7为总列数
//第四行
XSSFRow row3 = sheet.createRow(rowNum++);
row3.setHeight((short) 700);
String[] row_3_str = {"学历","",Convert.toStr(resultMap.get("educationVal")), "行政级别",Convert.toStr(resultMap.get("administrationVal")), "",""};
for (int i = 0; i < row_3_str.length; i++) {
XSSFCell tempCell = row3.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_3_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(3, 3, 0, 1));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(3, 3, 4, 6));//标题合并单元格操作,7为总列数
//第五行
XSSFRow row4 = sheet.createRow(rowNum++);
row4.setHeight((short) 700);
String[] row_4_str = {"单位名称","",Convert.toStr(resultMap.get("companyName")), "内设机构",Convert.toStr(resultMap.get("mechanism")), "职务",Convert.toStr(resultMap.get("studentDuties"))};
for (int i = 0; i < row_4_str.length; i++) {
XSSFCell tempCell = row4.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_4_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(4, 4, 0, 1));//标题合并单元格操作,7为总列数
//第六行
XSSFRow row5 = sheet.createRow(rowNum++);
row5.setHeight((short) 700);
String[] row_5_str = {"脱产培训","培训班名称","", "培训时间","", "主办单位","学分"};
for (int i = 0; i < row_5_str.length; i++) {
XSSFCell tempCell = row5.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_5_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(5, 5, 1, 2));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(5, 5, 3, 4));//标题合并单元格操作,7为总列数
//第六行带的数据 循环插入
for (Map<String, Object> actuaLData : actualList) {
XSSFRow tempRow = sheet.createRow(rowNum++);
tempRow.setHeight((short) 700);
// 循环单元格填入数据
for (int j = 0; j < 7; j++) {
XSSFCell tempCell = tempRow.createCell(j);
tempCell.setCellStyle(contentStyle);
String tempValue;
if (j == 0) {
tempValue = "";
} else if (j == 1) {
tempValue = Convert.toStr(actuaLData.get("actualName"));
} else if (j == 2) {
tempValue = "";
} else if (j == 3) {
tempValue = Convert.toStr(actuaLData.get("actualTime"));
} else if (j == 4) {
tempValue = "";
} else if (j == 5) {
tempValue = Convert.toStr(actuaLData.get("actualOrgan"));
} else {
tempValue = Convert.toStr(actuaLData.get("actualPoint"));
}
tempCell.setCellValue(tempValue);
}
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 2));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 3, 4));//标题合并单元格操作,7为总列数
}
//培训班小计行
XSSFRow rowxj = sheet.createRow(rowNum++);
rowxj.setHeight((short) 700);
String[] row_xj_str = {"","小计","", "","", "",Convert.toStr(resultMap.get("totalActualPoint"))};
for (int i = 0; i < row_5_str.length; i++) {
XSSFCell tempCell = rowxj.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_xj_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 1, 5));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(5, rowNum - 1, 0, 0));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
//网络培训标题行
XSSFRow rowNetworkTitle = sheet.createRow(rowNum++);
rowNetworkTitle.setHeight((short) 700);
String[] row_networkTitle_str = {"网络培训","所学课程类别","", "","", "课程数","学分"};
for (int i = 0; i < row_networkTitle_str.length; i++) {
XSSFCell tempCell = rowNetworkTitle.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_networkTitle_str[i]);
}
try {
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 4));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
//做标记,动态计算坐标合并
int startIndex = rowNum - 1;
//网络培训list数据填充
for (Map<String, Object> networkData : netWorkList) {
XSSFRow tempRow = sheet.createRow(rowNum++);
tempRow.setHeight((short) 700);
// 循环单元格填入数据
for (int j = 0; j < 7; j++) {
XSSFCell tempCell = tempRow.createCell(j);
tempCell.setCellStyle(contentStyle);
String tempValue;
if (j == 0) {
tempValue = "";
} else if (j == 1) {
tempValue = Convert.toStr(networkData.get("name"));
} else if (j == 2) {
tempValue = "";
} else if (j == 3) {
tempValue = "";
} else if (j == 4) {
tempValue = "";
} else if (j == 5) {
tempValue = Convert.toStr(networkData.get("networkCount"));
} else {
tempValue = Convert.toStr(networkData.get("point"));
}
tempCell.setCellValue(tempValue);
}
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 4));//标题合并单元格操作,7为总列数
}
//网络培训专题班行
XSSFRow rowNetworkZtb = sheet.createRow(rowNum++);
rowNetworkZtb.setHeight((short) 700);
String[] row_NetworkZtb_str = {"","专题班","", "","", Convert.toStr(resultMap.get("lessonCount")),Convert.toStr(resultMap.get("pointSum"))};
for (int i = 0; i < row_NetworkZtb_str.length; i++) {
XSSFCell tempCell = rowNetworkZtb.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_NetworkZtb_str[i]);
}
//合并
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 1, 4));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
//网络培训小计行
XSSFRow rowNetworkXj = sheet.createRow(rowNum++);
rowNetworkXj.setHeight((short) 700);
String[] row_NetworkXj_str = {"","小计","", "","", Convert.toStr(resultMap.get("networkCount")),Convert.toStr(resultMap.get("networkPoint"))};
for (int i = 0; i < row_NetworkXj_str.length; i++) {
XSSFCell tempCell = rowNetworkXj.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_NetworkXj_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 1, 4));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(startIndex, rowNum - 1, 0, 0));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
//年度完成专题班行
XSSFRow rowYearNetwork = sheet.createRow(rowNum++);
rowYearNetwork.setHeight((short) 700);
String yearNetwork = Convert.toStr(resultMap.get("yearNetwork"));
String[] row_YearNetwork_str;
if (yearNetwork == null){
row_YearNetwork_str = new String[]{"年度完成专题班", "", "", "", "", "个", ""};
}else {
row_YearNetwork_str = new String[]{"年度完成专题班", "", "", "", "", Convert.toStr(resultMap.get("yearNetworkCount")) + "个", ""};
}
for (int i = 0; i < row_YearNetwork_str.length; i++) {
XSSFCell tempCell = rowYearNetwork.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_YearNetwork_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 0, 4));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 5, 6));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
//学分合计行
XSSFRow rowPointCount = sheet.createRow(rowNum++);
rowPointCount.setHeight((short) 700);
String[] row_PointCount_str = new String[]{"学分合计", "", "", "", "", Convert.toStr(resultMap.get("yearPoint")), ""};
for (int i = 0; i < row_PointCount_str.length; i++) {
XSSFCell tempCell = rowPointCount.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_PointCount_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 0, 4));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 5, 6));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
//excel底部两行
XSSFRow rowUnder2 = sheet.createRow(rowNum++);
rowUnder2.setHeight((short) 900);
String[] row_Under2_str = new String[]{"主管部门意见", "", "", Convert.toStr(resultMap.get("is")), "", "", ""};
for (int i = 0; i < row_Under2_str.length; i++) {
XSSFCell tempCell = rowUnder2.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_Under2_str[i]);
}
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 3, 6));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
XSSFRow rowUnder1 = sheet.createRow(rowNum++);
rowUnder1.setHeight((short) 800);
String[] row_Under1_str = new String[]{"", "", "", "", "", Convert.toStr(resultMap.get("pdfTime")), ""};
for (int i = 0; i < row_Under1_str.length; i++) {
XSSFCell tempCell = rowUnder1.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_Under1_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 3, 4));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 5, 6));//标题合并单元格操作,7为总列数
sheet.addMergedRegion(new CellRangeAddress(rowNum-2, rowNum - 1, 0, 2));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
//备注行
XSSFRow rowremarks = sheet.createRow(rowNum++);
rowremarks.setHeight((short) 1300);
String[] row_remarks_str = new String[]{"注:根据《干部教育培训工作条例》,干部参加教育培训,每年累计不少于12天或者90学时,因故未按规定参加教育培训或者未达到教育培训要求的,应当及时补训。干部教育培训考核不合格的,年度考核不得确定为优秀等次。", "", "", "", "","", ""};
for (int i = 0; i < row_remarks_str.length; i++) {
XSSFCell tempCell = rowremarks.createCell(i);
tempCell.setCellStyle(headerStyle);
tempCell.setCellValue(row_remarks_str[i]);
}
// 合并单元格,参数依次为起始行,结束行,起始列,结束列 (索引0开始)
//此处没有任何问题,程序不让运行,就给捕获了,不用操作别的,之后的代码也是一样
try {
sheet.addMergedRegion(new CellRangeAddress(rowNum-1, rowNum - 1, 0, 6));//标题合并单元格操作,7为总列数
} catch (Exception e){
}
try {
//添加图片水印
FileOutputStream fileOut = null;
BufferedImage bufferImg = null;
ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
//加载图片
bufferImg = ImageIO.read(new File("src/main/resources/static/template/peqk.png"));
ImageIO.write(bufferImg, "png", byteArrayOut);
XSSFDrawing patriarch = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0,5, rowNum-3, 7,rowNum-1 );
//插入图片 1
patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG));
// // 输出文件
// wb.write(fileOut);
} catch (Exception e){
e.printStackTrace();
}
File fileExcel = xssfWorkbookToFile(wb, "src/main/resources/static/template/peqk.xlsx");
ExcelToPdf excelToPdf = new ExcelToPdf();
excelToPdf.sheetToPdf("src/main/resources/static/template/peqk.xlsx", "src/main/resources/static/template/peqk.pdf");
File filePdf = new File("src/main/resources/static/template/peqk.pdf");
ServletOutputStream out = null;
try{
out = response.getOutputStream();
/** 导出pdf文件流 */
response.setCharacterEncoding("UTF-8");
response.setContentType("application/pdf");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline; filename="+ URLEncoder.encode("公务员培训情况备案表.pdf","UTF-8"));
FileInputStream inputStream = new FileInputStream(filePdf);
// 读取文件流
int len = 0;
byte[] buffer = new byte[1024 * 10];
while ((len = inputStream.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
out.close();
}catch (Exception e){
e.printStackTrace();
}finally {
fileExcel.delete();
filePdf.delete();
}
return null;
}
下面是工具方法,样式为自定义,如果想添加表格背景颜色,字体,都是可以定义的,具体查询poi的api
/**
* 讲ex对象转换成文件
* @param wb
* @param name
* @return
*/
public static File xssfWorkbookToFile(XSSFWorkbook wb, String name) {
File toFile = new File(name);
try {
OutputStream os = new FileOutputStream(toFile);
wb.write(os);
os.close();
} catch (Exception e) {
e.printStackTrace();
}
return toFile;
}
/**
* 创建标题样式
* @param wb
* @return
*/
private static XSSFCellStyle createTitleCellStyle(XSSFWorkbook wb) {
XSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
// cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
// cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
// cellStyle.setBorderRight(BorderStyle.THIN); //右边框
// cellStyle.setBorderTop(BorderStyle.THIN); //上边框
// cellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());//背景颜色
XSSFFont headerFont1 = (XSSFFont) wb.createFont(); // 创建字体样式
// headerFont1.setBold(true); //字体加粗
headerFont1.setFontName("宋体"); // 设置字体类型
headerFont1.setFontHeightInPoints((short) 17); // 设置字体大小
cellStyle.setFont(headerFont1); // 为标题样式设置字体样式
return cellStyle;
}
/**
* 创建表头样式
* @param wb
* @return
*/
private static XSSFCellStyle createHeadCellStyle(XSSFWorkbook wb) {
XSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setWrapText(true);// 设置自动换行
// cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());//背景颜色
cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直对齐
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
cellStyle.setBorderRight(BorderStyle.THIN); //右边框
cellStyle.setBorderTop(BorderStyle.THIN); //上边框
XSSFFont headerFont = (XSSFFont) wb.createFont(); // 创建字体样式
// headerFont.setBold(true); //字体加粗
headerFont.setFontName("宋体"); // 设置字体类型
headerFont.setFontHeightInPoints((short) 16); // 设置字体大小
// cellStyle.setFont(headerFont); // 为标题样式设置字体样式
return cellStyle;
}
/**
* 创建内容样式
* @param wb
* @return
*/
private static XSSFCellStyle createContentCellStyle(XSSFWorkbook wb) {
XSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
cellStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
cellStyle.setWrapText(true);// 设置自动换行
cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
cellStyle.setBorderRight(BorderStyle.THIN); //右边框
cellStyle.setBorderTop(BorderStyle.THIN); //上边框
// 生成12号字体
XSSFFont font = wb.createFont();
font.setColor((short)8);
font.setFontHeightInPoints((short) 12);
cellStyle.setFont(font);
return cellStyle;
}
最终结果为 pdf 向导出excel把转换pdf的语句删掉就可以了
文章来源:https://www.toymoban.com/news/detail-457651.html
到了这里,关于POI实现导出复杂Excel(动态行,复杂单元格,水印,Excel转换为PDF)。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!