应用python、nodejs、xlsx.full.min.js解决省市区excel数据转成json**

需要形容:通常会拿到excel这样的数据格式,然而咱们在代码里应用个别是json类型的数据,因而须要将excel里的数据内容转成json格局的。可通过三种办法实现:python、nodejs+mongodb、xlsx.full.min.js

一、python

Python 是一种解释型、面向对象、动静数据类型的高级程序设计语言。

1、特点:
1.易于学习:Python有绝对较少的关键字,构造简略,和一个明确定义的语法,学习起来更加简略。

2.易于浏览:Python代码定义的更清晰。

3.易于保护:Python的胜利在于它的源代码是相当容易保护的。

4.一个宽泛的规范库:Python的最大的劣势之一是丰盛的库,跨平台的,在UNIX,Windows和Macintosh兼容很好。

5.互动模式:互动模式的反对,您能够从终端输出执行代码并取得后果的语言,互动的测试和调试代码片断。

6.可移植:基于其凋谢源代码的个性,Python曾经被移植(也就是使其工作)到许多平台。

7.可扩大:如果你须要一段运行很快的要害代码,或者是想要编写一些不愿凋谢的算法,你能够应用C或C++实现那局部程序,而后从你的Python程序中调用。

8.数据库:Python提供所有次要的商业数据库的接口。

9.GUI编程:Python反对GUI能够创立和移植到许多零碎调用。

10.可嵌入: 你能够将Python嵌入到C/C++程序,让你的程序的用户取得"脚本化"的能力。

2、python环境搭建

3、运行python文件

// aa.pyprint('hello');//运行python a.py

4、运行代码

import jsonimport pandas as pdclass BookTree:    def __init__(self, excel_path, out_file):        self.excel_path = excel_path        self.fp = open(out_file, 'w')    def get_name(self, lt):        lt1 = []        for i in lt:            if str(i).strip() and i not in lt1:                lt1.append(i)        return lt1    def parse_data(self, df, num):        code_ = '行政区域代码' + str(num)        name_ = '行政区域名称' + str(num)        if num == 3:            codes = self.get_name(df[code_].tolist())            lt = []            for code in codes:                dic = {}                dic['code'] = str(code).strip()                name = df[df[code_] == code][name_].tolist()[0].strip()                dic['name'] = name                lt.append(dic)            return lt        else:            codes = self.get_name(df[code_].tolist())            lt = []            for code in codes:                dic = {}                dic['code'] = str(code).strip()                name_lt = df[df[code_] == code][name_].tolist()                dic['name'] = name_lt[0].strip()                chil = self.parse_data(df[df[code_] == code], num + 1)                if chil:                    dic['children'] = chil                lt.append(dic)            return lt    def get_df(self):        df = pd.read_excel(self.excel_path, dtype=object)        df = df.dropna(how='all').fillna('')        city = self.parse_data(df, 1)        print(json.dumps({'city': city}, ensure_ascii=False, indent=4), file=self.fp)    def process(self):        self.get_df()def main():    excel_path = 'test.xlsx'    out_file = 'test.json'    book_tree = BookTree(excel_path, out_file)    book_tree.process()if __name__ == '__main__':    main()

5、代码解析

二、js实现

1、xlsx.full.min.js
是一个前端上传excel解析工具,将excel表格额数据解析为json模式。
反对xls、xlsx、cds等格局

2、代码实现

<!DOCTYPE html><html><head>    <meta charset="UTF-8">    <title>Excel Analysis</title>    <style>    h1 {        text-align: center;    }    #input {        white-space: pre;        margin: 20px 0;    }    #drop {        border: 2px dashed #bbb;        border-radius: 5px;        padding: 25px;        text-align: center;        font: 20pt bold;        color: #bbb;    }    #xlf {        float: left;    }    #output {        resize: vertical;        white-space: pre-wrap;        box-sizing: border-box;        width: 100%;        height: 200px;        padding: 10px;        font-size: 12px;        line-height: 18px;    }    </style></head><body>    <h1>Excel Analysis</h1>    <div id="input">        <div id="drop">Drop a spreadsheet file here to see sheet data</div>        <div>Or click here to select a file:</div>        <input type="file" id="xlf">    </div>    <textarea id="output"></textarea>    <script src="https://cdn.bootcdn.net/ajax/libs/xlsx/0.16.9/xlsx.full.min.js"></script>    <!-- <script src="//oss.sheetjs.com/js-xlsx/xlsx.full.min.js"></script> -->    <script>        /* eslint-disable */        let processWb = (function () {            let out = document.getElementById('output');            let toJson = function (workbook) {                let result = {};                workbook.SheetNames.forEach(function (sheetName) {                    let roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {                        header: 1                    });                    if (roa.length) {                        result[sheetName] = roa;                    }                });                return JSON.stringify(result, 2, 2);            };            let processCode = function (code) {                let result = [];                let k = 0;                for (let i = 0; i <= code.length - 1; i++) {                    if (i > 0 && (code[i][0] !== code[i - 1][0])) {                        k++;                    }                    result[k] = result[k] || {};                    result[k]['code'] = String(code[i][0]);                    result[k]['name'] = code[i][1];                    let rr = recursive(code[i].slice(2, code[i].length));                    result[k]['children'] = combine(result[k]['children'], rr);                }                let json = {                    resultCode: '000000',                    resultMsg: '胜利',                    resultData: result                };                return JSON.stringify(json);            };            let recursive = function (data) {                let result = {code: String(data[0]), name: data[1]};                if (data.length <= 2) {                    return result;                } else {                    result['children'] = [recursive(data.slice(2, data.length))];                    return result;                }            };            let combine = function (node = [], data) {                let cNode = node.filter((n) => n.code === data.code);                console.log(cNode,data)                if (!cNode || !cNode.length) {                    node.push(data);                    return node;                } else {                    cNode = cNode[0];                    cNode.children = combine(cNode.children, data.children[0]);                    return node;                }            };            return function (wb) {                let output = toJson(wb);                output = JSON.parse(output);                let code = Reflect.get(output, Reflect.ownKeys(output)[0]);                out.innerText = processCode(code);            };        })();        let doFile = (function () {            return function (files) {                let f = files[0];                let reader = new FileReader();                reader.onload = function (e) {                    let data = e.target.result;                    processWb(XLSX.read(data, {                        type: 'array'                    }));                };                reader.readAsArrayBuffer(f);            };        })();        (function () {            let drop = document.getElementById('drop');            if (!drop.addEventListener) {                return;            }            function handleDrop(e) {                e.stopPropagation();                e.preventDefault();                doFile(e.dataTransfer.files);            }            function handleDragover(e) {                e.stopPropagation();                e.preventDefault();                e.dataTransfer.dropEffect = 'copy';            }            drop.addEventListener('dragenter', handleDragover, false);            drop.addEventListener('dragover', handleDragover, false);            drop.addEventListener('drop', handleDrop, false);        })();        (function () {            let xlf = document.getElementById('xlf');            if (!xlf.addEventListener) {                return;            }            function handleFile(e) {                doFile(e.target.files);            }            xlf.addEventListener('change', handleFile, false);        })();    </script></body></html>

