A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本文讲解关于使用java导出excel的方法。主要针对POJO对象以及Mongodb返回的BsonDocument数据类型。

导出excel,这里实现的方法,默认只有一行表头信息,如果表头有多级则无法使用。最主要的是讲解如何导出excel以及给某些字段加上超链接。

使用到的模型类:

package sora.test.exampl;

/**
* 键值对模型
* 主要针对导出,笔者在这里就解释一下这个模型类到底怎么赋值
* 导出的Excel一般情况下都是第一行是标题,比如:姓名,年龄,性别,名族,学校等中文标题,
* 但是我们的POJO对象的属性不可能用中文命名,一般都是:name,age,gender,nation,scholl
* 所以,利用这个模型,把POJO对象的属性名和标题对应起来,
* 比如第一个字段,那么KeyValueVO对象里面,key就是name,value就是姓名
* @author sora
*
*/
public class KeyValueVO {
       
        private String key;
       
        private String value;

        public String getKey() {
                return key;
        }

        public void setKey(String key) {
                this.key = key;
        }

        public String getValue() {
                return value;
        }

        public void setValue(String value) {
                this.value = value;
        }
       
}
导出工具类代码:

/**
* Excel文件导出工具类
* 主要针对POJO对象以及BsonDocument类型的导出
* 导出Excel使用第一行为标题,第二行开始为正文数据,可以给字段加超链接
* @author sora
*
*/
public class ExcelExportUtil {
       
        private static final int TWO_HUNDRED_FIFTY_SIX = 256;
       
        private static final int FOUR = 4;
       
        private static final int THREE = 3;
       
        private static final int TWO = 2;
       
