• 快速连接数据库整理数据导出Excel与Excel转JAVA实体工具类


    package cn.com.utils;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import javax.sql.DataSource;
    import org.apache.log4j.Logger;
    import com.jolbox.bonecp.BoneCPDataSource;
    /**
     * DBUtils工具类,提供数据库连接池对象和数据库连接对象
     */
    public enum BonecpUtils {
    
        INSTANCE;
    
        private static final Logger LOG = Logger.getLogger(BonecpUtils.class);
    
        private static final BoneCPDataSource DATA_SOURCE = new BoneCPDataSource();
    
        static {
            try {
                String driver, url, username, password;
                
                driver = "com.mysql.cj.jdbc.Driver";
                url = "jdbc:mysql://127.0.0.1:3306/dbname?characterEncoding=utf8";
                username = "root";
                password = "root";
                
                DATA_SOURCE.setDriverClass(driver);
                DATA_SOURCE.setJdbcUrl(url);
                DATA_SOURCE.setUser(username);
                DATA_SOURCE.setPassword(password);
            } catch (Exception e) {
                LOG.error("BoneCPDataSource设置加载失败!" + e);
            }
        }
    
        // 获取数据源
        public DataSource getDataSource() {
            return DATA_SOURCE;
        }
    
        // 获取连接
        public Connection getConnection() throws SQLException {
            return DATA_SOURCE.getConnection();
        }
    }
    public static void main(String[] args) throws Exception {
    
        DataSource dataSource = BonecpUtils.INSTANCE.getDataSource();
        QueryRunner qr = new QueryRunner(dataSource);
        String sql = "SELECT * FROM table_name";
        //开启下划线->驼峰转换所用
        BeanProcessor bean = new GenerousBeanProcessor();
        RowProcessor processor = new BasicRowProcessor(bean);
        // T 为具体的POJO对象,这里是伪代码
        List<T> list = qr.query(sql, new BeanListHandler<>(T.class,processor));
        // 生成Excel
        ExcelExportUtils.getInstance().export(new File("D:/result.xls"), ExcelExportUtils.Resource.getInstance(list));
    
    }
    <dependency>
        <groupId>com.jolbox</groupId>
        <artifactId>bonecp</artifactId>
        <version>0.8.0.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.20</version>
    </dependency>
    
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.7</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>4.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.9</version>
    </dependency>
    
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>compile</scope>
    </dependency>
    package cn.bevis.poi;
    
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.UnsupportedEncodingException;
    import java.lang.annotation.Annotation;
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import java.lang.reflect.Field;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFCellStyle;
    import org.apache.poi.hssf.usermodel.HSSFFont;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.hssf.util.HSSFColor.HSSFColorPredefined;
    import org.apache.poi.ss.usermodel.HorizontalAlignment;
    import org.apache.poi.ss.usermodel.VerticalAlignment;
    import org.apache.poi.ss.util.CellRangeAddress;
    
    
    
    /**
     * @ClassName ExcelExportUtils
     * @Description:基于POI的Excel导出通用方法
     * @author CP_biyongfei
     * @date 2017-8-18 下午3:56:52
     */
    public class ExcelExportUtils {
        
        private static final int PAGESIZE = 65530;
        
        private int defaultColumnWidth = 10;//默认列宽
        
        private static final short FONT_COLOR = HSSFColorPredefined.BLACK.getIndex();//默认字体颜色,黑色;
        
        private ExcelExportUtils() {
            super();
        }
    
        private ExcelExportUtils(int defaultColumnWidth) {
            super();
            this.defaultColumnWidth = defaultColumnWidth;
        }
    
        /**
         * 默认列宽是10(即10个10号汉字的宽度)
         * @return
         */
        public static ExcelExportUtils getInstance() {
            return new ExcelExportUtils();
        }
    
        /**
         * 自定义列宽(即defaultColumnWidth个10号汉字的宽度)
         * @param defaultColumnWidth
         * @return
         */
        public static ExcelExportUtils getInstance(int defaultColumnWidth) {
            return new ExcelExportUtils(defaultColumnWidth);
        }
        
        private int totalColumn;//记录列的总个数
        private Map<Integer,Integer> specialColumn = new HashMap<Integer,Integer>();
        
        /**
         * 需要单独为某一列设置列宽的方法,从0开始,第一列为0,第二列为1...
         * 可以多次调用,设定不同的列的列宽,
         * 例如:ExcelExportUtils.getInstance().setColumnWidth(1,15).setColumnWidth(2,20).export(...);
         * @param columnNum:哪一列?列数
         * @param columnWidth:列宽,默认列宽是10(即10个10号汉字的宽度)
         * @return
         */
        @SuppressWarnings("unused")
        private ExcelExportUtils setColumnWidth(int columnNum,int columnWidth) {
            specialColumn.put(columnNum, columnWidth);
            return this;
        }
        
        /**
         * @Fields specialColumnStyle : 记录values(rown)需要特殊指定文字内容左对齐的列
         */
        private List<Integer> specialColumnStyle = new ArrayList<Integer>();
        
        /**
         * @Title setColumnTextLeft
         * @Description:设置values(rown)需要特殊指定文字内容左对齐的列
         * 需要单独为某一列设置文字内容左对齐的方法,从0开始,第一列为0,第二列为1...
         * 可以多次调用,设定不同的列的列宽,
         * 例如:ExcelExportUtils.getInstance().setColumnTextLeft(1).setColumnTextLeft(2).export(...);
         * 表示第一列,第二列左对齐
         * 例如:ExcelExportUtils.getInstance().setColumnTextLeft(1,2,3).export(...);
         * 表示第一列,第二列,第三列左对齐
         * 例如:ExcelExportUtils.getInstance().setColumnTextLeft().setColumnTextLeft(2).export(...);
         * 未指定则表示居中对齐
         * @param columnNums 哪一列?列数
         * @return
         * @user CP_biyongfei 2017年9月20日
         * @updater:
         * @updateTime:
         */
        @SuppressWarnings("unused")
        private ExcelExportUtils setColumnTextLeft(int ... columnNums) {
            if(columnNums.length > 0) {
                for (int i : columnNums) {
                    specialColumnStyle.add(i);
                }
            }
            return this;
        }
    
        /**
         * @Title export
         * @Description:不指定firstHeader,默认第一列firstHeader是序号,firstValues对应的是行号
         * @param request
         * @param response
         * @param excelName 导出Excel的文件名字,也是sheet的部分名字,如果title=true,也是首行title的名字
         * @param title
         * @param header
         * @param values
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void export(HttpServletRequest request,
                HttpServletResponse response, String excelName, String sheetName, boolean title, List<String> header,
                List<List<String>> values) {
            export(request, response, excelName, sheetName, title, "序号", null, header, values);
        }
        
        /**
         * @Description:数据导出公用方法
         * @param excelName
         *               :导出Excel的文件名字,也是sheet的部分名字,如果title=true且sheetName="",也是首行title的名字
         * @Param sheetName
         *               :sheet的名字
         * @param title
         *            :文档标题行(第一行),title为true且sheetName="",首行会将excelName作为首行标题,false,title(首行)不创建,下面的内容向上偏移一行
         * @param firstHeader
         *            :序号
         * @param firstValues
         *            :1,2...
         * @param header
         *            :表格标题行(第二行)
         * @param values
         *            :表格标题行对应的值(第三行,第四行...)
         * @return
         * @user CP_biyongfei 2017-7-18
         * @updater:
         * @updateTime:
         */
        private void export(HttpServletRequest request, HttpServletResponse response, String excelName, String sheetName, boolean title, String firstHeader,
                List<String> firstValues, List<String> header,List<List<String>> values) {
            HSSFWorkbook wb = new HSSFWorkbook();
            validate(excelName, firstHeader, firstValues, header, values);
            initAndValidateSpecialColumnWidth(header);
            fillDate(wb, StringUtils.isBlank(sheetName)?excelName:sheetName, title, firstHeader, firstValues, header, values);
            try {
                responseWriteExcel(request, response, excelName, wb);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 初始化需要特殊设定列宽的列
         * @param header
         */
        private void initAndValidateSpecialColumnWidth(List<String> header) {
            this.totalColumn = header.size() + 1;//为总列数赋值
            for (Integer columnNum : specialColumn.keySet()) {
                if (columnNum > (totalColumn - 1)) {
                    throw new RuntimeException("设定列宽的列的列数超出总列数!");
                }
            }
            for (Integer columnNum : specialColumnStyle) {
                if (columnNum > (totalColumn - 1)) {
                    throw new RuntimeException("设定列宽的列的列数超出总列数!");
                }
            }
        }
    
        /**
         * @Title responseWriteExcel
         * @Description:响应并写出Excel数据
         * @param request
         * @param response
         * @param excelName
         * @param wb
         * @throws IOException
         * @throws UnsupportedEncodingException
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void responseWriteExcel(HttpServletRequest request,
                HttpServletResponse response, String excelName, HSSFWorkbook wb)
                throws IOException, UnsupportedEncodingException {
            response.reset();
            // 设置相应头信息,以附件形式下载并且指定文件名
            response.setContentType("application/msexcel;charset=UTF-8");
            String finalName = "attachment;";
            finalName += " filename="" + encodeURIComponent(request, excelName+".xls") +"";";
            finalName += " filename*=utf-8''" + encodeURIComponent(request, excelName+".xls");
            response.setHeader("Cache-Control", "must-revalidate,post-check=0,pre-check=0");
            response.setHeader("Pragma", "public");
            response.setDateHeader("Expires", (System.currentTimeMillis()+1000));
            response.setHeader("Content-Disposition", finalName);
            OutputStream os = new BufferedOutputStream(response.getOutputStream());
            wb.write(os);
            os.flush();
            os.close();
        }
        
        private void responseWriteExcel(String dirStr, String excelName, HSSFWorkbook wb)
                throws IOException, UnsupportedEncodingException {
            
            // 设置文件名
            String finalName = excelName+".xls";
            File dir = new File(dirStr);
            if(!dir.exists() || dir.isFile()) {
                dir.mkdirs();
            }
            File finalFile = new File(dir, finalName);
            FileOutputStream in = new FileOutputStream(finalFile);
            OutputStream os = new BufferedOutputStream(in);
            wb.write(os);
            os.flush();
            os.close();
        }
        
        /**
        * 根据不同的浏览器设置下载附件的文件名,防止中文名称乱码!
        * <pre>
        * 符合 RFC 3986 标准的“百分号URL编码”
        * 在这个方法里,空格会被编码成%20,而不是+
        * 和浏览器的encodeURIComponent行为一致
        * </pre>
        * @param request
        * @param filename
        * @return
        */
        private String encodeURIComponent(HttpServletRequest request, String filename) {
          try {
              String agent = request.getHeader("User-Agent").toLowerCase();
              
              if(agent.indexOf("safari") > 0){//苹果
                  return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
              } else if(agent.indexOf("firefox") > 0) {//火狐
                  return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
              } else if(agent.indexOf("chrome") > 0) {//谷歌
                  return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
              } else if(agent.indexOf("opera") > 0) {//欧朋
                  return URLEncoder.encode(filename, "UTF-8").replaceAll("\+", "%20");
              } else if(agent.indexOf("msie") > 0) {//IE
                  return URLEncoder.encode(filename, "UTF-8").replaceAll("\+", "%20");
              } else {//其他
                  return URLEncoder.encode(filename, "UTF-8").replaceAll("\+", "%20");
              }
          } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
          }
        }
    
        /**
         * @Title validate
         * @Description:检验数据
         * @param excelName
         * @param firstHeader
         * @param firstValues
         * @param header
         * @param values
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void validate(String excelName, String firstHeader,
                List<String> firstValues, List<String> header,
                List<List<String>> values) {
            if (StringUtils.isBlank(excelName)) {
                throw new RuntimeException("excelName不能为空!");
            }
    
            if (StringUtils.isBlank(firstHeader)) {
                throw new RuntimeException("firstHeader不能为空!");
            }
    
            if (!"序号".equals(firstHeader) && null == firstValues) {
                throw new RuntimeException("firstValues不能为null!");
            }
    
            if (null == header || null == values) {
                throw new RuntimeException("firstValues,header,values参数不能为null!");
            }
    
            if ((null !=firstValues && firstValues.size() == 0) || header.size() == 0 || values.size() == 0) {
                throw new RuntimeException("firstValues,header,values的size不能为0!");
            }
    
            int size = 0;
            for (int i = 0; i < values.size(); i++) {
                if (0 != i && values.get(i).size() != size) {
                    throw new RuntimeException("values里的每个list的size不相同!");
                }
                if (values.get(i).size() == 0) {
                    throw new RuntimeException("参数values里面的任何一个list的size不能为0!");
                }
                size = values.get(i).size();
            }
    
            if (header.size() != values.get(0).size()) {
                throw new RuntimeException("参数values里面的任何一个list的size与header的size不相同!");
            }
    
            if (null !=firstValues && firstValues.size() != values.size()) {
                throw new RuntimeException("参数firstValues的size与values的size不相同!");
            }
        }
        
        /**
         * @Title getIndexByPage
         * @Description:根据当前页码,每页显示条数,总条数,计算当前页的内容对应values的开始index和结束index
         * @param pagenum:当前页码
         * @param pageSize:每页显示条数
         * @param total:总条数
         * @return
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private List<Integer> getIndexByPage(int pagenum, int pageSize, int total) {
            int sindex = 0;//开始角标
            int eindex = 0;//结束角标
            if (total<=pageSize) {
                sindex = 0;
                eindex = total;
                return Arrays.asList(sindex,eindex);
            }
            int pages = total%pageSize==0?total/pageSize:(total/pageSize)+1;
            if (pagenum == pages && total%pageSize!=0) {
                sindex = (pagenum - 1)*pageSize;
                eindex = sindex+total%pageSize;
                return Arrays.asList(sindex,eindex);
            }
            sindex = (pagenum - 1)*pageSize;
            eindex = sindex+pageSize;
            return Arrays.asList(sindex,eindex);
        }
    
        
        /**
         * @Fields firstRow : 默认是title,第一行,行标0,-1表示没有title行
         */
        private int firstRowIndexOff = 0;//默认是0表示有title行,-1表示首行向上偏移一行,title行去除
        
        /**
         * @Title fillDate
         * @Description:向Excel填充数据
         * @param wb
         * @param excelName
         * @param title
         * @param firstHeader
         * @param firstValues
         * @param header
         * @param values
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void fillDate(HSSFWorkbook wb, String sheetName, boolean title, String firstHeader,
                List<String> firstValues, List<String> header,
                List<List<String>> values) {
            int total = values.size();
            int pages = total/PAGESIZE==0?1:(total%PAGESIZE==0?total/PAGESIZE:(total/PAGESIZE)+1);
            for (int i = 1; i <= pages; i++) {
                HSSFSheet sheet = wb.createSheet(sheetName+"-"+i);
                initDefaultColumnStyle(wb, sheet, totalColumn);
                if(title){
                    row0(wb, sheet, sheetName, header.size());
                } else {
                    firstRowIndexOff = -1;
                }
                row1(wb, firstHeader, header, sheet);
                List<Integer> pageinfo = getIndexByPage(i,PAGESIZE,total);
                rown(firstValues, values, sheet, pageinfo);
            }
        }
    
        /**
         * @Title rown
         * @Description:第三行,第四行...填充数据
         * @param firstValues
         * @param values
         * @param sheet
         * @param pageinfo
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void rown(List<String> firstValues,
                List<List<String>> values, HSSFSheet sheet, List<Integer> pageinfo) {
            for (int i = pageinfo.get(0); i < pageinfo.get(1); i++) {// 表格标题行对应的值(第三行,第四行...)
                HSSFRow rown = sheet.createRow(i - pageinfo.get(0) + 2 + firstRowIndexOff);
                for (int j = 0; j <= values.get(i).size(); j++) {
                    if (j != 0) {
                        rown.createCell(j).setCellValue(values.get(i).get(j - 1));
                    } else {
                        if (firstValues == null) {// 序号
                            rown.createCell(j).setCellValue(String.valueOf(i + 1));
                        } else {
                            rown.createCell(j).setCellValue(firstValues.get(i));
                        }
                    }
                }
            }
        }
    
        /**
         * @Title row1
         * @Description:第二行填充数据
         * @param wb
         * @param firstHeader
         * @param header
         * @param sheet
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void row1(HSSFWorkbook wb, String firstHeader, List<String> header,
                HSSFSheet sheet) {
            HSSFRow row1 = sheet.createRow(1 + firstRowIndexOff);
            row1.setHeightInPoints(15);//设置行高20px
            for (int i = 0; i <= header.size(); i++) {
                if (i != 0) {
                    HSSFCell cell = row1.createCell(i);
                    cell.setCellStyle(getHeaderCellStyle(wb));
                    cell.setCellValue(header.get(i - 1));// 设置第二行,表格标题行
                } else {
                    HSSFCell cell = row1.createCell(i);
                    cell.setCellStyle(getHeaderCellStyle(wb));
                    cell.setCellValue(firstHeader);// 设置第二行,表格标题行第一格
                }
            }
        }
    
        /**
         * @Title initDefaultColumnStyle
         * @Description:初始化默认样式
         * @param wb
         * @param sheet
         * @param totalColumn
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void initDefaultColumnStyle(HSSFWorkbook wb, HSSFSheet sheet, int totalColumn) {
            for (int i = 0; i < totalColumn; i++) {
                if (specialColumn.containsKey(i)) {
                    sheet.setColumnWidth(i, specialColumn.get(i) * 512);// 需要特殊指定的列宽,512*几就表示几个汉字的宽度
                } else {
                    sheet.setColumnWidth(i, defaultColumnWidth * 512);// 默认列宽,约10个汉字,512*几就表示几个汉字的宽度
                }
                if (specialColumnStyle.contains(i)) {
                    sheet.setDefaultColumnStyle(i, getSpecialValuesCellStyle(wb));
                } else {
                    sheet.setDefaultColumnStyle(i, getValuesCellStyle(wb));
                }
            }
        }
    
        /**
         * @Title row0
         * @Description:第一行填充数据
         * @param wb
         * @param sheet
         * @param excelName
         * @param titleColspan
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private void row0(HSSFWorkbook wb, HSSFSheet sheet, String excelName,
                int titleColspan) {
            HSSFRow row0 = sheet.createRow(firstRowIndexOff);
            row0.setHeightInPoints(20);//设置行高20px
            HSSFCell cell = row0.createCell(0);
            cell.setCellStyle(getTitleCellStyle(wb));
            cell.setCellValue(excelName);
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, titleColspan));// 设置第一行,标题行
        }
    
        /**
         * @Title getTitleCellStyle
         * @Description:定义title样式
         * @param wb
         * @return
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private HSSFCellStyle getTitleCellStyle(HSSFWorkbook wb) {//定义title样式
            HSSFFont font = wb.createFont();
            font.setFontHeightInPoints((short) 16);
            font.setColor(FONT_COLOR);
            HSSFCellStyle cellStyle = wb.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setFont(font);
            cellStyle.setWrapText(true);//自动换行
            //cellStyle.setFillBackgroundColor(HSSFColor.CORAL.index);
            return cellStyle;
        }
    
        /**
         * @Title getHeaderCellStyle
         * @Description:定义header的样式
         * @param wb
         * @return
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private HSSFCellStyle getHeaderCellStyle(HSSFWorkbook wb) {//定义header的样式
            HSSFFont font = wb.createFont();
            font.setBold(true);//加粗字体
            font.setFontHeightInPoints((short) 12);
            font.setColor(FONT_COLOR);
            HSSFCellStyle cellStyle = wb.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setFont(font);
            cellStyle.setWrapText(true);//自动换行
            return cellStyle;
        }
        
        /**
         * @Title getValuesCellStyle
         * @Description:定义values的样式(居中对齐)
         * @param wb
         * @return
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private HSSFCellStyle getValuesCellStyle(HSSFWorkbook wb) {//定义values的样式
            HSSFFont font = wb.createFont();
            font.setFontHeightInPoints((short) 10);
            font.setColor(FONT_COLOR);
            HSSFCellStyle cellStyle = wb.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setFont(font);
            cellStyle.setWrapText(true);//自动换行
            return cellStyle;
        }
        
        /**
         * @Title getSpecialValuesCellStyle
         * @Description:定义values的样式(左对齐)
         * @param wb
         * @return
         * @user CP_biyongfei 2017-8-18
         * @updater:
         * @updateTime:
         */
        private HSSFCellStyle getSpecialValuesCellStyle(HSSFWorkbook wb) {//定义values的样式
            HSSFFont font = wb.createFont();
            font.setFontHeightInPoints((short) 10);
            font.setColor(FONT_COLOR);
            HSSFCellStyle cellStyle = wb.createCellStyle();
            cellStyle.setAlignment(HorizontalAlignment.LEFT);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            cellStyle.setFont(font);
            cellStyle.setWrapText(true);//自动换行
            return cellStyle;
        }
        
        /**
         * @ClassName ExcelUtilsFields
         * @Description: 自定义注解
         * @author CP_biyongfei
         * @date 2017-8-31 下午3:50:58
         */
        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public static @interface ExcelExport {
            /**
             * @Title excelName
             * @Description:导出Excel的文件名字,也是sheet的部分名字,如果title=true,也是首行title的名字
             * @return
             * @user CP_biyongfei 2017-8-31
             * @updater:
             * @updateTime:
             */
            public String excelName();
            
            /**
             * @Title sheetName
             * @Description:sheet的名字
             * @return
             * @user CP_biyongfei 2017年9月26日
             * @updater:
             * @updateTime:
             */
            public String sheetName();
            
            /**
             * @Title title
             * @Description:是否显示创建,文档标题行(第一行),默认为true,表示创建
             * @return
             * @user CP_biyongfei 2017年9月21日
             * @updater:
             * @updateTime:
             */
            public boolean title() default true;
            /**
             * @Title firstHeader
             * @Description:表格标题行(第二行,第一列)默认序号
             * @return
             * @user CP_biyongfei 2017-8-31
             * @updater:
             * @updateTime:
             */
            public String firstHeader() default "序号";
            /**
             * @Title firstValues
             * @Description:可以不赋值,不赋值即null。
             * 表格标题行(第二行,第一列),对应表格中第二行下面第一列的值
             * @return
             * @user CP_biyongfei 2017-8-31
             * @updater:
             * @updateTime:
             */
            public String[] firstValues() default {};
            /**
             * @Title header
             * @Description:表格标题行(第二行),导出的Excel将按照你填写的顺序
             * @return
             * @user CP_biyongfei 2017-8-31
             * @updater:
             * @updateTime:
             */
            public String[] header();
            /**
             * @Title field
             * @Description:List<T> 类型数据,T 对象fieldNames, 需要和header一一对应
             * @return
             * @user CP_biyongfei 2017-8-31
             * @updater:
             * @updateTime:
             */
            public String[] fieldNames();
        }
        
        /**
         * 多值时需要特殊指定的列宽的注解
         * 多值时需要特殊指定的内容左对齐的列的注解
         * @author bevis
         */
        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public static @interface SpecialColumn {
            
            /**
             * 定义格式如下:"0-15,1-20,...,5-10"
             * 表示第0列15个汉字宽,第1列20个汉字宽,...,第5列10个汉字宽(10号汉字)
             * @return
             */
            public String value() default "0-5";
            
            /**
             * 例如:居左对其,不设置默认居中
             * columnLeft={0,1,7},表示第0,1,7列居左对齐
             */
            public int[] columnLeft() default {};
            
        }
        
        private List<Map<Integer,Integer>> mSpecialColumnWidth = new ArrayList<Map<Integer,Integer>>();
        private List<List<Integer>> mSpecialColumnStyle = new ArrayList<List<Integer>>();
        
        /**
         * @Title export
         * @Description:根据List<T> 数据格式,以及注解,导出Excel
         * 注解使用示例:@@ExcelExport(title="文档标题",header={"标题一","标题二"},fieldNames={"field1","field2"})
         * 此注解只能使用在导出的方法上,并且export(HttpServletResponse response, List<T> result)方法必须由该 导出方法 直接调用
         * fieldNames,是T对象的field的名字的数组,导出后即header的标题一,标题二...对应的值
         * 
         * 快速入门:
         * 
         *  package zz.cn.bevis.test;
         *    
         *    import cn.bevis.poi.ExcelExportUtils.ExcelExportUtilsAnnotation;
         *    
         *  @SpecialColumn(value="0-5,1-7",columnLeft={0,1,7}) 设置列宽以及居左对齐,可选
         *    @ExcelExport(excelName="测试文档",header={"班级英语","班级语文","班级数学"},fieldNames={"c","a","b"})
         *    public class Person {
         *        private String a = "语文85";
         *        private String b = "数学90";
         *        private String c = "英语99";
         *        public String getA() {
         *            return a;
         *        }
         *        public void setA(String a) {
         *            this.a = a;
         *        }
         *        public String getB() {
         *            return b;
         *        }
         *        public void setB(String b) {
         *            this.b = b;
         *        }
         *        public String getC() {
         *            return c;
         *        }
         *        public void setC(String c) {
         *            this.c = c;
         *        }
         *        @Override
         *        public String toString() {
         *            return "Person [a=" + a + ", b=" + b + ", c=" + c + "]";
         *        }
         *    }
         *    
         *    Servlet 请求示例
         *    
         *    package zz.cn.bevis.servlet;
         *    
         *    import java.io.IOException;
         *    import java.util.ArrayList;
         *    import java.util.List;
         *    import javax.servlet.ServletException;
         *    import javax.servlet.http.HttpServlet;
         *    import javax.servlet.http.HttpServletRequest;
         *    import javax.servlet.http.HttpServletResponse;
         *    import zz.cn.bevis.test.Person;
         *    import cn.bevis.poi.ExcelExportUtils;
         *    
         *    public class TestServlet extends HttpServlet {
         *    
         *        private static final long serialVersionUID = -8023831766863687042L;
         *    
         *        @Override
         *        protected void doGet(HttpServletRequest request,
         *                HttpServletResponse response) throws ServletException, IOException {
         *            
         *            
         *            List<Person> result = new ArrayList<Person>();
         *            result.add(new Person());
         *            ExcelExportUtils.getInstance().export(request,response,result);
         *    
         *        }
         *    }
         * 
         * @param request
         * @param response
         * @param result
         * @user CP_biyongfei 2017-8-31
         * @updater:
         * @updateTime:
         */
        @SuppressWarnings({ "unused", "unchecked" })
        private <T> void export(HttpServletRequest request, HttpServletResponse response, List<T> result) {
            try {
                if (null == result || result.size() <= 0) {
                    export(request, response, "查询无结果", "查询无结果", true, Arrays.asList("查询无结果"), Arrays.asList(Arrays.asList("查询无结果")));
                } else {
                    if (null == response) {
                        throw new RuntimeException("参数response不能为null!");
                    }
                    
                    //获取实体类上的注解
                    Annotation annotation = result.get(0).getClass().getAnnotation(ExcelExport.class);
                    ExcelExport ann = (ExcelExport)annotation;
                    
                    if (null == ann) {
                        throw new RuntimeException("List<T> result T对象类上需要@ExcelExport注解!");
                    }
                    
                    String excelName = ann.excelName();
                    String sheetName = ann.sheetName();
                    boolean title = ann.title();
                    String firstHeader = ann.firstHeader();
                    String[] firstValues = ann.firstValues();
                    String[] header = ann.header();
                    String[] fieldNames = ann.fieldNames();
                    
                    List<List<String>> values = new ArrayList<List<String>>();
                    
                    for (T t : result) {
                        List<String> line = new ArrayList<String>();
                        for (String fieldName : fieldNames) {
                            Field field = t.getClass().getDeclaredField(fieldName);
                            field.setAccessible(true);//对私有方法解除安全限制
                            Object object = field.get(t);
                            line.add(null==object?"":object.toString());
                        }
                        values.add(line);
                    }
                    export(request, response, excelName, sheetName, title, firstHeader, firstValues.length==0?null:Arrays.asList(firstValues), Arrays.asList(header), values);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        /**
         * @Description:多数据导出公用方法
         * @param excelName
         *               :导出Excel的文件名字,也是sheet的部分名字
         * @param titles
         *               :是否显示title行(集合)
         * @param sheetNames(集合)
         *               :导出excel的sheetName定义
         * @param mheader(集合)
         *            :表格标题行(第二行)
         * @param mvalues(集合)
         *            :表格标题行对应的值(第三行,第四行...)
         * @return
         * @user CP_biyongfei 2017-7-18
         * @updater:
         * @updateTime:
         */
        @SuppressWarnings("unused")
        private void export(HttpServletRequest request, HttpServletResponse response, String excelName, List<Boolean> titles, 
                List<String> sheetNames, List<List<String>> mheader,List<List<List<String>>> mvalues) {
            List<String> mfirstHeader = new ArrayList<String>();
            List<List<String>> mfirstValues = new ArrayList<List<String>>();
            for (int i = 0; i < sheetNames.size(); i++) {
                mfirstHeader.add("序号");
                mfirstValues.add(null);
            }
            export(request, response, excelName, titles, mfirstHeader, mfirstValues, sheetNames, mheader, mvalues);
        }
        
        /**
         * @Description:多数据导出公用方法
         * @param excelName
         *               :导出Excel的文件名字,也是sheet的部分名字
         * @param titles
         *               :是否显示title行(集合)
         * @param sheetNames(集合)
         *               :导出excel的sheetName定义
         * @param mfirstHeader(集合)
         *            :序号
         * @param mfirstValues(集合)
         *            :1,2...
         * @param mheader(集合)
         *            :表格标题行(第二行)
         * @param mvalues(集合)
         *            :表格标题行对应的值(第三行,第四行...)
         * @return
         * @user CP_biyongfei 2017-7-18
         * @updater:
         * @updateTime:
         */
        private void export(HttpServletRequest request, HttpServletResponse response, String excelName, List<Boolean> titles, 
                List<String> mfirstHeader, List<List<String>> mfirstValues,
                List<String> sheetNames, List<List<String>> mheader,List<List<List<String>>> mvalues) {
            if(null == sheetNames || null == mfirstHeader || null == mfirstValues) {
                throw new RuntimeException("sheetNames,mfirstHeader,mfirstValues不能为null!");
            } else if(sheetNames.size() == 0 || sheetNames.size() != mheader.size() 
                      || sheetNames.size() != mvalues.size() || sheetNames.size() != titles.size()
                      || sheetNames.size() != mfirstHeader.size() || sheetNames.size() != mfirstValues.size()) {
                throw new RuntimeException("sheetNames.size()需要大于0并且sheetNames.size()需要等于mheader.size()且等于mvalues.size()且等于titles.size()且等于mfirstHeader.size()且等于mfirstValues.size()!");
            }
            HSSFWorkbook wb = new HSSFWorkbook();
            for (int i = 0; i < mheader.size(); i++) {
                String firstHeader = mfirstHeader.get(i);
                List<String> firstValues = mfirstValues.get(i);
                List<String> header = mheader.get(i);
                List<List<String>> values = mvalues.get(i);
                String sheetName = sheetNames.get(i);
                if(StringUtils.isBlank(sheetName)) {
                    throw new RuntimeException("sheetName不能为null!");
                }
                validate(excelName, firstHeader, firstValues, header, values);
                initAndValidateSpecialColumnWidth(header);
                if(null!=mSpecialColumnWidth&&mSpecialColumnWidth.size()==mheader.size()){
                    specialColumn.clear();
                    specialColumn.putAll(mSpecialColumnWidth.get(i));
                    specialColumnStyle.clear();
                    specialColumnStyle.addAll(mSpecialColumnStyle.get(i));
                }
                fillDate(wb, sheetName, titles.get(i), firstHeader, firstValues, header, values);
            }
            try {
                responseWriteExcel(request, response, excelName, wb);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        private void export(String dirStr, String excelName, List<Boolean> titles, 
                List<String> mfirstHeader, List<List<String>> mfirstValues,
                List<String> sheetNames, List<List<String>> mheader,List<List<List<String>>> mvalues) {
            if(null == sheetNames || null == mfirstHeader || null == mfirstValues) {
                throw new RuntimeException("sheetNames,mfirstHeader,mfirstValues不能为null!");
            } else if(sheetNames.size() == 0 || sheetNames.size() != mheader.size() 
                      || sheetNames.size() != mvalues.size() || sheetNames.size() != titles.size()
                      || sheetNames.size() != mfirstHeader.size() || sheetNames.size() != mfirstValues.size()) {
                throw new RuntimeException("sheetNames.size()需要大于0并且sheetNames.size()需要等于mheader.size()且等于mvalues.size()且等于titles.size()且等于mfirstHeader.size()且等于mfirstValues.size()!");
            }
            HSSFWorkbook wb = new HSSFWorkbook();
            for (int i = 0; i < mheader.size(); i++) {
                String firstHeader = mfirstHeader.get(i);
                List<String> firstValues = mfirstValues.get(i);
                List<String> header = mheader.get(i);
                List<List<String>> values = mvalues.get(i);
                String sheetName = sheetNames.get(i);
                if(StringUtils.isBlank(sheetName)) {
                    throw new RuntimeException("sheetName不能为null!");
                }
                validate(excelName, firstHeader, firstValues, header, values);
                initAndValidateSpecialColumnWidth(header);
                if(null!=mSpecialColumnWidth&&mSpecialColumnWidth.size()==mheader.size()){
                    specialColumn.clear();
                    specialColumn.putAll(mSpecialColumnWidth.get(i));
                    specialColumnStyle.clear();
                    specialColumnStyle.addAll(mSpecialColumnStyle.get(i));
                }
                fillDate(wb, sheetName, titles.get(i), firstHeader, firstValues, header, values);
            }
            try {
                responseWriteExcel(dirStr, excelName, wb);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        @SuppressWarnings("rawtypes")
        public static final class Resource {
            private List<List> mresults = new ArrayList<List>();
            private Resource(List ... results) {
                for (List result : results) {
                    mresults.add(result);
                }
            }
            public static final Resource getInstance(List ... results) {
                return new Resource(results);
            }
            public final List<List> getResults() {
                return mresults;
            }
        }
        
        
        /**
         * @Title export
         * @Description:多数据导出注解方法
         * 
         * @Description:根据List<T> 数据格式,以及注解,导出Excel
         * 注解使用示例:@@ExcelExport(title="文档标题",header={"标题一","标题二"},fieldNames={"field1","field2"})
         * 此注解只能使用在导出的方法上,并且export(HttpServletResponse response, List<T> result)方法必须由该 导出方法 直接调用
         * fieldNames,是T对象的field的名字的数组,导出后即header的标题一,标题二...对应的值
         * 
         * 快速入门:
         * 
         *  package zz.cn.bevis.test;
         *    
         *    import cn.bevis.poi.ExcelExportUtils.ExcelExportUtilsAnnotation;
         *
         *    @SpecialColumn(value="0-5,1-7",columnLeft={0,1,7}) 设置列宽以及居左对齐,可选
         *    @ExcelExport(excelName="测试文档",header={"班级英语","班级语文","班级数学"},fieldNames={"c","a","b"})
         *    public class Person {
         *        private String a = "语文85";
         *        private String b = "数学90";
         *        private String c = "英语99";
         *        public String getA() {
         *            return a;
         *        }
         *        public void setA(String a) {
         *            this.a = a;
         *        }
         *        public String getB() {
         *            return b;
         *        }
         *        public void setB(String b) {
         *            this.b = b;
         *        }
         *        public String getC() {
         *            return c;
         *        }
         *        public void setC(String c) {
         *            this.c = c;
         *        }
         *        @Override
         *        public String toString() {
         *            return "Person [a=" + a + ", b=" + b + ", c=" + c + "]";
         *        }
         *    }
         *    
         *    Servlet 请求示例
         *    
         *    package zz.cn.bevis.servlet;
         *    
         *    import java.io.IOException;
         *    import java.util.ArrayList;
         *    import java.util.List;
         *    import javax.servlet.ServletException;
         *    import javax.servlet.http.HttpServlet;
         *    import javax.servlet.http.HttpServletRequest;
         *    import javax.servlet.http.HttpServletResponse;
         *    import zz.cn.bevis.test.Person;
         *    import cn.bevis.poi.ExcelExportUtils;
         *  import cn.bevis.poi.ExcelExportUtils.Resource;
         *    
         *    public class TestServlet extends HttpServlet {
         *    
         *        private static final long serialVersionUID = -8023831766863687042L;
         *    
         *        @Override
         *        protected void doGet(HttpServletRequest request,
         *                HttpServletResponse response) throws ServletException, IOException {
         *            
         *            
         *            List<Person> result = new ArrayList<Person>();
         *            result.add(new Person());
         *          
         *          Resource resource = new Resource().getInstance(result);//一个或多个list都支持
         *            ExcelExportUtils.getInstance().export(request,response,resource);
         *    
         *        }
         *    }
         * 
         * @param results
         * @param request
         * @param response
         * @user CP_biyongfei 2017年9月26日
         * @updater:
         * @updateTime:
         */
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public void export(HttpServletRequest request, HttpServletResponse response, Resource mres) {
            String mexcelName = "";
            List<Boolean> titles = new ArrayList<Boolean>();
            List<String> sheetNames = new ArrayList<String>();
            List<String> mfirstHeader = new ArrayList<String>();
            List<List<String>> mfirstValues = new ArrayList<List<String>>();
            List<List<String>> mheader = new ArrayList<List<String>>();
            List<List<List<String>>> mvalues = new ArrayList<List<List<String>>>();
            try {
                List<List> results = mres.getResults();
                for (int i = 0; i < results.size(); i++) {
                    List result = results.get(i);
                    if (null == result || result.size() <= 0) {
                        if(i != (results.size()-1)) {
                            titles.add(true);
                            sheetNames.add("查询无结果-"+i);
                            mfirstHeader.add("序号");
                            mfirstValues.add(null);
                            mheader.add(Arrays.asList("查询无结果"));
                            mvalues.add(Arrays.asList(Arrays.asList("查询无结果")));
                        } else {
                            titles.add(true);
                            sheetNames.add("查询无结果-"+i);
                            mfirstHeader.add("序号");
                            mfirstValues.add(null);
                            mheader.add(Arrays.asList("查询无结果"));
                            mvalues.add(Arrays.asList(Arrays.asList("查询无结果")));
                            mexcelName = StringUtils.isBlank(mexcelName)?"查询无结果":mexcelName;
                        }
                    } else {
                        if (null == response) {
                            throw new RuntimeException("参数response不能为null!");
                        }
                        //获取实体类上的注解
                        Annotation annotation = result.get(0).getClass().getAnnotation(ExcelExport.class);
                        ExcelExport ann = (ExcelExport)annotation;
                        
                        if (null == ann) {
                            throw new RuntimeException("List<T> result T对象类上需要@ExcelExport注解!");
                        }
                        //处理需要特殊指定的列宽
                        Annotation specannotation = result.get(0).getClass().getAnnotation(SpecialColumn.class);
                        SpecialColumn specann = (SpecialColumn)specannotation;
                        if (null != specann) {
                            Map<Integer, Integer> specwidthmap = new HashMap<Integer, Integer>();
                            String specvalue = specann.value();
                            if (StringUtils.isNotBlank(specvalue)) {
                                String[] specmap = specvalue.split(",");
                                for (String spm : specmap) {
                                    String[] sma = spm.split("-");
                                    specwidthmap.put(Integer.valueOf(sma[0]), Integer.valueOf(sma[1]));
                                }
                                mSpecialColumnWidth.add(specwidthmap);
                            } else {
                                mSpecialColumnWidth.add(new HashMap<Integer,Integer>());
                            }
                            int[] specLeft = specann.columnLeft();
                            List<Integer> specLeftList = new ArrayList<Integer>();
                            for (Integer spi : specLeft) {
                                specLeftList.add(spi);
                            }
                            mSpecialColumnStyle.add(specLeftList);
                        } else {
                            mSpecialColumnWidth.add(new HashMap<Integer,Integer>());
                            mSpecialColumnStyle.add(new ArrayList<Integer>());
                        }
                        //处理excel相关数据
                        String excelName = ann.excelName();
                        if(i != 0 && StringUtils.isNotBlank(excelName) && !excelName.equals(mexcelName)) {
                            throw new RuntimeException("List<T> result T对象类上@ExcelExport注解excelName的值不一致");
                        } else {
                            if(StringUtils.isBlank(excelName)) {
                                throw new RuntimeException("List<T> result T对象类上@ExcelExport注解excelName不能为空");
                            }
                        }
                        mexcelName = excelName;
                        String sheetName = ann.sheetName();
                        if(StringUtils.isBlank(sheetName)) {
                            throw new RuntimeException("List<T> result T对象类上需要@ExcelExport注解!sheetName需要指定");
                        }
                        sheetNames.add(sheetName);
                        boolean title = ann.title();
                        titles.add(title);
                        String firstHeader = ann.firstHeader();
                        mfirstHeader.add(firstHeader);
                        String[] firstValues = ann.firstValues();
                        if(firstValues.length == 0) {
                            mfirstValues.add(null);
                        } else {
                            mfirstValues.add(Arrays.asList(firstValues));
                        }
                        String[] header = ann.header();
                        mheader.add(Arrays.asList(header));
                        String[] fieldNames = ann.fieldNames();
                        List<List<String>> values = new ArrayList<List<String>>();
                        for (Object t : result) {
                            List<String> line = new ArrayList<String>();
                            for (String fieldName : fieldNames) {
                                Field field = t.getClass().getDeclaredField(fieldName);
                                field.setAccessible(true);//对私有方法解除安全限制
                                Object object = field.get(t);
                                if(object instanceof Date) {
                                    line.add(null==object?"":new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(object));
                                } else {
                                    line.add(null==object?"":object.toString());
                                }
                            }
                            values.add(line);
                        }
                        mvalues.add(values);
                    }
                }
                export(request, response, mexcelName, titles, mfirstHeader, mfirstValues, sheetNames, mheader, mvalues);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public void export(String dirStr, Resource mres) {
            String mexcelName = "";
            List<Boolean> titles = new ArrayList<Boolean>();
            List<String> sheetNames = new ArrayList<String>();
            List<String> mfirstHeader = new ArrayList<String>();
            List<List<String>> mfirstValues = new ArrayList<List<String>>();
            List<List<String>> mheader = new ArrayList<List<String>>();
            List<List<List<String>>> mvalues = new ArrayList<List<List<String>>>();
            try {
                List<List> results = mres.getResults();
                for (int i = 0; i < results.size(); i++) {
                    List result = results.get(i);
                    if (null == result || result.size() <= 0) {
                        if(i != (results.size()-1)) {
                            titles.add(true);
                            sheetNames.add("查询无结果-"+i);
                            mfirstHeader.add("序号");
                            mfirstValues.add(null);
                            mheader.add(Arrays.asList("查询无结果"));
                            mvalues.add(Arrays.asList(Arrays.asList("查询无结果")));
                        } else {
                            titles.add(true);
                            sheetNames.add("查询无结果-"+i);
                            mfirstHeader.add("序号");
                            mfirstValues.add(null);
                            mheader.add(Arrays.asList("查询无结果"));
                            mvalues.add(Arrays.asList(Arrays.asList("查询无结果")));
                            mexcelName = StringUtils.isBlank(mexcelName)?"查询无结果":mexcelName;
                        }
                    } else {
                        
                        //获取实体类上的注解
                        Annotation annotation = result.get(0).getClass().getAnnotation(ExcelExport.class);
                        ExcelExport ann = (ExcelExport)annotation;
                        
                        if (null == ann) {
                            throw new RuntimeException("List<T> result T对象类上需要@ExcelExport注解!");
                        }
                        //处理需要特殊指定的列宽
                        Annotation specannotation = result.get(0).getClass().getAnnotation(SpecialColumn.class);
                        SpecialColumn specann = (SpecialColumn)specannotation;
                        if (null != specann) {
                            Map<Integer, Integer> specwidthmap = new HashMap<Integer, Integer>();
                            String specvalue = specann.value();
                            if (StringUtils.isNotBlank(specvalue)) {
                                String[] specmap = specvalue.split(",");
                                for (String spm : specmap) {
                                    String[] sma = spm.split("-");
                                    specwidthmap.put(Integer.valueOf(sma[0]), Integer.valueOf(sma[1]));
                                }
                                mSpecialColumnWidth.add(specwidthmap);
                            } else {
                                mSpecialColumnWidth.add(new HashMap<Integer,Integer>());
                            }
                            int[] specLeft = specann.columnLeft();
                            List<Integer> specLeftList = new ArrayList<Integer>();
                            for (Integer spi : specLeft) {
                                specLeftList.add(spi);
                            }
                            mSpecialColumnStyle.add(specLeftList);
                        } else {
                            mSpecialColumnWidth.add(new HashMap<Integer,Integer>());
                            mSpecialColumnStyle.add(new ArrayList<Integer>());
                        }
                        //处理excel相关数据
                        String excelName = ann.excelName();
                        if(i != 0 && StringUtils.isNotBlank(excelName) && !excelName.equals(mexcelName)) {
                            throw new RuntimeException("List<T> result T对象类上@ExcelExport注解excelName的值不一致");
                        } else {
                            if(StringUtils.isBlank(excelName)) {
                                throw new RuntimeException("List<T> result T对象类上@ExcelExport注解excelName不能为空");
                            }
                        }
                        mexcelName = excelName;
                        String sheetName = ann.sheetName();
                        if(StringUtils.isBlank(sheetName)) {
                            throw new RuntimeException("List<T> result T对象类上需要@ExcelExport注解!sheetName需要指定");
                        }
                        sheetNames.add(sheetName);
                        boolean title = ann.title();
                        titles.add(title);
                        String firstHeader = ann.firstHeader();
                        mfirstHeader.add(firstHeader);
                        String[] firstValues = ann.firstValues();
                        if(firstValues.length == 0) {
                            mfirstValues.add(null);
                        } else {
                            mfirstValues.add(Arrays.asList(firstValues));
                        }
                        String[] header = ann.header();
                        mheader.add(Arrays.asList(header));
                        String[] fieldNames = ann.fieldNames();
                        List<List<String>> values = new ArrayList<List<String>>();
                        for (Object t : result) {
                            List<String> line = new ArrayList<String>();
                            for (String fieldName : fieldNames) {
                                Field field = t.getClass().getDeclaredField(fieldName);
                                field.setAccessible(true);//对私有方法解除安全限制
                                Object object = field.get(t);
                                if(object instanceof Date) {
                                    line.add(null==object?"":new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(object));
                                } else {
                                    line.add(null==object?"":object.toString());
                                }
                            }
                            values.add(line);
                        }
                        mvalues.add(values);
                    }
                }
                export(dirStr, mexcelName, titles, mfirstHeader, mfirstValues, sheetNames, mheader, mvalues);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    package cn.bevis.poi;
    
    import org.apache.poi.ss.usermodel.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import java.lang.reflect.Field;
    import java.text.DecimalFormat;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    
    import static org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted;
    
    /**
     * 首行作为表格标题,不解析
     *
     *
     * @Description: Excel操作工具
     * @author: bevis
     *
     */
    public class ExcelImportUtils {
    
        private static Logger logger = LoggerFactory.getLogger(ExcelImportUtils.class);
    
        public static <T> List<T> importExcel(File file, Class<T> tClass) {
            List<T> tList = new ArrayList<T>();
            InputStream inputStream = null;
            Workbook workbook = null;
            int errorRow = 0;
            try {
                inputStream = new FileInputStream(file);
                //1.创建HSSFWorkbook对象
                workbook = WorkbookFactory.create(inputStream);
                //获取第一个sheet
                Sheet sheet = workbook.getSheetAt(0);
                //3.获取sheet中行数
                int physicalNumberOfRows = sheet.getPhysicalNumberOfRows();
                T instance = null;
                boolean isNull = false;
                for (int j = 0; j < physicalNumberOfRows; j++) {
                    if (j == 0) {
                        continue;//标题行
                    }
                    errorRow = j;
                    //4.获取行
                    Row row = sheet.getRow(j);
                    if (isRowEmpty(row)) {
                        break;
                    }
                    instance = tClass.newInstance();
                    //5.获取行中单元格
                    int lastCellNum = row.getLastCellNum();
                    Object value = null;
                    for (int k = 0; k < lastCellNum; k++) {
                        Cell cell = row.getCell(k);
                        if (Objects.nonNull(cell)) {
                            if (cell.getCellType() == CellType.BLANK) {
                                continue;
                            } else if (cell.getCellType() == CellType.NUMERIC) {
                                if (isCellDateFormatted(cell)) {
                                    // 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)
                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                                    value = cell.getDateCellValue();
                                    value = sdf.format(value);
                                } else {
                                    value = cell.getNumericCellValue();
                                    value = new DecimalFormat("#").format(value);
                                }
                            } else {
                                value = cell.getStringCellValue();
                            }
                        } else {
                            value = "";
                        }
                        Field[] fields = tClass.getDeclaredFields();
                        for (Field field : fields) {
                            if (field.isAnnotationPresent(ExcelColumn.class)) {
                                ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
                                int position = annotation.position();
                                if (position == 0) {
                                    if (value == null) {
                                        isNull = true;
                                        break;
                                    }
                                }
                                //注解中的position和单元格中的列匹配上
                                if (annotation.position() == k) {
                                    field.setAccessible(true);
                                    field.set(instance, value);
                                    break;
                                }
                            }
                        }
                        if (isNull) {
                            break;
                        }
                    }
                    if (isNull) {
                        break;
                    }
                    tList.add(instance);
                }
            } catch (IllegalAccessException e) {
                logger.error(e.getMessage() + "错误行数:" + errorRow);
            } catch (InstantiationException e) {
                logger.error(e.getMessage() + "错误行数:" + errorRow);
            } catch (IOException e) {
                logger.error(e.getMessage() + "错误行数:" + errorRow);
            } finally {
                if (null != inputStream) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != workbook) {
                    try {
                        workbook.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return tList;
        }
    
        // 校验空行
        public static boolean isRowEmpty(Row row) {
            for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {
                Cell cell = row.getCell(c);
                if (Objects.nonNull(cell) && cell.getCellType() != CellType.BLANK) {
                    return false;
                }
            }
            return true;
        }
    
        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        public @interface ExcelColumn {
            // excel表格一行中列的角标值,从0开始
            int position();
        }
    }
  • 相关阅读:
    黄聪:WordPress动作钩子函数add_action()、do_action()源码解析
    黄聪:使用WORDPRESS自带AJAX方法
    黄聪:get_posts 函数 | wordpress
    黄聪:wordpress伪静态的原理
    黄聪:wordpress如何开启文章格式post format
    黄聪:Xmind修改默认字体风格设置
    黄聪:让WordPress主题支持语言本地化(使用poedit软件实现中文翻译功能)
    ArcGIS Pro二次开发-选择gdb
    arcgis pro2.5 改变地图范围
    创建用户SQL
  • 原文地址:https://www.cnblogs.com/bevis-byf/p/13133403.html
Copyright © 2020-2023  润新知