---
order: 6
navTitle: 取数和计算
---
# 取数和计算

报表填报应用支持多种灵活的取数和计算方式，包括基本的四则运算，[函数](../../exp/func/README.md)计算，从数据模型中取数等各种情况。本文主要介绍在各种不同的业务场景下，如何使用报表填报应用的取数计算能力。以下是计算相关的基本属性设置：

![属性设置](./images/2024-05-22-11-40-00.png)

## 默认值{#default-value}

**默认值**是一种只会在页面初始化时计算一次的表达式，后续不会因为用户填报表格或点击计算按钮而重新计算。通常用于新增数据时，计算一个初始值，用户在后续填报时可以根据实际业务情况进行再次修改。对于计算后就不再修改的内容，比如按照固定的规则生成主键或计算创建人等，此时还需要额外设置单元格不可填写。

![默认值](./images/2024-05-22-11-20-00.png)

示例地址：[默认值](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=default_value)

## 计算公式{#calc}

**计算公式**是可以按需进行再次计算的公式，当计算公式引用的其他单元格发生变化时会自动重新计算，当用户点击**计算**按钮时也会重新计算。比如在表单中需要在填写过销量和单价后自动计算出销售金额，则可在填写销售金额的单元格中添加**计算公式**，计算单价和销量相乘的结果。

![计算公式](./images/2024-05-22-11-30-00.png)

示例地址：[计算公式](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=inter_table_calc)

::: tip

1. **计算条件**可以控制**计算公式**只在条件返回`TRUE`或为空时才会计算，例如根据输入的身份证号码来计算出生日期、性别，只有当输入的内容是符合身份证号码规范的时候计算才有意义，此时可以设置计算条件为`pidcheck(身份证号码)`。
2. 单元格添加**计算公式**后，会自动叠加上**计算**状态样式，默认是一个斜线底纹，详细规则可参考[条件样式](./design-form/condition-style.md)文档。
3. 有**计算公式**的单元格默认不可填写，当需要填写时，需要设置**单元格**>**输入**>**禁用/只读**属性为**启用**。

:::

## 取数公式{#fetchdata}

**取数公式**可以自动从数据库或第三方业务系统获取实际的数据并初始化到表格，供用户确认后按需修改并上报。实际使用过程中，可能会对一个数据集按多种取数口径来取数，类似报表查询，如下示例所示：

![取数公式](./images/2024-05-23-10-00-00.png)

示例地址：[取数公式](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=fixed_fetchdata)

