使用ssrs矩阵

要把原代码的 Excel 导出功能转成 SSRS 报表,报表设计是最核心的环节 ------ 尤其是如何用 "数据集" 准备数据,用 "矩阵" 处理动态列(比如不确定数量的维度),这部分很容易 confusion,下面用 "大白话 + 实例" 讲透。

先明确一个核心目标

报表最终要长成这样(和原 Excel 一致):

plaintext

复制代码
┌───────────┬───────────┬───────────┬───────────┬───────────┬...(其他余额列)
│ 维度1名称  │ 维度2名称  │ 科目描述   │ 交易币种   │ 期初本位币 │
├───────────┼───────────┼───────────┼───────────┼───────────┼
│ 维度1值    │ 维度2值    │ 银行存款   │ CNY       │ 1000.00   │
│ 维度1值    │ 维度2值    │ 应收账款   │ USD       │ 2000.00   │
└───────────┴───────────┴───────────┴───────────┴───────────┘

其中,"维度 1、维度 2" 的数量不固定(可能 1 个,也可能 5 个,取决于系统配置的财务维度集),这就是 "动态列";"科目描述、币种、余额" 是固定不变的列。

一、数据集:报表的数据 "粮仓"

数据集(Dataset)就是报表的 "数据源",相当于提前把要显示的数据整理成一张 "表格",报表里的文字、数字都从这张 "表格" 里取。

原代码里的数据存在临时表ledgerTrialBalanceTmp中,SSRS 报表也需要基于这张表做数据集,但要拆成两个:一个存实际业务数据,一个存动态维度的名称

1. 主数据集(MainDataset):存业务数据

作用:存储所有要显示的行数据(比如每一行的维度值、科目描述、各种余额)。

怎么来的? 对应原代码的generateData方法 ------ 通过LedgerTrialBalanceTmp::calculateBalances_V2生成的ledgerTrialBalanceTmp临时表。我们只需要把这张表的字段 "挑出来" 做成数据集。

具体字段(必须包含这些)

字段类别 例子(对应原代码) 说明
动态维度值 DimensionValues1DimensionValues2... 第 1 个维度的值、第 2 个维度的值(最多 N 个)
固定基础信息 PrimaryFocusDescription(科目描述) 原代码里的科目文本
固定基础信息 YMZTransactionCurrency(交易币种) 原代码里的币种字段
余额数据 YMZOpeningBalanceBaseCurrency(期初本位币) 原代码里的余额字段
其他余额数据 借方 / 贷方 / 期末的本位币、交易币字段 同上,按原代码字段一一对应

配置方法 :在 D365 的报表设计工具(如 Visual Studio 的 Report Designer)中,新建一个数据集,数据源选 "查询",然后选我们提前建好的YMZLedgerTrialBalanceQuery(这个查询关联了ledgerTrialBalanceTmp临时表,并包含上述所有字段)。

2. 维度信息数据集(DimSegmentsDataset):存动态维度的名称

作用:告诉报表 "有多少个维度""每个维度叫什么名字"(比如 "部门""成本中心"),用于动态生成表头。

怎么来的? 对应原代码的dimensionSetSegmentNames------ 从DimensionHierarchyLevel::getDimensionHierarchyLevelNames获取的维度名称。我们需要把这些名称和对应的序号(第 1 个、第 2 个)做成数据集。

具体字段

字段名 说明
SegmentNumber 维度序号(1、2、3...)
SegmentName 维度名称(如 "部门""成本中心")

配置方法 :新建一个数据集,数据源可以是自定义的方法(X++),比如写一个方法getDimensionSegments(),返回包含上述字段的临时表(里面存着当前配置的维度序号和名称)。

二、矩阵(Matrix):处理动态列的 "神器"

报表里的 "动态维度列"(数量不固定)必须用矩阵组件来做。矩阵和 Excel 的 "数据透视表" 很像,能根据数据自动生成列(或行)。

如果用普通的 "表格" 组件,列数是固定的,没法应对 "有时 3 个维度,有时 5 个维度" 的情况;而矩阵的 "列组" 可以动态生成列,完美解决这个问题。

矩阵的核心结构(先看懂这个再动手)

矩阵有 3 个核心区域,对应到我们的报表需求:

plaintext

复制代码
┌───────────────────────────────────── 列组(动态维度列) ─────────────────────────────────────┐
│  ┌───────────┐  ┌───────────┐  ┌───────────┐                                                │
│  │ 维度1名称  │  │ 维度2名称  │  │ 维度3名称  │  ...(固定列:科目描述、币种、余额...)        │
│  └───────────┘  └───────────┘  └───────────┘                                                │
├────────────────────────────────── 数据区域(维度值) ──────────────────────────────────────┤
│  ┌───────────┐  ┌───────────┐  ┌───────────┐                                                │
│  │ 维度1值    │  │ 维度2值    │  │ 维度3值    │  ...(固定列的值)                           │
│  └───────────┘  └───────────┘  └───────────┘                                                │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
行组(这里不需要额外分组,默认一行一条数据)
  • 列组(Column Group) :控制 "动态维度列" 的表头(显示维度名称),由DimSegmentsDatasetSegmentNumberSegmentName驱动。
  • 数据区域(Data) :填充动态维度列的值(比如 "维度 1 值""维度 2 值"),从MainDatasetDimensionValues1等字段取。
  • 行组(Row Group):这里不需要分组(因为每一行就是一条独立的数据),保持默认即可。
手把手配置矩阵(以 "3 个维度" 为例)

假设系统当前配置了 3 个维度(部门、成本中心、项目),我们一步步让矩阵显示这 3 列。

步骤 1:添加矩阵到报表

在 Report Designer 的 "工具箱" 里拖一个 "Matrix" 到报表主体(Body)中,会看到默认的矩阵结构:

plaintext

复制代码
┌────────────┬────────────┐
│ [列组]     │ [数据]     │
├────────────┼────────────┤
│ [行组]     │ [数据]     │
└────────────┴────────────┘
步骤 2:配置列组(动态显示维度名称)

目标:让列组根据DimSegmentsDatasetSegmentNumber生成 3 列,每列的表头显示SegmentName(如 "部门""成本中心")。

  • 右键矩阵的 "列组" 区域(默认显示 "列组" 的地方),选 "添加组"→"父组"。
  • 在弹出的窗口中,"分组依据" 选DimSegmentsDatasetSegmentNumber(维度序号)。
  • 勾选 "添加组头",点确定。此时列组会生成一个基于SegmentNumber的分组。
  • 把列组表头的文本框(默认显示[SegmentNumber])改成[SegmentName](从DimSegmentsDatasetSegmentName字段到这里)。

此时列组会自动根据DimSegmentsDataset的数据生成列:如果有 3 个维度,就显示 3 列,表头分别是 "部门""成本中心""项目"。

步骤 3:配置数据区域(填充维度值)

目标:让动态列的单元格显示对应维度的值(如 "部门" 列显示DimensionValues1,"成本中心" 列显示DimensionValues2)。

  • 矩阵中间的 "数据" 区域(默认显示[数据]的地方)需要根据 "当前维度序号" 动态取MainDatasetDimensionValuesN字段。

  • 这里需要用 "表达式" 判断:如果SegmentNumber=1,就取DimensionValues1SegmentNumber=2,就取DimensionValues2...

  • 右键数据区域的文本框,选 "表达式",输入: vb

    复制代码
    =Switch(
        Fields!SegmentNumber.Value = 1, Fields!DimensionValues1.Value,
        Fields!SegmentNumber.Value = 2, Fields!DimensionValues2.Value,
        Fields!SegmentNumber.Value = 3, Fields!DimensionValues3.Value
        -- 按系统最大维度数补充,比如最多10个就写到10
    )

    这个表达式的意思是:根据当前列的维度序号(1/2/3),显示对应的维度值字段。

步骤 4:添加固定列(科目描述、币种、余额等)

动态维度列配置完后,右侧需要添加固定列(和原 Excel 的固定列一致)。

  • 右键矩阵的最右侧列,选 "插入列"→"在右侧",插入新列(需要多少固定列就插多少)。
  • 第一列固定列的表头:拖@SYS92116(原代码中的科目描述标签)到表头文本框。
  • 该列的数据区域:拖MainDatasetPrimaryFocusDescription字段(科目描述的值)。
  • 第二列固定列的表头:拖@SYS62786(原代码中的币种标签)到表头。
  • 该列的数据区域:拖MainDatasetYMZTransactionCurrency字段(币种值)。
  • 后续余额列(期初、借方、贷方等)以此类推:表头用原代码中的标签(如@YMZ:OpeningBalanceBaseCurrency),数据区域拖对应的余额字段(如YMZOpeningBalanceBaseCurrency)。
步骤 5:设置数字格式(余额字段必做)

原代码中余额字段是 "0.00" 格式,报表里也要保持一致:

  • 右键余额字段的数据文本框(如[YMZOpeningBalanceBaseCurrency]),选 "文本框属性"。
  • 切换到 "数字" 选项卡,选 "标准",小数位数设为 "2",点确定。

三、最终效果验证

配置完后,预览报表会看到:

  • 动态维度列:根据系统配置的维度数量自动生成(比如 3 个维度就显示 3 列,表头是维度名称)。
  • 动态列数据:每列显示对应维度的值(部门列显示部门值,成本中心列显示成本中心值)。
  • 固定列:科目描述、币种、余额等字段按原格式显示,余额带 2 位小数。

和原 Excel 导出的效果完全一致,但更灵活(支持导出 PDF、打印等)。

关键总结

  1. 数据集是 "粮仓":主数据集存业务数据(维度值、余额等),维度数据集存动态列的名称和序号。
  2. 矩阵是 "动态列工具":用列组(基于维度序号)生成动态列,用表达式根据序号匹配维度值。
  3. 固定列直接加:动态列右侧插固定列,绑定对应字段即可。
相关推荐
fangzhanpeng1685 天前
快速掌握C#语言基础知识点(1.基础数据类型)
开发语言·c#·1024程序员节
无己心7 天前
面向多平台 AI 搜索引擎的适配层架构设计
前端·人工智能·搜索引擎·ai·1024程序员节
u01030552713 天前
AI驱动的安卓UI自动生成功能实现
人工智能·1024程序员节
u01030552714 天前
长株潭智能体赋能腾讯元器链接共享
1024程序员节
云贝贝贝15 天前
OceanBase认证体系介绍与备考指南
运维·服务器·oceanbase·1024程序员节
u01030552715 天前
Java图像处理实战指南
人工智能·1024程序员节
u01030552716 天前
Java AWT鼠标事件全解析
人工智能·1024程序员节
u01030552718 天前
Java实用类应用精讲
人工智能·1024程序员节
u01030552718 天前
Java I/O核心操作实战
人工智能·1024程序员节
u01030552719 天前
ArrayList操作详解与实战应用
人工智能·1024程序员节