上篇文章中提到关于xlsx改造冻结窗格的代码,我是怎么知道要加pane的呢,加下来就把我的心路历程记录一下。
我改造之前也是没有头绪的,我网上查了很多,只告诉我如何使用,但源码里没有针对!freeze的处理,所以即便把!freeze传过去也是无用的。于是我想既然js可以实现excel的导出,那应该有办法能实现,只是原作者写到pro版里了,那么我能不能加上呢,如何加呢?
我先贴上部分代码
// 冻结第一行和第一列:
worksheet['!freeze'] = {
xSplit: "0", //冻结列
ySplit: "1", //冻结行
// topLeftCell: "A2", //在未冻结区域的左上角显示的单元格,默认为第一个未冻结的单元格
state: "frozen"
}
var wbout = XLSX.write(workbook, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
})
首先我打印了wbout,发现是一个二进制文件,然后找到xlsx.write的write
// 部分代码
...
XLSX.parse_zip = parse_zip;
XLSX.read = readSync; //xlsread
XLSX.readFile = readFileSync; //readFile
XLSX.readFileSync = readFileSync;
XLSX.write = writeSync;
XLSX.writeFile = writeFileSync;
XLSX.writeFileSync = writeFileSync;
XLSX.writeFileAsync = writeFileAsync;
XLSX.utils = utils;
XLSX.writeXLSX = writeSyncXLSX;
XLSX.writeFileXLSX = writeFileSyncXLSX;
XLSX.SSF = SSF;
然后找到writeSync方法 -》 write_zip_type -》 write_zip -》write_zip_xlsx
function write_zip(wb, opts) {
console.log('write_zip', opts.bookType)
if(opts.bookType == "ods") return write_ods(wb, opts);
if(opts.bookType == "numbers") return write_numbers_iwa(wb, opts);
if(opts.bookType == "xlsb") return write_zip_xlsxb(wb, opts);
return write_zip_xlsx(wb, opts);
}
关键点就在write_zip_xlsx方法中
在write_zip_xlsx方法中,我们找到xl/worksheets/sheet的下面的write_ws_xml方法,
write_ws_xml方法返回的就是一段字符串,就是我们要导出的excel的内容
// 部分代码
...
var wsrels = {'!id':{}};
var ws = wb.Sheets[wb.SheetNames[rId-1]];
var _type = (ws || {})["!type"] || "sheet";
switch(_type) {
case "chart":
/* falls through */
default:
f = "xl/worksheets/sheet" + rId + "." + wbext;
zip_add_file(zip, f, write_ws_xml(rId-1, opts, wb, wsrels));
ct.sheets.push(f);
add_rels(opts.wbrels, -1, "worksheets/sheet" + rId + "." + wbext, RELS.WS[0]);
}
这里我们在write_zip_xlsx方法的xl/worksheets/sheet的下面打印一下console.log(write_ws_xml(rId-1, opts, wb, wsrels))
这里我们可以看见返回的是一个类似xml格式的字符串
(这里我加上!freeze代码之后的打印结果,没加之前是没有
这串字符的)
我们就想了excel的原理是不是就是xml格式呢,我怎么往里面添加上它能识别的标签呢??
带着疑问,我查找了下面的资料:
Excel2007格式分析和XML解析
Excel文件的本质:一个包含XML、图片文件的压缩文件夹-压缩文件-上犹电脑信息网
根据资料,我试着本地新建一个excel文件,分别一次设置冻结窗口,一个不设置,然后将文件后缀改为zip、解压,得到的目录和资料中的一致,对比两个xl/worksheets/sheet1.xml的区别,发现是
//部分代码
...
// 冻结窗口
var pane = null;
var freeze = ws['!freeze'];
console.log(freeze)
if (freeze !== undefined) {
pane = writextag('pane', null, {
xSplit: freeze.xSplit, // 冻结列
ySplit: freeze.ySplit, // 冻结行
topLeftCell: freeze.topLeftCell, // 在未冻结区域的左上角显示的单元格,默认为第一个未冻结的单元格
activePane: freeze.activePane,
state: freeze.state || 'frozen'
})
}
return writextag("sheetViews", writextag("sheetView", pane, sview), {});
以上就是完整的流程,改造冻结窗口只是示例,通过类似的过程,我们可以改造成我们想要的其他格式。