首页 > 编程语言 >Java中使用easyexcel导入导出数据

Java中使用easyexcel导入导出数据

时间:2024-03-19 14:13:27浏览次数:25  
标签:Java String int easyexcel excel private 导入 new import

  工作中常常遇到导入导出Excel数据,还需要设置表格边框、合并单元格、字体居中等等各种样式,尝试了多种方式觉得阿里的easyexcel挺好使,记录一下使用、表格样式如下:

  导入依赖

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>2.2.3</version>
</dependency>

  创建导出实体类

@HeadRowHeight(38)  //设置标题行高
@Data
public class SwhcBdcVo implements Serializable {

    @ExcelProperty(value = { "基本信息", "序号" }, index = 0)  //需要在表格显示的列
    @ColumnWidth(6)   //每列占用的宽度,列宽
    private String xh;

    @ExcelProperty(value = { "基本信息", "姓名" }, index = 1)
    @ColumnWidth(8)
    private String qlrmc;

    @ExcelProperty(value = { "基本信息", "性别" }, index = 2)
    @ColumnWidth(6)
    private String xb;

    @ExcelProperty(value = { "基本信息", "身份证号" }, index = 3)
    @ColumnWidth(16)
    private String qlrzjh;

    @ExcelProperty(value = {"不动产信息", "房产来源(去向)" }, index = 4)
    @ColumnWidth(30)
    private String qx;

    @ExcelProperty(value = {"不动产信息", "具体地址" }, index = 5)
    @ColumnWidth(30)
    private String dz;

    @ExcelProperty(value = {"不动产信息", "建筑面积(m²)" }, index = 6)
    @ColumnWidth(11)
    private BigDecimal jzmj;

    @ExcelProperty(value = {"不动产信息", "产权性质" }, index = 7)
    @ColumnWidth(11)
    private String cqxz;

    @ExcelProperty(value = {"不动产信息", "登记时间(年月)" }, index = 8)
    @ColumnWidth(11)
    private String djsj;

    @ExcelProperty(value = {"不动产信息", "交易价格(万元)" }, index = 9)
    @ColumnWidth(11)
    private BigDecimal jyjg;

    @ExcelProperty(value = "备注", index = 10)
    @ColumnWidth(24)
    private String bz;

    @ExcelIgnore  //不需要在表格展示的字段
    private String ywh;

    @ExcelIgnore
    private Date compareDjsj;

}

  生成Excel模板

public void generateTemplate(HttpServletResponse response) {
		SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMddHHmmss");
		String fileName = URLEncoder.encode(String.format("%s.xlsx", sdf2.format(new Date())),
				StandardCharsets.UTF_8.toString());
		response.setContentType("application/force-download");
		response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

		// 这里 需要指定写用哪个class去写
		ExcelWriter writer = new ExcelWriterBuilder()
				.autoCloseStream(true)
				.excelType(ExcelTypeEnum.XLSX)
				.file(response.getOutputStream())
				.head(SwhcBdcVo.class)
				// 核心代码:表头和正文的样式在此
				.registerWriteHandler(setConfigure())
				.build();
		WriteSheet writeSheetfw = new WriteSheet();
		writeSheetfw.setSheetName("Sheet1");
		writer.write(null, writeSheetfw);
		// 关闭流
		writer.finish();
	}

  数据导入读取

public R dr(MultipartFile file) {
		if (!StrUtil.endWithAny(file.getOriginalFilename(), ".xls", ".xlsx")) {
			return R.failed("上传的文件不是excel");
		}
		List<SwhcBdcVo> drList = EasyExcelUtil.readExcel(file, "Sheet1", SwhcBdcVo.class, 2);    //2为表格标题占用的行数,读取跳过标题
		if (CollUtil.isEmpty(drList )) {
			return R.failed("未获取到导入表格数据");
		}
}

  EasyExcelUtil工具类

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class EasyExcelUtil {

	public static <T> List<T> readExcel(MultipartFile excel, String sheetName, Class<T> clazz, int headLineNum)
			throws IOException {
		ExcelReaderBuilder readerBuilder = getReader(excel);
		if (readerBuilder == null) {
			return null;
		}
		ExcelReaderSheetBuilder sheet = readerBuilder.sheet(sheetName);
		if (sheet == null) {
			return null;
		}
		sheet.head(clazz).headRowNumber(headLineNum);

		return sheet.doReadSync();
	}

	private static ExcelReaderBuilder getReader(MultipartFile excel) throws IOException {
		String filename = excel.getOriginalFilename();
		if (filename != null && (filename.toLowerCase().endsWith(".xls") || filename.toLowerCase().endsWith(".xlsx"))) {
			InputStream is = new BufferedInputStream(excel.getInputStream());
			return EasyExcel.read(is);
		} else {
			return null;
		}
	}
}

  数据生成到表格