给**取数公式**添加**取数条件**的过程类似于在报表单元格上添加[过滤](../../report/design/data/README.md#filter)，例如上述示例地址中的报表填报应用，所有的**取数公式**其实都是在对一份明细数据求[COUNT](../../exp/func/aggregate/COUNT.md)，只是会用不同的取数条件来过滤得到不同维度下的明细数据结果。

::: tip

1. **取数条件**等价于报表单元格的过滤条件，它是对数据集过滤条件的一种补充，与数据集过滤条件是AND的关系。
2. **取数执行条件**等价于计算公式的**计算条件**，是在满足这个条件的情况下才会计算**取数公式**。

:::

## 根据业务场景选用公式{#choose}

由于默认值、计算公式以及取数公式的计算逻辑不同，业务上存在一些容易混淆的情况可能导致公式错误配置，以下述常见场景进行说明：

- 以[UUID](../../exp/func/string/UUID.md)作为主键存储。
  - 错误配置：在**计算公式**中添加`UUID()`，这会导致主键内容不稳定，每次手动触发计算都会导致主键发生变化。
  - 正确配置：在**默认值**中设置，这样生成的主键就是稳定不变的。
- 初始化时以前期数据作为默认值，并可在得到的结果基础上继续修改，修改后的内容不希望被覆盖掉。
  - 错误配置：在**计算公式**中使用[PRE](../../exp/func/analysis/PRE.md)函数计算前期数据，并设置单元格允许编辑，这会导致触发计算交互时，这些不希望被覆盖的数据会因此重新计算而被覆盖。
  - 正确配置：在**默认值**中配置，由于默认值初始化时仅计算一次的原则，后续触发的计算或取数交互都不会对其造成影响所以总是不会覆盖数据。
- 初始化时以前期数据作为默认值，并可继续修改，初始化的来源数据可能发生变化，需要手动同步最新数据后继续修改。
  - 错误配置：在**默认值**或**计算公式**中配置，并设置单元格允许编辑，如果是默认值则后续来源数据修改无法同步，如果是计算公式则会导致手动修改的数据很容易无意中被覆盖掉。
  - 正确配置：在**取数公式**中配置，页面初始化时获取初始值，可以继续修改，当数据来源发生变化后点击取数按钮重新取数即可，还可仅对指定有变化的数据集进行重新取数。
- 根据下拉框可选项内容计算，计算得到的内容还可继续修改。
  - 错误配置：在**计算公式**中获取下拉选项相关内容，并设置单元格允许修改，这样设置会导致手动触发计算其他内容时此处修改过的值也会重新计算进而发生数据覆盖。
  - 正确配置：通过**设置组件属性**交互来设置单元格的值，当下拉框值发生变化时触发交互同步修改需要发生计算的其他单元格，后续触发计算也不会导致这里的内容被覆盖。
- 单元格之间存在计算逻辑，导出Excel后在Excel中进行修改，然后导入回表单，希望导入的结果和文件中的内容一致。
  - 错误配置：在**计算公式**中配置相应的计算逻辑，并且设置单元格允许修改，这种情况下导入最后计算公式总是会重新计算导致导入的结果与文件中的不一致。
  - 正确配置：通过**设置组件属性**交互来设置单元格的值，单元格允许编辑，此时再次导入不会重新触发计算。

## 计算优先级{#priority}

报表填报应用中有多种数据来源，除默认值、计算公式以及取数公式外，还可以有汇总数据和补足数据，当这些数据来源同时作用时，按以下优先级计算：

1. 提交过数据后，如果单元格有绑定字段，则再次进入表单总是以**绑定字段**中装载的数据为主，不会计算其他表达式。
2. **汇总数据**仅在查看上级单位的表单时有效，如果上级单位没有提交过数据且设置了汇总，则此时以汇总为主，如果此时汇总的单元格上有**计算公式**，且**计算公式**中引用了其他汇总单元格，则汇总后该**计算公式**会因为被影响计算而自动计算一次。
3. 新增数据时，如果此时不是汇总单位，则按照**取数公式**>**默认值**>**计算公式**的优先级来计算。
4. **计算公式**总是会在引用的内容发生变化的情况下自动计算。
5. **补足数据**只能在浮动表中作用，优先级总是最低的，当汇总、取数或装载的数据不满足期望的行数时，才会处理补足。
6. 汇总、取数、计算都可通过对应的按钮强行触发计算。

## 应用场景{#scenarios}

### 取前期数据{#pre}

有时需要将以前填报的数据作为参考值显示在表单中。比如填报每月的收支情况，希望在填本月的数据时能够对比下上月的数据，此时可以使用[PRE](../../exp/func/analysis/PRE.md)函数来获取上一期的数据。

![上期值](./images/2024-05-22-11-00-00.png)

示例地址：[上期值](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=%E4%B8%8A%E6%9C%9F%E5%80%BC)

::: tip

[PRE](../../exp/func/analysis/PRE.md)函数针对字段使用时，需要带上字段的模型前缀，使用类似`pre(model1.field1)`的表达式来获取字段对应的前期数据。

:::

### 浮动表取其他模型数据{#float-fetch}

填报浮动表时，可使用**取数公式**来初始化一批数据到浮动行中。这样做的好处在于填报时无需自行添加行，大部分能直接通过查询得到的内容不需要用户再手动输入，用户只需要填写必要的数据即可。例如填报产品销量明细，可将要填写的产品以及部分规格参数初始化到浮动表中，用户只需要填写每类产品的销售单价以及销售数量即可。

![浮动取数](./images/2024-05-22-11-50-00.png)

示例地址：[浮动取数](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=float_fetchdata)

以产品销量填报为例，浮动表取其他模型的数据有以下几个关键步骤：

1. 对取数模型施加过滤条件，仅保留需要获取的数据，此处只保留第一级的产品数据。
2. 在**浮动单元格**中设置**取数公式**为`产品表.代码`，这决定了在做取数查询时会以这个字段作为查询的主粒度，即当前产品表中有多少行数据那么浮动区域中初始化的行也一定是一致的。
3. 在浮动区域的其他单元格中设置需要一起取数的内容，此处需要获取产品名称，因此在B3单元格中设置**取数公式**为`产品表.名称`。

::: tip

1. **取数公式**的应用可以看作是一个报表查询，报表填报应用只是将查询的结果存储到填报模型中。
2. 基于上述概念，浮动表取数时，浮动单元格必须设置**取数公式**。如果没有，效果等同于报表的浮动单元格中未设置计算公式，会导致查不出来任何数据。
3. 浮动表的主键是技术键时，比如UUID，此时浮动单元格可以没有**取数公式**，但浮动区域必须设置**业务单元格**，**业务单元格**中必须有**取数公式**，此时取数的查询会以**业务单元格**为依据。
4. 当**浮动单元格**或**业务单元格**有关联维表，此时通过**数据补足**搭配**计算公式**可以达到一样的取数效果，具体操作可参考[浮动设置](/ci/floating)文档。

:::

### 列出下级单位数据{#list-org}

上级单位填报时，有时需要参考下级单位的数据。如果按照默认体验去查看下级单位的数据，需要频繁的在填报单位树中切换，因此会将所有下级单位的数据以浮动表的形式在上级单位的表单中展示出来。

![取下级数据](./images/2024-05-22-11-10-00.png)

示例地址：[列出下级单位数据](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=%E5%88%97%E5%87%BA%E4%B8%8B%E7%BA%A7%E5%8D%95%E4%BD%8D%E6%95%B0%E6%8D%AE)

以在岗职工统计表为例，在上级单位的表单中列出所有下级有以下几个关键步骤：

1. 克隆当前填报数据集，右键点击**设置**，在**高级**标签页下勾选**自定义加载数据条件**。
2. 添加**加载数据条件**，设置`数据期=当前数据期`和`填报单位.上级单位=当前单位`，意思是要过滤出所有当前数据期下本单位的下级单位数据。
3. 添加**浮动区域**，绑定上述克隆数据集，并在对应的单元格上设置好**绑定字段**，这样设置后，打开表单时如果克隆数据集过滤后有数据则会自动装载到表单浮动区域中。
4. **浮动区域**设置显示条件`当前单位.SZ_LEAF != '1'`，仅在上级单位打开表单时才显示。

::: tip

**周期填报应用**中所有与单元格有绑定关系的数据集都有默认的数据期、填报单位过滤条件，这限制了填报者不能越权操作其他单位的数据，因为这个限制，默认情况下，表单中是无法直接展示其他单位数据的。详细说明可参考[数据存储](./data-storage.md)文档。

:::

### 取单行数据集的数据{#onerowquery}

当数据来源于同一模型且有相同的取数口径时，建议使用**单行数据集**取数。单行数据集的取数方式可参考**SuperPage**的[取数和计算](https://docs.succapp.com/v5/guide/superpage/fetch-and-calc)文档。表单示例如下：

示例地址：[单行数据集](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=index_calc)

### 取指标数据集的数据{#measure}

通过#表达式，可获取**单主键**模型指定行的数据，常用于获取指标的相关信息进行计算。例如员工绩效考核，需要根据不同的考核项来填写员工的分数，以固定表的形式填报存储时按[行存储](./design-form/data-mapping.md#row-table)，填报时需要表样中提供每个考核项的总分值供填报人参考，表单示例如下：

![指标计算](./images/2024-12-13-09-00-00.png)

示例地址：[指标计算](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=index_calc)

在固定行表中，指标项的行表条件通常会覆盖整行，但是条件区域内的计算公式不会作用行表条件，即在计算公式中使用`数据集.字段`来获取指标中的信息时，即便在条件区域内存在行表条件来过滤指定行，此时计算公式中引用的数据集也不会作用这个条件，这会导致数据集仍是多行的无法计算出结果，此时需要通过#表达式来获取指定行数据。

1. 引用的数据集本身是单主键或添加完过滤条件后仅余下某个主键未被过滤时，编辑表达式，在这类数据集后写#会提示所有候选项的信息。
2. 通过形如`数据集#[指标ID].字段`的表达式可以获取到该数据集指定行某个字段的值。

### 使用QUERY函数取数{#query}

当要取的数据比较简单且数据量不大时，可在计算公式中使用[QUERY](../../exp/func/others/QUERY.md)函数达到效果，具体使用场景可参考[QUERY](../../exp/func/others/QUERY.md)函数文档。表单示例如下：

示例地址：[QUERY函数](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=query_func)

### 一致性维度计算{#conformeddim}

不同浮动区域按相同维度浮动时，此时认为它们具有一致性维度，例如都是按产品类型浮动出所有产品小类。当具有一致性维度的浮动区域间需要相互引用内容进行计算时，如下示例所示：

| 填写数据 | 根据一致性维度同步内容 |
| :------: | :------: |
| ![浮动表A](./images/2024-12-12-09-10-00.png) | ![浮动表B](./images/2024-12-12-09-20-00.png) |

示例地址：[一致性维度计算](https://demo.succbi.com/v5/DEMO/app/ci.app?:id=fetch-and-calc&:dataPeriod=202212&:orgId=010301&:sheet=conformed_dimenson)

1. 浮动表A按产品浮动，用于填写各小类产品的销售情况。
2. 浮动表B同样按产品浮动，用于同步浮动表A中填写的零售单价和销售数量。
3. 两表都是按产品类型浮动的，具有一致性维度，此时可在浮动表B中直接引用浮动表A中的单元格，即形如`浮动表A.D4`的表达式即可，系统会自动按照对应的产品类型来得到相同产品类型的数据。

::: tip

1. 如果不使用一致性维度计算规则，当存在这种跨浮动区域的引用时，需要通过[浮动函数](../../exp/func/float/FALL.md)来明确需要获取浮动结果中哪一行的数据，即上述获取相同产品的数据需要使用类似`FGET(浮动表A.D4,浮动表A.A4=A4)`的表达式，意为依据当前浮动行的产品类型来获取浮动表A中相同类型的数据，这样写相对比较麻烦。
2. 一致性维度计算只适用于在一个浮动区域中获取另一个浮动区域中相同行的数据，即上述类似获取相同产品类型数据的场景，如果需要获取不同行的数据，例如产品类型为A1的行要获取其他浮动区域中产品类型为A2的数据，此时还是需要借助[浮动函数](../../exp/func/float/FALL.md)来达到目的。

:::
