65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ActiveReportsJS 和 Node.js 构建响应式 Web 库存和发票应用

2020 年 9 月 11 日

CPOL

14分钟阅读

viewsIcon

16605

在本文中,我们提供了一种使用 GrapeCity 的 ActiveReportsJS Designer 构建月度销售报表的操作方法。

要开展今天的业务,您需要能够随时随地访问您的订单、库存和财务数据。为此,屏幕报表不仅需要灵活且交互性强,还需要支持各种屏幕分辨率。

使用 ActiveReportsJS,您可以构建具有高度交互式报表功能的响应式 Web 应用程序,该应用程序可在任何浏览器、桌面设备和移动设备上运行。

在本文中,我们将向您展示如何使用 Node.js 和 ActiveReportsJS 构建一个用于订单跟踪报表的响应式应用程序。该应用程序将允许您从月度订单量的表格或图表中向下钻取到单个订单和产品详细信息。

构建基于 Web 的销售报表

假设一位名为 ACME Inc. 的客户委托您构建一份销售报表。客户的要求附带了一个附件,那是真实报表的模型,看起来如下:

Node.js Web-Based Sales Report Output

为了创建上述企业级报表,GrapeCity 提供了 ActiveReportsJS Designer,这是一个直观的工具,可帮助您配置报表以获取数据并使用多种视觉元素类型(包括表格、条形图、饼图等)进行渲染。

ActiveReportsJS Designer 以特殊的 JSON 格式存储报表定义,并将它们保存在具有 **.rdlx-json** 扩展名的文件中。

使用 Windows、macOS 或 Linux 安装程序 安装 ActiveReportsJS

设计报表标题

要创建新报表,请在 Designer 中打开 **文件** 菜单。选择 **RDL** 选项(数据驱动报表的标准语言),然后将新报表另存为 **MonthlyOrders.rdlx-json**。

报表标题由一个包含徽标图像和标签的容器组成。请注意左侧的控件工具箱。

ActiveReportsJS Toolbox - Report Controls

您可以将报表控件从工具箱拖放到报表画布上。要创建带有图像和标题的标题,您需要一个容器来容纳这些控件。容器对于组合您希望一起移动的控件特别有用。

将一个容器控件拖放到报表顶部。

将一个图像控件拖放到容器中。图像可以从外部源(如 URL 或数据库)拉取,也可以嵌入。

在容器中添加一个文本框来显示标题文本。根据需要自定义标题字体、大小和颜色。

标题应如下所示

ActiveReportsJS Report Header

单击工具栏中的“资源管理器”图标。

在打开的控件树中,选择“报表”节点。属性面板将打开到右侧。在“属性”选项卡上,将报表边距大小更改为 1 厘米。

为报表创建标题。

Container  
    Background Color: #f1f1f1  
    Items:  
        Image  
            Source: #551e5f  
            #551e5f: FitProportional  
        Textbox  
            Value: "Monthly Orders"

您可以使用“资源管理器”来选择控件并查看它们的属性。

ActiveReportsJS Designer Explorer

在 Node.js 中定义数据访问

ActiveReportsJS Designer 通过两种类型的实体管理数据:数据源和数据集。

数据源作为到外部数据存储的连接,例如 URI、JSON 文件或可以嵌入到报表本身中的 JSON 文档。

数据集是中间元素,它从数据源获取数据并将其绑定到报表数据模型中的字段。您还可以定义计算字段,这些字段使用表达式转换源数据。然后,报表组件可以使用数据集字段。

您的报表将通过位于 HTTP 服务上的外部 API 访问数据,该 API 将以 JSON 格式返回结果。报表将根据该服务的“实时”数据显示各种订单信息。

要定义报表中对客户数据的访问,请先选择 **数据源** 选项卡。

Data Sources Tab

在选项卡上,单击 **添加**。

在打开的 **新建数据源** 对话框中,在 **名称** 字段中输入“Customers”。

Add New Data Source

要定义 Customers 数据源,请在 **内容 URI** 字段中输入某个 HTTP Rest 服务终结点,该终结点以 JSON 格式返回客户集合。

https://[some-api-service]/Customers

注意:此数据源仅为连接配置,尚未发出任何请求。

单击加号以使用 Customers 数据源连接添加新数据集。

Data Source Tab - Add Data Set

