Java POI (5)—— 复杂报表导出案例

一、需求分析

某个仪器会连续采集1~4通道的16进制的原始数据,现在需要将这些数据,先按照通道进行分类,然后将分好类的数据进行处理,转化成10进制,再最终带入到一个拟合公式,得到处理后的数据,然后再将这些数据写入到Excel表格中进行记录

写入的Excel表格有如下的要求:

四个通道的数据分别放在四个sheet中,每个sheet内的数据按照第一列放“时间”,第二列放“数据”的方式排列,即一条完整的数据占两列,如果这个sheet内不只一条数据,第二条数据就在第四列开始写入(即每条完整的数据之间空一列)最终将这些数据绘成散点图(绘图不做要求)

二、定义实体类

@Data
public class MdBean {/***  prodInst 仪器编号*/private String prodInst;/***  inTime 录入时间*/private Date inTime;/***  currentChannel 通道 ic1 ic2 ic3 ic4*/private String currentChannel;/***  16 进制原始数据值*/private String data;/***   添加转换后的数据列表*/private List<List<BigDecimal>> convertedData;// 其他属性的getter和setter方法public List<List<BigDecimal>> getConvertedData() {return convertedData;}public void setConvertedData(List<List<BigDecimal>> convertedData) {this.convertedData = convertedData;}
}

