当前位置: 首页 > news >正文

Excel表格导入/导出数据工具类

Excel表格导入/导出数据工具

这里以java语言为类,实现一个简单且较通用的Excel表格数据导入工具类。

  1. 自定义注解 ExcelColumn
  2. 写导入工具类 ExcelImportUtil

自定义注解 ExcelColumn

@Retention(RetentionPolicy.RUNTIME)
@Target({java.lang.annotation.ElementType.FIELD})
public @interface ExcelColumn {/*** 字段的含义*/String name();/*** 配置列的名称,对应A,B,C,D....*/String column();/*** 是否导出数据*/boolean isExport() default true;
}

定义数据类

/*** 数据对象* @author*/
@Getter
@Setter
@ToString
public class DataDTO implements Serializable {@ExcelColumn(name = "*XXX", column = "A")private String a;@ExcelColumn(name = "xxx", column = "B")private String b;@ExcelColumn(name = "xxx", column = "C")private String c;// 导入时记录失败原因的字段  按需取private String errorMsg;}
}

Excel表格导入导出工具类代码:

@Slf4j
public class ExcelCustomUtil<T> {private static final String SUFFIX = "XLS";protected Class<T> clazz;public ExcelWithPicUtil(Class<T> clazz) {this.clazz = clazz;}/*** 批量导入, 每个sheet 数据格式一致* @param input* @param ignore 忽略前多少行,也就是从哪行开始读取数据* @return* @throws Exception*/public List<T> importBatch(InputStream input, Integer ignore, String suffix) throws Exception {List<T> newList = new ArrayList<>();Workbook workbook;if (SUFFIX.equalsIgnoreCase(suffix)) {workbook = new HSSFWorkbook(input);} else {workbook = new XSSFWorkbook(input);}Sheet sheet = workbook.getSheetAt(0);if(null != sheet){List<T> importProcessor = importProcessor(sheet, ignore);newList.addAll(importProcessor);}return newList;}/*** @param sheet* @param ignoreRow, 忽略前多少行* @return* @throws Exception*/protected List<T> importProcessor(Sheet sheet, Integer ignoreRow) throws Exception {log.info("执行导入操作");int maxCol = 0;List<T> list = new ArrayList<T>();int rows = sheet.getPhysicalNumberOfRows();log.info("importProcessor rows:{}", rows);if (rows > 0) {// 有数据时才处理List<Field> allFields = getMappedFiled(clazz, null);// 定义一个map用于存放列的序号和field.Map<Integer, Field> fieldsMap = new HashMap<>(16);for (Field field : allFields) {// 将有注解的field存放到map中.if (field.isAnnotationPresent(ExcelColumn.class)) {ExcelColumn attr = field.getAnnotation(ExcelColumn.class);// 获得列号int col = getExcelCol(attr.column());maxCol = Math.max(col, maxCol);fieldsMap.put(col, field);}}log.info("importProcessor fieldsMap:{}, maxCol:{}", JSON.toJSONString(fieldsMap), maxCol);// 默认第二行开始为数据行if (ignoreRow == null) {ignoreRow = 1;}for (int i = ignoreRow; i < rows; i++) {// 从第2行开始取数据,默认第一行是表头.Row row = sheet.getRow(i);boolean rowEmpty = isRowEmpty(row);log.info("importProcessor row:{}, rowEmpty:{}", i, rowEmpty);if (rowEmpty) {continue;}T entity = null;for (int j = 0; j <= maxCol; j++) {// 如果不存在实例则新建.entity = (entity == null ? clazz.newInstance() : entity);// 从map中得到对应列的field.Field field = fieldsMap.get(j);if (field == null) {continue;}// 取得类型,并根据对象类型设置值.Class<?> fieldType = field.getType();ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);Cell cell = row.getCell(j);if (cell != null) {CellType cellType = cell.getCellType();String c = getCellValue(cellType, cell);log.info("importProcessor row:{}, col:{}, cellType:{}, c:{}", i, j, cellType, c);try {if (String.class == fieldType){field.set(entity, c.trim());} else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {Double dou = Double.parseDouble(c);field.set(entity, dou.intValue());} else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {field.set(entity, Long.valueOf(c));} else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {field.set(entity, Float.valueOf(c));} else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {field.set(entity, Short.valueOf(c));} else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {field.set(entity, Double.valueOf(c));} else if (Character.TYPE == fieldType) {if ((c != null) && (c.length() > 0)) {field.set(entity, Character.valueOf(c.charAt(0)));}} else if (Date.class == fieldType) {}} catch (Exception e) {e.printStackTrace();}}}if (entity != null) {list.add(entity);}}}return list;}public static boolean isRowEmpty(Row row) {if (row == null) {return true;}int firstCellNum = row.getFirstCellNum();int lastCellNum = row.getLastCellNum();for (int i = firstCellNum; i < lastCellNum; i++) {Cell cell = row.getCell(i);if (cell != null && cell.getCellType() != CellType.BLANK) {return false;}}return true;}private String getCellValue(CellType cellType, Cell cell) {String c;if (cellType == CellType.NUMERIC) {DecimalFormat df = new DecimalFormat("0");c = df.format(cell.getNumericCellValue());} else if (cellType == CellType.BOOLEAN) {c = String.valueOf(cell.getBooleanCellValue());} else {c = cell.getStringCellValue();}return c;}/*** 将EXCEL中A,B,C,D,E列映射成0,1,2,3,4* @param col*/public static int getExcelCol(String col) {col = col.toUpperCase();// 从-1开始计算,字母重1开始运算。这种总数下来算数正好相同。int count = -1;char[] cs = col.toCharArray();for (int i = 0; i < cs.length; i++) {count += (cs[i] - 64) * Math.pow(26, cs.length - 1 - i);}return count;}/*** 表头(标题)格式设置** @param workbook* @return*/private CellStyle createTitleStyle(Workbook workbook) {log.info("创建表头格式 createTitleStyle");CellStyle cellStyle = workbook.createCellStyle();// 填充样式cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);// 填充色cellStyle.setFillForegroundColor(HSSFColor.HSSFColorPredefined.GREY_25_PERCENT.getIndex());// 水平居中cellStyle.setAlignment(HorizontalAlignment.CENTER);// 垂直居中cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 填充色cellStyle.setFillForegroundColor(IndexedColors.ROYAL_BLUE.getIndex());// 边框样式buildBorder(cellStyle, BorderStyle.THIN);// 字体设置Font font = workbook.createFont();font.setFontHeightInPoints((short) 11);font.setBold(true);font.setColor(IndexedColors.WHITE.getIndex());cellStyle.setFont(font);// 自动换行cellStyle.setWrapText(true);return cellStyle;}/*** 内容格式设置** @param workbook* @return*/private CellStyle createContentStyle(Workbook workbook) {log.info("创建表头格式 createTitleStyle");CellStyle cellStyle = workbook.createCellStyle();// 水平居中cellStyle.setAlignment(HorizontalAlignment.CENTER);// 垂直居中cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 字体设置Font font = workbook.createFont();font.setFontHeightInPoints((short) 11);cellStyle.setFont(font);// 自动换行cellStyle.setWrapText(true);return cellStyle;}/*** 设置边框** @param cellStyle* @param style*/private void buildBorder(CellStyle cellStyle, BorderStyle style) {cellStyle.setBorderBottom(style);cellStyle.setBorderTop(style);cellStyle.setBorderLeft(style);cellStyle.setBorderRight(style);}/*** 自适应宽度(中文支持)** @param sheet* @param size*/private void setSizeColumn(Sheet sheet, int size) {for (int columnNum = 0; columnNum < size; columnNum++) {int columnWidth = sheet.getColumnWidth(columnNum) / 256;for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {Row currentRow;//当前行未被使用过if (sheet.getRow(rowNum) == null) {currentRow = sheet.createRow(rowNum);} else {currentRow = sheet.getRow(rowNum);}if (currentRow.getCell(columnNum) != null) {Cell currentCell = currentRow.getCell(columnNum);String value = "";CellType cellType = currentCell.getCellType();if (cellType == CellType.NUMERIC) {currentCell.setCellType(CellType.STRING);value = currentCell.getStringCellValue();} else if (cellType == CellType.STRING) {value = currentCell.getStringCellValue();}int length = value.getBytes().length;if (columnWidth < length) {columnWidth = length;}}}sheet.setColumnWidth(columnNum, columnWidth * 256);}}/*** 得到实体类所有通过注解映射了数据表的字段*  递归调用*/protected List<Field> getMappedFiled(Class clazz, List<Field> fields) {if (fields == null) {fields = new ArrayList<>();}// 得到所有定义字段Field[] allFields = clazz.getDeclaredFields();for (Field field : allFields) {if (field.isAnnotationPresent(ExcelColumn.class)) {fields.add(field);}}if (clazz.getSuperclass() != null && !clazz.getSuperclass().equals(Object.class)) {getMappedFiled(clazz.getSuperclass(), fields);}return fields;}/*** 将数据写入Excel* @param dataList* @param failData* @return*/public String writeDataToExcel(List<T> dataList, boolean failData) {String localFileDir = "/tmp/localFile";String fileName = UUID.randomUUID().toString() + ".xlsx";String localFilePath = FileUtils.createFile(localFileDir, fileName);File file = new File(localFilePath);try (Workbook workbook = writeDataToExcel(dataList, failData);FileOutputStream output = new FileOutputStream(file)) {workbook.write(output);output.flush();return localFilePath;} catch (Exception e) {log.error("writeDataToExcelAndUpload e:", e);throw new BusinessException("将数据写入excel异常");}}public Workbook writeDataToExcel(List<T> dataList, boolean failData) throws Exception{List<String> headerNames = new ArrayList<>();List<Field> fields = getMappedFiled(clazz, null);boolean hasPic = false;for (Field field : fields) {ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);headerNames.add(excelColumn.name());}if (failData) {headerNames.add("失败原因");}XSSFWorkbook workbook = new XSSFWorkbook();XSSFSheet sheet = workbook.createSheet();// 创建第一栏,抬头栏XSSFRow headRow = sheet.createRow(0);headRow.setHeightInPoints(91);// 设置单元格类型CellStyle headStyle = createTitleStyle(workbook);// 创建抬头栏单元格for (int j = 0; j < headerNames.size(); j++) {XSSFCell cell = headRow.createCell(j);if (headerNames.get(j) != null) {cell.setCellValue(headerNames.get(j));cell.setCellStyle(headStyle);}}int size = dataList.size();int maxCol = headerNames.size();int fieldCol = fields.size();try {CellStyle contentStyle = createContentStyle(workbook);CellStyle errorMsgStyle = createErrorMsgStyle(workbook);for (int i = 0; i < size; i++) {XSSFRow row = sheet.createRow(i + 1);row.setHeightInPoints(60);T vo = dataList.get(i);XSSFCell cell;for (int j = 0; j < maxCol; j++) {// 当j > fieldCol时if (j > fieldCol - 1 && j == maxCol - 1) {Field field = clazz.getDeclaredField("errorMsg");field.setAccessible(true);Object o = field.get(vo);cell = row.createCell(j);cell.setCellStyle(errorMsgStyle);cell.setCellType(CellType.STRING);cell.setCellValue(o != null ? o.toString() : "");} else {Field field = fields.get(j);field.setAccessible(true);ExcelColumn attr = field.getAnnotation(ExcelColumn.class);cell = row.createCell(getExcelCol(attr.column()));if (field.getType() == String.class) {cell.setCellStyle(contentStyle);cell.setCellType(CellType.STRING);String cellValue = field.get(vo) == null ? "" : String.valueOf(field.get(vo));cell.setCellValue(cellValue);}}}}// 宽度自适应} catch (Exception e) {log.error("失败 e:", e);throw new Exception("失败");}return workbook;}
}

这个工具类只是展示了简单的字段导入/导出的读取,如果带图片或者其他特殊要求的字段,可以自定义规则读取。

相关文章:

Excel表格导入/导出数据工具类

Excel表格导入/导出数据工具 这里以java语言为类&#xff0c;实现一个简单且较通用的Excel表格数据导入工具类。 自定义注解 ExcelColumn写导入工具类 ExcelImportUtil 自定义注解 ExcelColumn Retention(RetentionPolicy.RUNTIME) Target({java.lang.annotation.ElementTy…...

Python自学之路--004:Python使用注意点(原始字符串‘r’\字符转换\‘wb’与‘w区别’\‘\‘与‘\\’区别)

目录 1、原始字符串‘r’ 2、字符转换问题 3、open与write函数’wb’与’w’区分 4、Python里面\与\\的区别 1、原始字符串‘r’ 以前的脚本通过Python2.7写的&#xff0c;通过Python3.12去编译发现不通用了&#xff0c;其实也是从一个初学者的角度去看待这些问题。 其中的\…...

javaEE进阶——SpringBoot与SpringMVC第一讲

文章目录 什么是springMVCSpringMVC什么是模型、视图、控制器MVC和SpringMVC的关系SpringMVC的使用第一个SpringMVC程序RestController什么是注解 那么RestController到底是干嘛的呢&#xff1f;RequestMapping 如何接收来自请求中的querystryingRequestParamRequestMapping(&q…...

LabVIEW和usrp连接实现ofdm通信系统 如何实现

1. 硬件准备 USRP设备&#xff1a;选择合适的USRP硬件&#xff08;如USRP B210或N210&#xff09;&#xff0c;并确保其与计算机连接&#xff08;通常通过USB或以太网&#xff09;。天线&#xff1a;根据频段需求选择合适的天线。 2. 软件安装 LabVIEW&#xff1a;安装LabVI…...

NGINX SPRING HTTPS证书

服务器&#xff1a;xxx.xxx.xxx.56 客户端器&#xff1a;xxx.xxx.xxx.94##生成服务器证书和密钥容器 keytool -genkey -alias tas-server -keypass 250250 -keyalg RSA -keysize 2048 -validity 3650 -keystore D:\https证书\tas-server.jks -storepass 250250 -dname "C…...

WordPress插件Plus WebP,可将jpg、png、bmp、gif图片转为WebP

现在很多浏览器和CDN都支持WebP格式的图片了&#xff0c;不过我们以前的WordPress网站使用的图片都是jpg、png、bmp、gif&#xff0c;那么应该如何将它们转换为WebP格式的图片呢&#xff1f;推荐安装这款Plus WebP插件&#xff0c;可以将上传到媒体库的图片转为WebP格式图片&am…...

GitLab CI/CD的原理及应用详解(五)

本系列文章简介&#xff1a; 在当今快速变化的软件开发环境中&#xff0c;持续集成&#xff08;Continuous Integration, CI&#xff09;和持续交付&#xff08;Continuous Delivery, CD&#xff09;已经成为提高软件开发效率、确保代码质量以及快速响应市场需求的重要手段。Gi…...

连锁收银系统如何助力实体门店私域运营

作为实体门店&#xff0c;私域运营是提升客户黏性和增加复购率的重要策略之一。而连锁收银系统在私域运营中扮演了关键的角色&#xff0c;它不仅可以帮助门店管理客户信息和消费记录&#xff0c;还能够通过数据分析和营销功能提供个性化的服务和推广活动。下面看看连锁收银系统…...

JETBRAINS IDES 分享一个2099通用试用码!PhpStorm 2024 版 ,支持一键升级

文章目录 废话不多说上教程&#xff1a;&#xff08;动画教程 图文教程&#xff09;一、动画教程激活 与 升级&#xff08;至最新版本&#xff09; 二、图文教程 &#xff08;推荐&#xff09;Stage 1.下载安装 toolbox-app&#xff08;全家桶管理工具&#xff09;Stage 2 : 下…...

超级好用的C++实用库之MD5信息摘要算法

&#x1f4a1; 需要该C实用库源码的大佬们&#xff0c;可搜索微信公众号“希望睿智”。添加关注后&#xff0c;输入消息“超级好用的C实用库”&#xff0c;即可获得源码的下载链接。 概述 MD5信息摘要算法是一种广泛使用的密码散列函数&#xff0c;由Ronald L. Rivest在1991年设…...

ssm132医院住院综合服务管理系统设计与开发+vue

医院住院综合服务管理系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对医院住院信息管理混乱&…...

在Linux上安装并启动Redis

目录 安装gcc环境 上传redis文件 启动redis-server 后台启动redis-server 查看redis启动状态 参考文章&#xff1a;Linux 安装 Redis 及踩坑 - 敲代码的阿磊 - 博客园 (cnblogs.com) 准备&#xff1a;打开VMware Workstation&#xff0c;创建一个虚拟机&#xff0c;进入管…...

vue3.0+antdv的admin管理系统vue-admin-beautiful推荐

前言 几年前&#xff0c;笔者自学了vue这一优秀的前端框架&#xff0c;但苦于没项目练手&#xff0c;无意间发现了vue-admin-beautiful这一优秀的前端集成框架。当时就使用它做了一很有意思的小项目---终端监控云平台&#xff0c;实现了前端和后台的整体功能。整体方案介绍参见…...

C# WinForm —— 20 RichTextBox 介绍

1. 简介 富文本框&#xff0c;拥有TextBox的所有功能&#xff0c;&#xff0c;但还有更多高级的文本输入和编辑功能&#xff0c;比如设置字体颜色、样式、段落、图片、超链接等 2. 常用属性 属性解释(Name)控件ID&#xff0c;在代码里引用的时候会用到,一般以 rtxt 开头Acce…...

springmvc数据绑定

数据绑定 数据绑定流程 springmvc框架将ServletRequest对象及目标方法的入参实例传递给WebDataBinderFactory实例&#xff0c;以创建DataBinder实例对象 DataBinder调用装配在springmvc上下文中的ConversionService组件进行数据类型转换、数据格式化工作。将Servlet中的请求信息…...

Milvus的存储/计算分离

前言 根据数据面与控制面相隔离的原则&#xff0c;从可扩展性和灾难恢复来看&#xff0c;Milvus由4个相互独立的层组成 访问层 由一系列无状态的代理组成&#xff0c;访问层是系统和用户之间的第一层&#xff0c;它主要是验证客户端请求和规整返回的结果 代理是无状态的&am…...

SHAP值是个什么值?

SHAP 值是个什么值&#xff1f; 起初&#xff0c;我们知道SHAP值代表了变量对于结局变量的贡献程度&#xff0c;然而&#xff0c;在做了一些SHAP分析之后&#xff0c;感觉有一些SHAP值还是有一些难以理解的地方&#xff0c;比如&#xff0c;为什么有负值&#xff1f;SHAP值为0…...

Django接口卡死一直没有返回响应

当Django接口出现卡死且没有返回响应时&#xff0c;可能是由于多种原因导致的。以下是一些排查和解决问题的步骤&#xff1a; 查看日志&#xff1a; 首先检查Django的日志&#xff0c;看看是否有任何错误或异常被记录。这可以帮助你确定问题的根源。 检查数据库连接&#xff1…...

7-139 有趣的括号

括号()的组合千奇百怪,Drizzle 想知道各种组合的括号可以是否合法 合法要求:每个同类型的左括号必须有与之对应的同类的右括号以正确的顺序闭合 要求: 输入:输入一个括号字符串 输出:输出是否合法,是则True,否则False 示例: 输入: (){}[]输出: True范围: 对于 1…...

解决qt5.12.12编译源码没有libqxcb的问题

最近要研究一下qt源码,因为设计到要修改源码,所以需要编译源码并替换修改的库文件运行验证。 我这里使用的是qt5.12.12版本,去官网上下载对应版本的安装包,安装时勾选上源码即可。 后面编译完发现,plugins/platforms/目录下没有生成库文件libqxcb.so,造成了一点麻烦。 设置 e…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...