log.info("-------开始数据写表操作------------------");
        //查询到的数据写入Excel表格,表格文件传入minio
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        //需要合并的列
        int[] mergeColumeIndex = {0,1,2,3};
        //从第三行后开始合并
        int mergeRowIndex = 2;
        // 调用合并单元格工具类,此工具类是根据工程名称相同则合并后面数据
        ExcelFillCellMergeStrategy excelFillCellMergeStrategy = new ExcelFillCellMergeStrategy(mergeRowIndex, mergeColumeIndex);
        EasyExcel.write(out, SwhcBdcVo.class)
                .autoCloseStream(true)
                .excelType(ExcelTypeEnum.XLSX)
                .head(SwhcBdcVo.class)
                // 核心代码:表头和正文的样式在此
                .registerWriteHandler(setConfigure())
                .registerWriteHandler(excelFillCellMergeStrategy)
                .sheet("Sheet1")
                .doWrite(totalPersonBdcList);
        byte[] bs = out.toByteArray();
        out.close();
        try (XSSFWorkbook workbook = new XSSFWorkbook(new ByteArrayInputStream(bs));
             OutputStream out1 = new FileOutputStream("./测试文件.xlsx")) {
            workbook.write(out1);
            log.info("-----------写入文件结束------------");
        }

  设置标题样式和内容样setConfigure()方法

//配置字体,表头背景等
    private static HorizontalCellStyleStrategy setConfigure() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE1.getIndex()); // 白色背景
        WriteFont headWriteFont = new WriteFont();

        // 加粗
//        headWriteFont.setBold(true);
//        headWriteFont.setFontHeightInPoints((short) 14); // 设置行高,不重要
        headWriteCellStyle.setWriteFont(headWriteFont);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 字体策略
        WriteFont contentWriteFont = new WriteFont();
        // 字体大小
//        contentWriteFont.setFontHeightInPoints((short) 14);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //导出数据垂直居中
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //导出数据水平居中
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 设置边框
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);

        //设置 自动换行
        //contentWriteCellStyle.setWrapped(true);

        //设置
        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }

  设置内容合并策略,指定列的内容相同,单元格合并

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.Data;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

@Data
public class ExcelFillCellMergeStrategy implements CellWriteHandler {

    private int[] mergeColumnIndex;
    private int mergeRowIndex;

    public ExcelFillCellMergeStrategy() {
    }

    public ExcelFillCellMergeStrategy(int mergeRowIndex, int[] mergeColumnIndex) {
        this.mergeRowIndex = mergeRowIndex;
        this.mergeColumnIndex = mergeColumnIndex;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        //当前行
        int curRowIndex = cell.getRowIndex();
        //当前列
        int curColIndex = cell.getColumnIndex();

        if (curRowIndex > mergeRowIndex) {
            for (int i = 0; i < mergeColumnIndex.length; i++) {
                if (curColIndex == mergeColumnIndex[i]) {
                    mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex);
                    break;
                }
            }
        }
    }


    /**
     * 当前单元格向上合并
     *
     * @param writeSheetHolder
     * @param cell             当前单元格
     * @param curRowIndex      当前行
     * @param curColIndex      当前列
     */
    private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) {
        //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并
        Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : cell.getNumericCellValue();
        Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex);
        Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : preCell.getNumericCellValue();

        // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行
        if (curData.equals(preData)) {
            Sheet sheet = writeSheetHolder.getSheet();
            List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
            boolean isMerged = false;
            for (int i = 0; i < mergeRegions.size() && !isMerged; i++) {
                CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
                if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) {
                    sheet.removeMergedRegion(i);
                    cellRangeAddr.setLastRow(curRowIndex);
                    sheet.addMergedRegion(cellRangeAddr);
                    isMerged = true;
                }
            }
            // 若上一个单元格未被合并,则新增合并单元
            if (!isMerged) {
                CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, curColIndex);
                sheet.addMergedRegion(cellRangeAddress);
            }
        }
    }
}

  