**编辑数据集** 对话框将打开。将新数据集命名为“Customers”。
Edit Data Set Dialog

修改 **查询** 字段值,使其读取

$.[*]

此字段是 JsonPath 表达式,用于从您定义的 URI 返回的 JSON 格式数据中推断报表字段。

单击 **验证** 按钮并展开 **绑定字段** 部分,以查看从数据集创建的报表字段。

Data Set Bound Fields

请注意,这些字段是根据数据源的 JSON 结果自动创建的。

现在创建新的 Products 数据源和相应的数据集。使用上述为 Customers 数据访问描述的过程。在 **内容 URI** 字段中,输入返回产品集合的终结点的 URI,例如:

https://[some-api-service]/Products

使用上述过程和以下字段值,创建 Orders 数据源和相应的数据集。

对于 **内容 URI**,使用返回订单及其订单项的集合的某个 HTTP Rest 服务终结点的 URL。

https://[some-api-service]/Orders

对于 **查询**,使用

$.value[*]

使用计算字段

有时,您需要将一个或多个源字段转换为新的计算字段,供报表使用。ActiveReportsJS 提供了一个 表达式语言,其中包含一套丰富的内置函数来满足此需求。

在此示例中,我们将 orderDate 字段转换为“月/年”格式。为此,您需要在自动绑定字段列表中添加自定义字段。

展开 **计算字段** 部分。

添加 MonthYear 字段。

将以下公式作为 MonthYear 字段的值输入:

=DateTime.Parse(Fields!orderDate.Value).ToString("MM/yyyy")

Data Set - Calculated Fields (MonthYear)

基于现有的 Orders 数据源创建新的 OrderDetails 数据集,但将 **查询** 字段值设为

$.value.[*].orderDetails[*]

请注意,OrderDetails 数据集不包含每项的总值字段。此值可能在报表中需要多次使用。因此,您要么必须在每次需要时计算此值,要么创建一个新的计算字段。后一种选择效率更高。

展开 **计算字段** 部分。

添加 Subtotal 字段。

将以下公式作为 Subtotal 字段的值输入:

=Round(100 * (Fields!unitPrice.Value - (Fields!unitPrice.Value*Fields!discount.Value))*Fields!quantity.Value) / 100.0

Data Set - Calculated Fields (Subtotal)

添加图表

以图形方式向用户呈现检索到的销售数据。

在报表顶部,紧挨着标题下方,添加一个图表控件。

Monthly Orders Report with Chart

修改图表以使用来自 OrderDetails 数据集的 data。插入后,图表将出现在“资源管理器”选项卡中,成为易于配置的元素树。

Report Explorer - Chart Elements

按如下方式定义图表属性:

元素 相关值
图表 数据集名称:“OrderDetails”
标题 标题:“按月销售额”
X 轴 标题:“月份”
Y 轴 标题:“销售额($)”
主要间隔 20,000
最小值 0
最大值 150,000
绘图 字段值:“=Fields!Subtotal.Value”
聚合:求和
类别:“=Lookup(Fields!orderId.Value, Fields!orderId.Value, Fields!MonthYear.Value, "Orders")”
类别排序表达式:“=Fields!orderDate.Value”
标签文本模板:“=Value Field Value”
工具提示模板:“=Value Field Value”

图表由一组条形组成,表示每月销售额。Y 轴值是根据 OrderDetails 数据集的 Subtotal 字段计算的。X 轴从 1 月到 12 月,按月显示。图表类别按 orderDate 字段的值排序。

单击 **预览** 以显示包含 OrderDetails 数据的图表。

Monthly Orders Report - Sales Volume By Month

添加表格

除了图表之外,我们还将创建月度订单量的表格视图。我们将新表格放置在图表下方。

默认情况下,新表格包含三列三行。您可以使用工具来调整表格大小、添加或删除行和列,以及定义多个页眉、页脚行等。

Table - Details Row

现在按如下方式配置表格:

元素
表格 名称:“tableMonths”
数据集名称:“Orders”

然后删除页眉和页脚行,因为它们不需要。

Table - Delete Row

然后合并详细信息行的单元格。
Table - Merge Cells

将合并的单元格命名为 txtMonth,并将其值设置为表达式 =MonthName(Month(Fields!orderDate.Value)) & “/” & Year(Fields!orderDate.Value)。

