【node+demo】使用xlsx-style設置表格的寬高等樣式

傳送門

先放一些我認為非常優秀的參考文檔,作為傳送門集合,方便大家查看吧:

【1】Node.js中如何利用xlsx設置導出表格的樣式?

這個問題告訴了你,你用xlsx設置樣式不行,但是用xlsx-style導出樣式就ok

【2】純前端利用 js-xlsx 實現 Excel 文件導入導出功能示例
這算是全網,注意是全網講解js-xlsx比較全面系統的文章了,可以好好了解一下。

本系統使用node+express 作為后臺,導出excel使用的是xlsx-style。在開始之前,先簡單介紹一下node常用的一些導出excel的工具,因為這對我們后面的工作十分重要。

預備

(1)js-xlsx和xlsx。xlsx和js-xlsx可以理解為基本庫,API十分復雜,上手難度高,但是你想要的功能,基本上都有。但是文檔不好,看起來十分費力。不信你去點點下面的鏈接看看,嚇死你……

js-xlsx文檔:https://www.npmjs.com/package/js-xlsx
xlsx文檔:https://www.npmjs.com/package/xlsx

(2)node-xlsx。基于基本庫的封裝,底層的庫是用的xlsx。

node-xlsx npm文檔:https://www.npmjs.com/package/node-xlsx

十分操蛋的文檔,反正我是看完之后不知道怎么用,寫了跟沒寫一樣,關鍵的樣式都沒說。

(3)xlsx-style 基于xlsx封裝的樣式庫,可以在xlsx的基礎上設置樣式。

正文

一般在使用node的時候我們是直接使用node-xlsx庫的,關鍵的導出代碼如下:

const xlsx = require('node-xlsx').default;

  const options = {
        '!cols': [
          {wpx: 300},//1-變更名稱
          {wpx: 100},//2-變更描述
          {wpx: 140},//3-計劃上線測試時間
          {wpx: 140}, //4-計劃上線時間
          {wpx: 250}, //5-子系統、模塊名稱
          {wpx: 120}, //6-依賴模塊
          {wpx: 195},//7-功能點
          {wpx: 195}, //8-詳細描述
          {wpx: 195}, //9-測試要點
          {wpx: 205}, //10-對應需求
          {wpx: 150}, //11-是否
          {wpx: 150}, //12-開發A
          {wpx: 150}, //13-開發B
          {wpx: 110}, //14-關聯版本
          {wpx: 110}, //15-代碼走查
        ],
        '!rows': [
          {hpx: 40,},
          {hpx: 60},
          {hpx: 80},
          {hpx: 100},
        ],
        '!margins': {left: 0.7, right: 0.7, top: 0.75, bottom: 0.75, header: 0.3, footer: 0.3},
      }

      const range = {s: {c: 0, r: 0}, e: {c: 0, r: 2}}; // A1:A4
      options['!merges'] = [range]

      const xlsxData = xlsx.build([form], options)

options是導出表格的一些樣式,!cows和!rows分別設置的是列寬和行高,可以成功設置,但是樣式不能成功設置,也就是說


s標簽里的東西通通無效。

在網上查詢了一些辦法后,發現主需要吧node-xlsx里對xlsx的引入改為xlsx-style就能夠成功設置樣式。

image.png

