报表技术3-EasyPOI

EasyPOI

Easypoi的目标不是替代poi,而是让一个不懂导入导出的快速使用poi完成Excel和word的各种操作,而不是看很多api才可以完成这样工作。

开发目的

  • 不太熟悉poi的
  • 不想写太多重复太多的
  • 只是简单的导入导出的
  • 喜欢使用模板的
  • 都可以使用easypoi

导入依赖

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.1.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.1.0</version>
</dependency>

或SpringBoot依赖

<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.1.0</version>
</dependency>

Excel注解

属性类型类型说明
nameStringnull列名
needMergebooleanfasle纵向合并单元格
orderNumString“0”列的排序,支持name_id
replaceString[]{}值得替换 导出是{a_id,b_id} 导入反过来
savePathString“upload”导入文件保存路径
typeint1导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本
widthdouble10列宽
heightdouble10列高,后期打算统一使用@ExcelTarget的height,这个会被废弃,注意
isStatisticsbooleanfasle自动统计数据,在追加一行统计,把所有数据都和输出这个处理会吞没异常,请注意这一点
isHyperlinkbooleanfalse超链接,如果是需要实现接口返回对象
isImportFieldbooleantrue校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id
exportFormatString“”导出的时间格式,以这个是否为空来判断是否需要格式化日期
importFormatString“”导入的时间格式,以这个是否为空来判断是否需要格式化日期
formatString“”时间格式,相当于同时设置了exportFormat 和 importFormat
databaseFormatString“yyyyMMddHHmmss”导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string类型,这个需要设置这个数据库格式,用以转换时间格式输出
numFormatString“”数字格式化,参数是Pattern,使用的对象是DecimalFormat
imageTypeint1导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的
suffixString“”文字后缀,如% 90 变成90%
isWrapbooleantrue是否换行 即支持\n
mergeRelyint[]{}合并单元格依赖关系,比如第二列合并是基于第一列 则{1}就可以了
mergeVerticalbooleanfasle纵向合并内容相同的单元格

注解方式导出

实体类:必须要有空构造函数,否则会报错“对象创建错误”

@Data
@Table(name="tb_user")
public class User {
    @Id
    @KeySql(useGeneratedKeys = true)
    @Excel(name = "编号", orderNum = "0", width = 5)
    private Long id;         //主键
    @Excel(name = "员工名", orderNum = "1", width = 15)
    private String userName; //员工名
    @Excel(name = "手机号", orderNum = "2", width = 15)
    private String phone;    //手机号
    @Excel(name = "省份名", orderNum = "3", width = 15)
    private String province; //省份名
    @Excel(name = "城市名", orderNum = "4", width = 15)
    private String city;     //城市名
    @Excel(name = "工资", orderNum = "5", width = 10)
    private Integer salary;   // 工资
    @JsonFormat(pattern="yyyy-MM-dd")
    @Excel(name = "入职日期",  format = "yyyy-MM-dd",orderNum = "6", width = 15)
    private Date hireDate; // 入职日期
    private String deptId;   //部门id
    @Excel(name = "出生日期",  format = "yyyy-MM-dd",orderNum = "7", width = 15)
    private Date birthday; //出生日期
    @Excel(name = "照片", orderNum = "10",width = 15,type = 2)
    private String photo;    //一寸照片
    @Excel(name = "现在居住地址", orderNum = "9", width = 30)
    private String address;  //现在居住地址
    private List<Resource> resourceList; //办公用品
}

使用EasyPOI方式导出

public void downLoadWithEasyPOI(HttpServletResponse response) throws Exception {
        //文件名,sheet名,文件类型
        ExportParams exportParams = new ExportParams("员工信息列表","数据", ExcelType.XSSF);
        List<User> userList = userMapper.selectAll();

        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, User.class, userList);

        //4.下载
        //一个流两个头
        String fileName = "POI数据导出.xlsx";
        response.setHeader("content-disposition","attachment;filename="+new String(fileName.getBytes(),"ISO8859-1"));
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        //执行
        workbook.write(response.getOutputStream());
    }

注解方式导入

将刚导出的数据库导入到表中

