zoukankan      html  css  js  c++  java
  • 基于LuckySheet在线表格的Excel下载功能开发

    最近开发的项目中使用到了一个非常强大的在线表格展示库Luckysheet

    下面记录一下基于luckysheet的下载功能的开发

    第一步:获取到要下载的数据。

    LuckySheet给我们提供了一个获取所有sheet数据的方法 luckysheet.getluckysheetfile(),通过该方法我们可以得到所有的sheet的数据以及配置信息

    let allSheetData = luckysheet.getluckysheetfile();
    let sheet1 = allSheetData[0];
    let downOriginData = sheet1.data;  
    // 该方法会返回一个数组结构,其中包含了我们所创建的所有的sheet数据
    // allSheetData = [{sheet1},{sheet2},{sheet3}]
    // 每个sheet的数据结果如下
    {
    "name": "sheet1", "color": "", "chart": [], "status": 0, "order": 0, "celldata": [],
       "data":[],
    "row":90, "column":100, "index": 0, "visibledatarow": [], "visibledatacolumn": [], "rowsplit": [], "ch_width": 4629, "rh_height": 1681, "luckysheet_select_save": {}, "luckysheet_selection_range": {}, "scrollLeft": 0, "scrollTop": 0, "load": "1", "config": { "columlen": {}, "rowhidden": {} } , "pivotTable": {}, "isPivotTable": true, "calcChain": [], "filter":{key1:value1, key2:value2}, "filter_select": {} }

    data的数据结构

    let arr = [];  // 所有的单元格数据组成的二维数组
    let bgConfig = {};
    let percentageReg = /%$/;
    let cellValue = null;
    // 获取单元格的背景色
    function setBackground(row, col, bg) {
        var colA = luckysheet.luckysheetchatatABC(col);
        var key = colA + (row + 1);
        bgConfig[key] = bg.replace(/#?/, '');
    }
    
    // 判断值类型是否为百分比 %
    function isPercentage(value) {
        return percentageReg.test(value.m) && value.ct && value.ct.t === 'n'
    }
    
    // 获取二维数组
    for (let row = 0; row < downOriginData.length; row++) {
        let arrRow = [];
        for (let col = 0; col < downOriginData[row].length; col++) {
            if (cellValue = downOriginData[row][col]) {
                // 处理单元格的背景颜色
                if (cellValue.bg) {
                    setBackground(row, col, cellValue.bg)
                }
                if (cellValue.ct != null && cellValue.ct.t == 'd') {
                    //  d为时间格式  2019-01-01   或者2019-01-01 10:10:10
                    arrRow.push(new Date(cellValue.m.replace(/-/g, '/'))) //兼容IE
                } else if (cellValue.m && isPercentage(cellValue)) {
                    //百分比问题
                    arrRow.push(cellValue.m)
                } else {
                    arrRow.push(cellValue.v)
                }
            }
        }
        arr.push(arrRow)
    }

    第二步:通过SheetJs将数据转化为excel格式数据

    let opts = {
        dateNF: 'm/d/yy h:mm',
        cellDates: true,
        cellStyles: true
    }
    let ws = XLSX.utils.aoa_to_sheet(arr, opts)

     第三步:设置单元格的类型以及单元格样式

     1 let reg = /[u4e00-u9fa5]/g;
     2 for (let key in ws) {
     3     let item = ws[key]
     4     if (item.t === 'd') {
     5         if (item.w) {
     6             //时间格式的设置
     7             let arr = item.w.split(' ')
     8             if (arr[1] && arr[1] == '0:00') {
     9                 ws[key].z = 'm/d/yy'
    10             } else {
    11                 item.z = 'yyyy/m/d h:mm:ss'
    12             }
    13         }
    14     } else if (item.t === 's') {
    15         //百分比设置格式
    16         if (item.v && !item.v.match(reg) && item.v.indexOf('%') > -1) {
    17             item.t = 'n'
    18             item.z = '0.00%'
    19             item.v = Number.parseFloat(item.v) / 100
    20         }
    21         else if (item.v && item.v.match(reg)) {
    22             //含有中文的设置居中样式
    23             item['s'] = {
    24                 alignment: { vertical: 'center', horizontal: 'center' }
    25             }
    26         }
    27     }
    28     // 设置单元格样式
    29     if (bgConfig[key]) {
    30         ws[key]['s'] = {
    31             alignment: { vertical: 'center', horizontal: 'center' },
    32             fill: { bgColor: { indexed: 32 }, fgColor: { rgb: bgConfig[key] } },
    33             border: {
    34                 top: { style: 'thin', color: { rgb: '999999' } },
    35                 bottom: { style: 'thin', color: { rgb: '999999' } },
    36                 left: { style: 'thin', color: { rgb: '999999' } },
    37                 right: { style: 'thin', color: { rgb: '999999' } }
    38             }
    39         }
    40     }
    41 }

    第四步:组装下载数据格式

        let name = 'sheet1';
            let tmpWB = {
              SheetNames: [name], //保存的表标题
              Sheets: {
                [name]: Object.assign({},ws)//内容 
              }
            }

     第五步:合并单元格配置

    let mergeConfig = sheet1.config.merge
    let mergeArr = [];
    if (JSON.stringify(mergeConfig) !== '{}') {
        mergeArr = handleMergeData(mergeConfig)
        tmpWB.Sheets[name]['!merges'] = merge
    }
    //处理合并单元格config数据
    function handleMergeData(origin) {

      let result = [] if (origin instanceof Object) { var r = "r", c = "c", cs = "cs", rs = "rs"; for (var key in origin) { var startR = origin[key][r]; var endR = origin[key][r]; var startC = origin[key][c]; var endC = origin[key][c]; // 如果只占一行 为1 如果占两行 为2 if (origin[key][cs] > 0) { endC = startC + (origin[key][cs] - 1); } if (origin[key][rs] > 0) { endR = startR + (origin[key][rs] - 1); } // s为合并单元格的开始坐标 e为结束坐标 var obj = { s: { "r": startR, "c": startC }, e: { "r": endR, "c": endC } } result.push(obj) } }
      return result }

     第六步:写入文件

        
    let fileName = 'test';
    // sheetjs js-xlsx 的方法 ,不能设置单元格格式 XLSX.writeFile(tmpWB,fileName + ".xlsx");

     由于sheetJs 社区版本的方法不支持设置样式,可以选择Pro版本,需要付费,好像是 1000$

    当然如果不需要设置背景色,单元格对齐方式,边框等样式,社区版就够用了。

    另一种解决方法 xlsx-style

    function s2ab(s) {
        if (typeof ArrayBuffer !== 'undefined') {
            var buf = new ArrayBuffer(s.length);
            var view = new Uint8Array(buf);
            for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
            return buf;
        } else {
            var buf = new Array(s.length);
            for (var i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
            return buf;
        }
    }
    function saveAs(obj, fileName) {
        var tmpa = document.createElement("a");
        tmpa.download = fileName || "download";
        tmpa.href = URL.createObjectURL(obj);
        tmpa.click();
        setTimeout(function () {
            URL.revokeObjectURL(obj);
        }, 100);
    }
    
    ws = new Blob(
        [
            s2ab(
                S_XLSX.write(tmpWB, { bookType: 'xlsx', bookSST: false, type: 'binary' })//这里的数据是用来定义导出的格式类型
            )
        ]
    )
    saveAs(ws, fileName + '.xlsx')
  • 相关阅读:
    iOS越狱系列(一):使用Reveal分析APP
    ios-异步消息同步问题-典型使用场景: 微信私信界面
    ios 消息跳转处理
    iOS开发UI篇—IOS CoreText.framework --- 基本用法
    IOS开发之实现App消息推送(最新)
    Thread 1: signal SIGABRT-内存管理的陋习
    别用symbolicatecrash来解析crash Log了by 风之枫
    通过崩溃trace来查找问题原因 .
    Xcode 6视图调试小贴士
    调试message send to deallocated instance问题
  • 原文地址:https://www.cnblogs.com/recode-hyh/p/13168226.html
Copyright © 2011-2022 走看看