利用itextpdf导出复杂pdf表格的工具类

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});

下面就是看看效果图了,数据我就不取了,因为是现场数据。第一次整合工具类还是有点提高的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值