通过Excel JS宏,将表格中的数据以”列“形式导出为JSON数据格式。
我们在整理文档时,产品会通过Excel将功能点和功能描述分层级整理出来,有时需要将此数据导入到系统中,Web端对Json这类数据比较友好,所以这里试着使用Excel JS宏将数据导出为JSON数据。
图1-1
如上图,我们将此信息生成为树结构的JSON数据格式的文本文件。
一、宏创建
1.1 定义宏
首先,打开Excel中的宏编辑器,在模块中定义宏,代码如下:
/*** 创建将Excel数据转换为JSON格式的数据宏*/
function 数据转换为JSON数据(){}
如果对JS宏还不了解朋友,或不知道在哪创建宏的,可以看下前面写的一篇,地址:
WPS Office JS宏实现批量处理Word中的表格样式-CSDN博客
1.2 获取内容
Sheets 对象指定的或活动工作簿中所有工作表的集合。Sheets 集合可以包含 Chart 或 Worksheet 对象。使用 Sheets(index)(其中 index 是工作表名称或索引号)可返回一个 Chart 或 Worksheet 对象。
所以通过Sheets对象获取Sheet 1中的数据内容,UsedRange返回一个 Range 对象,该对象表示指定工作表上所使用的区域。代码如下:
/*** 创建将Excel数据转换为JSON格式的数据宏*/
function 数据转换为JSON数据(){// 获取Sheet 1内容let wbContent = Sheets("Sheet1").UsedRange;}
Sheets()可以使用ThisWorkbook.Sheets()调用,这里可以省略ThisWorkbook。
1.3 获取行数据
图1-1中,每列对应一个字段,所以在读取数据时,我们需要一行一行读取,读取每行数据后,再通过列关联上对应数据。
这里将通过Rows对象获取到每行数据集,以及通过Cells获取每行中对应列的单元格数据,代码如下:
/*** 创建将Excel数据转换为JSON格式的数据宏*/
function 数据转换为JSON数据(){// 获取Sheet 1内容let wbContent = Sheets("Sheet1").UsedRange;// 获取所有行数据let dataRows = wbContent.Rows;// 定义变量存储json数据let JsonData = [];// 循环输出数据for(let rows of dataRows){// 循环出每列数据for(let column of rows.Cells){console.log('column', column.Column, column.Text);}}
}
如上代码执行后,获取结果如下图:
1.4 组装数据
数据获取到后,如何将数据组装成JSON格式树状数据,需要通过一些简单逻辑判断即可,由1.3中输出结果可以看出,第1、2两列会出现空数据,所以由此可以判断出对应的一级和二级数据,代码如下:
/*** 创建将Excel数据转换为JSON格式的数据宏*/
function 数据转换为JSON数据(){// 获取Sheet 1内容let wbContent = Sheets("Sheet1").UsedRange;// 获取所有行数据let dataRows = wbContent.Rows;// 定义变量存储json数据let JsonData = [];// 存储索引let JsonFirstIndex = -1, //一级目录JsonSecondIndex = -1; //二级目录// 循环输出数据for(let rows of dataRows){// 循环出每列数据for(let column of rows.Cells){switch(column.Column){// 列1case 1: // 判断是否为一级栏目,并且文本不为空创建对象if(column.Text){JsonFirstIndex++;// 创建一级对象JsonData[JsonFirstIndex] = {name: column.Text,children: []};}break;// 列2case 2: // 判断是否为二级栏目,并且文本不为空创建对象if(column.Text){let secondArr = JsonData[JsonFirstIndex]['children'];// 如果一级children为数组,则自递索引,新增二级数据if(Array.isArray(secondArr)){JsonSecondIndex++;secondArr[JsonSecondIndex] = {name: column.Text,children: []}}}break;// 列3case 3: let threeArr = JsonData[JsonFirstIndex].children[JsonSecondIndex]['children'];// 如果二级children为数组,则追加数据,列3为末级功能,列4为功能描述,都在此组装if(Array.isArray(threeArr)){threeArr.push({name: rows.Cells.Item(3).Text,description: rows.Cells.Item(4).Text});}break;}}}console.log(JSON.stringify(JsonData));
}
此时,Json数据则组装完成了,输出后结果如下:
二、输出Json数据
2.1 JSON.stringify()
语法:JSON.stringify(value, replacer , space)
属性
名称 | 描述 |
---|---|
value | 将要序列化成 一个JSON 字符串的值。 |
replace(可选) | 如果该参数是一个函数,则在序列化过程中,被序列化的值的每个属性都会经过该函数的转换和处理;如果该参数是一个数组,则只有包含在这个数组中的属性名才会被序列化到最终的 JSON 字符串中;如果该参数为null或者未提供,则对象所有的属性都会被序列化。 |
space(可选) | 指定缩进用的空白字符串,用于美化输出(pretty-print);如果参数是个数字,它代表有多少的空格;上限为10。该值若小于1,则意味着没有空格;如果该参数为字符串(字符串的前十个字母),该字符串将被作为空格;如果该参数没有提供(或者为null)将没有空格。 |
2.2 输出序列化json数据
/*** 创建将Excel数据转换为JSON格式的数据宏*/
function 数据转换为JSON数据(){// 获取Sheet 1内容let wbContent = Sheets("Sheet1").UsedRange;// 获取所有行数据let dataRows = wbContent.Rows;// 定义变量存储json数据let JsonData = [];// 存储索引let JsonFirstIndex = -1, //一级目录JsonSecondIndex = -1; //二级目录// 循环输出数据for(let rows of dataRows){// 循环出每列数据for(let column of rows.Cells){switch(column.Column){// 列1case 1: // 判断是否为一级栏目,并且文本不为空创建对象if(column.Text){JsonFirstIndex++;// 创建一级对象JsonData[JsonFirstIndex] = {name: column.Text,children: []};}break;// 列2case 2: // 判断是否为二级栏目,并且文本不为空创建对象if(column.Text){let secondArr = JsonData[JsonFirstIndex]['children'];// 如果一级children为数组,则自递索引,新增二级数据if(Array.isArray(secondArr)){JsonSecondIndex++;secondArr[JsonSecondIndex] = {name: column.Text,children: []}}}break;// 列3case 3: let threeArr = JsonData[JsonFirstIndex].children[JsonSecondIndex]['children'];// 如果二级children为数组,则追加数据,列3为末级功能,列4为功能描述,都在此组装if(Array.isArray(threeArr)){threeArr.push({name: rows.Cells.Item(3).Text,description: rows.Cells.Item(4).Text});}break;}}}// 将数据转换为JSON格式字符串let jsonStringData = JSON.stringify(JsonData, null, 2);console.log(jsonStringData);
}
通过JSON.stringify()将json数据进行序列化后,并缩进2位显得更为美观,输出结果如下图:
2.3 保存json数据
从数据的读取,分析,以及json数据组装工作已完成,现在咱们则将最终的数据导出为json格式文件,代码如下:
/*** 创建将Excel数据转换为JSON格式的数据宏*/
function 数据转换为JSON数据(){// 获取Sheet 1内容let wbContent = Sheets("Sheet1").UsedRange;// 获取所有行数据let dataRows = wbContent.Rows;// 定义变量存储json数据let JsonData = [];// 存储索引let JsonFirstIndex = -1, //一级目录JsonSecondIndex = -1; //二级目录// 循环输出数据for(let rows of dataRows){// 循环出每列数据for(let column of rows.Cells){switch(column.Column){// 列1case 1: // 判断是否为一级栏目,并且文本不为空创建对象if(column.Text){JsonFirstIndex++;// 创建一级对象JsonData[JsonFirstIndex] = {name: column.Text,children: []};}break;// 列2case 2: // 判断是否为二级栏目,并且文本不为空创建对象if(column.Text){let secondArr = JsonData[JsonFirstIndex]['children'];// 如果一级children为数组,则自递索引,新增二级数据if(Array.isArray(secondArr)){JsonSecondIndex++;secondArr[JsonSecondIndex] = {name: column.Text,children: []}}}break;// 列3case 3: let threeArr = JsonData[JsonFirstIndex].children[JsonSecondIndex]['children'];// 如果二级children为数组,则追加数据,列3为末级功能,列4为功能描述,都在此组装if(Array.isArray(threeArr)){threeArr.push({name: rows.Cells.Item(3).Text,description: rows.Cells.Item(4).Text});}break;}}}// 将数据转换为JSON格式字符串let jsonStringData = JSON.stringify(JsonData, null, 2);// 创建新的工作簿并保存为JSON文件let filePath = "D:\\workspace\\work\\office-study\\data\\data.json";// 将JSON数据写入文件// 打开文件Open(filePath, '#1', jsOutput, jsWrite, jsLockWrite, jsonStringData.length*2);// 写入数据Write('#1', jsonStringData);// 关闭流Close('#1');// 提示MsgBox("数据保存成功~", jsInformation, "提示");
}
此时点击运行按钮,则文件保存到filePath指定的位置了,如下图:
data.json内容如下图:
细心朋友此时会发现导出的json数据开头和结尾,会多出一个双引号。这里查了下VBA文档:
- Write #和 Input #旨在与“结构化”文件 (.csv) 一起使用,并使用文本限定数据 - 任何 String或 Variant带有字符串子类型的双引号转义为 "" , 整个事情都用引号括起来。
- Print #和 Input(number, #filenumber)旨在与“非结构化”文件一起使用。
在WPS中没找到Print对象,这里就先手动删除,有朋友在WPS发现有和Print对象一样功能的,欢迎留言告知。