diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..62120cdb2c57a47d1939045d307b815678dca8da
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/target
+/.idea
+/.mvn/
+/*.iml
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
deleted file mode 100644
index 2cc7d4a55c0cd0092912bf49ae38b3a9e3fd0054..0000000000000000000000000000000000000000
Binary files a/.mvn/wrapper/maven-wrapper.jar and /dev/null differ
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..18a94fdc66185f633d84516932d9c52b69eea96a
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,18 @@
+language: java
+
+jdk:
+ - openjdk8
+
+notifications:
+ email: false
+
+before_install:
+ - chmod +x mvnw
+
+script:
+ - export TZ=Asia/Shanghai
+ - mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
+ - mvn cobertura:cobertura -Dcobertura.report.format=xml -Dmaven.javadoc.skip.true
+
+after_success:
+ - bash <(curl -s https://codecov.io/bash)
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ee5839968a2bf86c93283efc09d40fd050b7cfa2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,127 @@
+ 木兰宽松许可证, 第2版
+
+ 木兰宽松许可证, 第2版
+ 2020年1月 http://license.coscl.org.cn/MulanPSL2
+
+
+ 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束:
+
+ 0. 定义
+
+ “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。
+
+ “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。
+
+ “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。
+
+ “法人实体”是指提交贡献的机构及其“关联实体”。
+
+ “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。
+
+ 1. 授予版权许可
+
+ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。
+
+ 2. 授予专利许可
+
+ 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。
+
+ 3. 无商标许可
+
+ “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。
+
+ 4. 分发限制
+
+ 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。
+
+ 5. 免责声明与责任限制
+
+ “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。
+
+ 6. 语言
+ “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。
+
+ 条款结束
+
+ 如何将木兰宽松许可证,第2版,应用到您的软件
+
+ 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步:
+
+ 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字;
+
+ 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中;
+
+ 3, 请将如下声明文本放入每个源文件的头部注释中。
+
+ Copyright (c) [Year] [name of copyright holder]
+ [Software Name] is licensed under Mulan PSL v2.
+ You can use this software according to the terms and conditions of the Mulan PSL v2.
+ You may obtain a copy of Mulan PSL v2 at:
+ http://license.coscl.org.cn/MulanPSL2
+ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ See the Mulan PSL v2 for more details.
+
+
+ Mulan Permissive Software License,Version 2
+
+ Mulan Permissive Software License,Version 2 (Mulan PSL v2)
+ January 2020 http://license.coscl.org.cn/MulanPSL2
+
+ Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions:
+
+ 0. Definition
+
+ Software means the program and related documents which are licensed under this License and comprise all Contribution(s).
+
+ Contribution means the copyrightable work licensed by a particular Contributor under this License.
+
+ Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License.
+
+ Legal Entity means the entity making a Contribution and all its Affiliates.
+
+ Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity.
+
+ 1. Grant of Copyright License
+
+ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not.
+
+ 2. Grant of Patent License
+
+ Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken.
+
+ 3. No Trademark License
+
+ No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4.
+
+ 4. Distribution Restriction
+
+ You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software.
+
+ 5. Disclaimer of Warranty and Limitation of Liability
+
+ THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ 6. Language
+
+ THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL.
+
+ END OF THE TERMS AND CONDITIONS
+
+ How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software
+
+ To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps:
+
+ i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner;
+
+ ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package;
+
+ iii Attach the statement to the appropriate annotated syntax at the beginning of each source file.
+
+
+ Copyright (c) [Year] [name of copyright holder]
+ [Software Name] is licensed under Mulan PSL v2.
+ You can use this software according to the terms and conditions of the Mulan PSL v2.
+ You may obtain a copy of Mulan PSL v2 at:
+ http://license.coscl.org.cn/MulanPSL2
+ THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
+ See the Mulan PSL v2 for more details.
diff --git a/README.md b/README.md
index 3b41d1855ad3865edfa113c573e1c699f4f3136b..04f95f279e0537fc6f07ada5810003933b1cbfeb 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,428 @@
-## Excel支持大量图片导出
+# Excel支持大量图片导出
+[](https://app.travis-ci.com/github/mwk719/excel-batch-picture-support)
+[](https://codecov.io/gh/mwk719/excel-batch-picture-support)
+
+
+
+
-**背景**
+## 背景
用户在导出统计数据时需要导出大量图片.目前用的比较多的poi导出能支持批量导出大量数据(不包括自媒体).但是当需要导出大量图片时,即使设置了flushSize ,但是对于图片对象却没有效果,图片在内存中无法释放,写的图片越多,占用内存越大,导致频繁GC,甚至OOM
-**思路**
+### 思路
+
excel文件由声明,表数据,单元格数据,媒体文件等等组件组成,
这些组件分别对应了不同的数据单元.只要把数据分别写入对应的组件,最后构建成一个需要的excel文件.
-**功能**
+### 原理
+
+生成excel时先将读取到的图片缓存在磁盘上,然后逐步将磁盘上的图片写入到excel中。不像poi导出图片时它是把所有的图片数据放在内存里,然后写入到excel中。
+
+## 功能
+
采用流式方法写入文件,不会导致内存堆积而占用太多系统资源,有效避免频繁GC问题
+
1. 支持自动合并单元格
2. 使用流式处理,支持大量图片导出
3. 支持注解导出,在实体上添加注解,自动生成标题
-**测试**
+### 测试
+
经测试,可以生成几个G的文件。(保证生成的文件没问题,文件是否能打开由使用者计算机决定)
-## 下面对EXCEL的操作做具体介绍
-EXCEL由几大组件构建而成,具体部分:
+## 问题反馈
+
+- [Gitee issue](https://gitee.com/mwk719/excel-batch-picture-support/issues)
+
+## 快速使用
+
+### Maven导入
+
+在项目的pom.xml的dependencies中加入以下内容: 点击查看[最新版本 ${excel-x.version}](https://search.maven.org/artifact/top.minwk/excel-x)
+
+```xml
+
+ top.minwk
+ excel-x
+ ${excel-x.version}
+
+```
+
+### 示例
+
+*[具体功能使用示例可见版本更迭](https://gitee.com/mwk719/excel-batch-picture-support#%E7%89%88%E6%9C%AC%E6%9B%B4%E8%BF%AD)*
+
+- #### 注解使用示例代码
+
+ ```java
+ @GetMapping("/export/lastversion/{row}")
+ public void exportLastVersion(HttpServletResponse response, @PathVariable int row) throws IOException {
+ /*
+ 操作窗口
+ 当写入excel数据行数大于flushSize时{@link Sheet.SheetHandler#createRow(int)},
+ 会刷新数据到流,调用该方法
+ {@link com.ibiz.excel.picture.support.flush.DrawingXmlRelsHandler#copyPictureAppendDrawingRelsXML(Sheet, Picture)}
+ 将图片刷新在磁盘中
+ 不会占用内存空间
+ flushSize = -1 时不刷新流
+ */
+ Workbook workBook = Workbook.getInstance(1);
+ Sheet sheet = workBook.createSheet("测试");
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ sheet.addCellStyle(new CellStyle(0, "66cc66"));
+ List list = new ArrayList<>();
+ UserPicture userPicture;
+ for (int r = 0; r < row; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ // 导出本地单张图片
+ userPicture.setPicture("E:\\test\\img\\1.jpg");
+ // 导出url单张图片
+ userPicture.setHeaderPicture("https://portrait.gitee.com/uploads/avatars/user/552/1657608_mwk719_1641537497.png");
+ // 导出本地图片集合
+ userPicture.setPictures(Arrays.asList("E:\\test\\img\\1.jpg","E:\\test\\img\\2.jpg"));
+ // 导出url图片集合
+ userPicture.setUrlPictures(Arrays.asList("https://portrait.gitee.com/uploads/avatars/user/552/1657608_mwk719_1641537497.png",
+ "https://img2.baidu.com/it/u=2602880481,728201544&fm=26&fmt=auto"));
+ list.add(userPicture);
+ }
+ sheet.write(UserPicture.class).createRow(list);
+ WebUtil.writeExcel(workBook, "最新使用示例代码导出".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), response);
+ }
+ ```
+
+ ```java
+ /**
+ * @auther 喻场
+ * @date 2020/7/813:41
+ */
+ public class UserPicture {
+
+ public UserPicture() {
+ }
+
+ @ExportModel( sort = 0, title = "姓名")
+ private String name;
+ @ExportModel(sort = 1, title = "年龄")
+ private Integer age;
+ @ExportModel(sort = 3, title = "部门")
+ private String department;
+ @ExportModel(sort = 2, isPicture = true, title = "图片1")
+ private String picture;
+ @ExportModel(sort = 4, isPicture = true, title = "图片2")
+ private String headerPicture;
+ @ExportModel(sort = 5, isPicture = true, title = "多图片")
+ private List pictures;
+ @ExportModel(sort = 6, isPicture = true, title = "url多图片")
+ private List urlPictures;
+
+ public UserPicture(String name, Integer age, String department, String picture) {
+ this.name = name;
+ this.age = age;
+ this.department = department;
+ this.picture = picture;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public String getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(String department) {
+ this.department = department;
+ }
+
+ public String getPicture() {
+ return picture;
+ }
+
+ public void setPicture(String picture) {
+ this.picture = picture;
+ }
+
+ public String getHeaderPicture() {
+ return headerPicture;
+ }
+
+ public void setHeaderPicture(String headerPicture) {
+ this.headerPicture = headerPicture;
+ }
+
+ public List getPictures() {
+ return pictures;
+ }
+
+ public void setPictures(List pictures) {
+ this.pictures = pictures;
+ }
+
+ public List getUrlPictures() {
+ return urlPictures;
+ }
+
+ public void setUrlPictures(List urlPictures) {
+ this.urlPictures = urlPictures;
+ }
+ }
+
+ ```
+
+- #### 动态配置表头excel导出示例代码
+
+ *实体对象需要实现BizExcelPojoInterface接口*
+
+ ```java
+ @GetMapping("/export/dynamic-config-header")
+ public void exportDynamicConfigHeader(HttpServletResponse response) throws IOException {
+ // 模拟需要导出的数据集合
+ List students = new ArrayList<>();
+ students.add(new Student("李四", 16, null, null, 0));
+ students.add(new Student("张三", 17, null,
+ Arrays.asList("https://portrait.gitee.com/uploads/avatars/user/552/1657608_mwk719_1641537497.png",
+ "https://img2.baidu.com/it/u=2602880481,728201544&fm=26&fmt=auto"), 1));
+ students.add(new Student("王五", 15, IMG_PATH_1, null, 2));
+
+ // 配置导出excel的表头、顺序、对应导出的数据集合的字段、是否是图片、单元格宽度等
+ List excels = new ArrayList<>();
+ excels.add(new BizExcelRel("姓名", "name", 2));
+ excels.add(new BizExcelRel("年龄", "age", 3));
+ excels.add(new BizExcelRel("表现", "performance", 4));
+ excels.add(new BizExcelRel("头像", "headPicture", 5, true, 20));
+ excels.add(new BizExcelRel("相册", "album", 6, true));
+
+ // 创建excel
+ Workbook workBook = Workbook.getInstance(100);
+ Sheet sheet = workBook.createSheet("测试");
+ // 创建样式
+ CellStyle cellStyle = new CellStyle(0, "F0F0F0");
+ // 创建数据字典
+ Map performanceMap = new HashMap<>(3);
+ performanceMap.put("0", "一般");
+ performanceMap.put("1", "良好");
+ performanceMap.put("2", "优秀");
+
+ // 构建sheet
+ ExcelTableProcessor.sheet(sheet)
+ // 添加样式
+ .addCellStyle(cellStyle)
+ // 添加对应属性字段的数据字典
+ .registryEnumMap("performance", performanceMap)
+ // 构建excel
+ .buildExcel(excels, students);
+ WebUtil.writeExcel(workBook, "ExportExampleDynamicConfigHeader".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), response);
+ }
+ ```
+
+ ```java
+ public class Student implements BizExcelPojoInterface {
+
+ public Student(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public Student(String name, Integer age, String headPicture) {
+ this.name = name;
+ this.age = age;
+ this.headPicture = headPicture;
+ }
+
+ public Student(String name, Integer age, String headPicture, List album, Integer performance) {
+ this.name = name;
+ this.age = age;
+ this.headPicture = headPicture;
+ this.album = album;
+ this.performance = performance;
+ }
+
+ private String name;
+
+ private Integer age;
+
+ private String headPicture;
+
+ /**
+ * 相册
+ */
+ private List album;
+
+ /**
+ * 表现 0一般;1良好;2优秀
+ */
+ private Integer performance;
+
+ public Integer getPerformance() {
+ return performance;
+ }
+
+ public void setPerformance(Integer performance) {
+ this.performance = performance;
+ }
+
+ public List getAlbum() {
+ return album;
+ }
+
+ public void setAlbum(List album) {
+ this.album = album;
+ }
+
+ public String getHeadPicture() {
+ return headPicture;
+ }
+
+ public void setHeadPicture(String headPicture) {
+ this.headPicture = headPicture;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+ }
+ ```
+
+- [excel含图片导出demo地址](https://gitee.com/mwk719/excel-batch-picture-support/tree/dev/src/test/java/com/ibiz/excel/picture/support/example),具体使用以后缀最新日期为准,其他示例仅供测试
+
+- [微云-6767张图片共800mb资源.rar 可用于测试](https://minwk.top/big-size-img/)
+
+- [项目中导出下载excel使用示例](https://gitee.com/mwk719/spring-learn/blob/master/src/main/java/com/mwk/external/controller/ExcelController.java)
+
+#### 项目中测试使用
+
+1. 设置项目jvm堆栈大小都是20m
+
+ ```bash
+ -Xms20m -Xmx20m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\log\springlearn.hprof
+ ```
+
+2. 复制上方 【最新使用示例代码】到项目中
+
+3. 找一堆图片随机添加到UserPicture中
+
+4. 导出一个5000条的记录,在最大堆栈占用为20m的情况下,导出excel大小为700m,未发生内存溢出情况
+
+## 版本更迭
+
+*点击可跳转链接可以查看功能使用示例*
+
+#### 2.4.3(2023.07.20)
+
+- 修复单元格合并错误
+
+#### 2.4.2(2023.07.17)
+
+- [添加内容对齐操作(自动换行、上下左右)](https://gitee.com/mwk719/excel-batch-picture-support/blob/master/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230713.java#L74)([issues#I7IO5K](https://gitee.com/mwk719/excel-batch-picture-support/issues/I7IO5K))
+- 修复当添加列超过52列时出现异常
+
+#### 2.4.1(2023.06.06)
+
+- [添加对全局边框进行加粗、对单元格边框加粗配置](https://gitee.com/mwk719/excel-batch-picture-support/blob/dev/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230110.java#L64)
+- 修复Microsoft Excel2010打开单元格超宽问题
+- 优化创建标题时控制列顺序
+
+#### 2.4.0(2023.01.12)
+
+- [添加可以给单个单元格设置样式](https://gitee.com/mwk719/excel-batch-picture-support/blob/dev/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230110.java)
+
+#### 2.3.1(2022.12.19)
+
+- 修复渲染生成列元素A-Z坐标时,使用到Z时,下一列从AA开始
+- 修复行元素为空时合并单元格错误
+
+#### 2.3.0(2022.02.23)
+
+- [添加可动态配置表头excel导出](https://gitee.com/mwk719/spring-learn/blob/master/src/main/java/com/mwk/external/controller/ExcelController.java#L285)
+
+#### 2.2.2(2022.02.08)
+
+- 修复合并后的单元格没有边框线
+
+#### 2.2.1(2022.01.28)
+
+- [优化对合并单元格的处理](https://gitee.com/mwk719/excel-batch-picture-support/blob/master/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220128.java#L30)
+
+#### 2.2.0(2022.01.27)
+
+- [添加导出excel中字体设置](https://gitee.com/mwk719/spring-learn/blob/master/src/main/java/com/mwk/external/controller/ExcelController.java#L243)
+
+#### 2.1.0(2022.01.14)
+
+- [添加导出网络链接图片到excel中](https://gitee.com/mwk719/spring-learn/blob/master/src/main/java/com/mwk/external/controller/ExcelController.java#L146)
+- [添加createRow集合列表生成excel方法](https://gitee.com/mwk719/spring-learn/blob/master/src/main/java/com/mwk/external/controller/ExcelController.java#L191)
+- 修改CellStyle样式的使用
+
+#### 2.0.0(2021.12.30)
+
+- [添加用户可自定义背景色样式](https://gitee.com/mwk719/excel-batch-picture-support/blob/dev/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPicturesExportExample.java)
+- [添加使用注解可对图片集合进行导出](https://gitee.com/mwk719/excel-batch-picture-support/blob/dev/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPicturesExportExample.java)
+- 添加自定义图片的高度;图片高度和单元格高度自适应
+- 修复导出图片集合变多时单元格宽度不够
+- 修复导出数据行数大于100 excel打开异常
+- 修复导出多组图片excel中缺失部分图片问题
+
+#### 1.0.4(2021.12.08)
+
+- 添加使用注解导出含图片或文本的使用示例
+- 修复图片遮挡所在单元格边框线
+- 修复f使用注解导出图片所在下边框不是加粗实线
+
+#### 1.0.3(2021.02.26)
+
+- 简化使用示例
+- 修复flushSize = -1 时不刷新流
+- 修复其他未知问题
+
+#### 1.0.2(2021.01.26)
+
+- 修复MD5时未关闭流
+
+#### 1.0.1(2021.01.23)
+
+- 添加合并单元列值
+- 添加设置单元格背景色
+- 添加可自定义单元格宽度
+- 添加设置字体,目前有默认字体
+- 修复office打开提示需修复的问题
+
+## 组件介绍
+
+EXCEL由几大组件构建而成
+
+### 具体部分:

-工作文件实例
+
+### 工作文件实例
+
1. workbook代表一个excel工作文件
2. Sheet对应文件中多个sheet页
3. Row 为sheet页中的行数据,包含多个Cell单元格
diff --git a/pom.xml b/pom.xml
index fc73582a8018644bb4e450ee926c052844c9d896..17efe6f9657393f16de64e5dba3d6d967b527333 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,53 +1,209 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.3.1.RELEASE
-
-
- com.ibiz
- excel-x
- 0.0.1-SNAPSHOT
- excel-x
- Demo project for Spring Boot
-
-
- 1.8
-
-
-
-
- org.springframework.boot
- spring-boot-starter
-
-
- org.apache.ant
- ant
- 1.10.5
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
-
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+ 4.0.0
+ top.minwk
+ excel-x
+ 2.4.3
+ excel-x
+ 支持excel中批量导出图片
+ https://gitee.com/mwk719/excel-batch-picture-support
+
+
+ utf-8
+ utf-8
+
+ true
+
+ 8
+ 1.8
+ 5.3.15
+ 5.7.19
+ 4.13.2
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ actable
+
+
+
+
+
+ minwk
+ minweikai@gmail.com
+ 影落离风
+ https://minwk.top/
+
+
+
+
+ https://gitee.com/mwk719/excel-batch-picture-support
+ https://gitee.com/mwk719/excel-batch-picture-support.git
+ https://gitee.com/mwk719/excel-batch-picture-support
+
+
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.32
+
+
+ org.springframework
+ spring-core
+ ${version.spring}
+
+
+ org.springframework
+ spring-beans
+ ${version.spring}
+
+
+
+ javax.servlet
+ javax.servlet-api
+ 4.0.0
+ provided
+
+
+ org.springframework
+ spring-web
+ ${version.spring}
+
+
+ cn.hutool
+ hutool-core
+ ${hutool.version}
+
+
+ cn.hutool
+ hutool-http
+ ${hutool.version}
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+ 2.8.2
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.1
+
+ ${compile.version}
+ ${compile.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.1.1
+
+
+ package
+
+ jar
+
+
+
+
+
+ none
+
+
+
+
+
+
+
+
+
+ release
+
+
+ oss
+ https://oss.sonatype.org/content/repositories/snapshots/
+
+
+ oss
+ https://oss.sonatype.org/service/local/staging/deploy/maven2/
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.2.1
+
+
+ oss
+ package
+
+ jar-no-fork
+
+
+
+
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ 2.7
+
+
+ html
+ xml
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ oss
+ verify
+
+ sign
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.8
+ true
+
+ oss
+ https://oss.sonatype.org/
+ true
+
+
+
+
+
+
+
diff --git a/src/main/java/com/ibiz/excel/picture/support/ExcelXApplication.java b/src/main/java/com/ibiz/excel/picture/support/ExcelXApplication.java
deleted file mode 100644
index 48cdf2a938ec3e00f40601ef8cd222e3350586cf..0000000000000000000000000000000000000000
--- a/src/main/java/com/ibiz/excel/picture/support/ExcelXApplication.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.ibiz.excel.picture.support;
-
-import com.ibiz.excel.picture.support.model.Sheet;
-import com.ibiz.excel.picture.support.model.Workbook;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import java.util.stream.IntStream;
-
-@SpringBootApplication
-public class ExcelXApplication {
-
- public static void main(String[] args) {
- Workbook workBook = Workbook.getInstance(200);
- Sheet sheet = workBook.createSheet("导出个表");
- /*User u1 = new User("z1", 12, "a1", "D:\\1.png");
- User u2 = new User("z2", 12, "a2", "");
- User u3 = new User("z3", 12, "a3", "D:\\1.png");
- User u4 = new User("z3", 12, "a3", "");*/
- IntStream.range(0, 1).forEach(r -> {
- /*sheet.createRow(u1);
- sheet.createRow(u2);
- sheet.createRow(u3);
- sheet.createRow(u4);*/
- });
- workBook.close();
- }
-}
diff --git a/src/main/java/com/ibiz/excel/picture/support/annotation/ExportModel.java b/src/main/java/com/ibiz/excel/picture/support/annotation/ExportModel.java
index f325619c18a925c3d4e30abecab51cb3d6ea1e93..0cff822098367cf236372b0acb1bba009140ff91 100644
--- a/src/main/java/com/ibiz/excel/picture/support/annotation/ExportModel.java
+++ b/src/main/java/com/ibiz/excel/picture/support/annotation/ExportModel.java
@@ -1,24 +1,72 @@
package com.ibiz.excel.picture.support.annotation;
+import com.ibiz.excel.picture.support.constants.PictureSourceContent;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.Picture;
+
import java.lang.annotation.*;
/**
* 导出模型
* 使用该注解程序会根据相应属性对单元格做设置
+ *
+ * @author MinWeikai
+ * @date 2021-12-22 14:43:43
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface ExportModel {
- /**排序*/
- int sort() default 0;
- /**是否是图片*/
+ /**
+ * 排序,必填,且不能重复
+ *
+ */
+ int sort() ;
+
+ /**
+ * 是否是图片
+ */
boolean isPicture() default false;
- /**表头*/
+
+ /**
+ * 表头
+ */
String title() default "";
- /**已这列为准进行合并列*/
+
+ /**
+ * 已这列为准进行合并列
+ */
boolean mergeMaster() default false;
- /**这一列是否要合并*/
+
+ /**
+ * 这一列是否要合并
+ */
boolean merge() default false;
+
+ /**
+ * 图片所在单元格宽度,图片和单元格宽度一致,建议使用默认 1500000作为宽度
+ * {@link com.ibiz.excel.picture.support.model.Picture}
+ *
+ * @return
+ */
+ int width() default WorkbookConstant.PICTURE_WEIGHT;
+
+ /**
+ * 图片所在单元格行高度,单元格会自适应图片的高度
+ * 如需要自定义图片高度,注意:在导出类中有多个图片字段,需要在每个图片字段上注解配置自定义的高度
+ *
+ * @return
+ */
+ int height() default WorkbookConstant.PICTURE_HEIGHT;
+
+ /**
+ * 图片来源 默认为0,自动判断图片来源
+ * {@link Picture#autoPictureSourceByPath()}
+ * 不设置的话自动匹配,也可自己指定
+ * {@link PictureSourceContent}
+ *
+ * @return
+ */
+ int pictureSource() default 0;
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/constants/PictureSourceContent.java b/src/main/java/com/ibiz/excel/picture/support/constants/PictureSourceContent.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e7f4cc23c4322cb64c28b08c0834c2f61679816
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/constants/PictureSourceContent.java
@@ -0,0 +1,20 @@
+package com.ibiz.excel.picture.support.constants;
+
+/**
+ * 图片来源
+ *
+ * @author MinWeikai
+ * @date 2022/1/7 16:51
+ */
+public class PictureSourceContent {
+
+ /**
+ * 绝对路径
+ */
+ public static final int ABSOLUTE_PATH = 1;
+
+ /**
+ * 网络链接
+ */
+ public static final int WEB_URL = 2;
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/constants/WorkbookConstant.java b/src/main/java/com/ibiz/excel/picture/support/constants/WorkbookConstant.java
index 9b7fc321cbed7d5d814119a8481a7e5d2a57f097..e3ce3a73fc9190590bc3be3af789ad5d867ad2f4 100644
--- a/src/main/java/com/ibiz/excel/picture/support/constants/WorkbookConstant.java
+++ b/src/main/java/com/ibiz/excel/picture/support/constants/WorkbookConstant.java
@@ -6,9 +6,66 @@ package com.ibiz.excel.picture.support.constants;
*/
public class WorkbookConstant {
public static final String AUTO_DIR = System.getProperty("java.io.tmpdir");
- public static final String FILE_SEPARATOR = "\\";
+ public static final String FILE_SEPARATOR = "/";
public static final String DEST_FILE_NAME_SUFFIX = ".xlsx";
public static final String MEDIA_IMAGE_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
- /**有图片的行高设置为100*/
+ /**
+ * 有图片的行高设置为100
+ */
public static final int PICTURE_ROW_HEIGHT = 100;
+
+ /**
+ * 图片默认高度
+ */
+ public static final int PICTURE_HEIGHT = 1260000;
+ /**
+ * 图片默认宽度
+ */
+ public static final int PICTURE_WEIGHT = 1500000;
+
+ /**
+ * 单元格宽度
+ */
+ public static final double CELL_WEIGHT = 23.5;
+
+ /**
+ * 下载网络图片超时时间
+ */
+ public static final int DOWNLOAD_PICTURE_TIME_OUT = 10 * 1000;
+
+ /**
+ * 默认已有cellStyles样式
+ */
+ public static final int S = 1;
+
+ /**
+ * 边框加粗,默认为1加粗,0不加粗
+ */
+ public static int BORDER_BOLD = 1;
+
+ /**
+ * 设置自动换行
+ * 1表示自动换行
+ */
+ public static int WRAP_TEXT = 0;
+
+ /**
+ * 垂直对齐方式
+ * 默认居中对齐
+ */
+ public static String VERTICAL = "center";
+
+ /**
+ * 水平对齐方式
+ * 默认居中对齐
+ */
+ public static String HORIZONTAL = "center";
+
+ /**
+ * 边框加粗,true加粗,false不加粗
+ * @param borderBold
+ */
+ public static void setBorderBold(boolean borderBold) {
+ BORDER_BOLD = borderBold ? 1 : 0;
+ }
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/factory/RepositoryFactory.java b/src/main/java/com/ibiz/excel/picture/support/factory/RepositoryFactory.java
index f844e2434d8f00adaa6d2b34ecfdafb49d9e81f3..e329b28f27731453c0456e027eab0a10bb763919 100644
--- a/src/main/java/com/ibiz/excel/picture/support/factory/RepositoryFactory.java
+++ b/src/main/java/com/ibiz/excel/picture/support/factory/RepositoryFactory.java
@@ -1,14 +1,22 @@
package com.ibiz.excel.picture.support.factory;
-import com.ibiz.excel.picture.support.flush.*;
import com.ibiz.excel.picture.support.constants.Alias;
+import com.ibiz.excel.picture.support.flush.Drawing1Handler;
+import com.ibiz.excel.picture.support.flush.DrawingXmlRelsHandler;
+import com.ibiz.excel.picture.support.flush.IRepository;
+import com.ibiz.excel.picture.support.flush.Repository;
+import com.ibiz.excel.picture.support.flush.SharedStringXmlHandler;
+import com.ibiz.excel.picture.support.flush.Sheet1Handler;
+import com.ibiz.excel.picture.support.flush.StylesHandler;
import com.ibiz.excel.picture.support.util.StringUtils;
import java.io.BufferedWriter;
import java.io.File;
-import java.io.FileWriter;
import java.io.IOException;
+import java.io.OutputStreamWriter;
import java.lang.reflect.Proxy;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
/**
* @auther 喻场
@@ -19,9 +27,9 @@ public class RepositoryFactory {
public static IRepository getNewInstance(String alisa, File file, String content, String endContent, boolean writeXmlHead) throws IOException {
Repository instance = new Repository();
String name = file.getName();
- if (name.indexOf(".") > -1) {
+ if (name.contains(".")) {
//加这个判断因为media是一个目录,不是文件
- instance.setWrite(new BufferedWriter(new FileWriter(file)));
+ instance.setWrite(new BufferedWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8)));
}
instance.setFile(file);
instance.setWriteXmlHead(writeXmlHead);
@@ -29,13 +37,15 @@ public class RepositoryFactory {
instance.setEndContent(endContent);
IRepository repository = instance;
if (StringUtils.equals(alisa, Alias.DRAWING1_XML_RELS)) {
- repository = (IRepository)Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new DrawingXmlRelsHandler(instance));
+ repository = (IRepository) Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new DrawingXmlRelsHandler(instance));
} else if (StringUtils.equals(alisa, Alias.DRAWING1)) {
- repository = (IRepository)Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new Drawing1Handler(instance));
+ repository = (IRepository) Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new Drawing1Handler(instance));
} else if (StringUtils.equals(alisa, Alias.SHARED_STRING_XML)) {
- repository = (IRepository)Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new SharedStringXmlHandler(instance));
+ repository = (IRepository) Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new SharedStringXmlHandler(instance));
} else if (StringUtils.equals(alisa, Alias.SHEET1)) {
- repository = (IRepository)Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new Sheet1Handler(instance));
+ repository = (IRepository) Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new Sheet1Handler(instance));
+ } else if (StringUtils.equals(alisa, Alias.STYLES)) {
+ repository = (IRepository) Proxy.newProxyInstance(RepositoryFactory.class.getClassLoader(), new Class[]{IRepository.class}, new StylesHandler(instance));
}
return repository;
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/flush/Drawing1Handler.java b/src/main/java/com/ibiz/excel/picture/support/flush/Drawing1Handler.java
index a21c254e22d80e6d004f504ed3d148d6d3d175f7..26a672b82b5a39cee7e7fd46541a7819dfb23fbe 100644
--- a/src/main/java/com/ibiz/excel/picture/support/flush/Drawing1Handler.java
+++ b/src/main/java/com/ibiz/excel/picture/support/flush/Drawing1Handler.java
@@ -2,49 +2,106 @@ package com.ibiz.excel.picture.support.flush;
import com.ibiz.excel.picture.support.model.Picture;
import com.ibiz.excel.picture.support.model.Sheet;
+
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
-import java.util.Objects;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
- * 图片
- * @auther 喻场
- * @date 2020/7/618:33
+ * 适应单元格填充多图
+ *
+ * @author MinWeikai
+ * @date 2021-01-19 18:53:06
*/
public class Drawing1Handler implements InvocationHandler {
- private IRepository target;
- public Drawing1Handler(IRepository proxy) {
- this.target = proxy;
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getName().equals("write")) {
- Sheet sheet = (Sheet)args[0];
- List pictures = sheet.getPictures();
- pictures.stream().filter(Objects::nonNull).forEach(p -> {
- writerDrawingXML(p);
- });
- }
- return method.invoke(target, args);
- }
-
- /**
- * 写 drawing1.xml
- * @param picture
- * @param picture
- */
- private void writerDrawingXML(
- Picture picture) {
- String content = "" + picture.getFromCol() +"0" +
- "" + picture.getFromRow() + "0\n" +
- "" + picture.getToCol() +"9525" +
- "" + picture.getToRow() +"1260000" +
- "" +
- "\n" +
- "\n" +
- "";
- target.append(content);
- }
+ private IRepository target;
+
+ /**
+ * 容器间距 默认10000,可能约等于1px吧
+ */
+ private static final int PADDING = 10000;
+
+ public Drawing1Handler(IRepository proxy) {
+ this.target = proxy;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().equals("write")) {
+ Sheet sheet = (Sheet) args[0];
+ // 将同一单元格的图片分组在一个集合中
+ Map> listMap = sheet.getPictures().stream()
+ .collect(Collectors.groupingBy(e -> e.getFromCol() + "_" + e.getFromRow()));
+ for (Map.Entry> map : listMap.entrySet()) {
+ this.writerDrawing(map.getValue());
+ }
+ }
+ return method.invoke(target, args);
+ }
+
+ private void writerDrawing(List pictures) {
+ Picture p;
+ for (int i = 0; i < pictures.size(); i++) {
+ p = pictures.get(i);
+ if (p != null) {
+ writerDrawingXML(p, i);
+ }
+ }
+ }
+
+ /**
+ * 写 drawing1.xml
+ *
+ * @param picture 图片
+ * @param i 第几张图片,从0开始
+ */
+ private void writerDrawingXML(
+ Picture picture, int i) {
+ /*
+ 表示从xx开始
+ 2 第几个单元格
+ 9525 离左边框距离
+ 2 第几行
+ 9525 离上边框距离
+
+ 表示到xx位置
+ 2 第几个单元格
+ 1009525
+ 3 第几行
+ 12225 离上边框距离
+
+ 图片标签
+
+ */
+ String content = "" +
+ "" + picture.getFromCol() + "";
+ // 图片间距
+ int colOff = i * picture.getWidth();
+ // 默认从离左边框1个像素,防止图片遮挡边框线
+ if(colOff == 0){
+ colOff = PADDING;
+ }
+ content = content + colOff + "" +
+ "" + picture.getFromRow() + "" +
+ "" + PADDING +
+ "" +
+ "" +
+ "\n" +
+ "" + picture.getToCol() + "" + (colOff + picture.getWidth() - PADDING) + "" +
+ "" + (picture.getToRow()) +
+ // 设置图片高度
+ ""+ picture.getHeight() +"" +
+ "" +
+ "" +
+ "" +
+ "\n" +
+ "\n" +
+ "" +
+ "" +
+ "";
+ target.append(content);
+ }
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/flush/DrawingXmlRelsHandler.java b/src/main/java/com/ibiz/excel/picture/support/flush/DrawingXmlRelsHandler.java
index 4ff6bbfcf68986569233f1e2a988669cfc878edd..efb4684bb3f3415bb284e6bb7154bfd550ed055e 100644
--- a/src/main/java/com/ibiz/excel/picture/support/flush/DrawingXmlRelsHandler.java
+++ b/src/main/java/com/ibiz/excel/picture/support/flush/DrawingXmlRelsHandler.java
@@ -1,47 +1,50 @@
package com.ibiz.excel.picture.support.flush;
-import com.ibiz.excel.picture.support.util.CovertUtil;
+import cn.hutool.http.HttpUtil;
import com.ibiz.excel.picture.support.constants.Alias;
+import com.ibiz.excel.picture.support.constants.PictureSourceContent;
import com.ibiz.excel.picture.support.constants.WorkbookConstant;
import com.ibiz.excel.picture.support.model.Picture;
import com.ibiz.excel.picture.support.model.Sheet;
import com.ibiz.excel.picture.support.module.RelationShip;
+import com.ibiz.excel.picture.support.util.CovertUtil;
import com.ibiz.excel.picture.support.util.FileUtil;
import com.ibiz.excel.picture.support.util.MD5Digester;
import com.ibiz.excel.picture.support.util.StringUtils;
-import org.apache.tools.ant.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
-import java.util.*;
+import java.util.List;
+import java.util.Objects;
/**
* 图片
+ *
* @auther 喻场
* @date 2020/7/618:33
*/
public class DrawingXmlRelsHandler implements InvocationHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private IRepository target;
+
public DrawingXmlRelsHandler(IRepository proxy) {
this.target = proxy;
}
+
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("write")) {
- Sheet sheet = (Sheet)args[0];
+ Sheet sheet = (Sheet) args[0];
List pictures = sheet.getPictures();
pictures.stream().filter(Objects::nonNull).forEach(p -> {
if (StringUtils.isNotBlank(p.getPicturePath())) {
- File file = new File(p.getPicturePath());
- if(file.exists()) {
- //写图片
- copyPictureAppendDrawingRelsXML(sheet, p);
- }
+ //写图片
+ copyPictureAppendDrawingRelsXML(sheet, p);
}
});
}
@@ -50,35 +53,91 @@ public class DrawingXmlRelsHandler implements InvocationHandler {
/**
* 把图片copy到media目录下
+ *
* @param sheet
* @param picture
*/
private void copyPictureAppendDrawingRelsXML(Sheet sheet, Picture picture) {
+ String picturePath = picture.getPicturePath();
+ // 根据图片来源获取文件md5值
+ String md5;
+ try {
+ md5 = getMd5BySource(picture.getPictureSource(), picturePath);
+ } catch (FileNotFoundException e) {
+ logger.warn("获取不到路径为{}的图片", picturePath);
+ // 获取不到时跳出
+ return;
+ }
+
try {
- File srcPicture = new File(picture.getPicturePath());
- String md5 = MD5Digester.digestMD5(srcPicture);
Integer drawingSequence = sheet.getWorkbook().getImageCache().get(md5);
+ // 已存在的图片
if (Objects.nonNull(drawingSequence)) {
- RelationShip relationShip = new RelationShip("rId" + drawingSequence, WorkbookConstant.MEDIA_IMAGE_TYPE, "../media/image" + drawingSequence +".png");
+ // 记录索引
picture.setRembed(drawingSequence);
- target.append(CovertUtil.covert(relationShip));
return;
}
File media = sheet.getSheetContext().getRepositoryHolder().get(Alias.MEDIA).getFile();
drawingSequence = sheet.getDrawingSequence();
- File destPicture = new File(media, "image"+ drawingSequence + ".png");
- FileUtil.copyFile(srcPicture, destPicture);
+ // 获取excel资源图片
+ File destPicture = getExcelDestPicture(picture, picturePath, drawingSequence, media);
+ // 输出的图片不存在则跳出
+ if (!destPicture.exists()) {
+ return;
+ }
picture.setRembed(drawingSequence);
- RelationShip relationShip = new RelationShip("rId" + drawingSequence, WorkbookConstant.MEDIA_IMAGE_TYPE, "../media/image" + drawingSequence +".png");
+ RelationShip relationShip = new RelationShip("rId" + drawingSequence, WorkbookConstant.MEDIA_IMAGE_TYPE, "../media/image" + drawingSequence + ".png");
//先把drawingSequence放入缓存,因为从缓存中获取时设置drawingSequence再+1对应图片。实际图片的drawingSequence不变
sheet.getWorkbook().getImageCache().put(md5, drawingSequence);
drawingSequence++;
sheet.setDrawingSequence(drawingSequence);
target.append(CovertUtil.covert(relationShip));
- } catch (IOException e) {
- logger.error("图片copy到media目录下异常",e);
- }catch (Exception e) {
- logger.error("图片copy到media目录下异常",e);
+ } catch (Exception e) {
+ logger.error("图片copy到media目录下异常", e);
+ }
+ }
+
+ /**
+ * 获取excel资源图片
+ * @param picture
+ * @param picturePath
+ * @param drawingSequence
+ * @param media
+ * @return
+ * @throws IOException
+ */
+ private static File getExcelDestPicture(Picture picture, String picturePath, Integer drawingSequence, File media) throws IOException {
+ File destPicture = new File(media, "image" + drawingSequence + ".png");
+ if (PictureSourceContent.WEB_URL == picture.getPictureSource()) {
+ // 下载网络图片到excel资源路径
+ HttpUtil.downloadFile(picturePath, destPicture, WorkbookConstant.DOWNLOAD_PICTURE_TIME_OUT);
+ } else {
+ // 绝对路径图片
+ File srcPicture = new File(picturePath);
+ // 复制绝对图片到excel资源路径
+ FileUtil.copyFile(srcPicture, destPicture);
+ }
+ return destPicture;
+ }
+
+ /**
+ * 根据图片来源获取文件md5值
+ *
+ * @param pictureSource
+ * @param picturePath
+ * @return
+ * @throws FileNotFoundException
+ */
+ private static String getMd5BySource(int pictureSource, String picturePath) throws FileNotFoundException {
+ String md5;
+ // 判断图片来源
+ if (PictureSourceContent.WEB_URL == pictureSource) {
+ md5 = MD5Digester.digestMD5(picturePath);
+ } else {
+ // 绝对路径图片
+ File srcPicture = new File(picturePath);
+ md5 = MD5Digester.digestMD5(srcPicture);
}
+ return md5;
}
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/flush/Sheet1Handler.java b/src/main/java/com/ibiz/excel/picture/support/flush/Sheet1Handler.java
index 7e28279972e1fcd3872be9ce35f8cfc26d99e9b4..eb08971f0249106815f10399c11bbf6b0dff4862 100644
--- a/src/main/java/com/ibiz/excel/picture/support/flush/Sheet1Handler.java
+++ b/src/main/java/com/ibiz/excel/picture/support/flush/Sheet1Handler.java
@@ -1,35 +1,44 @@
package com.ibiz.excel.picture.support.flush;
-import com.ibiz.excel.picture.support.model.Cell;
-import com.ibiz.excel.picture.support.model.MergeCell;
-import com.ibiz.excel.picture.support.model.Row;
-import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.*;
import com.ibiz.excel.picture.support.util.StringUtils;
+import org.springframework.util.CollectionUtils;
+
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
/**
* 图片
+ *
* @auther 喻场
* @date 2020/7/618:33
*/
public class Sheet1Handler implements InvocationHandler {
private IRepository target;
+
+ private StylesIndex stylesIndex = new StylesIndex();
+
public Sheet1Handler(IRepository proxy) {
this.target = proxy;
}
+
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Sheet sheet = (Sheet)args[0];
+ Sheet sheet = (Sheet) args[0];
if (method.getName().equals("write")) {
List rows = sheet.getRows();
if (!rows.isEmpty()) {
//未刷新过说明没有写入过流,这里主要为了写表头
//如果写过了,则从脚标1开始,原因是为了对比合并单元格在row1中保存上一次刷新的最后一条数据
int subIndex = !sheet.hasFlush() ? 0 : 1;
- setMergeCell(sheet, rows);
+ this.setMergeCell(sheet, rows);
+ //设置宽度
+ this.setColumnWidth(sheet, subIndex);
rows.subList(subIndex, rows.size()).stream().forEach(r -> writeSheetXML(r));
}
} else if (method.getName().equals("close")) {
@@ -39,8 +48,35 @@ public class Sheet1Handler implements InvocationHandler {
return method.invoke(target, args);
}
+ /**
+ * 设置列宽度
+ *
+ * @param sheet
+ * @param subIndex
+ */
+ private void setColumnWidth(Sheet sheet, int subIndex) {
+ if (subIndex == 0) {
+ StringBuilder content = new StringBuilder();
+ content.append("")
+ // 默认宽度
+ .append("");
+ // 自定义的宽度
+ sheet.getColumnHelperMap().entrySet().forEach(column ->
+ content.append(""));
+ content.append("");
+ target.append(content.toString());
+ }
+ }
+
/**
* 增加合并列内容
+ *
* @param sheet
*/
private void setMergeContent(Sheet sheet) {
@@ -49,10 +85,25 @@ public class Sheet1Handler implements InvocationHandler {
if (sheet.isAutoMergeCell() && !sheet.getMergeCells().isEmpty()) {
content.append("");
sheet.getMergeCells().stream().forEach(m -> {
- colCells.forEach(c -> {
- content.append("");
- });
+ if (CollectionUtils.isEmpty(colCells)) {
+ //增加合并行内容
+ Cell start = new Cell(m.getFirstRow(), m.getFirstCol());
+ Cell end = new Cell(m.getLastRow(), m.getLastCol());
+ content.append("");
+ } else {
+ colCells.forEach(c -> content
+ .append(""));
+ }
});
content.append("");
}
@@ -68,32 +119,32 @@ public class Sheet1Handler implements InvocationHandler {
private void setMergeCell(Sheet sheet, List rows) {
String oldValue = "";
- for(int i = 0; i < rows.size(); i++){
+ for (int i = 0; i < rows.size(); i++) {
Row row = rows.get(i);
- if(null == row){
+ if (null == row) {
continue;
}
List cells = row.getCells();
int mergeCellNumber = sheet.getMergeCellNumber();
- if(mergeCellNumber >= cells.size()){
+ if (mergeCellNumber >= cells.size()) {
//合并列超出范围,不进行合并
break;
}
Cell cell = cells.get(mergeCellNumber);
- if(StringUtils.isNotBlank(oldValue) && oldValue.equals(cell.getValue())){
+ if (StringUtils.isNotBlank(oldValue) && oldValue.equals(cell.getValue())) {
MergeCell mergeCell = null;
- if(!sheet.getMergeCells().isEmpty()){
+ if (!sheet.getMergeCells().isEmpty()) {
mergeCell = sheet.getMergeCells().getLast();
}
if (null == mergeCell) {
mergeCell = new MergeCell();
}
- int endRowNumber = mergeCell.getEndRowNumber();
+ int endRowNumber = mergeCell.getLastRow();
if (row.getRowNumber() == endRowNumber) {
//与上一个合并对象合并
- mergeCell.endRowNumber(++endRowNumber);
+ mergeCell.setLastRow(++endRowNumber);
} else {
- mergeCell = new MergeCell().startRowNumber(row.getRowNumber()).endRowNumber(row.getRowNumber() + 1);
+ mergeCell = new MergeCell().setFirstRow(row.getRowNumber()).setLastRow(row.getRowNumber() + 1);
sheet.getMergeCells().add(mergeCell);
}
}
@@ -106,10 +157,26 @@ public class Sheet1Handler implements InvocationHandler {
//customHeight=1 使用自定义高度
content.append("");
- row.getCells().forEach(c ->
- content.append("")
- .append("").append(c.getColDataNumber()).append("")
- );
+ CellStyle rowCellStyle = row.getCellStyle();
+ // 设置cellStyle样式下标
+ stylesIndex.addCellStyle(rowCellStyle);
+
+ for (Cell c : row.getCells()) {
+ CellStyle cellStyle = c.getCellStyle();
+ stylesIndex.addCellStyle(cellStyle);
+ if (Objects.isNull(cellStyle)) {
+ cellStyle = rowCellStyle;
+ }
+
+ content.append("")
+ .append("")
+ .append(c.getColDataNumber())
+ .append("");
+ }
content.append(" ");
target.append(content.toString());
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/flush/StylesHandler.java b/src/main/java/com/ibiz/excel/picture/support/flush/StylesHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..67aa0c9ac30990d622bff17b7ff586ae6d755c18
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/flush/StylesHandler.java
@@ -0,0 +1,142 @@
+package com.ibiz.excel.picture.support.flush;
+
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Font;
+import com.ibiz.excel.picture.support.model.Row;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.util.StringUtils;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 设置样式
+ *
+ * @author MinWeikai
+ * @date 2021/12/10 16:55
+ */
+public class StylesHandler implements InvocationHandler {
+ private IRepository target;
+
+ public StylesHandler(IRepository proxy) {
+ this.target = proxy;
+ }
+
+ /**
+ * 字体
+ */
+ private final StringBuilder fonts = new StringBuilder("" +
+ "");
+
+
+ /**
+ * 填充色
+ */
+ private final StringBuilder fills = new StringBuilder("" +
+ "" +
+ "");
+
+
+ /**
+ * 样式调用
+ */
+ private final StringBuilder cellXfs = new StringBuilder(("" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "").concat(
+ "").concat(
+ "").concat(
+ ""));
+
+ private final StringBuilder cellStyles = new StringBuilder("".concat(
+ ""));
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (method.getName().equals("write")) {
+ Sheet sheet = (Sheet) args[0];
+ List rows = sheet.getRows();
+ if (!rows.isEmpty()) {
+ rows.forEach(row -> {
+ addCellStyle(row.getCellStyle());
+ row.getCells().forEach(cell -> addCellStyle(cell.getCellStyle()));
+ });
+ }
+ }else if (method.getName().equals("close")) {
+ // 关闭时将所有的样式追加在Styles对象中
+ target.append(fonts.append(fills).append(cellXfs).append(cellStyles).toString());
+ }
+ return method.invoke(target, args);
+ }
+
+ private void addCellStyle(CellStyle cellStyle) {
+ if (cellStyle != null && !cellStyle.isExist()) {
+ // 追加字体
+ this.appendFont(cellStyle.getFont());
+ // 追加背景色样式
+ this.appendFill(cellStyle);
+ // 追加调用下标样式
+ this.appendXf(cellStyle);
+ }
+ }
+
+ /**
+ * 追加调用下标样式
+ *
+ * @param cellStyle
+ */
+ private void appendXf(CellStyle cellStyle) {
+ Font font = cellStyle.getFont();
+ cellXfs.append("")
+ .append(cellStyle.getAlignmentNullDefault().toXmlString())
+ .append("");
+
+ }
+
+ /**
+ * 追加背景色样式
+ *
+ * @param cellStyle
+ */
+ private void appendFill(CellStyle cellStyle) {
+ if(StringUtils.isNotBlank(cellStyle.getFgColorRgb())){
+ fills.append("");
+ }
+ }
+
+ /**
+ * 追加字体
+ * @param font
+ */
+ private void appendFont(Font font) {
+ if(font != null){
+ fonts.append("");
+ // 加粗标志
+ if(font.isBoldWeight()){
+ fonts.append("");
+ }
+ fonts.append("");
+ }
+ }
+
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/flush/StylesIndex.java b/src/main/java/com/ibiz/excel/picture/support/flush/StylesIndex.java
new file mode 100644
index 0000000000000000000000000000000000000000..86be2a6b6e0e60681b52ebb69a0b10758dcdd75e
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/flush/StylesIndex.java
@@ -0,0 +1,58 @@
+package com.ibiz.excel.picture.support.flush;
+
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Font;
+import com.ibiz.excel.picture.support.util.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 样式下标取值
+ *
+ * @author MinWeikai
+ * @date 2022/1/10 15:31
+ */
+public class StylesIndex {
+
+ private int fillId = 2;
+ private int s = 2;
+ private int fontId = 1;
+
+ private final Map styleIndexMap = new HashMap<>();
+
+ protected void addCellStyle(CellStyle cellStyle) {
+ if (cellStyle == null) {
+ return;
+ }
+
+ String styleKey = getStyleKey(cellStyle);
+ if (styleIndexMap.containsKey(styleKey)) {
+ CellStyle style = styleIndexMap.get(styleKey);
+ cellStyle.setS(style.getS());
+ cellStyle.setFillId(style.getFillId());
+ cellStyle.setExist(true);
+ return;
+ }
+
+ if (StringUtils.isNotBlank(cellStyle.getFgColorRgb())) {
+ cellStyle.setFillId(fillId);
+ fillId++;
+ }
+
+ cellStyle.setS(s);
+ styleIndexMap.put(styleKey, cellStyle);
+ s++;
+
+ Font font = cellStyle.getFont();
+ if (font != null) {
+ font.setFontId(fontId);
+ fontId++;
+ }
+ }
+
+ private String getStyleKey(CellStyle cellStyle) {
+ return cellStyle.toString();
+ }
+
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/BizExcelPojoInterface.java b/src/main/java/com/ibiz/excel/picture/support/model/BizExcelPojoInterface.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc9c5e241ce9336760988d81493fa1d967020a2d
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/BizExcelPojoInterface.java
@@ -0,0 +1,11 @@
+package com.ibiz.excel.picture.support.model;
+
+/**
+ * 动态导出pojo接口
+ * 目前在动态导出时需要实现该接口
+ *
+ * @author MinWeikai
+ * @date 2022/2/9 9:45
+ */
+public interface BizExcelPojoInterface {
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/BizExcelRel.java b/src/main/java/com/ibiz/excel/picture/support/model/BizExcelRel.java
new file mode 100644
index 0000000000000000000000000000000000000000..1baaabcaf78023816255abba6faf352c1db64652
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/BizExcelRel.java
@@ -0,0 +1,115 @@
+package com.ibiz.excel.picture.support.model;
+
+/**
+ * Excel导出配置
+ *
+ * @author MinWeikai
+ * @date 2022/2/8 14:45
+ */
+public class BizExcelRel {
+
+ public BizExcelRel() {
+ }
+
+ /**
+ * 创建标题,默认使用在列表中的添加顺序
+ * @param excelName
+ * @param field
+ */
+ public BizExcelRel(String excelName, String field) {
+ this.excelName = excelName;
+ this.field = field;
+ }
+
+ /**
+ * 创建标题,可自定义列的顺序
+ * @param excelName
+ * @param field
+ * @param orderNo
+ */
+ public BizExcelRel(String excelName, String field, int orderNo) {
+ this.excelName = excelName;
+ this.field = field;
+ this.orderNo = orderNo;
+ }
+
+ public BizExcelRel(String excelName, String field, int orderNo, boolean isPicture) {
+ this.excelName = excelName;
+ this.field = field;
+ this.orderNo = orderNo;
+ this.isPicture = isPicture;
+ }
+
+ public BizExcelRel(String excelName, String field, int orderNo, boolean isPicture, double cellWeight) {
+ this.excelName = excelName;
+ this.field = field;
+ this.orderNo = orderNo;
+ this.isPicture = isPicture;
+ this.cellWeight = cellWeight;
+ }
+
+ /**
+ * excel显示的字段名称
+ */
+ private String excelName;
+
+ /**
+ * 字段
+ */
+ private String field;
+
+ /**
+ * 排序
+ */
+ private int orderNo = 0;
+
+ /**
+ * 是否是图片
+ */
+ private boolean isPicture = false;
+
+ /**
+ * 单元格宽度
+ */
+ private double cellWeight = -1;
+
+ public boolean isPicture() {
+ return isPicture;
+ }
+
+ public void setPicture(boolean picture) {
+ isPicture = picture;
+ }
+
+ public String getExcelName() {
+ return excelName;
+ }
+
+ public void setExcelName(String excelName) {
+ this.excelName = excelName;
+ }
+
+ public String getField() {
+ return field;
+ }
+
+ public void setField(String field) {
+ this.field = field;
+ }
+
+ public int getOrderNo() {
+ return orderNo;
+ }
+
+ public void setOrderNo(int orderNo) {
+ this.orderNo = orderNo;
+ }
+
+ public double getCellWeight() {
+ return cellWeight;
+ }
+
+ public void setCellWeight(double cellWeight) {
+ this.cellWeight = cellWeight;
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/Cell.java b/src/main/java/com/ibiz/excel/picture/support/model/Cell.java
index 170b87999c2223335a518b20d09a02fbcc5edf8b..eb4afcefad022e28fc7535cb37f6bf6a66e469c9 100644
--- a/src/main/java/com/ibiz/excel/picture/support/model/Cell.java
+++ b/src/main/java/com/ibiz/excel/picture/support/model/Cell.java
@@ -5,13 +5,51 @@ package com.ibiz.excel.picture.support.model;
* @date 2020/7/217:31
*/
public class Cell {
- private final String[] CELL_NUMBER_LINE = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
private int cellNumber;//第几列
private int rowNumber;//行号
private String colNumber = "";//列号 例 A1 B1
private String col = ""; //单元格列 例 A B AA AB
private int colDataNumber; //列对应值序号
- private String value; //单元格值
+ private String value; //单元格值
+
+ /**
+ * 该单元格样式
+ */
+ private CellStyle cellStyle;
+
+ public Cell(int cellNumber) {
+ this.cellNumber = cellNumber;
+ }
+
+ public Cell(int rowNumber, int cellNumber) {
+ super();
+ this.rowNumber = rowNumber;
+ this.cellNumber = cellNumber;
+ this.autoSetCell(rowNumber, cellNumber);
+ }
+
+ public Cell(int cellNumber, String value) {
+ this.cellNumber = cellNumber;
+ this.value = value;
+ }
+
+ /**
+ * 自动设置Cell顺序
+ *
+ * @param rowNumber
+ * @param cellNumber
+ */
+ public void autoSetCell(int rowNumber, int cellNumber) {
+ StringBuilder colName = new StringBuilder();
+ int mod;
+ while (cellNumber > 0) {
+ mod = (cellNumber - 1) % 26;
+ colName.insert(0, (char) ('A' + mod));
+ cellNumber = (cellNumber - 1) / 26;
+ }
+ colNumber = colName.toString();
+ col += colNumber + (rowNumber + 1);
+ }
public String getColNumber() {
return colNumber;
@@ -25,21 +63,22 @@ public class Cell {
this.colDataNumber = colDataNumber;
}
- public int getRowNumber() {
+ public Integer getRowNumber() {
return rowNumber;
}
- public Cell(int rowNumber,int cellNumber) {
- super();
+ public void setRowNumber(int rowNumber) {
this.rowNumber = rowNumber;
- this.cellNumber = cellNumber;
- int line = cellNumber;
- if(cellNumber >= CELL_NUMBER_LINE.length){
- line = cellNumber - CELL_NUMBER_LINE.length;
- colNumber += "A";
- }
- col += colNumber + CELL_NUMBER_LINE[line];
- colNumber += CELL_NUMBER_LINE[line] + (rowNumber + 1);
+ }
+
+ /**
+ * 设置RowNumber并自动排序
+ *
+ * @param rowNumber
+ */
+ public void autoSetRowNumber(int rowNumber) {
+ this.rowNumber = rowNumber;
+ this.autoSetCell(rowNumber, this.cellNumber);
}
public String getCol() {
@@ -50,12 +89,9 @@ public class Cell {
return value;
}
- public void setValue(String value) {
+ public Cell setValue(String value) {
this.value = value;
- }
-
- public Cell(int cellNumber) {
- this(0,cellNumber);
+ return this;
}
public int getCellNumber() {
@@ -65,4 +101,19 @@ public class Cell {
public void setCellNumber(int cellNumber) {
this.cellNumber = cellNumber;
}
+
+ /**
+ * 设置该单元格样式
+ *
+ * @param cellStyle
+ * @return
+ */
+ public Cell setCellStyle(CellStyle cellStyle) {
+ this.cellStyle = cellStyle;
+ return this;
+ }
+
+ public CellStyle getCellStyle() {
+ return cellStyle;
+ }
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/CellStyle.java b/src/main/java/com/ibiz/excel/picture/support/model/CellStyle.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b03c6288550b311b7245db31593a66281961c5b
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/CellStyle.java
@@ -0,0 +1,233 @@
+package com.ibiz.excel.picture.support.model;
+
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.style.Alignment;
+
+import java.util.Optional;
+
+/**
+ * 控制该行样式
+ *
+ * @author MinWeikai
+ * @date 2021/1/19 14:04
+ */
+public class CellStyle {
+
+ public static CellStyle build() {
+ return new CellStyle();
+ }
+
+ /**
+ * 默认已有fill样式
+ * 与对应{@link com.ibiz.excel.picture.support.module.Styles}
+ */
+ private int fillId = 0;
+
+ /**
+ * 默认已有cellStyles样式
+ */
+ private int s = WorkbookConstant.S;
+
+ /**
+ * 存在
+ */
+ private boolean exist = false;
+
+
+ /**
+ * 行号
+ */
+ private Integer rowNumber;
+
+ /**
+ * 是否持续向下该列样式
+ */
+ private boolean colLast;
+
+ /**
+ * 列号
+ */
+ private Integer colNumber;
+
+ /**
+ * fgColor rgb颜色
+ * RGB网页颜色在线取色器 https://link.fobshanghai.com/rgbcolor.htm
+ */
+ private String fgColorRgb;
+
+ /**
+ * 字体
+ */
+ private Font font;
+
+ /**
+ * 边框加粗,默认为1加粗,0不加粗
+ */
+ private Integer borderBold;
+
+ /**
+ * 设置内容对齐方式
+ */
+ private Alignment alignment;
+
+ public CellStyle() {
+ }
+
+ public Font getFont() {
+ return font;
+ }
+
+ public CellStyle setFont(Font font) {
+ this.font = font;
+ return this;
+ }
+
+ /**
+ * 创建单元格前景色
+ *
+ * @param fgColorRgb
+ */
+ public CellStyle(String fgColorRgb) {
+ this.fgColorRgb = fgColorRgb;
+ }
+
+ /**
+ * 根据行号设置颜色
+ *
+ * @param rowNumber
+ * @param fgColorRgb RGB网页颜色在线取色器 https://link.fobshanghai.com/rgbcolor.htm
+ */
+ public CellStyle(Integer rowNumber, String fgColorRgb) {
+ this(rowNumber, null, fgColorRgb, null);
+ }
+
+ public CellStyle(Integer rowNumber, String fgColorRgb, Boolean borderBold) {
+ this(rowNumber, null, fgColorRgb, borderBold);
+ }
+
+ public CellStyle(Integer rowNumber, Integer colNumber, String fgColorRgb) {
+ this(rowNumber, colNumber, fgColorRgb, null);
+ }
+
+ public CellStyle(Integer rowNumber, Integer colNumber, String fgColorRgb, Boolean borderBold) {
+ this.rowNumber = rowNumber;
+ this.colNumber = colNumber;
+ this.fgColorRgb = fgColorRgb;
+ this.setBorderBold(borderBold);
+ }
+
+ public String getFgColorRgb() {
+ return fgColorRgb;
+ }
+
+ /**
+ * fgColor rgb颜色
+ * RGB网页颜色在线取色器 https://link.fobshanghai.com/rgbcolor.htm
+ *
+ * @return
+ */
+ public CellStyle setFgColorRgb(String fgColorRgb) {
+ this.fgColorRgb = fgColorRgb;
+ return this;
+ }
+
+ public Integer getRowNumber() {
+ return rowNumber;
+ }
+
+ public CellStyle setRowNumber(Integer rowNumber) {
+ this.rowNumber = rowNumber;
+ return this;
+ }
+
+ public int getFillId() {
+ return fillId;
+ }
+
+ public void setFillId(int fillId) {
+ this.fillId = fillId;
+ }
+
+ public int getS() {
+ return s;
+ }
+
+ public void setS(int s) {
+ this.s = s;
+ }
+
+ public Integer getColNumber() {
+ return colNumber;
+ }
+
+ public CellStyle setColNumber(Integer colNumber) {
+ this.colNumber = colNumber;
+ return this;
+ }
+
+ public Integer getBorderBold() {
+ return this.borderBold;
+ }
+
+ /**
+ * 设置边框是否加粗
+ *
+ * @param borderBold
+ * @return
+ */
+ public CellStyle setBorderBold(Boolean borderBold) {
+ this.borderBold = borderBold != null ? (borderBold ? 1 : 0) : null;
+ return this;
+ }
+
+ public boolean isColLast() {
+ return colLast;
+ }
+
+ /**
+ * 是否持续向下该列样式
+ * @param colLast
+ * @return
+ */
+ public CellStyle setColLast(boolean colLast) {
+ this.colLast = colLast;
+ return this;
+ }
+
+ public Alignment getAlignment() {
+ return alignment;
+ }
+
+ public Alignment getAlignmentNullDefault() {
+ return Optional.ofNullable(getAlignment()).orElse(new Alignment());
+ }
+
+ /**
+ * 设置内容对齐方式
+ * @param alignment
+ * @return
+ */
+ public CellStyle setAlignment(Alignment alignment) {
+ this.alignment = alignment;
+ return this;
+ }
+
+ public boolean isExist() {
+ return exist;
+ }
+
+ public void setExist(boolean exist) {
+ this.exist = exist;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("CellStyle{");
+ sb.append("fgColorRgb='").append(fgColorRgb).append('\'');
+ sb.append(", font=").append(font);
+ sb.append(", borderBold=").append(borderBold);
+ sb.append(", alignment=").append(alignment);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/ColumnHelper.java b/src/main/java/com/ibiz/excel/picture/support/model/ColumnHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..faec35d452ffb898b1719ed1da0096ae0efd1c5c
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/ColumnHelper.java
@@ -0,0 +1,51 @@
+package com.ibiz.excel.picture.support.model;
+
+/**
+ * 单元格辅助功能类
+ *
+ * @author MinWeikai
+ * @date 2021/1/19 15:41
+ */
+public class ColumnHelper {
+
+ /**
+ * 单元格列号, 1表示A列
+ */
+ private int columnIndex;
+
+ /**
+ * 单元格宽度, 默认10
+ */
+ private double width = 10;
+
+ /**
+ * 设置第几列单元格宽度
+ *
+ * @param columnIndex 第几列单元格
+ * @param width 宽度
+ */
+ public ColumnHelper(int columnIndex, double width) {
+ this.columnIndex = columnIndex;
+ this.width = width;
+ }
+
+ /**
+ * 设置第几列单元格宽度
+ * @param columnIndex 第几列单元格,默认宽度{@code width}
+ */
+ public ColumnHelper(int columnIndex) {
+ this.columnIndex = columnIndex;
+ }
+
+ public int getColumnIndex() {
+ return columnIndex;
+ }
+
+ public double getWidth() {
+ return width;
+ }
+
+ public void setWidth(double width) {
+ this.width = width;
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/Font.java b/src/main/java/com/ibiz/excel/picture/support/model/Font.java
new file mode 100644
index 0000000000000000000000000000000000000000..14849011ee9a0589993dcafa448e09cd05116861
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/Font.java
@@ -0,0 +1,96 @@
+package com.ibiz.excel.picture.support.model;
+
+/**
+ * 字体
+ *
+ * @author MinWeikai
+ * @date 2022/1/27 11:47
+ */
+public class Font{
+
+ /**
+ * 字体id
+ */
+ private int fontId = 0;
+
+ /**
+ * 设置字体的名称
+ */
+ private String fontName = "宋体";
+
+ /**
+ * 是否加粗,默认不加粗
+ */
+ private boolean boldWeight = false;
+
+ /**
+ * 字体颜色
+ */
+ private String color;
+
+ /**
+ * 字体大小
+ */
+ private short fontHeightInPoints = 11;
+
+ public static Font build() {
+ return new Font();
+ }
+
+ public String getFontName() {
+ return fontName;
+ }
+
+ public Font setFontName(String fontName) {
+ this.fontName = fontName;
+ return this;
+ }
+
+ public boolean isBoldWeight() {
+ return boldWeight;
+ }
+
+ public Font setBoldWeight(boolean boldWeight) {
+ this.boldWeight = boldWeight;
+ return this;
+ }
+
+ public String getColor() {
+ return color;
+ }
+
+ public Font setColor(String color) {
+ this.color = color;
+ return this;
+ }
+
+ public short getFontHeightInPoints() {
+ return fontHeightInPoints;
+ }
+
+ public Font setFontHeightInPoints(short fontHeightInPoints) {
+ this.fontHeightInPoints = fontHeightInPoints;
+ return this;
+ }
+
+ public int getFontId() {
+ return fontId;
+ }
+
+ public void setFontId(int fontId) {
+ this.fontId = fontId;
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("Font{");
+ sb.append("fontId=").append(fontId);
+ sb.append(", fontName='").append(fontName).append('\'');
+ sb.append(", boldWeight=").append(boldWeight);
+ sb.append(", color='").append(color).append('\'');
+ sb.append(", fontHeightInPoints=").append(fontHeightInPoints);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/MergeCell.java b/src/main/java/com/ibiz/excel/picture/support/model/MergeCell.java
index f41b7eb29c0e111fbb99ddbb1729c40662a5ff37..9a514d9442c4be41d32c3ef04189d112a0a0c325 100644
--- a/src/main/java/com/ibiz/excel/picture/support/model/MergeCell.java
+++ b/src/main/java/com/ibiz/excel/picture/support/model/MergeCell.java
@@ -1,29 +1,71 @@
package com.ibiz.excel.picture.support.model;
/**
- * @auther 喻场
- * @date 2020/7/217:36
+ * 合并单元格
+ *
+ * @author MinWeikai
+ * @date 2021-01-19 09:18:15
*/
public class MergeCell {
- private int startRowNumber; //合并单元格起始行
- private int endRowNumber; //合并单元格结束行
- public MergeCell startRowNumber(int startRowNumber) {
- this.startRowNumber = startRowNumber;
+ private int firstRow;
+ private int firstCol;
+ private int lastRow;
+ private int lastCol;
+
+ public MergeCell() {
+ }
+
+ /**
+ * 构造此合并单元格对象可以进行合并
+ * 下标,从0开始
+ *
+ * @param firstRow
+ * @param firstCol
+ * @param lastRow
+ * @param lastCol
+ */
+ public MergeCell(int firstRow, int firstCol, int lastRow, int lastCol) {
+ this.firstRow = firstRow;
+ this.firstCol = firstCol;
+ this.lastRow = lastRow;
+ this.lastCol = lastCol;
+ }
+
+ public int getFirstRow() {
+ return firstRow;
+ }
+
+ public MergeCell setFirstRow(int firstRow) {
+ this.firstRow = firstRow;
return this;
}
- public MergeCell endRowNumber(int endRowNumber) {
- this.endRowNumber = endRowNumber;
+ public int getFirstCol() {
+ return firstCol + 1;
+ }
+
+ public MergeCell setFirstCol(int firstCol) {
+ this.firstCol = firstCol;
return this;
}
- public int getStartRowNumber() {
- return startRowNumber;
+ public int getLastRow() {
+ return lastRow;
+ }
+
+ public MergeCell setLastRow(int lastRow) {
+ this.lastRow = lastRow;
+ return this;
}
- public int getEndRowNumber() {
- return endRowNumber;
+ public int getLastCol() {
+ return lastCol + 1;
+ }
+
+ public MergeCell setLastCol(int lastCol) {
+ this.lastCol = lastCol;
+ return this;
}
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/Picture.java b/src/main/java/com/ibiz/excel/picture/support/model/Picture.java
index d5e359cfdb9c0b7c3f2f96fda6df2402b08ec0d8..3af76f65bb34391e6b60d877987fb667b5420d1f 100644
--- a/src/main/java/com/ibiz/excel/picture/support/model/Picture.java
+++ b/src/main/java/com/ibiz/excel/picture/support/model/Picture.java
@@ -1,5 +1,11 @@
package com.ibiz.excel.picture.support.model;
+import com.ibiz.excel.picture.support.constants.PictureSourceContent;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.util.StringUtils;
+
+import java.util.Objects;
+
/**
* @auther 喻场
* @date 2020/7/217:35
@@ -10,8 +16,25 @@ public class Picture {
private int fromRow; //图片起始行 Row.rowNumber
private int toCol; //图片结束列 Cell.cellNumber + 1
private int toRow; //图片结束行 Row.rowNumber
- /**当前系统中图片的绝对路径*/
+ /**当前系统中图片的绝对路径 或 url地址*/
private String picturePath; //图片路径
+
+ /**
+ * 图片来源
+ * {@link com.ibiz.excel.picture.support.constants.PictureSourceContent}
+ */
+ private int pictureSource;
+
+ /**
+ * 图片宽度
+ */
+ private int width = WorkbookConstant.PICTURE_WEIGHT;
+
+ /**
+ * 图片高度
+ */
+ private int height = WorkbookConstant.PICTURE_HEIGHT;
+
public Picture(){
}
@@ -24,6 +47,59 @@ public class Picture {
this.picturePath = picturePath;
}
+ public Picture(int fromRow,int fromCol, int width, String picturePath) {
+ super();
+ this.fromRow = fromRow;
+ this.fromCol = fromCol;
+ this.toRow = fromRow;
+ this.toCol = fromCol;
+ this.picturePath = picturePath;
+ this.width = width;
+ }
+
+ public Picture(int fromRow,int fromCol, int width, int height,String picturePath) {
+ super();
+ this.fromRow = fromRow;
+ this.fromCol = fromCol;
+ this.toRow = fromRow;
+ this.toCol = fromCol;
+ this.picturePath = picturePath;
+ this.width = width;
+ this.height = height;
+ }
+
+ public Picture(int fromRow,int fromCol, int width, int height,String picturePath, int pictureSource) {
+ super();
+ this.fromRow = fromRow;
+ this.fromCol = fromCol;
+ this.toRow = fromRow;
+ this.toCol = fromCol;
+ this.picturePath = picturePath;
+ this.width = width;
+ this.height = height;
+ this.pictureSource = pictureSource;
+ }
+
+ /**
+ * 自动设置图片来源
+ * @return
+ */
+ public Picture autoPictureSourceByPath(){
+ // 来源为0,自动匹配
+ try {
+ if(this.pictureSource == 0
+ // 图片路径不为空
+ && StringUtils.isNotBlank(this.picturePath)
+ // 是url
+ && Objects.equals(this.picturePath.substring(0, 4),"http")){
+ this.pictureSource = PictureSourceContent.WEB_URL;
+ }
+ }catch (Exception e){
+ throw new RuntimeException("错误的图片地址: " + this.picturePath, e);
+ }
+ return this;
+ }
+
public String getPicturePath() {
return picturePath;
}
@@ -72,4 +148,27 @@ public class Picture {
this.rembed = rembed;
}
+ public int getWidth() {
+ return width;
+ }
+
+ public Picture setWidth(int width) {
+ return this;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+ public void setHeight(int height) {
+ this.height = height;
+ }
+
+ public int getPictureSource() {
+ return pictureSource;
+ }
+
+ public void setPictureSource(int pictureSource) {
+ this.pictureSource = pictureSource;
+ }
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/Row.java b/src/main/java/com/ibiz/excel/picture/support/model/Row.java
index f97ef6a1f30079d73b8cc64978cb51e9e82ccc1d..d52295198f9542624c39d6b816f018d857dfc46a 100644
--- a/src/main/java/com/ibiz/excel/picture/support/model/Row.java
+++ b/src/main/java/com/ibiz/excel/picture/support/model/Row.java
@@ -8,29 +8,45 @@ import java.util.List;
* @date 2020/7/217:33
*/
public class Row {
- private int rowNumber; //行号
+ private int rowNumber; //行号
private int autoHeight = 30; //默认行高
/**
* 默认列头为30
* setHeight后使用设置的值,必须大于0
*/
- private int height; //列高
+ private int height; //列高
private List cells = new ArrayList<>();
- public Row(){
+
+ /**
+ * 该行样式
+ */
+ private CellStyle cellStyle;
+
+ public Row() {
this(1);
}
- public Row(int rowNumber){
+
+ public Row(int rowNumber) {
this.rowNumber = rowNumber;
}
+
public int getHeight() {
return height <= 0 ? autoHeight : height;
}
+
+ /**
+ * 设置行高
+ *
+ * @param height
+ */
public void setHeight(int height) {
this.height = height;
}
+
public int getRowNumber() {
return rowNumber;
}
+
public void setRowNumber(int rowNumber) {
this.rowNumber = rowNumber;
}
@@ -43,13 +59,61 @@ public class Row {
this.cells = cells;
}
- public Cell createCell(int cellNumber){
- Cell cell = new Cell(rowNumber,cellNumber);
+ /**
+ * 自动配置行对应的单元格
+ *
+ * @param cells
+ */
+ public void autoRowCells(List cells) {
+ cells.parallelStream().forEach(cell -> cell.autoSetRowNumber(rowNumber));
+ this.cells = cells;
+ }
+
+ public Cell createCell(int cellNumber) {
+ Cell cell = new Cell(rowNumber, cellNumber);
cells.add(cell);
return cell;
}
- public void clear(){
+ public void clear() {
this.cells.clear();
}
+
+ public CellStyle getCellStyle() {
+ return cellStyle;
+ }
+
+ /**
+ * 设置行样式
+ *
+ * @param cellStyle
+ * @return
+ */
+ public Row setCellStyle(CellStyle cellStyle) {
+ this.cellStyle = cellStyle;
+ return this;
+ }
+
+ /**
+ * 添加行中单元格元素
+ *
+ * @param cell
+ * @return
+ */
+ public Row addCell(Cell cell) {
+ List cells = new ArrayList<>();
+ cells.add(cell);
+ autoRowCells(cells);
+ return this;
+ }
+
+ /**
+ * 获取单元格
+ *
+ * @param num 单元格号
+ * @return
+ */
+ public Cell getCell(int num) {
+ return this.getCells().get(num);
+ }
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/Sheet.java b/src/main/java/com/ibiz/excel/picture/support/model/Sheet.java
index 74a247cbdc152a3fe665461d1fff3df0748a979e..2036f82eb8e28f81700535ac6fb783bcb046b4d3 100644
--- a/src/main/java/com/ibiz/excel/picture/support/model/Sheet.java
+++ b/src/main/java/com/ibiz/excel/picture/support/model/Sheet.java
@@ -1,30 +1,34 @@
package com.ibiz.excel.picture.support.model;
-import com.ibiz.excel.picture.support.constants.WorkbookConstant;
-import com.ibiz.excel.picture.support.event.CloseEvent;
-import com.ibiz.excel.picture.support.event.InitEvent;
-import com.ibiz.excel.picture.support.factory.EventFactory;
-import com.ibiz.excel.picture.support.listener.CloseListener;
-import com.ibiz.excel.picture.support.listener.FlushListener;
+import cn.hutool.core.collection.CollectionUtil;
import com.ibiz.excel.picture.support.SheetContext;
import com.ibiz.excel.picture.support.annotation.ExportModel;
import com.ibiz.excel.picture.support.constants.Alias;
+import com.ibiz.excel.picture.support.event.CloseEvent;
import com.ibiz.excel.picture.support.event.FlushEvent;
+import com.ibiz.excel.picture.support.event.InitEvent;
+import com.ibiz.excel.picture.support.factory.EventFactory;
import com.ibiz.excel.picture.support.factory.ListenerFactory;
+import com.ibiz.excel.picture.support.listener.CloseListener;
import com.ibiz.excel.picture.support.listener.ContentListener;
+import com.ibiz.excel.picture.support.listener.FlushListener;
import com.ibiz.excel.picture.support.listener.InitListener;
-import com.ibiz.excel.picture.support.util.StringUtils;
+import com.ibiz.excel.picture.support.processor.PictureProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+
import java.util.*;
/**
* 工作表
+ *
* @auther 喻场
* @date 2020/7/217:36
*/
public class Sheet {
private Logger logger = LoggerFactory.getLogger(this.getClass());
+
//sheet上下文
//包括组件文件流,文件模版,
private void init() {
@@ -35,13 +39,14 @@ public class Sheet {
private int flushSize;
private Workbook workbook;
private String sheetName; //默认sheet1
- private int drawingSequence = 1; //图片id序号 对应drawing1.xml.rels Id后的数字
- private int sharedStringSequence = -1; //单元格值序号 sharedString.xml对应标签序号
- private boolean autoMergeCell = Boolean.FALSE; //是否自动合并单元格
+ private int drawingSequence = 1; //图片id序号 对应drawing1.xml.rels Id后的数字
+ private int sharedStringSequence = -1; //单元格值序号 sharedString.xml对应标签序号
+ private boolean autoMergeCell = Boolean.TRUE; //是否自动合并单元格
private boolean hasFlush; //是否已经执行过flush
private boolean hasWriteHead; //是否已经写标题
private final List closeAlias = Arrays.asList(Alias.APP, Alias.WORKBOOK_XML);
private final SheetHandler SHEET_HANDLER = new SheetHandler();
+
private Sheet(int flushSize, String sheetName, Workbook workbook) {
this.flushSize = flushSize;
this.sheetName = sheetName;
@@ -50,19 +55,37 @@ public class Sheet {
}
private int writeRow = -1;
- /**行*/
+ /**
+ * 行
+ */
private List rows = new ArrayList<>();
//图片
private List pictures = new ArrayList<>();
- /**需要合并单元格*/
+ /**
+ * 需要合并单元格
+ */
private LinkedList mergeCells = new LinkedList<>();
- /**已这列值为标准,对colCells进行合并
- * 0代表A0列 */
- private int mergeCellNumber = 0; //根据第几列值合并
- /**需要合并单元格的列
- * 对应excel column {"A"} A列行相同的值要合并*/
+ /**
+ * 已这列值为标准,对colCells进行合并
+ * 0代表A0列
+ */
+ private int mergeCellNumber = 0; //根据第几列值合并
+ /**
+ * 需要合并单元格的列
+ * 对应excel column {"A"} A列行相同的值要合并
+ */
private Set colCells = new HashSet<>();
+ /**
+ * 单元格辅助类
+ */
+ private Map columnHelperMap = new HashMap<>();
+
+ /**
+ * 预设样式
+ */
+ private final Map cellStyleMap = new HashMap<>();
+
public List getPictures() {
return pictures;
}
@@ -81,7 +104,8 @@ public class Sheet {
/**
* 创建行,单元格会根据t的属性自动填充
- * @param t 列属性 只会读取com.ibiz.excelx.annotation.Model 注解的属性
+ *
+ * @param t 列属性 只会读取{@link ExportModel} 注解的属性
* @param
* @return Row
*/
@@ -89,10 +113,48 @@ public class Sheet {
return SHEET_HANDLER.createRow(t);
}
+ /**
+ * 创建集合行数据,单元格会根据t的属性自动填充
+ * 需要调用{@link Sheet#write(Class)}写入excel信息
+ * 否则 collections为空时,excel中没u有标题
+ * 写法如: sheet.write(UserPicture.class).createRow(list);
+ * @param collections 集合列属性 只会读取{@link ExportModel} 注解的属性
+ * @return
+ */
+ public Sheet createRow(Collection> collections) {
+ if(!CollectionUtils.isEmpty(collections)){
+ collections.forEach(this::createRow);
+ }
+ return this;
+ }
+
public Row createRow(int rowNumber) {
return SHEET_HANDLER.createRow(rowNumber);
}
+ /**
+ * 开始行号
+ *
+ * @param startRowNumber 表示从第几行开始写入数据
+ * @return
+ */
+ public Sheet startRow(int startRowNumber) {
+ writeRow = --startRowNumber;
+ return this;
+ }
+
+ /**
+ * 构建并写入excel信息
+ *
+ * @param
+ * @param head 标题
+ * @return
+ */
+ public Sheet write(Class head) {
+ SHEET_HANDLER.write(head);
+ return this;
+ }
+
/**
* 刷新数据到流
*/
@@ -115,7 +177,7 @@ public class Sheet {
}
//保证rowList中有一行数据,用作下一行与上一行对比是否合并单元格
- public void clear(){
+ public void clear() {
SHEET_HANDLER.clear();
}
@@ -130,6 +192,7 @@ public class Sheet {
public static Sheet getInstance(int flushSize, String sheetName, Workbook workbook) {
return new Sheet(flushSize, sheetName, workbook);
}
+
public boolean isAutoMergeCell() {
return autoMergeCell;
}
@@ -170,6 +233,15 @@ public class Sheet {
return rows;
}
+ /**
+ * 根据行号,获取行对象,默认从0开始
+ * @param num
+ * @return
+ */
+ public Row getRow(int num) {
+ return this.getRows().get(num);
+ }
+
public int getDrawingSequence() {
return drawingSequence;
}
@@ -177,11 +249,18 @@ public class Sheet {
public void setDrawingSequence(int drawingSequence) {
this.drawingSequence = drawingSequence;
}
- /**总行数*/
+
+ /**
+ * 总行数
+ */
public int getRowCount() {
return writeRow + 1;
}
+ public int getFlushSize() {
+ return flushSize;
+ }
+
class SheetHandler {
void init() {
sheetContext = SheetContext.getInstance(Sheet.this);
@@ -202,9 +281,10 @@ public class Sheet {
//创建组件文件
sheetContext.getEvents().stream().filter(e -> e instanceof InitEvent).forEach(e -> e.onEvent(Sheet.this));
}
+
Row create(T t, final boolean isHead) {
Row row = createRow(++writeRow);
- logger.info("create the " + writeRow + " row");
+ logger.info("create the " + writeRow + " row");
Arrays.stream(t.getClass().getDeclaredFields()).filter(f -> null != f.getAnnotation(ExportModel.class))
.sorted(Comparator.comparing(c -> c.getAnnotation(ExportModel.class).sort())).forEach(f -> {
f.setAccessible(true);
@@ -215,57 +295,78 @@ public class Sheet {
boolean merge = model.merge();
String title = model.title();
Cell cell = new Cell(row.getRowNumber(), sort);
+ // 合并 是标题 并且 是要合并的基准列,将元素放在基准列中
if (isHead && mergeMaster) {
mergeCellNumber = sort;
autoMergeCell = true;
colCells.add(cell.getCol());
}
+ // 合并 是标题 并且 是要合并的列
if (isHead && merge) {
colCells.add(cell.getCol());
}
- String value = null;
+
+ Object value = null;
try {
- value = null == f.get(t) ? "" : "" + f.get(t);
+ value = f.get(t);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
+ // 是标题,则将title设置为单元格的值
if (isHead) {
cell.setValue(title);
} else {
- cell.setValue(value);
- }
- if (!isHead && isPicture && StringUtils.isNotBlank(value)) {
- //有图片的行,行高设置为100
- row.setHeight(WorkbookConstant.PICTURE_ROW_HEIGHT);
- //增加图片
- pictures.add(new Picture(row.getRowNumber(), cell.getCellNumber(), value));
- }
- if (isHead || !isPicture) {
- row.getCells().add(cell);
+ // 不是标题 并且 是图片 并且 值不为空
+ if (isPicture && value != null) {
+ // 添加图片
+ PictureProcessor.build(Sheet.this).addPictures(row, cell.getCellNumber(), value, model);
+ } else {
+ cell.setValue(value == null ? "" : String.valueOf(value));
+ }
}
+
+ // 将组装好的元素项,放到该行的元素项集合中
+ row.getCells().add(cell);
});
hasWriteHead = writeRow > -1;
return row;
}
+
Row createRow(T t) {
if (!hasWriteHead) {
- create(t, true);
+ createRowAndCellStyle(t, true);
+ }
+ return createRowAndCellStyle(t, false);
+ }
+
+ private Row createRowAndCellStyle(T t, final boolean isHead) {
+ // 创建行数据
+ Row row = create(t, isHead);
+ // 最小单元配置优先,所以优先取Row中设置的样式
+ if(Objects.isNull(row.getCellStyle())){
+ // 获取样式
+ CellStyle cellStyle = cellStyleMap.get(row.getRowNumber());
+ if(cellStyle != null){
+ row.setCellStyle(cellStyle);
+ }
}
- return create(t, false);
+ return row;
}
+
Row createRow(int rowNumber) {
writeRow = rowNumber;
- if(rows.size() > flushSize){
+ if (rows.size() > flushSize && flushSize != -1) {
flush();
}
Row row = new Row(rowNumber);
rows.add(row);
return row;
}
- void clear(){
+
+ void clear() {
Row row = null;
- if(rows.size()>1){
- row = rows.get(rows.size()-1);
+ if (rows.size() > 1) {
+ row = rows.get(rows.size() - 1);
}
List list = new ArrayList<>();
list.add(row);
@@ -273,5 +374,96 @@ public class Sheet {
rows.addAll(list);
pictures.clear();
}
+
+ /**
+ * 构建并写入excel信息
+ *
+ * @param head 标题类
+ * @param
+ */
+ public void write(Class head) {
+ try {
+ createRowAndCellStyle(head.newInstance() , true);
+ } catch (InstantiationException | IllegalAccessException e) {
+ throw new RuntimeException("写入标题异常", e);
+ }
+ }
+
+ }
+
+ /**
+ * 设置单元格宽度
+ *
+ * @param columnIndex 坐标
+ * @param width 宽度
+ */
+ public Sheet setColumnWidth(int columnIndex, double width) {
+ // 判断 columnHelperMap 不包含 columnIndex
+ if(!this.columnHelperMap.containsKey(columnIndex)){
+ this.columnHelperMap.put(columnIndex, new ColumnHelper(columnIndex, width));
+ }else {
+ // 存在时,则取出来
+ ColumnHelper columnHelper = this.columnHelperMap.get(columnIndex);
+ // 比较新的宽度和存在的宽度,将最大的宽度设置进去
+ if(width > columnHelper.getWidth()){
+ columnHelper.setWidth(width);
+ }
+ }
+ return this;
+ }
+
+ public Map getColumnHelperMap() {
+ return columnHelperMap;
+ }
+
+ /**
+ * 批量添加样式
+ *
+ * @param cellStyles
+ */
+ public void addCellStyle(List cellStyles) {
+ cellStyles.forEach(cellStyle-> this.cellStyleMap.put(cellStyle.getRowNumber(), cellStyle));
+ }
+
+ /**
+ * 添加样式
+ * @param cellStyle
+ * @return
+ */
+ public Sheet addCellStyle(CellStyle cellStyle) {
+ this.cellStyleMap.put(cellStyle.getRowNumber(), cellStyle);
+ return this;
+ }
+
+ /**
+ * 添加元素的合并
+ * 必须放在对元素赋值之后
+ *
+ * @param mergeCell
+ */
+ public void addMergeCell(MergeCell mergeCell) {
+ // 对合并的单元格添加空元素
+ addFillSpace(mergeCell);
+ this.getMergeCells().add(mergeCell);
+ }
+
+ /**
+ * 对合并的单元个添加填充占位
+ *
+ * @param mergeCell
+ */
+ private void addFillSpace(MergeCell mergeCell) {
+ List cells = new ArrayList<>();
+ for (int i = mergeCell.getFirstRow(); i < mergeCell.getLastRow() + 1; i++) {
+ for (int j = mergeCell.getFirstCol() + 1; j < mergeCell.getLastCol() + 1; j++) {
+ cells.add(new Cell(j, ""));
+ }
+ if(CollectionUtil.isNotEmpty(this.rows)){
+ List rowCell = this.getRow(i).getCells();
+ rowCell.addAll(cells);
+ this.getRow(i).autoRowCells(rowCell);
+ }
+
+ }
}
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/Workbook.java b/src/main/java/com/ibiz/excel/picture/support/model/Workbook.java
index d978c1d2839a70b133d8b47d8fd2ab11d22aee5e..7329a166630f988acdaaead862a0e4c4b093f333 100644
--- a/src/main/java/com/ibiz/excel/picture/support/model/Workbook.java
+++ b/src/main/java/com/ibiz/excel/picture/support/model/Workbook.java
@@ -1,12 +1,13 @@
package com.ibiz.excel.picture.support.model;
+import cn.hutool.core.util.ZipUtil;
import com.ibiz.excel.picture.support.constants.WorkbookConstant;
import com.ibiz.excel.picture.support.util.FileUtil;
-import com.ibiz.excel.picture.support.util.CompressorUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.*;
+import java.io.File;
+import java.io.OutputStream;
import java.util.*;
/**
@@ -15,9 +16,19 @@ import java.util.*;
*/
public class Workbook {
private Logger logger = LoggerFactory.getLogger(this.getClass());
- /**到达row行数就刷新流*/
+ /**
+ * 操作窗口
+ * 当写入excel数据行数大于flushSize时{@link Sheet.SheetHandler#createRow(int)},
+ * 会刷新数据到流,调用该方法
+ * {@link com.ibiz.excel.picture.support.flush.DrawingXmlRelsHandler#copyPictureAppendDrawingRelsXML(Sheet, Picture)}
+ * 将图片刷新在磁盘中
+ * 不会占用内存空间
+ * flushSize = -1 时不刷新流
+ */
private int flushSize;
- /**工作表sheet */
+ /**
+ * 工作表sheet
+ */
private List sheets;
public File getWorkbookFile() {
@@ -25,12 +36,18 @@ public class Workbook {
}
private final File workbookFile;
- /**excel临时目录名*/
+ /**
+ * excel临时目录名
+ */
private final String filePath;
- /**生成的excel文件绝对路径*/
+ /**
+ * 生成的excel文件绝对路径
+ */
private final String destPath;
/**执行了close方法后,才会有dest*/
- /**目的文件*/
+ /**
+ * 目的文件
+ */
private File destFile;
private boolean close;
/***
@@ -42,9 +59,11 @@ public class Workbook {
public Map getImageCache() {
return imageCache;
}
+
private Workbook() {
this(100);
}
+
private Workbook(int flushSize) {
this.flushSize = flushSize;
filePath = WorkbookConstant.AUTO_DIR + WorkbookConstant.FILE_SEPARATOR + UUID.randomUUID().toString().replace("-", "");
@@ -55,14 +74,28 @@ public class Workbook {
/**
* 获取WorkBook实例,默认100行刷新
+ *
* @return
*/
public static Workbook getInstance() {
return getInstance(100);
}
+
+ /**
+ * 操作窗口
+ * 当写入excel数据行数大于flushSize时{@link Sheet.SheetHandler#createRow(int)},
+ * 会刷新数据到流,调用该方法
+ * {@link com.ibiz.excel.picture.support.flush.DrawingXmlRelsHandler#copyPictureAppendDrawingRelsXML(Sheet, Picture)}
+ * 将图片刷新在磁盘中
+ * 不会占用内存空间
+ * flushSize = -1 时不刷新流
+ * @param flushSize
+ * @return
+ */
public static Workbook getInstance(int flushSize) {
return new Workbook(flushSize);
}
+
public Sheet createSheet() {
Sheet sheet = Sheet.getInstance(flushSize, this);
sheets.add(sheet);
@@ -81,7 +114,7 @@ public class Workbook {
}
sheets.forEach(Sheet::close);
//把文件打包成xlsx
- CompressorUtil.compress(filePath, destPath);
+ ZipUtil.zip(filePath, destPath);
destFile = new File(destPath);
deleteFile(filePath);
logger.info("dest excel path:{}", destPath);
@@ -111,5 +144,4 @@ public class Workbook {
throw new RuntimeException("workbook is closed");
}
}
-
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/abt/XmlAbstract.java b/src/main/java/com/ibiz/excel/picture/support/model/abt/XmlAbstract.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c4bac76f1826c7c5b05538739433d6ba63f35ab
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/abt/XmlAbstract.java
@@ -0,0 +1,23 @@
+package com.ibiz.excel.picture.support.model.abt;
+
+import com.ibiz.excel.picture.support.util.XmlUtil;
+
+import javax.xml.bind.JAXBException;
+
+/**
+ * @author MinWeikai
+ * @date 2023/7/13 10:57
+ * @description Xml抽象处理
+ */
+public abstract class XmlAbstract implements XmlInterface {
+
+ @Override
+ public String toXmlString() {
+ try {
+ return XmlUtil.objectToXmlStr(this, false, true);
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/abt/XmlInterface.java b/src/main/java/com/ibiz/excel/picture/support/model/abt/XmlInterface.java
new file mode 100644
index 0000000000000000000000000000000000000000..b5edaaa33decdaae3f420e9c463086abc7398928
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/abt/XmlInterface.java
@@ -0,0 +1,11 @@
+package com.ibiz.excel.picture.support.model.abt;
+
+/**
+ * @author MinWeikai
+ * @date 2023/7/13 10:55
+ * @description xml接口类
+ */
+public interface XmlInterface {
+
+ String toXmlString();
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/model/style/Alignment.java b/src/main/java/com/ibiz/excel/picture/support/model/style/Alignment.java
new file mode 100644
index 0000000000000000000000000000000000000000..15dc082c8f83aa5372fc7de262cc697547ebc6dd
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/model/style/Alignment.java
@@ -0,0 +1,90 @@
+package com.ibiz.excel.picture.support.model.style;
+
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.abt.XmlAbstract;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+
+/**
+ * @author MinWeikai
+ * @date 2023/7/7 18:09
+ * @description excel 内容对齐
+ */
+@XmlRootElement(name = "alignment")
+public class Alignment extends XmlAbstract {
+
+ /**
+ * 对齐方向默认值
+ */
+ public static final String CENTER = "center";
+ public static final String LEFT = "left";
+ public static final String RIGHT = "right";
+ public static final String TOP = "top";
+ public static final String BOTTOM = "bottom";
+
+ public static Alignment build() {
+ return new Alignment();
+ }
+
+ /**
+ * 自动换行
+ */
+ private Integer wrapText = WorkbookConstant.WRAP_TEXT;
+
+ /**
+ * 垂直对齐方式
+ */
+ private String vertical = WorkbookConstant.VERTICAL;
+
+ /**
+ * 水平对齐方式
+ */
+ private String horizontal = WorkbookConstant.HORIZONTAL;
+
+ @XmlAttribute
+ public Integer getWrapText() {
+ return wrapText;
+ }
+
+ /**
+ * 1自动换行,0不换行
+ *
+ * @param wrapText
+ * @return
+ */
+ public Alignment setWrapText(Integer wrapText) {
+ this.wrapText = wrapText;
+ return this;
+ }
+
+ @XmlAttribute
+ public String getVertical() {
+ return vertical;
+ }
+
+ public Alignment setVertical(String vertical) {
+ this.vertical = vertical;
+ return this;
+ }
+
+ @XmlAttribute
+ public String getHorizontal() {
+ return horizontal;
+ }
+
+ public Alignment setHorizontal(String horizontal) {
+ this.horizontal = horizontal;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("Alignment{");
+ sb.append("wrapText=").append(wrapText);
+ sb.append(", vertical='").append(vertical).append('\'');
+ sb.append(", horizontal='").append(horizontal).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/module/Sheet1.java b/src/main/java/com/ibiz/excel/picture/support/module/Sheet1.java
index 1d9260114796450913df0ac0428c017bdcd4a4f7..ad0485a3cf8445e6930dafc8b33a2d606a545963 100644
--- a/src/main/java/com/ibiz/excel/picture/support/module/Sheet1.java
+++ b/src/main/java/com/ibiz/excel/picture/support/module/Sheet1.java
@@ -14,8 +14,8 @@ public class Sheet1 {
@AutoFile(subDir = "worksheets", fileName = "sheet1.xml", alias = Alias.SHEET1,
xmlEnd = AutoXmlHeadEndContent.SHEET1_END)
String content = "" +
- "" +
- "";
+ "xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" mc:Ignorable=\"x14ac\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" " +
+ ">" +
+ "";
+
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/module/Styles.java b/src/main/java/com/ibiz/excel/picture/support/module/Styles.java
index c248a1b86d7ca9619a9d6b221e4213711e5710d3..02319d301e640f8629007ee3c73f78770683a51a 100644
--- a/src/main/java/com/ibiz/excel/picture/support/module/Styles.java
+++ b/src/main/java/com/ibiz/excel/picture/support/module/Styles.java
@@ -5,37 +5,18 @@ import com.ibiz.excel.picture.support.annotation.AutoWrite;
import com.ibiz.excel.picture.support.constants.Alias;
/**
- * @auther 喻场
- * @date 2020/7/310:03
+ * 有时间可以优化
+ * 电子表格样式参考处
+ * http://officeopenxml.com/SSstyles.php
+ *
+ * @author MinWeikai
+ * @date 2021-01-19 14:00:55
*/
@AutoWrite(dir = "xl")
public class Styles {
@AutoFile(fileName = "styles.xml", alias = Alias.STYLES)
- String content = "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "";
+ String content() {
+ return "";
+
+ }
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/processor/ExcelTableProcessor.java b/src/main/java/com/ibiz/excel/picture/support/processor/ExcelTableProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..a993b8caa53305ddc5d558927bb141cc8a616fe5
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/processor/ExcelTableProcessor.java
@@ -0,0 +1,209 @@
+package com.ibiz.excel.picture.support.processor;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.map.MapUtil;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * excel表格处理器
+ * 简化并辅助解决动态表头导出问题
+ *
+ * @author MinWeikai
+ * @date 2022/2/9 11:22
+ */
+public class ExcelTableProcessor {
+
+ public ExcelTableProcessor(Sheet sheet) {
+ this.sheet = sheet;
+ }
+
+ public static ExcelTableProcessor sheet(Sheet sheet) {
+ return new ExcelTableProcessor(sheet);
+ }
+
+ /**
+ * 行高
+ */
+ private int rowHeight = WorkbookConstant.PICTURE_ROW_HEIGHT;
+
+ private final Sheet sheet;
+
+ /**
+ * 开始行号
+ */
+ private int startRow = 0;
+
+ /**
+ * 开始单元格
+ */
+ private int startCell = 0;
+
+ /**
+ * 样式
+ */
+ private final List cellStyles = new ArrayList<>();
+
+ /**
+ * key : 对象的field属性名称
+ * value : 此属性value相关的数据字典
+ */
+ private final Map> fieldEnumMap = new HashMap<>();
+
+ /**
+ * 构建excel
+ *
+ * @param excels excel属性配置,会根据excels中的field属性反射取出list中的值
+ * @param list 需要导出的集合对象 该对象必须实现接口{@link BizExcelPojoInterface}
+ */
+ public void buildExcel(List excels, List extends BizExcelPojoInterface> list) {
+ // 开始行放标题
+ Row row = sheet.createRow(startRow).setCellStyle(getCellStyle(startRow, null));
+ List cells = new ArrayList<>();
+ BizExcelRel rel;
+ excels = excels.stream().sorted(Comparator.comparing(BizExcelRel::getOrderNo)).collect(Collectors.toList());
+ for (int i = startCell; i < excels.size(); i++) {
+ rel = excels.get(i);
+ cells.add(new Cell(i).setValue(rel.getExcelName()).setCellStyle(getCellStyle(startRow, i)));
+ // 设置单元格宽度
+ if (rel.getCellWeight() > 0) {
+ sheet.setColumnWidth(rel.getOrderNo(), rel.getCellWeight());
+ }
+ }
+ row.autoRowCells(cells);
+ int num;
+ BizExcelPojoInterface excelPojoInterface;
+ Map cellStyleMap = new HashMap<>();
+ for (int j = 0; j < list.size(); j++) {
+ // 开始行的下一行放内容
+ num = startRow + j + 1;
+ row = sheet.createRow(num).setCellStyle(getCellStyle(num, null));
+ cells = new ArrayList<>();
+ int index = startCell;
+ excelPojoInterface = list.get(j);
+ for (BizExcelRel excel : excels) {
+ Object propertyValue = BeanUtil.getFieldValue(excelPojoInterface, excel.getField());
+ String value;
+ // 是图片
+ if (excel.isPicture() && Objects.nonNull(propertyValue)) {
+ // 添加图片
+ PictureProcessor.build(sheet).addPictures(row, index, propertyValue,
+ 0, WorkbookConstant.PICTURE_WEIGHT, WorkbookConstant.PICTURE_HEIGHT);
+ value = "";
+ } else {
+ value = propertyValue == null ? "" : propertyValue.toString();
+ }
+ row.setHeight(rowHeight);
+ // 数据字典值获取
+ value = getValueByFiledEnumMap(excel.getField(), value);
+ // 设置以下数据样式
+ CellStyle cellStyle = getCellStyle(num, index);
+ Cell cell = new Cell(num, index++).setValue(value);
+ if (cellStyle != null && cellStyle.isColLast()) {
+ cellStyleMap.put(index, cellStyle);
+ }
+
+ CellStyle style = cellStyleMap.get(index);
+ if (style != null) {
+ style = BeanUtil.copyProperties(style, CellStyle.class);
+ }else {
+ style = cellStyle;
+ }
+ cells.add(cell.setCellStyle(style));
+ row.setCells(cells);
+ }
+
+ }
+ }
+
+ private CellStyle getCellStyle(Integer row, Integer col) {
+ return this.cellStyles.stream()
+ .filter(c -> Objects.equals(c.getRowNumber(), row) && Objects.equals(col, c.getColNumber()))
+ .findFirst().orElse(null);
+ }
+
+ /**
+ * 数据字典值获取
+ *
+ * @param field
+ * @param value
+ * @return
+ */
+ private String getValueByFiledEnumMap(String field, String value) {
+ Map enumMap = fieldEnumMap.get(field);
+ if (MapUtil.isNotEmpty(enumMap)) {
+ return enumMap.get(value);
+ }
+ return value;
+ }
+
+ /**
+ * 设置行高
+ *
+ * @param rowHeight
+ * @return
+ */
+ public ExcelTableProcessor setRowHeight(int rowHeight) {
+ this.rowHeight = rowHeight;
+ return this;
+ }
+
+ /**
+ * 批量添加样式
+ *
+ * @param cellStyles
+ * @return
+ */
+ public ExcelTableProcessor addCellStyle(List cellStyles) {
+ this.cellStyles.addAll(cellStyles);
+ return this;
+ }
+
+ /**
+ * 添加样式
+ *
+ * @param cellStyle
+ * @return
+ */
+ public ExcelTableProcessor addCellStyle(CellStyle cellStyle) {
+ this.cellStyles.add(cellStyle);
+ return this;
+ }
+
+ /**
+ * 设置写入数据开始行号
+ *
+ * @param startRow
+ * @return
+ */
+ public ExcelTableProcessor setStartRow(int startRow) {
+ this.startRow = startRow;
+ return this;
+ }
+
+ /**
+ * 设置写入数据开始单元格
+ *
+ * @param startCell
+ * @return
+ */
+ public ExcelTableProcessor setStartCell(int startCell) {
+ this.startCell = startCell;
+ return this;
+ }
+
+ /**
+ * 注入属性字典值
+ *
+ * @param field 属性名
+ * @param enumMap 数据字典值
+ * @return
+ */
+ public ExcelTableProcessor registryEnumMap(String field, Map enumMap) {
+ fieldEnumMap.put(field, enumMap);
+ return this;
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/processor/PictureProcessor.java b/src/main/java/com/ibiz/excel/picture/support/processor/PictureProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..b341f9134738b0264769808d5f1c3d0c529b46dd
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/processor/PictureProcessor.java
@@ -0,0 +1,114 @@
+package com.ibiz.excel.picture.support.processor;
+
+import com.ibiz.excel.picture.support.annotation.ExportModel;
+import com.ibiz.excel.picture.support.model.Picture;
+import com.ibiz.excel.picture.support.model.Row;
+import com.ibiz.excel.picture.support.model.Sheet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * excel中图片处理器
+ *
+ * @author MinWeikai
+ * @date 2022/2/11 13:55
+ */
+public class PictureProcessor {
+
+ public PictureProcessor(Sheet sheet) {
+ this.sheet = sheet;
+ }
+
+ public static PictureProcessor build(Sheet sheet) {
+ return new PictureProcessor(sheet);
+ }
+
+ private final Sheet sheet;
+
+ /**
+ * 添加图片
+ *
+ * @param row
+ * @param cellNumber
+ * @param value
+ * @param model
+ */
+ public void addPictures(Row row, int cellNumber, Object value, ExportModel model) {
+ // 图片所在单元格宽度,图片和单元格宽度一致
+ int width = model.width();
+ // 图片所在单元格行高度
+ int height = model.height();
+ addPictures(row, cellNumber, value, model.pictureSource(), width, height);
+ }
+
+ /**
+ * 添加图片
+ *
+ * @param row
+ * @param cellNumber
+ * @param value
+ * @param pictureSource
+ * @param width
+ * @param height
+ */
+ public void addPictures(Row row, int cellNumber, Object value, int pictureSource, int width, int height) {
+ List values = getValues(value);
+ // 计算行高
+ calculateRowHeight(row, height);
+ // 计算单元格宽度根据单元格中值的数量
+ calculateColumnWidth(cellNumber, width, values.size());
+ //增加图片
+ values.forEach(val ->
+ sheet.getPictures().add(
+ new Picture(row.getRowNumber(), cellNumber, width, height, val, pictureSource)
+ // 自动设置图片来源
+ .autoPictureSourceByPath()
+ ));
+ }
+
+ /**
+ * 获取value集合
+ *
+ * @param value
+ * @return
+ */
+ private List getValues(Object value) {
+ List values = new ArrayList<>();
+ if (value instanceof List) {
+ values = (List) value;
+ } else {
+ values.add(String.valueOf(value));
+ }
+ return values;
+ }
+
+ /**
+ * 计算行高
+ *
+ * @param row
+ * @param height
+ */
+ private void calculateRowHeight(Row row, int height) {
+ // 设置行高自适应于图片的高度
+ row.setHeight((height / 12600) - 1);
+ }
+
+ /**
+ * 计算单元格宽度根据单元格中值的数量
+ *
+ * @param cellNumber
+ * @param width
+ * @param valuesSize 图片数
+ */
+ private void calculateColumnWidth(int cellNumber, int width, int valuesSize) {
+ // 实际宽
+ int actualWidth = width / 76923;
+ //
+ // 数组为空时,给默认值1,否则单元格宽度会被计算成0
+ valuesSize = valuesSize == 0 ? 1 : valuesSize;
+ // 设置单元格宽度,单元格宽度 = 图片宽*图片数量
+ double columnWidth = actualWidth * valuesSize + valuesSize / 1.5;
+ sheet.setColumnWidth(cellNumber + 1, columnWidth);
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/util/BeanUtil.java b/src/main/java/com/ibiz/excel/picture/support/util/BeanUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..2219744f742789033e235798cd56ff98543815cd
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/util/BeanUtil.java
@@ -0,0 +1,87 @@
+package com.ibiz.excel.picture.support.util;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author MinWeikai
+ * @date 2022/2/9 9:31
+ */
+public class BeanUtil {
+
+ /**
+ * 反射获取对象属性,支持嵌套
+ * 例如:
+ * User user = new User();
+ * Position position = new Position();
+ * position.setName("fjjffj");
+ * user.setPositionList(Lists.newArrayList(position));
+ * Organization organization = new Organization();
+ * organization.setName("1111111");
+ * user.setOrganization(organization);
+ * BaseCriteria criteria = new BaseCriteria();
+ * Map map = Maps.newHashMap();
+ * map.put("bb","aaaaaaaaaaaaaaaa");
+ * criteria.setStrValue(map);
+ * user.setCriteria(criteria);
+ * Object obj = getPropertyValue(user, "organization.name");
+ * System.out.println(obj);
+ * obj = getPropertyValue(user, "positionList[0].name");
+ * System.out.println(obj);
+ * obj = getPropertyValue(user, "criteria.strValue[bb]");
+ * System.out.println(obj);
+ * @param obj
+ * @param key
+ * @return
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ */
+ public static Object getPropertyValue(Object obj, String key){
+ if (key.contains(".")){
+ int dotMarkIndex = key.indexOf(".");
+ String prefixKey = key.substring(0, dotMarkIndex);
+ Object prefixObj = getSimplePropertyValue(obj, prefixKey);
+ String suffixKey = key.substring(dotMarkIndex+1);
+ return getPropertyValue(prefixObj, suffixKey);
+ }
+ return getSimplePropertyValue(obj, key);
+ }
+
+ private static Object getSimplePropertyValue(Object obj, String key){
+ String prefixKey ;
+ String suffixKey = null;
+ Object returnValue ;
+ if(key.matches("(\\w+)\\[(\\w+)\\]$")){
+ int endIndex = key.indexOf("[");
+ prefixKey = key.substring(0, endIndex);
+ suffixKey = key.substring(endIndex+1, key.length() -1);
+ }else{
+ prefixKey = key;
+ }
+ if(obj instanceof Map){
+ returnValue = ((Map) obj).get(prefixKey);
+ }else {// obj instanceof Object
+ PropertyDescriptor propertyDescriptor = org.springframework.beans.BeanUtils.getPropertyDescriptor(obj.getClass(), prefixKey);
+ try {
+ assert propertyDescriptor != null;
+ returnValue = propertyDescriptor.getReadMethod().invoke(obj);
+ } catch (InvocationTargetException | IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ if (StringUtils.isNotBlank(suffixKey)){
+ try {
+ int index = Integer.parseInt(suffixKey);//数字 -->> 数组/集合
+ if(returnValue instanceof Collection){//集合转数组
+ returnValue = ((Collection) returnValue).toArray(new Object[0]);
+ }
+ returnValue = ((Object[])returnValue)[index];
+ }catch (NumberFormatException e){//字符串 -->> 对象
+ returnValue = getPropertyValue(returnValue, suffixKey);
+ }
+ }
+ return returnValue;
+ }
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/util/CompressorUtil.java b/src/main/java/com/ibiz/excel/picture/support/util/CompressorUtil.java
deleted file mode 100644
index 25995be27c66dfcffc3fdb437c92ffd85c1ee03f..0000000000000000000000000000000000000000
--- a/src/main/java/com/ibiz/excel/picture/support/util/CompressorUtil.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.ibiz.excel.picture.support.util;
-
-import java.io.File;
-
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.taskdefs.Zip;
-import org.apache.tools.ant.types.FileSet;
-
-/**
- * 将文件夹压缩成文件
- */
-public class CompressorUtil {
- /**
- *
- * @param src 原文件绝对路径
- * @param dest 目标文件绝对路径
- */
- public static void compress(String src, String dest) {
- //目的文件
- File destFile = new File(dest);
- //原文件
- File srcFile = new File(src);
- if (!srcFile.exists()){
- throw new RuntimeException(src + "不存在!");
- }
- Project prj = new Project();
- Zip zip = new Zip();
- zip.setProject(prj);
- zip.setDestFile(destFile);
- FileSet fileSet = new FileSet();
- fileSet.setProject(prj);
- fileSet.setDir(srcFile);
- //fileSet.setIncludes("**/*.java"); //包括哪些文件或文件夹 eg:zip.setIncludes("*.java");
- //fileSet.setExcludes(...); //排除哪些文件或文件夹
- zip.addFileset(fileSet);
- zip.execute();
- }
-}
-
diff --git a/src/main/java/com/ibiz/excel/picture/support/util/FileUtil.java b/src/main/java/com/ibiz/excel/picture/support/util/FileUtil.java
index 37826f48f731413ff069c62c0c6e8625bbf70f1e..61ef0646e3aea750a1a44bc01d46afb29a6569e5 100644
--- a/src/main/java/com/ibiz/excel/picture/support/util/FileUtil.java
+++ b/src/main/java/com/ibiz/excel/picture/support/util/FileUtil.java
@@ -47,14 +47,13 @@ public class FileUtil {
}
public static void writeToOutput(File source, OutputStream output) {
- try {
- byte[] buf = new byte[2048];
- FileInputStream fis = new FileInputStream(source);
- while (fis.read(buf) != -1) {
- output.write(buf);
+ byte[] buf = new byte[1024];
+ int len;
+ try(BufferedInputStream fis = new BufferedInputStream(new FileInputStream(source))) {
+ while((len = fis.read(buf)) != -1){
+ output.write(buf, 0 , len);
}
- fis.close();
- } catch (IOException e) {
+ }catch (IOException e) {
throw new RuntimeException("write to output error , destFile path:" + source.getAbsolutePath(), e);
}
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/util/MD5Digester.java b/src/main/java/com/ibiz/excel/picture/support/util/MD5Digester.java
index 59e1cacdb4471d00f2c4bc426f2edac0eb3475b5..0b5ccd487618f54fe0e2a0403bb25b7d24471593 100644
--- a/src/main/java/com/ibiz/excel/picture/support/util/MD5Digester.java
+++ b/src/main/java/com/ibiz/excel/picture/support/util/MD5Digester.java
@@ -6,6 +6,7 @@ import java.security.NoSuchAlgorithmException;
/**
* 文件流md5
+ *
* @author yc 创建时间:2018年1月24日 下午4:50:35
*/
public class MD5Digester {
@@ -13,34 +14,35 @@ public class MD5Digester {
* digital
*/
public static final char[] DIGITAL = "0123456789ABCDEF".toCharArray();
+
/**
* MD5Digester
*/
- private MD5Digester() {}
+ private MD5Digester() {
+ }
public static String digestMD5(File file) throws FileNotFoundException {
FileInputStream fis = new FileInputStream(file);
return digestMD5(fis);
}
+
/**
* 文件流md5
- * @param is InputStream
- * @return md5
+ *
+ * @param inputStream InputStream
+ * @return md5
*/
- public static String digestMD5(InputStream is) {
- try {
+ public static String digestMD5(InputStream inputStream) {
+ try (InputStream is = inputStream) {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[8192];
- int len = 0;
+ int len;
while (-1 != (len = is.read(buffer))) {
digest.update(buffer, 0, len);
}
byte[] md5hash = digest.digest();
return encodeHexStr(md5hash);
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- throw new RuntimeException(e);
- } catch (IOException e) {
+ } catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
@@ -48,6 +50,7 @@ public class MD5Digester {
/**
* encodeHexStr
+ *
* @param bytes bytes
* @return String
*/
@@ -63,4 +66,27 @@ public class MD5Digester {
return new String(result);
}
+ /**
+ * 获取字符串的摘要 md5值
+ *
+ * @param data
+ * @return
+ */
+ public static String digestMD5(String data) {
+ MessageDigest message;
+ try {
+ message = MessageDigest.getInstance("MD5");
+ message.update(data.getBytes());
+ byte[] b = message.digest();
+ return encodeHexStr(b);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(digestMD5("12312erdhhjfdkti5745468587ry87r4tuy87rt4u8rt44u36346"));
+ }
+
}
diff --git a/src/main/java/com/ibiz/excel/picture/support/util/WebUtil.java b/src/main/java/com/ibiz/excel/picture/support/util/WebUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..aefa9bb5b572b8d78d7c6ea73c0120838418f319
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/util/WebUtil.java
@@ -0,0 +1,71 @@
+package com.ibiz.excel.picture.support.util;
+
+import cn.hutool.core.io.FileUtil;
+import com.ibiz.excel.picture.support.model.Workbook;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.util.WebUtils;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+ * web文件处理工具
+ *
+ * @author MinWeikai
+ * @date 2021-12-06 17:49:09
+ */
+public class WebUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(WebUtils.class);
+
+ /**
+ * excel导出测试
+ *
+ * @param wb 自定义的excel工作簿excel
+ * @param fileName 文件名
+ * @param tempPath 生成文件存放临时路径
+ */
+ public static void writeExcelTest(Workbook wb, String fileName, String tempPath) {
+ File file = FileUtil.touch(tempPath.concat(fileName));
+ try (BufferedOutputStream os = FileUtil.getOutputStream(file)) {
+ wb.write(os);
+ } catch (Exception e) {
+ // 报错时删除文件
+ FileUtil.del(file);
+ log.error("测试导出excel异常", e);
+ }finally {
+ wb.close();
+ }
+ log.debug("测试导出excel路径:{}", file.getAbsolutePath());
+ }
+
+ /**
+ * excel web端下载
+ *
+ * @param wb 自定义的excel工作簿excel
+ * @param fileName 文件名
+ * @param response 响应体
+ * @throws IOException
+ */
+ public static void writeExcel(Workbook wb, String fileName, HttpServletResponse response) throws IOException {
+ response.reset();
+ response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+ try (ServletOutputStream os = response.getOutputStream()) {
+ wb.write(os);
+ } catch (Exception e) {
+ log.error("导出excel异常", e);
+ } finally {
+ wb.close();
+ }
+ }
+
+
+}
diff --git a/src/main/java/com/ibiz/excel/picture/support/util/XmlUtil.java b/src/main/java/com/ibiz/excel/picture/support/util/XmlUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..0331b628d331927f59b9c15ac888e0c142dd88b2
--- /dev/null
+++ b/src/main/java/com/ibiz/excel/picture/support/util/XmlUtil.java
@@ -0,0 +1,35 @@
+package com.ibiz.excel.picture.support.util;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import java.io.StringWriter;
+
+/**
+ * @author MinWeikai
+ * @date 2023-07-07 18:55:10
+ * @description xml操作工具类
+ */
+public class XmlUtil {
+
+ /**
+ * 对象转xml字符串
+ * @param object
+ * @param formatted 是否格式化
+ * @param fragment 是否不生成XML声明
+ * @param
+ * @return
+ * @throws JAXBException
+ */
+ public static String objectToXmlStr(T object, boolean formatted, boolean fragment) throws JAXBException {
+ JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
+ Marshaller marshaller = jaxbContext.createMarshaller();
+ // 格式化
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formatted);
+ // 生成XML声明
+ marshaller.setProperty(Marshaller.JAXB_FRAGMENT, fragment);
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(object, writer);
+ return writer.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
deleted file mode 100644
index 8b137891791fe96927ad78e64b0aad7bded08bdc..0000000000000000000000000000000000000000
--- a/src/main/resources/application.properties
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/main/resources/image/image1.png b/src/main/resources/image/image1.png
deleted file mode 100644
index f684908bcf28561e2d768462c4d986e3f28622e3..0000000000000000000000000000000000000000
Binary files a/src/main/resources/image/image1.png and /dev/null differ
diff --git a/src/main/resources/image/image2.png b/src/main/resources/image/image2.png
deleted file mode 100644
index 631853e09cbe1cf1319a85573532387e95cab9fd..0000000000000000000000000000000000000000
Binary files a/src/main/resources/image/image2.png and /dev/null differ
diff --git a/src/main/resources/image/image3.png b/src/main/resources/image/image3.png
deleted file mode 100644
index 3494b0e4446f5469c0239a40dd48fb386d6003c4..0000000000000000000000000000000000000000
Binary files a/src/main/resources/image/image3.png and /dev/null differ
diff --git a/src/main/resources/image/image4.png b/src/main/resources/image/image4.png
deleted file mode 100644
index c66f9cbdf708a2f417bc8cad03ef7ae9e5bae7f4..0000000000000000000000000000000000000000
Binary files a/src/main/resources/image/image4.png and /dev/null differ
diff --git a/src/main/resources/image/image5.png b/src/main/resources/image/image5.png
deleted file mode 100644
index 2318785bbe372ffad41b3073567ffc54f6c99ed4..0000000000000000000000000000000000000000
Binary files a/src/main/resources/image/image5.png and /dev/null differ
diff --git a/src/test/java/com/ibiz/excel/picture/support/ColMergeCellTest.java b/src/test/java/com/ibiz/excel/picture/support/ColMergeCellTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b3f97da0915c00ba8e72736ec3e513af2150ebf
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/ColMergeCellTest.java
@@ -0,0 +1,71 @@
+package com.ibiz.excel.picture.support;
+
+import cn.hutool.core.io.FileUtil;
+import com.ibiz.excel.picture.support.model.*;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 横向合并列测试
+ *
+ * @author MinWeikai
+ * @date 2021/1/18 17:22
+ */
+public class ColMergeCellTest {
+
+ static final String CURRENT_PATH = "E:\\test\\";
+
+ public static void main(String[] args) throws IOException {
+ Date start = new Date();
+ Workbook workBook = Workbook.getInstance(1);
+ Sheet sheet = workBook.createSheet("测试");
+
+ // 第一行表头
+ Row row = sheet.createRow(0);
+ String[] excelName = {"文本1", "文本2", "图片1", "图片2", "图片3"};
+ row.addCell(new Cell(0, 0).setValue("表头"));
+ sheet.addMergeCell(new MergeCell(0, 0, 0, excelName.length - 1));
+
+ // 第二行放标题
+ row = sheet.createRow(1);
+ List cells = new ArrayList<>();
+ for (int i = 0; i < excelName.length; i++) {
+ Cell cell = new Cell(1, i).setValue(excelName[i]);
+ cells.add(cell);
+ }
+ row.setCells(cells);
+
+ // 第三行放内容
+ row = sheet.createRow(2);
+ cells = new ArrayList<>();
+ for (int i = 0; i < excelName.length; i++) {
+ Cell cell = new Cell(2, i).setValue("文本" + i);
+ cells.add(cell);
+ }
+ row.setCells(cells);
+
+
+ File file = createFile();
+ BufferedOutputStream os = FileUtil.getOutputStream(file);
+ workBook.write(os);
+ workBook.close();
+ Date end = new Date();
+ System.out.println("file capital :" + (file.length() / 1024 / 1024) + "M name :" + file.getName());
+ System.out.println("file cost time :" + (end.getTime() - start.getTime()));
+ os.close();
+ }
+
+
+ private static File createFile() {
+ String dir = CURRENT_PATH + "excel/";
+ File file = new File(dir);
+ if (!file.exists()) {
+ file.mkdir();
+ }
+ String name = CURRENT_PATH + "excel/" + UUID.randomUUID() + ".xlsx";
+ return new File(name);
+ }
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/CustomTitleDemo.java b/src/test/java/com/ibiz/excel/picture/support/CustomTitleDemo.java
new file mode 100644
index 0000000000000000000000000000000000000000..d89afa0cb870502d65c1d559790452ae2175cb41
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/CustomTitleDemo.java
@@ -0,0 +1,83 @@
+package com.ibiz.excel.picture.support;
+
+import cn.hutool.core.io.FileUtil;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.*;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 自定义标题,填入文本和图片
+ *
+ * @author MinWeikai
+ * @date 2021-01-15 15:19:44
+ */
+public class CustomTitleDemo {
+ static final String CURRENT_PATH = "E:\\test\\";
+
+ private final static String IMG_PATH = CURRENT_PATH + "img\\";
+
+ private final static String IMG_PATH_1 = IMG_PATH + "ia_1900002528.jpeg";
+ private final static String IMG_PATH_2 = IMG_PATH + "ia_1200000645.jpg";
+
+
+ public static void main(String[] args) throws IOException {
+ Date start = new Date();
+ Workbook workBook = Workbook.getInstance(1);
+ Sheet sheet = workBook.createSheet("测试");
+
+ // 第一行放标题
+ Row rowHead = sheet.createRow(0);
+ String[] excelName = {"文本1", "文本2", "图片1", "图片2", "图片3"};
+ List nameCells = new ArrayList<>();
+ int n = 0;
+ for (int i = 0; i < excelName.length; i++) {
+ nameCells.add(new Cell(0, n).setValue(excelName[i]));
+ if (Objects.equals(excelName[i], "图片1")) {
+ n = n + 9;
+ }
+ n++;
+ }
+ rowHead.setCells(nameCells);
+
+ // 第二行放文本图片
+ Row row = sheet.createRow(1);
+ List valueCells = new ArrayList<>();
+ List pictures = sheet.getPictures();
+ for (int i = 0; i < excelName.length; i++) {
+ if (i < 2) {
+ valueCells.add(new Cell(1, i).setValue("文本"));
+ } else {
+ //有图片的行,行高设置为100
+ row.setHeight(WorkbookConstant.PICTURE_ROW_HEIGHT);
+ //增加图片
+ pictures.add(new Picture(row.getRowNumber(), i, IMG_PATH_1));
+ }
+ }
+ row.setCells(valueCells);
+
+ File file = createFile();
+ BufferedOutputStream os = FileUtil.getOutputStream(file);
+ workBook.write(os);
+ workBook.close();
+ Date end = new Date();
+ System.out.println("file capital :" + (file.length() / 1024 / 1024) + "M name :" + file.getName());
+ System.out.println("file cost time :" + (end.getTime() - start.getTime()));
+ os.close();
+ }
+
+
+ private static File createFile() {
+ String dir = CURRENT_PATH + "excel/";
+ File file = new File(dir);
+ if (!file.exists()) {
+ file.mkdir();
+ }
+ String name = CURRENT_PATH + "excel/" + UUID.randomUUID() + ".xlsx";
+ return new File(name);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/Demo.java b/src/test/java/com/ibiz/excel/picture/support/Demo.java
index 9b18521ccef81d963ae1d203d964689751c63f96..8b35dc9d215cfe0b8550f7314c5fd0e5a5c5cf01 100644
--- a/src/test/java/com/ibiz/excel/picture/support/Demo.java
+++ b/src/test/java/com/ibiz/excel/picture/support/Demo.java
@@ -2,6 +2,7 @@ package com.ibiz.excel.picture.support;
import com.ibiz.excel.picture.support.model.Sheet;
import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.pojo.User;
import java.io.*;
import java.util.Date;
@@ -13,7 +14,7 @@ import java.util.stream.IntStream;
* @date 2020/7/817:29
*/
public class Demo {
- static final String CURRENT_PATH = Demo.class.getClassLoader().getResource(".").getPath();
+ static final String CURRENT_PATH = "E:\\test\\";
static final String picture1 = CURRENT_PATH + "image/image1.png";
static final String picture2 = CURRENT_PATH + "image/image2.png";
static final String picture3 = CURRENT_PATH + "image/image3.png";
@@ -23,7 +24,7 @@ public class Demo {
Date start = new Date();
Workbook workBook = Workbook.getInstance(200);
Sheet sheet = workBook.createSheet("导出个表");
- IntStream.range(1, 5000).forEach(r -> {
+ IntStream.range(1, 10).forEach(r -> {
String pre = "a";
if (r % 3 == 0) {
pre = "b";
diff --git a/src/test/java/com/ibiz/excel/picture/support/ExcelXApplicationTests.java b/src/test/java/com/ibiz/excel/picture/support/ExcelXApplicationTests.java
deleted file mode 100644
index 7e766221e450ba5dd523322c3a06a27b39fbb681..0000000000000000000000000000000000000000
--- a/src/test/java/com/ibiz/excel/picture/support/ExcelXApplicationTests.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.ibiz.excel.picture.support;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-import java.io.*;
-
-@SpringBootTest
-class ExcelXApplicationTests {
-
- @Test
- void contextLoads() throws IOException {
- }
-}
diff --git a/src/test/java/com/ibiz/excel/picture/support/RowMergeCellTest.java b/src/test/java/com/ibiz/excel/picture/support/RowMergeCellTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..396a30479cd7655ec44230d84d0f9477d84f5d04
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/RowMergeCellTest.java
@@ -0,0 +1,65 @@
+package com.ibiz.excel.picture.support;
+
+import cn.hutool.core.io.FileUtil;
+import com.ibiz.excel.picture.support.model.*;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * 纵向合并行测试
+ *
+ * @author MinWeikai
+ * @date 2021/1/18 17:22
+ */
+public class RowMergeCellTest {
+
+ static final String CURRENT_PATH = "E:\\test\\";
+
+ public static void main(String[] args) throws IOException {
+ Date start = new Date();
+ Workbook workBook = Workbook.getInstance(1);
+ Sheet sheet = workBook.createSheet("测试");
+
+ // 第一行放标题
+ Row rowHead = sheet.createRow(0);
+ String[] excelName = {"文本1", "文本2", "图片1", "图片2", "图片3"};
+ List nameCells = new ArrayList<>();
+
+ sheet.getMergeCells().add(new MergeCell().setFirstRow(1).setLastRow(3));
+ sheet.setAutoMergeCell(true);
+ Set colCells = new HashSet<>();
+ for (int i = 0; i < excelName.length; i++) {
+ Cell cell = new Cell(0, i).setValue(excelName[i]);
+ if (i == 0) {
+ colCells.add(cell.getCol());
+ sheet.setColCells(colCells);
+ }
+ nameCells.add(cell);
+ }
+ rowHead.setCells(nameCells);
+
+
+ File file = createFile();
+ BufferedOutputStream os = FileUtil.getOutputStream(file);
+ workBook.write(os);
+ workBook.close();
+ Date end = new Date();
+ System.out.println("file capital :" + (file.length() / 1024 / 1024) + "M name :" + file.getName());
+ System.out.println("file cost time :" + (end.getTime() - start.getTime()));
+ os.close();
+ }
+
+
+ private static File createFile() {
+ String dir = CURRENT_PATH + "excel/";
+ File file = new File(dir);
+ if (!file.exists()) {
+ file.mkdir();
+ }
+ String name = CURRENT_PATH + "excel/" + UUID.randomUUID() + ".xlsx";
+ return new File(name);
+ }
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/WebImgTest.java b/src/test/java/com/ibiz/excel/picture/support/WebImgTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..85cc78f244ced46b917a118aa4d0f2ad1cf54120
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/WebImgTest.java
@@ -0,0 +1,21 @@
+package com.ibiz.excel.picture.support;
+
+import cn.hutool.http.HttpUtil;
+
+import java.io.File;
+
+/**
+ * 网络图片测试
+ *
+ * @author MinWeikai
+ * @date 2022/1/7 16:34
+ */
+public class WebImgTest {
+
+ public static void main(String[] args) {
+ String url = "https://portrait.gitee.com/uploads/avatars/user/552/1657608_mwk719_1641537497.png";
+ File destFilePath = new File("E:\\test\\img\\1111.png");
+ long destFile = HttpUtil.downloadFile(url, destFilePath, 5 * 1000);
+ System.out.println(destFile);
+ }
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/common/BaseJunitTest.java b/src/test/java/com/ibiz/excel/picture/support/common/BaseJunitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..622e7c93b3b562499969a7db356ebaf186b199c5
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/common/BaseJunitTest.java
@@ -0,0 +1,71 @@
+package com.ibiz.excel.picture.support.common;
+
+import cn.hutool.core.io.FileUtil;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * @author MinWeikai
+ * @date 2022/1/7 18:09
+ */
+public class BaseJunitTest {
+
+ protected static final String CURRENT_PATH = "E:\\test\\";
+ protected static final String TEMP_PATH = CURRENT_PATH + "excel\\";
+ protected final static String IMG_PATH = "E:\\test\\img\\";
+
+ protected final static String IMG_PATH_1 = IMG_PATH + "1.jpg";
+ protected final static String IMG_PATH_2 = IMG_PATH + "2.jpg";
+ protected final static String IMG_PATH_3 = IMG_PATH + "3.jpg";
+
+ protected final static String IMAGES_PATH = CURRENT_PATH + "images\\";
+
+ /**
+ * url图片测试集合
+ */
+ protected final static List URLS = new ArrayList<>();
+
+ /**
+ * 本地测试图片数组
+ */
+ protected final static File[] LOCAL_TEST_FILES;
+
+ static {
+ URLS.add("https://portrait.gitee.com/uploads/avatars/user/552/1657608_mwk719_1641537497.png");
+ URLS.add("https://img2.baidu.com/it/u=121102239,1207969661&fm=253&fmt=auto&app=120&f=JPEG?w=1195&h=500");
+
+ LOCAL_TEST_FILES = FileUtil.ls(IMAGES_PATH);
+ }
+
+
+ /**
+ * 根据图片数组和要获取图片的数量,随机从图片数组中取出若干
+ * @param files 图片数组
+ * @param getCount 获取图片的数量
+ * @return
+ */
+ protected static List getPictures(int getCount) {
+ List list = new ArrayList<>(getCount);
+ for (int i = 0; i < getCount; i++) {
+ int index = new Random().nextInt(LOCAL_TEST_FILES.length);
+ list.add(LOCAL_TEST_FILES[index].getAbsolutePath());
+ }
+ return list;
+ }
+
+ protected static String getUrl() {
+ int index = new Random().nextInt(URLS.size());
+ return URLS.get(index);
+ }
+
+ protected static List getUrls(int getCount) {
+ List list = new ArrayList<>(getCount);
+ for (int i = 0; i < getCount; i++) {
+ list.add(getUrl());
+ }
+ return list;
+ }
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPictureExportExample.java b/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPictureExportExample.java
new file mode 100644
index 0000000000000000000000000000000000000000..33468d365b8076f3e44b6e878cb7a38e9eefb55d
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPictureExportExample.java
@@ -0,0 +1,40 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.util.WebUtil;
+
+import java.io.IOException;
+
+/**
+ * 注解图片导出示例
+ *
+ * @author MinWeikai
+ * @date 2021-12-07 10:59:49
+ */
+public class AnnotationPictureExportExample {
+ static final String CURRENT_PATH = "E:\\test\\";
+ private static final String TEMP_PATH = CURRENT_PATH + "excel\\";
+ private final static String IMG_PATH = "E:\\test\\img\\";
+
+ private final static String IMG_PATH_1 = IMG_PATH + "1.jpg";
+ private final static String IMG_PATH_2 = IMG_PATH + "2.jpg";
+
+
+ public static void main(String[] args) throws IOException {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ UserPicture userPicture;
+ for (int r = 0; r < 5; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ userPicture.setPicture(IMG_PATH_1);
+ // 创建行数据在excel中
+ sheet.createRow(userPicture);
+ }
+ WebUtil.writeExcelTest(workBook, "注解导出图片示例".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPicturesExportExample.java b/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPicturesExportExample.java
new file mode 100644
index 0000000000000000000000000000000000000000..6498cbfef65eeb2ce25dddf838a27aae06a2fd9f
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/AnnotationPicturesExportExample.java
@@ -0,0 +1,50 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.Random;
+
+/**
+ * 注解图片集合导出示例
+ *
+ * @author MinWeikai
+ * @date 2021/12/14 10:36
+ */
+@Ignore
+public class AnnotationPicturesExportExample extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance(56);
+ Sheet sheet = workBook.createSheet("测试");
+
+// 需要在创建行前预设宽度
+// sheet.setColumnWidth(6, 100);
+ UserPicture userPicture;
+ for (int r = 0; r < 10; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ userPicture.setPicture(IMG_PATH_1);
+ userPicture.setHeaderPicture(getUrl());
+ // 根据图片数组和要获取图片的数量,随机从本地测试图片数组中取出若干
+ userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ sheet.createRow(userPicture);
+ // 不设置时,自适应图片的高度
+// .setHeight(200);
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ if(r == 0){
+ sheet.getRow(0).setCellStyle(new CellStyle("66cc66"));
+ }
+ }
+ WebUtil.writeExcelTest(workBook, "注解导出图片集合示例".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/AnnotationTextExportExample.java b/src/test/java/com/ibiz/excel/picture/support/example/AnnotationTextExportExample.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ca4cce9791883f29aa91823a04aaa89f5eef9b6
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/AnnotationTextExportExample.java
@@ -0,0 +1,36 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Test;
+
+/**
+ * 注解无图导出示例
+ *
+ * @author MinWeikai
+ * @date 2021-12-08 11:18:49
+ */
+public class AnnotationTextExportExample extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ UserPicture u1;
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ sheet.addCellStyle(new CellStyle(0, "66cc66"));
+ for (int r = 0; r < 5; r++) {
+ u1 = new UserPicture();
+ u1.setAge(15);
+ u1.setName("测试-" + r);
+ u1.setDepartment("研发部");
+ sheet.createRow(u1);
+ }
+ WebUtil.writeExcelTest(workBook, "注解导出文本示例".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/EasyUseExample4.java b/src/test/java/com/ibiz/excel/picture/support/example/EasyUseExample4.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab1f8063420ea149e928986d5b0e04ba781e48e4
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/EasyUseExample4.java
@@ -0,0 +1,100 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.*;
+import com.ibiz.excel.picture.support.util.WebUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * 简化设置EasyUseExample4
+ * 1. 需要文本列表信息
+ * 2. 需要单元格填充多张图片
+ * 3. 需要表头
+ * 4. 多行数据写入
+ *
+ * @author MinWeikai
+ * @date 2021-02-07 16:47:17
+ */
+public class EasyUseExample4 {
+ private static final String CURRENT_PATH = "E:\\test\\";
+
+ private static final String TEMP_PATH = CURRENT_PATH + "excel\\";
+
+ private final static String IMG_PATH = CURRENT_PATH + "img\\";
+
+ private final static String IMG_PATH_1 = IMG_PATH + "1.jpg";
+ private final static String IMG_PATH_2 = IMG_PATH + "2.jpg";
+
+
+ public static void main(String[] args) {
+ Workbook workBook = Workbook.getInstance(100);
+ Sheet sheet = workBook.createSheet("测试");
+
+ // 需要在创建行前预设宽度
+ // 序号宽度 有时需要单独设置序号宽度窄一点
+ sheet.setColumnWidth(1, 5)
+ // 设置第三列宽度
+ .setColumnWidth(3, 50);
+
+ // 第一行表头
+ Row row = sheet.createRow(0).setCellStyle(new CellStyle("cc3300"));
+ row.addCell(new Cell(0).setValue("表头"));
+
+ // 第二行放标题
+ String[] excelName = {"文本1", "文本2", "图片1", "图片2", "图片3"};
+ //要进行合并的列
+ sheet.addMergeCell(new MergeCell(0, 0, 0, excelName.length - 1));
+
+ row = sheet.createRow(1).setCellStyle(new CellStyle("996699"));
+ List cells = new ArrayList<>();
+ for (int i = 0; i < excelName.length; i++) {
+ cells.add(new Cell(i).setValue(excelName[i]));
+ }
+ row.autoRowCells(cells);
+
+ // 第三行放内容
+ int num;
+ List pictures = sheet.getPictures();
+ for (int j = 0; j < 1; j++) {
+ // 第三行放内容
+ num = j + 2;
+ row = sheet.createRow(num);
+
+ cells = new ArrayList<>();
+ int index = 0;
+ for (int i = 0; i < excelName.length; i++) {
+ Object propertyValue = null;
+ switch (i) {
+ case 0:
+ propertyValue = num - 1;
+ break;
+ case 1:
+ propertyValue = "文本2";
+ break;
+ case 2:
+ //在第二列添加多张图片
+ pictures.add(new Picture(row.getRowNumber(), 2, WorkbookConstant.PICTURE_WEIGHT, IMG_PATH_1));
+ pictures.add(new Picture(row.getRowNumber(), 2, WorkbookConstant.PICTURE_WEIGHT, IMG_PATH_2));
+ row.setHeight(90);
+ break;
+ case 3:
+ propertyValue = "333";
+ break;
+ case 4:
+ propertyValue = "144411";
+ break;
+ default:
+ }
+ cells.add(new Cell(num, index++).setValue(propertyValue == null ? "" : propertyValue.toString()));
+ row.setCells(cells);
+ }
+ }
+
+ WebUtil.writeExcelTest(workBook, "多数据图测试导出".concat(String.valueOf(UUID.randomUUID())).concat(".xlsx"), TEMP_PATH);
+ }
+
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220110.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220110.java
new file mode 100644
index 0000000000000000000000000000000000000000..410f935bd684f6f35e3da61cc31dba0bc0d5c784
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220110.java
@@ -0,0 +1,75 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * 导出excel示例
+ *
+ * @author MinWeikai
+ * @date 2022-01-10 10:08:03
+ */
+@Ignore
+public class ExportExample_20220110 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ sheet.addCellStyle(new CellStyle(0, "66cc66"));
+ UserPicture userPicture;
+ for (int r = 0; r < 101; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ // 导出本地单张图片
+ userPicture.setPicture(IMG_PATH_1);
+ // 导出url单张图片
+ userPicture.setHeaderPicture(getUrl());
+ // 导出本地图片集合
+ userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ // 导出url图片集合
+ userPicture.setUrlPictures(getUrls(5));
+ sheet.createRow(userPicture);
+ }
+ WebUtil.writeExcelTest(workBook, "ExportExample_20220110_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+ @Test
+ public void export1() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ sheet.addCellStyle(new CellStyle(0, "66cc66"));
+ List list = new ArrayList<>();
+ UserPicture userPicture;
+ for (int r = 0; r < 101; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ // 导出本地单张图片
+ userPicture.setPicture(IMG_PATH_1);
+ // 导出url单张图片
+ userPicture.setHeaderPicture(getUrl());
+ // 导出本地图片集合
+ userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ // 导出url图片集合
+ userPicture.setUrlPictures(getUrls(5));
+ list.add(userPicture);
+ }
+ sheet.write(UserPicture.class).createRow(list);
+ WebUtil.writeExcelTest(workBook, "ExportExample_20220110_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220127.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220127.java
new file mode 100644
index 0000000000000000000000000000000000000000..b28f929fab33ba8236301eaae27c348ca5bee037
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220127.java
@@ -0,0 +1,71 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Font;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * 导出excel示例
+ * 字体设置
+ * @author MinWeikai
+ * @date 2022-01-10 10:08:03
+ */
+@Ignore
+public class ExportExample_20220127 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ // 给第一行加上背景色和字体配置
+ CellStyle cellStyle = new CellStyle(0, "F0F0F0");
+ Font font = Font.build()
+ .setFontName("黑体")
+ .setFontHeightInPoints((short) 15)
+ .setColor("FF4040")
+ .setBoldWeight(true);
+ cellStyle.setFont(font);
+ sheet.addCellStyle(cellStyle);
+
+ // 给第三行字体放大到18
+ CellStyle cellStyle1 = new CellStyle();
+ Font font1 = new Font();
+ font1.setFontHeightInPoints((short) 18);
+ cellStyle1.setRowNumber(2);
+ cellStyle1.setFont(font1);
+ sheet.addCellStyle(cellStyle1);
+
+ // 给第五行加上背景色
+ sheet.addCellStyle(new CellStyle(4, "AB82FF"));
+
+ List list = new ArrayList<>();
+ UserPicture userPicture;
+ for (int r = 0; r < 5; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ // 导出本地单张图片
+ userPicture.setPicture(IMG_PATH_1);
+ // 导出url单张图片
+ userPicture.setHeaderPicture(getUrl());
+ // 导出本地图片集合
+ userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ // 导出url图片集合
+ userPicture.setUrlPictures(getUrls(5));
+ list.add(userPicture);
+ }
+ sheet.write(UserPicture.class).createRow(list);
+ WebUtil.writeExcelTest(workBook, "ExportExample_20220127_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220128.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220128.java
new file mode 100644
index 0000000000000000000000000000000000000000..6331102bd642df5636701036b8a9d6f1ba579689
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220128.java
@@ -0,0 +1,72 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.*;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * 导出excel示例
+ * 字体设置|合并标题
+ *
+ * @author MinWeikai
+ * @date 2022-01-10 10:08:03
+ */
+@Ignore
+public class ExportExample_20220128 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+
+ // 标题样式
+ CellStyle cellStyle = new CellStyle("F0F0F0");
+ Font font = Font.build()
+ .setFontName("黑体")
+ .setFontHeightInPoints((short) 15)
+ .setBoldWeight(true);
+ cellStyle.setFont(font);
+
+ // 标题信息
+ sheet.createRow(0)
+ .addCell(new Cell(0, "测试标题"))
+ .setCellStyle(cellStyle)
+ .setHeight(30);
+ sheet.addMergeCell(new MergeCell(0, 0, 0, 6));
+
+ // 表头样式
+ CellStyle cellStyle1 = new CellStyle(1, "66CC66");
+ Font font1 = Font.build()
+ .setFontHeightInPoints((short) 13)
+ .setBoldWeight(true);
+ cellStyle1.setFont(font1);
+ sheet.addCellStyle(cellStyle1);
+
+ List list = new ArrayList<>();
+ UserPicture userPicture;
+ for (int r = 0; r < 5; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ // 导出本地单张图片
+ userPicture.setPicture(IMG_PATH_1);
+ // 导出url单张图片
+ userPicture.setHeaderPicture(getUrl());
+ // 导出本地图片集合
+ userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ // 导出url图片集合
+ userPicture.setUrlPictures(getUrls(5));
+ list.add(userPicture);
+ }
+ sheet.startRow(1).write(UserPicture.class).createRow(list);
+ WebUtil.writeExcelTest(workBook, "ExportExample_20220128_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220208.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220208.java
new file mode 100644
index 0000000000000000000000000000000000000000..249aa9dabb827c6accbf4fd85acf26e5922f496e
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20220208.java
@@ -0,0 +1,66 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.BizExcelRel;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.pojo.Student;
+import com.ibiz.excel.picture.support.processor.ExcelTableProcessor;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 动态配置表头excel导出
+ *
+ * @author MinWeikai
+ * @date 2022/2/8 14:49
+ */
+public class ExportExample_20220208 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ // 模拟需要导出的数据集合
+ List students = new ArrayList<>();
+ students.add(new Student("李四", 16, null, null, 0));
+ students.add(new Student("张三", 17, null, getPictures(5), 1));
+ students.add(new Student("王五", 15, IMG_PATH_1, null, 2));
+
+ // 配置导出excel的表头、顺序、对应导出的数据集合的字段、是否是图片、单元格宽度等
+ List excels = new ArrayList<>();
+ excels.add(new BizExcelRel("姓名", "name", 2));
+ excels.add(new BizExcelRel("年龄", "age", 3));
+ excels.add(new BizExcelRel("表现", "performance", 4));
+ excels.add(new BizExcelRel("头像", "headPicture", 5, true, 20));
+ excels.add(new BizExcelRel("相册", "album", 6, true));
+
+ // 创建excel
+ Workbook workBook = Workbook.getInstance(100);
+ Sheet sheet = workBook.createSheet("测试");
+ // 创建样式
+ CellStyle cellStyle = new CellStyle(0, "F0F0F0");
+ // 创建数据字典
+ Map performanceMap = new HashMap<>();
+ performanceMap.put("0", "一般");
+ performanceMap.put("1", "良好");
+ performanceMap.put("2", "优秀");
+
+ // 构建sheet
+ ExcelTableProcessor.sheet(sheet)
+ // 添加样式
+ .addCellStyle(cellStyle)
+ // 添加对应属性字段的数据字典
+ .registryEnumMap("performance", performanceMap)
+ // 构建excel
+ .buildExcel(excels, students);
+
+ WebUtil.writeExcelTest(workBook, "ExportExample_20220208_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20221219.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20221219.java
new file mode 100644
index 0000000000000000000000000000000000000000..30afbedfe841f410490c59179f3b82f6a89a4ec1
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20221219.java
@@ -0,0 +1,71 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.*;
+import com.ibiz.excel.picture.support.pojo.Student;
+import com.ibiz.excel.picture.support.processor.ExcelTableProcessor;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author MinWeikai
+ * @date 2022-12-19 15:15:44
+ * @description bug https://gitee.com/mwk719/excel-batch-picture-support/issues/I669N5 测试
+ */
+public class ExportExample_20221219 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ // 模拟需要导出的数据集合
+ List students = new ArrayList<>();
+ students.add(new Student("李四", 16, null, null, 0));
+ students.add(new Student("张三", 17, null, getPictures(5), 1));
+ students.add(new Student("王五", 15, IMG_PATH_1, null, 2));
+
+ // 配置导出excel的表头、顺序、对应导出的数据集合的字段、是否是图片、单元格宽度等
+ List excels = new ArrayList<>();
+ for (int i = 0; i < 31; i++) {
+ int orderNo = 2 + i;
+ // 给第5列设置为图片
+ if(orderNo == 5){
+ excels.add(new BizExcelRel("相册", "album", orderNo, true));
+ }else {
+ excels.add(new BizExcelRel("姓名" + i, "name", orderNo));
+ }
+ }
+
+
+ // 创建excel
+ Workbook workBook = Workbook.getInstance(100);
+ Sheet sheet = workBook.createSheet("测试");
+
+ //要进行合并的列
+ sheet.addMergeCell(new MergeCell(0, 0, 0, 2));
+
+ // 创建样式
+ CellStyle cellStyle = new CellStyle(0, "F0F0F0");
+ // 创建数据字典
+ Map performanceMap = new HashMap<>();
+ performanceMap.put("0", "一般");
+ performanceMap.put("1", "良好");
+ performanceMap.put("2", "优秀");
+
+ // 构建sheet
+ ExcelTableProcessor.sheet(sheet)
+ // 添加样式
+ .addCellStyle(cellStyle)
+ // 添加对应属性字段的数据字典
+ .registryEnumMap("performance", performanceMap)
+ // 构建excel
+ .buildExcel(excels, students);
+
+ WebUtil.writeExcelTest(workBook, "ExportExample_20221219_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230110.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230110.java
new file mode 100644
index 0000000000000000000000000000000000000000..eba662776ed69b9c4a1df73bb7ad1cff26af6596
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230110.java
@@ -0,0 +1,100 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.*;
+import com.ibiz.excel.picture.support.model.style.Alignment;
+import com.ibiz.excel.picture.support.pojo.Student;
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.processor.ExcelTableProcessor;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.*;
+
+/**
+ * @author MinWeikai
+ * @date 2023-01-10 17:07:51
+ * @description 单个单元格添加样式示例
+ */
+@Ignore
+public class ExportExample_20230110 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ sheet.addCellStyle(new CellStyle(0, "66cc66"));
+ UserPicture userPicture;
+ for (int r = 0; r < 5; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ // 导出本地单张图片
+// userPicture.setPicture(IMG_PATH_1);
+ // 导出url单张图片
+ userPicture.setHeaderPicture(getUrl());
+ // 导出本地图片集合
+ userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ // 导出url图片集合
+ userPicture.setUrlPictures(getUrls(5));
+// sheet.createRow(userPicture);
+ sheet.createRow(userPicture).getCell(0).setCellStyle(new CellStyle("9F79EE"));
+ }
+ WebUtil.writeExcelTest(workBook, "ExportExample_20230110_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+ @Test
+ public void export1() {
+ // 模拟需要导出的数据集合
+ List students = new ArrayList<>();
+ students.add(new Student("李四qweqweqweqweqwe12312312321", 16, null, null, 0));
+ students.add(new Student("张三", 17, null, getPictures(5), 1));
+ students.add(new Student("王五", 15, IMG_PATH_1, null, 2));
+
+ // 配置导出excel的表头、顺序、对应导出的数据集合的字段、是否是图片、单元格宽度等
+ List excels = new ArrayList<>();
+ excels.add(new BizExcelRel("姓名", "name", 2));
+ excels.add(new BizExcelRel("年龄", "age", 3));
+ excels.add(new BizExcelRel("表现", "performance", 4));
+ excels.add(new BizExcelRel("头像", "headPicture", 5, true, 20));
+ excels.add(new BizExcelRel("相册", "album", 6, true));
+
+ // 设置对全局操作边框是否加粗
+ WorkbookConstant.setBorderBold(false);
+ WorkbookConstant.WRAP_TEXT = 1;
+ // 创建excel
+ Workbook workBook = Workbook.getInstance(100);
+ Sheet sheet = workBook.createSheet("测试");
+
+ //要进行合并的列
+ sheet.addMergeCell(new MergeCell(1, 0, 3, 0));
+ sheet.addMergeCell(new MergeCell(0, 1, 0, 3));
+ // 创建样式
+ List cellStyles = Arrays.asList(
+ new CellStyle(0, "66cc66"),
+ CellStyle.build().setColNumber(0).setRowNumber(1).setFgColorRgb("9F79EE").setAlignment(Alignment.build().setWrapText(1))
+ );
+
+ // 创建数据字典
+ Map performanceMap = new HashMap<>();
+ performanceMap.put("0", "一般");
+ performanceMap.put("1", "良好");
+ performanceMap.put("2", "优秀");
+
+ // 构建sheet
+ ExcelTableProcessor.sheet(sheet)
+ // 添加样式
+ .addCellStyle(cellStyles)
+ // 添加对应属性字段的数据字典
+ .registryEnumMap("performance", performanceMap)
+ // 构建excel
+ .buildExcel(excels, students);
+
+ WebUtil.writeExcelTest(workBook, "ExportExample_20230110_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230713.java b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230713.java
new file mode 100644
index 0000000000000000000000000000000000000000..48ab4291d3d4246319cf12e6935a3dfdddf2590f
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/example/ExportExample_20230713.java
@@ -0,0 +1,100 @@
+package com.ibiz.excel.picture.support.example;
+
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.constants.WorkbookConstant;
+import com.ibiz.excel.picture.support.model.*;
+import com.ibiz.excel.picture.support.model.style.Alignment;
+import com.ibiz.excel.picture.support.pojo.Student;
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.processor.ExcelTableProcessor;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.*;
+
+@Ignore
+public class ExportExample_20230713 extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance();
+ Sheet sheet = workBook.createSheet("测试");
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ sheet.addCellStyle(new CellStyle(0, "66cc66"));
+ UserPicture userPicture;
+ for (int r = 0; r < 5; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试哈哈哈啊哈哈啊哈测试哈哈哈啊哈哈啊哈-" + r);
+ // 导出本地单张图片
+ userPicture.setPicture(IMG_PATH_1);
+ // 导出url单张图片
+// userPicture.setHeaderPicture(getUrl());
+ // 导出本地图片集合
+// userPicture.setPictures(getPictures(new Random().nextInt(5)));
+ // 导出url图片集合
+// userPicture.setUrlPictures(getUrls(5));
+// sheet.createRow(userPicture);
+ sheet.createRow(userPicture).getCell(0).setCellStyle(CellStyle.build().setColNumber(1).setRowNumber(1).setFgColorRgb("9F79EE")
+ .setAlignment(Alignment.build().setWrapText(1)));
+ }
+ WebUtil.writeExcelTest(workBook, "ExportExample_20230713_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+ @Test
+ public void export1() {
+ // 模拟需要导出的数据集合
+ List students = new ArrayList<>();
+ students.add(new Student("李四qweqweqweqweqwe12312312321", 16, null, null, 0));
+ students.add(new Student("张三", 17, null, getPictures(5), 1));
+ students.add(new Student("王五", 15, IMG_PATH_1, null, 2));
+ students.add(new Student("王五u五五五五五五五五五五呀呀呀呀呀呀呀", 18, IMG_PATH_1, null, 0));
+
+ // 配置导出excel的表头、顺序、对应导出的数据集合的字段、是否是图片、单元格宽度等
+ List excels = new ArrayList<>();
+ excels.add(new BizExcelRel("姓名", "name", 2));
+ excels.add(new BizExcelRel("年龄", "age", 3));
+ excels.add(new BizExcelRel("表现", "performance", 4));
+ excels.add(new BizExcelRel("头像", "headPicture", 5, true, 20));
+ excels.add(new BizExcelRel("相册", "album", 6, true));
+
+ // 设置对全局操作边框是否加粗
+ WorkbookConstant.setBorderBold(false);
+ // 创建excel
+ Workbook workBook = Workbook.getInstance(100);
+ Sheet sheet = workBook.createSheet("测试");
+
+ //要进行合并的列
+ sheet.addMergeCell(new MergeCell(0, 0, 0, 2));
+
+ // 创建样式
+ List cellStyles = Arrays.asList(
+ new CellStyle(0, "66cc66")
+ , CellStyle.build().setColNumber(0).setRowNumber(1).setColLast(true).setFgColorRgb("FFEFDB")
+ // 表示自动换行,左对齐+底端对齐
+ .setAlignment(Alignment.build().setWrapText(1).setHorizontal(Alignment.LEFT).setVertical(Alignment.BOTTOM))
+ // 表示在excel中从第2列,第3行开始一直往下,该列都保持该样式背景色#9F79EE
+ , CellStyle.build().setColNumber(1).setRowNumber(2).setColLast(true).setFgColorRgb("9F79EE")
+ );
+
+ // 创建数据字典
+ Map performanceMap = new HashMap<>();
+ performanceMap.put("0", "一般");
+ performanceMap.put("1", "良好");
+ performanceMap.put("2", "优秀");
+
+ // 构建sheet
+ ExcelTableProcessor.sheet(sheet)
+ // 添加样式
+ .addCellStyle(cellStyles)
+ // 添加对应属性字段的数据字典
+ .registryEnumMap("performance", performanceMap)
+ // 构建excel
+ .buildExcel(excels, students);
+
+ WebUtil.writeExcelTest(workBook, "ExportExample_20230713_".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/pojo/Student.java b/src/test/java/com/ibiz/excel/picture/support/pojo/Student.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5468ca8a36a4c688c3ed4a31258bc8128e3a2ac
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/pojo/Student.java
@@ -0,0 +1,87 @@
+package com.ibiz.excel.picture.support.pojo;
+
+import com.ibiz.excel.picture.support.model.BizExcelPojoInterface;
+
+import java.util.List;
+
+/**
+ * @author MinWeikai
+ * @date 2022/2/9 9:21
+ */
+public class Student implements BizExcelPojoInterface {
+
+ public Student(String name, Integer age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public Student(String name, Integer age, String headPicture) {
+ this.name = name;
+ this.age = age;
+ this.headPicture = headPicture;
+ }
+
+ public Student(String name, Integer age, String headPicture, List album, Integer performance) {
+ this.name = name;
+ this.age = age;
+ this.headPicture = headPicture;
+ this.album = album;
+ this.performance = performance;
+ }
+
+ private String name;
+
+ private Integer age;
+
+ private String headPicture;
+
+ /**
+ * 相册
+ */
+ private List album;
+
+ /**
+ * 表现 0一般;1良好;2优秀
+ */
+ private Integer performance;
+
+ public Integer getPerformance() {
+ return performance;
+ }
+
+ public void setPerformance(Integer performance) {
+ this.performance = performance;
+ }
+
+ public List getAlbum() {
+ return album;
+ }
+
+ public void setAlbum(List album) {
+ this.album = album;
+ }
+
+ public String getHeadPicture() {
+ return headPicture;
+ }
+
+ public void setHeadPicture(String headPicture) {
+ this.headPicture = headPicture;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/User.java b/src/test/java/com/ibiz/excel/picture/support/pojo/User.java
similarity index 97%
rename from src/test/java/com/ibiz/excel/picture/support/User.java
rename to src/test/java/com/ibiz/excel/picture/support/pojo/User.java
index b1069aec1878f1b9e3778b910191e15640c45c27..a1be8a94dde1541ce34892dc9fe09607b7bde79c 100644
--- a/src/test/java/com/ibiz/excel/picture/support/User.java
+++ b/src/test/java/com/ibiz/excel/picture/support/pojo/User.java
@@ -1,4 +1,4 @@
-package com.ibiz.excel.picture.support;
+package com.ibiz.excel.picture.support.pojo;
import com.ibiz.excel.picture.support.annotation.ExportModel;
@@ -10,7 +10,7 @@ import java.util.StringJoiner;
*/
public class User {
- @ExportModel(title = "姓名", mergeMaster = true)
+ @ExportModel(sort = 0,title = "姓名", mergeMaster = true)
private String name;
@ExportModel(sort = 1, title = "年龄")
private Integer age;
@@ -163,4 +163,4 @@ public class User {
public void setPicture3(String picture3) {
this.picture3 = picture3;
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/com/ibiz/excel/picture/support/pojo/UserPicture.java b/src/test/java/com/ibiz/excel/picture/support/pojo/UserPicture.java
new file mode 100644
index 0000000000000000000000000000000000000000..de67a94f8d355ebc4fee98f6bc3fb51d55a8e47b
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/pojo/UserPicture.java
@@ -0,0 +1,104 @@
+package com.ibiz.excel.picture.support.pojo;
+
+import com.ibiz.excel.picture.support.annotation.ExportModel;
+import com.ibiz.excel.picture.support.constants.PictureSourceContent;
+
+import java.util.List;
+
+/**
+ * @auther 喻场
+ * @date 2020/7/813:41
+ */
+public class UserPicture {
+
+ public UserPicture() {
+ }
+
+ @ExportModel(sort = 0, title = "姓名")
+ private String name;
+ @ExportModel(sort = 1, title = "年龄")
+ private Integer age;
+ @ExportModel(sort = 3, title = "部门")
+ private String department;
+ @ExportModel(sort = 2, isPicture = true, title = "图片1")
+ private String picture;
+ @ExportModel(sort = 4, isPicture = true, title = "图片2", pictureSource = PictureSourceContent.WEB_URL)
+ private String headerPicture;
+ @ExportModel(sort = 5, isPicture = true, title = "本地多图片")
+ private List pictures;
+ @ExportModel(sort = 6, isPicture = true, title = "url多图片")
+ private List urlPictures;
+
+ private String address;
+
+ public UserPicture(String name, Integer age, String department, String picture) {
+ this.name = name;
+ this.age = age;
+ this.department = department;
+ this.picture = picture;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+
+ public String getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(String department) {
+ this.department = department;
+ }
+
+ public String getPicture() {
+ return picture;
+ }
+
+ public void setPicture(String picture) {
+ this.picture = picture;
+ }
+
+ public String getHeaderPicture() {
+ return headerPicture;
+ }
+
+ public void setHeaderPicture(String headerPicture) {
+ this.headerPicture = headerPicture;
+ }
+
+ public List getPictures() {
+ return pictures;
+ }
+
+ public void setPictures(List pictures) {
+ this.pictures = pictures;
+ }
+
+ public List getUrlPictures() {
+ return urlPictures;
+ }
+
+ public void setUrlPictures(List urlPictures) {
+ this.urlPictures = urlPictures;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+}
diff --git a/src/test/java/com/ibiz/excel/picture/support/simulation/SimulateRealBusinessExportExample.java b/src/test/java/com/ibiz/excel/picture/support/simulation/SimulateRealBusinessExportExample.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ba154d24e4a826c0a7b689e09a66eedec2d88f6
--- /dev/null
+++ b/src/test/java/com/ibiz/excel/picture/support/simulation/SimulateRealBusinessExportExample.java
@@ -0,0 +1,50 @@
+package com.ibiz.excel.picture.support.simulation;
+
+import com.ibiz.excel.picture.support.pojo.UserPicture;
+import com.ibiz.excel.picture.support.common.BaseJunitTest;
+import com.ibiz.excel.picture.support.model.CellStyle;
+import com.ibiz.excel.picture.support.model.Sheet;
+import com.ibiz.excel.picture.support.model.Workbook;
+import com.ibiz.excel.picture.support.util.WebUtil;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.Random;
+
+/**
+ * 模拟真实业务场景导出
+ *
+ * @author MinWeikai
+ * @date 2021-12-22 15:36:46
+ */
+@Ignore
+public class SimulateRealBusinessExportExample extends BaseJunitTest {
+
+ @Test
+ public void export() {
+ Workbook workBook = Workbook.getInstance(50);
+ Sheet sheet = workBook.createSheet("测试");
+ UserPicture userPicture;
+ for (int r = 0; r < 101; r++) {
+ userPicture = new UserPicture();
+ userPicture.setAge(15);
+ userPicture.setName("测试-" + r);
+ if(new Random().nextInt(10) > 5){
+ // 模拟场景1. 在业务数据集合中,有些数据没有图片,有图片时请传图片绝对路径,没有图片时则不设置值
+ userPicture.setPicture(IMG_PATH_1);
+ }
+ userPicture.setHeaderPicture(IMG_PATH_2);
+ if(new Random().nextInt(10) > 5){
+ // 模拟场景2. 在业务数据集合中,有些数据没有图片对应的图片集合,没有则不设置值
+ userPicture.setPictures(getPictures(new Random().nextInt(10)));
+ }
+ sheet.createRow(userPicture);
+ // 给标题行加上背景色,加颜色时,会对字体加粗
+ if (r == 0) {
+ sheet.getRow(r).setCellStyle(new CellStyle("66cc66"));
+ }
+ }
+ WebUtil.writeExcelTest(workBook, "模拟真实业务场景导出示例".concat(String.valueOf(System.currentTimeMillis())).concat(".xlsx"), TEMP_PATH);
+ }
+
+}
| | | | | | | | | | | |