文章目录
- @Excel注解
- excel数据导入
- 前端实现
- 后端实现
- 下载模板
- 前端实现
- 后端实现
- excel数据导出
- 前端实现
- 后端实现
- 自定义标题信息
- 导出用户管理表格新增标题(用户列表)
- 导入表格包含标题处理方式
- 自定义数据处理器
- 自定义隐藏属性列
- 导入对象的子对象
- 导出对象的子列表
@Excel注解
在实际开发中经常需要使用导入导出功能来加快数据的操作。在项目中可以使用注解来完成此项功能。 在需要被导入导出的实体类属性添加@Excel注解。
在使用@Excel注解时,通常可以使用的参数包括:
-
name
:指定Excel列的标题名称,用于导出时生成Excel文件的表头。 -
orderNum
:指定Excel列的顺序,从0开始,用于导出时确定列的顺序。 -
type
:指定导入导出时的数据类型转换,例如可以指定日期格式、数字格式等。 -
width
:指定Excel列的宽度,用于导出时设置列宽。 -
height
:指定Excel行的高度,用于导出时设置行高。 -
format
:指定导入导出时的数据格式,例如可以指定日期的格式化方式。 -
replace
:指定导入导出时的值替换规则,例如可以将特定的值替换为另一个值。 -
exportFormat
:指定导出时的数据格式,例如可以指定数字的格式化方式。 -
importFormat
:指定导入时的数据格式,例如可以指定日期的解析方式。
以上参数中,name
和orderNum
通常是必需的,其他参数根据实际需求进行选择。在使用时,可以根据具体情况来决定是否需要设置这些参数。
excel数据导入
目前若依的版本是在用户管理页面有数据导入的功能:
前端实现
导入功能前端的实现和之前文件上传差不多。
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的用户数据
</div>
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</el-dialog>
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
this.getList();
},
// 提交上传文件
submitFileForm() {
this.$refs.upload.submit();
}
后端实现
在实体变量上添加@Excel注解,默认为导出导入,也可以单独设置仅导入Type.IMPORT
@Excel(name = "用户序号")
private Long id;
@Excel(name = "部门编号", type = Type.IMPORT)
private Long deptId;
@Excel(name = "用户名称")
private String userName;
/** 导出部门多个对象 */
@Excels({
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
@Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
private SysDept dept;
/** 导出部门单个对象 */
@Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT)
private SysDept dept;
在Controller添加导入方法,updateSupport属性为是否存在则覆盖(可选)
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
@PreAuthorize("@ss.hasPermi('system:user:import')")
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> userList = util.importExcel(file.getInputStream());
String operName = getUsername();
String message = userService.importUser(userList, updateSupport, operName);
return success(message);
}
下载模板
下载模板实际上就是将一张空表返回给前端。
前端实现
/** 下载模板操作 */
importTemplate() {
this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
},
后端实现
注意this.init(null, sheetName, title, Type.IMPORT); null表示数据为空,只返回了表头。
/**
* 对list数据源将其里面的数据导入到excel表单
*
* @param sheetName 工作表的名称
* @param title 标题
* @return 结果
*/
public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
{
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
this.init(null, sheetName, title, Type.IMPORT);
exportExcel(response);
}
excel数据导出
导出默认流程是先创建一个临时文件,等待前端请求下载结束后马上删除这个临时文件。
前端实现
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:fileNotice:export']"
>导出</el-button>
</el-col>
/** 导出按钮操作 */
handleExport() {
this.download('system/fileNotice/export', {
...this.queryParams
}, `fileNotice_${new Date().getTime()}.xlsx`)
}
后端实现
@PreAuthorize("@ss.hasPermi('system:fileNotice:export')")
@Log(title = "系统文件", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, FileNotice fileNotice)
{
List<FileNotice> list = fileNoticeService.selectFileNoticeList(fileNotice);
ExcelUtil<FileNotice> util = new ExcelUtil<FileNotice>(FileNotice.class);
util.exportExcel(response, list, "系统文件数据");
}
自定义标题信息
有时候我们希望导出表格包含标题信息,我们可以这样做。
导出用户管理表格新增标题(用户列表)
public AjaxResult export(SysUser user)
{
List<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
return util.exportExcel(list, "用户数据", "用户列表");
}
导入表格包含标题处理方式
util.importExcel(file.getInputStream(), 1);
其中1表示标题占用行数,根据实际情况填写。
/**
* 对excel表单默认第一个索引名转换成list
*
* @param is 输入流
* @param titleNum 标题占用行数
* @return 转换后集合
*/
public List<T> importExcel(InputStream is, int titleNum) throws Exception
{
return importExcel(StringUtils.EMPTY, is, titleNum);
}
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> userList = util.importExcel(file.getInputStream(), 1);
String operName = SecurityUtils.getUsername();
String message = userService.importUser(userList, updateSupport, operName);
return AjaxResult.success(message);
}
自定义数据处理器
有时候我们希望数据展现为一个特殊的格式,或者需要对数据进行其它处理。Excel注解提供了自定义数据处理器以满足各种业务场景。
1、在实体类用Excel注解handler属性指定自定义的数据处理器
public class SysUser extends BaseEntity
{
@Excel(name = "用户名称",handler = MyDataHandler.class)
private String nickName;
}
2、编写数据处理器MyDataHandler继承ExcelHandlerAdapter,返回值为处理后的值。
public class MyDataHandler implements ExcelHandlerAdapter
{
@Override
public Object format(Object value, String[] args, Cell cell, Workbook wb)
{
if ("若依".equals(value))
{
// 自定义用户名为若依/单元格文字设置为红色
CellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
style.setBorderRight(BorderStyle.THIN);
style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderLeft(BorderStyle.THIN);
style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderTop(BorderStyle.THIN);
style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
style.setBorderBottom(BorderStyle.THIN);
style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
Font dataFont = wb.createFont();
dataFont.setFontName("Arial");
dataFont.setFontHeightInPoints((short) 10);
dataFont.setColor(IndexedColors.RED.index);
style.setFont(dataFont);
cell.setCellStyle(style);
}
return value;
}
}
自定义隐藏属性列
有时候我们希望对列信息根据业务去动态显示,那么我们可以进行如下处理。
示例:对用户进行条件判断,符合条件则隐藏属性。导出的文件则不会显示此列信息。
@PostMapping("/export")
public void export(HttpServletResponse response, SysUser user)
{
List<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
if (条件A) {
// 不显示用户ID(单个)
util.hideColumn("userId");
} else if (条件B) {
// 不显示用户名称、用户手机(多个)
util.hideColumn("userId", "phonenumber");
} } else if (条件C) {
// 不显示用户邮箱、部门名称(子对象)
util.hideColumn("email", "dept.deptName");
}
util.exportExcel(response, list, "用户数据");
}
导入对象的子对象
有时候我们导入对象里面还包含对象,例如用户管理包含部门需要导入,那么我们可以进行如下处理。
/**
* 用户对象 sys_user
*
* @author ruoyi
*/
public class SysUser extends BaseEntity
{
/** 部门对象 */
@Excels({
@Excel(name = "部门名称", targetAttr = "deptName"),
@Excel(name = "部门负责人", targetAttr = "leader"),
@Excel(name = "部门状态", targetAttr = "status", dictType = "sys_normal_disable")
})
private SysDept dept = new SysDept();
}
导出对象的子列表
有时候对象里面还包含集合列表,例如用户管理包含多个角色需要导出,那么我们可以进行如下处理。
注意:
需要合并的须在注解里面加上needMerge = true
private List roles;的定义要放在最下面,不然合并的时候回混乱。
/**
* 用户对象 sys_user
*
* @author ruoyi
*/
public class SysUser extends BaseEntity
{
/** 用户ID */
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号", needMerge = true, width = 20)
private Long userId;
@Excel(name = "登录名称", needMerge = true, width = 20)
private String userName;
@Excel(name = "最后登录IP", type = Type.EXPORT,needMerge = true)
private String loginIp;
@Excel(name = "角色")
private List<SysRole> roles;
}
public class SysRole
{
@Excel(name = "角色编号", cellType = ColumnType.NUMERIC)
private String roleId;
@Excel(name = "角色名称")
private String roleName;
@Excel(name = "角色字符")
private String roleKey;
}
导出文件结果: