不久前,咱們接了一個本身作前端後端產品的活,今後過上了可憐巴巴敲代碼開開心心收穫知識的日子呢。javascript
用戶小姐姐在羣裏說,系統篩選工卡有效期很差使。(系統:不不不,不是個人鍋前端
我看了一下數據庫,發現,咱們原定的有效期格式是這樣的java
整整齊齊。數據庫
數據庫中當時的數據是這樣的json
甚至是這樣的後端
看到這種狀況,我以爲確定是輸入的時候輸的不太對(年輕…app
因而我決定從 Excel 下手ui
小姐姐們的操做流程是先用咱們的系統導出一份 Excel,編輯以後再導入系統的,那隻要我把這工卡一列的格式限制爲日期,就必定能夠統一格式的,嗯。this
咱們項目使用了 js-xlsx 處理表格的導入導出,下面是導出 Excel 的僞代碼:spa
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)
複製代碼
這樣以後就能夠拿到正確的日期啦。咕嘰。