Excel导入时需要的参数类ImportParams常用设置说明:

  1. 读取指定的sheet,比如要读取上传得第二个sheet 需要把startSheetIndex = 1
  2. 读取几个sheet,比如读取前2个sheet,sheetNum=2
  3. 读取第二个到第五个sheet,设置startSheetIndex = 1 然后sheetNum = 4
  4. 读取全部的sheet sheetNum 设置大点就可以了
  5. 保存Excel 设置 needVerfiy = true,默认保存的路径为upload/excelUpload/Test/yyyyMMddHHmss 保存名称上传时间五位随机数 如果自定义路径 修改saveUrl ,同时saveUrl也是图片上传时候的保存的路径
  6. 判断一个Excel是不是合法的Excel,importFields 设置值,表示表头必须至少包含的字段,如果缺一个就是不合法的excel不导入
  7. 图片的导入,导入的配置和导出是一样的,但是需要设置保存路径,设置保存路径saveUrl 默认为"upload/excelUpload" 可以手动修改 ImportParams 修改下就可以了

实体类:

@Data
@Table(name="tb_user")
public class User {
    @Id
    @KeySql(useGeneratedKeys = true) //主键
    //不添加@Excel注解不导出,,isImportField = "true"是否依据注解导入
    @Excel(name="编号",orderNum = "0",width = 5)
    private Long id;    
        
    @Excel(name="员工姓名",orderNum = "1",width = 15,isImportField = "true")
    private String userName; //员工名
    
    @Excel(name="手机号",orderNum = "2",width = 15,isImportField = "true")
    private String phone;    //手机号
    
    @Excel(name="省份",orderNum = "3",width = 15,isImportField = "true")
    private String province; //省份名
    
    @Excel(name="城市",orderNum = "4",width = 15,isImportField = "true")
    private String city;     //城市名
    
    @Excel(name="工资",orderNum = "5",width = 10,type = 10,isImportField = "true")
    private Integer salary;   // 工资
    
    @Excel(name="入职日期",orderNum = "6",width = 15,format = "yyyy-MM-dd",isImportField = "true")
    @JsonFormat(pattern="yyyy-MM-dd")
    private Date hireDate; // 入职日期
   
    //和表属性不对应
    @Transient
    //转json不考虑这个字段
    @JsonIgnore
    private String hireDateStr; // 入职日期-字符串格式
   
    private String deptId;   //部门id
   
    @Excel(name="出生日期",orderNum = "7",width = 15,format = "yyyy-MM-dd",isImportField = "true")
    private Date birthday; //出生日期
   
    //savePath = ""图片存放路径
    @Excel(name="图片",orderNum = "9",width = 15,type = 2,isImportField = "true",savePath = "D:\\java\\idea\\IdeaProject2\\user_management\\src\\main\\resources\\static\\user_photos")
    private String photo;    //一寸照片
   
    @Excel(name="现住址",orderNum = "8",width = 20,isImportField = "true")
    private String address;  //现在居住地址
   
    private List<Resource> resourceList; //办公用品

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                '}';
    }
}

easyPOI导入数据

    /**
     * 使用easyPOI方式导入数据
     */
    public void uploadExcelWithEasyPOI(MultipartFile file) throws Exception {
        ImportParams importParams = new ImportParams();
        importParams.setNeedSave(false);//是否需要保存
        importParams.setTitleRows(1);//大标题占多少行
        importParams.setHeadRows(1);//小标题占多少行
        //输入流,指定类型
        List<User> userList = ExcelImportUtil.importExcel(file.getInputStream(),User.class,importParams);
        for (User user : userList) {
            //数据库中已有id,新增主键报错
            user.setId(null);
            userMapper.insert(user);
        }
    }

根据模板导出数据

