用Echarts实现SpreadJS引用从属关系可视化
在金融行业,我们经常会有审计审查的需求,对某个计算结果进行审查,但是这个计算结果可能依赖多个单元格,而且会有会有多级依赖的情况,如果让我们的从业人员靠眼睛找,工作量巨大,而且准确性存疑,基本上死路一条,因此让整个审查过程可视化,迫在眉睫,现在我们利用纯前端表格和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构建企业现金流量表
用Echarts实现SpreadJS引用从属关系可视化的更多相关文章
- 用Echarts的力向导图可视化数据
学习背景:做一个图论的题目的时候需要将结果可视化来直观的看效果,所以使用Echarts来画.感觉效果不错. Echarts下载地址:https://echarts.baidu.com/download ...
- echarts地图的引用
最近是跟echarts杠上了 所在公司是搞数据的 所以身为前端的我 就必须使用echarts将数据展示出来 ,进公司一周 ,前前后后大概用了八九种echarts图,我举得最难的就是引用的地图,因为刚开 ...
- echarts词云引用
最近项目中需要使用echarts的词云图,因为几经波折才引用成功,所以想记下来跟大家分享,(我的随笔不会写那么多让人需要动脑子去理解的东西,就是记录一下步骤,因为经验甚少,底层原理懂得不多,所以就先记 ...
- echarts 移动端地图数据可视化教程
如上效果图: 以下未代码: <!doctype html> <html lang="en"> <head> <meta charset ...
- echarts 移动端地图数据可视化开发教程
如上效果图: 以下未代码: <!doctype html> <html lang="en"> <head> <meta charset ...
- Echarts数据可视化,easyshu图表集成。
介绍: ECharts,一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,Firefox,Sa ...
- 项目实战:在线报价采购系统(React +SpreadJS+Echarts)
小伙伴们对采购系统肯定不陌生,小到出差路费.部门物资采购:大到生产计划.原料成本预估都会涉及到该系统. 管理人员可以通过采购系统减少管理成本,说是管理利器毫不过分,对于采购的效率提升也有极大帮助. 但 ...
- 【可视化】DataV接入ECharts图表库 可视化利器强强联手
DataV接入ECharts图表库 可视化利器强强联手 摘要: 两个扛把子级产品的结合,而且文末有彩蛋. DataV 数据可视化是搭建每年天猫双十一作战大屏的幕后功臣,ECharts 是广受数据可视化 ...
- 【教程】高德地图使用ECharts实现数据可视化
关于百度地图结合ECharts实现数据可视化的资料已经很多了,毕竟是官方提供支持的,这里就不再赘述.今天我们来讲一下让高德地图与ECharts结合来实现数据可视化图表的展示. 一.ECharts 高德 ...
- python+echarts+flask实现对全国疫情数据的爬取并可视化展示
用Python进行数据爬取并存储到数据库,3.15学习总结(Python爬取网站数据并存入数据库) - 天岁 - 博客园 (cnblogs.com) 通过echarts+flask实现数据的可视化展示 ...
随机推荐
- [题解] HDU 5115 Dire Wolf 区间DP
考虑先枚举所有的物品中最后拿走的,这样就分成了2个子问题,即先拿完左边的,再拿完右边的,最后拿选出的那个.令dp(i,j)表示拿完[i,j]所有物品的最小代价.你可能会说,我们拿[i,j]这一段物品的 ...
- 一文读懂Apache Geode缓存中间件
目录 一.对缓存中间件的诉求 1.1 我们为什么需要缓存中间件 1.2 缓存的分类 1.1.1 弱势缓存 1.1.2 强势缓存 二.什么是Apache Geode 2.1 Apache Geode的架 ...
- 2022“杭电杯”中国大学生算法设计超级联赛(6)- 1011 Find different
2022"杭电杯"中国大学生算法设计超级联赛(6)- 1011 Find different 比赛时队友开摆,还剩半个小时,怎么办?? 当然是一起摆 Solution 看到这个题没 ...
- 检测 MySQL 服务是否存活 shell脚本
#!/bin/bash # 检测 MySQL 服务是否存活 # host 为你需要检测的 MySQL 主机的 IP 地址,user 为 MySQL 账户名,passwd 为密码 # 这些信息需要根据实 ...
- Linux基础_3_文件/文件夹权限管理
注:权限遮罩码: 控制用户创建文件和文件夹的默认安全设置,文件默认权限为666-umask的值,文件夹默认权限为777-umask的值. root默认0022,普通用户默认0002. 文件的默认权限不 ...
- springboot+redis+虚拟机 springboot连接linux虚拟机中的redis服务
文章目录 1.前提条件:确保虚拟机开启.并且连接到redis 2.新建立一个springboot项目,创建项目时勾选web选项 3.在pom中引入redis依赖 4.在application.prop ...
- 齐博x1第三季《模板风格的制作》系列009-自定义区块代码
本节来说明如何自定义区块代码,不再继承上层模板,实现个性模板 上一节因为我们继承了layout布局模版,所以我们自定义的代码就无效了 如果我们继承了上层模板,那么相当于我们复制了一份上层模板的结构,也 ...
- 齐博x1内容页中下一页上一页的标签
在模板中分别插入如下代码即可 前一页 {:fun('content@prev',$info,20)} 后一页 {:fun('content@next',$info,20)} 复制 其中20代表取标题多 ...
- python基础爬虫,翻译爬虫,小说爬虫
基础爬虫: # -*- coding: utf-8 -*- import requests url = 'https://www.baidu.com' # 注释1 headers = { # 注释2 ...
- ES6 学习笔记(三)原始值与引用值
总结: 1.原始值,表示单一的数据,如10,"abc",true等. 1.1. ES的6种原始值: Undefined.Null.Boolean.Number.String.Sym ...