最新技术资源(建议收藏)

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结构,废话不说,直接上核心代码

  1. // 递归构建追踪树
  2. buildNodeTreeAndPaint = (spreadSource, trackCellInfo) => {
  3. let info = this.getCellInfo(trackCellInfo);
  4. let sheetSource = spreadSource.getSheetFromName(info.sheetName);
  5. // 创建跟节点
  6. let rootNode = this.creatNode(info.row, info.col, sheetSource, 0, "");
  7. let name = rootNode.sheetName + "*" + rootNode.row + "*" + rootNode.col + "*" + Math.random().toString();
  8. let precedentsRootNode = '';
  9. let dependentsRootNode = '';
  10. if (this.state.trackType === "Precedents" || this.state.trackType === "Both") {
  11. this.getNodeChild(rootNode, sheetSource, "Precedents")
  12. debugger;
  13. console.log(rootNode)
  14. if (this.state.trackType === "Both") {
  15. let rootNodeChildren = JSON.parse(JSON.stringify(rootNode.children));
  16. rootNode.children = [];
  17. precedentsRootNode = JSON.parse(JSON.stringify(rootNode));
  18. precedentsRootNode.children.push({
  19. name: "Precedents",
  20. value: "Precedents",
  21. children: rootNodeChildren
  22. })
  23. this.setState({
  24. precedentsRootNode: JSON.parse(JSON.stringify(precedentsRootNode)),
  25. })
  26. }
  27. }
  28. if (this.state.trackType === "Dependents" || this.state.trackType === "Both") {
  29. this.getNodeChild(rootNode, sheetSource, "Dependents")
  30. console.log(rootNode)
  31. if (this.state.trackType === "Both") {
  32. let deepInfo = [1];
  33. let rootNodeChildren = JSON.parse(JSON.stringify(rootNode.children));
  34. rootNode.children = [];
  35. dependentsRootNode = JSON.parse(JSON.stringify(rootNode));
  36. dependentsRootNode.children.push({
  37. name: "Dependents",
  38. value: "Dependents",
  39. children: rootNodeChildren
  40. })
  41. this.setState({
  42. dependentsRootNode: JSON.parse(JSON.stringify(dependentsRootNode)),
  43. })
  44. }
  45. }
  46. if (this.state.trackType === "Both") {
  47. precedentsRootNode.children = precedentsRootNode.children.concat(dependentsRootNode.children);
  48. // let bothRootNode = precedentsRootNode.children[0].children.concat(dependentsRootNode.children[0].children)
  49. this.setState({
  50. rootNode1: JSON.parse(JSON.stringify(precedentsRootNode)),
  51. })
  52. } else {
  53. this.setState({
  54. rootNode1: JSON.parse(JSON.stringify(rootNode)),
  55. })
  56. }
  57. }
  58. creatNode = (row, col, sheet, deep, trackType) => {
  59. let node = {
  60. value: sheet.getValue(row, col),
  61. position: sheet.name() + "!" + GC.Spread.Sheets.CalcEngine.rangeToFormula(new GC.Spread.Sheets.Range(row, col, 1, 1)),
  62. deep: deep,
  63. name: `${sheet.name()}!${GC.Spread.Sheets.CalcEngine.rangeToFormula(new GC.Spread.Sheets.Range(row, col, 1, 1))}\nvalue:${sheet.getValue(row, col)}`,
  64. sheetName: sheet.name(),
  65. row: row,
  66. col: col,
  67. trackType: trackType
  68. };
  69. return node;
  70. }
  71. getNodeChild = (rootNode, sheet, trackType) => {
  72. let childNodeArray = [];
  73. let children = [];
  74. let row = rootNode.row, col = rootNode.col, deep = rootNode.deep;
  75. if (trackType == "Precedents") {
  76. children = sheet.getPrecedents(row, col);
  77. }
  78. else {
  79. children = sheet.getDependents(row, col);
  80. }
  81. // let self = this;
  82. if (children.length >= 1) {
  83. children.forEach((node) => {
  84. let row = node.row,
  85. col = node.col,
  86. rowCount = node.rowCount,
  87. colCount = node.colCount,
  88. _sheet = sheet.parent.getSheetFromName(node.sheetName);
  89. if (rowCount > 1 || colCount > 1) {
  90. for (let r = row; r < row + rowCount; r++) {
  91. for (let c = col; c < col + colCount; c++) {
  92. let newNode = this.creatNode(r, c, _sheet, deep + 1, trackType)
  93. // if (deep < self.maxDeep) {
  94. this.getNodeChild(newNode, _sheet, trackType);
  95. // }
  96. childNodeArray.push(newNode);
  97. }
  98. }
  99. } else {
  100. let newNode = this.creatNode(row, col, _sheet, deep + 1, trackType)
  101. // if (deep < self.maxDeep) {
  102. this.getNodeChild(newNode, _sheet, trackType);
  103. // }
  104. childNodeArray.push(newNode);
  105. }
  106. });
  107. }
  108. rootNode.children = childNodeArray;
  109. }

五.将构造好的引用和从属树rootNode在Echarts中渲染

  1. myChart.setOption(
  2. (option = {
  3. tooltip: {
  4. trigger: 'item',
  5. triggerOn: 'mousemove'
  6. },
  7. series: [
  8. {
  9. type: 'tree',
  10. data: [this.state.rootNode1],
  11. top: '1%',
  12. left: '15%',
  13. bottom: '1%',
  14. right: '7%',
  15. symbolSize: 10,
  16. orient: this.state.trackType === 'review'?'LR':'RL',
  17. label: {
  18. position: this.state.trackType === 'review'?'left':'right',
  19. verticalAlign: 'middle',
  20. align: this.state.trackType === 'review'?'right':'left',
  21. },
  22. leaves: {
  23. label: {
  24. position: this.state.trackType === 'review'?'right':'left',
  25. verticalAlign: 'middle',
  26. align: this.state.trackType === 'review'?'left':'right'
  27. }
  28. },
  29. emphasis: {
  30. focus: 'descendant'
  31. },
  32. // layout: 'radial',
  33. expandAndCollapse: true,
  34. animationDuration: 550,
  35. animationDurationUpdate: 750
  36. }
  37. ]
  38. })
  39. );
  40. option && myChart.setOption(option);