3、代码解析

①读取excel
读取excel次要是通过XLSX.read(data, {type: type});办法来实现,返回一个叫WorkBook的对象,type次要取值如下:

base64: 以base64形式读取;
binary: BinaryString格局(byte n is data.charCodeAt(n))
string: UTF8编码的字符串;
buffer: nodejs Buffer;
array: Uint8Array,8位无符号数组;
file: 文件的门路(仅nodejs下反对);

②读取本地文件

// 示例let doFile = (function () {  return function (files) {      let f = files[0];      let reader = new FileReader();      reader.onload = function (e) {          let data = e.target.result;          processWb(XLSX.read(data, {              type: 'array'          }));                    // XLSX.read()会返回一个workback对象      };      reader.readAsArrayBuffer(f);  };})();

workbook打印

能够看到,SheetNames外面保留了所有的sheet名字,而后Sheets则保留了每个sheet的具体内容(咱们称之为Sheet Object)。每一个sheet是通过相似A1这样的键值保留每个单元格的内容,咱们称之为单元格对象(Cell Object),也就是excel表格的数据:

每一个Sheet Object示意一张表格,只有不是!结尾的都示意一般cell,否则,示意一些非凡含意,具体如下:

sheet['!ref']:示意所有单元格的范畴,例如从A1到F8则记录为A1:F8;
sheet[!merges]:寄存一些单元格合并信息,是一个数组,每个数组由蕴含s和e形成的对象组成,s示意开始,e示意完结,r示意行,c示意列;
等等;

每一个单元格是一个对象(Cell Object),次要有t、v、r、h、w等字段(详见这里):

t:示意内容类型,s示意string类型,n示意number类型,b示意boolean类型,d示意date类型,等等
v:示意原始值;
f:示意公式,如B2+B3;
h:HTML内容
w:格式化后的内容
r:富文本内容rich text
等等

③读取workbook

let toJson = function (workbook) {  let result = {};  // workbook.SheetNames 工作表名称汇合  workbook.SheetNames.forEach(function (sheetName) {      // workbook.Sheets[sheetName] 只能通过工作表名称来获取指定工作表      let roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {          header: 1      });      if (roa.length) {          result[sheetName] = roa;      }  });  return JSON.stringify(result, 2, 2);};

插件本身曾经有写好的工具栏XLSX.utils,咱们应用的是输入json格局的数据。

XLSX.utils.sheet_to_csv:生成CSV格局
XLSX.utils.sheet_to_txt:生成纯文本格式
XLSX.utils.sheet_to_html:生成HTML格局
XLSX.utils.sheet_to_json:输入JSON格局

输入后果:
输入一个对象,返回每一行单元格的数据合成一个数组

④读取数据
应用Reflect.getReflect.ownKeys解决数据

return function (wb) {    let output = toJson(wb);    output = JSON.parse(output);    let code = Reflect.get(output, Reflect.ownKeys(output)[0]);    console.log(code)    out.innerText = processCode(code);};

code的打印数据:

而后可依据返回的数据进行解决,转成json格局的数据

最初的打印后果:

四、补充

Reflect 是一个内置的对象,它提供拦挡 JavaScript 操作的办法。这些办法与proxy handlers的办法雷同。Reflect不是一个函数对象,因而它是不可结构的。

1、Reflect.get
Reflect.get(target, propertyKey[, receiver])
参数:
target
须要取值的指标对象
propertyKey
须要获取的值的键值
receiver
如果target对象中指定了getter,receiver则为getter调用时的this值。

// Objectvar obj = { x: 1, y: 2 };Reflect.get(obj, "x"); // 1// ArrayReflect.get(["zero", "one"], 1); // "one"// Proxy with a get handlervar x = {p: 1};var obj = new Proxy(x, {  get(t, k, r) { return k + "bar"; }});Reflect.get(obj, "foo"); // "foobar"

2、Reflect.ownKeys
Reflect.ownKeys:返回一个由指标对象本身的属性键组成的数组。

const object1 = {  property1: 42,  property2: 13};const array1 = [];console.log(Reflect.ownKeys(object1));// expected output: Array ["property1", "property2"]console.log(Reflect.ownKeys(array1));