TextBox Table Cell - txtMonth

最后,您需要定义表格分组。

Table Grouping

将组的第一级设置为公式 =Year(Fields!orderDate.Value),第二级设置为 =Month(Fields!orderDate.Value)。

Table Group Details

新表格显示表格区域中的第一级数据。

Preview of Table with Grouping

要添加另一级别的数据,请修改 tableMonths 并添加新的详细信息行。

Add Detail Row to Table

增加新创建行的高度,然后在该行内创建一个名为 tableOrders 的新表格。

Add Table to New Detail Row

按如下方式配置新表格:

元素
表格 名称:“tableOrders”
数据集名称:“Orders”

然后删除页眉和页脚行,因为它们不需要。

接下来,合并详细信息行的单元格 1、2 和 3,并将合并单元格的值设置为表达式 ="Order ID: " & [orderId]。

单击 **预览** 以查看结果。

Preview of Table Grouping for Monthly Orders

请注意,tableOrders 在报表中处于第二级:它详细说明了特定月份下达的订单。

更多细节

现在显示订单总额。要显示每个订单的总金额,请在 tableOrders 中创建一个名为 tableOrderTotal 的新表格。

在当前 tableOrders 行下方创建一个新的详细信息行,并将新表格插入其中。

Table for Orders

按如下方式配置新表格:

元素
表格 名称:“tableOrderTotal” 数据集名称:“OrderDetails”

再次删除详细信息行和页脚行,因为它们不需要。

然后仅合并详细信息行的中心和右侧单元格。定义左侧单元格公式为“Total:”。将合并单元格的对齐方式配置为左对齐,格式配置为货币。然后定义合并单元格公式为 =SUM(Fields!Subtotal.Value)。

Table Header (Total)

现在,在“资源管理器”中选择 tableOrderTotal 表格并展开 Filters 属性。

Table Filters Property

单击 Add Item 并添加具有以下字段的新过滤器条件:

  1. 筛选器表达式:“=Fields!orderId.Value”
  2. 运算符:“等于”
  3. 值:“=Fields!orderId.Value”

Table Filter Properties

如我们所见,新的 tableOrderTotals 表格基于 OrderDetails 数据集。总值是通过按 tableOrder 行的订单 ID 过滤订单详细信息,并对 Subtotal 字段值求和来获得的。

单击 **预览** 并查看结果。

Table Preview of Grouped Monthly Orders and Totals

最后,让我们创建一个代表订单项的表格。

在 tableOrders 中创建一个新的详细信息行,然后在该行内创建 tableOrderDetails 表格。按如下方式配置表格:

元素
表格 名称:“tableOrderDetails”
数据集名称:“OrderDetails”
页眉行 列标签: 1. "Item" 2. "Qty" 3. "Unit Price" 4. "Discount" 5. "Discounted Price" 6. "Total Price"
详细信息行 单元格 1 公式:“=Lookup([productId], [productId], [productName], "Products")”
单元格 2 公式:“=[quantity]”
单元格 3 公式:“=[unitPrice]”
单元格 4 公式:“=[discount]”
单元格 5 公式:“=[unitPrice] - ([unitPrice]*[discount])”
单元格 6 公式:“=[Subtotal]”
页脚行 单元格 1 公式:“总发票金额:”
单元格 2 公式:“=SUM(([unitPrice] - ([unitPrice][discount]))*[quantity])”
Filter 筛选器表达式:“=Fields!orderId.Value”
运算符:等于
值:“=Fields!orderId.Value”

此表格将有 6 列。添加新列,然后按如下方式定义它们的页眉行标签:

  1. “项目”
  2. “数量”
  3. “单价”
  4. “折扣”
  5. “折扣价”
  6. “总价”

Table Header Row - Column Headers

对于行详细信息,配置单元格公式以显示订单项。

  1. 单元格 1 公式:“=Lookup([productId], [productId], [productName], "Products")”
  2. 单元格 2 公式:“=[quantity]”
  3. 单元格 3 公式:“=[unitPrice]”
  4. 单元格 4 公式:“=[discount]”
  5. 单元格 5 公式:“=[unitPrice] - ([unitPrice]*[discount])”
  6. 单元格 6 公式:“=[Subtotal]”

Table Details Row - cell values

现在,配置页脚行以表示订单摘要。合并最后两个单元格,然后按如下方式定义它们的公式:

  1. 单元格 1 公式:“总发票金额:”
  2. 单元格 2 公式:“=SUM(([unitPrice] - ([unitPrice]*[discount]))*[quantity])”

Table Footer Row - Total Invoice Value

最后,您必须在 OrderDetails 表格和来自 Orders 表格的数据之间创建关系。在“资源管理器”中选择 tableOrderDetails 表格并展开 Filters 属性。

Filters for TableOrderDetails

单击 Add Item 并添加具有以下字段的新过滤器条件:

  1. 筛选器表达式:“=Fields!orderId.Value”
  2. 运算符:“等于”
  3. 值:“=Fields!orderId.Value”

Filter Properties for TableOrderDetails

单击 **预览** 查看结果。

Preview Table with Groupd Monthly Orders, Order Details and Totals

钻取

现在让我们添加一个钻取功能,该功能将使 tableOrders 和 tableOrderDetails 保持折叠状态,直到用户展开它们。

重命名以下标签:

字段(报表中显示) 新名称
“1996 年 7 月” txtMonth
“订单 ID:10248” txtOrderId

选择 tableOrders,并按如下方式更改 **Hidden** 和 **Toggle Item** 属性:

Visibility Properties of tableOrders Table

同样,使 tableOrderDetails 可折叠。

Visibility Properties of tableOrderDetails Table

现在我们可以通过单击“+/-”符号来展开/折叠详细信息级别。

Preview of Collapsed tableOrders

我们可以先展开月份。

Preview of Expanded Month Table

然后我们可以展开订单。

Preview of Expanded Month and Order Table

接下来,让我们为订单信息添加更多详细信息。

在现有页眉行上方添加四个新行,然后在新单元格中输入以下公式:

  1. 联系人姓名:“=Lookup([customerId], [customerID], [contactName], "Customers").ToUpper()”
  2. 订单日期:“=DateTime.Parse(Fields!orderDate.Value).ToString("MM/dd/yyyy")”

请注意,我们在多个地方使用了 Lookup 函数。与 Excel 电子表格中的 Lookup 类似,此函数允许您创建一个简单的查询,该查询根据两个字段之间的关系从一个数据集导航到另一个数据集,然后检索第三个字段的值。

选择 tableOrderDetails 的页眉行中的一个单元格,并在页眉上方插入四个新行。

Add Rows to tableOrderDetails Table

创建两个新字段来包含客户姓名和订单日期。对于客户姓名,我们将使用 Lookup 函数两次,从 OrderDetails 导航到 Customers 数据集,并以 Orders 数据集作为跳板。

  1. 客户:“=Lookup(Lookup(Fields!orderId.Value, Fields!orderId.Value, Fields!customerId.Value, "Orders"), Fields!customerId.Value, Fields!companyName.Value, "Customers")”

对于订单日期,我们将从 OrderDetails 数据集导航到 Orders 数据集。

  1. 订单日期:“=DateTime.Parse(Lookup(Fields!orderId.Value, Fields!orderId.Value, Fields!orderDate.Value, "Orders")).ToString("dd/MM/yyyy")”

单击 **预览** 以查看客户姓名和订单日期。

Preview of tableOrderDetails with Additional Detail Rows

排序列

最后,让我们使订单详细信息的列可排序。

选择每个页眉单元格,并在“用户排序”部分下使用以下公式填充 Sort Expression 字段:

列标题 排序表达式
项目 “=Lookup(Fields!productId.Value, Fields!productId.Value, Fields!productName.Value, "Products")”
数量 “=Fields!quantity.Value”
单价 “=Fields!unitPrice.Value”
折扣 “=Fields!discount.Value”
折扣价 “=Fields!unitPrice.Value - (Fields!unitPrice.Value*Fields!discount.Value)”
总价 “=Fields!Subtotal.Value”

单击 **预览** 并按数量对订单项进行排序。

Table with Sorting

按总价对订单项进行排序。

Table Sort Items by Price

创建 Host 和 NodeJS 应用

现在,报表已定义,您可以为此创建响应式 Web 显示 - 该显示在桌面和移动设备上看起来都不错。ActiveReportsJS 默认提供此功能。

