V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GrapeCityChina
V2EX  ›  推广

性能碾压 POI !利用模板语法快速生成 Excel 报表

  •  
  •   GrapeCityChina · 2020-07-10 16:11:36 +08:00 · 2567 次点击
    这是一个创建于 1627 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本期讲师:刘鹏 GcExcel 项目组,核心开发者

    Hello,大家好,本期葡萄城技术公开课,将由我来为大家带来《性能碾压 POI !利用模板语法快速生成 Excel 报表》的技术分享。

    本期课程,我们将借助服务端表格组件 GcExcel 的模板语法来完成 Excel 报表的生成,通过使用简单的语法标记,可以在不借助任何第三方组件的情况下,结合数据源,自动化地生成 Excel 模板文件。

    目前,GcExcel 可以生成的文件格式包括 XLSX 、PDF 、SSJSON 以及 HTML 。在公开课上,我将详细介绍 GcExcel 的模板功能,并教大家如何使用模板生成 Excel 报表,欢迎大家预约本期公开课,7 月 10 日 下午 14:00,期待您的准时收看。

    免费预约地址:https://live.vhall.com/120821085 image.png

    GcExcel 的模板功能简介

    GcExcel 的模板功能是一个高级功能,它提供了一组标记,使用户可以通过简单的语法,快速制作出一个 Excel 模板文件。然后,结合数据源,自动化地生成文件。

    要使用这个功能,请前往 GcExcel 产品官网下载试用最新版本。

    工作机制:

    1. 首先,我们需要准备一个模板文件(不限于 Excel 文件,也可以是 GcExcel 的模板实例)

    2. 有了模板文件,我们就可以结合数据源和 GcExcel 的模板引擎,实现自动化生成模板文件的功能,从而避免了手动输入大量数据的工作

    image.png

    GcExcel 的模板功能工作机制

    代码示例:

    
    //重要的 4 个步骤:
    
    //1\. 打开模板文件(.xlsx)
    
    //2\. 添加并命名数据源
    
    //3\. 处理模板,调用接口 IWorkbook.processTemplate()
    
    //4\. 保存已处理的文件
    
    IWorkbook workbook = new Workbook();
    
    workbook.open("template.xlsx"); //打开模板文件
    
    workbook.addDataSource("ds", *getData());* //添加并命名数据源
    
    workbook.processTemplate(); //处理模板
    
    workbook.save("result.xlsx");//导出处理后的文件
    
    

    模板样例:

    · Tablix 报告:该模板主要用于设计复杂表头样式,如行和列标题中存在多行、表头中存在小计行等。

    image.png

    · 员工缺勤计划:该模板使用了条件格式,它通过一个工作表名称,在单独的工作表中显示每个月的数据。

    image.png

    · 商品详情:该模板使用了模板属性 "image=true",即在模板处理后把图片字段的数据显示为图片。

    image.png

    注意:上述模板的展示效果并非 GcExcel 的功能,而是借助了 SpreadJS 纯前端表格控件进行可视化展示。

    使用模板生成 Excel 的基本概念和步骤详解

    通过上一节,相信大家已经对 GcExcel 的模板功能有了一定的认识,下面我会详细介绍如何使用模板来生成 Excel 报表。

    基本语法:

    1. GcExcel 中模板的定义:

    · 使用 {{ 和 }} 作为标记符,用以定义模板。

    · 在这两个标记符之间,用户可以定义数据字段、函数、表达式等。

    · GcExcel 提供了丰富的属性,用以配置并更改默认行为。

    1. 模板的用法:

    · 可以以字符串的形式,设置在 Excel 单元格中。

    · 目前,一个单元格只能使用一个模板。

    1. 代码示例:
    
     {{ds.name}} {{ds.students.name}}
    
     {{=sum(ds.score)}}
    
     {{=ds.count*ds.price}}
    
    
    1. 模板属性

    · 定义:在 GcExcel 的模板中,可以用键值对的形式配置属性。

    · 用法:{{模板(属性名 1=属性值 1, 属性名 2=属性值 2, …)}}

    在模板尾部,使用一对圆括号作为标记, 可以在其中配置各种属性。

    属性用等于号(=)作为分隔符,以键值对的形式定义。多个属性之间用逗号分隔。

    · 示例:{{ds.name(Context=D5, Group=list)}}

    GcExcel 的模板属性过多,在本期公开课上就不一一讲解了,感兴趣的同学可以前往 GcExcel 产品官网的学习指南中了解更多。

    GcExcel 提供了非常丰富的模板类型,可以满足不同场景下的业务需要,常用的模板类型包括:数据模板、函数模板、表达式模板、公式模板、工作表模板和内联模板。

    模板类型:

    数据模板:用来从数据源提取纯数据的模板类型。

    · 用法:在模板标记符内,使用圆点(.)作为名称分隔符,指示数据访问路径:{{数据源名称.字段名}}

    · 示例:{{ds.name}}

    其中,ds 为数据源名称,是用户通过代码设置数据源时指定的; name 为数据库字段名,或自定义代码对象的属性名; image.png

    数据模板示例

    函数模板:该模板内置了 10 种统计函数:Sum, Count, Average, Max, Min, Product, StdDev, StdDevp, Var, Varp

    · 用法:在模板标记符内,以单个等号(=)开头。参数名为数据模板,或者数据模板在表格中的位置名称。目前,这些函数只支持单个参数,也就是说,只能对单个数据字段进行统计。如:{{=函数名(参数名)}}

    · 示例:

    {{=Sum(ds.score)}} 对数据 ds.score 进行求和;

    {{=Sum(A6)}} 对表格中 A6 单元格里的数据模板进行求和

    image.png

    函数模板示例

    表达式模板:该模板支持以下操作符组成的四则运算表达式:'+', '-', '*', '/' 和 '()'

    · 用法:在模板标记符内,以单个等于号(=)开头。表达式由操作符、数据字段、位置名称组成。如:{{=表达式}}

    · 示例:

    {{=ds.count*ds.price}}

    {{=A18+D18-G18}}

    {{=(A18+A20)*0.3}}

    image.png

    表达式模板示例

    公式模板:该模板经过 GcExcel 的处理后,对应单元格直接生成 Excel 公式,而不只是数值。

    · 用法:在模板标记符内,以两个等于号(==)开头。经公式模板处理后,公式中的单元格引用,也会根据最终结果进行调整。可以支持任意 Excel 公式。如:{{==Excel 公式}}

    · 示例:{{==SUM(C15, D15)}}

    image.png

    公式模板示例

    工作表模板:在 Excel 工作表的表名中,使用模板。

    · **用法:**与数据模板相同。经模板处理后,GcExcel 将根据工作表模板对应的用户数据,为每条数据生成独立的 Excel 工作表。并且,每个工作表中仅展示与当前表名数据对应的内容。

    image.png

    工作表模板示例

    内联模板:在单元格内容中使用的模板,叫作内联模板。

    · 用法:你好, {{ds.name}} !通过内联模板,可以把模板嵌入到单元格的内容中,自定义展示结果。目前,一个单元格只能嵌入一个模板类型。

    · 示例:销售总额:{{=SUM(C15)}} 万元

    基础概念:

    这部分主要会讲解制作模板文件时需要注意的一些重要概念,如单元格扩展、上下文和区域上下文。

    单元格扩展:一个模板单元格,在处理完成后,会扩展为多个单元格。

    · 扩展方向: 可以使用属性 E(extension)来为模板配置扩展方向,例如:{{ds.name(E=H)}}

    · 扩展方向分为:

    • 垂直扩展:从上到下扩展,记作 V(vertical);

    • 水平扩展:从左到右扩展,记作 H(horizontal);

    · 注意:一个模板只能有一种扩展方向,默认为垂直扩展。

    · 单元格扩展示例:

    image.png

    image.png

    image.png

    上下文:一个模板在数据处理过程中,所要参考的对象,我们称之为它的上下文.就像在语文阅读理解中,要确定一个词语的具体含义,需要参考它所处位置前后语句一样。在模板文件中,两个相邻模板单元格之间,会默认形成一种分组与过滤的关系,我们称之为模板之间的上下文关系(Context)。当前模板单元格在处理后的最终结果,需要参考它所属的上下文模板来决定。

    image.png

    · 上下文单元格:一个模板单元格,作为其他模板的上下文时,被称为上下文单元格。一个上下文单元格,根据其扩展方向的不同,又被称为水平上下文和垂直上下文。

    o 水平上下文单元格,通常位于其他单元格的上边;

    o 垂直上下文单元格,通常位于其他单元格的左边;

    o 一个模板最多可以拥有一个水平上下文和一个垂直上下文。

    · 上下文单元格示例:

    o A2 模板受其水平上下文模板 A1 的影响,在水平方向进行了分组。

    o A2 模板的数据,则在各组内,默认按照垂直方向扩展显示。

    image.png

    · 默认上下文:由 GcExcel 模板引擎自动识别各个模板之间的上下文关系。

    o 识别规则:相邻的左边单元格为模板单元格并且扩展类型(Expansion)是 Vertical,则选中作为当前单元格的上下文节点;相邻的上边单元格为模板单元格并且扩展类型(Expansion)是 Horizontal,则选中作为当前单元格的上下文节点;非相邻模板之间不产生默认上下文关系。如果有需要,用户必须通过 Context 属性显式指定。

    o 条件:位置和扩展类型两个条件,缺一不可。

    o 示例:

    image.png

    · 上下文属性:可以通过属性 C(context) 来主动指定一个模板的上下文,常见的有以下几种设置方式:

    • 无:(C=None)。即没有上下文,当前模板独立扩展。

    image.png

    • 默认:用户不指定上下文属性, 由模板引擎自动识别上下文。

    image.png

    • 自定义: 用户主动指定当前模板的上下文,可以是数据字段或单元格位置。

    image.png

    · 示例:

    • 一个上下文: (C=A15) (C=ds.Team)

    • 两个上下文: (C=A3*B2) (C=ds.Team*ds.City)

    • 两个上下文之间需要用星号(*)分隔。

    • 目前不支持两个以上的上下文。

    区域上下文:有些场景下,存在大量模板的上下文是相同的情况,此时通过 Context 属性逐个设置,会非常繁琐。因此,GcExcel 推出了区域上下文的功能,可以使用 R(range) 属性,为一个模板单元格设置一个区域值,该模板称为区域上下文模板。如:{{ds.Team(R=A5:G10)}}

    在该区域内,所有单元格都会被视作模板。并且,区域内任何的一个模板如果既没有显式设置上下文,又无法找到默认上下文,则它会使用区域上下文作为其上下文模板。

    · 区域值:由冒号(:)分隔的两个单元格所形成的矩形区域。(下图中的所有元素:数据、样式等都应该以人员名称作为上下文。)

    image.png

    image.png

    样式设置:

    · 单元格样式:模板的样式可以通过 Excel 的单元格样式系统进行设置,样式可以作用到相应模板的每一条数据上。

    · 示例:

    image.png

    image.png

    模板数据源:

    代码示例:

    
    //步骤:
    
    //1\. 打开模板文件(.xlsx)
    
    //2\. 添加并命名数据源
    
    //3\. 处理模板,调用接口 IWorkbook.processTemplate()
    
    //4\. 保存已处理的文件
    
    IWorkbook workbook = new Workbook();
    
    workbook.open("template.xlsx"); //打开模板文件
    
    workbook.addDataSource("ds", *getData());* //添加并命名数据源
    
    workbook.processTemplate(); //处理模板
    
    workbook.save("result.xlsx");//导出处理后的文件
    
    

    自定义对象: 用户通过代码,定义和创建的数据对象。把对象添加为数据源后,可以将相应的属性名,作为数据模板的名称来使用。如:ds.name

    对于嵌套对象,可以用点号(.)组成一个链式访问路径。如:ds.student.father.name

    1. 自定义对象
    
    public class SalesData{
    
     public List<SalesRecord> sales;
    
    }
    
     public class SalesRecord{
    
     public String area;
    
     public String city;
    
     public String category;
    
     public String name;
    
     public double revenue;
    
    }
    
    
    1. 数据源配置
    
    SalesData datasource = new SalesData();
    
    … //设置数据
    
    … //设置数据
    
     //添加数据源
    
    workbook.addDataSource("ds", datasource);
    
    
    1. 数据源使用
    
    {{ds.sales.category}}
    {{ds.sales.name}}
    
    {{ds.sales.revenue}}
    
    

    变量:用户通过代码定义的变量,可作为单独的数据源,添加至模板中。

    · 示例代码:

    
    //定义变量
    
    String className = "一年级三班";
    
    int [] records=new int[30];
    
    List<String> students = new ArrayList<String>();
    
     //添加数据源
    
    workbook.addDataSource("className", className);
    
    workbook.addDataSource("records",  records);
    
    workbook.addDataSource("students",  students);
    
    //引用
    
    {{className}}
    
    {{records}}
    
    

    数据库对象:

    GcExcel 支持将数据库的结果集,作为数据源使用:

    • Java 语言,支持的是 java.sql.ResultSet ;

    • .Net 语言,支持的是 DataTable ;

    注意:用户需要自己建立数据库链接,并将数据读取至对应的结果集,然后作为数据源,添加到模板中。

    数据库表中的字段名,即列名,可以作为数据模板的字段名称。

    · 示例代码:

    
    //获取数据库结果
    
    java.sql.ResultSet datasource = new GcMockResultSet(…);
    
     //添加数据源
    
    workbook.addDataSource("ds",  datasource);
    
    //引用
    
    {{ds.Category}}
    
    {{ds.City}}
    
    

    JSON 文件:

    用户可以使用 JSON 文件作为数据源。在此之前,用户需要把 JSON 文件读取并序列化成自定义对象,而后作为数据源使用。事实上,任何可以序列化的数据,都可以用这种方式,转换成模板数据源。如:XML 文件,csv 文件等。

    · 示例代码:

    
    //从 JSON 文件获取数据
    
    InputStreamReader reader = new InputStreamReader(this.getResourceStream("Template_FamilyInfo.json"));
    
    Gson gson = new Gson();
    
    //数据序列化
    
    StudentInfos datasource = gson.fromJson(reader, StudentInfos.class);
    
     //添加数据源
    
    workbook.addDataSource("ds", datasource);
    
    

    经典模板展示

    结果文件: image.png

    左表头:

    image.png

    image.png

    上表头:

    image.png

    数据区域:

    image.png

    统计项目:

    image.png

    除了上述模板,GcExcel 还支持更多模板类型:如图片、图表、迷你图、条件格式等,可以帮助大家制作非常漂亮且内容丰富的统计表、帐目表和个人简历。

    更多精彩内容,欢迎前往我的公开课了解,7 月 10 日 下午 14:00,期待与大家不见不散。

    免费预约地址:https://live.vhall.com/120821085

    关于服务端表格组件 GcExcel

    GrapeCity Documents for Excel (简称:GcExcel )是一款基于 Java 平台的服务端高性能表格组件,可与 纯前端表格控件 SpreadJS 前后端兼容,无需依赖 POI 或第三方应用软件,在前端展示电子表格数据,在服务端批量创建、加载、编辑、打印、导入 /导出 Excel 文档,为您开发的应用程序提供在线文档的前后端数据同步、在线填报与服务端批量导出与打印,以及类 Excel 报表模板设计与服务端高性能处理等一整套 类 Excel 全栈解决方案

    8 条回复    2020-07-13 15:03:55 +08:00
    wysnylc
        1
    wysnylc  
       2020-07-10 16:44:15 +08:00
    隔几天就来个 Excel 推广,同一拨人?
    winterbells
        2
    winterbells  
       2020-07-10 16:50:36 +08:00 via Android
    @wysnylc 同一个人好像
    wysnylc
        3
    wysnylc  
       2020-07-10 17:17:12 +08:00
    @winterbells #2 还真是一个人
    Keyes
        4
    Keyes  
       2020-07-10 20:07:52 +08:00 via iPhone
    发推广节点的没毛病
    EminemW
        5
    EminemW  
       2020-07-13 13:21:33 +08:00
    导 excel 为什么不在前端导出
    GrapeCityChina
        6
    GrapeCityChina  
    OP
       2020-07-13 13:34:37 +08:00
    @EminemW 批量导出的时候,前端性能会有瓶颈,服务端则不会
    ffLoveJava
        7
    ffLoveJava  
       2020-07-13 14:54:04 +08:00
    @EminemW 前端怎么能把的数据导出 Excel ??
    Haulk
        8
    Haulk  
       2020-07-13 15:03:55 +08:00
    牛逼
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1000 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:28 · PVG 04:28 · LAX 12:28 · JFK 15:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.