首页 > 其他分享 >还在担心报表不好做?不用怕,试试这个方法

还在担心报表不好做?不用怕,试试这个方法

时间:2024-01-30 09:11:22浏览次数:27  
标签:getRange 报表 试试 worksheet 不用 baseRow setValue Scores data

前言

在各种业务场景中,我们经常需要生成各种报表,例如学校中的学生成绩表、商业场景中的销售单和发票单、测量检测场景中的检测报告等等。这些报表对于组织和管理数据非常重要,因为它们提供了直观、清晰的方式来展示和分析数据。

一般情况下,使用Excel设计和生成这些报表就可以,但是随着业务规模的扩大,需求也会逐渐由人工转变为电脑自动批量生成,这个时候再用Excel设计就非常慢了,因此今天小编为大家介绍一下如何使用编程语言来设计一个报表。

操作步骤

下图是一个简单的学生成绩表,以下表为例给大家介绍一下操作的具体步骤:

1. 抽象数据结构

首先按照报表中的字段(学号、姓名等)抽象对应的数据结构:

class Data {
    public String School;
    public int Grade;
    public int Class;
    public String PrintDate;
    public ArrayList<Score> Scores = new ArrayList<>();
}

class Score {
    public int SID;
    public String SName;
    public int Chinese;
    public int Math;
    public int English;

    public Score(int sid, String sName, int chinese, int math, int english) {
        this.SID = sid;
        this.SName = sName;
        this.Chinese = chinese;
        this.Math = math;
        this.English = english;
    }
}

2. 传数据

第二步小编将数据传入到第一步生成数据结构的Scores 队列中。

private static Data CreateData() {
    Data data = new Data();
    data.School = "高新第六小学";
    data.Grade = 1;
    data.Class = 2;
    data.PrintDate = "2023年1月5日";

    data.Scores.add(new Score(1, "李明", 98, 100, 96));
    data.Scores.add(new Score(2, "王芳", 96, 97, 98));
    data.Scores.add(new Score(3, "张锋", 99, 99, 95));
    data.Scores.add(new Score(4, "高明", 94, 96, 100));
    data.Scores.add(new Score(5, "沈梦", 90, 94, 93));
    data.Scores.add(new Score(6, "张菲", 93, 94, 95));
    data.Scores.add(new Score(7, "白洁", 95, 92, 94));
    data.Scores.add(new Score(8, "王鹏", 96, 97, 99));
    data.Scores.add(new Score(9, "刘玲", 96, 93, 94));
    data.Scores.add(new Score(10, "李丽", 94, 98, 99));
    return data;
}

3. 生成报表逻辑

生成数据之后,下面是编写生成一个报表的代码,该代码创建了一个工作簿并添加了一个工作表。除了添加数据外,还配置了报表所需的样式。

可以看到,该代码量不小且与业务高度相关。如果报表的样式或布局发生变化,就需要调整代码,这种情况下,维护成本会很高。

Data data = CreateData();

Workbook workbook = new Workbook();
IWorksheet worksheet = workbook.getWorksheets().get(0);

worksheet.getRange("A1").setValue(data.School);
worksheet.getRange("A3").setValue("年级");
worksheet.getRange("B3").setValue(data.Grade);
worksheet.getRange("D3").setValue("班级");
worksheet.getRange("E3").setValue(data.Class);

Object[] array = new Object[]{"学号", "姓名", "语文", "数学", "英语"};
worksheet.getRange("A5:E5").setValue(array);

worksheet.getRange("D7").setValue("打印日期");
worksheet.getRange("E7").setValue("2023年1月5日");

//报表样式
worksheet.getRange("A1:E1").setColumnWidthInPixel(140);
worksheet.getRange("1:2").setRowHeightInPixel(50);

worksheet.getRange("A1:E1").merge();
worksheet.getRange("A1").getFont().setSize(16);
worksheet.getRange("A1").setHorizontalAlignment(HorizontalAlignment.Center);

worksheet.getRange("B3,E3").getBorders().get(BordersIndex.EdgeBottom).setColor(Color.GetBlack());
worksheet.getRange("A3:E3,D7").setHorizontalAlignment(HorizontalAlignment.Center);

worksheet.getRange("E7").setHorizontalAlignment(HorizontalAlignment.Right);


