xmind文件如图所示,

最终生成的数据结构如图 

2,选择导出为excel文件,导出的excel文件打开如图

3,安装node读取excel模块 cnpm i  node-xlsx --save

4,使用node-xlsx模块读取excel文件,注意文件名不能为中文,

使用示例

var xlsx2json = require("node-xlsx");
var list = xlsx2json.parse("./test3.xlsx");
读取出的excel数据如图

5,分析该数据结构和实际的excel可以发现,node模块读取是按excel一行一行的读取,未读取到的就是null,例如,第一行读取到的

因为第一行中一些单元格合并为了一个,所以node模块读取的时候是按照一行读取的,所以数组第二项读取的前四项都为空

接下来是实现将读取到的数组转换为json数据的核心部分,

主要由3个函数组成

function arrToJson(arr, column) { //将数组转换为嵌套的json对象
    let MaxLength = arr.length - 1;
    let deep = {}
    for (let index = MaxLength; index >= 0; index--) {
        if (arr[index] === null) {
            break;
        }
        let obj = {};
        if (Object.keys(deep).length > 0) {
            let childArr = []
            obj['id'] = String(column) + '_' + String(index)
            obj['text'] = arr[index]
            childArr.push(deep)
            obj['children'] = childArr;
            deep = obj
        } else {
            obj['id'] = String(column) + '_' + String(index)
            obj['text'] = arr[index]
            deep = obj
        }
    }
    return deep;
}
改函数作用是将每一行中的有效数据转为具有层级的数形结构,对比node模块读取出的数据和excel的数据规律可以发现

每一行数据可以转化为如图嵌套的结构,数组的长度就是当前行的最大深度,

将最初的数组的每一项都转为该结构如图

6,再次分析node模块读取的数据和excel规律可以发现

第二行为个null,代表第一行的前四个数据,因此,只需要将第二行生成的嵌套对象和第一行生成的嵌套对象合并,再将第二行数据和第三行数据合并3->4合并,后边以此类推即可得到完整的tree,

但是有一个问题,假设同样有两个第三级的数据我怎么能知道后一项是插入第三级的哪一项中呢,其实观察数据的规律不难发现,每次插入的时候只需要获取当前数据所在项的深度,然后插入到比当前数据深度多一的父级的最后插入当前数据,即可保证插入的层级不会错误,

实现代码如下

function createTree(arr) { //生成最终树
    let renderTree = {}
     arr=JSON.parse(JSON.stringify(arr))
    arr.forEach((element, index) => {
        let result = arrToJson(element, index);
        if (Object.keys(renderTree).length > 0) {
            renderTree = getMergeTree(renderTree, result)
        } else {
            renderTree = getMergeTree(result, null)
        }
    });
    writeJson(renderTree)
}
function getMergeTree(parentobj, currentobj) { //生成合并的树
    if (currentobj == null) {
        return parentobj;
    }
    let resultObj = {}
    DFS(parentobj, currentobj);
    function DFS(parentobj, currentobj) {
        let idNumber;
        try {
            idNumber = Number(currentobj.id.split('_')[1]) - 1
        } catch (error) {
            idNumber = -10;
        }
        let child = parentobj.children;
        if (child !== undefined && child.length > 0) {
            let childrenLength = child.length - 1
            let parentId = Number(parentobj.id.split('_')[1])
            if (parentId == idNumber) {
                child.push(currentobj)
            }
            DFS(child[childrenLength], currentobj)
            resultObj = parentobj
        }
    }
    return resultObj
}
该函数是一个DFS搜索算法,搜索出比当前级大一级的父级对象树,并且在父级树的children数组的最后一项插入当前对象
如图是前四项生成的json对象和第五项的合并

完整代码如下:

