若依平台ExcelUtil工具类

本文介绍了若依框架自带的Excel导出工具类ExcelUtil,基于ApachePOIAPI,详细讲解了如何使用Poi对象进行数据导入和导出,以及若依平台如何通过Excel注解进行字段映射。还涵盖了创建Excel文件、处理单元格数据和工作簿的操作方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

若依框架自带的Excel导出工具类——ExcelUtil基于org.apache.poi

1 Apache API

1.1 Apache POI简介

Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“简洁版的模糊实现”。

HSSF一读写Microsoft Excel XLS

xSSF一读写Microsoft Excel OOXML XLSX

HWPF一读写Microsoft Word Doc

HSLF一提供读写Microsoft PowerPoint

Java类

HSSFWorkbook:用于操作Excel2003以前(包括2003)的版本,扩展名是.xls;

XSSFWorkbook:用于操作Excel2007后的版本,扩展名是.xlsx;

SXSSFWorkbook:用于操作Excel2007后的版本,扩展名是.xlsx;

1.2 使用

1.2.1 Poi对象

主要使用一下几个对象:

  1. XSSFWorkbook;工作簿(即整个excel文件)
  2. XSSFSheet:工作表(即excel文件的一个选项卡,选项卡在可视化界面下方)
  3. Row:行(即一整行)
  4. Cell:单元格(即一格)

1.2.2 导入Excel数据

步骤

  1. 创建工作簿
  2. 获取工作表
  3. 遍历工作表获得行对象
  4. 遍历行对象获取单元格对象
  5. 获得单元格中的值
    实例:
    public  void test() throws IOException {
        //1. 获取工作簿
        XSSFWorkbook sheets = new XSSFWorkbook("fileUrl");


        //2. 获取工作表
        //sheets.getSheet(); 根据选项卡名称,即工作表名称
        //根据索引获取工作表
        XSSFSheet sheetAt = sheets.getSheetAt(0);

        //3.1. 获取行
        for (Row cells : sheetAt) {
            //4.1. 获取单元格
            for (Cell cell : cells) {
                //获取单元格中的值
                String value = cell.getStringCellValue();
                System.out.println(value);
            }
        }

        //5. 释放资源
        sheets.close();
    }

使用索引读取每行中的单元格:

        //3.2. 获取行
        //获取最后一行索引
        int lastRowNum = sheetAt.getLastRowNum();
        for (int i = 0; i<lastRowNum; i++) {
            //获取当前行数据
            XSSFRow row = sheetAt.getRow(i);
            if (row != null) {
                //获取当前行最后一个单元格索引
                short lastCellNum = row.getLastCellNum();
                for (int j = 0; j < lastCellNum; j++) {
                    //获取当前党员格数据
                    XSSFCell cell = row.getCell(j);
                    if (cell != null) {
                        String stringCellValue = cell.getStringCellValue();
                        System.out.println(stringCellValue);
                    }
                }
            }
        }

1.2.3 导出Excel

步骤

  1. 创建一个Excel文件
  2. 创建工作表
  3. 创建行
  4. 创建单元格赋值
  5. 通过输出流将对象下载到磁盘,或者发送给网络中
public void test() throws IOException {
        //1. 创建工作薄
        XSSFWorkbook sheets = new XSSFWorkbook();

        //2. 创建工作表
        XSSFSheet sheet = sheets.createSheet("工作表一");

        //3. 创建行
        for (int i = 0; i < 3; i++) {
            XSSFRow row = sheet.createRow(i);
            //4. 创建单元格
            row.createCell(0).setCellValue("a" + i);
            row.createCell(1).setCellValue("b" + i);
            row.createCell(2).setCellValue("c" + i);
        }

        //5. 创建输出流
        FileOutputStream fileOutputStream = new FileOutputStream("fileUrl");

        //将内容写入文件
        sheets.write(fileOutputStream);

        //刷新
        fileOutputStream.flush();

        //6. 释放资源
        fileOutputStream.close();
        sheets.close();
        System.out.println("写入成功");

    }

2 若依ExcelUtil

2.1 注解

若依平台通过Excel注解在类的属性上标注,定义属性在Excel表中的映射关系,使用@Excel和@Excels注解,后者是前者的数据集;
注解路径:/ruoyi-common/src/main/java/com/ruoyi/common/annontation
案例

