好的室内设计网站,居民瑞app下载,电子商务网站建设的难点,扬中网站建设服务Excel Report
耗费了半个月的时间#xff0c;终于在元旦这三天把报表框架开发完成了#xff0c;使用该框架你可以非常方便的导出复杂的Excel报表。
项目开源地址#xff1a;
GiteeGithub
前言
不知道各位在使用POI开发报表导出过程中遇到过以下的情况#xff1a;
频繁…Excel Report
耗费了半个月的时间终于在元旦这三天把报表框架开发完成了使用该框架你可以非常方便的导出复杂的Excel报表。
项目开源地址
GiteeGithub
前言
不知道各位在使用POI开发报表导出过程中遇到过以下的情况
频繁的使用中间变量记录报表数据写到那个Cell中了。一个复杂的报表往往至少要几百行、甚至是上千行的代码。POI的api非常难用设置一个值甚至绘制一个图形要调用好多类为Cell设置Style非常麻烦还得时时担心style数量会不会超过excel的最大限制merge Cell的时候提心吊胆的得谨慎小心的计算应该merge的cell范围
等等等等上面的这些内容我估计频繁开发复杂报表的同学应该非常熟悉这些还不是最痛苦的最痛苦的是遇到那种报表修改的情况假如某一个地方要加一列某个地方要合并一个列就必须把这成百上千的代码逻辑再次梳理一遍因为所有的cell位置都是相关的加了一列就必须把相关的cell位置也更新才可以。
复杂报表框架 Excel-Report
鉴于上面这种复杂报表的导出问题花了半个月的时间开发了一个复杂报表导出框架。它可以让我们像设计UI界面那样简单。
框架的特点
几乎完全屏蔽POI操作提供类UI框架的操作接口、定义报表非常简单提供模板文件定义类似于各种模板框架支持SPEL表达式的模板定义提供类似于 Themleaf 的 If, For 标签更方便定义模板自动计算组件位置简化CellStyle设置支持各种不同类型的组件例如TextList、ImageLink、Table、Chart…
适合做什么
比较复杂的各种嵌套的报表经常有可能会变化的报表单元格样式比较多的报表
不适合做什么
大数据量的数据导出 因为该框架是基于模板的报表生成框架也就意味着要想让表达式工作就需要把数据加载到内存中才可以所以大数据量的数据导出不适合用这个框架去做。非常简单的报表 比如一个报表可能就一个table一个list这种方式用框架反而可能适得其反阿里的easyexcel导出这类的报表更简单。
下面看看使用这个框架之后将会怎么简化报表的导出
引入依赖
dependencygroupIdio.github.mengfly/groupIdartifactIdexcel-report/artifactIdversion1.0.0/version
/dependency定义报表组件Java代码方式
框架提供了类似的UI编程的方式如果大家有接触过UI框架那么对这些操作应该比较熟悉。
// 垂直布局
VLayout layout new VLayout();layout.addItem(new TextComponent(new Size(10, 5), Test(width10, height5)));
// 添加一个横向布局
final HLayout hLayout layout.addItem(new HLayout());final TextComponent item new TextComponent(new Size(3, 1), Test(width3));
// 设置样式
item.addStyle(CellStyles.fontColor, CellStyles.createColor(0xff0000));
item.addStyle(CellStyles.fontBold, true);
item.addStyle(CellStyles.fontName, 楷体);hLayout.addItem(item);
hLayout.addItem(new TextComponent(new Size(5, 1), Test(width5)));这样就定义好了一个非常简单的组件。
下面可以通过一下代码导出excel
ExcelReport report new ExcelReport();
report.exportSheet(sheet1, layout, SheetStyles.DEFAULT_STYLE);
report.save(new File(test.xlsx);这样就生成了一个自定义布局的Excel。
定义报表组件模板方式、推荐
定义模板
首先编辑一个报表模板只需要引入对应的命名空间就会有输入提示如下
以下为实例
具体的模板实例可以参考模板文件
?xml version1.0 encodingUTF-8 ?
templatexmlnshttp://mengfly.github.io/excel-report/1.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://mengfly.github.io/excel-report/1.0.0 https://mengfly.github.io/xsd/excel-report-1.0.0.xsdnametestImagedescription测试模板version1.0authorMengFlycreateAt2023-12-26!-- 定义模板参数该参数无特殊意义只是为了统一放在这里方便对模板内的参数统一展示方便了解模板参数数据 --parametersparameter idparameter name参数名称//parameters!-- Sheet 页参数一个模板文件对应一个sheet页 --sheetStyleautobreakstrue/autobreaks!-- ... --/sheetStylestyles!-- 定义Cell样式表可以在下面的组件中引用 --style idtestStyle/stylestyle idtestStyle2/style/styles!-- 编写模板结构使用表达式传递数据 --containerVLayout styletestStyle testStyle2HLayout style{width:auto}Text text${value}//HLayout/VLayout/container
/template传递参数渲染模板
import io.github.mengfly.excel.report.excel.ExcelReport;public static void main(String[] args) {// 创建报表类ExcelReport report new ExcelReport();// 构建数据参数DataContext context new DataContext();context.put(image, TestDataUtil.getTestImageFile());context.put(tableData, TestDataUtil.getData(10));context.put(listData, TestDataUtil.getRandomStringList(9));// ...try (InputStream stream getClass().getClassLoader().getResourceAsStream(TestTemplate.xml)) {// 加载模板ReportTemplate template new ReportTemplate(stream);// 导出模板到Sheet页 一个ExcelReport 代表了一个Excel文件每次调用export就是在向里面添加一个Sheet页report.exportTemplate(template, FileUtil.mainName(templatePath), context);}// 存储文件report.save(new File(test-template.xlsx));
}
最终结果 应用示例
我在网上随便找了一个国家统计年鉴的数据表格我们以这个表格为例说明一下怎么使用该框架复现这么一个报表。 1. 分析报表结构
首先可以看到这张报表其实分为几个部分
最上面的Header部分 包括一个大的文档标题右下角有一个单位:人的字样中间的表头 这个表头是一个固定的表头可以非常简单Text罗列出来下方的数据项 很明显这个数据项是分组的可以看成一个空行一组数据然后下面是类似的结构比如全国是一组北京、天津、河北、山西、内蒙古是一组。
报表结构如下 2. 定义模板
了解了报表的结构之后就可以定义模板了我们一步一步定义
0. 顶级布局
首先这里的所有部分是一个垂直排布的所以顶级布局我们选择VLayout VLayout/VLayout1. 红色部分
红色部分其实是由两部分组成的上面一个大字体站13列一行
下面一个小字体站13列2行, 而且可以看到的是下方的单元格边框为粗线、深绿色因此我们定义他们的样式 !--无框线的样式--style idnoBorderwidthauto/widthalignHorizontalcenter/alignHorizontalborderBottomnone/borderBottomborderRightnone/borderRightborderLeftnone/borderLeftborderTopnone/borderTop/style!--文字位置在右上角 字体大小18--style idheaderStylefontHeight18/fontHeightfontBoldtrue/fontBoldalignVerticaltop/alignVertical/styleText size13,1 styleheaderStyle noBordertext1-3a 各地区分性别的户口登记地在外乡镇街道的人口状况(城市)/Text size13,2 styletagStyle text单位人/2. 绿色部分
绿色部分就是一个简单的HLayout和Vlayout组合的表头背景颜色淡蓝色有边框。 style idheaderBackgroundfillForegroundColor#99CCFF/fillForegroundColoralignHorizontalcenter/alignHorizontal/styleHLayout styleheaderBackgroundText size1,3 text地区/VLayoutText size6,1 text户口登记地/HLayoutText size3,1 text合计/Text size3,1 text本县(市、区)//HLayoutHLayoutText text合计/Text text男/Text text女/Text text小计/Text text男/Text text女//HLayout/VLayoutVLayoutText size6,1 text户口登记地/HLayoutText size3,1 text本省其他县(市、区)/Text size3,1 text省 外//HLayoutHLayoutText text小计/Text text男/Text text女/Text text小计/Text text男/Text text女//HLayout/VLayout/HLayout3. 黄色部分
黄色部分复杂一些我们需要使用变量表达式完成黄色部分每一部分其实都是两个部分组成的。 上方是一个空白行下方是一个table。我们使用下面的方式定义。
!--第一列的style背景颜色淡黄色、右边框--style idnameCellStylefillForegroundColor#FFFF99/fillForegroundColorborderTopnone/borderTopborderRightthin/borderRightborderBottomnone/borderBottomborderLeftnone/borderLeftalignHorizontaldistributed/alignHorizontal/style
!--使用SPEL表达式 遍历分组数据--
VLayout stylenoBorder foritem,index: ${data}!--空白行第一列淡蓝色--HLayoutText stylenameCellStyle text/Text text size12,1//HLayout!--table数据不显示header 并且在第一组数据的时候字体加粗也就是全国那个数据--Table dataList${item} headerVisiblefalse style{fontBold:${index0?true:false}}column idname name地区 dataStylenameCellStyle/column idall.sum name合计/column idall.man name男/column idall.women name女/column idlocal.sum name合计/column idlocal.man name男/column idlocal.women name女/column idlocalOther.sum name合计/column idlocalOther.man name男/column idlocalOther.women name女/column idother.sum name合计/column idother.man name男/column idother.women name女//Table/VLayout这样一个完整的报表模板就定义完了。
完整的模板文件地址 https://gitee.com/mengfly_p/excel-report/blob/master/src/test/resources/Example1Template.xml
3. 渲染数据
其实可以看到模板中定义的变量一定是要和渲染的数据结构一一对应的这其中的原理和 thymeleaf 一样他们都是通过表达式取的数据。
我们的数据也是按照数据组进行组织的如下 // 数据组ListListDataStat dataGroup;/*** 单行数据 */private static class DataStat {private String name;private DataItem all;private DataItem local;private DataItem localOther;private DataItem other;}/*** 小数据项*/public static class DataItem {private Long sum;private Long man;private Long women;}接下来我用模拟数据来进行数据的渲染
public static ListListDataStat getData() {ListListDataStat province new ArrayList();province.add(Collections.singletonList(DataStat.createRandom(all)));for (int i 0; i 5; i) {ListDataStat stats new ArrayList();for (int i1 0; i1 RandomUtil.randomInt(3, 8); i1) {stats.add(DataStat.createRandom(XXX));}province.add(stats);}return province;}public static void main(String[] args) throws IOException {DataContext context new DataContext();// 设置数据context.put(data, Example1.getData());ExcelReport report new ExcelReport();try (final InputStream resourceAsStream Example1.class.getClassLoader().getResourceAsStream(Example1Template.xml)) {// 加载模板ReportTemplate template new ReportTemplate(resourceAsStream);// 渲染数据report.exportTemplate(template, null, context);}report.save(new File(example1.xlsx));}4. 最终结果 可以看到几乎已经和原来的报表非常相似了。而且如果以后需要调整的话只需要调整模板就可以。