[{"id":"ff052704-1389-4029-bcdd-73c6cbe9f807","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"8e72e33e-b4ab-4fb3-98fc-a0b148134aed","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"c90d5fdf-420f-4978-8bf5-c9a2bb4334b3","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"900e6cab-065d-4f1c-844d-efa3c074e270","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"760b37c7-c713-4b24-b9ba-4bfe7d8437a6","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"89c707ed-9841-4e53-96fb-940cc3214804","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"64e2f4a3-2303-4bfa-8a93-6c23ef01de58","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"aa71a884-c5bc-4842-8d6a-873dfd645167","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"2605431b-dc80-491d-886e-28981595d277","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"69e79655-e015-4f9a-a230-2a25c988c926","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"a570c8e7-07a2-47da-965b-da44fd1fa5cf","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"86662220-9b9e-4940-9ced-d22642ea49a8","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"24769ecd-2b08-4a85-b318-4f533bbf8393","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"a244ead7-a2c6-47a3-ac17-c5dbfa337362","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"04e73782-aa78-4dfe-a4f9-e72ed4c78a11","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"4f41e22e-eb51-49e5-aeae-a42dd6bf352c","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"790bc77a-9216-48fd-b8f9-fbc374ebb155","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"21c6131f-0f2d-41d1-9284-6ad9ee803c1f","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"7ded3a22-15eb-49b8-a488-e83c2cd872eb","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"33638a1c-7196-42c1-a96d-38b2d9ba8ac4","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"4a0842a3-20b1-40c3-8e00-cd5941ffdf53","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"6e6ac5b1-1501-4e28-89cc-525139488537","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"b0576ca2-cb84-4390-9f95-9354ec20eda5","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"55fd3bb8-18d4-4edb-9640-ca3a365b798f","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"dacc7931-6785-4675-be31-80930403cf7b","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"63c577e6-6cf9-497e-94e1-2307f7d3f498","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"1b88a165-2563-437e-99bb-ae30bd4b56db","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"adf3817f-7667-4a4c-8a5f-767b0b7e1e3e","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"3a083583-1d5f-492b-b450-34b2b5c775b8","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"5d37413b-3600-4da9-9700-feea54355f59","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"a5a73576-16ea-4cbc-925c-ef547389eaa5","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"1126cfab-6210-4e28-bee0-02c113fb7a0c","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"09a66339-64c0-415c-b142-0691587a8e4a","tags":[{"product":null,"links":null,"id":"9e117e35-984a-4c14-95ca-ef0ec7b9fb60","name":"\u65B0\u589E","color":"DarkGreen","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"0baaf91d-84f6-404c-a487-735226b6d5b6","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"5b7aeac5-c755-426a-95c7-1ae8e547179a","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]},{"id":"57c94653-8893-403b-a5b1-0d1e33a0bd0f","tags":[{"product":null,"links":null,"id":"a2f84374-4a3f-4d22-96fd-765e9de495bf","name":"\u66F4\u65B0","color":"Coral","productId":"098be112-50ec-44e4-b746-6bc8bf76af97"}]}]
        
(Showing Draft Content)

用Echarts实现SpreadJS引用从属关系可视化

问题:如何用Echarts实现SpreadJS引用从属关系可视化?


背景:

在金融行业,我们经常会有审计审查的需求,对某个计算结果进行审查,但是这个计算结果可能依赖多个单元格,而且会有会有多级依赖的情况,如果让我们的从业人员靠眼睛找,工作量巨大,而且准确性存疑,基本上死路一条。

因此让整个审查过程可视化,迫在眉睫,本章我们利用SpreadJS和Echarts将审计审查过程可视化。


Step1、首先了解一下SpreadJS或Excel中引用和从属关系:

1、在单元格B1中设置公式 =SUM(A1)。 单元格A1是单元格B1的引用单元格(引用关系

2、在单元格B1中设置公式 =SUM(A1)。 单元格B1是单元格A1的从属单元格(从属关系

Step2、看一下最终实现效果:

1、引用关系

image

2、从属关系

image

Step3、使用Echarts树图将引用和从属关系可视化

关于Echarts上手,大家去Echarts官网有完整上手教程,Echarts社区有很多开发者做的许多有趣又实用的demo,这里我们用的是树图。

image

我们看一下它的data的数据结构:

image

Step4、使用SpreadJS的获取引用和从属关系API将单元格解析

将这些关系构造成Echarts树图的data结构,核心代码如下:

// 递归构建追踪树
buildNodeTreeAndPaint = (spreadSource, trackCellInfo) => {
  let info = this.getCellInfo(trackCellInfo);
  let sheetSource = spreadSource.getSheetFromName(info.sheetName); // 创建跟节点
  let rootNode = this.creatNode(info.row, info.col, sheetSource, 0, "");

  let name =
    rootNode.sheetName +
    "*" +
    rootNode.row +
    "*" +
    rootNode.col +
    "*" +
    Math.random().toString();
  let precedentsRootNode = "";
  let dependentsRootNode = "";
  if (
    this.state.trackType === "Precedents" ||
    this.state.trackType === "Both"
  ) {
    this.getNodeChild(rootNode, sheetSource, "Precedents");
    debugger;
    console.log(rootNode);
    if (this.state.trackType === "Both") {
      let rootNodeChildren = JSON.parse(JSON.stringify(rootNode.children));
      rootNode.children = [];
      precedentsRootNode = JSON.parse(JSON.stringify(rootNode));
      precedentsRootNode.children.push({
        name: "Precedents",
        value: "Precedents",
        children: rootNodeChildren,
      });
      this.setState({
        precedentsRootNode: JSON.parse(JSON.stringify(precedentsRootNode)),
      });
    }
  }
  if (
    this.state.trackType === "Dependents" ||
    this.state.trackType === "Both"
  ) {
    this.getNodeChild(rootNode, sheetSource, "Dependents");
    console.log(rootNode);
    if (this.state.trackType === "Both") {
      let deepInfo = [1];
      let rootNodeChildren = JSON.parse(JSON.stringify(rootNode.children));
      rootNode.children = [];
      dependentsRootNode = JSON.parse(JSON.stringify(rootNode));
      dependentsRootNode.children.push({
        name: "Dependents",
        value: "Dependents",
        children: rootNodeChildren,
      });
      this.setState({
        dependentsRootNode: JSON.parse(JSON.stringify(dependentsRootNode)),
      });
    }
  }
  if (this.state.trackType === "Both") {
    precedentsRootNode.children = precedentsRootNode.children.concat(
      dependentsRootNode.children
    ); // let bothRootNode = precedentsRootNode.children[0].children.concat(dependentsRootNode.children[0].children)
    this.setState({
      rootNode1: JSON.parse(JSON.stringify(precedentsRootNode)),
    });
  } else {
    this.setState({
      rootNode1: JSON.parse(JSON.stringify(rootNode)),
    });
  }
};
creatNode = (row, col, sheet, deep, trackType) => {
  let node = {
    value: sheet.getValue(row, col),
    position:
      sheet.name() +
      "!" +
      GC.Spread.Sheets.CalcEngine.rangeToFormula(
        new GC.Spread.Sheets.Range(row, col, 1, 1)
      ),
    deep: deep,
    name: `${sheet.name()}!${GC.Spread.Sheets.CalcEngine.rangeToFormula(
      new GC.Spread.Sheets.Range(row, col, 1, 1)
    )}\nvalue:${sheet.getValue(row, col)}`,
    sheetName: sheet.name(),
    row: row,
    col: col,
    trackType: trackType,
  };
  return node;
};
getNodeChild = (rootNode, sheet, trackType) => {
  let childNodeArray = [];
  let children = [];
  let row = rootNode.row,
    col = rootNode.col,
    deep = rootNode.deep;
  if (trackType == "Precedents") {
    children = sheet.getPrecedents(row, col);
  } else {
    children = sheet.getDependents(row, col);
  } // let self = this;
  if (children.length >= 1) {
    children.forEach((node) => {
      let row = node.row,
        col = node.col,
        rowCount = node.rowCount,
        colCount = node.colCount,
        _sheet = sheet.parent.getSheetFromName(node.sheetName);
      if (rowCount > 1 || colCount > 1) {
        for (let r = row; r < row + rowCount; r++) {
          for (let c = col; c < col + colCount; c++) {
            let newNode = this.creatNode(r, c, _sheet, deep + 1, trackType); // if (deep < self.maxDeep) {
            this.getNodeChild(newNode, _sheet, trackType); // }
            childNodeArray.push(newNode);
          }
        }
      } else {
        let newNode = this.creatNode(row, col, _sheet, deep + 1, trackType); // if (deep < self.maxDeep) {
        this.getNodeChild(newNode, _sheet, trackType); // }
        childNodeArray.push(newNode);
      }
    });
  }
  rootNode.children = childNodeArray;
};
Step5、将构造好的引用和从属树rootNode在Echarts中渲染
myChart.setOption(
  (option = {
    tooltip: {
      trigger: "item",
      triggerOn: "mousemove",
    },
    series: [
      {
        type: "tree",
        data: [this.state.rootNode1],
        top: "1%",
        left: "15%",
        bottom: "1%",
        right: "7%",
        symbolSize: 10,
        orient: this.state.trackType === "review" ? "LR" : "RL",
        label: {
          position: this.state.trackType === "review" ? "left" : "right",
          verticalAlign: "middle",
          align: this.state.trackType === "review" ? "right" : "left",
        },
        leaves: {
          label: {
            position: this.state.trackType === "review" ? "right" : "left",
            verticalAlign: "middle",
            align: this.state.trackType === "review" ? "left" : "right",
          },
        },
        emphasis: {
          focus: "descendant",
        }, // layout: 'radial',
        expandAndCollapse: true,
        animationDuration: 550,
        animationDurationUpdate: 750,
      },
    ],
  })
);

option && myChart.setOption(option);

以上就是实现报表中公式引用从属关系Echarts可视化的核心实现逻辑。

如果需要获取源码,可以前往该链接获取。

作者: Steven.Lv | 审核:Lynn.Dou | 更新时间:2023.11.15