采用的写法是{{}}代表表达式,然后根据表达式里面的数据取值,easypoi不会改变excel原有的样式
模板样式:
在这里插入图片描述

   /**
     * 使用EasyPOI,根据模板导出数据
     * @param id
     * @param response
     */
    public void downLoadUserInfoByTemplateEasyPOI(Long id, HttpServletResponse response) throws Exception {
        //1.读取模板
        //获取项目的根目录,创建目录---获取绝对路径
        File rootPath = new File(ResourceUtils.getURL("classpath:").getPath());
        File templateFile = new File(rootPath.getAbsolutePath(), "/excel_template/userInfo3.xlsx");
        //用来做导出的param,模板地址,是否遍历sheet
        TemplateExportParams exportParams = new TemplateExportParams(templateFile.getPath(),true);
        User user = userMapper.selectByPrimaryKey(id);
        //处理图片
        ImageEntity imageEntity = new ImageEntity();
        //图片路径
        imageEntity.setUrl(rootPath+user.getPhoto());
        //设置图片-铺满--占几行,占几列
        imageEntity.setColspan(2);
        imageEntity.setRowspan(4);
        //设置宽,高
        //imageEntity.setWidth(50);
        //imageEntity.setHeight(100);
        Map<String, Object> map = EntityUtils.entityToMap(user);
        map.put("photo",imageEntity);
        //导出
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams,map);
        //4.下载
        //一个流两个头
        String fileName = "EasyPOI用户数据导出.xlsx";
        response.setHeader("content-disposition","attachment;filename="+new String(fileName.getBytes(),"ISO8859-1"));
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        //执行
        workbook.write(response.getOutputStream());
    }

导出CSV

CsvExportParams 的参数描述如下:

属性类型默认值功能
encodingStringUTF8文件编码
spiltMarkString,分隔符
textMarkString字符串识别,可以去掉,需要前后一致
titleRowsint0表格头,忽略
headRowsint1标题
exclusionsString[]0忽略的字段

如果需要导出几百万数据时不可能全部加载到一个List中的,所以easyPOI的方式导出csv是支持不了太大的数据量的,如果导出几百万条数据还是得选择OpenCSV方式导出。

    public void downLoadCSVByEasyPOI(HttpServletResponse response) throws Exception {
        ServletOutputStream outputStream = response.getOutputStream();

        //导出
        String fileName = "csv数据导出.csv";
        response.setHeader("content-disposition","attachment;filename="+new String(fileName.getBytes(),"ISO8859-1"));
        response.setContentType("text/csv");
        
        CsvExportParams csvExportParams = new CsvExportParams();
        List<User> userList = userMapper.selectAll();
        //参数,类型,数据,输出流User.class和excel共用的
        //忽略到图片导出
        csvExportParams.setExclusions(new String[]{"照片"});
        CsvExportUtil.exportCsv(csvExportParams,User.class,userList,outputStream);
    }

导出word(docx)

仅仅支持07版本的word也是只能生成后缀是docx的文档。
列举下EasyPoi支持的指令以及作用,最主要的就是各种fe的用法:

