EasyExcel导出带下拉选数据的Excel数据导入模板

这篇具有很好参考价值的文章主要介绍了EasyExcel导出带下拉选数据的Excel数据导入模板。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

#因为项目中需要导入一些信息,但是这些信息比较不常见,且在项目字典数据中维护有这些数据,所以在导出模板的时候,把这些数据一并导出,可以减少用户的编写,避免在导入的时候因为数据错误,发生一些业务问题

直接开始

一、首先引入依赖   easyexcel依赖

<!--easyexcel依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.10</version>
        </dependency>

二、创建自定义注解



import java.lang.annotation.*;

/**
 * 标注导出的列为下拉框类型,并为下拉框设置内容
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelSelected {
	/**
	 * 固定下拉内容
	 */
	String[] source() default {};

	/**
	 * 动态下拉内容
	 */
	Class<? extends ExcelDynamicSelect>[] sourceClass() default {};

	/**
	 * 设置下拉框的起始行,默认为第二行
	 */
	int firstRow() default 1;

	/**
	 * 设置下拉框的结束行,默认为最后一行
	 */
	int lastRow() default 0x10000;
}

三、解析自定义注解接口


public interface ExcelDynamicSelect {
	/**
	 * 获取动态生成的下拉框可选数据
	 * @return 动态生成的下拉框可选数据
	 */
	String[] getSource();
}

四、创建一个实体类,(这边以我项目内的演示)

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import org.springblade.basicdata.service.impl.DeptTemplateServiceImpl;
import org.springblade.basicdata.service.impl.SchoolTemplateServiceImpl;
import org.springblade.basicdata.service.impl.StationlateServiceImpl;
import org.springblade.basicdata.service.impl.ZgTypeslateServiceImpl;

import java.io.Serializable;


@Data
@HeadRowHeight(20)
@ContentRowHeight(18)
public class TeacherExcel implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 职工编号
	 */
	@ExcelProperty(index = 0, value = "职工编号")
	@ColumnWidth(20)
	private String no;
	/**
	 * 姓名
	 */
	@ExcelProperty(index = 1, value = "姓名")
	@ColumnWidth(30)
	private String name;
	/**
	 * 身份证
	 */
	@ExcelProperty(index = 2, value = "身份证号")
	@ColumnWidth(25)
	private String idCard;

	/**
	 * 电话
	 */
	@ExcelProperty(index = 3, value = "联系电话")
	@ColumnWidth(15)
	private String phone;
	/**
	 * 学校id
	 */
    //需要自定义实现  SchoolTemplateServiceImpl,下面有具体的实现方式
	@ExcelSelected(sourceClass = SchoolTemplateServiceImpl.class)
	@ExcelProperty(index = 4, value = "校区")
	@ColumnWidth(45)
	private String schoolName;
	/**
	 * 部门
	 */
    //需要自定义实现  DeptTemplateServiceImpl,下面有具体的实现方式
	@ExcelSelected(sourceClass = DeptTemplateServiceImpl.class)
	@ExcelProperty(index = 5, value = "部门")
	@ColumnWidth(45)
	private String bumenName;
	/**
	 * 岗位类别
	 */
    //需要自定义实现  StationlateServiceImpl,下面有具体的实现方式
	@ExcelSelected(sourceClass = StationlateServiceImpl.class)
	@ExcelProperty(index = 6, value = "岗位类别")
	@ColumnWidth(15)
	private String station;
	/**
	 * 职工类型
	 */
    //需要自定义实现  ZgTypeslateServiceImpl,下面有具体的实现方式
	@ExcelSelected(sourceClass = ZgTypeslateServiceImpl.class)
	@ExcelProperty(index = 7, value = "职工类型")
	@ColumnWidth(15)
	private String zhigongleibie;
	/**
	 * 备注
	 */
	@ExcelProperty(index = 8, value = "备注")
	@ColumnWidth(15)
	private String remarks;


}

五、重点是以下的代码

1、以岗位类型为例,展示数据的实现方式

