如何解析你,Excel的Date呀

簡單的背景介紹

不久前,我們接了一個自己做前端後端產品的活,從此過上了可憐巴巴敲代碼開開心心收穫知識的日子呢。

那是一個平平無奇的週一下午

用戶小姐姐在羣裏說,系統篩選工卡有效期不好使。(系統:不不不,不是我的鍋

我看了一下數據庫,發現,我們原定的有效期格式是這樣的

整整齊齊。

數據庫中當時的數據是這樣的

甚至是這樣的

看到這種情況,我覺得肯定是輸入的時候輸的不太對(年輕…

於是我決定從Excel下手

小姐姐們的操作流程是先用我們的系統導出一份Excel,編輯之後再導入系統的,那隻要我把這工卡一列的格式限制爲日期,就一定可以統一格式的,嗯。

我們項目使用了js-xlsx處理表格的導入導出,下面是導出Excel的僞代碼:

import * as XLSX from 'xlsx';

const xlsxMineType = 'application/vnd.openxmlformats-
officedocument.spreadsheetml.sheet'
const data = 數據.map((s: any) => ({
ID: s.id,
工卡有效期: s.card_expired,
……
}));

const sheet = XLSX.utils.json_to_sheet(data);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, sheet, '員工信息表');
const wbbuf = XLSX.write(wb, {
  type: 'base64'
});

this.success({ name: "員工信息表.xlsx", data: wbbuf, type:xlsxMineType });

通過 json_to_sheet 可以拿到包含單元格信息的對象

{ 
 A2: { t: 'n', v: 3776 },
 B2: { t: 's', v: '2019-04-01' },
 A3: { t: 'n', v: 3831 },
 B3: { t: 's', v: '2019-04-01' },
 A1: { t: 's', v: 'ID' },
 B1: { t: 's', v: '工卡有效期' },
 '!ref': 'A1:B3' 
}

對象中以單元格位置作爲key,每個單元格的值(v)、類型(t)等等屬性作爲value。其中單元格的類型支持:

b Boolean, n Number, e error, s String, d Date

看起來Date類型十分符合上面的要求,就嘗試了一下:

const sheet = XLSX.utils.json_to_sheet(data);
// 篩選出除表頭的工卡列
Object.keys(sheet).filter(item => /^B/.test(item) && item !== "B1").forEach(key => {
   sheet[key].t = "d";
})

然鵝,如果工卡有效期本來就爲空,這時候導出,打開Excel會報錯,並且空的位置會變成NaN

翻閱了各種中英文文檔、Issue,導出一百多個員工信息表之後,我發現Excel真的很奇妙,或許應該在js上來格式化導入的數據,而不是限制單元格的類型。

如果不控制單元格類型的話,那麼當管理員輸入日期的時候,這個單元格可能是:文本、常規、日期、自定義類型,所以只要保證不管單元格是什麼格式,程序都能拿到正確的數據就好了。

當管理員使的工卡有效期的單元格類型是文本或者常規的時候,則比較簡單,程序可以按預期解析出來一個相應的字符串,用moment解析一下,就可以獲得想要的格式的數據了。

那麼當有效期單元格的類型是日期和自定義的時候,我們拿到的數據是像下圖一樣

這也就是之前數據庫中奇怪的數字的由來,這個數字的意義,其實是當前日期距離1900年1月0日的天數。還需要注意的是,Excel中有個bug:

它以爲1900年是閏年,所以我們拿到的天數都會多了一天,因爲轉換之前還需要先進行減一操作…

item.工卡有效期 = new Date(1900, 0, expried - 1)

這樣之後就可以拿到正確的日期啦。咕嘰。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章