关于前端:使用pythonnodejsxlsxfullminjs处理省市区excel数据转成json

5次阅读

共计 7329 个字符,预计需要花费 19 分钟才能阅读完成。

应用 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.py

print('hello');

// 运行
python a.py

4、运行代码

import json
import pandas as pd


class 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 值。

// Object
var obj = {x: 1, y: 2};
Reflect.get(obj, "x"); // 1

// Array
Reflect.get(["zero", "one"], 1); // "one"

// Proxy with a get handler
var 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));
正文完
 0