上一次已經初步學會了通過workbook
配置,實現簡單excel導出,但是excel不是簡單的表格光有數據就完了,如果是那樣我直接用逗號分隔符創建csv就好了。
這次,我來看看如何實現樣式,我要實現的功能有
1.單元格合并
2.列寬設置
3.樣式設置 對齊方式 字體/背景顏色 邊框
我先用excel做了包含這些功能的簡單范本,最終希望用js-xlsx重現
但是經過嘗試,已經確認SheetJS/xlsx 導出excel時
cell
的s
樣式配置是無效的,他們提供了一個Pro Version,似乎只有使用這個專業版才能實現這個功能。
不過我很快找到了替代品 protobi/js-xlsx
npm install xlsx-style
斯巴達,我的項目一引用這個包就無法正常運行了
會拋出這個錯誤,不知道是這個包有問題還是我的環境有問題,已經嘗試在項目上安裝
fs
dev也安裝fs
依然沒解決。
使用protobi/js-xlsx
我只能采用傳統頁面加載方式來使用,從他們的git上clone了項目,在頁面上加載xlsx.core.min.js
文件,因為用前端加載,同時也要引入Blob
和 file-saver
,我在搜索引擎上找到了一個簡單的函數來實現 file-saver
的功能,當前項目代碼如下
<script type="text/javascript" src="./xlsx-style/dist/xlsx.core.min.js"></script>
<script type="text/javascript" src="./Blob.js"></script>
<script>
const saveAs = (obj, fileName)=>{
const a = document.createElement('a');
a.download = fileName || '下載';
a.href = URL.createObjectURL(obj);
a.click();
setTimeout(()=> {
URL.revokeObjectURL(obj);
}, 100);
};
const s2ab = s => {
let buf = new ArrayBuffer(s.length);
let view = new Uint8Array(buf);
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
};
const workbook = { //本次學習只對這個對象做修改,其他代碼塊保持不動
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: {
}
}
};
const workbookOut = XLSX.write(workbook, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(workbookOut)], {
type: 'application/octet-stream'
}), 'export.xlsx')
</script>
因為只是學習測試,我直接用簡練的es6語法,實現功能為主,不考慮瀏覽器兼容性問題
1.單元格合并sheet['!merges']
回顧官方文檔,sheet
提供了一個配置項!merges
用來實現單元格合并
使用之前先了解它的用法,sheet['!merges']
接受一個數組參數,數組對象的格式如下
[
{
s: { //s start 開始
c: 1,//cols 開始列
r: 0 //rows 開始行
},
e: {//e end 結束
c: 4,//cols 結束列
r: 0 //rows 結束行
}
}
]
為了實現合并A1:D1我給sheet['!merges']
增加對應配置,現在的workbook
如下
const workbook = {
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: {
'!ref': 'A1:D4',
'!merges': [{
s: {c: 0, r: 0},
e: {c: 3, r: 0}
}],
A1: {v: '采購單', t: 's'},
}
}
};
運行導出,成功
2.列寬設置 sheet['!cols']
sheet
提供了一個配置項!cols
用來實現設置列寬
[
{
hidden? : boolean, //列的顯示true或隱藏false
/* column width is specified in one of the following ways: */
wpx? : number, // 列寬 單位是像素
width? : number, // width in Excel's "Max Digit Width", width*256 is integral
wch? : number, // width in characters
/* other fields for preserving features from files */
MDW? : number, // Excel's "Max Digit Width" unit, always integral
}
]
我的示例中的單元格寬度是 45px 165px 45px 45px
配置一下
'!cols': [{wpx: 45}, {wpx: 165}, {wpx: 45}, {wpx: 45}]
運行導出
可以看到列寬有被正確配置,但是產生的寬度是 51px 189px 51px 51px,雖然有誤差,不過配置項有效,誤差原因就不深究了
清注意,下面的功能由
xlsx-style
實現 ,對xlsx
無效
樣式配置表
樣式屬性 | 子屬性 | 參數 |
---|---|---|
fill | patternType | "solid" or "none"” |
fgColor | COLOR_SPEC | |
bgColor | COLOR_SPEC | |
font | name | "Calibri" // default |
sz | "11" // font size in points | |
color | COLOR_SPEC | |
bold | true or false | |
underline | true or false | |
italic | true or false | |
strike | true or false | |
outline | true or false | |
shadow | true or false | |
vertAlign | true or false | |
numFmt | "0" // integer index to built in formats, see StyleBuilder.SSF property | |
"0.00%" // string matching a built-in format, see StyleBuilder.SSF | ||
"0.0%" // string specifying a custom format | ||
"0.00%;\(0.00%\);\-;@" // string specifying a custom format, escaping special characters | ||
"m/dd/yy" // string a date format using Excel's format notation | ||
alignment | vertical | "bottom" or "center" or "top" |
horizontal | "bottom" or "center" or "top" | |
wrapText | true or false | |
readingOrder | 2 // for right-to-left | |
textRotation | Number from 0 to 180 or 255 (default is 0) | |
90 is rotated up 90 degrees | ||
45 is rotated up 45 degrees | ||
135 is rotated down 45 degrees | ||
180 is rotated down 180 degrees | ||
255 is special, aligned vertically | ||
border | top | { style: BORDER_STYLE, color: COLOR_SPEC } |
bottom | { style: BORDER_STYLE, color: COLOR_SPEC } | |
left | { style: BORDER_STYLE, color: COLOR_SPEC } | |
right | { style: BORDER_STYLE, color: COLOR_SPEC } | |
diagonal | { style: BORDER_STYLE, color: COLOR_SPEC } | |
diagonalUp | true or false | |
diagonalDown | true or false |
COLOR_SPEC: 填充、字體和邊框的顏色對象:
- { auto: 1}指定自動值
- { rgb: "FFFFAA00" } 指定16進制的ARGB
- { theme: "1", tint: "-0.25"} 指定主題顏色和色調的整數索引(默認值為0)
- { indexed: 64} 默認值 fill.bgColor
BORDER_STYLE: 邊框樣式是一個字符串值,它可以是以下值之一:
- thin
- medium
- thick
- dotted
- hair
- dashed
- mediumDashed
- dashDot
- mediumDashDot
- dashDotDot
- mediumDashDotDot
- slantDashDot
2.樣式設置
我的測試范例中標題“采購單”是水平居中對齊,18號加粗字體
給A1增加對應配置
A1: {
v: '采購單',
t: 's',
s: {
font: {
sz: 18, //18號字體
bold: true //加粗
},
alignment: {
horizontal: 'center' //水平居中對其
}
}
}
運行導出
配置有效!我很快就按配置表寫出下面的
workbook
const borderAll = { //單元格外側框線
top: {
style: 'thin'
},
bottom: {
style: 'thin'
},
left: {
style: 'thin'
},
right: {
style: 'thin'
}
};
const workbook = {
SheetNames: ['Sheet1'],
Sheets: {
Sheet1: {
'!ref': 'A1:D4',
'!cols': [{wpx: 45}, {wpx: 165}, {wpx: 45}, {wpx: 45}],
'!merges': [{
s: {c: 0, r: 0},
e: {c: 3, r: 0}
}],
A1: {
v: '采購單',
t: 's',
s: {
font: {
sz: 18,
bold: true
},
alignment: {
horizontal: 'center'
}
}
},
A2: {
v: '序號',
t: 's',
s: {
border: borderAll
}
},
B2: {
v: '商品名稱',
t: 's',
s: {
border: borderAll
}
},
C2: {
v: '數量',
t: 's',
s: {
border: borderAll
}
},
D2: {
v: '顏色',
t: 's',
s: {
border: borderAll
}
},
A3: {
v: 1,
t: 'n',
s: {
border: borderAll
}
},
B3: {
v: '商品1',
t: 's',
s: {
border: borderAll
}
},
C3: {
v: 100,
t: 'n',
s: {
border: borderAll,
font: {
color: {
rgb: 'FF4F81BD' //字體顏色
}
}
}
},
D3: {
v: '',
s: {
border: borderAll,
fill: {
fgColor: {
rgb: 'FFC0504D' //背景顏色
}
}
}
}
}
}
};
運行
到此,本次對使用js-xlsx導出excel的學習基本告一段落,可以準備投入生產了