通过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){
// 列1
case 1:
// 判断是否为一级栏目,并且文本不为空创建对象
if(column.Text){
JsonFirstIndex++;
// 创建一级对象
JsonData[JsonFirstIndex] = {
name: column.Text,
children: []
};
}
break;
// 列2
case 2:
// 判断是否为二级栏目,并且文本不为空创建对象
if(column.Text){
let secondArr = JsonData[JsonFirstIndex]['children'];
// 如果一级children为数组,则自递索引,新增二级数据
if(Array.isArray(secondArr)){
JsonSecondIndex++;
secondArr[JsonSecondIndex] = {
name: column.Text,
children: []
}
}
}
break;
// 列3
case 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){
// 列1
case 1:
// 判断是否为一级栏目,并且文本不为空创建对象
if(column.Text){
JsonFirstIndex++;
// 创建一级对象
JsonData[JsonFirstIndex] = {
name: column.Text,
children: []
};
}
break;
// 列2
case 2:
// 判断是否为二级栏目,并且文本不为空创建对象
if(column.Text){
let secondArr = JsonData[JsonFirstIndex]['children'];
// 如果一级children为数组,则自递索引,新增二级数据
if(Array.isArray(secondArr)){
JsonSecondIndex++;
secondArr[JsonSecondIndex] = {
name: column.Text,
children: []
}
}
}
break;
// 列3
case 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){
// 列1
case 1:
// 判断是否为一级栏目,并且文本不为空创建对象
if(column.Text){
JsonFirstIndex++;
// 创建一级对象
JsonData[JsonFirstIndex] = {
name: column.Text,
children: []
};
}
break;
// 列2
case 2:
// 判断是否为二级栏目,并且文本不为空创建对象
if(column.Text){
let secondArr = JsonData[JsonFirstIndex]['children'];
// 如果一级children为数组,则自递索引,新增二级数据
if(Array.isArray(secondArr)){
JsonSecondIndex++;
secondArr[JsonSecondIndex] = {
name: column.Text,
children: []
}
}
}
break;
// 列3
case 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对象一样功能的,欢迎留言告知。