一.遇到問題
1.給自定義格式的excel中的合併單元格加邊框的時候,出現邊框不完整的情況.
解決:將該合併單元格拆分成最小單位的單元格,設置其邊框屬性. 直接賦值的話不可行,因爲子單元格並沒有邊框屬性,只有合併單元格纔有, 這裏使用的方法是:記錄合併單元格的屬性信息, 然後循環對子單元格賦值.
代碼:
function addRangeBorder(range,ws){
let arr = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
range.forEach(item=>{
let startColNumber = Number(item.s.r), endColNumber = Number(item.e.r);
let startRowNumber = Number(item.s.c), endRowNumber = Number(item.e.c);
const test = ws[arr[startRowNumber] + (startColNumber + 1)];
for(let col = startColNumber ; col <= endColNumber ; col++)
{
for(let row = startRowNumber; row <= endRowNumber ; row++)
{
//const test = ws[arr[j] + i];
//console.log(arr[row] + (col + 1));
ws[arr[row] + (col + 1)] = test;
//{s:{border:{top:{style:'thin'}, left:{style:'thin'},bottom:{style:'thin'},right:{style:'thin'}}}};
}
}
})
return ws;
}
二.DEMO
一個完整的例子:
import FileSaver from 'file-saver'
import XLSX from 'xlsx-style'
// 設置表格中cell默認的字體,居中,顏色等
var defaultCellStyle = {
font: {
name: "宋體", sz: 11, color: { auto: 1 } ,
},
border: {
color: { auto: 1 },
top: { style: 'thin' },
bottom: { style: 'thin'},
left: { style: 'thin' },
right: { style: 'thin' }
},
alignment: {
/// 自動換行
wrapText: 1,
// 居中
horizontal: "center",
vertical: "center",
indent: 0
}
};
// 從json轉化爲sheet,xslx中沒有aoaToSheet的方法,該方法摘自官方test
function sheet_from_array_of_arrays(data) {
const ws = {};
const range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }};
for(let R = 0; R !== data.length; ++R) {
for(let C = 0; C !== data[R].length; ++C) {
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;
/// 這裏生成cell的時候,使用上面定義的默認樣式
const cell = {v: data[R][C], s: defaultCellStyle};
if(cell.v == null) continue;
const cell_ref = XLSX.utils.encode_cell({c:C,r:R});
/* TEST: proper cell types and value handling */
if(typeof cell.v === 'number') cell.t = 'n';
else if(typeof cell.v === 'boolean') cell.t = 'b';
else if(cell.v instanceof Date) {
cell.t = 'n'; cell.z = XLSX.SSF._table[14];
cell.v = this.dateNum(cell.v);
}
else cell.t = 's';
ws[cell_ref] = cell;
}
}
/* TEST: proper range */
if(range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
return ws;
}
// 將一個sheet轉成最終的excel文件的blob對象,然後利用URL.createObjectURL下載
function sheet2blob(sheet, sheetName) {
sheetName = sheetName || 'sheet1';
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
workbook.Sheets[sheetName] = sheet
window.console.log(workbook)
// 生成excel的配置項
const wopts = {
bookType: 'xlsx', // 要生成的文件類型
bookSST: false, // 是否生成Shared String Table,官方解釋是,如果開啓生成速度會下降,但在低版本IOS設備上有更好的兼容性
type: 'binary'
};
const wbout = XLSX.write(workbook, wopts, { defaultCellStyle: defaultCellStyle });
const blob = new Blob([s2ab(wbout)], {type: "application/octet-stream"});
// 字符串轉ArrayBuffer
function s2ab(s) {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i=0; i!==s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
return blob;
}
function addRangeBorder(range,ws){
let arr = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
range.forEach(item=>{
let startColNumber = Number(item.s.r), endColNumber = Number(item.e.r);
let startRowNumber = Number(item.s.c), endRowNumber = Number(item.e.c);
const test = ws[arr[startRowNumber] + (startColNumber + 1)];
for(let col = startColNumber ; col <= endColNumber ; col++)
{
for(let row = startRowNumber; row <= endRowNumber ; row++)
{
//const test = ws[arr[j] + i];
//console.log(arr[row] + (col + 1));
ws[arr[row] + (col + 1)] = test;
//{s:{border:{top:{style:'thin'}, left:{style:'thin'},bottom:{style:'thin'},right:{style:'thin'}}}};
}
}
})
return ws;
}
function funtransformF() {
// 表頭信息 要合併的字段用null代替
let aoa = [
['江蘇省多式聯運示範工程項目2019年第二季度動態監測信息表'],
['序號', '市別', '示範工程項目名稱', '示範工程項目運行情況'],
[null, null, null, '聯運組織',null, null, null, null, null, null, '企業總貨物運輸量(萬噸/萬標箱)', null, '樞紐場站建設投資額(萬元)', '裝備配備建設投資額(萬元)', '信息化建設投資額(萬元)', '其他'],
[null, null, null, '聯運線路(條)','聯運線路運營情況', null, null, null, null, null],
[null, null, null, null, '線路', '聯運路線', '聯運模式', '聯運量', null, '聯運週轉量(萬噸公里)', null, null, null, null, null, null],
[null, null, null, null, null, null, null, '萬噸', '萬標箱', null, '萬噸', '萬標箱', null, null, null]
]
// json => sheet
const sheet = sheet_from_array_of_arrays(aoa);
// 表頭合併: r: row 行;c:column 列
const mergeTitle = [
// 江蘇省多式聯運示範工程項目2019年第二季度動態監測信息表
{
s: {r: 0, c: 0},
e: {r: 0, c: 15}
},
// 序號
{
s: {r: 1, c: 0},
e: {r: 5, c: 0}
},
// 市別
{
s: {r: 1, c: 1},
e: {r: 5, c: 1}
},
// 示範工程名稱
{
s: {r: 1, c: 2},
e: {r: 5, c: 2}
},
// 示範工程項目運行情況
{
s: {r: 1, c: 3},
e: {r: 1, c: 15}
},
// 聯運組織
{
s: {r: 2, c: 3},
e: {r: 2, c: 9}
},
// 聯運線路(條)
{
s: {r: 3, c: 3},
e: {r: 5, c: 3}
},
// 聯運線路運營情況
{
s: {r: 3, c: 4},
e: {r: 3, c: 9}
},
// 線路
{
s: {r: 4, c: 4},
e: {r: 5, c: 4}
},
// 聯運路線
{
s: {r: 4, c: 5},
e: {r: 5, c: 5}
},
// 聯運模式
{
s: {r: 4, c: 6},
e: {r: 5, c: 6}
},
// 聯運量
{
s: {r: 4, c: 7},
e: {r: 4, c: 8}
},
// 聯運週轉量(萬噸公里)
{
s: {r: 4, c: 9},
e: {r: 5, c: 9}
},
// 企業總貨物運輸量(萬噸/萬標箱)
{
s: {r: 2, c: 10},
e: {r: 4, c: 11}
},
// 樞紐場站建設投資額(萬元)
{
s: {r: 2, c: 12},
e: {r: 5, c: 12}
},
//裝備配備建設投資額(萬元)
{
s: {r: 2, c: 13},
e: {r: 5, c: 13}
},
// 信息化建設投資額(萬元)
{
s: {r: 2, c: 14},
e: {r: 5, c: 14}
},
// 其他
{
s: {r: 2, c: 15},
e: {r: 5, c: 15}
},
]
//sheet['!merges'] = mergeTitle.concat(mergeContent);
sheet['!merges'] = mergeTitle;
// 凍結前6行和第一列,右下可以滑動
sheet["!freeze"] = {
xSplit: "1",
ySplit: "6",
topLeftCell: "B7",
activePane: "bottomRight",
state: "frozen",
}
sheet["!margins"] = { left: 1.0, right: 1.0, top: 1.0, bottom: 1.0, header: 0.5, footer: 0.5 }
// 列寬 使用的不是像素值
const sheetCols = [
{ wch: 8} , // 序號
{ wch: 10 }, // 市別
{ wch: 20 }, // 示範工程項目名稱
{ wch: 9 }, // 聯運線路(條)
{ wch: 8 }, // 線路
{ wch: 18 }, // 聯運路線
{ wch: 15 }, // 聯運模式
{ wch: 9 }, // 聯運量-萬噸
{ wch: 9 }, // 聯運量-萬標箱
{ wch: 12 }, // 聯運週轉量
{ wch: 9 }, // 企業萬噸
{ wch: 9 }, // 企業 萬標箱
{ wch: 10 }, // 樞紐站
{ wch: 10 }, // 裝備
{ wch: 10 }, // 信息化
{ wch: 27 }, // 備註
];
sheet['!cols'] = sheetCols;
addRangeBorder(mergeTitle, sheet);
const wbBlob = sheet2blob(sheet, '1')
// 保存下載
FileSaver.saveAs(wbBlob, 'd.xlsx')
}
export {
funtransformF
}
效果圖: