利用Java自定义格式,循环导出数据、图片到excel

利用Java自定义格式,循环导出数据、图片到excel

  • 1、自定义格式循环导出数据
    • 1.1.设置格式
      • 1.1.1、居中样式
      • 1.1.2、应用样式到合并区域
      • 1.1.3、合并单元格
      • 1.1.4、设置列宽
    • 1.2、写入数据
      • 1.2.1、创建标签头部
      • 1.2.2、写入标签内容
  • 2、自定义格式循环导出图片
    • 2.1、设置格式并插入图片
  • 3、格式和数据写入统一封装
  • 4、测试方法和效果
    • 4.1、测试方法
    • 4.2、运行效果

1、自定义格式循环导出数据

我有一个需求,需要做一个标签,格式固定,但是数据从数据库中获取,手动一个一个写不现实,所以我考虑写个方法,自定义格式,循环的将数据导出到excel。
说明:

因为我要做的一个标签,占据excel 5行4列,所以在下面的代码中,会提到 4 5或者这两数的倍数关系,请注意这个情况

1.1.设置格式

1.1.1、居中样式

// 创建居中样式private static CellStyle createCenterStyle(Workbook workbook) {CellStyle style = workbook.createCellStyle();// 水平居中style.setAlignment(HorizontalAlignment.CENTER);// 垂直居中style.setVerticalAlignment(VerticalAlignment.CENTER);// 设置边框style.setBorderTop(BorderStyle.THIN);style.setBorderBottom(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);//字体Font font = workbook.createFont();font.setFontName("微软雅黑"); // 设置字体类型font.setFontHeightInPoints((short) 8); // 设置字体大小style.setFont(font);return style;}

1.1.2、应用样式到合并区域

    /*** 应用样式到合并区域* @param sheet 工作表* @param region 合并区域* @param style 样式*/private static void applyStyleToMergedRegion(Sheet sheet, CellRangeAddress region, CellStyle style) {for (int row = region.getFirstRow(); row <= region.getLastRow(); row++) {Row sheetRow = sheet.getRow(row) != null ? sheet.getRow(row) : sheet.createRow(row);for (int col = region.getFirstColumn(); col <= region.getLastColumn(); col++) {Cell cell = sheetRow.getCell(col) != null ?sheetRow.getCell(col) : sheetRow.createCell(col);cell.setCellStyle(style);}}}

1.1.3、合并单元格

	/*** 合并单元格并居中* @param sheet 工作表* @param centerStyle 样式* @param columnsNum 列数* @param lineNum 行数*/private static void mergeAndCenterCells(Sheet sheet, CellStyle centerStyle,int columnsNum, int lineNum) {for (int i = 0; i < lineNum; i=i+5) {for (int j = 0; j < columnsNum; j=j+4) {//标签头部的合并区域  同一行 4列CellRangeAddress titleMerge = new CellRangeAddress(i, i, j, j+3);//图片合并区域 标签头部第2行到第5行 第1列到第2列CellRangeAddress photoMerge = new CellRangeAddress(i+1, i+4, j, j+1);//数据合并区域CellRangeAddress queMerge = new CellRangeAddress(i+3, i+3, j+2, j+3);CellRangeAddress timeMerge = new CellRangeAddress(i+4, i+4, j+2, j+3);//写入工作表sheet.addMergedRegion(titleMerge);sheet.addMergedRegion(photoMerge);sheet.addMergedRegion(queMerge);sheet.addMergedRegion(timeMerge);// 应用居中样式到合并区域applyStyleToMergedRegion(sheet, titleMerge, centerStyle);applyStyleToMergedRegion(sheet, photoMerge, centerStyle);applyStyleToMergedRegion(sheet, queMerge, centerStyle);applyStyleToMergedRegion(sheet, timeMerge, centerStyle);}}}

1.1.4、设置列宽

循环设置标签列宽,以适应图片和数据,大小 1 * 256 为1个字符。

 	/*** 设置列的宽度 以适应图片和数据* @param columnsNum 列数* @param sheet 工作表*/private static void setColumnWidth(int columnsNum,Sheet sheet){//循环设置标签的列宽for (int i=0;i<columnsNum;i=i+4){sheet.setColumnWidth(i, 4 * 256); // 设置第一列宽度为4个字符sheet.setColumnWidth(i+1, 4 * 256); // 设置第二列宽度为4个字符sheet.setColumnWidth(i+2, 12 * 256); // 设置第三列宽度为12个字符sheet.setColumnWidth(i+3, 12 * 256); // 设置第四列宽度为12个字符}}

1.2、写入数据

1.2.1、创建标签头部

	/*** 创建标签头部* @param sheet 工作表* @param style 居中样式* @param mainTitleStr 头部数据* @param columnsNum 列数* @param lineNum 行数*/private static void createHeader(Sheet sheet, CellStyle style,String mainTitleStr,int columnsNum, int lineNum) {for (int i = 0; i < lineNum; i=i+5) {// 隔5行设置一次Row headerRow = sheet.createRow(i);// 主标题(将被合并)for (int j = 0; j < columnsNum; j=j+4) {//隔4列设置一次Cell mainTitle = headerRow.createCell(j);mainTitle.setCellValue(mainTitleStr);mainTitle.setCellStyle(style);}}}

1.2.2、写入标签内容

标签固定的内容可以在这里先写好,其他有变动的可以从其他渠道获取后再去拼接。

    /*** 设置内容格式及数据 固定不变的可以在这里写好 其他从数据库取到的再去拼接* @param sheet 工作表* @param style 样式* @param List 从数据库或其他途径取到的数据* @param columnsNum 列数* @param lineNum 行数*/private static void createContent(Sheet sheet, CellStyle style,List<Map<Object,Object>> List,int columnsNum, int lineNum) {int lineTemp=0;// 临时的 行数int columnsTemp=0;// 临时的 列数for (Map<Object,Object> map:List) {//搞成二位数据 直接固定格式 后续方便固定格式 写入excel表格Object[][] data = {{"型号:"+map.get("name"), "夹具类型:"+ map.get("type")},{"精度:符合标准", "编号:"+map.get("num")},{"确认人:xxx □    xxx □   "},{"点检有效期:"+ DateUtil.year(new Date())+"       - "+ DateUtil.year(new Date())+"         "},};//遍历二维数组for (int i = 0; i < data.length; i++) {int temp=lineTemp+i + 1;//要生成指定行 行数  +1 是因为数据在标签头部下面写入//这么做的目的是 为了避免重新生成一行,导致之前的数据被删除Row row=sheet.getRow(temp);//获得之前生成的行if (row==null){//如果之前未生成行 那将需要去生成row = sheet.createRow(temp);}int cellTemp=columnsTemp+2;//指定哪一列 +2是因为前面两列是设置图片for (int j = 0; j < data[i].length; j++) {Cell value = row.createCell(cellTemp);row.createCell(cellTemp).setCellValue(data[i][j].toString());//写入内容value.setCellStyle(style);//设置格式cellTemp+=1;//下一列}}//为了不超过设置的行数 和列数 做出如下判断if (columnsTemp<columnsNum && (columnsTemp+4)!=columnsNum){columnsTemp=columnsTemp+4;}else {columnsTemp=0;if (lineTemp<lineNum && (lineTemp+5)!=lineNum){lineTemp=lineTemp+5;}else{lineTemp=0;}}}}

2、自定义格式循环导出图片

在每个标签中,我都要插入一个二维码,位置都是固定的,所以就自定义图片的位置,并且循环插入不同的二维码。

2.1、设置格式并插入图片

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** 图片保存到excel的类*/
public class ImageForExcel {/*** 设置图片保存到excel的位置* @param workbook excel* @param sheet 工作表* @param photoPath 插入图片的路径 一个list集合* @param columnsNum 列数* @param lineNum 行数*/public static void setPhoto(Workbook workbook, Sheet sheet, List<String> photoPath, int columnsNum, int lineNum){int index=0;for (int i = 0; i < lineNum; i=i+5) {for (int j = 0; j < columnsNum; j=j+4) {// 读取图片文件try (InputStream is = new FileInputStream(photoPath.get(index))) {// 将图片转换为字节数组byte[] bytes = IOUtils.toByteArray(is);// 添加图片到工作簿int pictureIdx = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);// 创建绘图工具CreationHelper helper = workbook.getCreationHelper();Drawing<?> drawing = sheet.createDrawingPatriarch();// 创建锚点,设置图片位置ClientAnchor anchor = helper.createClientAnchor();anchor.setCol1(j); // 图片起始列(0-based)anchor.setRow1(i+1); // 图片起始行(0-based)anchor.setCol2(j+2); // 图片结束列(0-based)anchor.setRow2(i+5); // 图片结束行(0-based)// 创建图片并设置锚点Picture pict = drawing.createPicture(anchor, pictureIdx);index=index+1;// 可选:调整单元格大小以适应图片
//            sheet.setColumnWidth(1, 4 * 256); // 调整列宽
//            sheet.setColumnWidth(0, 4 * 256); // 调整列宽/*Row row = sheet.createRow(3);row.setHeightInPoints(100); // 调整行高*/} catch (IOException e) {e.printStackTrace();}}}}
}

3、格式和数据写入统一封装

将格式设计和写入数据的方法同意封装成一个方法,方便调用。

/*** 统一封装的方法* @param mainTitleStr 标签头部* @param exportPath 导出的路径 二维码图片获取的路径* @param columnsNum 标签的总列数* @param lineNum 标签的总行数* @param data 变动的数据* @return* @throws Exception*/public static String exportTitle(String mainTitleStr, String exportPath,int columnsNum, int lineNum, List<Map<Object,Object>> data) throws Exception {String excelPath=exportPath+"标签WZ.xlsx";Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet("标签");//工作表名// 1、设置列宽(单位是1/256个字符宽度)setColumnWidth(columnsNum,sheet);// 设置行高(单位是点,1点=1/20像素)
//        Row row = sheet.createRow(0);
//        row.setHeightInPoints(30); // 设置行高为30点// 2. 创建居中样式CellStyle centerStyle = createCenterStyle(workbook);// 3. 设置表头数据createHeader(sheet, centerStyle,mainTitleStr,columnsNum,lineNum);// 4. 设置内容数据createContent(sheet, centerStyle,data,columnsNum,lineNum);// 5. 设置合并区域并应用居中样式mergeAndCenterCells(sheet, centerStyle,columnsNum,lineNum);//将图片插入excelList<String> photoPath=new ArrayList<>();for (Map<Object,Object> map:data) {photoPath.add(exportPath+map.get("mold").toString()+".png");}ImageForExcel.setPhoto(workbook,sheet,photoPath,columnsNum,lineNum);// 7. 保存文件try (FileOutputStream out = new FileOutputStream(excelPath)) {workbook.write(out);}return excelPath;}

4、测试方法和效果

文字数据是我自己编的,如果大家要从数据库或者其他来源获取,改动data即可。
二维码图片是我利用二维码生成方法生成的,如果大家有兴趣,可以看看我上一篇的博客。点击这里: 二维码生成方法

4.1、测试方法

这个是有循环生成多个标签的功能。
所以列数 行数 需要根据自己的需求。
如不需要循环,只需将行列数设置为一个标签所需要占据的数即可。
目前我的测试方法是,一个标签占据5行4列,下面设定是有4个标签。
如果对代码中 4 5 或者 4 5 倍数 ,又或者其他数据有疑问的话,可以看看这里

import com.codermy.myspringsecurityplus.utils.qrUtils.TitleForExcel;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class BiaoQian {public static void main(String[] args) throws Exception {//1、表头String mainTitleStr="夹具确认表 DOC-190-AA0004-01D";//2、excel存放的位置String exportPath="D:/java/codeSpace/testFile/";/*这个是有生成多个的功能 所以列数 行数 需要根据自己的需求如不需要循环,只需将行列数设置为一个标签所需要占据的数即可目前我的数据是,一个标签占据5行4列,下面设定是循环写入4个标签如果对代码中 4 5  或者 4 5 倍数 ,又或者其他数据有疑问的话,可以看看这里*///3、列数int columnsNum=8;//4、行数int lineNum=10;//5、数据   可以从数据库中得到 然后再按照我们需要的数据做处理// 下面是我自己模拟的一些数据List<Map<Object,Object>> data=new ArrayList<>();String name="C40888";String type="WZ";//这个 (i < 5) ,需要对应上面的行列数 有四个标签for (int i = 1; i < 5; i++) {Map<Object,Object> map=new HashMap<>();map.put("name",name);map.put("type",type);map.put("num",i);map.put("mold",name+"-"+type+"-"+i);data.add(map);}String result=TitleForExcel.exportTitle(mainTitleStr,exportPath,columnsNum,lineNum,data);System.out.println(result);}}

4.2、运行效果

由于图片有二维码,会被和谐,所以我在二维码上搞了贴纸,实际导出效果没有贴纸
在这里插入图片描述


以上就是本篇文章的全部内容,部分代码是利用AI生成,然后再去修改成我想要的效果,如果有侵权的地方,还请联系本人。
本文有很多可以修改优化的地方,如果各位同学有好的见解可以评论留言讨论。
如果代码有异常,或者有其他疑惑、可以评论区留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91433.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91433.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAP学习笔记 - 开发45 - RAP开发 Managed App New Service Definition,Metadata Extension

上一章讲了在 Data Model View ( CDS View for BO Structure )基础上创建 Projection View ( CDS View for BO Projection )。 SAP学习笔记 - 开发44 - RAP开发 Managed App 建 Projection View&#xff0c;Provider Contract&#xff0c;用 redirected to 设定父子关系-CSDN博…

React强大且灵活hooks库——ahooks入门实践之高级类hook(advanced)详解

什么是 ahooks&#xff1f; ahooks 是一个 React Hooks 库&#xff0c;提供了大量实用的自定义 hooks&#xff0c;帮助开发者更高效地构建 React 应用。其中高级类 hooks 是 ahooks 的一个重要分类&#xff0c;专门用于处理一些高级场景&#xff0c;如受控值、事件发射器、性能…

计算机网络——数据链路层(25王道最新版)

数据链路层前言数据链路层的功能封装成帧&#xff08;组帧&#xff09;字符计数法字节填充法零比特填充法违规编码法小节差错控制检错编码奇偶校验码CRC校验码&#xff08;循环冗余校验码&#xff09;基本思想如何构造如何检错纠错纠错编码海明校验码设计思路求解步骤&#xff…

【PTA数据结构 | C语言版】字符串替换算法

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 请编写程序&#xff0c;将给定主串 s 中的子串 sub_s 替换成另一个给定字符串 t&#xff0c;再输出替换后的主串 s。 输入格式&#xff1a; 输入给出 3 个非空字符串&#xff0c;依次为&#xff1a…

事物生效,订单类内部更新订单

代码如下以下代码1不生效&#xff0c;2生效解决方案1&#xff0c;外层方法加注解&#xff0c;内层不加2&#xff0c;不要拆分方法&#xff0c;把更新订单操作放在带事物的大方法中3&#xff0c;拆方法&#xff08;内部&#xff09;&#xff0c;注入自己&#xff0c;用代理对象调…

非对称加密:RSA

文章目录 非对称加密:RSA 1、RSA 加解密 2、RSA 生成密钥对(公钥、私钥)、加解密 参考资料 非对称加密:RSA 1、RSA 加解密 <!-- RSA --><!-- 引入jsencrypt库 --><script src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/3.3.2/jsencrypt.min.js&q…

MongoDB 数据库 启用访问控制

0. 最近服务器安装了 MongoDB 被勒索了 测试服务器安装了 MongoDB 等&#xff0c;开放了 27017 对所有 ip。 哈哈哈哈哈哈&#xff0c;问就是有点犯懒&#xff0c;之前都是只允许自己的 ip。 好家伙&#xff0c;然后没过几个小时&#xff0c;数据库集合被清空&#xff0c;只留…

【Unity Sprite属性拓展】

Unity Inspector 精灵图预览为 Unity 中的 Sprite 类型属性提供了​​增强版的 Inspector 显示​​&#xff0c;在保留标准精灵选择功能的基础上&#xff0c;添加了大型预览图和精灵名称显示功能代码 using UnityEngine; using UnityEditor;// 1️⃣ 告诉 Unity&#xff1a;所有…

细菌实验入门:浓度测定与菌种鉴定技术详解

在微生物实验中&#xff0c;细菌浓度的精准测定和菌种的准确鉴定是两项基础且核心的操作。本文将详细介绍相关技术的原理、操作步骤及注意事项&#xff0c;为新手提供系统性指导。一、细菌浓度测定方法1. 光密度法&#xff08;OD600&#xff09;&#xff1a;快速定量的首选原理…

GaussDB 数据库架构师修炼(一)数据库容量规划

1、容量规划的定义GaussDB容量规划是指根据客户业务系统的负载需求或历史运行数据&#xff0c;进行合理规划GaussDB的计算、存储和网络资源配置&#xff0c;以满足业务系统正常使用和未来若干年负载增长诉求的过程。2、容量规划活动主要步骤需求收集调研生产系统的业务特征&…

hashMap原理(一)

概念HashMap是java中一种非常常用的基于哈希表的数据结构&#xff0c;允许o(1)的时间复杂度进行元素插入&#xff0c;查找&#xff0c;和删除。它通过”键-值“ 对的方式存储数据。总的来说&#xff1a;HashMap的底层原理&#xff1a;数组链表红黑树&#xff08;jdk1.8之后还涉…

Ubuntu24 辅助系统-屏幕键盘的back按键在网页文本框删除不正常的问题解决方法

Ubuntu24 辅助系统-屏幕键盘的back按键异常 问题描述ubuntu24这个屏幕键盘&#xff0c;只有在网页的搜索框或者文本框&#xff0c;比如百度首页的搜索框&#xff0c;留言的文本框&#xff0c;才会出现点击back按钮的时候&#xff0c;出现了先选中当前这个字符&#xff0c;删除此…

自然语言指令驱动的工业机器人协同学习系统:大语言模型如何重塑智能体协作范式

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

web:js的switch语句

在js中,switch语句是一种用于根据不同的条件执行不同代码块的控制流语句。它类似于多个if...else if...else语句,但结构更清晰,特别是在有多个条件分支的情况下。 基本语法 switch (expression) {case value1:// 当expression的值等于value1时执行这里的代码break;case va…

为何说分布式 AI 推理已成为下一代计算方式

2024 年&#xff0c;我们见证了人工智能创新的空前爆发。AI 的快速发展令很多人惊叹&#xff0c;为了训练更先进的大语言模型&#xff08;LLM&#xff09;&#xff0c;科技巨头争相获取强大的 GPU。如今&#xff0c;AI 正在无缝融入我们世界的每个角落。在众多新兴 AI 公司、模…

阿里云 RabbitMQ 可观测性最佳实践

阿里云 RabbitMQ 阿里云 RabbitMQ 是一款高性能、高可靠的消息中间件&#xff0c;支持多种消息协议和丰富的功能特性。它提供消息队列功能&#xff0c;能够实现应用间的消息解耦和异步通信&#xff0c;提升系统扩展性和稳定性。其支持多种消息持久化策略&#xff0c;确保消息不…

vue-router 导航式编程 参数的设置

主要是想记录一下this.$router.push、replace、go等方法的参数如何设置。字符串路径router.push(/home)直接使用字符串&#xff08;或模板字符串&#xff09;路径&#xff0c;可跳转到相应的URL路径。对象式路径路径也可以是一个对象&#xff0c;对象里以key:value的形式表示UR…

Swift实现股票图:从基础到高级

目录一、核心实现方案1. 原生方案&#xff1a;使用 Core Graphics 绘制2. 使用第三方库&#xff1a;Charts3. 跨平台方案&#xff1a;使用 SwiftUI Canvas二、技术指标实现1. 移动平均线 (MA)2. 布林带 (Bollinger Bands)3. MACD (Moving Average Convergence Divergence)三、…

【unitrix】 6.4 数特征(number.rs)

一、源码 这段代码定义了一个名为Number的trait&#xff08;特质&#xff09;以及它的实现。 use crate::sealed::Sealed; use crate::number::{V, BaseNumber, TNumber};/// 数值的统一标记特质 /// 可以是编译时类型化数字(TNumber)或运行时变量(V<T>) pub trait Numbe…

AI治AI:大语言模型自检新法

“以火攻火”的思路解决大语言模型(LLMs)“幻觉”问题 虚构是由于与提示无关的内部因素而不可预测地从 LLM 中出现的幻觉。作者专注于衡量 LLM 对提示响应的不确定性,使用高不确定性表示虚构的假设。他们通过计算一个称为熵的量来估计这种不确定性**,熵可以被认为是模型生…