目 录CONTENT

文章目录

EasyPoi的使用

Jinty
2023-12-27 / 0 评论 / 0 点赞 / 20 阅读 / 15293 字

EasyPoi的简单使用

依赖引入

        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>${easypoi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

编写导出实体类

Company.java

package cn.com.jcoo.model;

import cn.afterturn.easypoi.excel.annotation.*;
import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;

@Data
@Builder
@ExcelTarget("company")
public class Company {

	Long keyId;

	@Excel(name = "机构名称", width = 20, needMerge = true)
	@NotNull
	String companyName;

	@Excel(name = "机构地址", width = 25, needMerge = true)
	String companyAddress;

	@Excel(name = "成立日期", format = "yyyy/MM/dd", needMerge = true)
	Date foundingDate;

	@Excel(name = "员工人数", needMerge = true)
	// @Min(value = 1, message = "员工人数不能少于1")
	// @Max(value = 10000000, message = "员工人数不能大于10000000")
	Integer totalEmployees;

	@Excel(name = "是否公立", needMerge = true)
	String publicMate;

	@ExcelIgnore
	Boolean isPublic;

	public Boolean getPublic() {
		return StringUtils.endsWith(publicMate, "是");
	}

	@Excel(name = "网站地址")
	// @Pattern(regexp = "^(http|https)://[a-zA-Z0-9-.]+.[a-zA-Z]{2,}(/\\S*)?$", message =
	// "网站地址格式不正确")
	String officialWebsite;

	@ExcelEntity(id = "leader", name = "领导人")
	User leader;

	@ExcelCollection(name = "部门")
	List<Department> departments;
}

Department.java

package cn.com.jcoo.model;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
@ExcelTarget("department")
public class Department {
	Long keyId;

	/**
	 * @see Company#keyId
	 */
	Long companyId;

	@Excel(name = "部门名称", needMerge = true)
	String dptName;

	@Excel(name = "部门职责", needMerge = true)
	String dptJob;

	@ExcelEntity(id = "manager", name = "部门负责人")
	User manager;

	// 这里加这个导出存在问题
	// @ExcelCollection(id = "cym", name = "管理层")
	// List<User> managers;

	@ExcelCollection(name = "工作小组")
	List<Group> groups;

}

Group.java

package cn.com.jcoo.model;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelCollection;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
@ExcelTarget("group")
public class Group {
	Long keyId;

	/**
	 * {@link Department#keyId}
	 */
	String dptId;

	@Excel(name = "工作组名称", needMerge = true)
	String groupName;

	@ExcelEntity(id = "grouper", name = "组长")
	User grouper;

	@ExcelCollection(id = "member", name = "成员")
	List<User> members;
}

User.java

package cn.com.jcoo.model;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Builder;
import lombok.Data;

import java.math.BigDecimal;

@Data
@Builder
@ExcelTarget("user")
public class User {
	Long keyId;

	@Excel(name = "法人_leader,成员_cym,部门负责人_manager,组长_grouper,小组成员_member", needMerge = true)
	String username;

	@Excel(name = "年龄", needMerge = true)
	Integer age;

	@Excel(name = "收入", needMerge = true)
	BigDecimal revenue;

}

测试导出功能

ExportTest.java

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.com.jcoo.model.Company;
import cn.com.jcoo.model.Department;
import cn.com.jcoo.model.Group;
import cn.com.jcoo.model.User;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Slf4j
public class ExportTest {
	@SneakyThrows
	@Test
	public void testExport() {
		User jcoo = User.builder().username("Jcoo").age(28)
				.revenue(new BigDecimal("30000")).build();
		User alice = User.builder().username("alice").revenue(new BigDecimal("25000.89"))
				.age(25).build();
		User ben = User.builder().username("ben").revenue(new BigDecimal("20000")).age(27)
				.build();

		Group java1DevGroup = Group.builder().groupName("Java研发一组").grouper(ben)
				.members(Lists.newArrayList(ben)).build();

		Group java2DevGroup = Group.builder().groupName("Java研发二组").grouper(alice)
				.members(Lists.newArrayList(alice, jcoo)).build();

		Department dev = Department.builder().dptName("研发部")
				.groups(Lists.newArrayList(java1DevGroup, java2DevGroup)).manager(alice)
				.build();

		Department manage = Department.builder().dptName("管理层")
				.groups(Lists.newArrayList())
				// .managers(Lists.newArrayList(alice, jcoo))
				.manager(jcoo).build();

		Company company = Company.builder().companyName("xx技术有限责任公司").leader(jcoo)
				.companyAddress("四川成都xx").departments(Lists.newArrayList(manage, dev))
				.build();

		List<Company> companies = Lists.newArrayList(company);

		ExportParams exportParams = new ExportParams();
		exportParams.setType(ExcelType.XSSF);
		exportParams.setSheetName("机构");

		String now = new SimpleDateFormat("yyyyMMddmmHHss").format(new Date());
		String filename = "机构" + now + ".xlsx";
		try (Workbook sheets = ExcelExportUtil.exportExcel(exportParams, Company.class,
				companies)) {
			File file = new File(filename);
			try (FileOutputStream fos = new FileOutputStream(file)) {
				sheets.write(fos);
			}
		}

	}
}

测试结果:

其中黑色部分是应该要合并单元格的,但是实际却没有合并。

excel模板填充导出

jszzyhwzb.xlsx(resource路径的template/zzjs/下)

Object cacheObject = redisService.getCacheObject("zzjs:pausetasklist:zbdata");
if (cacheObject != null) {
    String time = DateUtil.now();
    Object obj = redisService.getCacheObject("zzjs:pausetasklist:cachetime");
    if (obj != null) {
        time = (String) obj;
    }
    String date = DateUtil.format(DateUtil.parse(time), "yy年MM月dd日");

    List<PauseTaskZbVo> zb = JacksonUtils.parseList((String)cacheObject, PauseTaskZbVo.class);
    if (zb == null) {
        return;
    }
    TemplateExportParams params = new TemplateExportParams("template/zzjs/jszzyhwzb.xlsx", true);
    List<PauseTaskVo> pauseTaskList = evoaPauseAndRecoverService.getPauseTaskList(false, false);
    Map<String, Object> map = evoaPauseAndRecoverService.getZbDataMap(date, zb, pauseTaskList);
    try (Workbook workbook = ExcelExportUtil.exportExcel(params, map)) {
        String filename = "计时中止与恢复模块-数据排查周报(截止" + date + ").xlsx";
        response.setCharacterEncoding("UTF-8");
        response.setHeader("content-Type", "application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        workbook.write(response.getOutputStream());
    } catch (Exception e) {
        log.error(e.getMessage());
    }
}

public Map<String, Object> getZbDataMap(String date, List<PauseTaskZbVo> zb, List<PauseTaskVo> pauseTaskList) {
    Map<String, Object> map = new HashMap<>();
    map.put("date", date);
    List<PauseTaskVo> wttasklist = new ArrayList<>();
    for (PauseTaskZbVo pauseTaskZbVo : zb) {
        List<PauseTaskVo> pauseTaskVoList = pauseTaskZbVo.getPauseTaskVoList();
        int pausecount = ListUtil.isEmpty(pauseTaskVoList) ? 0 : pauseTaskVoList.size();
        map.put(pauseTaskZbVo.getSeq()+"pausecount", pausecount);

        List<PauseTaskVo> pauseTaskVoWtList = pauseTaskZbVo.getPauseTaskVoWtList();
        int wtcount = ListUtil.isEmpty(pauseTaskVoWtList) ? 0 : pauseTaskVoWtList.size();
        map.put(pauseTaskZbVo.getSeq()+"wtcount", wtcount);
        if  (wtcount > 0) {
            wttasklist.addAll(pauseTaskVoWtList);
        }
    }
    wttasklist = wttasklist.stream().filter(distinctByKey(PauseTaskVo::getSeq)).collect(Collectors.toList());
    map.put("wttasklist", wttasklist);
    map.put("allwtcount", wttasklist.size());
    map.put("allpausetask", pauseTaskList);
    map.put("allpausecount", ListUtil.isEmpty(pauseTaskList) ? 0 : pauseTaskList.size());
    return map;
}

大批量导出

使用EasyExportUtil中的exportBigExcel方法

    @SneakyThrows
    @GetMapping("/download")
    public void download(HttpServletResponse response) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        List<CompletableFuture<Company>> companyGenFutures = new ArrayList<>();

        for (int i = 0; i < 10000; i++) {
            int finalI = i;
            companyGenFutures.add(CompletableFuture.supplyAsync(() -> genData("xxx" + finalI + "公司", "四川" + finalI + "地址"), executorService));
        }
        CompletableFuture.allOf(companyGenFutures.toArray(new CompletableFuture[0])).join();

        List<Company> companies = new ArrayList<>();
        for (CompletableFuture<Company> companyGenFuture : companyGenFutures) {
            Company company = companyGenFuture.get();
            companies.add(company);
        }

        ExportParams exportParams = new ExportParams();
        exportParams.setType(ExcelType.XSSF);
        exportParams.setSheetName("机构");

        String now = new SimpleDateFormat("yyyyMMddmmHHss").format(new Date());
        String filename = "机构" + now + ".xlsx";
		// v4.4.0
        ExcelUtils.batchDownload(companies, Company.class, filename, 200, exportParams, response);
        // v3.2.0
//        Workbook sheets = ExcelExportUtil.exportBigExcel(exportParams, Company.class, companies);
//        ExcelUtils.download(sheets, response, filename);

//        // 将 Excel 写入文件或输出流
//        File file = new File("C:\\alice\\temp\\company.xlsx");
//        FileOutputStream out = new FileOutputStream(file);
//        sheets.write(out);
//        out.close();

    }


@SuppressWarnings("unused")
public class ExcelUtils {

    public static final MediaType MS_EXCEL = new MediaType("application", "vnd.ms-excel");

    public static final String MS_EXCEL_VALUE = "application/vnd.ms-excel;charset=UTF-8";

    public static void download(List<?> dataList, Class<?> pojoClass, String filename,
                                ExportParams exportParams,
                                HttpServletResponse response) throws IOException {
        try (Workbook sheets = ExcelExportUtil.exportExcel(exportParams, pojoClass, dataList)) {
            download(sheets, response, filename);
        }
    }

    // v4.4.0
    public static void batchDownload(List<?> dataList, Class<?> pojoClass, String filename,
                                int batchSize,
                                ExportParams exportParams,
                                HttpServletResponse response) throws IOException {
        int total = dataList.size();
        int pageCount = total / batchSize + (total % batchSize == 0 ? 0 : 1);
        try (Workbook sheets = ExcelExportUtil.exportBigExcel(exportParams, pojoClass, (o, i) -> {
            if ((int) o < i) {
                return null;
            }

            int skip = (i - 1) * batchSize;
            return dataList.stream().skip(skip).limit(batchSize).collect(Collectors.toList());
        }, pageCount)) {
            download(sheets, response, filename);
        }
    }

    public static void download(Workbook sheets, HttpServletResponse response, String filename) throws IOException {
//        response.setHeader(HttpHeaders.CONTENT_TYPE, MS_EXCEL_VALUE);
        response.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, getDisposition(filename));
        ServletOutputStream outputStream = response.getOutputStream();
        sheets.write(outputStream);
    }

    @SneakyThrows
    private static String getDisposition(String filename) {
        return "attachment;filename=" + new String((filename).getBytes("GB2312"), StandardCharsets.ISO_8859_1);
    }

}

注意事项:

  1. 不同版本对应的用法有所更改

  2. 效率与导出类的复杂程度正相关, 一对多关系越多效率越低,建议不使用一对多

参考资料

  1. http://doc.wupaas.com/docs/easypoi/easypoi-1c0u8jachdq52

0

评论区