int baseRow = 5;
int dataRowCount = data.Scores.size();
worksheet.getRange(5, 0, dataRowCount, 1).getEntireRow().insert(InsertShiftDirection.Down);
for (int i = 0; i < data.Scores.size(); i++) {
    worksheet.getRange(baseRow + i, 0).setValue(data.Scores.get(i).SName);
    worksheet.getRange(baseRow + i, 1).setValue(data.Scores.get(i).SID);
    worksheet.getRange(baseRow + i, 2).setValue(data.Scores.get(i).Chinese);
    worksheet.getRange(baseRow + i, 3).setValue(data.Scores.get(i).Math);
    worksheet.getRange(baseRow + i, 4).setValue(data.Scores.get(i).English);
}

worksheet.getRange("A5:E5").getInterior().setColor(Color.FromArgb(21, 96, 130));
worksheet.getRange("A5:E5").getFont().setColor(Color.GetWhite());
worksheet.getRange("A5:E5").setHorizontalAlignment(HorizontalAlignment.Center);

worksheet.getRange(baseRow, 0, dataRowCount, 5).getInterior().setColor(Color.FromArgb(192, 230, 245));
worksheet.getRange(baseRow - 1, 0, dataRowCount + 1, 5).getBorders().setColor(Color.FromArgb(68, 179, 225));
worksheet.getRange(baseRow - 1, 0, dataRowCount + 1, 2).setHorizontalAlignment(HorizontalAlignment.Center);

worksheet.getSheetView().setDisplayGridlines(false);

4. 通过模板简化生成报表逻辑代码

通过第三步的代码可以发现,许多样式,如字体、列宽、行高和颜色等都是相同的,但数据和布局却与业务密切相关,并随着报表而变化。为了解决上述问题,可以将报表抽象为一个Excel模板,并保留不变的内容,移除可变的内容,如下图所示:

这样小编就可以简化报表样式部分的代码,保留核心代码,如下所示:

Data data = CreateData();

Workbook workbook = new Workbook();
workbook.open("template.xlsx");
IWorksheet worksheet = workbook.getWorksheets().get(0);

worksheet.getRange("A1").setValue(data.School);
worksheet.getRange("B3").setValue(data.Grade);
worksheet.getRange("E3").setValue(data.Class);
worksheet.getRange("E8").setValue("2023年1月5日");

int baseRow = 5;
int dataRowCount = data.Scores.size();
worksheet.getRange(baseRow + 1, 0, dataRowCount - 1, 1).getEntireRow().insert(InsertShiftDirection.Down);
worksheet.getRange(baseRow, 0, 1, 5).copy(worksheet.getRange(baseRow + 1, 0, dataRowCount - 1, 5));
//循环给报表中的字段传值
for (int i = 0; i < data.Scores.size(); i++) {
    worksheet.getRange(baseRow + i, 0).setValue(data.Scores.get(i).SName);
    worksheet.getRange(baseRow + i, 1).setValue(data.Scores.get(i).SID);
    worksheet.getRange(baseRow + i, 2).setValue(data.Scores.get(i).Chinese);
    worksheet.getRange(baseRow + i, 3).setValue(data.Scores.get(i).Math);
    worksheet.getRange(baseRow + i, 4).setValue(data.Scores.get(i).English);
}

可以看到,剥离掉样式的代码,简化了很多。但是,布局的调整,尤其是需要根据数据量调整行列,还是没有做到完全的业务解耦。

5. 使用模板语言二次简化代码

为了进一步解决第四步中的问题,我们可以通过模板语言,将报表改造成模板文件,来彻底做到业务解耦。将业务需求留在模板文件中,大大降低了代码维护的成本。下面小编对第四步的模板进行一些改造,如下图所示:

可以看到,和第四步的模板相比,新的模板将字段(年龄、班级等)对应的值以参数值表示,以{{ds.School}}为例,模板语言由两个大括号组成,中间的字符串表示从名为ds的数据源中,将School字段填充至 C1 单元格中。

下面是使用报表语言后简化后的代码:

Workbook workbook = new Workbook();
workbook.open("template.xlsx");
workbook.addDataSource("ds",CreateData());
workbook.processTemplate();
workbook.save("reprot.xlsx");

展示效果:

总结

本文所用到的所有代码均来自葡萄城公司的服务端表格控件产品GcExcel。如果您想了解更多信息,可以参考这篇产品文档Demo 网站

扩展链接:

Redis从入门到实践

一节课带你搞懂数据库事务!

Chrome开发者工具使用教程

如何在Web应用中添加一个JavaScript Excel查看器