var xlsx2json = require("node-xlsx");
var list = xlsx2json.parse("./test3.xlsx");
var fs = require("fs")
let testarr = [
    ['教育心理学', '教育心理学概述', '教育心理学的基本内涵', '研究对象与研究内容', '概念'],
    [null, null, null, null, '学科性质'],
    [null, null, null, null, '研究内容', '五要素三过程'],
    [null, null, null, '教育心理学与普通心理学的关系'],
    [null, null, null, '教育心理学的作用', '描述'],
    [null, null, null, null, '解释'],
    [null, null, null, null, '预测'],
    [null, null, null, null, '控制'],
    [null, null, "教育心理学的发展史", "初创时期", "裴斯泰洛齐"],
    [null, null, null, null, "赫尔巴特"],
    [null, null, null, null, "桑代克"],
    [null, null, null, "发展时期", "小原又一"],
    [null, null, null, null, "廖世承"],
    [null, null, null, "成熟时期", "布鲁纳"],
]
createTree(list[0].data)//使用node读取的数组数据
// createTree(testarr)//测试,使用testarr数据可直接查看生成的数据,测试数据采用真实的一部分数据
// let totalobj={"id":"0_0","text":"教育心理学","children":[{"id":"0_1","text":"教育心理学概述","children":[{"id":"0_2","text":"教育心理学的基本内涵","children":[{"id":"0_3","text":"研究对象与研究内容","children":[{"id":"0_4","text":"概念"}]}]}]}]}
// let resultObj= getMergeTree(totalobj,{"id":"1_4","text":"学科性质"})
// console.log(JSON.stringify(resultObj));
function createTree(arr) { //生成最终树
    let renderTree = {}
     arr=JSON.parse(JSON.stringify(arr))
    arr.forEach((element, index) => {
        let result = arrToJson(element, index);
        if (Object.keys(renderTree).length > 0) {
            renderTree = getMergeTree(renderTree, result)
        } else {
            renderTree = getMergeTree(result, null)
        }
    });
    writeJson(renderTree)
}
function arrToJson(arr, column) { //将数组转换为嵌套的json对象
    let MaxLength = arr.length - 1;
    let deep = {}
    for (let index = MaxLength; index >= 0; index--) {
        if (arr[index] === null) {
            break;
        }
        let obj = {};
        if (Object.keys(deep).length > 0) {
            let childArr = []
            obj['id'] = String(column) + '_' + String(index)
            obj['text'] = arr[index]
            childArr.push(deep)
            obj['children'] = childArr;
            deep = obj
        } else {
            obj['id'] = String(column) + '_' + String(index)
            obj['text'] = arr[index]
            deep = obj
        }
    }
    return deep;
}
function getMergeTree(parentobj, currentobj) { //生成合并的树
    if (currentobj == null) {
        return parentobj;
    }
    let resultObj = {}
    DFS(parentobj, currentobj);
    function DFS(parentobj, currentobj) {
        let idNumber;
        try {
            idNumber = Number(currentobj.id.split('_')[1]) - 1
        } catch (error) {
            idNumber = -10;
        }
        let child = parentobj.children;
        if (child !== undefined && child.length > 0) {
            let childrenLength = child.length - 1
            let parentId = Number(parentobj.id.split('_')[1])
            if (parentId == idNumber) {
                child.push(currentobj)
            }
            DFS(child[childrenLength], currentobj)
            resultObj = parentobj
        }
    }
    return resultObj
}
function writeJson(arrlist) {
    fs.writeFile('person.json', JSON.stringify(arrlist), function (err) {
        if (err) {
            console.error(err);
        }
        console.log('----------新增成功-------------');
    })
}
 
 