创建StationlateServiceImpl实现类,实现方法 为我自己的业务需求,你们可以根据你们的情况去修改,这边返回给注解的是一个字符串的数组,也就是需要导出的下拉选数据


import java.util.List;
import java.util.stream.Collectors;

/**
 * 岗位类别下拉选数据实现类
 */
public class StationlateServiceImpl implements ExcelDynamicSelect {

	private static IDictClient dictClient;


	static {
		dictClient = SpringUtil.getBean(IDictClient.class);
	}



	@Override
	public String[] getSource() {
		R<List<Dict>> dictClientList =
			dictClient.getList(DictEnum.POST_TYPE.getName());
		if(Func.isNotEmpty(dictClientList) && dictClientList.getCode() == 200){
			if(Func.isNotEmpty(dictClientList.getData())){
				return Func.toStrArray(dictClientList.getData().stream().map(Dict::getDictValue).collect(Collectors.joining(",")));
			}
		}
		return new String[0];
	}
}

Func.toStrArray方法就是讲给定的逗号拼接的字符串转为字符串数组,这个百度一下,一大堆

六、EasyExcelUtil工具类

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.WriteSheet;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Slf4j
public class EasyExcelUtil {

	/**
	 * 创建即将导出的sheet页(sheet页中含有带下拉框的列)
	 * @param head 导出的表头信息和配置
	 * @param sheetNo sheet索引
	 * @param sheetName sheet名称
	 * @param <T> 泛型
	 * @return sheet页
	 */
	public static <T> WriteSheet writeSelectedSheet(Class<T> head, Integer sheetNo, String sheetName) {
		Map<Integer, ExcelSelectedResolve> selectedMap = resolveSelectedAnnotation(head);

		return EasyExcel.writerSheet(sheetNo, sheetName)
			.head(head)
			.registerWriteHandler(new SelectedSheetWriteHandler(selectedMap))
			.build();
	}

	/**
	 * 解析表头类中的下拉注解
	 * @param head 表头类
	 * @param <T> 泛型
	 * @return Map<下拉框列索引, 下拉框内容> map
	 */
	private static <T> Map<Integer, ExcelSelectedResolve> resolveSelectedAnnotation(Class<T> head) {
		Map<Integer, ExcelSelectedResolve> selectedMap = new HashMap<>();

		// getDeclaredFields(): 返回全部声明的属性;getFields(): 返回public类型的属性
		Field[] fields = head.getDeclaredFields();
		for (int i = 0; i < fields.length; i++){
			Field field = fields[i];
			// 解析注解信息
			ExcelSelected selected = field.getAnnotation(ExcelSelected.class);
			ExcelProperty property = field.getAnnotation(ExcelProperty.class);
			if (selected != null) {
				ExcelSelectedResolve excelSelectedResolve = new ExcelSelectedResolve();
				String[] source = excelSelectedResolve.resolveSelectedSource(selected);
				if (source != null && source.length > 0){
					excelSelectedResolve.setSource(source);
					excelSelectedResolve.setFirstRow(selected.firstRow());
					excelSelectedResolve.setLastRow(selected.lastRow());
					if (property != null && property.index() >= 0){
						selectedMap.put(property.index(), excelSelectedResolve);
					} else {
						selectedMap.put(i, excelSelectedResolve);
					}
				}
			}
		}
		return selectedMap;
	}

