开发者问题收集

计算行:如何使用 AG Grid 根据同一列中其他行的值计算特定列的单元格值?

2021-12-17
3028

我想使用同一列中其他行的值对特定行实现自定义计算。我发现 AG Grid 提供了定义 列定义表达式 aggFunc 的功能,但它们不能解决我想要的问题:

  1. 列定义表达式 (我们称之为 CDE)允许用户引用同一行的其他列
  2. aggFunc 在分组的情况下很有用,用户可以使用内置函数或定义自定义聚合函数,该函数只能在特定组内使用同一列的单元格值。

我需要解决以下:

Category groups         | Jan                        | Feb | Total
---------------------------------------------------------------------------------
Income                  | {it is place for aggFunc}  |     | {it is place for CDE}
    In 1                |                            |     |
    In 2                |                            |     |
    Ignored In in Net   |                            |     |
Liabilities             |                            |     |
Net Income       ???    | In 1 + In 2 - Liabilities  |     |
Net Income Total ???    | Income - Liabilities       |     |

结果应该是这样的:

Category groups         | Jan   | Feb | Total
----------------------------------------------
Income                  | 62    |  17 |  79
    In 1                | 12    |  10 |  22
    In 2                | 20    |  5  |  25
    Ignored In in Net   | 30    |  2  |  32
Liabilities             | 15    |  10 |  25
Net Income       ???    | 17    |  5  |  22
Net Income Total ???    | 47    |  7  |  54

那么, 如何通过 AG Grid (react) 定义 Net Income 行和 Net Income Total 行的公式(表达式/聚合函数), 在哪里我可以引用同一列中任何需要的行 (在上述情况下, Net Income = In 1 + In 2 - LiabilitiesNet Income Total = Income - Liabilities 为 Jan、Feb 等)?可以使用哪些 API?

目前,我实现了这个 DEMO ,并且在官方 AG Grid 文档中没有找到关于如何实现所需案例的任何线索,以及是否有可能使用这个库……

UPD 。我尝试通过以下方式实现它:

  1. 覆盖 getRowNodeId() 回调以获得可预测的 rowNodeId;
  2. 通过 api.getRowNode(rowId) 获取 rowNode;
  3. 使用 getValue() 函数,该函数具有 2 个参数 (colKey, rowNode) ,理论上它应该返回指定行的目标列的值。

结果我有:

gridOptions = {
  getRowNodeId: row => {
    return `${row.level0}${row.lastLevel}`;
  },
  ...
  columnTypes: {
    ...
    janType: {
      enableValue: true,
      aggFunc: 'sum',
      valueGetter: ({ data, getValue, api }) => {
        if (data.lastLevel === 'Net Income') {
          const in1Row = api.getRowNode('IncomeIn 1');
          const in2Row = api.getRowNode('IncomeIn 2');
 
          // Uncaught RangeError: Maximum call stack size exceeded
          return getValue("Jan", in1Row) + getValue("Jan", in2Row);
        }
        ...
        return data.Jan;
      }
    },
    ...
  },
};

这不起作用,并且 getValue("Jan", in1Row) + getValue("Jan", in2Row) 导致 未捕获的 RangeError:超出最大调用堆栈大小

感谢提供解决此案例的任何想法/示例!

2个回答

目前看来,实现此操作的唯一可能方法和地点是使用 onGridReady 事件,并且可以在其中设置计算行的值(通过 rowNode.setDataValue() )。网格在此阶段拥有所有数据(+ 聚合数据)。此 链接 有助于了解如何收集所有数据。

更好的方法是定义 getRowNodeId 回调

getRowNodeId: row => {
   // custom rowNodeId resolver
},

并通过数据列和 rowId 获取值(Jan、Feb 等)。

这是一个简单的实现:

  onGridReady: ({ api }) => {
    const income = api.getRowNode('row-group-0');
    const in1Row = api.getRowNode('IncomeIn 1');
    const in2Row = api.getRowNode('IncomeIn 2');
    const liabilities = api.getRowNode('Liabilities');
    
    api.forEachNode(rowNode => console.log(rowNode.id));

    for (const col of ["Jan", "Feb"]) {
      const netIncome = api.getValue(col, in1Row) + api.getValue(col, in2Row) - api.getValue(col, liabilities);
      const netIncomeTotal = api.getValue(col, income) - api.getValue(col, liabilities);

      const netIncomeRow = api.getRowNode('Net Income');
      netIncomeRow.setDataValue(col, netIncome);

      const netIncomeTotalRow = api.getRowNode('Net Income Total');
      netIncomeTotalRow.setDataValue(col, netIncomeTotal);
    }
  }

对 plunker 的引用 此处

Nick
2021-12-20

您是否查看过我们与 AG Grid 结合使用的 AdapTable 中的计算列?

它能为您提供所需的一切: https://docs.adaptabletools.com/guide/handbook-calculated-column

Simone
2022-04-04