本文讲解关于使用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
版权声明:本文为博主原创文章,转载请附上博文链接!
|
|