标签:Java,String,int,easyexcel,excel,private,导入,new,import
From: https://www.cnblogs.com/zhuifenglang/p/18082623

相关文章

  • Java基础知识总结(下)
    本文部分内容节选自JavaGuide,地址:https://javaguide.cn/java/basis/java-basic-questions-03.html......
  • 分月饼【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-分月饼中秋节,公司分月饼,m个员工,买了n个月饼,m<=n,每个员工至少分1个月饼,但可以分多个,单人分到最多月饼的个数是Max1,单人分到第二多月饼个数是Max2,Max1-Max2<=3,单人分到第n-1多月饼个数是Max(n-1),单人分到第n多月饼个数是Max(n),Max(n-1)–Max(n)<=3,问有多少......
  • springboot+vue流浪动物宠物救助网站java-ssm
    系统包含两种角色:管理员、用户,系统分为前台和后台两大模块,主要功能如下。技术栈ide工具:IDEA或者eclipse编程语言:java数据库:mysql5.7+框架:springboot前端:vue.js+ElementUI详细技术:springboot+vue+MYSQL+MAVEN数据库工具:Navicat/SQLyog都可以前台:﹣动物领养/捐赠:......
  • springboot+vue中药知识科普网站java-ssm
    系统包含两种角色:管理员、用户,系统分为前台和后台两大模块,主要功能如下。技术栈ide工具:IDEA或者eclipse编程语言:java数据库:mysql5.7+框架:springboot前端:vue.js+ElementUI详细技术:springboot+vue+MYSQL+MAVEN数据库工具:Navicat/SQLyog都可以前台:﹣首页:展示网站......
  • java基于springboot的羽毛球馆场地预约管理系统ssm
    jdk版本:1.8及以上ide工具:IDEA或者eclipse数据库:mysql 编程语言:nodejs框架:springboot/springboot都有maven:3.6.1前端:layui+bootstrap+jsp详细技术:HTML+CSS+JS+jsp+springmvc+mybatis+MYSQL+MAVEN+tomcat羽毛球馆管理系统采用B/S架构,数据库是MySQL。网站的搭建......
  • java基于Spring boot+vue的小区物业报修缴费居民论坛交流系统ssm
    系统包含两种角色:管理员、用户,系统分为前台和后台两大模块,主要功能如下。技术栈ide工具:IDEA或者eclipse编程语言:java数据库:mysql5.7+框架:springboot前端:vue.js+ElementUI详细技术:springboot+vue+MYSQL+MAVEN数据库工具:Navicat/SQLyog都可以前台:1.首页:展示小区......
  • java社保费自助缴费系统(ssm框架毕业设计)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义标题:社保费自助缴费系统的引入背景在信息技术飞速发展的今天,传统的社保费缴纳方式已逐渐不能满足人们的需求。以往,社会保险费的缴纳往往需要通过单位代扣代缴或亲......
  • java社会职业技能培训管理平台(ssm框架毕业设计)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义标题:构建社会职业技能培训管理平台的必要性随着经济社会的快速发展和产业结构的不断升级,传统的职业培训模式已难以满足市场对高技能人才的迫切需求。企业对于专业......
  • 使用Java给图片添加水印
    什么是水印呢?比如使用手机拍摄一张照片的时候,照片右下角的位置显示得有日期和时间信息,那就表示一个水印。 项目开发中给图片添加水印的操作很常见,比如给图片添加日期和时间,给图片添加公司的logo之类的等等。下面就来聊聊如何使用Java来给图片添加水印。大致的思路如下:实......
  • Java-Java基础学习(2)-网络编程-TCP-UDP
    2.网络编程2.1.通信协议TCP、UDP对比TCP打电话连接,稳定三次握手,四次挥手三次握手A:你瞅啥?B:瞅你咋地?A:干一场!四次挥手A:我要走了B:你真的要走了吗?B:你真的真的要走了吗?A:我真的要走了客户端、服务端传输完成,释放连接,效率低UDP发短信不连......