// 单个字段导出
@Excel(name = "员工", targetAttr = "deptName", type = Type.EXPORT)
private User user;

// 多个字段导出
@Excels({
    @Excel(name = "员工", targetAttr = "deptName", type = Type.EXPORT),
    @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
})
private  User user;

在@Excel注解中,有多种方法用来定义字段的规则,如下:

方法功能
sort()导出时在excel中排序
name()导出到Excel中的名字
dateFormat()日期格式, 如: yyyy-MM-dd
dictType()如果是字典类型,请设置字典的type值 (如: sys_user_sex)
readConverterExp()读取内容转表达式 (如: 0=男,1=女,2=未知)
separator()分隔符,读取字符串组内容
scale()BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
roundingMode()BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
cellType()导出类型(0数字 1字符串)
height()导出时在excel中每个列的高度 单位为字符
width()导出时在excel中每个列的宽 单位为字符
suffix()文字后缀,如% 90 变成90%
defaultValue()当值为空时,字段的默认值
prompt()提示信息
combo()设置只能选择不能输入的列内容
isExport()是否导出数据
targetAttr()另一个类中的属性名称,支持多级获取,以小数点隔开
isStatistics()是否自动统计数据,在最后追加一行统计数据总和
align()导出字段对齐方式(0:默认;1:靠左;2:居中;3:靠右)
default自定义数据处理器
args()自定义数据处理器参数

在这里插入图片描述

2.2 ExcelUtil

路径:/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil
主要方法:

ExcelUtil构造方法
生成方法有两种,都需要实体类

public ExcelUtil(Class<T> clazz)
    {
        this.clazz = clazz;
    }

    public ExcelUtil(List<String> extFields, Class<T> clazz) {
        this.extFields = extFields;
        this.clazz = clazz;
    }

2.2.1 导出

init()初始化方法

调用导出即生成Excel时最终都会调用该方法

    public void init(List<T> list, String sheetName, String title, Type type)
    {
        if (list == null)
        {
            list = new ArrayList<T>();
        }
        this.list = list;
        this.sheetName = sheetName;
        this.type = type;
        this.title = title;
        createExcelField();
        createWorkbook();
        createTitle();
    }

createExcelField()
作用:得到所有定义字段的信息(fields是注解列表,maxHeight是最大高度)

    /**
     * 得到所有定义字段
     */
    private void createExcelField()
    {
     // 获得实体类属性的信息:
        this.fields = getFields();
      //按照Excel注解信息来排序
        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
        //遍历属性,获取最大行高
        this.maxHeight = getRowHeight();
    }

getFields()获取字段注解信息
作用:传入ExcelUtil的实体类,获取头上带有俩注解之一的属性(包括父类的),经过一点逻辑,然后返回赋值给ExcelUtil的fields属性;同时,如果实体类中有集合属性存在,也会给subMethod和subFields赋值

getRowHeight()获取最大行高
getRowHeight()遍历ExcelUtil的属性fields,即所有@Excel注解的属性,找出最大行高并返回maxHeight * 20

public short getRowHeight()
    {
        double maxHeight = 0;
    //遍历所有字段,获取其注解信息,然后找到最大的height属性,最后返回
        for (Object[] os : this.fields)
        {
            //os[1],即获取注解信息
            Excel excel = (Excel) os[1];
            maxHeight = Math.max(maxHeight, excel.height());
        }
        return (short) (maxHeight * 20);
    }

createWorkbook() 创建一个工作薄
作用:创建一个工作薄(wb是工作薄对象xlsx版,sheet是工作表对象,styles是样式列表(map集合))

    public void createWorkbook()
    {
        this.wb = new SXSSFWorkbook(500);
        //Workbook已有的创建工作表的方法
        this.sheet = wb.createSheet();
        //给第一个(索引)工作表命名
        wb.setSheetName(0, sheetName);
        //Map<String, CellStyle> styles
        //创建所有的样式,赋值给styles
        this.styles = createStyles(wb);
    }

createStyles():创建表格样式,如某行单元格的大小、字体等
createTitle():作用:根据ExcelUtil的tittle属性是否为空选择是否创建excel第一行标题

exportExcel()

在init()方法之后,最后都会调用该方法,该方法有两个,一个带参数,一个不带参数
作用:根据init()方法初始化的属性,来创建excel表,并填入数据