然后就發現了樣式成功設置,行高卻無效了……(我tm!@#¥%)

問題分析

我對比了xlsx-style和xlsx的源碼,發現兩個庫很多的方法和代碼都是一樣的,xlsx-style之所以能夠設置樣式,是因為它多了一個styleBuilder


而xlsx-style不能夠設置行高,是因為在write_ws_xml-data里沒有對rows進行處理,而在xlsx庫里可以清楚的看到它對!rows的處理

所以解決方法就必須去改庫(我認為),思路也有2中:
(1)在xlsx-style加xlsx里設置行高的代碼
(2)在xlsx里加入xlsx-style里設置樣式的代碼

用腳想也應該知道(1)的工作量最小,所以解決辦法就是在xlsx-style里加入行高設置的代碼。

解決方法:

先修改node-xlsx lib目錄下的hepler.js

var buildSheetFromMatrix = function buildSheetFromMatrix(data) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var workSheet = {};
  var range = {s: {c: 1e7, r: 1e7}, e: {c: 0, r: 0}};

  if (!Array.isArray(data)) throw new Error('sheet data is not array');

  for (var R = 0; R !== data.length; R += 1) {
    for (var C = 0; C !== data[R].length; C += 1) {
      if (!Array.isArray(data[R])) throw new Error(R + 'th row data is not array');

      if (range.s.r > R) range.s.r = R;
      if (range.s.c > C) range.s.c = C;
      if (range.e.r < R) range.e.r = R;
      if (range.e.c < C) range.e.c = C;
      if (data[R][C] === null) {
        continue; // eslint-disable-line
      }
      var cell = isCellDescriptor(data[R][C]) ? data[R][C] : {v: data[R][C]};
      var cellRef = _xlsx2.default.utils.encode_cell({c: C, r: R});
      if (isNumber(cell.v)) {
        cell.t = 'n';
      } else if (isBoolean(cell.v)) {
        cell.t = 'b';
      } else if (cell.v instanceof Date) {
        cell.t = 'n';
        cell.v = buildExcelDate(cell.v);
        cell.z = cell.z || _xlsx2.default.SSF._table[14]; // eslint-disable-line no-underscore-dangle
      } else {
        cell.t = 's';
      }
      if (isNumber(cell.z)) cell.z = _xlsx2.default.SSF._table[cell.z]; // eslint-disable-line no-underscore-dangle
      workSheet[cellRef] = cell;
    }
  }
  if (range.s.c < 1e7) {
    workSheet['!ref'] = _xlsx2.default.utils.encode_range(range);
  }
  if (options['!cols']) {
    workSheet['!cols'] = options['!cols'];
  }

  if (options['!rows']) {
    workSheet['!rows'] = options['!rows'];
  }
  
  if (options['!merges']) {
    workSheet['!merges'] = options['!merges'];
  }
  return workSheet;
};

讓opts里的rows能夠被添加至workSheet當中

然后再修改在xlsx-style里的xlsx.js write_ws_xml_data 方法,添加設置行高的代碼。

function write_ws_xml_data(ws, opts, idx, wb) {
    var o = [], r = [], range = safe_decode_range(ws['!ref']), cell, ref, rr = "", cols = [], R, C,rows = ws['!rows'];
    for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
    for(R = range.s.r; R <= range.e.r; ++R) {
        r = [];
        rr = encode_row(R);
        for(C = range.s.c; C <= range.e.c; ++C) {
            ref = cols[C] + rr;
            if(ws[ref] === undefined) continue;
            if((cell = write_ws_xml_cell(ws[ref], ref, ws, opts, idx, wb)) != null) r.push(cell);
        }
        if(r.length > 0){
      params = ({r:rr});
      if(rows && rows[R]) {
        row = rows[R];
        if(row.hidden) params.hidden = 1;
        height = -1;
        if (row.hpx) height = px2pt(row.hpx);
        else if (row.hpt) height = row.hpt;
        if (height > -1) { params.ht = height; params.customHeight = 1; }
        if (row.level) { params.outlineLevel = row.level; }
      }
      o[o.length] = (writextag('row', r.join(""), params));
    }
    }
  if(rows) for(; R < rows.length; ++R) {
    if(rows && rows[R]) {
      params = ({r:R+1});
      row = rows[R];
      if(row.hidden) params.hidden = 1;
      height = -1;
      if (row.hpx) height = px2pt(row.hpx);
      else if (row.hpt) height = row.hpt;
      if (height > -1) { params.ht = height; params.customHeight = 1; }
      if (row.level) { params.outlineLevel = row.level; }
      o[o.length] = (writextag('row', "", params));
    }
  }
    return o.join("");
}

結語

如果還有什么問題歡迎評論交流,最近一段時間都會折騰excel,所以會經常關注的。

詳細的樣式和完整的設置代碼過段時間再補上~

先附上導出表格的效果圖:


問題回復

【1】

這里再解釋一下node-xlsx和xlsx的關系。首先node-xlsx是對xlsx的封裝,簡化了一些操作(這是我們在node項目里使用它比較重要的原因)

但是由于xlsx庫沒有對樣式做處理,所以有人又在xlsx的基礎上封裝了樣式,也就是xlsx-style庫。

所以我們進行了從A到B的步驟,為的就是能夠使用樣式


在回到問題本身,只用xlsx-style的話肯定可以,修改的方法和上述一樣。因為這種方法的核心就是去修改xlsx-style里的xlsx文件


只不過,如果只使用xlsx-style的話,那你需要一些額外的步驟去調用build方法,可以參看node-xlsx的處理(因為node-xlsx就是對xlsx的封裝)

這里再多說一句,其實xlsx庫和xlsx-style庫很多很多地方都非常相似,而后者主要增加了對樣式的處理。

以上。(如果還有不明白的歡迎繼續留言~)

--------------------------------------4月5日更新--------------------------------------------------

增加github的demo供大家參考~
https://github.com/huyifan/NodeExcelStyleDemo
歡飲大家討論~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容