首页 > 其他分享 >妙趣横生:利用Echarts实现SpreadJS引用从属关系的可视化魅力

妙趣横生:利用Echarts实现SpreadJS引用从属关系的可视化魅力

时间:2024-07-15 10:53:50浏览次数:13  
标签:SpreadJS 妙趣横生 Echarts col rootNode let trackType children row

最新技术资源(建议收藏)
https://www.grapecity.com.cn/resources/

在金融行业,我们经常会有审计审查的需求,对某个计算结果进行审查,但是这个计算结果可能依赖多个单元格,而且会有会有多级依赖的情况,如果让我们的从业人员靠眼睛找,工作量巨大,而且准确性存疑,基本上死路一条,因此让整个审查过程可视化,迫在眉睫,现在我们利用纯前端表格和Echarts将审计审查过程可视化

一.首先我们先了解一下前端表格或Excel中引用和从属关系:
1.在单元格B1中设置公式 =SUM(A1)。 单元格A1是单元格B1的引用单元格(引用关系
2.在单元格B1中设置公式 =SUM(A1)。 单元格B1是单元格A1的从属单元格(从属关系

二.接下来我们看一下最终实现效果:

1.引用关系

2.从属关系

三.本次我们用的是Echarts的树图将引用和从属关系可视化,关于Echarts上手,大家去Echarts官网有完整上手教程,Echarts社区有很多开发者做的许多有趣又实用的demo,这里我们用的是树图

四.接下来我们要用纯前端表格控件的获取引用和从属关系的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;
    }

五.将构造好的引用和从属树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可视化的核心实现逻辑,由于工程较大,如需获取源码,可私信获取。

拓展阅读

React + Springboot + Quartz,从0实现Excel报表自动化

电子表格也能做购物车?简单三步就能实现

使用纯前端类Excel表格控件SpreadJS构建企业现金流量表

标签:SpreadJS,妙趣横生,Echarts,col,rootNode,let,trackType,children,row
From: https://www.cnblogs.com/powertoolsteam/p/18302719

相关文章

  • 【可视化大屏系列】Echarts之饼图绘制
    本文为个人近期学习总结,若有错误之处,欢迎指出!Echarts之饼图绘制前言1.需求2.实现效果3.大概思路4.代码实现子组件写法父组件写法5.附加(1)圆环饼图的绘制(2)南丁格尔玫瑰饼图A.半径展示数据的大小B.面积展示数据的大小前言在前文页面布局、DataV的使用、Echarts......
  • Echarts5之地图实现
    示例图说明依赖目录【左v5右v4】实现<template><divid="bmap"ref="canvas"class="canvas":style="{width:'100%',height:canHeight+'px'}"></div></template><scriptsetupla......
  • 可视化课设总结(星巴克网页爬取信息,百度地图网页版爬取信息,百度地图api,pyecharts库,pyth
    一、引言       本博客是本人是基于本人可视化课设所做的总结,其中有些过程的实现可能并不是最优的实现方法,有些实现效果也因为本人的实力有限,并不能达到预期的效果,所以也欢迎大家指点和改良。(刚考完期末回家,终于有时间把这个课设写个博客了,虽然这课设是明天截至的,我今......
  • Echarts-x轴数据换行显示
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><metahttp-equiv="X-UA-Compatib......
  • echarts 如何设置 legend 展示为虚线或者实线
    文章目录一、操作步骤1.找虚线或者实线的svg2.echarts中legend部分的完整代码3.预览效果总结一、操作步骤1.找虚线或者实线的svg在阿里巴巴矢量图标库里面找相应的内容。截图:复制里面的svg代码如下(实线举例):<svgt="1720600860976"class="icon"viewBox="00......
  • 利用 ECharts 地图:实现纹理和图像的效果(上海json)
    注:shanghaiGeoJSON换为你需要的区域json<template><divref="mapContainer"style="width:100%;height:500px"></div></template>import*asechartsfrom'echarts';importshanghaiGeoJSONfrom'@/assets......
  • echarts——横坐标轴文字过长如何换行
    横坐标轴文字过长,想要换行实现如下效果具体实现代码如下:axisLabel:{show:true,interval:0,formatter:function(value){varret="";//拼接加\n返回的类目项varma......
  • react或vue中页面多个echarts,只有最后一个能自适应的处理方法
    页面多个echarts时,自适应绑定方式必须是addEventListenerwindow.addEventListener("resize",()=>{myChart.resize();myChart2.resize();})myChart,myChart2是echart实例   ......
  • echarts折线图实现矩形圈中的点可拖拽,圈外的点不可拖拽
    原生HTML+JavaScript版本<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>曲线形式的统计图示例</title><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.9.0-rc.1/echarts.min.js&q......
  • echarts折线图加一条目标值线
    文章目录一、echarts折线图加一条目标值线?二、使用步骤1.代码如下:2.示例图片总结一、echarts折线图加一条目标值线?在ECharts中添加一条目标值线(即一个固定值的水平线),可以使用markLine组件,以下是一个简单的例子,展示了如何在ECharts折线图中添加一条目标值线。......