使用node.js将xmind导出的excel转换为json树的更多相关文章

  1. tablib把数据导出为Excel、JSON、CSV等格式的Py库(写入数据并导出exl)

    #tablib把数据导出为Excel.JSON.CSV等格式的Py库 #python 3 import tablib #定义列标题 headers = ('1列', '2列', '3列', '4列', ...

  2. Node.js模块导入导出

    这篇文章本来是想模块导入导出和事件循环一起写的,但是感觉一起写的话会太长了,所以就分开两篇文章写吧.下一篇会重点介绍一下js中的事件循环,js代码到底是以何种顺序去执行的呢?我相信你看懂了事件循环再去 ...

  3. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 解析JSON

    视频地址:https://www.cctalk.com/v/15114923886141 JSON 数据 我颠倒了整个世界,只为摆正你的倒影. 前面的文章中,我们已经完成了项目中常见的问题,比如 路由 ...

  4. C# Excel转换为Json

    demo:https://files.cnblogs.com/files/guxingy/Excel%E8%BD%AC%E6%8D%A2%E4%B8%BAJson%E5%AF%B9%E8%B1%A1. ...

  5. 在Node.js中使用ejsexcel输出EXCEL文件

    1.背景 在Nodejs应用程序中输出Excel,第一印象想到的一般是node-xlsx,这类插件不仅需要我们通过JS写入数据,还需要通过JS进行EXCEL显示样式的管理. 这是个大问题,不仅代码冗余 ...

  6. 有趣的Node爬虫,数据导出成Excel

    最近一直没更新了诶,因为学习Backbone好头痛,别问我为什么不继续AngularJs~因为2.0要出来了啊,妈蛋!好,言归正传,最近帮我的好基友扒数据,他说要一些股票债券的数据.我一听,那不就是要 ...

  7. js实现table导出为Excel文件

    1.首先创建好表格. 2.然后在js中写三个方法 1)判断浏览器 2)定义文档类型 template : 定义文档的类型,相当于html页面中顶部的<!DOCTYPE> 声明.(个人理解, ...

  8. 关于Node.js中HTTP请求返回数据需要JSON解析的问题

    在编写项目过程中,需要用到实时数据的推送需求, 所以首先想到了NodeJS的websocket模块 在网上找了一个聊天室的例子  然后将其改为自己需求的推送 其中遇到的问题 返回数据问题  :   由 ...

  9. node.js + webstorm :配置开发环境

    一.配置开发环境: 1.先安装node (1).访问http://nodejs.org打开安装包,正常安装,点击next即可. 为了测试是否安装成功,打开命令提示符,输入node,则进入node.js ...

随机推荐

  1. 跳跳棋——二分+建模LCA

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 我们用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  2. 参观路线——并查集+dfs

    题目描述 Lambdaland由N个城市组成,任两个城市间都有一条道路相连.  下个月TBL准备参观Lambdaland.他将从城市1开始,以深度优先搜索顺序参观能所有遍历到的城市. 由于TBL是一位 ...

  3. 大数据之路day02_1--运算符

    运算符这一节主要是介绍算数运算符.赋值运算符.比较运算符.逻辑运算符.三元运算符.接下来一一介绍. 1.算数运算符 ++ 和 -- 的用法 例如:a++ 和 ++a的区别 %的应用场景(取模其实就是取 ...

  4. C语言程序设计100例之(4):水仙花数

    例4    水仙花数 题目描述 一个三位整数(100-999),若各位数的立方和等于该数自身,则称其为“水仙花数”(如:153=13+53+33),找出所有的这种数. 输入格式 没有输入 输出格式 若 ...

  5. php imagick蒙版做法

    php imagick蒙版做法<pre> $image = new \Imagick(); $image->readImage(__DIR__ . '/mengban.png'); ...

  6. Spring 应用之Spring JDBC实现

    jdbcTemplate类的入门 方式一 POM.XML <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:x ...

  7. ASP.NET Core 1.0: API的输入参数

    Web API是需要接受参数的,譬如,通常用于创建数据的POST method需要接受输入数据,而用于GET method也需要接受一些可选参数,譬如:为了性能起见,控制返回数据的数量是至关重要的. ...

  8. Salesforce学习之路(十一)Aura组件属性<aura:attribute />

    1. <aura:attribute />语法 Aura组件属性类似与Apex中类的成员变量(或者说Java中类的成员变量).他们是组件在特定的实例上设置的类型化字段,可以使用表达式语法从 ...

  9. 菜鸟手把手学Shiro之shiro认证流程

    一.使用的spring boot +mybatis-plus+shiro+maven来搭建项目框架 <!--shiro--> <dependency> <groupId& ...

  10. 如何打造一款m3u8视频爬虫

    0.前言 m3u8是一种很常见的网页视频播放器的视频源,比如说中国大学MOOC中课程就是使用了该种视频格式. 随便打开一门课程,就可以发现在网络请求中存在一个m3u8的文件,在preview中预览,它 ...