区别:

  1. exportExcel(HttpServletResponse response)利用servlet容器,把文件响应给客户端
  2. exportExcel()根据配置文件路径,下载文件到指定路径下

2.2.2 导入

importExcel()
作用:实现了从Excel文件中导入数据的功能,将每一行不为空的列转换为指定类型的实体对象,并存储在一个List中返回。

public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception

整体逻辑:

  1. 首先设置了type为Type.IMPORT,表示当前操作是导入。然后使用WorkbookFactory.create(is)方法创建一个Workbook对象,该对象表示整个Excel文件。接下来,根据sheetName获取对应的工作表对象Sheet,如果sheetName为空,则默认获取第一个工作表。

  2. 然后,根据Excel文件的类型(.xlsx或.xls),分别调用getSheetPictures07或getSheetPictures03方法获取工作表中的图片数据。

  3. 接下来,获取工作表中最后一个非空行的行号,并进行循环处理每一行的数据。在循环中,首先获取表头行heard,并根据表头行获取每一列的列名和列号,存储在cellMap中。

  4. 然后,获取类的字段信息,并根据字段的注解Excel和cellMap中的列号,构建一个fieldsMap,用于存储列号和字段信息的映射关系。

  5. 接下来,从titleNum + 1行开始循环处理每一行的数据。在循环中,首先判断当前行是否为空行,如果是则跳过。然后,根据extDataStartCol获取额外数据,并将其存储在extDataList中。

  6. 然后,根据fieldsMap中的映射关系,获取每一列的值,并根据字段的类型进行转换和赋值操作。

  7. 最后,将转换后的实体对象添加到list中,并返回list。

3 若依框架导入导出实现方法

3.1 前端

3.1.1 导入getToken方法

在需要实现导入导出功能的页面的index.vue中的< script >< /script >中增加如下代码:

import { getToken } from "@/utils/auth";

3.1.2 新增upload参数

在index.vue的data数据中添加upload属性

// 导入参数
upload: {
        // 是否显示弹出层(导入弹窗)
        open: false,
        // 弹出层标题(自己填写)
        title: "自己填写",
        // 是否禁用上传
        isUploading: false,
        // 设置上传的请求头部
        headers: { Authorization: "Bearer " + getToken() },
        // 上传的地址,即后端接口地址
        url: process.env.VUE_APP_BASE_API + "/url"
      },

3.1.3 新增导入按钮所需的函数

在index.vue的methods中新增一下几个函数,具体可以自己修改:

/** 导入按钮操作 */
handleImport() {
  this.upload.title = "自己设置";
  this.upload.open = true;
},
    /** 下载模板操作 */
    importTemplate() {
      this.download('下载模板的url', {
      }, `user_template_${new Date().getTime()}.xlsx`)
    },
// 文件上传中处理
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(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
  this.getList();
},
// 提交上传文件
submitFileForm() {
  this.$refs.upload.submit();
}

3.1.4 添加导入按钮与导入弹窗

index.vue的中的合适位置添加如下代码,其中v-hasPermi为访问权限,设置可以个人修改,导入弹窗使用了标签及相关属性,action属性为url路径。

      <el-col :span="1.5">
        <el-button
          type="info"
          icon="el-icon-upload2"
          size="mini"
          @click="handleImport"
          v-hasPermi="['system:user:import']"
        >导入</el-button>
      </el-col>

<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px">
  <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" slot="tip">
	  <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
	  <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
	</div>
	<div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</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>

3.2 后端

3.2.1 添加注解@Excel

在需要导入与导出功能的类的属性上增加@Excel注解,并添加name属性与其他属性,案例如下:

    @Excel(name = "姓名")
    private String userName;

3.2.2 在对应的类中新增导入接口与下载模板接口

具体实体类与服务按照实际需求来实现。

@Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<SysHonor> util = new ExcelUtil<SysHonor>(SysHonor.class);
        List<SysHonor> userList = util.importExcel(file.getInputStream());
        LoginUser loginUser = getLoginUser();
        String operName = loginUser.getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return AjaxResult.success(message);
    }

    @GetMapping("/importTemplate")
    public AjaxResult importTemplate()
    {
        ExcelUtil<SysHonor> util = new ExcelUtil<SysHonor>(SysHonor.class);
        return util.importTemplateExcel("用户数据");
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值