        /**
         * 导出excel表格数据
         * @param datas 需要导出的数据模型集合
         * @param specialFields 需要特殊处理的字段,比如这个字段需要加上超链接
         * @param excelName 导出Excel文件名
         * @param tableHeaders 表格数据模型与表头信息键值对
         * @param response 响应
         */
        public static <T> void excelExport(List<T> datas, List<KeyValueVO> specialFields, String excelName,
                        List<KeyValueVO> tableHeaders, HttpServletResponse response)
        {
                //如果需要导出的数据或者表头信息为空等,则返回
                if (null == datas || datas.isEmpty() || tableHeaders == null || tableHeaders.isEmpty())
                {
                        return;
                }
                try
                {
                        excelName = new String(excelName.getBytes("UTF-8"),"ISO-8859-1");
                }
                catch (Exception e1)
                {
                        e1.printStackTrace();
                }
               
                response.setCharacterEncoding("utf-8");
               
                try
                {
                        writeExcel(datas,specialFields,excelName,tableHeaders,response);
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }
       
        /**
         *  写入数据
         * @param datas 数据
         * @param specialFields 需要特殊处理的字段
         * @param excelName 导出Excel名字
         * @param tableHeaders 表头信息
         * @param response 响应
         * @throws Exception
         */
        private static <T> void writeExcel(List<T> datas, List<KeyValueVO> specialFields, String excelName,
                        List<KeyValueVO> tableHeaders, HttpServletResponse response) throws Exception
        {
                //创建一个excel文件
                HSSFWorkbook excel = new HSSFWorkbook();
                //excel文件里面一张表格sheet
                HSSFSheet excelSheet = excel.createSheet("sheet1");
                //sheet中的行
                HSSFRow excelRow = null;
                //sheet中的单元格
                HSSFCell excelCell = null;
                //行下标
                Integer rowSubScript = 0;
                //单元格下标
                Integer cellSubScript = 0;
               
                //获取数据模型的类对象
                Class<?> clazz = datas.get(0).getClass();
               
                //遍历数据
                for (T data : datas)
                {
                        //一个数据就是一行,每一行开始,单元格的下标都要设置为0
                        cellSubScript = 0;
                        //创建改行
                        excelRow = excelSheet.createRow(rowSubScript);
                       
                        //遍历表头信息
                        for (KeyValueVO tableHeader : tableHeaders)
                        {
                                //创建单元格
                                excelCell = excelRow.createCell(cellSubScript);
                               
                                //如果改行下标为0,表示该行是标题行,还未开始写数据,这一行的单元格的值就是表格的标题等
                                if (rowSubScript == 0)
                                {
                                        //单元格的值为标题
                                        excelCell.setCellValue(tableHeader.getValue());
                                        //设置单元格的长度,确保长度合适,能完整显示标题并留下适当的空白
                                        excelSheet.setColumnWidth(cellSubScript, tableHeader.getValue().getBytes("UTF-8").length
                                                        * TWO * TWO_HUNDRED_FIFTY_SIX / THREE + FOUR * TWO_HUNDRED_FIFTY_SIX);
                                }
                                else
                                {
                                        //如果不是标题行,那么就开始写数据,通过反射获取POJO对象属性的值
                                        String methodName = getInitialsUp(tableHeader.getKey());
                                        Method getMethod = null;
                                        //获取POJO对象对应属性的getter方法
                                        getMethod = clazz.getMethod("get" + methodName);

                                        setExcelCellValue(getMethod, data, excelCell);
                                }
                                cellSubScript++;
                        }
                        rowSubScript++;
                }
                //将Excel对象写入流中
                OutputStream output = response.getOutPutStream();
                excel.write(output);
                output.flush();
                output.close();
                excel.close();
        }
       
        /**
         *  设置单元格的值
         * @param getMethod 类对象属性的get方法
         * @param data 数据
         * @param excelCell 单元格
         * @param specialFields 需要特殊处理的字段
         * @param thisField 当前字段
         * @param <T> 泛型
         */
        private static <T> void setExcelCellValue(Method getMethod, T data, HSSFCell excelCell,
                        List<KeyValueVO> specialFields, String thisField)
        {
                //如果需要特殊处理的字段为Null,初始化一个空值,避免空指针异常
                if (specialFields == null)
                {
                        specialFields = new ArrayList<>();
                }
                try
                {
                        if (null == getMethod.invoke(data))
                        {
                                excelCell.setCellValue("");
                        }
                        else
                        {
                                //根据需要特殊处理的字段集合和当前字段,返回需要特殊处理的各种参数值
                                KeyValueVO temp = needToSpecialDeal(specialFields, thisField);
                               
                                if (null == temp)
                                {
                                        //如果返回的需要特殊处理的变量为空,说明这个字段不需要特殊处理
                                        //那么单元格的值直接利用反射获取POJO对象对应属性的值
                                        excelCell.setCellValue(getMethod.invoke(data).toString());
                                }
                                else
                                {
                                        //如果该字段需要特殊处理
                                        //因为目前遇到的特殊处理基本就是加一个超链接
                                        //所以笔者这里没有判断需要特殊处理的方式是哪种,temp.getKey()会返回特殊处理的方式
                                        //如果是超链接处理,temp.getKey()会返回“hyperlink”,temp.getValue()会返回超链接的链接地址
                                        excelCell.setCellFormula("HYPERLINK(\"" + temp.getValue() + "\", \"" + getMethod.invoke(data).toString() + "\")");
                                }
                               
                                excelCell.setCellValue(getMethod.invoke(data).toString());
                        }
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }
       
        /**
         * 判断是否需要特殊处理,如果需要返回特殊处理的方式和值
         * @param specialFields 所有需要特殊处理的字段
         * @param thisField 当前字段
         * @return 值
         */
        private static KeyValueVO needToSpecialDeal(List<KeyValueVO> specialFields, String thisField)
        {
                //遍历需要特殊处理的字段,判断当前字段是不是需要特殊处理
                //如果需要,就把特殊处理的方式和值写入KeyValueVO对象里面并返回
                //如果不需要,则返回null
                for (KeyValueVO oneField : specialFields)
                {
                        //如果当前字段匹配上了特殊处理的字段,那么说明需要特殊处理
                        if (thisField.equals(oneField.getKey()))
                        {
                                KeyValueVO temp = new KeyValueVO();
                               
                                temp.setKey("hyperlink");
                                temp.setValue(oneField.getValue());
                               
                                return temp;
                        }
                }
                return null;
        }
       
        /**
         *  将字符串首字母大写,如:big → Big
         * @param field 字符串
         * @return 首字母大写之后的字符串
         */
        public static String getInitialsUp(String field)
        {
                byte[] items = null;
                try
                {
                        items = field.getBytes("UTF-8");
                        items[0] = (byte) ((char)items[0] - 'a' + 'A');
                        return new String(items, "UTF-8");
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                        return "";
                }
        }
       
        /**
         * 导出BsonDocument文档数据到excel
         * @param datas 数据
         * @param specialFields 需要特殊处理的字段
         * @param excelName excel名字
         * @param tableHeaders 表头信息
         * @param response 响应
         */
        public static void exportBsonDocument(List<Document> datas, List<KeyValueVO> specialFields, String excelName,
                        List<KeyValueVO> tableHeaders, HttpServletResponse response)
        {
                if (null == datas || datas.isEmpty() || tableHeaders == null || tableHeaders.isEmpty())
                {
                        return;
                }
                try
                {
                        excelName = new String(excelName.getBytes("UTF-8"),"ISO-8859-1");
                }
                catch (Exception e1)
                {
                        e1.printStackTrace();
                }
               
                response.setCharacterEncoding("utf-8");
               
                try
                {
                        writeExcel(datas,specialFields,excelName,tableHeaders,response);
                }
                catch (Exception e)
                {
                        e.printStackTrace();
                }
        }
       
        /**
         * 同POJO导出
         * @param datas
         * @param specialFields
         * @param excelName
         * @param tableHeaders
         * @param response
         * @throws IOException
         */
        private static void writeBsonDocumentExcel(List<Document> datas, List<KeyValueVO> specialFields, String excelName,
                        List<KeyValueVO> tableHeaders, HttpServletResponse response) throws IOException
        {
                HSSFWorkbook excel = new HSSFWorkbook();
                HSSFSheet excelSheet = excel.createSheet("sheet1");
                HSSFRow excelRow = null;
                HSSFCell excelCell = null;
                Integer rowSubScript = 0;
                Integer cellSubScript = 0;
               
                //遍历数据
                for (Document data : datas)
                {
                        cellSubScript = 0;
                        excelRow = excelSheet.createRow(rowSubScript);
                       
                        for (KeyValueVO tableHeader : tableHeaders)
                        {
                                excelCell = excelRow.createCell(cellSubScript);
                               
                                if (rowSubScript == 0)
                                {
                                        excelCell.setCellValue(tableHeader.getValue());
                                        excelSheet.setColumnWidth(cellSubScript, tableHeader.getValue().getBytes("UTF-8").length
                                                        * TWO * TWO_HUNDRED_FIFTY_SIX / THREE + FOUR * TWO_HUNDRED_FIFTY_SIX);
                                }
                                else
                                {
                                        setValueOfBsonCell(specialFields, tableHeader.getKey(), excelCell, data, tableHeader);
                                }
                                cellSubScript++;
                        }
                        rowSubScript++;
                }

                OutputStream output = response.getOutPutStream();
                excel.write(output);
                output.flush();
                output.close();
                excel.close();
        }
       
        /**
         * bson文档导出设置单元格值
         * @param specialFields 需要特殊处理字段
         * @param thisField 当期字段
         * @param excelCell 单元格
         * @param data 数据
         * @param tableHeader 表头信息
         */
        private static void setValueOfBsonCell(List<KeyValueVO> specialFields, String thisField, HSSFCell excelCell,
                        Document data, KeyValueVO tableHeader)
        {
                if (null == specialFields)
                {
                        specialFields = new ArrayList<>();
                }
               
                KeyValueVO temp = needToSpecialDeal(specialFields, thisField);
               
                if (null == temp)
                {
                        excelCell.setCellValue(data.getString(tableHeader.getKey()));
                }
                else
                {
                        excelCell.setCellFormula("HYPERLINK(\"" + temp.getValue() + "\", \"" + data.getString(tableHeader.getKey()) + "\")");
                }
        }
}
这两个导出工具类,适用于第一行为标题,第二行开始为正文数据,通用POJO对象的导出和BsonDocument类型的导出。

在这里,主要笔者想说的是导出的思路,就是创建封装好的excel对象,然后依次创建sheet,在sheet里面创建一行,行里面创建单元格,然后给每一个单元格赋值,非常简单。
---------------------
【转载,仅作分享,侵删】
作者:m0_37872413
原文:https://blog.csdn.net/m0_37872413/article/details/87425802
版权声明:本文为博主原创文章,转载请附上博文链接!

1 个回复

倒序浏览
奈斯,感谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马