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

傳送門

先放一些我認(rèn)為非常優(yōu)秀的參考文檔,作為傳送門集合侦副,方便大家查看吧:

【1】Node.js中如何利用xlsx設(shè)置導(dǎo)出表格的樣式侦锯?

這個(gè)問題告訴了你,你用xlsx設(shè)置樣式不行秦驯,但是用xlsx-style導(dǎo)出樣式就ok

【2】純前端利用 js-xlsx 實(shí)現(xiàn) Excel 文件導(dǎo)入導(dǎo)出功能示例
這算是全網(wǎng)尺碰,注意是全網(wǎng)講解js-xlsx比較全面系統(tǒng)的文章了,可以好好了解一下译隘。

本系統(tǒng)使用node+express 作為后臺亲桥,導(dǎo)出excel使用的是xlsx-style。在開始之前固耘,先簡單介紹一下node常用的一些導(dǎo)出excel的工具题篷,因?yàn)檫@對我們后面的工作十分重要。

預(yù)備

(1)js-xlsx和xlsx厅目。xlsx和js-xlsx可以理解為基本庫番枚,API十分復(fù)雜法严,上手難度高,但是你想要的功能葫笼,基本上都有深啤。但是文檔不好,看起來十分費(fèi)力路星。不信你去點(diǎn)點(diǎn)下面的鏈接看看溯街,嚇?biāo)滥恪?/p>

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

十分操蛋的文檔垫挨,反正我是看完之后不知道怎么用韩肝,寫了跟沒寫一樣,關(guān)鍵的樣式都沒說九榔。

(3)xlsx-style 基于xlsx封裝的樣式庫哀峻,可以在xlsx的基礎(chǔ)上設(shè)置樣式。

正文

一般在使用node的時(shí)候我們是直接使用node-xlsx庫的哲泊,關(guān)鍵的導(dǎo)出代碼如下:

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

  const options = {
        '!cols': [
          {wpx: 300},//1-變更名稱
          {wpx: 100},//2-變更描述
          {wpx: 140},//3-計(jì)劃上線測試時(shí)間
          {wpx: 140}, //4-計(jì)劃上線時(shí)間
          {wpx: 250}, //5-子系統(tǒng)剩蟀、模塊名稱
          {wpx: 120}, //6-依賴模塊
          {wpx: 195},//7-功能點(diǎn)
          {wpx: 195}, //8-詳細(xì)描述
          {wpx: 195}, //9-測試要點(diǎn)
          {wpx: 205}, //10-對應(yīng)需求
          {wpx: 150}, //11-是否
          {wpx: 150}, //12-開發(fā)A
          {wpx: 150}, //13-開發(fā)B
          {wpx: 110}, //14-關(guān)聯(lián)版本
          {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是導(dǎo)出表格的一些樣式,!cows和切威!rows分別設(shè)置的是列寬和行高育特,可以成功設(shè)置,但是樣式不能成功設(shè)置先朦,也就是說


s標(biāo)簽里的東西通通無效缰冤。

在網(wǎng)上查詢了一些辦法后,發(fā)現(xiàn)主需要吧node-xlsx里對xlsx的引入改為xlsx-style就能夠成功設(shè)置樣式喳魏。

image.png

然后就發(fā)現(xiàn)了樣式成功設(shè)置棉浸,行高卻無效了……(我tm!@#¥%)

問題分析

我對比了xlsx-style和xlsx的源碼刺彩,發(fā)現(xiàn)兩個(gè)庫很多的方法和代碼都是一樣的迷郑,xlsx-style之所以能夠設(shè)置樣式,是因?yàn)樗嗔艘粋€(gè)styleBuilder


而xlsx-style不能夠設(shè)置行高创倔,是因?yàn)樵趙rite_ws_xml-data里沒有對rows進(jìn)行處理嗡害,而在xlsx庫里可以清楚的看到它對!rows的處理

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

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

解決方法:

先修改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當(dāng)中

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

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("");
}

結(jié)語

如果還有什么問題歡迎評論交流抑堡,最近一段時(shí)間都會折騰excel摆出,所以會經(jīng)常關(guān)注的。

詳細(xì)的樣式和完整的設(shè)置代碼過段時(shí)間再補(bǔ)上~

先附上導(dǎo)出表格的效果圖:


問題回復(fù)

【1】

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

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

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


在回到問題本身棚壁,只用xlsx-style的話肯定可以杯矩,修改的方法和上述一樣。因?yàn)檫@種方法的核心就是去修改xlsx-style里的xlsx文件


只不過袖外,如果只使用xlsx-style的話史隆,那你需要一些額外的步驟去調(diào)用build方法,可以參看node-xlsx的處理(因?yàn)閚ode-xlsx就是對xlsx的封裝)

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熔酷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子豺裆,更是在濱河造成了極大的恐慌拒秘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臭猜,死亡現(xiàn)場離奇詭異躺酒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蔑歌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門阴颖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丐膝,你說我怎么就攤上這事〖鼐眨” “怎么了帅矗?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長煞烫。 經(jīng)常有香客問我浑此,道長,這世上最難降的妖魔是什么滞详? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任凛俱,我火速辦了婚禮紊馏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蒲犬。我一直安慰自己朱监,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布原叮。 她就那樣靜靜地躺著赫编,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奋隶。 梳的紋絲不亂的頭發(fā)上擂送,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音唯欣,去河邊找鬼嘹吨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛境氢,可吹牛的內(nèi)容都是我干的蟀拷。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼产还,長吁一口氣:“原來是場噩夢啊……” “哼匹厘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脐区,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤愈诚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后牛隅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炕柔,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年媒佣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匕累。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡默伍,死狀恐怖欢嘿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情也糊,我是刑警寧澤炼蹦,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站狸剃,受9級特大地震影響掐隐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钞馁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一虑省、第九天 我趴在偏房一處隱蔽的房頂上張望匿刮。 院中可真熱鬧,春花似錦探颈、人聲如沸熟丸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虑啤。三九已至,卻和暖如春架馋,著一層夾襖步出監(jiān)牢的瞬間狞山,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工叉寂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萍启,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓屏鳍,卻偏偏與公主長得像勘纯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子钓瞭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容