以上就是实现报表中公式引用从属关系Echarts可视化的核心实现逻辑,由于工程较大,如需获取源码,可私信获取。

拓展阅读

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

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

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

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

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

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

  2. 利用echarts展示旅行足迹

    前言 一直有个环游世界的梦,周游列国,体验不同国家的人类文明,寻山访水,体验造物主大自然的伟大造化.毕竟人生不止眼前的苟且,还有诗和远方.这么多年以来,陆续走过了一些地方,每到一个地方,都让我离梦想又 ...

  3. 利用Echarts设计一个图表平台(一)

    Echarts是一款百度的开源图表库,里面提供了非常多的图表样式,我们今天要讲的内容是利用这一款开源js图表,制作一个能够动态定制的图表平台. 1)Echarts API介绍 首先我们先来看一下Ech ...

  4. echarts地图的引用

    最近是跟echarts杠上了 所在公司是搞数据的 所以身为前端的我 就必须使用echarts将数据展示出来 ,进公司一周 ,前前后后大概用了八九种echarts图,我举得最难的就是引用的地图,因为刚开 ...

  5. echarts词云引用

    最近项目中需要使用echarts的词云图,因为几经波折才引用成功,所以想记下来跟大家分享,(我的随笔不会写那么多让人需要动脑子去理解的东西,就是记录一下步骤,因为经验甚少,底层原理懂得不多,所以就先记 ...

  6. 利用ECharts开发的步骤

    引入Echarts的相关库文件,以及自定义的js文件 <script src="${pageContext.request.contextPath}/js/echarts/source ...

  7. 利用echarts自定义环形图

    一.代码 app.title = '通讯盒各版本用户占比'; option = { backgroundColor: '#0f0f31', title: { show:true, x:"le ...

  8. 利用echarts做图表统计

    以项目中的扇形统计图为例: 首先,第一步: 引入外部echarts.js文件 其次,第二步: HTML代码块 <div class="count-body-con count-tj&q ...

  9. 利用Echarts实现全国各个省份数据占比,图形为中国地图

    最近项目需求,需要一个对于全国各个省份的数据分析,图形最好是地图的样子,这样子更为直观. 最先想到的图表插件是Echarts,他的文档相对于阿里的G2,G6更加清晰一些.在Echarts 里找到的个 ...

  10. 利用echarts highcharts 实现自定义地图 关系图效果 侧边3D柱形图饼图散点图

    github 地址:  https://https://github.com/Gengshaoxuan/medataMap github 地址:  https://https://github.com ...

随机推荐

  1. 网络安全—Kerberos认证系统

    文章目录 前提知识 原理 第一次对话 第二次对话 第三次对话 总结发现 前提知识 KDC:由AS.TGS,还有一个Kerberos Database组成. Kerberos Database用来存储用 ...

  2. 后台生成单个Word文档

    在实际项目开发中经常会遇到一种场景,客户希望点击页面上的生成文件按钮,执行程序动态填充数据到Word模板,直接在后台生成Word文档,而无需显示Word文档.目前网上有一些针对此需求的方案,但每个方案 ...

  3. 二:nacos 的服务注册

    一:怎么引用依赖 dependencyManagement:spring cloud alibaba 的版本,由于spring cloud alibaba 还未纳入spring cloud 的主版本管 ...

  4. .net core DataTable.Load()方法,返回的行缺少,少于reader读出的行

    我分析的原因是,datatable模式的schema默认是根据查询的sql来的.起因是我写的sql中带有主键的列,查出来有很多重复值, 然后dt.load会默认把主键重复的行给合并掉,所以最终查询出来 ...

  5. pyinstaller 打包无窗口python http.server无法启动

    最近在写一个简单的文件服务器用来访问静态文件,遇到在pyinstaller无窗口模式下无法启动的问题,记录一下解决方案. 原因:http.server需要将记录输出到窗口,而pyinstaller打包 ...

  6. 这是一个基于threading可停止线程的有限容量有限并行度的python任务管理器

    这是一个可停止线程的有限容量有限并行度的任务管理器 基于:GitHub - AlitaIcon/StopableThreadJob: 可停止线程任务管理器 Quick Start 基础调用与效果 im ...

  7. C++笔记(3)引用

    引用是变量的别名.也就是说,它是某个已存在变量的另一个名字.一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量. 1.创建引用 int i = 0; int& r = i;/ ...

  8. 【 INFINI Workshop 上海站】7 月 27 日一起动手实验玩转 Easysearch

    [ INFINI Workshop 上海站]7 月 27 日下午 和 INFINI Labs 的技术专家面对面,第一时间了解极限实验室的发布最新产品和功能特性,通过动手实战,快速掌握最前沿的搜索技术, ...

  9. HP惠普战66电源黄灯闪烁无法充电

    HP惠普战66电源黄灯闪烁无法充电 TYPE-C PD 无法充电. 解决办法:关机状态下,拔除外部设备,长按电源键30秒以释放主板静电,再插电源线可以开机.

  10. ChatGPT应用与实践初探

    近期,长江商学院EMBA38期&甄知科技开展了题为"ChatGPT应用与实践初探"的线下沙龙活动,由上海甄知科技创始合伙人兼CTO张礼军主讲,主要给大家解密最近很火的Cha ...