Java之基于注解的Excel导出
原文地址:https://blog.csdn.net/wenxingchen/article/details/84791205
数据库 Excel 导出操作代码过于冗长惨不忍睹, 无法复用。
目录
注解配合工具类做了个小工具如下:
第一步:自定义注解:
package com.ruoyi.framework.aspectj.lang.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/
-
自定义导出 Excel 数据注解
-
@author ruoyi
/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
/*
- 导出到 Excel 中的名字.
*/
public String name();
/
- 日期格式, 如: yyyy-MM-dd
*/
public String dateFormat() default "";
/
- 读取内容转表达式 (如: 0= 男,1= 女,2= 未知)
*/
public String readConverterExp() default "";
/
- 导出时在 excel 中每个列的高度 单位为字符
*/
public double height() default 14;
/
- 导出时在 excel 中每个列的宽 单位为字符
*/
public double width() default 20;
/
- 文字后缀, 如 % 90 变成 90%
*/
public String suffix() default "";
/
- 当值为空时, 字段的默认值
*/
public String defaultValue() default "";
/
- 提示信息
*/
public String prompt() default "";
/
- 设置只能选择不能输入的列内容.
*/
public String[] combo() default {};
/
- 是否导出数据, 应对需求: 有时我们需要导出一份模板, 这是标题需要但内容需要用户手工填写.
*/
public boolean isExport() default true;
}
第二步:实体类:
package com.ruoyi.project.system.dict.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.framework.web.domain.BaseEntity;
/
-
字典数据表 sys_dict_data
-
@author ruoyi
*/
public class DictData extends BaseEntity
{
private static final long serialVersionUID = 1L;
/ 字典编码 */
@Excel(name = "字典编码")
private Long dictCode;
/ 字典排序 */
@Excel(name = "字典排序")
private Long dictSort;
/ 字典标签 */
@Excel(name = "字典标签")
private String dictLabel;
/ 字典键值 */
@Excel(name = "字典键值")
private String dictValue;
/ 字典类型 */
@Excel(name = "字典类型")
private String dictType;
/ 字典样式 */
@Excel(name = "字典样式")
private String cssClass;
/ 表格字典样式 */
private String listClass;
/ 是否默认(Y 是 N 否) */
@Excel(name = "是否默认", readConverterExp = "Y= 是,N= 否")
private String isDefault;
/ 状态(0 正常 1 停用) */
@Excel(name = "状态", readConverterExp = "0= 正常,1= 停用")
private String status;
public Long getDictCode()
{
return dictCode;
}
public void setDictCode(Long dictCode)
{
this.dictCode = dictCode;
}
public Long getDictSort()
{
return dictSort;
}
public void setDictSort(Long dictSort)
{
this.dictSort = dictSort;
}
public String getDictLabel()
{
return dictLabel;
}
public void setDictLabel(String dictLabel)
{
this.dictLabel = dictLabel;
}
public String getDictValue()
{
return dictValue;
}
public void setDictValue(String dictValue)
{
this.dictValue = dictValue;
}
public String getDictType()
{
return dictType;
}
public void setDictType(String dictType)
{
this.dictType = dictType;
}
public String getCssClass()
{
return cssClass;
}
public void setCssClass(String cssClass)
{
this.cssClass = cssClass;
}
public String getListClass()
{
return listClass;
}
public void setListClass(String listClass)
{
this.listClass = listClass;
}
public String getIsDefault()
{
return isDefault;
}
public void setIsDefault(String isDefault)
{
this.isDefault = isDefault;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("dictCode", getDictCode())
.append("dictSort", getDictSort())
.append("dictLabel", getDictLabel())
.append("dictValue", getDictValue())
.append("dictType", getDictType())
.append("cssClass", getCssClass())
.append("listClass", getListClass())
.append("isDefault", getIsDefault())
.append("status", getStatus())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}
第三步:解析工具类:
package com.ruoyi.common.utils.poi;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.apache.poi.hssf.usermodel.DVConstraint;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataValidation;
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.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.web.domain.AjaxResult;
/
-
Excel 相关处理
-
@author ruoyi
*/
public class ExcelUtil<T>
{
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public Class<T> clazz;
public ExcelUtil(Class<T> clazz)
{
this.clazz = clazz;
}
/
- 对 excel 表单默认第一个索引名转换成 list
- @param input 输入流
- @return 转换后集合
*/
public List<T> importExcel(InputStream input) throws Exception
{
return importExcel(StringUtils.EMPTY, input);
}
/
-
对 excel 表单指定表格索引名转换成 list
-
@param sheetName 表格索引名
-
@param input 输入流
-
@return 转换后集合
*/
public List<T> importExcel(String sheetName, InputStream input) throws Exception
{
List<T> list = new ArrayList<T>();
Workbook workbook = WorkbookFactory.create(input);
Sheet sheet = null;
if (StringUtils.isNotEmpty(sheetName))
{
// 如果指定 sheet 名, 则取指定 sheet 中的内容.
sheet = workbook.getSheet(sheetName);
}
else
{
// 如果传入的 sheet 名不存在则默认指向第 1 个 sheet.
sheet = workbook.getSheetAt(0);
}
if (sheet == null)
{
throw new IOException("文件 sheet 不存在");
}
int rows = sheet.getPhysicalNumberOfRows();
if (rows > 0)
{
// 默认序号
int serialNum = 0;
// 有数据时才处理 得到类的所有 field.
Field[] allFields = clazz.getDeclaredFields();
// 定义一个 map 用于存放列的序号和 field.
Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
for (int col = 0; col < allFields.length; col++)
{
Field field = allFields[col];
// 将有注解的 field 存放到 map 中.
if (field.isAnnotationPresent(Excel.class))
{
// 设置类的私有字段属性可访问.
field.setAccessible(true);
fieldsMap.put(++serialNum, field);
}
}
for (int i = 1; i < rows; i++)
{
// 从第 2 行开始取数据, 默认第一行是表头.
Row row = sheet.getRow(i);
int cellNum = serialNum;
T entity = null;
for (int j = 0; j < cellNum; j++)
{
Cell cell = row.getCell(j);
if (cell == null)
{
continue;
}
else
{
// 先设置 Cell 的类型,然后就可以把纯数字作为 String 类型读进来了
row.getCell(j).setCellType(CellType.STRING);
cell = row.getCell(j);
}
String c </span>=<span style="color: rgba(0, 0, 0, 1)"> cell.getStringCellValue();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isEmpty(c))
{
</span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果不存在实例则新建.</span>
entity = (entity == <span style="color: rgba(0, 0, 255, 1)">null</span> ?<span style="color: rgba(0, 0, 0, 1)"> clazz.newInstance() : entity);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 从map中得到对应列的field.</span>
Field field = fieldsMap.<span style="color: rgba(0, 0, 255, 1)">get</span>(j + <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取得类型,并根据对象类型设置值.</span>
Class<?> fieldType =<span style="color: rgba(0, 0, 0, 1)"> field.getType();
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (String.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType)
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">(entity, String.valueOf(c));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> ((Integer.TYPE == fieldType) || (Integer.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType))
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">(entity, Integer.parseInt(c));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> ((Long.TYPE == fieldType) || (Long.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType))
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">(entity, Long.valueOf(c));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> ((Float.TYPE == fieldType) || (Float.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType))
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">(entity, Float.valueOf(c));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> ((Short.TYPE == fieldType) || (Short.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType))
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">(entity, Short.valueOf(c));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> ((Double.TYPE == fieldType) || (Double.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType))
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">(entity, Double.valueOf(c));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (Character.TYPE ==<span style="color: rgba(0, 0, 0, 1)"> fieldType)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> ((c != <span style="color: rgba(0, 0, 255, 1)">null</span>) && (c.length() > <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">))
{
field.</span><span style="color: rgba(0, 0, 255, 1)">set</span>(entity, Character.valueOf(c.charAt(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)));
}
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (java.util.Date.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (cell.getCellTypeEnum() ==<span style="color: rgba(0, 0, 0, 1)"> CellType.NUMERIC)
{
SimpleDateFormat sdf </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> SimpleDateFormat(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">yyyy-MM-dd HH🇲🇲ss</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
cell.setCellValue(sdf.format(cell.getNumericCellValue()));
c </span>=<span style="color: rgba(0, 0, 0, 1)"> sdf.format(cell.getNumericCellValue());
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
c </span>=<span style="color: rgba(0, 0, 0, 1)"> cell.getStringCellValue();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (java.math.BigDecimal.<span style="color: rgba(0, 0, 255, 1)">class</span> ==<span style="color: rgba(0, 0, 0, 1)"> fieldType)
{
c </span>=<span style="color: rgba(0, 0, 0, 1)"> cell.getStringCellValue();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (entity != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
list.add(entity);
}
}
}
return list;
}
/
-
对 list 数据源将其里面的数据导入到 excel 表单
-
@param list 导出数据集合
-
@param sheetName 工作表的名称
-
@return 结果
*/
public AjaxResult exportExcel(List<T> list, String sheetName)
{
OutputStream out = null;
HSSFWorkbook workbook = null;
try
{
// 得到所有定义字段
Field[] allFields = clazz.getDeclaredFields();
List<Field> fields = new ArrayList<Field>();
// 得到所有 field 并存放到一个 list 中.
for (Field field : allFields)
{
if (field.isAnnotationPresent(Excel.class))
{
fields.add(field);
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 产生工作薄对象</span>
workbook = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HSSFWorkbook();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> excel2003中每个sheet中最多有65536行</span>
<span style="color: rgba(0, 0, 255, 1)">int</span> sheetSize = <span style="color: rgba(128, 0, 128, 1)">65536</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 取出一共有多少个sheet.</span>
<span style="color: rgba(0, 0, 255, 1)">double</span> sheetNo = Math.ceil(list.size() /<span style="color: rgba(0, 0, 0, 1)"> sheetSize);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> index = <span style="color: rgba(128, 0, 128, 1)">0</span>; index <= sheetNo; index++<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 产生工作表对象</span>
HSSFSheet sheet =<span style="color: rgba(0, 0, 0, 1)"> workbook.createSheet();
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (sheetNo == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
workbook.setSheetName(index, sheetName);
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置工作表的名称.</span>
workbook.setSheetName(index, sheetName +<span style="color: rgba(0, 0, 0, 1)"> index);
}
HSSFRow row;
HSSFCell cell; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 产生单元格
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 产生一行</span>
row = sheet.createRow(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写入各个字段的列头名称</span>
<span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i < fields.size(); i++<span style="color: rgba(0, 0, 0, 1)">)
{
Field field </span>= fields.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(i);
Excel attr </span>= field.getAnnotation(Excel.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建列</span>
cell =<span style="color: rgba(0, 0, 0, 1)"> row.createCell(i);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置列中写入内容为String类型</span>
cell.setCellType(CellType.STRING);
HSSFCellStyle cellStyle = workbook.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
if (attr.name().indexOf("注:") >= 0)
{
HSSFFont font = workbook.createFont();
font.setColor(HSSFFont.COLOR_RED);
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(HSSFColorPredefined.YELLOW.getIndex());
sheet.setColumnWidth(i, 6000);
}
else
{
HSSFFont font = workbook.createFont();
// 粗体显示
font.setBold(true);
// 选择需要用到的字体格式
cellStyle.setFont(font);
cellStyle.setFillForegroundColor(HSSFColorPredefined.LIGHT_YELLOW.getIndex());
// 设置列宽
sheet.setColumnWidth(i, (int)((attr.width() + 0.72) * 256));
row.setHeight((short)(attr.height() * 20));
}
cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
cellStyle.setWrapText(true);
cell.setCellStyle(cellStyle);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写入列名</span>
cell.setCellValue(attr.name());
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果设置了提示信息则鼠标放上去提示.</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotEmpty(attr.prompt()))
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里默认设了2-101列提示.</span>
setHSSFPrompt(sheet, <span style="color: rgba(128, 0, 0, 1)">""</span>, attr.prompt(), <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">, i, i);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果设置了combo属性则本列只能选择不能输入</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (attr.combo().length > <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里默认设了2-101列只能选择不能输入.</span>
setHSSFValidation(sheet, attr.combo(), <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">, i, i);
}
}
</span><span style="color: rgba(0, 0, 255, 1)">int</span> startNo = index *<span style="color: rgba(0, 0, 0, 1)"> sheetSize;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> endNo = Math.min(startNo +<span style="color: rgba(0, 0, 0, 1)"> sheetSize, list.size());
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写入各条记录,每条记录对应excel表中的一行</span>
HSSFCellStyle cs =<span style="color: rgba(0, 0, 0, 1)"> workbook.createCellStyle();
cs.setAlignment(HorizontalAlignment.CENTER);
cs.setVerticalAlignment(VerticalAlignment.CENTER);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = startNo; i < endNo; i++<span style="color: rgba(0, 0, 0, 1)">)
{
row </span>= sheet.createRow(i + <span style="color: rgba(128, 0, 128, 1)">1</span> -<span style="color: rgba(0, 0, 0, 1)"> startNo);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 得到导出对象.</span>
T vo = (T) list.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(i);
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> j = <span style="color: rgba(128, 0, 128, 1)">0</span>; j < fields.size(); j++<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获得field.</span>
Field field = fields.<span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(j);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置实体类私有属性可访问</span>
field.setAccessible(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
Excel attr </span>= field.getAnnotation(Excel.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置行高</span>
row.setHeight((<span style="color: rgba(0, 0, 255, 1)">short</span>) (attr.height() * <span style="color: rgba(128, 0, 128, 1)">20</span><span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 根据Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.</span>
<span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (attr.isExport())
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 创建cell</span>
cell =<span style="color: rgba(0, 0, 0, 1)"> row.createCell(j);
cell.setCellStyle(cs);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (vo == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果数据存在就填入,不存在填入空格.</span>
cell.setCellValue(<span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">continue</span><span style="color: rgba(0, 0, 0, 1)">;
}
String dateFormat </span>=<span style="color: rgba(0, 0, 0, 1)"> attr.dateFormat();
String readConverterExp </span>=<span style="color: rgba(0, 0, 0, 1)"> attr.readConverterExp();
</span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotEmpty(dateFormat))
{
cell.setCellValue(DateUtils.parseDateToStr(dateFormat, (Date) field.</span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(vo)));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (StringUtils.isNotEmpty(readConverterExp))
{
cell.setCellValue(convertByExp(String.valueOf(field.</span><span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">(vo)), readConverterExp));
}
</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">
{
cell.setCellType(CellType.STRING);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果数据存在就填入,不存在填入空格.</span>
cell.setCellValue(StringUtils.isNull(field.<span style="color: rgba(0, 0, 255, 1)">get</span>(vo)) ? attr.defaultValue() : field.<span style="color: rgba(0, 0, 255, 1)">get</span>(vo) +<span style="color: rgba(0, 0, 0, 1)"> attr.suffix());
}
}
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e)
{
log.error(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">导出Excel失败{}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, e.getMessage());
}
}
}
}
String filename </span>=<span style="color: rgba(0, 0, 0, 1)"> encodingFilename(sheetName);
</span><span style="color: rgba(0, 0, 255, 1)">out</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> FileOutputStream(getAbsoluteFile(filename));
workbook.write(</span><span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> AjaxResult.success(filename);
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e)
{
log.error(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">导出Excel异常{}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">, e.getMessage());
</span><span style="color: rgba(0, 0, 255, 1)">return</span> AjaxResult.error(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">导出Excel失败,请联系网站管理员!</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">finally</span><span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (workbook != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
{
workbook.close();
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e1)
{
e1.printStackTrace();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">out</span> != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
{
</span><span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)">.close();
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (IOException e1)
{
e1.printStackTrace();
}
}
}
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 设置单元格上提示
*
* @param sheet 要设置的sheet.
* @param promptTitle 标题
* @param promptContent 内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> HSSFSheet setHSSFPrompt(HSSFSheet sheet, String promptTitle, String promptContent, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> firstRow,
</span><span style="color: rgba(0, 0, 255, 1)">int</span> endRow, <span style="color: rgba(0, 0, 255, 1)">int</span> firstCol, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> endCol)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 构造constraint对象</span>
DVConstraint constraint = DVConstraint.createCustomFormulaConstraint(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">DD1</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 四个参数分别是:起始行、终止行、起始列、终止列</span>
CellRangeAddressList regions = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CellRangeAddressList(firstRow, endRow, firstCol, endCol);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 数据有效性对象</span>
HSSFDataValidation dataValidationView = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HSSFDataValidation(regions, constraint);
dataValidationView.createPromptBox(promptTitle, promptContent);
sheet.addValidationData(dataValidationView);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sheet;
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 设置某些列的值只能输入预制的数据,显示下拉框.
*
* @param sheet 要设置的sheet.
* @param textlist 下拉框显示的内容
* @param firstRow 开始行
* @param endRow 结束行
* @param firstCol 开始列
* @param endCol 结束列
* @return 设置好的sheet.
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> HSSFSheet setHSSFValidation(HSSFSheet sheet, String[] textlist, <span style="color: rgba(0, 0, 255, 1)">int</span> firstRow, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> endRow,
</span><span style="color: rgba(0, 0, 255, 1)">int</span> firstCol, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> endCol)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 加载下拉列表内容</span>
DVConstraint constraint =<span style="color: rgba(0, 0, 0, 1)"> DVConstraint.createExplicitListConstraint(textlist);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置数据有效性加载在哪个单元格上,四个参数分别是:起始行、终止行、起始列、终止列</span>
CellRangeAddressList regions = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CellRangeAddressList(firstRow, endRow, firstCol, endCol);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 数据有效性对象</span>
HSSFDataValidation dataValidationList = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> HSSFDataValidation(regions, constraint);
sheet.addValidationData(dataValidationList);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> sheet;
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 解析导出值 0=男,1=女,2=未知
*
* @param propertyValue 参数值
* @param converterExp 翻译注解
* @return 解析后值
* @throws Exception
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> String convertByExp(String propertyValue, String converterExp) throws Exception
{
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">
{
String[] convertSource </span>= converterExp.split(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">,</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">for</span><span style="color: rgba(0, 0, 0, 1)"> (String item : convertSource)
{
String[] itemArray </span>= item.split(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">=</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (itemArray[<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">].equals(propertyValue))
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> itemArray[<span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">];
}
}
}
</span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e)
{
</span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> e;
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> propertyValue;
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 编码文件名
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String encodingFilename(String filename)
{
filename </span>= UUID.randomUUID().toString() + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_</span><span style="color: rgba(128, 0, 0, 1)">"</span> + filename + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">.xls</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> filename;
}
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 获取下载路径
*
* @param filename 文件名称
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> String getAbsoluteFile(String filename)
{
String downloadPath </span>= RuoYiConfig.getDownloadPath() +<span style="color: rgba(0, 0, 0, 1)"> filename;
File desc </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> File(downloadPath);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">desc.getParentFile().exists())
{
desc.getParentFile().mkdirs();
}
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> downloadPath;
}
}
第四步:使用:
@Log(title = "字典数据", businessType = BusinessType.EXPORT) @RequiresPermissions("system:dict:export") @PostMapping("/export") @ResponseBody public AjaxResult export(DictData dictData) { List<DictData> list = dictDataService.selectDictDataList(dictData); ExcelUtil<DictData> util = new ExcelUtil<DictData>(DictData.class); return util.exportExcel(list, "dictData");}