您的示例应用程序将使用 Node.JS,这是一个 JavaScript 运行时环境,用于在服务器端执行 Web 应用程序。

遵循创建 PureJS Web 应用程序 的必要步骤,这是一个使用 ActiveReportsJS Viewer 组件的模板引擎。

为您的应用程序创建一个新的 OrdersReport 文件夹。

在命令提示符中键入以下行以安装 Node.JS Express 包:

npm install express

要安装 ActiveReportsJS 模块(这些模块是查看和嵌入 Web 应用程序客户端的月度销售报表所必需的),请输入以下命令:

npm install @grapecity/activereports

使用以下内容创建 index.html 文件:

<html>
<head>
    <meta charset="utf-8" />
    <title>ActiveReportsJS Viewer</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="node_modules/@grapecity/activereports/styles/ar-js-viewer.css" />
    <script type="text/javascript" src="node_modules/@grapecity/activereports/dist/ie-polyfills.js"></script> <!--to run in IE-->
    <script type="text/javascript" src="node_modules/@grapecity/activereports/dist/ar-js-core.js"></script>
    <script type="text/javascript" src="node_modules/@grapecity/activereports/dist/ar-js-viewer.js"></script>
</head>
<body onload="load()">
    <div id="ARJSviewerDiv" style="height: 600px"></div>
    <script>
        function load() {
            const viewer = new ActiveReports.Viewer('#ARJSviewerDiv');
            viewer.open('MonthlyOrders.rdlx-json');
        }
    </script>
</body>
</html>

请注意,上述代码使用 ActiveReportsJS Viewer 在客户端的网页上显示报表。

通过添加以下内容的 server.js 文件来创建 Web 服务器逻辑:

const express = require('express'); //import Express.js module  
const app = express();  
const path = require('path');  
app.use(express.static(path.join(__dirname)));  
app.listen(8085);

运行 Node.js 应用

现在您已将 ActiveReportsJS Viewer 嵌入到客户端 JavaScript 代码中,您可以运行您的 Web 应用程序以实际查看其某些功能:

node .\server.js

在桌面浏览器中导航到 https://:8085

您的应用程序将在 index.html 主页中运行,其中嵌入了 ActiveReportsJS Viewer。

View Report in Web Application Hosted in Node.js

顶部的条形图显示了每月的订单量。

图表报表特别有助于将大量数据转换为视觉地图,通过突出显示最大值和最小值并提供基于类别或时段的趋势的视觉线索,使用户能够立即理解。

报表包含一个工具提示,当您将鼠标悬停在条形图上时,它会显示该条形图的数据。

Report Tooltip

还记得您为某些报表元素配置的 Visibility 和 Toggle Item 属性吗?这些属性在您在报表中实现多级数据钻取时非常有用。

Drill Down Report with Table Sorting

在您的应用程序中,钻取功能允许您的用户从月份导航到该月份的订单,然后导航到订单中的项目。您还可以根据设计报表时配置的排序公式对列进行排序。钻取和排序是 ActiveReportsJS 交互功能的示例。

ActiveReportsJS Viewer 组件是响应式的:它可以在各种设备上、在各种屏幕尺寸下适当呈现。您可以使用 Web 浏览器中提供的开发者工具快速模拟各种移动设备、屏幕尺寸和页面方向。

比较桌面设备和 Chrome 和 Safari 浏览器中可用的移动模拟器上相同报表页面的视图。

Mobile Preview of Sales Report in Browser

View Reponsive Sales Report on Mobile

Responsive and Interactive Mobile Report

创建月度销售报表

在本文中,我们提供了一种使用 GrapeCity 的 ActiveReportsJS Designer 创建月度销售报表的操作方法。我们解释了如何聚合信息以绘制按月分组的销售图表,以及一个钻取的、交互式的表格报表,该报表按月和订单 ID 汇总销售数据。

开始探索 ActiveReportsJS 的功能,包括设计更完整、更具视觉吸引力的报表,并与流行的 Web 框架集成。

要继续尝试本文创建的代码,请随时下载或克隆 **存储库**。

作为练习,我们建议您扩展钻取创意,为报表添加新的数据级别。

例如,您可以从产品钻取到产品详细信息。您还可以创建一个新报表,其中包含显示按产品类别划分的销售额的图表,以及一个包含相应销售额的表格产品列表。

© . All rights reserved.