java-poi实现excel自定义注解生成数据并导出
因为项目很多地方需要使用导出数据excel的功能,所以开发了一个简易的统一生成导出方法。
依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
定义注解
标题栏注解
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.IndexedColors;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelTitle {/*** 标题名称* @return 默认空*/String titleName() ;/*** 标题背景* @return 默认空*/IndexedColors titleBack() default IndexedColors.WHITE;/*** 标题文字大小* @return 默认空*/short titleSize() default 14;/*** 标题文字颜色* @return 黑色*/HSSFColor.HSSFColorPredefined titleColor() default HSSFColor.HSSFColorPredefined.BLACK;/*** 边框格式* @return 细*/BorderStyle borderStyle() default BorderStyle.THIN;/*** 边框颜色* @return 默认*/IndexedColors borderColor() default IndexedColors.AUTOMATIC;/*** 标题文字加粗* @return 黑色*/boolean boldFont() default true;/*** 是否忽略* @return 黑色*/boolean ignore() default false;/*** 排序* @return 0*/int order() default 0;
}
数据栏注解
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @description: excel导出结果配置*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelProperty {/*** 背景* @return 默认空*/IndexedColors textBack() default IndexedColors.WHITE;/*** 内容类型,查看* @link org.apache.poi.ss.usermodel.BuiltinFormats* @return 默认TEXT*/String textType() default "TEXT";/*** 文字大小* @return 默认18*/short textSize() default 12;/*** 数据属于key:value时,可以自定义转换,配置格式为:key1=value;key2=value2;.....* @return 默认空*/String textKv() default "";/*** 文字颜色* @return 黑色*/HSSFColor.HSSFColorPredefined textColor() default HSSFColor.HSSFColorPredefined.BLACK;/*** 水平位置* @return 水平居中*/HorizontalAlignment horizontal() default HorizontalAlignment.CENTER;/*** 垂直位置* @return 垂直居中*/VerticalAlignment vertical() default VerticalAlignment.CENTER;/*** 文字加粗* @return 不加粗*/boolean boldFont() default false;
}
代码
标题栏格式生成
解析对象属性的@ExcelTitle注解的信息,并设置相关选项。
private CellStyle initTitleCellStyle(SXSSFWorkbook wb, Field titleField) {// 单元格样式XSSFCellStyle cellStyle = (XSSFCellStyle) wb.createCellStyle();//水平居中cellStyle.setAlignment(HorizontalAlignment.CENTER);//垂直居中cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);ExcelTitle excelTitle = titleField.getAnnotation(ExcelTitle.class);//背景颜色if(excelTitle != null && excelTitle.titleBack() != null){cellStyle.setFillForegroundColor(excelTitle.titleBack().getIndex());} else {cellStyle.setFillForegroundColor(IndexedColors.WHITE1.getIndex());}//文字的设置字体颜色Font font = wb.createFont();if(excelTitle != null && excelTitle.titleColor() != null){font.setColor(excelTitle.titleColor().getIndex());} else {font.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex());}font.setBold(excelTitle != null && excelTitle.boldFont());font.setFontHeightInPoints(excelTitle != null && excelTitle.titleSize() != 0 ? excelTitle.titleSize(): 12);cellStyle.setFont(font);//设置为文本格式cellStyle.setDataFormat(BuiltinFormats.getBuiltinFormat("TEXT"));cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);//边框if(excelTitle != null && excelTitle.borderStyle() != null){cellStyle.setBorderTop(excelTitle.borderStyle());cellStyle.setBorderBottom(excelTitle.borderStyle());cellStyle.setBorderLeft(excelTitle.borderStyle());cellStyle.setBorderRight(excelTitle.borderStyle());} else {cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setBorderLeft(BorderStyle.THIN);cellStyle.setBorderRight(BorderStyle.THIN);}//边框if(excelTitle != null && excelTitle.borderColor() != null){cellStyle.setTopBorderColor(excelTitle.borderColor().getIndex());cellStyle.setBottomBorderColor(excelTitle.borderColor().getIndex());cellStyle.setLeftBorderColor(excelTitle.borderColor().getIndex());cellStyle.setRightBorderColor(excelTitle.borderColor().getIndex());} else {cellStyle.setTopBorderColor(IndexedColors.RED.getIndex());cellStyle.setBottomBorderColor(IndexedColors.RED.getIndex());cellStyle.setLeftBorderColor(IndexedColors.RED.getIndex());cellStyle.setRightBorderColor(IndexedColors.RED.getIndex());}return cellStyle;}
数据栏格式生成
解析对象属性的@ExcelProperty注解的信息,并设置相关选项。
private CellStyle initCellStyle(SXSSFWorkbook wb, Field titleField) {// 单元格样式(垂直居中)XSSFCellStyle cellStyle = (XSSFCellStyle) wb.createCellStyle();ExcelProperty excelProperty = titleField.getAnnotation(ExcelProperty.class);//水平居中if(excelProperty != null && excelProperty.horizontal() != null) {cellStyle.setAlignment(excelProperty.horizontal());}//垂直居中if(excelProperty != null && excelProperty.vertical() != null) {cellStyle.setVerticalAlignment(excelProperty.vertical());}//背景颜色if(excelProperty != null && excelProperty.textBack() != null){cellStyle.setFillForegroundColor(excelProperty.textBack().getIndex());}//文字的设置字体颜色Font font = wb.createFont();if(excelProperty != null && excelProperty.textColor() != null){font.setColor(excelProperty.textColor().getIndex());}font.setBold(excelProperty != null && excelProperty.boldFont());font.setFontHeightInPoints(excelProperty != null && excelProperty.textSize() != 0 ? excelProperty.textSize(): 12);cellStyle.setFont(font);cellStyle.setBorderTop(BorderStyle.THIN);cellStyle.setBorderBottom(BorderStyle.THIN);cellStyle.setBorderLeft(BorderStyle.THIN);cellStyle.setBorderRight(BorderStyle.THIN);//设置为文本格式cellStyle.setDataFormat(BuiltinFormats.getBuiltinFormat(excelProperty != null && excelProperty.textType() != null ? excelProperty.textType() : "TEXT"));cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);return cellStyle;}
同时提供一个默认的配置:
private CellStyle initDefaultCellStyle(SXSSFWorkbook wb) {// 单元格样式(垂直居中)XSSFCellStyle cellStyle = (XSSFCellStyle) wb.createCellStyle();//水平居中cellStyle.setAlignment(HorizontalAlignment.CENTER);//垂直居中cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//设置为文本格式cellStyle.setDataFormat(BuiltinFormats.getBuiltinFormat("TEXT"));//文字的设置Font font = wb.createFont();font.setColor(HSSFColor.HSSFColorPredefined.BLACK.getIndex()); //设置字体颜色return cellStyle;}
解析数据,生成sheet
private SXSSFWorkbook creatBook(List<ExcelSheetVo> list) {//创建工作簿SXSSFWorkbook wb = new SXSSFWorkbook();for (ExcelSheetVo excelSheetVo : list) {createSXSSFSheet(excelSheetVo, wb);}return wb;}private SXSSFSheet createSXSSFSheet(ExcelSheetVo excelSheetVo, SXSSFWorkbook wb) {//创建工作簿SXSSFSheet sxssfSheet = wb.createSheet(excelSheetVo.getSheetName());//设置默认的行宽sxssfSheet.setDefaultColumnWidth(20);//设置morning的行高(不能设置太小,可以不设置)sxssfSheet.setDefaultRowHeight((short) 300);//设置morning的单元格格式//CellStyle style = initCellStyle(wb);//标题单元格格式//CellStyle titleStyle = initTitleCellStyle(wb, excelSheetVo.getDataClass());//初始化标题栏initTitle(wb, sxssfSheet, excelSheetVo.getDataClass());initSheetData(wb, sxssfSheet, excelSheetVo, 1);return sxssfSheet;}private void initSheetData(SXSSFWorkbook wb, SXSSFSheet sxssfSheet, ExcelSheetVo excelSheetVo, int dataStartLine) {if (CollectionUtils.isEmpty(excelSheetVo.getSheetData())) {return;}try {for (Object dataObject : excelSheetVo.getSheetData()) {SXSSFRow row = sxssfSheet.createRow(dataStartLine);Field[] fields = dataObject.getClass().getDeclaredFields();List<Field> fieldList = Arrays.stream(fields).filter(item -> item.getAnnotation(ExcelTitle.class) != null && !item.getAnnotation(ExcelTitle.class).ignore()).sorted(Comparator.comparingInt(item -> {ExcelTitle excelTitle = item.getAnnotation(ExcelTitle.class);return excelTitle.order();})).collect(Collectors.toList());for (int i = 0; i < fieldList.size(); i++) {//根据title的值对应的值SXSSFCell cell = row.createCell(i);Field field = fieldList.get(i);cell.setCellStyle(initCellStyle(wb, field));field.setAccessible(true);cell.setCellValue(dealValue(field, dataObject));}dataStartLine++;}} catch (Exception e){LOGGER.error("生成数据异常", e);}}
key:value数据解析
private String dealValue(Field field, Object dataObject) throws IllegalAccessException {ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class);Object value = field.get(dataObject);if(value == null){return null;}if(excelProperty != null && StringUtils.isNotEmpty(excelProperty.textKv())){String[] kvs = excelProperty.textKv().split(";");Map<String, String> map = new HashMap<>();for(String str: kvs){map.put(str.split("=")[0], str.split("=")[1]);}return map.get(value.toString());}return value.toString();}
导出设置:
/*** 导出excel数据** @param response 亲求返回* @param list 每个sheet页的数据,一个elist表示一个sheet页* @param fileName 导出的名称* @return 结果*/public boolean creatExcel(HttpServletResponse response, List<ExcelSheetVo> list, String fileName) {SXSSFWorkbook wb = creatBook(list);//导出数据try {//设置Http响应头告诉浏览器下载这个附件response.reset();response.setCharacterEncoding("utf-8");response.setContentType("application/vnd.ms-excel");//名称要从新进行 ISO8859-1 编码否则会文件名称会乱码response.setHeader("Content-Disposition", "attachment;Filename=" + encodeFileName(fileName) + ".xlsx");OutputStream outputStream = response.getOutputStream();ByteArrayOutputStream baos = new ByteArrayOutputStream();wb.write(baos);outputStream.write(baos.toByteArray());baos.flush();baos.close();outputStream.close();} catch (Exception ex) {LOGGER.error("导出excel失败", ex);}return true;}private String encodeFileName(String fileName) {try {//fileName = java.net.URLEncoder.encode(fileName, "UTF-8");fileName = URLDecoder.decode(fileName, "UTF-8");return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);} catch (UnsupportedEncodingException e) {return "未命名";}}
测试
定义数据实体
数据标题和数据定义
@Data
public class TestExcelVo {@ExcelTitle(titleName = "名称", titleColor = HSSFColor.HSSFColorPredefined.BLUE, borderStyle = BorderStyle.HAIR, titleSize = 12, titleBack = IndexedColors.YELLOW)@ExcelProperty()private String name;@ExcelTitle(titleName = "年龄", titleColor = HSSFColor.HSSFColorPredefined.GREEN, borderStyle = BorderStyle.HAIR, titleBack = IndexedColors.RED)@ExcelProperty(textType = "0", textColor = HSSFColor.HSSFColorPredefined.RED)private Integer age;@ExcelTitle(titleName = "性别", titleColor = HSSFColor.HSSFColorPredefined.BLUE, titleSize = 12, titleBack = IndexedColors.GREEN)@ExcelProperty(textKv = "0=男;1=女", textBack = IndexedColors.BROWN)private Integer sex;@ExcelTitle(titleName = "描述", titleColor = HSSFColor.HSSFColorPredefined.BLUE, titleBack = IndexedColors.GREEN)@ExcelProperty(boldFont = true, textSize = 18)private String des;
}
sheet的数据定义
@Data
public class ExcelSheetVo<T> {/*** 每一个sheet页得名称*/private String sheetName;/*** 每个sheet里面得数据* 其中Object中得注解必须时包含 @ExcelTitle 和 @ExcelProperties*/private List<T> sheetData;/*** 数据对象得类型*/private Class dataClass;
}
测试代码
@RestController
@RequestMapping(value = "exceExport")
public class ExcelExportController {@GetMapping("testExport")public void testExport(HttpServletResponse response){String fileName = "测试sheet";List<ExcelSheetVo> sheetVoList = new ArrayList<>();for(int i = 0; i < 3; i++){sheetVoList.add(createSheetData(i));}new ExcelCreateUtil().creatExcel(response, sheetVoList, fileName);}private ExcelSheetVo<TestExcelVo> createSheetData(int index){ExcelSheetVo<TestExcelVo> excelSheetVo = new ExcelSheetVo<>();excelSheetVo.setDataClass(TestExcelVo.class);excelSheetVo.setSheetName("sheet" + index);List<TestExcelVo> testExcelVos = createTestExcelVo(new Random().nextInt(30) + 10, "sheet" + index);excelSheetVo.setSheetData(testExcelVos);return excelSheetVo;}private List<TestExcelVo> createTestExcelVo(int size, String sheetName){List<TestExcelVo> testExcelVos = new ArrayList<>();for(int i = 0; i < size; i++){TestExcelVo testExcelVo = new TestExcelVo();testExcelVo.setName(sheetName + "-" + i);testExcelVo.setAge(i);testExcelVo.setSex(i % 2);testExcelVo.setDes("哈哈哈哈哈" + i);testExcelVos.add(testExcelVo);}return testExcelVos;}
}
结果:
相关文章:

java-poi实现excel自定义注解生成数据并导出
因为项目很多地方需要使用导出数据excel的功能,所以开发了一个简易的统一生成导出方法。 依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version…...
LeetCode707 设计链表
前言 题目: 707. 设计链表 文档: 代码随想录——设计链表 编程语言: C 解题状态: 代码功底不够,只能写个大概 思路 主要考察对链表结构的熟悉程度,对链表的增删改查,比较考验代码功底以及对链表…...

[Mysql-DDL数据操作语句]
目录 DDL语句操作数据库 库: 查看:show 创建:creat 删除:drop 使用(切换):use 表: 查看:desc show 创建:create 表结构修改 rename as add drop modify change rename as …...

google 浏览器插件开发简单学习案例:TodoList;打包成crx离线包
参考: google插件支持: https://blog.csdn.net/weixin_42357472/article/details/140412993 这里是把前面做的TodoList做成google插件,具体网页可以参考下面链接 TodoList网页: https://blog.csdn.net/weixin_42357472/article/de…...

如何学习Doris:糙快猛的大数据之路(从入门到专家)
引言:大数据世界的新玩家 还记得我第一次听说"Doris"这个名字时的情景吗?那是在一个炎热的夏日午后,我正在办公室里为接下来的大数据项目发愁。作为一个刚刚跨行到大数据领域的新手,我感觉自己就像是被丢进了深海的小鱼—周围全是陌生的概念和技术。 就在这时,我的…...

梯度下降算法,gradient descent algorithm
定义:是一个优化算法,也成最速下降算法,主要的部的士通过迭代找到目标函数的最小值,或者收敛到最小值。 说人话就是求一个函数的极值点,极大值或者极小值 算法过程中有几个超参数: 学习率n,又称…...
Spring boot 2.0 升级到 3.3.1 的相关问题 (六)
文章目录 Spring boot 2.0 升级到 3.3.1 的相关问题 (六)spring-data-redis 和 Spring AOP 警告的问题问题描述问题调研结论解决方案方案1-将冲突的Bean 提升为InfrastructureBean方案2 其他相关资料 Spring boot 2.0 升级到 3.3.1 的相关问题 ÿ…...

C++模版基础知识与STL基本介绍
目录 一. 泛型编程 二. 函数模板 1. 概念 2. 函数模版格式 3. 函数模版的原理 4. 模版函数的实例化 (1). 隐式实例化 (2.) 显式实例化 5. 模版参数的匹配原则 三. 类模板 1. 类模板的定义格式 2. 类模板的实例化 四. STL的介绍 1. 什么是STL? 2. STL的版…...

Android 防止重复点击
1.第一种方式: // 两次点击按钮之间的点击间隔不能少于1000毫秒 private static final int MIN_CLICK_DELAY_TIME 700; private static long lastClickTime; /** * 是否是快速点击 * return */ public static boolean isFastClick() { …...

使用阿里云云主机通过nginx搭建文件服务器
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、准备基础环境二、安装配置nginx三、阿里云安全组配置安全组配置 
微信Android一面凉经(2024)
微信Android一面凉经(2024) 笔者作为一名双非二本毕业7年老Android, 最近面试了不少公司, 目前已告一段落, 整理一下各家的面试问题, 打算陆续发布出来, 供有缘人参考。今天给大家带来的是《微信Android一面凉经(2024)》。 面试职位: 微信-客户端开发工程师-基础功能(广州) And…...

VMware、Docker - 让虚拟机走主机代理,解决镜像封禁问题
文章目录 虚拟机全局代理配置找到 VMnet8 的 IPv4 地址代理相关配置虚拟机代理配置 Docker 代理配置修改镜像修改 Docker 代理配置 虚拟机全局代理配置 找到 VMnet8 的 IPv4 地址 a)打开此电脑,输入 “控制面板”,然后回车. b)之…...
版本管理|为什么不推荐使用Git Rebase
文章目录 什么是 Git Rebase?如何使用 Git Rebase?基本语法示例更多选项 注意事项何时使用何时避免其他注意事项 为什么需要谨慎使用 Git Rebase?面试中的常见问题问题 1: Git Rebase 和 Git Merge 有何不同?问题 2: 为什么有时应…...
Https post 请求时绕过证书验证方案
解决异常:Caused by: java.security.cert.CertificateException: No subject alternative names matching IP address xxx.xx.xx.xx found // Https POST 请求private cn.hutool.json.JSON PostGsData(String url, String appKey, String token, Map<String, Ob…...

C# 数组常用遍历方式
// 假设数组Point[] points new Point[2];// 第一种遍历 forfor (int i 0; i < points.Length; i){Point p points[i];Console.WriteLine($"X{p.X},y{p.Y}");}// 第二种遍历 foreachforeach (Point p in points){Console.WriteLine($"X{p.X},y{p.Y}"…...

【JavaScript】详解Day.js:轻量级日期处理库的全面指南
文章目录 一、Day.js简介1. 什么是Day.js?2. 安装Day.js 二、Day.js的基本用法1. 创建日期对象2. 格式化日期3. 解析日期字符串4. 操作日期5. 比较日期 三、Day.js的高级功能1. 插件机制2. 国际化支持 四、实际应用案例1. 事件倒计时2. 日历应用 在JavaScript开发中…...

AI算法与图像处理 | 吴恩达团队新作!多模态方向
本文来源公众号“AI算法与图像处理”,仅用于学术分享,侵权删,干货满满。 原文链接:吴恩达团队新作!多模态方向 研究评估了先进多模态基础模型在 10 个数据集上的多样本上下文学习,揭示了持续的性能提升。…...

云服务器Ubuntu18.04进行Nginx配置
云服务器镜像版本信息:Ubuntu 18.04 server 64bit,本文记录了在改版本镜像上安装Nginx,并介绍了Nginx配置文件目录,便于后面再次有需求时进行复习。 文章目录 Nginx的安装Nginx配置文件分析 Nginx的安装 1.执行下面命令进行安装…...

SQL labs-SQL注入(四,sqlmap对于post传参方式的注入)
本文仅作为学习参考使用,本文作者对任何使用本文进行渗透攻击破坏不负任何责任。 序言:本文主要讲解基于SQL labs靶场,sqlmap工具进行的post传参方式的SQL注入。 传参方式有两类,一类是直接在url栏内进行url编码后进行的传参&am…...

R包:plot1cell单细胞可视化包
介绍 plot1cell是用于单细胞数据seurat数据对象的可视化包。 安装 ## You might need to install the dependencies below if they are not available in your R library. bioc.packages <- c("biomaRt","GenomeInfoDb","EnsDb.Hsapiens.v86&qu…...

shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...