	public static boolean isIDNumber(String IDNumber) {
		if (IDNumber == null || "".equals(IDNumber)) {
			return false;
		}
		// 定义判别用户身份证号的正则表达式(15位或者18位,最后一位可以为字母)
		String regularExpression = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|" +
			"(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
		//假设18位身份证号码:41000119910101123X  410001 19910101 123X
		//^开头
		//[1-9] 第一位1-9中的一个      4
		//\\d{5} 五位数字           10001(前六位省市县地区)
		//(18|19|20)                19(现阶段可能取值范围18xx-20xx年)
		//\\d{2}                    91(年份)
		//((0[1-9])|(10|11|12))     01(月份)
		//(([0-2][1-9])|10|20|30|31)01(日期)
		//\\d{3} 三位数字            123(第十七位奇数代表男,偶数代表女)
		//[0-9Xx] 0123456789Xx其中的一个 X(第十八位为校验值)
		//$结尾

		//假设15位身份证号码:410001910101123  410001 910101 123
		//^开头
		//[1-9] 第一位1-9中的一个      4
		//\\d{5} 五位数字           10001(前六位省市县地区)
		//\\d{2}                    91(年份)
		//((0[1-9])|(10|11|12))     01(月份)
		//(([0-2][1-9])|10|20|30|31)01(日期)
		//\\d{3} 三位数字            123(第十五位奇数代表男,偶数代表女),15位身份证不含X
		//$结尾
		boolean matches = IDNumber.matches(regularExpression);

		//判断第18位校验值
		if (matches) {

			if (IDNumber.length() == 18) {
				try {
					char[] charArray = IDNumber.toCharArray();
					//前十七位加权因子
					int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
					//这是除以11后,可能产生的11位余数对应的验证码
					String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
					int sum = 0;
					for (int i = 0; i < idCardWi.length; i++) {
						int current = Integer.parseInt(String.valueOf(charArray[i]));
						int count = current * idCardWi[i];
						sum += count;
					}
					char idCardLast = charArray[17];
					int idCardMod = sum % 11;
					if (idCardY[idCardMod].toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) {
						return true;
					} else {
						return false;
					}

				} catch (Exception e) {
					e.printStackTrace();
					return false;
				}
			}
			return false;
		}
		return matches;
	}


	public static  boolean isMobile(String phone){
		Pattern p = null;
		Matcher m = null;
		boolean b = false;
		// 验证手机号
		String s2="^[1](([3|5|6|7|8|9][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$";
		if(StringUtils.isNotBlank(phone)){
			p = Pattern.compile(s2);
			m = p.matcher(phone);
			b = m.matches();
		}
		return b;
	}

}

七、SelectedSheetWriteHandler


import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddressList;

import java.util.Map;

@Data
@AllArgsConstructor
public class SelectedSheetWriteHandler implements SheetWriteHandler {

	private final Map<Integer, ExcelSelectedResolve> selectedMap;

	/**
	 * 设置阈值,避免生成的导入模板下拉值获取不到,可自行设置数量大小
	 */
	private static final Integer LIMIT_NUMBER = 25;

	/**
	 * Called before create the sheet
	 */
	@Override
	public void beforeSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {

	}

	/**
	 * Called after the sheet is created
	 */
	@Override
	public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
		// 这里可以对cell进行任何操作
		Sheet sheet = writeSheetHolder.getSheet();
		DataValidationHelper helper = sheet.getDataValidationHelper();
		selectedMap.forEach((k, v) -> {
			// 设置下拉列表的行: 首行,末行,首列,末列
			CellRangeAddressList rangeList = new CellRangeAddressList(v.getFirstRow(), v.getLastRow(), k, k);
			// 如果下拉值总数大于25,则使用一个新sheet存储,避免生成的导入模板下拉值获取不到
			if (v.getSource().length > LIMIT_NUMBER) {
				//定义sheet的名称
				//1.创建一个隐藏的sheet 名称为 hidden + k
				String sheetName = "hidden" + k;
				Workbook workbook = writeWorkbookHolder.getWorkbook();
				Sheet hiddenSheet = workbook.createSheet(sheetName);
				for (int i = 0, length = v.getSource().length; i < length; i++) {
					// 开始的行数i,列数k
					hiddenSheet.createRow(i).createCell(k).setCellValue(v.getSource()[i]);
				}
				Name category1Name = workbook.createName();
				category1Name.setNameName(sheetName);
				String excelLine = getExcelLine(k);
				// =hidden!$H:$1:$H$50  sheet为hidden的 H1列开始H50行数据获取下拉数组
				String refers = "=" + sheetName + "!$" + excelLine + "$1:$" + excelLine + "$" + (v.getSource().length + 1);
				// 将刚才设置的sheet引用到你的下拉列表中
				DataValidationConstraint constraint = helper.createFormulaListConstraint(refers);
				DataValidation dataValidation = helper.createValidation(constraint, rangeList);
				writeSheetHolder.getSheet().addValidationData(dataValidation);
				// 设置存储下拉列值得sheet为隐藏
				int hiddenIndex = workbook.getSheetIndex(sheetName);
				if (!workbook.isSheetHidden(hiddenIndex)) {
					workbook.setSheetHidden(hiddenIndex, true);
				}
			}
			// 设置下拉列表的值
			DataValidationConstraint constraint = helper.createExplicitListConstraint(v.getSource());
			// 设置约束
			DataValidation validation = helper.createValidation(constraint, rangeList);
			// 阻止输入非下拉选项的值
			validation.setErrorStyle(DataValidation.ErrorStyle.STOP);
			validation.setShowErrorBox(true);
//			validation.setSuppressDropDownArrow(true);
			validation.createErrorBox("提示", "请输入下拉选项中的内容");
			sheet.addValidationData(validation);
		});
	}


	/**
	 * 返回excel列标A-Z-AA-ZZ
	 *
	 * @param num 列数
	 * @return java.lang.String
	 */
	private String getExcelLine(int num) {
		String line = "";
		int first = num / 26;
		int second = num % 26;
		if (first > 0) {
			line = (char) ('A' + first - 1) + "";
		}
		line += (char) ('A' + second) + "";
		return line;
	}
}

八、ExcelDynamicSelect

public interface ExcelDynamicSelect {
	/**
	 * 获取动态生成的下拉框可选数据
	 * @return 动态生成的下拉框可选数据
	 */
	String[] getSource();
}

九、ExcelSelectedResolve

@Data
@Slf4j
public class ExcelSelectedResolve {
	/**
	 * 下拉内容
	 */
	private String[] source;

	/**
	 * 设置下拉框的起始行,默认为第二行
	 */
	private int firstRow;

	/**
	 * 设置下拉框的结束行,默认为最后一行
	 */
	private int lastRow;

	public String[] resolveSelectedSource(ExcelSelected excelSelected) {
		if (excelSelected == null) {
			return null;
		}

		// 获取固定下拉框的内容
		String[] source = excelSelected.source();
		if (source.length > 0) {
			return source;
		}

		// 获取动态下拉框的内容
		Class<? extends ExcelDynamicSelect>[] classes = excelSelected.sourceClass();
		if (classes.length > 0) {
			try {
				ExcelDynamicSelect excelDynamicSelect = classes[0].newInstance();
				String[] dynamicSelectSource = excelDynamicSelect.getSource();
				if (dynamicSelectSource != null && dynamicSelectSource.length > 0) {
					return dynamicSelectSource;
				}
			} catch (InstantiationException | IllegalAccessException e) {
				log.error("解析动态下拉框数据异常", e);
			}
		}
		return null;
	}

}

十、导出接口

/** 教师入职Excel模板导出 */
	@ApiLog("教师入职Excel模板导出")
	@GetMapping("export-template")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "教师入职Excel模板导出")
	public void exportTeacher(HttpServletResponse response, HttpServletRequest request) {
		String filename = "教师入职信息导入模板";
		try {
			String userAgent = request.getHeader("User-Agent");
			if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
				// 针对IE或者以IE为内核的浏览器:
				filename = java.net.URLEncoder.encode(filename, "UTF-8");
			} else {
				// 非IE浏览器的处理:
				filename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
			}
			response.setContentType("application/vnd.ms-excel");
			response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", filename + Func.formatDateTime(new Date()) + ".xlsx"));
			response.setHeader("Cache-Control", "no-cache");
			response.setHeader("Pragma", "no-cache");
			response.setDateHeader("Expires", -1);
			response.setCharacterEncoding("UTF-8");

			ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();
			WriteSheet writeSheet = EasyExcelUtil.writeSelectedSheet(TeacherExcel.class, 0, "教师入职信息数据表");
			excelWriter.write(new ArrayList<String>(), writeSheet);
			excelWriter.finish();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

十一、导出效果图

easyexcel导入模板设置默认数据,excel,java,spring boot文章来源地址https://www.toymoban.com/news/detail-774185.html

完结,有问题欢迎指正,QQ 781999475

到了这里,关于EasyExcel导出带下拉选数据的Excel数据导入模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • easyexcel poi根据模板导出Excel

    参考:https://blog.csdn.net/weixin_45742032/article/details/119593288?spm=1001.2101.3001.6650.1utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-119593288-blog-86538258.235%5Ev38%5Epc_relevant_anti_t3_basedepth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-11959328

    2024年02月10日
    浏览(34)
  • 使用EasyExcel实现Excel表格的导入导出

    Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。 easyexcel重

    2024年02月12日
    浏览(31)
  • spring boot导入导出excel,集成EasyExcel

    一、安装依赖 二、新建导出工具类 三、新建实体类 @ExcelProperty: 核心注解,value属性可用来设置表头名称,converter属性可以用来设置类型转换器; @ColumnWidth: 用于设置表格列的宽度; @DateTimeFormat: 用于设置日期转换格式; @NumberFormat: 用于设置数字转换格式。 四、如果需

    2024年02月06日
    浏览(45)
  • springboot中使用EasyExcel实现Excel 导入导出

    EasyExcel 是一款基于 Java 的简单易用的 Excel 文件操作工具。它提供了丰富的 API,可以方便地读取、写入和操作 Excel 文件,支持常见的 Excel 操作,如读取/写入单元格数据、合并单元格、设置样式、处理大数据量等。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将

    2024年02月12日
    浏览(56)
  • easyexcel根据模板导出Excel文件,表格自动填充问题

    同事在做easyexcel导出Excel,根据模板导出的时候,发现导出的表格,总会覆盖落款的内容。 这就很尴尬了,表格居然不能自动填充,直接怒喷工具,哈哈。 然后一起看了一下这个问题。 我找了自己的系统中关于表格导出的页面,导出了一下,发现可以正常扩充。 于是排查问

    2024年02月06日
    浏览(38)
  • 【Java结合EasyExcel,模板文件填充并导出Excel】

    需求描述: 客户网页上填一个Excel表格,数据存到数据库,这个导出接口要做的就是从数据库中的获取数据并填充到模板文件,最后通过response返给前端一个下载链接,用户即可获取填充好的Excel文件。 方案一: 一开始使用的是easypoi,发现当填充一行数据时是OK的,但是如果

    2024年02月09日
    浏览(40)
  • EasyExcel+POI制作带有有效性校验及下拉联动的Excel模板

    最近在做一个CRM系统的人员销售目标导入的相关需求,需要将销售人员的目标导入到系统中,就要求在Excel导入模板中 填写销售人员Id 和销售人员姓名。在使用的时候,这是一个易错的点,因为这两个字段交给了使用者去自由填写的话,是很容易填错的。除了文字本身填多填

    2024年02月11日
    浏览(24)
  • Spring Boot集成EasyExcel实现excel导入导出操作

    Easy Excel 官网 Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很

    2024年02月14日
    浏览(33)
  • SpringBoot整合EasyExcel,Excel导入导出就靠它了

    作者主页 :Designer 小郑 作者简介 :3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向 :Vue、SpringBoot、微信小程序 本文讲解了如何在SpringBoot项目中整合EasyExcel,实现Excel快捷导入导出,解析Excel导入导

    2024年02月16日
    浏览(22)
  • 使用POI和EasyExcel来实现excel文件的导入导出

    废话不多说咱们直接上干货!!!! 一.读取Excel表格 【1】使用POI读取excel表格中的数据 POI还可以操作我们这个word文档等等,他不仅仅只能弄Excel,而JXI只能操作excel 1.POI的结构,我们可以更具文件的类去选择 相关的对象我当前是使用的XLSX来操作的 HSSF - 提供读写Microsoft

    2024年02月05日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包