高性能渲染——详解HTML Canvas的优势与性能

标签:getRange,报表,试试,worksheet,不用,baseRow,setValue,Scores,data
From: https://www.cnblogs.com/powertoolsteam/p/17989804

相关文章

  • AI 绘画平台难开发,难变现?试试 Stable Diffusion API Serverless 版解决方案
    作者:王佳、江昱、筱姜StableDiffusion模型,已经成为AI行业从传统深度学习时代走向AIGC时代的标志性里程碑。越来越多的开发者借助stable-diffusion-webui(以下简称SDWebUI)能力进行AI绘画领域创业或者业务上新,获得高流量及商业价值,但是面对多客户、高并发的复杂场景,使用原......
  • 一个日常查询(报表、RFC、数据库表)的报表
    参考底表标准底表:TRDIR,TSTC,DD02L,DD02T,TFDIR,TFTIT.SAP标准底表表名描述TRDIRSystemTableTRDIRTSTCSAPTransactionCodesDD02LSAPTablesDD02TSAPDD:SAPTableTextsTFDIRFunctionModuleTFTITFunctionModuleShortTextRFC类其他......
  • API调试?试试Apipost
    你是否经常遇到接口开发过程中的各种问题?或许你曾为接口测试与调试的繁琐流程而烦恼。不要担心!今天我将向大家介绍一款功能强大、易于上手的接口测试工具——Apipost,并带你深入了解如何玩转它,轻松实现接口测试与调试。什么是Apipost?Apipost是一款API全生命周期管理平台,它提供了一系......
  • API调试?试试Apipost
    你是否经常遇到接口开发过程中的各种问题?或许你曾为接口测试与调试的繁琐流程而烦恼。不要担心!今天我将向大家介绍一款功能强大、易于上手的接口测试工具——Apipost,并带你深入了解如何玩转它,轻松实现接口测试与调试。什么是Apipost?Apipost是一款API全生命周期管理平台,它提供了......
  • 经典存储过程计算报表
       用单一存储过程计算报表,替换以前用java+Hibernate的给客户做的计算报表,客户每次用后系统慢等各种问题,该存储过程是当时花了近一周时间,看以前的逻辑,修改的,一开始觉得很简单,但越做越复杂,中途都想放弃,最终坚持下来,完整的替换了以前程序单条SQL计算,保留下来脚本,做纪念!IFEXIS......
  • 想在IDEA中调试API?试试这款,堪比postman
    Postman是大家最常用的API调试工具,那么有没有一种方法可以不用手动写入接口到Postman,即可进行接口调试操作?今天给大家推荐一款IDEA插件:ApipostHelper,写完代码就可以调试接口并一键生成接口文档!而且还可以根据已有的方法帮助您快速生成url和params。更重要的是他完全免费!Apipost......
  • 想在IDEA中调试API?试试这款,堪比postman
    Postman是大家最常用的API调试工具,那么有没有一种方法可以不用手动写入接口到Postman,即可进行接口调试操作?今天给大家推荐一款IDEA插件:ApipostHelper,写完代码就可以调试接口并一键生成接口文档!而且还可以根据已有的方法帮助您快速生成url和params。更重要的是他完全免费!Apipos......
  • Asp.net Webapi 的 Post 方法不能把参数加到 URL 中?试试这样写
    Restful风格的api虽然规范了四个方法(Get、Post、Put、Delete)用于数据的查询、增加、修改和删除,但在实际应用中,还是会有很多公司只使用了Get和Post两个方法,查询数据使用Get方法,其它业务操作使用Post方法(为什么会有情况,以后可以写一篇文章讨论一下_),但是Post方法一般......
  • FICO 三大报表运算维护表计算规则(表里维护行次的)
    1+2+3"内表整理科目报表项目汇总后计算公式1+2+3DATA:lv_strTYPEstring,lv_str1TYPEstring,lt_numTYPETABLEOFstring,lt_signTYPETABLEOFstring,lv_indexTYPECHAR4,lv_iTYPEi,lv_sumTYPEpDECIMALS3.......
  • acme.sh 签发证书如果提示 Error creating new account 试试这个解决方法
    24年1月18日用 acme.sh命令签发ssl证书,使用的--issue参数。acme.sh--issue--dnsdns_dp-dxxx.com-dwww.xxx.com--force会提示错误:Error,cannotgetdomaintoken"type":"dns-01","url":"https://acme.zerossl.com/v2/DV90/chall/-qe......