三元运算 {{test ? obj:obj2}}
n: 表示 这个cell是数值类型 {{n:}}
le: 代表长度{{le:()}} 在if/else 运用{{le:() > 8 ? obj1 : obj2}}
fd: 格式化时间 {{fd:(obj;yyyy-MM-dd)}}
fn: 格式化数字 {{fn:(obj;###.00)}}
fe: 遍历数据,创建row
!fe: 遍历数据不创建row
$fe: 下移插入,把当前行,下面的行全部下移.size()行,然后插入
#fe: 横向遍历
v_fe: 横向遍历值
!if: 删除当前列 {{!if:(test)}}
单引号表示常量值 ‘’ 比如’1’ 那么输出的就是 1
&NULL& 空格
&INDEX& 表示循环中的序号,自动添加
]] 换行符 多行遍历导出
sum: 统计数据

模板
在这里插入图片描述

   public void downloadContractByEasyPOI(Long id, HttpServletResponse response) throws Exception {
        //获取模板文档
        //获取项目的根目录,创建目录---获取绝对路径
        File rootPath = new File(ResourceUtils.getURL("classpath:").getPath());
        File templateFile = new File(rootPath.getAbsolutePath(), "word_template/contract_template2.docx");
        //准备数据
        User user = this.findById(id);
        //数据转map
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("userName",user.getUserName());
        hashMap.put("hireDate",simpleDateFormat.format(user.getHireDate()));
        hashMap.put("address",user.getAddress());

        ImageEntity imageEntity = new ImageEntity();
        imageEntity.setUrl(rootPath+user.getPhoto());
        //System.out.println("用户图片"+rootPath+user.getPhoto());
        imageEntity.setHeight(100);
        imageEntity.setWidth(50);
        hashMap.put("picture",imageEntity);
        //resourceList转map
        List<Map> resourceMapList = new ArrayList<>();
        Map<String,Object> map = null;
        for (Resource resource : user.getResourceList()) {
            map = new HashMap<>();
            map.put("name",resource.getName());
            map.put("price",resource.getPrice());
            map.put("needReturn",resource.getNeedReturn());
            //图片处理---在表格中做不到,需要POI
            ImageEntity image = new ImageEntity();
            image.setUrl(templateFile+"/static/"+resource.getPhoto());
            map.put("photo",image);
            resourceMapList.add(map);
        }
        hashMap.put("resourceList",resourceMapList);

        //模板文档结合数据--产生新的文档
        XWPFDocument document = WordExportUtil.exportWord07(templateFile.getPath(), hashMap);

        //4.导出word
        String fileName = "员工"+user.getUserName()+"合同.docx";
        response.setHeader("content-disposition","attachment;filename="+new String(fileName.getBytes(),"ISO8859-1"));
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        document.write(response.getOutputStream());
    }

结果:表格中的图片需要POI来做
在这里插入图片描述

word转pdf

1.环境准备:本机上安装了2007以上的office软件 ,jdk1.6以上的版本
2.下载jar包:地址
3.将jar放入本地仓库,进入到jar所在的目录执行以下命令:

mvn install:install-file -DgroupId=com.jacob -DartifactId=jacob -Dversion=1.19 -Dfile=jacob.jar -Dpackaging=jar

在这里插入图片描述
4.把dll文件放入到 jre\bin 目录下(64位的放x64文件,32位的放x86文件)
在这里插入图片描述
添加依赖

<dependency>
    <groupId>com.jacob</groupId>
    <artifactId>jacob</artifactId>
    <version>1.9</version>
</dependency>

测试代码

package com.itheima.demo;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;

public class JacobDemo {
    public static void main(String[] args) {
        String source = "D:\\李四_合同.docx";
        String target = "D:\\李四_合同.pdf";
        System.out.println("Word转PDF开始启动...");
        ActiveXComponent app = null;
        try {
            // 调用window中的程序
            app = new ActiveXComponent("Word.Application");
            // 调用的时候不显示窗口
            app.setProperty("Visible", false);
            // 获得所有打开的文档
            Dispatch docs = app.getProperty("Documents").toDispatch();
            Dispatch doc = Dispatch.call(docs, "Open", source).toDispatch();
            System.out.println("转换文档到PDF:" + target);
            // 另存为,将文档保存为pdf,其中Word保存为pdf的格式宏的值是17
            Dispatch.call(doc, "SaveAs", target, 17);
            Dispatch.call(doc, "Close");
        } catch (Exception e) {
            System.out.println("Word转PDF出错:" + e.getMessage());
        } finally {
            // 关闭office
            if (app != null) {
                app.invoke("Quit", 0);
            }
        }
    }
}

Excel操作其他文章
EasyExcel的使用
POI操作Excel
POI操作word及百万数据导入导出

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
甘特图(Gantt chart)是一种流程图,用于显示项目或任务的时间表,以及它们之间的关系。它通常用于项目管理和生产流程中,以帮助团队成员更好地了解任务的执行情况和进度。 Java报表软件通常会集成甘特图功能,以便于用户在报表中展示项目进度和任务安排。以下是一个深度解析Java报表软件中甘特图的实现过程: 1. 数据准备:首先,需要准备好要在甘特图中展示的数据。这些数据通常包括任务的名称、开始时间、结束时间和持续时间等信息。 2. 甘特图模板设计:在Java报表软件中,需要设计一个甘特图模板,以便于在报表中展示甘特图。模板通常包括甘特图的样式、布局、颜色等信息。 3. 数据绑定:将准备好的数据与甘特图模板进行绑定,以便于在报表中展示。数据绑定可以通过代码实现,也可以通过可视化界面完成。 4. 样式设置:在绑定数据后,需要对甘特图的样式进行设置。这包括颜色、字体、大小等方面的设置,以便于让甘特图更加美观和易于理解。 5. 事件处理:在Java报表软件中,甘特图通常会支持用户交互,例如点击任务以查看详细信息等。因此,需要对甘特图的事件进行处理,以实现这些功能。 6. 导出报表:最后,需要将设计好的甘特图报表导出成PDF、Excel或其他格式,以便于用户进行查看和分享。 总之,Java报表软件中的甘特图实现过程比较复杂,需要考虑到数据准备、模板设计、数据绑定、样式设置、事件处理等方面。但是,通过这些步骤,可以实现一个功能强大、易于使用的甘特图报表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值