三、实现逻辑 

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;public class Run {/*** Column indexes for each channel*/private static final int[] COLUMN_INDEXES = {0, 1, 3, 4};/*** 要生成的示例数据数量*/private static final int DATA_SIZE = 4;/*** 每个通道要生成的数据数量*/private static final int DATA_SIZE_PER_CHANNEL = 3;public static void main(String[] args) {List<MdBean> dataList = new ArrayList<>();// 创建示例数据// 循环四次,分别代表四个通道for (int i = 0; i < DATA_SIZE; i++) {// 每个通道生成指定数量的数据for (int j = 0; j < DATA_SIZE_PER_CHANNEL; j++) {// 根据循环索引生成ProdInstString prodInst = String.format("%03d", j + 1);// 当前时间Date inTime = new Date();// 当前通道类型String currentChannel = "ic" + (i + 1);String data = generateData(6);// 创建MdBean对象并设置属性MdBean bean = new MdBean();bean.setProdInst(prodInst);bean.setInTime(inTime);bean.setCurrentChannel(currentChannel);bean.setData(data);dataList.add(bean);}}// 获取分类后的数据MapMap<String, List<MdBean>> classifiedDataMap = groupAndConvertData(dataList);for (Map.Entry<String, List<MdBean>> entry : classifiedDataMap.entrySet()) {String channel = entry.getKey();List<MdBean> dataLists = entry.getValue();System.out.println("Channel: " + channel);for (MdBean bean : dataLists) {System.out.println("ProdInst: " + bean.getProdInst());System.out.println("InTime: " + bean.getInTime());System.out.println("ConvertedData: " + bean.getConvertedData());System.out.println("-------------------------------------");}System.out.println("-------------------------------------");}// 将数据写入ExcelwriteDataToExcel(classifiedDataMap, "output10.xlsx");}/*** 它接收一个 List类型的参数 dataList,该列表包含了MdBean对象。* 创建一个HashMap类型的classifiedDataMap,用于存储按照通道分类后的数据。* 方法遍历输入的dataList列表中的每个MdBean对象。* 对于每个MdBean对象,方法获取其当前通道currentChannel。* 如果classifiedDataMap中已经存在该通道对应的列表,则直接获取;否则,创建一个新的空列表。* 方法调用convertAndCalculateNewData方法,将该MdBean对象的原始数据转换为新的数据列表,并将转换后的数据设置到MdBean对象中。* 将该MdBean对象添加到通道对应的列表中。* 最后,将通道对应的列表存储到classifiedDataMap中。* 方法返回classifiedDataMap,其中包含了按照通道分类并转换数据后的结果。*/private static Map<String, List<MdBean>> groupAndConvertData(List<MdBean> dataList) {Map<String, List<MdBean>> classifiedDataMap = new HashMap<>();// 指定要处理的通道列表List<String> specifiedChannels = Arrays.asList("ic1", "ic2", "ic3", "ic4");for (MdBean data : dataList) {String currentChannel = data.getCurrentChannel();// 检查currentChannel是否在指定的通道列表中if (!specifiedChannels.contains(currentChannel)) {// 如果不在指定的通道列表中,则跳过当前数据continue;}// 如果在指定的通道列表中,则继续处理当前数据List<MdBean> channelDataList = classifiedDataMap.getOrDefault(currentChannel, new ArrayList<>());List<BigDecimal> newDataList = convertAndCalculateNewData(data.getData());List<List<BigDecimal>> lists = generateArray(newDataList);data.setConvertedData(lists);channelDataList.add(data);classifiedDataMap.put(currentChannel, channelDataList);}return classifiedDataMap;}private static List<List<BigDecimal>> generateArray(List<BigDecimal> newDataList) {List<List<BigDecimal>> channelArray = new ArrayList<>();// 设置初始时间为 -40.8 增长步径为 0.16BigDecimal currentTime = new BigDecimal("-40.8");BigDecimal step = new BigDecimal("0.16");for (BigDecimal data : newDataList) {List<BigDecimal> row = new ArrayList<>();row.add(currentTime);row.add(data);channelArray.add(row);// 使用BigDecimal的加法运算currentTime = currentTime.add(step);}return channelArray;}private static List<BigDecimal> convertAndCalculateNewData(String hexData) {List<BigDecimal> newDataList = new ArrayList<>();hexData = hexData.replaceAll("\\s", "");for (int i = 0; i < hexData.length(); i += 2) {String hexByte = hexData.substring(i, i + 2);int decimalValue = Integer.parseInt(hexByte, 16);BigDecimal y = BigDecimal.valueOf((1.0 / 64) * decimalValue - 2);newDataList.add(y);}return newDataList;}/*** 首先,创建一个XSSFWorkbook对象,表示一个Excel工作簿。* 然后,使用for循环遍历dataMap中的每个条目。dataMap的每个条目由通道名称作为键和该通道对应的MdBean对象列表作为值组成。* 在循环中,为每个通道创建一个工作表(Sheet),工作表的名称为通道名称。* 接着,获取该通道对应的MdBean对象列表,并使用另一个for循环遍历列表中的每个MdBean对象。* 对于每个MdBean对象,创建一行(Row),并为该行的每列设置值。第一列设置为prodInst属性的值,第二列设置为inTime属性的字符串表示形式,后续列设置为convertedData属性中的转换后数据。* 最后,将工作簿写入指定的文件路径中。** @param dataMap* @param filePath*/private static void writeDataToExcel(Map<String, List<MdBean>> dataMap, String filePath) {try (Workbook workbook = new XSSFWorkbook()) {for (Map.Entry<String, List<MdBean>> entry : dataMap.entrySet()) {String channel = entry.getKey();Sheet sheet = workbook.createSheet(channel);List<MdBean> dataList = entry.getValue();if (dataList != null) {for (MdBean bean : dataList) {System.out.println(bean.getProdInst());int i = 0;int columnIndex = getColumnIndex(sheet, bean);for (List<BigDecimal> entryData : bean.getConvertedData()) {Row r = sheet.getRow(i);if (r == null) {r = sheet.createRow(i);}Cell cell1 = r.createCell(columnIndex );Cell cell2 = r.createCell(columnIndex + 1);BigDecimal val1 = entryData.get(0);BigDecimal val2 = entryData.get(1);cell1.setCellValue(val1.doubleValue());cell2.setCellValue(val2.doubleValue());++i;}}}}try (FileOutputStream outputStream = new FileOutputStream(filePath)) {workbook.write(outputStream);}System.out.println("Data has been written to Excel successfully!");} catch (IOException e) {e.printStackTrace();}}private static int getColumnIndex(Sheet sheet, MdBean bean) {// 获取第一行Row firstRow = sheet.getRow(0);if (firstRow == null) {// 如果第一行为空,则直接返回0return 0;}// 获取 ProdInstint prodInstNumber = Integer.parseInt(bean.getProdInst());// 根据 ProdInst 计算列索引int columnIndex = (prodInstNumber - 1) * 3;return columnIndex;}/*** 生成指定长度的随机16进制字符串*/private static String generateData(int length) {StringBuilder sb = new StringBuilder();Random random = new Random();for (int i = 0; i < length; i++) {// 生成0-15之间的随机数int hexDigit = random.nextInt(16);// 转换为16进制字符并追加到字符串中sb.append(Integer.toHexString(hexDigit));}return sb.toString();}
}

 

 

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

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

相关文章

Flutter开发基础之动画专题

Flutter开发基础之动画专题 动画设计的作用是让UI界面更流畅、直观&#xff0c;能够有效的提升用户体验。 在Flutter开发中&#xff0c;动画分为多个方面&#xff1a; 基础动画、页面交互动画、绘图动画、矩阵变换等。 基本动画 常用的基本动画有透明度动画、缩放动画、旋转动…

leetcode73 矩阵置零

题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用原地算法。 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 输入&#xff1a;matrix [[0,1,2,0],[3,4…

基于机器学习预测岗位薪资

本文根据某招聘网站抓取的岗位信息&#xff0c;来预测该岗位平均薪资。 数据预处理 数据示例如下&#xff1a; 因为本文重点介绍如何实现预测&#xff0c;因此对于数据的预处理部分讲解一下处理逻辑&#xff1a; 1、统一薪资的单位&#xff0c;要么统一为年薪&#xff08;万/…

【员工培训体系的建立】使用培训积分制:量化培训效果

该公园希望通过定期培训来帮助员工获取有效信息和先进技术成果&#xff0c;不断提高员工的综合素质&#xff0c;适应新形势的需要&#xff0c;并且管理者逐步认识到&#xff0c;不应把现代公园的人员培训所产生人力资本的再生产视为一种消费&#xff0c;而应视为一种投资&#…

Android 四大组件启动

service: startService启动过程分析 - Gityuan博客 | 袁辉辉的技术博客 在整个startService过程&#xff0c;从进程角度看服务启动过程 Process A进程&#xff1a;是指调用startService命令所在的进程&#xff0c;也就是启动服务的发起端进程&#xff0c;比如点击桌面App图标…

3.Godot节点编辑操作及类的继承关系

1. 节点的父子关系 在层级树中&#xff0c;对象 (节点) 呈树形显示&#xff0c;一个节点下面&#xff0c;也可以下挂子节点 1 添加两个对象 2 拖拽一个对象到另一个对象&#xff0c;成为子对象 (子节点) 3 移动父对象、旋转父对象&#xff0c;观察可以发现&#xff0c;当父对…

【操作系统专题】计算机系统概述

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.基本构成2.微处理器…

MYSQL原理学习篇简记(二)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小周同志&#xff0c;25届双非校招生Java选手&#xff0c;很高兴认识大家 &#x1f4d5;学习出处&#xff1a;本文是学自小林coding (xiaolincoding.com) 网站的MYSQL图解篇 &#x1f525;如果感觉博主的文章还不错的…

使用idea运行程序,发现控制台的中文出现乱码

修改UTF-8发现没有效果&#xff0c;寻找.idea文件夹的encodings.xml文件&#xff0c;将里面的UTF-8全部变成GBK.

数据结构——单链表(C语言版)

文章目录 一、链表的概念及结构二、单链表的实现SList.h链表的打印申请新的结点链表的尾插链表的头插链表的尾删链表的头删链表的查找在指定位置之前插入数据在指定位置之后插入数据删除pos结点删除pos之后的结点销毁链表 三、完整源代码SList.hSList.ctest.c 一、链表的概念及…

Ubuntu 22上安装Anaconda3。下载、安装、验证详细教程

在Ubuntu 22上安装Anaconda3&#xff0c;你可以遵循以下步骤&#xff1a; 更新系统存储库&#xff1a; 打开终端并运行以下命令来更新系统存储库&#xff1a; sudo apt update安装curl包&#xff1a; 下载Anaconda安装脚本通常需要使用curl工具。如果系统中没有安装curl&#x…

基于单链表实现通讯管理系统!(有完整源码!)

​ 个人主页&#xff1a;秋风起&#xff0c;再归来~ 文章专栏&#xff1a;C语言实战项目 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 1、前言 友友们&#xff0c;这篇文章是基于单链…