1.首先就是导包 下面是maven坐标
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
2.就是编写工具类,不是很全,但是基本功能也可以自己加进去。
package com.fitk.emis.corp.export_Util.myPoi.excel;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
/**
* excel导出工具类
*/
@SuppressWarnings("all")
public class ExcelExpUtil01<T> {
private Logger log = LoggerFactory.getLogger(ExcelExpUtil01.class);
private Class clazz;//导出目标类的Class对象
private int colNum;//总列数
private int startRowIndex;//导出内容开始的行号,不包括表头
private Field[] fields;//所有是属性数组
private Boolean is_title=false; //是否要标题内容 默认没有
private String titleName;//标题内容
private Boolean is_Notes=false;//是否需要表尾内容
private String notes="";//表尾内容
private int headerNmu=1;//要合并的表头级别,1表示表标题下的第一层表头,数据层对应表头之上。
// 每个string以 "宠物信息1#1,2,0,1" 形式储存,#前为内容,#后为坐标 前两个数表示要合并的行号,后两位表示要合并的列号
private String[] headerArr;//要合并的表头数组
private String[][] headerArrMany;//要合并的多层表头数组
private String[] headers;// 列名集合
private Short[] columnWidth ;//列宽集合
private Integer[] alignList ;//内文样式位置集合,左对齐,居中或右对齐
private Boolean[] boderList ;// 是否需要边框 集合
private Integer[] fontColorList;// 字体颜色集合
private String[] fontNameList ;// 字体集合
private Short[] fontSizeList;// 字号集合
private Integer[] styleColorList ;// 单元格背景色 集合
private Field[] excelFileds ;//存放有注解的字段 也就是需要导出的字段 无注解字段排除
/**
* 没有合并表头的构造方法
* @param clazz 导出类的CLass对象
* @param titleName 标题名称
* @param colNum 总列数 需要与注解中标注的数量相同,不然会报错
* @param startRowIndex 导出内容开始的行号,不包括表头
*/
public ExcelExpUtil01(Class clazz,String titleName, int colNum, int startRowIndex){
this.clazz=clazz;
if(titleName!=null && titleName!=""){
this.is_title=true;
this.titleName = titleName;
}
this.colNum = colNum;
this.startRowIndex = startRowIndex-1;//从0开始的,所以减1
this.fields = clazz.getDeclaredFields();
this.headers = new String[colNum];
this.columnWidth = new Short[colNum];
this.alignList = new Integer[colNum];
this.boderList = new Boolean[colNum];
this.fontColorList = new Integer[colNum];
this.fontNameList = new String[colNum];
this.fontSizeList = new Short[colNum];
this.styleColorList = new Integer[colNum];
this.excelFileds = new Field[colNum];
}
/**
* 没有合并表头的构造方法并且没有表标题
* @param clazz 导出类的CLass对象
* @param colNum 总列数 需要与注解中标注的数量相同,不然会报错
* @param startRowIndex 导出内容开始的行号,不包括表头
*/
public ExcelExpUtil01(Class clazz, int colNum, int startRowIndex){
this(clazz,null,colNum,startRowIndex);//调用另一个构造方法
}
/**
* 有一行合并表头的构造方法
* @param clazz 导出类的CLass对象
* @param titleName 标题名称
* @param colNum 总列数
* @param startRowIndex 导出内容开始的行号,不包括表头
* @param headerArr 要合并的表头数组
*/
public ExcelExpUtil01(Class clazz,String titleName, int colNum, int startRowIndex,String[] headerArr){
this(clazz,titleName,colNum,startRowIndex);//调用另一个构造方法
this.headerArr = headerArr;
}
/**
* 有一行合并表头的构造方法 带表尾
* @param clazz 导出类的CLass对象
* @param titleName 标题名称
* @param colNum 总列数
* @param startRowIndex 导出内容开始的行号,不包括表头
* @param headerArr 要合并的表头数组
* @param notes 表尾内容
*/
public ExcelExpUtil01(Class clazz,String titleName, int colNum, int startRowIndex,String[] headerArr,String notes){
this(clazz,titleName,colNum,startRowIndex);//调用另一个构造方法
this.headerArr = headerArr;
if (notes!=null && notes!=""){
this.notes=notes;
this.is_Notes=true;
}
}
/**
* 有多行合并表头的构造方法,自定义表头行数
* @param clazz 导出类的CLass对象
* @param titleName 标题名称
* @param colNum 总列数
* @param startRowIndex 导出内容开始的行号,不包括表头
* @param headerArrMany 要合并的表头数组多级
* @param herderNum 要加的几层表头
*/
public ExcelExpUtil01(Class clazz,String titleName, int colNum, int startRowIndex,String[][] headerArrMany,int herderNum){
this(clazz,titleName,colNum,startRowIndex);//调用另一个构造方法
this.headerArrMany = headerArrMany;
this.headerNmu=herderNum;
}
/**
* 有多行合并表头的构造方法,自定义表头行数 带表尾的
* @param clazz 导出类的CLass对象
* @param titleName 标题名称
* @param colNum 总列数
* @param startRowIndex 导出内容开始的行号,不包括表头
* @param headerArrMany 要合并的表头数组多级
* @param herderNum 要加的几层表头
*/
public ExcelExpUtil01(Class clazz,String titleName, int colNum, int startRowIndex,String[][] headerArrMany,int herderNum,String notes){
this(clazz,titleName,colNum,startRowIndex);//调用另一个构造方法
if (notes!=null && notes!=""){
this.notes=notes;
this.is_Notes=true;
}
if(titleName!=null && titleName!=""){
this.is_title=true;
}
this.headerArrMany = headerArrMany;
this.headerNmu=herderNum;
}
/**
* 导出excel的方法
* @param dataList 导出的业务数据
* @param response 浏览器下载的流
* @param fileName 导出的文件名
* @param ext 导出的文件的扩展名,.xls .xlsx
*/
public void excelExp(List<T> dataList,HttpServletRequest request, HttpServletResponse response, String fileName, String ext){
//根据后缀名得到工作簿对象
Workbook workbook = getWorkBook(ext);
if(workbook != null){
creatSheet(workbook, dataList);//创建sheet页
//下载文件
this.downloadFile(workbook,request,response,fileName,ext);
}else{
log.error("创建工作簿失败");
}
}
/**
* 导出excel的方法(无url)
* @param dataList 导出的业务数据
* @param fileName 导出的文件名(可包含也可不包含后缀)
* @param ext 导出的文件的扩展名,.xls .xlsx
*/
public void excelExpBypathName(List<T> dataList, String fileName, String ext){
//如果文件名不包含那就补上
if(!fileName.contains(".xls") && !fileName.contains(".xlsx")){
fileName=fileName+ext;
}
excelExp(dataList,fileName,ext);
}
/**
* 导出excel的方法(无url)
* @param dataList 导出的业务数据
* @param filePathName 导出的路径及名称(带后缀)
* @param ext 导出的文件的扩展名,.xls .xlsx
*/
public void excelExp(List<T> dataList, String filePathName,String ext){
//根据后缀名得到工作簿对象
Workbook workbook = getWorkBook(ext);
if(workbook != null){
creatSheet(workbook, dataList);//创建sheet页
//导出
File file=new File(filePathName);
FileOutputStream out=null;
try {
if (file == null) {
file.createNewFile();
log.info("文件不存在,创建新文件:" + filePathName);
} else {
log.info("文件存在:" + filePathName);
}
out=new FileOutputStream(file);
workbook.write(out);
out.flush();
out.close();
}catch (IOException e){
e.printStackTrace();
log.info("Output is closed ");
}
}else{
log.error("创建工作簿失败");
}
}
//创建sheet
private void creatSheet(Workbook workbook, List<T> dataList) {
if(dataList==null || dataList.size()<=0){
return;
}
Sheet sheet = workbook.createSheet();//sheet对象
Row row =null;//行对象
Cell cell = null;//列对象
ExcelColumn excelColumn = null;
int j=0;//相当于是列号,从0开始的
for(short i = 0; i < fields.length; i++){
Field field = fields[i];//得到属性
//判断属性上面是否有注解:ExcelColumn
if(field.isAnnotationPresent(ExcelColumn.class)){
excelColumn = (ExcelColumn)field.getAnnotation(ExcelColumn.class);//得到注解信息
j = excelColumn.sort()-1;
excelFileds[j] = field;//放入到要导出字段的集合中
headers[j] = excelColumn.title();//把列名放入到列名集合中
columnWidth[j]=excelColumn.width();//把宽度放入到宽度集合中
alignList[j]=excelColumn.alignment().getValue();
boderList[j]=excelColumn.boder();
fontColorList[j]=excelColumn.fontColor().getValue();
fontNameList[j]=excelColumn.fontName();
fontSizeList[j]=excelColumn.fontSize();
styleColorList[j]=excelColumn.styleColor().getValue();
}
}
// 循环设置列宽
int length = columnWidth.length;
for (int i = 0; i < length; i++) {
sheet.setColumnWidth(i, columnWidth[i] * 256);
}
if(is_title){
// 产生表格标题行,标题行是第一行
this.createTitle(workbook,sheet,row);
}
//合并表头行设置 自定义一层
if(this.headerArr!=null && headerArrMany==null){
this.createHeBinHeader(workbook,sheet,row,cell);
}
//合并表头行设置 自定义多层
if(headerArrMany!=null){
for(int i=0;i<headerNmu;i++){ //其中 i+1代表表头数
headerArr=headerArrMany[i];
//第一次加是从1行开始
int lie=1;
//之后就是取合并后行+1
if(i!=0){
String[]pre_header=headerArrMany[i-1];
lie=Integer.parseInt(pre_header[pre_header.length-1].split("\\,")[1])+1;
}
this.createHeBinHeader(workbook,sheet,row,cell,lie);
}
}
//生成二级表头行,这是数据头及字段实体类中设置的表头
this.createHeader(workbook,sheet,row,cell);
// 遍历集合数据,产生数据行
this.setDataToSheet(workbook,sheet,row,cell,dataList);
if(this.is_Notes){
// 产生表格备注行,备注行是最后一行
this.createLastNotesTitle(workbook,sheet,row,startRowIndex,notes);
}
}
//根据表头数组信息合并行(一层)
private void createHeBinHeader(Workbook workbook, Sheet sheet, Row row, Cell cell) {
row = sheet.createRow(1);//第二行是合并表头的行,行号为1
row.setHeightInPoints(30);//设置行高
CellStyle boderStyle = workbook.createCellStyle();//创建一个样式
Font font = workbook.createFont();// 生成一个字体 默认字体微软雅黑
// font.setFontName("宋体");
font.setFontHeightInPoints((short)10);// 设置字体大小
font.setBoldweight(Font.BOLDWEIGHT_BOLD);//字体加粗
boderStyle.setFont(font);// 把字体应用到当前的样式
//设置边框
//boderStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
boderStyle.setBorderBottom(CellStyle.BORDER_THIN);
boderStyle.setBorderLeft(CellStyle.BORDER_THIN);
boderStyle.setBorderRight(CellStyle.BORDER_THIN);
boderStyle.setBorderTop(CellStyle.BORDER_THIN);
//垂直居中
boderStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
boderStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式
boderStyle.setWrapText(true);// 自动换行
String[] zuoBiaoArr = null;
int colIndex = 0;//列起始行号
for(int i = 0; i<headerArr.length;i++){
String[] valueArr = headerArr[i].split("#");
String cellValue = valueArr[0];//单元格内容
String zuoBiaoStr = valueArr[1];
zuoBiaoArr = zuoBiaoStr.split(",");
/** String[] headerArr = new String[2];
headerArr[0] = "宠物信息1#1,2,0,1"; 表示该行2个并列的表头
第一个宠物信息1,#后面表示第一行到第二行合并(主表头占一行,所有从1开始),第0列到第一列合并
headerArr[1] = "宠物信息2#1,2,2,3";
第二个宠物信息2
* colIndex 得到的这个值应该是合并坐标的其实列号,比如zuoBiaoArr={1,1,2,6},那么就是2,
* 如果下次进来的zuoBiaoArr={1,1,7,15},那么应该就是7
*/
colIndex=Integer.parseInt(zuoBiaoArr[2]);
cell = row.createCell(colIndex);//得到列
cell.setCellValue(cellValue);//设置内容
cell.setCellStyle(boderStyle);//设置样式
//调用方法设置合并样式
setMergeStyle(workbook, sheet, zuoBiaoArr);
}
}
//根据表头数组信息合并行(自定义多层)
private void createHeBinHeader(Workbook workbook, Sheet sheet, Row row, Cell cell,int headerNmu) {
row = sheet.createRow(headerNmu);//第二行是合并表头的行,行号为1
row.setHeightInPoints(30);//设置行高
CellStyle boderStyle = workbook.createCellStyle();//创建一个样式
Font font = workbook.createFont();// 生成一个字体 默认字体微软雅黑
// font.setFontName("宋体");
font.setFontHeightInPoints((short)12);// 设置字体大小
font.setBoldweight(Font.BOLDWEIGHT_BOLD);//字体加粗
boderStyle.setFont(font);// 把字体应用到当前的样式
//设置边框
//boderStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
boderStyle.setBorderBottom(CellStyle.BORDER_THIN);
boderStyle.setBorderLeft(CellStyle.BORDER_THIN);
boderStyle.setBorderRight(CellStyle.BORDER_THIN);
boderStyle.setBorderTop(CellStyle.BORDER_THIN);
//垂直居中
boderStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
boderStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式
boderStyle.setWrapText(true);// 自动换行
String[] zuoBiaoArr = null;
int colIndex = 0;//列起始行号
for(int i = 0; i<headerArr.length;i++){
String[] valueArr = headerArr[i].split("#");
String cellValue = valueArr[0];//单元格内容
String zuoBiaoStr = valueArr[1];
zuoBiaoArr = zuoBiaoStr.split(",");
/** String[] headerArr = new String[2];
headerArr[0] = "宠物信息1#1,2,0,1"; 表示该行2个并列的表头
第一个宠物信息1,#后面表示第一行到第二行合并(主表头占一行,所有从1开始),第0列到第一列合并
headerArr[1] = "宠物信息2#1,2,2,3";
第二个宠物信息2
* colIndex 得到的这个值应该是合并坐标的其实列号,比如zuoBiaoArr={1,1,2,6},那么就是2,
* 如果下次进来的zuoBiaoArr={1,1,7,15},那么应该就是7
*/
colIndex=Integer.parseInt(zuoBiaoArr[2]);
cell = row.createCell(colIndex);//得到列
cell.setCellValue(cellValue);//设置内容
cell.setCellStyle(boderStyle);//设置样式
//调用方法设置合并样式
setMergeStyle(workbook, sheet, zuoBiaoArr);
}
}
//自定义合并单元格(自定义多层) (合并起始行号,表头信息)
// headerNmu=1 ,heraderzj= 宠物信息1#1,2,0,1 表示行号1开始,第一行到第二行合并,第0列到第一列合并
private void createHeBinHeader_my(Workbook workbook, Sheet sheet, Row row, Cell cell,int headerNmu,String heraderzj) {
row = sheet.createRow(headerNmu);//第二行是合并表头的行,行号为1
row.setHeightInPoints(30);//设置行高
CellStyle boderStyle = workbook.createCellStyle();//创建一个样式
Font font = workbook.createFont();// 生成一个字体 默认字体微软雅黑
font.setFontName("宋体");
font.setFontHeightInPoints((short)10);// 设置字体大小
font.setBoldweight(Font.BOLDWEIGHT_BOLD);//字体加粗
boderStyle.setFont(font);// 把字体应用到当前的样式
//设置边框
//boderStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
boderStyle.setBorderBottom(CellStyle.BORDER_THIN);
boderStyle.setBorderLeft(CellStyle.BORDER_THIN);
boderStyle.setBorderRight(CellStyle.BORDER_THIN);
boderStyle.setBorderTop(CellStyle.BORDER_THIN);
//垂直居中
boderStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
boderStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式
boderStyle.setWrapText(true);// 自动换行
String[] zuoBiaoArr = null;
int colIndex = 0;//列起始行号
String[] valueArr = heraderzj.split("#");
String cellValue = valueArr[0];//单元格内容
String zuoBiaoStr = valueArr[1];
zuoBiaoArr = zuoBiaoStr.split(",");
/** String[] headerArr = new String[2];
headerArr[0] = "宠物信息1#1,2,0,1"; 表示该行2个并列的表头
第一个宠物信息1,#后面表示第一行到第二行合并(主表头占一行,所有从1开始),第0列到第一列合并
headerArr[1] = "宠物信息2#1,2,2,3";
第二个宠物信息2
* colIndex 得到的这个值应该是合并坐标的其实列号,比如zuoBiaoArr={1,1,2,6},那么就是2,
* 如果下次进来的zuoBiaoArr={1,1,7,15},那么应该就是7
*/
colIndex=Integer.parseInt(zuoBiaoArr[2]);
cell = row.createCell(colIndex);//得到列
cell.setCellValue(cellValue);//设置内容
cell.setCellStyle(boderStyle);//设置样式
//调用方法设置合并样式
setMergeStyle(workbook, sheet, zuoBiaoArr);
}
//设置合并的样式
private void setMergeStyle(Workbook workbook, Sheet sheet,String[] zuoBiaoArr) {
//给定要合并的单元格范围
CellRangeAddress region = new CellRangeAddress(Integer.parseInt(zuoBiaoArr[0]),
Integer.parseInt(zuoBiaoArr[1]), Integer.parseInt(zuoBiaoArr[2]), Integer.parseInt(zuoBiaoArr[3]));//给定要合并的单元格范围
sheet.addMergedRegion(region);//设置合并
//给合并过的单元格加边框
RegionUtil.setBorderBottom(HSSFCellStyle.BORDER_THIN, region, sheet, workbook); //下边框
RegionUtil.setBorderLeft(HSSFCellStyle.BORDER_THIN, region, sheet, workbook); //左边框
RegionUtil.setBorderRight(HSSFCellStyle.BORDER_THIN, region, sheet, workbook); //右边框
RegionUtil.setBorderTop(HSSFCellStyle.BORDER_THIN, region, sheet, workbook); //上边框
}
/**
* 循环遍历,把数据设置到表格中的方法
* @param workbook 工作簿
* @param row 行对象
* @param cell 单元格对象
* @param sheet sheet对象
* @param dataList 数据集合
* @param alignList 对齐方式集合
* @param boderList 是否边框的集合
* @param fontColorList 字体颜色的集合
* @param fontNameList 字体名称的集合
* @param fontSizeList 字体大小的集合
* @param styleColorList 背景颜色的集合
* @param excelFileds 需要导出的列 集合
*/
private void setDataToSheet(Workbook workbook, Sheet sheet, Row row,Cell cell, List<T> dataList) {
Iterator<T> it = dataList.iterator();
while (it.hasNext()) {
row = sheet.createRow(startRowIndex++);//从第几行开始
T t = (T) it.next();
// 利用反射,根据javabean属性的先后顺序,动态调用getXxx()方法得到属性值
for (int i = 0; i < excelFileds.length; i++) {
cell = row.createCell(i);
Field field = excelFileds[i];//获取属性
field.setAccessible(true);//忽略检查,不加这个写入不了数据
//调用方法进行样式设置
this.setCellStyle(workbook, cell, alignList[i], boderList[i],styleColorList[i],
fontColorList[i], fontNameList[i],fontSizeList[i],false);
String fieldName = field.getName();//得到属性名称
//得到属性的get方法名称
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
try {
cell.setCellValue(field.get(t)==null?"":field.get(t).toString());
//另外一种手动拼get方法的方式获取值
//得到对应的方法
/*Method getMethod = this.clazz.getMethod(getMethodName, new Class[] {});
//执行方法,得到返回值
Object value = getMethod.invoke(t, new Object[] {});
String textValue = value.toString();
if (textValue != null) {
RichTextString richString = new HSSFRichTextString(textValue);
cell.setCellValue(richString);
}*/
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//生成表头行
private void createHeader(Workbook workbook, Sheet sheet,Row row,Cell cell) {
row = sheet.createRow(this.startRowIndex-1);//内容开始行的上一行是表头行
for (int i = 0; i < headers.length; i++) {
cell = row.createCell(i);
//调用方法设置样式
this.setCellStyle(workbook, cell, alignList[i], boderList[i],styleColorList[i],
fontColorList[i], fontNameList[i],fontSizeList[i],true);
HSSFRichTextString text = new HSSFRichTextString(headers[i]);//获取该列的值
cell.setCellValue(text);//把值设置到单元格中
}
}
/**
* 创建标题行的方法
* @param workbook
* @param sheet
* @param row
*/
private void createTitle(Workbook workbook,Sheet sheet,Row row){
row = sheet.createRow(0);//标题行
row.setHeightInPoints(60);//设置行高
Cell titleCell = row.createCell(0);//得到标题列
CellStyle cellStyle = workbook.createCellStyle();
// 生成一个字体 默认字体微软雅黑
Font font = workbook.createFont();
// 设置字体大小
font.setFontHeightInPoints((short)12);
// 字体加粗
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
cellStyle.setFont(font);
//垂直居中
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
cellStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式
titleCell.setCellStyle(cellStyle);//设置样式
titleCell.setCellValue(this.titleName);//设置内容
sheet.addMergedRegion(new CellRangeAddress(row.getRowNum(),
row.getRowNum(), row.getRowNum(), this.colNum-1));//设置合并
}
/**
* 创建添加表尾备注的方法
* @param workbook
* @param sheet
* @param row
* @param notes 表尾内容
*/
private void createLastNotesTitle(Workbook workbook,Sheet sheet,Row row,int last_Note_num,String notes){
row = sheet.createRow(last_Note_num);//标题行
row.setHeightInPoints(60);//设置行高
Cell titleCell = row.createCell(0);//得到标题列
CellStyle cellStyle = workbook.createCellStyle();
// 生成一个字体 默认字体微软雅黑
Font font = workbook.createFont();
// 设置字体大小
font.setFontHeightInPoints((short)12);
// 字体加粗
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
// 把字体应用到当前的样式
cellStyle.setFont(font);
cellStyle.setBorderBottom(CellStyle.BORDER_THIN);
cellStyle.setBorderLeft(CellStyle.BORDER_THIN);
cellStyle.setBorderRight(CellStyle.BORDER_THIN);
cellStyle.setBorderTop(CellStyle.BORDER_THIN);
//垂直居中
cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
cellStyle.setAlignment(CellStyle.ALIGN_CENTER); // 创建一个居中格式
String[] zuoBiaoArr=new String[4];
zuoBiaoArr[0]=row.getRowNum()+"";
zuoBiaoArr[1]=row.getRowNum()+"";
zuoBiaoArr[2]="0";
zuoBiaoArr[3]=(this.colNum-1)+"";
titleCell.setCellStyle(cellStyle);//设置样式
titleCell.setCellValue(notes);//设置内容
//调用方法设置合并样式
setMergeStyle(workbook, sheet, zuoBiaoArr);
}
/**
* @Title: 设置单元格样式的方法
* @param workbook 工作簿
* @param cell 要配置的单元格
* @param alignment 单元格内文样式
* @param needBoder 是否需要环绕边框
* @param sytleColor 单元格背景色
* @param fontColor 文字颜色
* @param fontName 字体
* @param fontSize 字号
* @param isBold 表头是否加粗
* @Description: 设置单元格以及字体的整体样式
*/
private void setCellStyle(Workbook workbook, Cell cell, int alignment, Boolean needBoder, int sytleColor,int fontColor,
String fontName,short fontSize,boolean isBold) {
// 生成一个通用样式 默认背景为白色
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor((short)sytleColor);
// 单元格内容样式
style.setAlignment((short) alignment);
style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);//垂直居中
style.setAlignment(CellStyle.ALIGN_CENTER); // 水平居中
style.setWrapText(true);// 自动换行
// 单元格是否需要边框
if (needBoder) {
style.setFillPattern(CellStyle.SOLID_FOREGROUND);
style.setBorderBottom(CellStyle.BORDER_THIN);
style.setBorderLeft(CellStyle.BORDER_THIN);
style.setBorderRight(CellStyle.BORDER_THIN);
style.setBorderTop(CellStyle.BORDER_THIN);
}
// 生成一个字体 默认字体微软雅黑
Font font = workbook.createFont();
font.setFontName(fontName);
font.setColor((short) fontColor);
// 设置字体大小
font.setFontHeightInPoints(fontSize);
// 字体是否加粗
if (isBold) {
font.setBoldweight(Font.BOLDWEIGHT_BOLD);
}
// 把字体应用到当前的样式
style.setFont(font);
cell.setCellStyle(style);
}
//根据后缀名得到工作簿对象
private Workbook getWorkBook(String ext){
if(".xls".equals(ext)){
return new HSSFWorkbook();
}
if(".xlsx".equals(ext)){
return new SXSSFWorkbook();
}
log.error("扩展名只能为【.xls】或【.xlsx】");
return null;
}
/**
* 文件下载的方法
* @param workbook 工作簿
* @param request 请求
* @param response 响应
* @param filename 文件名称
* @param ext 文件扩展名
*/
private static void downloadFile(Workbook workbook,HttpServletRequest request, HttpServletResponse response,String filename,String ext){
filename = filename+ext;//文件名+扩展名
//调用其他下载方法
downloadFile(workbook,request,response,filename);
}
private static void downloadFile(Workbook workbook,HttpServletRequest request, HttpServletResponse response,String filename){
try {
//从请求头中获取User-Agent判断当前使用的是否是火狐浏览器
String agent = request.getHeader("User-Agent");
//根据不同浏览器进行不同的编码
String realFilename = "";
if (agent.contains("MSIE")) {
// IE浏览器
realFilename = URLEncoder.encode(filename, "utf-8");
realFilename = realFilename.replace("+", " ");
} else if (agent.contains("Firefox")) {
// 火狐浏览器,此处使用java8
realFilename = "=?utf-8?B?" + org.apache.commons.codec.binary.Base64.encodeBase64String(filename.getBytes("utf-8"))+"?=";
} else {
// 其它浏览器
realFilename = URLEncoder.encode(filename, "utf-8");
}
//设置要被下载的文件名
response.setHeader("Content-Disposition","attachment;filename="+realFilename);
response.setContentType("application/octet-stream");
response.setHeader("filename", filename);
workbook.write(response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.这里说明下list_Col集合是我对应数据库的,下面是表设计,主要看字段和主键就行
ALTER TABLE SYS_EXP_COL
DROP PRIMARY KEY CASCADE;
DROP TABLE SYS_EXP_COL CASCADE CONSTRAINTS;
CREATE TABLE SYS_EXP_COL
(
EXP_LIST VARCHAR2(30 BYTE) NOT NULL,
EXP_NUM NUMBER(3) NOT NULL,
COL_NAME VARCHAR2(50 BYTE),
COL_KEY VARCHAR2(50 BYTE),
COL_WIDTH NUMBER(3)
)
TABLESPACE MWMS
RESULT_CACHE (MODE DEFAULT)
PCTUSED 0
PCTFREE 10
INITRANS 1
MAXTRANS 255
STORAGE (
INITIAL 128K
NEXT 1M
MINEXTENTS 1
MAXEXTENTS UNLIMITED
PCTINCREASE 0
BUFFER_POOL DEFAULT
FLASH_CACHE DEFAULT
CELL_FLASH_CACHE DEFAULT
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL
MONITORING;
CREATE UNIQUE INDEX PK_SYS_EXP_COL ON HSBK.SYS_EXP_COL
(EXP_LIST, EXP_NUM)
LOGGING
TABLESPACE MWMS
PCTFREE 10
INITRANS 2
MAXTRANS 255
STORAGE (
INITIAL 64K
NEXT 1M
MINEXTENTS 1
MAXEXTENTS UNLIMITED
PCTINCREASE 0
BUFFER_POOL DEFAULT
FLASH_CACHE DEFAULT
CELL_FLASH_CACHE DEFAULT
)
NOPARALLEL;
ALTER TABLE SYS_EXP_COL ADD (
CONSTRAINT PK_SYS_EXP_COL
PRIMARY KEY
(EXP_LIST, EXP_NUM)
USING INDEX PK_SYS_EXP_COL
ENABLE VALIDATE);
4.还有一个工具类,是用来把对象集合转成map集合的,下面是这个工具类
package com.fitk.core.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import sun.misc.BASE64Decoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.*;
public class WebUtil {
/*public static <T> Map<String, Object> pageList(PageInfo<T> pageInfo) {
Map<String, Object> result = new HashMap<String, Object>(2);
if (pageInfo.getList() == null || pageInfo.getPages() == 0){
result.put("total", 0);
result.put("rows", new ArrayList<T>());
return result;
}
result.put("total", pageInfo.getTotal());
result.put("rows", pageInfo.getList());
return result;
}*/
public static <T> Map<String, Object> pageList(List<T> list) {
Map<String, Object> result = new HashMap<String, Object>(2);
if(list==null||list.size()==0){
result.put("total", 0);
result.put("rows", null);
return result;
}
result.put("total", list.size());
result.put("rows", list);
return result;
}
public static <T> Map<String, Object> pageList(List<T> list,List<T> list2) {
Map<String, Object> result = new HashMap<String, Object>(2);
if(list==null||list.size()==0){
result.put("total", 0);
result.put("rows", null);
return result;
}
result.put("total", list2.size());
result.put("rows", list);
return result;
}
/**
* 包装处理后的处理结果
* @param data data 处理后的结果集
* @param message message 返回消息
* @param errorCode errorCode 错误编码
* @return
*/
public static Map<String, Object> returnResult(Map data, String message, int errorCode) {
Map<String, Object> result = new HashMap<>();
List resultList = new ArrayList<>();
resultList.add(data);
result.put("result", resultList);
result.put("message", message);
result.put("errorCode", errorCode);
return result;
}
/**
* 包装处理后的处理结果
* @param data data 处理后的结果集
* @param message message 返回消息
* @param errorCode errorCode 错误编码
* @return
*/
public static Map<String, Object> returnResult(List data, String message, int errorCode) {
Map<String, Object> result = new HashMap<>();
result.put("result", data);
result.put("message", message);
result.put("errorCode", errorCode);
return result;
}
/**
* 包装处理后的处理结果
* @param message message 返回消息
* @param data data 处理后的结果集
* @return
*/
public static Map<String, Object> returnResult(List data, String message) {
return returnResult(data, message, 0);
}
/**
* 包装处理后的处理结果
* @param data data 处理后的结果集
* @return
*/
public static Map<String, Object> returnResult(List data) {
return returnResult(data, "操作成功!", 0);
}
/**
* 包装处理后的处理结果
* @param message message 返回消息
* @param data data 处理后的结果集
* @return
*/
public static Map<String, Object> returnResult(Map data, String message) {
return returnResult(data, message, 0);
}
/**
* 包装处理后的处理结果
* @param data data 处理后的结果集
* @return
*/
public static Map<String, Object> returnResult(Map data) {
return returnResult(data, "操作成功!", 0);
}
/**
* 包装处理后的返回消息
* @param message message 返回消息
* @param isSuccess isSuccess 是否成功
* @return
*/
public static Map<String, Object> returnMessage(String message, boolean isSuccess) {
Map<String, Object> result = new HashMap<String, Object>(1);
result.put("message", message);
result.put("result", isSuccess);
return result;
}
/**
* 包装处理后的返回消息
* @param message message 返回消息
* @param isSuccess isSuccess 是否成功
* @param errorCode 错误diamante
* @return
*/
public static Map<String, Object> returnMessage(String message, boolean isSuccess, String errorCode) {
Map<String, Object> result = new HashMap<String, Object>(1);
result.put("message", message);
result.put("result", isSuccess);
result.put("errorcode", errorCode);
return result;
}
/**
* 包装处理成功的返回消息
* @param message 返回消息
* @return
*/
public static Map<String, Object> returnSuccess(String message) {
return returnMessage(message, true);
}
/**
* 包装处理失败的返回消息
* @param message 返回消息
* @return
*/
public static Map<String, Object> returnFailure(String message) {
return returnMessage(message, false);
}
/**
* 包装处理失败的返回消息
* @param message 返回消息
* @return
*/
public static Map<String, Object> returnFailure(String message, String errorCode) {
return returnMessage(message, false, errorCode);
}
/**
* 获取前端传入排序进行包装传给Mapper
* @param map
* @param defaultSort
* @return
*/
public static Map<String, Object> getOrderby(Map<String, Object> map, String defaultSort){
// 排序 order sort
if (map.containsKey("sort")){
String orderby = "";
for(int i =0;i < map.get("sort").toString().split(",").length;i++){
if (i>0){
orderby += ",";
}
orderby += map.get("sort").toString().split(",")[i] + " " +
map.get("order").toString().split(",")[i];
}
map.put("orderby", orderby);
}else{
map.put("orderby", defaultSort);
}
return map;
}
/**
* 下载文件
* @param request
* @param response
* @param storeName
* @param contentType
* @param bzglRoute
* @throws Exception
*/
public static void download(HttpServletRequest request,
HttpServletResponse response, String storeName, String contentType,
String bzglRoute) throws Exception {
request.setCharacterEncoding("UTF-8");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
// 获取项目根目录
// String ctxPath = request.getSession().getServletContext()
// .getRealPath("");
// 获取下载文件露肩
String downLoadPath = bzglRoute + storeName;
// 获取文件的长度
long fileLength = new File(downLoadPath).length();
// 设置文件输出类型
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-disposition", "attachment; filename="
+ new String(storeName.getBytes("utf-8"), "ISO8859-1"));
// response.setHeader("Content-disposition", "attachment; filename="
// + storeName);
// 设置输出长度
response.setHeader("Content-Length", String.valueOf(fileLength));
// 获取输入流
bis = new BufferedInputStream(new FileInputStream(downLoadPath));
// 输出流
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bos.flush();
// 关闭流
bis.close();
bos.close();
}
public static void downloadNet(HttpServletRequest request,
HttpServletResponse response, String storeName,String urlNet) throws Exception {
URL url = new URL(urlNet);
request.setCharacterEncoding("UTF-8");
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
URLConnection conn = url.openConnection();
InputStream inStream = conn.getInputStream();
// String downLoadPath = bzglRoute + storeName;
// long fileLength = new File(downLoadPath).length();
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-disposition", "attachment; filename="
+ new String(storeName.getBytes("utf-8"), "ISO8859-1"));
// response.setHeader("Content-Length", String.valueOf(fileLength));
bis = new BufferedInputStream(inStream);
bos = new BufferedOutputStream(response.getOutputStream());
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bos.flush();
bis.close();
bos.close();
}
/**
* 删除单个文件
* @param sPath 被删除文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public static boolean deleteFile(String sPath) {
boolean flag = false;
File file = new File(sPath);
// 路径为文件且不为空则进行删除
if (file.isFile() && file.exists()) {
file.delete();
flag = true;
}
return flag;
}
/**
* JavaBean转换成xml
* 默认编码UTF-8
* @param obj
* @return
*/
public static String convertToXml(Object obj) {
return convertToXml(obj, "UTF-8");
}
/**
* JavaBean转换成xml
* @param obj
* @param encoding
* @return
*/
public static String convertToXml(Object obj, String encoding) {
String result = null;
try {
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
StringWriter writer = new StringWriter();
marshaller.marshal(obj, writer);
result = writer.toString();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* xml转换成JavaBean
* @param xml
* @param c
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T converyToJavaBean(String xml, Class<T> c) {
T t = null;
try {
JAXBContext context = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = context.createUnmarshaller();
t = (T) unmarshaller.unmarshal(new StringReader(xml));
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
public static final String DEF_CHATSET = "UTF-8";
public static final int DEF_CONN_TIMEOUT = 30000;
public static final int DEF_READ_TIMEOUT = 30000;
public static String userAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36";
/**
*
* @param strUrl 请求地址
* @param params 请求参数
* @param method 请求方法
* @return 网络请求字符串
* @throws Exception
*/
public static String net(String strUrl, Map params,String method) throws Exception {
HttpURLConnection conn = null;
BufferedReader reader = null;
String rs = null;
try {
StringBuffer sb = new StringBuffer();
if(method==null || method.equals("GET")){
strUrl = strUrl+"?"+urlencode(params);
}
URL url = new URL(strUrl);
conn = (HttpURLConnection) url.openConnection();
if(method==null || method.equals("GET")){
conn.setRequestMethod("GET");
}else{
conn.setRequestMethod("POST");
conn.setDoOutput(true);
}
conn.setRequestProperty("User-agent", userAgent);
conn.setUseCaches(false);
conn.setConnectTimeout(DEF_CONN_TIMEOUT);
conn.setReadTimeout(DEF_READ_TIMEOUT);
conn.setInstanceFollowRedirects(false);
conn.connect();
if (params!= null && method.equals("POST")) {
try {
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
out.writeBytes(urlencode(params));
} catch (Exception e) {
// TODO: handle exception
}
}
InputStream is = conn.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, DEF_CHATSET));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sb.append(strRead);
}
rs = sb.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
if (conn != null) {
conn.disconnect();
}
}
return rs;
}
//将map型转为请求参数型
public static String urlencode(Map<String,String> data) {
StringBuilder sb = new StringBuilder();
for (Map.Entry i : data.entrySet()) {
try {
sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue()+"","UTF-8")).append("&");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
* @Descriptionmap 对字节数组字符串进行Base64解码并生成图片
* @author
* @Date 2016-12-06
* @param base64 图片Base64数据
* @return
*/
public static byte[] base64ToImage(String base64) {// 对字节数组字符串进行Base64解码并生成图片
if (base64 == null){ // 图像数据为空
return null;
}
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解码
byte[] bytes = decoder.decodeBuffer(base64);
for (int i = 0; i < bytes.length; ++i) {
if (bytes[i] < 0) {// 调整异常数据
bytes[i] += 256;
}
}
// 生成jpeg图片
/*OutputStream out = new FileOutputStream(path);
out.write(bytes);
out.flush();
out.close();*/
return bytes;
} catch (Exception e) {
return null;
}
}
public static Object mapToObject(Map<String, Object> map, Class<?> beanClass){
Object obj=null;
if (map == null) {
return null;
}
try{
obj = beanClass.newInstance();
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
int mod = field.getModifiers();
if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
continue;
}
field.setAccessible(true);
field.set(obj, map.get(field.getName()));
}
}catch(Exception ex){
ex.printStackTrace();
}
return obj;
}
public static Map<String, Object> objectToMap(Object obj){
Map<String, Object> map = new HashMap();
try{
if(obj == null){return null;}
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields){
field.setAccessible(true);
if(field.get(obj) instanceof String){
if(field.get(obj)!=null/*&&!field.get(obj).equals("")*/){
map.put(field.getName(), field.get(obj));
}
}else if(field.get(obj) instanceof Long){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}else if(field.get(obj) instanceof Integer){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}/*else if(field.get(obj) instanceof Date){
if(field.get(obj)!=null){
map.put(field.getName(), DateFormater.DateToString((Date)field.get(obj),DateFormater.TIMEF_FORMAT));
}
}*/else if(field.get(obj) instanceof Double){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}else if(field.get(obj) instanceof Float){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}else if(field.get(obj) instanceof BigInteger){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}else if(field.get(obj) instanceof Short){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}else if(field.get(obj) instanceof BigInteger){
if(field.get(obj)!=null){
map.put(field.getName(), String.valueOf(field.get(obj)));
}
}else{
if(field.get(obj)==null){
map.put(field.getName(), "");
}
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return map;
}
}
5.下面就是测试代码,我只贴出主要部分。
fileName=filePath+fileName+".pdf";
//设置表头数据
//设置几级表头
int level=3;
int highs_header[]=new int[level];
ArrayList<float[]>columnWidths_header=new ArrayList<>();
ArrayList<String[]>columnText_header=new ArrayList<>();
//一级表头
float[] columnWidth_level0 = new float[5];
String[] columnText_level0 = new String[5];
columnWidth_level0[0]=0.2f;
columnWidth_level0[1]=0.2f;
columnWidth_level0[2]=0.2f;
columnWidth_level0[3]=0.2f;
columnWidth_level0[4]=0.2f;
columnText_level0[0]="1";
columnText_level0[1]="2";
columnText_level0[2]=version_number;
columnText_level0[3]="3";
columnText_level0[4]=modify_number;
highs_header[0]=15;
columnWidths_header.add(columnWidth_level0);
columnText_header.add(columnText_level0);
//二级表头
float[] columnWidth_level1 = new float[8];
String[] columnText_level1 = new String[8];
columnWidth_level1[0]=0.2f;
columnWidth_level1[1]=0.2f;
columnWidth_level1[2]=0.2f;
columnWidth_level1[3]=0.2f;
columnWidth_level1[4]=0.2f;
columnWidth_level1[5]=0.2f;
columnWidth_level1[6]=0.2f;
columnWidth_level1[7]=0.2f;
columnText_level1[0]="4";
columnText_level1[1]=train_type;
columnText_level1[2]="5";
columnText_level1[3]=ticket_number;
columnText_level1[4]="6";
columnText_level1[5]=ticket_name;
columnText_level1[6]="7";
columnText_level1[7]=repair_level;
highs_header[1]=15;
columnWidths_header.add(columnWidth_level1);
columnText_header.add(columnText_level1);
//三级表头
float[] columnWidth_level2 = new float[10];
String[] columnText_level2 = new String[10];
columnWidth_level2[0]=0.2f;
columnWidth_level2[1]=0.2f;
columnWidth_level2[2]=0.2f;
columnWidth_level2[3]=0.2f;
columnWidth_level2[4]=0.2f;
columnWidth_level2[5]=0.2f;
columnWidth_level2[6]=0.2f;
columnWidth_level2[7]=0.2f;
columnWidth_level2[8]=0.2f;
columnWidth_level2[9]=0.2f;
columnText_level2[0]="8";
columnText_level2[1]="9";
columnText_level2[2]="10";
columnText_level2[3]=resource_name;
columnText_level2[4]="11";
columnText_level2[5]=lie_code;
columnText_level2[6]="12";
columnText_level2[7]=car_no;
columnText_level2[8]="13";
columnText_level2[9]=zcbh;
highs_header[2]=15;
columnWidths_header.add(columnWidth_level2);
columnText_header.add(columnText_level2);
String text_footer="这是尾部啦!!!!!!";
/**
* @Description: 自定义多行表头
* @Param: outputPath 导出路径
* @Param: List<Map<String,String>> rowList 内容集合
* @Param: clazz 类型
* @Param: list_Col 数据库对应的字段及名称等
* @Param: columnWidths_all 行列宽(动态数据部分)
* @Param: highs_header[] 表头行高
* @Param: columnWidths_header ArrayList<Float[]> 表格列宽
* @Param: columnText_header《内容》 ArrayList<String[]> 表格列宽
* @return:
* @Author: sj
* @Date: 2023/12/18/018
*/
columnWidths_header.add(columnWidth_level2);
columnText_header.add(columnText_level2);
// new CreatePDFUtils1().createHardwarePDF(fileName, null, rowList, list_qlty_fact_detail.class, list_Col, columnWidths);
new CreatePDFUtils1(). createHardwarePDF(fileName, rowList,
list_Col, columnWidths,
highs_header ,columnWidths_header,columnText_header,new float[]{1f},new String[]{text_footer});
下面就是看看效果图了,数据我就不取了,因为是现场数据。第一次整合工具类还是有点提高的。