explicitly share styles and themes

This commit is contained in:
SheetJS 2017-03-18 19:25:50 -04:00
parent 5a3774e36e
commit 7888070603
20 changed files with 181 additions and 183 deletions

View File

@ -113,7 +113,6 @@ var parse_rs = (function parse_rs_factory() {
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
}
}
/* TODO: These should be generated styles, not inline */
var style = [];
if(font.b) style.push("font-weight: bold;");
if(font.i) style.push("font-style: italic;");

View File

@ -1,4 +0,0 @@
var styles = {}; // shared styles
var themes = {}; // shared themes

View File

@ -1,5 +1,5 @@
/* 18.8.21 fills CT_Fills */
function parse_fills(t, opts) {
function parse_fills(t, styles, opts) {
styles.Fills = [];
var fill = {};
t[0].match(tagregex).forEach(function(x) {
@ -39,13 +39,13 @@ function parse_fills(t, opts) {
break;
case '<fgColor/>': case '</fgColor>': break;
default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
}
});
}
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, opts) {
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
@ -77,7 +77,7 @@ function write_numFmts(NF/*:{[n:number]:string}*/, opts) {
}
/* 18.8.10 cellXfs CT_CellXfs */
function parse_cellXfs(t, opts) {
function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
t[0].match(tagregex).forEach(function(x) {
var y = parsexmltag(x);
@ -121,24 +121,25 @@ var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
return function parse_sty_xml(data, opts) {
var styles = {};
if(!data) return styles;
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* numFmts CT_NumFmts ? */
if((t=data.match(numFmtRegex))) parse_numFmts(t, opts);
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
/* fonts CT_Fonts ? */
/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/
/* fills CT_Fills */
if((t=data.match(fillsRegex))) parse_fills(t, opts);
if((t=data.match(fillsRegex))) parse_fills(t, styles, opts);
/* borders CT_Borders ? */
/* cellStyleXfs CT_CellStyleXfs ? */
/* cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts);
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
/* dxfs CT_Dxfs ? */
/* tableStyles CT_TableStyles ? */

View File

@ -42,6 +42,7 @@ function parse_BrtXF(data, length/*:number*/) {
/* [MS-XLSB] 2.1.7.50 Styles */
function parse_sty_bin(data, opts) {
var styles = {};
styles.NumberFmt = ([]/*:any*/);
for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];

View File

@ -1,7 +1,7 @@
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
/* 20.1.6.2 clrScheme CT_ColorScheme */
function parse_clrScheme(t, opts) {
function parse_clrScheme(t, themes, opts) {
themes.themeElements.clrScheme = [];
var color = {};
(t[0].match(tagregex)||[]).forEach(function(x) {
@ -59,23 +59,23 @@ function parse_clrScheme(t, opts) {
}
break;
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme';
default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
}
});
}
/* 20.1.4.1.18 fontScheme CT_FontScheme */
function parse_fontScheme(t, opts) { }
function parse_fontScheme(t, themes, opts) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(t, opts) { }
function parse_fmtScheme(t, themes, opts) { }
var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/;
/* 20.1.6.10 themeElements CT_BaseStyles */
function parse_themeElements(data, opts) {
function parse_themeElements(data, themes, opts) {
themes.themeElements = {};
var t;
@ -89,7 +89,7 @@ function parse_themeElements(data, opts) {
['fmtScheme', fmtsregex, parse_fmtScheme]
].forEach(function(m) {
if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
m[2](t, opts);
m[2](t, themes, opts);
});
}
@ -98,18 +98,19 @@ var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/;
/* 14.2.7 Theme Part */
function parse_theme_xml(data/*:string*/, opts) {
/* 20.1.6.9 theme CT_OfficeStyleSheet */
if(!data || data.length === 0) return themes;
if(!data || data.length === 0) return parse_theme_xml(write_theme());
var t;
var themes = {};
/* themeElements CT_BaseStyles */
if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme';
parse_themeElements(t[0], opts);
parse_themeElements(t[0], themes, opts);
return themes;
}
function write_theme() {
function write_theme(Themes, opts)/*:string*/ {
var o = [XML_HEADER];
o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
o[o.length] = '<a:themeElements>';
@ -264,15 +265,15 @@ function write_theme() {
o[o.length] = '</a:gradFill>';
o[o.length] = '</a:bgFillStyleLst>';
o[o.length] = '</a:fmtScheme>';
o[o.length] = '</a:themeElements>';
o[o.length] = '<a:objectDefaults>';
o[o.length] = '<a:spDef>';
o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>';
o[o.length] = '</a:spDef>';
o[o.length] = '<a:lnDef>';
o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>';
o[o.length] = '</a:lnDef>';
o[o.length] = '</a:lnDef>';
o[o.length] = '</a:objectDefaults>';
o[o.length] = '<a:extraClrSchemeLst/>';
o[o.length] = '</a:theme>';

View File

@ -1,5 +1,5 @@
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
function parse_Theme(blob, length) {
function parse_Theme(blob, length, opts) {
var dwThemeVersion = blob.read_shift(4);
if(dwThemeVersion === 124226) return;
blob.l += length-4;

View File

@ -22,7 +22,7 @@ function get_cell_style(styles, cell, opts) {
return len;
}
function safe_format(p, fmtid, fillid, opts) {
function safe_format(p, fmtid, fillid, opts, themes, styles) {
if(p.t === 'z') return;
if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v);
try {

View File

@ -8,7 +8,7 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ {
function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = ({}/*:any*/);
@ -39,7 +39,7 @@ function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ {
/* 18.3.1.80 sheetData CT_SheetData ? */
var mtch=data.match(sheetdataregex);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data.match(hlinkregex);
@ -173,7 +173,7 @@ var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata, s, opts, guess) {
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -288,7 +288,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId;
}
}
safe_format(p, fmtid, fillid, opts);
safe_format(p, fmtid, fillid, opts, themes, styles);
s[tag.r] = p;
}
}

View File

@ -256,7 +256,7 @@ function parse_BrtShrFmla(data, length, opts) {
}
/* [MS-XLSB] 2.1.7.61 Worksheet */
function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
if(!rels) rels = {'!id':{}};
var s = {};
@ -311,7 +311,7 @@ function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts);
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
s[encode_col(C=val[0].c) + rr] = p;
if(opts.cellFormula) {
af = false;

View File

@ -3,9 +3,9 @@ function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
return parse_wb_xml((data/*:any*/), opts);
}
function parse_ws(data, name/*:string*/, opts, rels, wb)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb);
return parse_ws_xml((data/*:any*/), opts, rels, wb);
function parse_ws(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb, themes, styles);
return parse_ws_xml((data/*:any*/), opts, rels, wb, themes, styles);
}
function parse_sty(data, name/*:string*/, opts) {

View File

@ -149,7 +149,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
biff: 8, // BIFF version
codepage: 0, // CP from CodePage record
winlocked: 0, // fLockWn from WinProtect
wtf: false
WTF: !!options && !!options.wtf
}/*:any*/);
if(options.password) opts.password = options.password;
var mergecells = [];

View File

@ -35,6 +35,7 @@ var parse_content_xml = (function() {
var rept = 1, isstub = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([^\u2603]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
@ -388,7 +389,7 @@ var parse_content_xml = (function() {
if(Rn[2] === 'uof:') break; // TODO: uof
if(Rn[2] === '表:') break; // TODO: uof
if(Rn[2] === '字:') break; // TODO: uof
if(opts.WTF) throw Rn;
if(opts.WTF) throw new Error(Rn);
}
var out = {
Sheets: Sheets,

View File

@ -6,10 +6,10 @@ function safe_parse_wbrels(wbrels, sheets) {
return !wbrels || wbrels.length === 0 ? null : wbrels;
}
function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb) {
function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb, themes, styles) {
try {
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb);
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb, themes, styles);
} catch(e) { if(opts.WTF) throw e; }
}
@ -42,14 +42,14 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
if(xlsb) set_cp(1200);
var themes = ({}/*:any*/);
var styles = ({}/*:any*/);
if(!opts.bookSheets && !opts.bookProps) {
strs = [];
if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts);
styles = {};
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
themes = {};
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
}
@ -112,7 +112,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
path = path.replace(/sheet0\./,"sheet.");
}
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb);
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb, themes, styles);
}
if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);

View File

@ -78,7 +78,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
/* TODO: something more intelligent with themes */
f = "xl/theme/theme1.xml";
zip.file(f, write_theme());
zip.file(f, write_theme(wb.Themes, opts));
ct.themes.push(f);
add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME);

View File

@ -15,6 +15,7 @@ type Workbook = {
Props?: any;
Custprops?: any;
Themes?: any;
SSF?: {[n:number]:string};
cfb?: any;

View File

@ -601,7 +601,7 @@ function diffsty(ws, r1,r2) {
}
describe('parse features', function() {
it('should have comment as part of cell properties', function(){
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
var X = require(modp);
var sheet = 'Sheet1';
var wb1=X.readFile(paths.swcxlsx);
@ -620,7 +620,7 @@ describe('parse features', function() {
});
describe('should parse core properties and custom properties', function() {
var wb1, wb2;
var wb1, wb2, wb3, wb4;
var bef = (function() {
wb1 = X.readFile(paths.cpxlsx);
wb2 = X.readFile(paths.cpxlsb);
@ -1142,7 +1142,7 @@ describe('corner cases', function() {
["foo","bar",new Date("2014-02-19T14:30Z"), "0.3"],
["baz", null, "q\"ux"]
];
ws = sheet_from_array_of_arrays(data);
var ws = sheet_from_array_of_arrays(data);
ws.A1.f = ""; ws.A1.w = "";
delete ws.C3.w; delete ws.C3.z; ws.C3.XF = {ifmt:14};
ws.A4.t = "e";

@ -1 +1 @@
Subproject commit e0b7060b10ef972ad48869faa4efffd089e1a428
Subproject commit 664ad78895cb8dad33e8e993614555baf7d999ae

106
tests.lst
View File

@ -353,8 +353,8 @@ openpyxl_r_null_file.xlsx.pending
phonetic_text.xlsx
pivot_table_named_range.xlsx
rich_text_stress.xlsx
roo-xls_numbers1.xlsx
roo-xls_type_excel.xlsx
roo_numbers1.xlsx
# roo_type_excel.xlsx # incorrect baseline
roo_1900_base.xlsx
roo_1904_base.xlsx
roo_Bibelbund.xlsx
@ -538,8 +538,8 @@ formula_stress_test.ods
merge_cells.ods
number_format.ods
rich_text_stress.ods
roo-xls_numbers1.ods
roo-xls_type_excel.ods
roo_numbers1.ods
roo_type_excel.ods
roo_Bibelbund.ods
roo_Bibelbund1.ods
roo_advanced_header.ods
@ -1193,34 +1193,34 @@ pyExcelerator_mini-mini.xls
pyExcelerator_mini.xls
pyExcelerator_oo14.xls
rich_text_stress.xls
roo-xls_1900_base.xls
roo-xls_1904_base.xls
roo-xls_Bibelbund.xls
roo-xls_bad_excel_date.xls
roo-xls_bbu.xls
roo-xls_boolean.xls
roo-xls_borders.xls
roo-xls_bug-row-column-fixnum-float.xls
roo-xls_comments.xls
roo-xls_datetime.xls
roo-xls_datetime_floatconv.xls
roo-xls_emptysheets.xls
roo-xls_false_encoding.xls
roo-xls_formula.xls
roo-xls_formula_parse_error.xls
roo-xls_link.xls
roo-xls_matrix.xls
roo-xls_named_cells.xls
roo-xls_numbers1.xls
roo-xls_only_one_sheet.xls
roo-xls_paragraph.xls
roo-xls_prova.xls
roo-xls_simple_spreadsheet.xls
roo-xls_simple_spreadsheet_from_italo.xls
roo-xls_style.xls
roo-xls_time-test.xls
roo-xls_type_excelx.xls
roo-xls_type_openoffice.xls
roo_1900_base.xls
roo_1904_base.xls
roo_Bibelbund.xls
roo_bad_excel_date.xls
roo_bbu.xls
roo_boolean.xls
roo_borders.xls
roo_bug-row-column-fixnum-float.xls
roo_comments.xls
roo_datetime.xls
roo_datetime_floatconv.xls
roo_emptysheets.xls
roo_false_encoding.xls
roo_formula.xls
roo_formula_parse_error.xls
roo_link.xls
roo_matrix.xls
roo_named_cells.xls
roo_numbers1.xls
roo_only_one_sheet.xls
roo_paragraph.xls
roo_prova.xls
roo_simple_spreadsheet.xls
roo_simple_spreadsheet_from_italo.xls
roo_style.xls
roo_time-test.xls
roo_type_excelx.xls
# roo_type_openoffice.xls # incorrect baseline
roo_whitespace.xls
smart_tags_2007.xls
sushi.xls
@ -1300,27 +1300,27 @@ protect_stress_test_xml.xml
rich_text_stress.xls.xml
rich_text_stress.xlsb.xml
rich_text_stress.xlsx.xml
roo-xls_Bibelbund.xml
roo-xls_bbu.xml
roo-xls_boolean.xml
roo-xls_borders.xml
roo-xls_bug-row-column-fixnum-float.xml
roo-xls_datetime.xml
roo-xls_datetime_floatconv.xml
roo-xls_emptysheets.xml
roo-xls_excel2003.xml
roo-xls_excel2003_namespace.xml
roo-xls_false_encoding.xml
roo-xls_formula.xml
roo-xls_formula_parse_error.xml
roo-xls_numbers1.xml
roo-xls_only_one_sheet.xml
roo-xls_paragraph.xml
roo-xls_simple_spreadsheet.xml
roo-xls_simple_spreadsheet_from_italo.xml
roo-xls_style.xml
roo-xls_time-test.xml
roo-xls_whitespace.xml
roo_Bibelbund.xml
# roo_bbu.xml # SSF TODO
# roo_boolean.xml # SSF TODO
roo_borders.xml
roo_bug-row-column-fixnum-float.xml
# roo_datetime.xml # SSF TODO
# roo_datetime_floatconv.xml # SSF TODO
roo_emptysheets.xml
# roo_excel2003.xml # SSF TODO
roo_excel2003_namespace.xml
# roo_false_encoding.xml # SSF TODO
roo_formula.xml
roo_formula_parse_error.xml
# roo_numbers1.xml # SSF TODO
roo_only_one_sheet.xml
roo_paragraph.xml
# roo_simple_spreadsheet.xml # SSF TODO
# roo_simple_spreadsheet_from_italo.xml # SSF TODO
roo_style.xml
# roo_time-test.xml # SSF TODO
# roo_whitespace.xml # SSF TODO
# roo_sheet1.xml
smart_tags_2007.xml
sushi.xml

View File

@ -4666,7 +4666,6 @@ var parse_rs = (function parse_rs_factory() {
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
}
}
/* TODO: These should be generated styles, not inline */
var style = [];
if(font.b) style.push("font-weight: bold;");
if(font.i) style.push("font-style: italic;");
@ -5072,12 +5071,8 @@ var XLMLPatternTypeMap = {
"ThinHorzCross": "lightGrid"
};
var styles = {}; // shared styles
var themes = {}; // shared themes
/* 18.8.21 fills CT_Fills */
function parse_fills(t, opts) {
function parse_fills(t, styles, opts) {
styles.Fills = [];
var fill = {};
t[0].match(tagregex).forEach(function(x) {
@ -5117,13 +5112,13 @@ function parse_fills(t, opts) {
break;
case '<fgColor/>': case '</fgColor>': break;
default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
}
});
}
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, opts) {
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(SSF._table)/*:any*/);
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
@ -5155,7 +5150,7 @@ function write_numFmts(NF/*:{[n:number]:string}*/, opts) {
}
/* 18.8.10 cellXfs CT_CellXfs */
function parse_cellXfs(t, opts) {
function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
t[0].match(tagregex).forEach(function(x) {
var y = parsexmltag(x);
@ -5199,24 +5194,25 @@ var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
return function parse_sty_xml(data, opts) {
var styles = {};
if(!data) return styles;
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* numFmts CT_NumFmts ? */
if((t=data.match(numFmtRegex))) parse_numFmts(t, opts);
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
/* fonts CT_Fonts ? */
/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/
/* fills CT_Fills */
if((t=data.match(fillsRegex))) parse_fills(t, opts);
if((t=data.match(fillsRegex))) parse_fills(t, styles, opts);
/* borders CT_Borders ? */
/* cellStyleXfs CT_CellStyleXfs ? */
/* cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts);
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
/* dxfs CT_Dxfs ? */
/* tableStyles CT_TableStyles ? */
@ -5293,6 +5289,7 @@ function parse_BrtXF(data, length/*:number*/) {
/* [MS-XLSB] 2.1.7.50 Styles */
function parse_sty_bin(data, opts) {
var styles = {};
styles.NumberFmt = ([]/*:any*/);
for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
@ -5385,7 +5382,7 @@ function write_sty_bin(data, opts) {
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
/* 20.1.6.2 clrScheme CT_ColorScheme */
function parse_clrScheme(t, opts) {
function parse_clrScheme(t, themes, opts) {
themes.themeElements.clrScheme = [];
var color = {};
(t[0].match(tagregex)||[]).forEach(function(x) {
@ -5443,23 +5440,23 @@ function parse_clrScheme(t, opts) {
}
break;
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme';
default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
}
});
}
/* 20.1.4.1.18 fontScheme CT_FontScheme */
function parse_fontScheme(t, opts) { }
function parse_fontScheme(t, themes, opts) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(t, opts) { }
function parse_fmtScheme(t, themes, opts) { }
var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/;
/* 20.1.6.10 themeElements CT_BaseStyles */
function parse_themeElements(data, opts) {
function parse_themeElements(data, themes, opts) {
themes.themeElements = {};
var t;
@ -5473,7 +5470,7 @@ function parse_themeElements(data, opts) {
['fmtScheme', fmtsregex, parse_fmtScheme]
].forEach(function(m) {
if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
m[2](t, opts);
m[2](t, themes, opts);
});
}
@ -5482,18 +5479,19 @@ var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/;
/* 14.2.7 Theme Part */
function parse_theme_xml(data/*:string*/, opts) {
/* 20.1.6.9 theme CT_OfficeStyleSheet */
if(!data || data.length === 0) return themes;
if(!data || data.length === 0) return parse_theme_xml(write_theme());
var t;
var themes = {};
/* themeElements CT_BaseStyles */
if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme';
parse_themeElements(t[0], opts);
parse_themeElements(t[0], themes, opts);
return themes;
}
function write_theme() {
function write_theme(Themes, opts)/*:string*/ {
var o = [XML_HEADER];
o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
o[o.length] = '<a:themeElements>';
@ -5648,22 +5646,22 @@ function write_theme() {
o[o.length] = '</a:gradFill>';
o[o.length] = '</a:bgFillStyleLst>';
o[o.length] = '</a:fmtScheme>';
o[o.length] = '</a:themeElements>';
o[o.length] = '<a:objectDefaults>';
o[o.length] = '<a:spDef>';
o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>';
o[o.length] = '</a:spDef>';
o[o.length] = '<a:lnDef>';
o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>';
o[o.length] = '</a:lnDef>';
o[o.length] = '</a:lnDef>';
o[o.length] = '</a:objectDefaults>';
o[o.length] = '<a:extraClrSchemeLst/>';
o[o.length] = '</a:theme>';
return o.join("");
}
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
function parse_Theme(blob, length) {
function parse_Theme(blob, length, opts) {
var dwThemeVersion = blob.read_shift(4);
if(dwThemeVersion === 124226) return;
blob.l += length-4;
@ -8248,7 +8246,7 @@ function get_cell_style(styles, cell, opts) {
return len;
}
function safe_format(p, fmtid, fillid, opts) {
function safe_format(p, fmtid, fillid, opts, themes, styles) {
if(p.t === 'z') return;
if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v);
try {
@ -8292,7 +8290,7 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ {
function parse_ws_xml(data/*:?string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = ({}/*:any*/);
@ -8323,7 +8321,7 @@ function parse_ws_xml(data/*:?string*/, opts, rels)/*:Worksheet*/ {
/* 18.3.1.80 sheetData CT_SheetData ? */
var mtch=data.match(sheetdataregex);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data.match(hlinkregex);
@ -8457,7 +8455,7 @@ var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata, s, opts, guess) {
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p/*:any*/;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -8572,7 +8570,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId;
}
}
safe_format(p, fmtid, fillid, opts);
safe_format(p, fmtid, fillid, opts, themes, styles);
s[tag.r] = p;
}
}
@ -8878,7 +8876,7 @@ function parse_BrtShrFmla(data, length, opts) {
}
/* [MS-XLSB] 2.1.7.61 Worksheet */
function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
function parse_ws_bin(data, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(!data) return data;
if(!rels) rels = {'!id':{}};
var s = {};
@ -8933,7 +8931,7 @@ function parse_ws_bin(data, opts, rels, wb)/*:Worksheet*/ {
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts);
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
s[encode_col(C=val[0].c) + rr] = p;
if(opts.cellFormula) {
af = false;
@ -9704,9 +9702,9 @@ function parse_wb(data, name/*:string*/, opts)/*:WorkbookFile*/ {
return parse_wb_xml((data/*:any*/), opts);
}
function parse_ws(data, name/*:string*/, opts, rels, wb)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb);
return parse_ws_xml((data/*:any*/), opts, rels, wb);
function parse_ws(data, name/*:string*/, opts, rels, wb, themes, styles)/*:Worksheet*/ {
if(name.slice(-4)===".bin") return parse_ws_bin((data/*:any*/), opts, rels, wb, themes, styles);
return parse_ws_xml((data/*:any*/), opts, rels, wb, themes, styles);
}
function parse_sty(data, name/*:string*/, opts) {
@ -10756,7 +10754,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
biff: 8, // BIFF version
codepage: 0, // CP from CodePage record
winlocked: 0, // fLockWn from WinProtect
wtf: false
WTF: !!options && !!options.wtf
}/*:any*/);
if(options.password) opts.password = options.password;
var mergecells = [];
@ -12763,6 +12761,7 @@ var parse_content_xml = (function() {
var rept = 1, isstub = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([^\u2603]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
@ -13116,7 +13115,7 @@ var parse_content_xml = (function() {
if(Rn[2] === 'uof:') break; // TODO: uof
if(Rn[2] === '表:') break; // TODO: uof
if(Rn[2] === '字:') break; // TODO: uof
if(opts.WTF) throw Rn;
if(opts.WTF) throw new Error(Rn);
}
var out = {
Sheets: Sheets,
@ -13296,10 +13295,10 @@ function safe_parse_wbrels(wbrels, sheets) {
return !wbrels || wbrels.length === 0 ? null : wbrels;
}
function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb) {
function safe_parse_ws(zip, path/*:string*/, relsPath/*:string*/, sheet, sheetRels, sheets, opts, wb, themes, styles) {
try {
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb);
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb, themes, styles);
} catch(e) { if(opts.WTF) throw e; }
}
@ -13332,14 +13331,14 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
if(xlsb) set_cp(1200);
var themes = ({}/*:any*/);
var styles = ({}/*:any*/);
if(!opts.bookSheets && !opts.bookProps) {
strs = [];
if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts);
styles = {};
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
themes = {};
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
}
@ -13402,7 +13401,7 @@ function parse_zip(zip/*:ZIP*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
path = path.replace(/sheet0\./,"sheet.");
}
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb);
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb, themes, styles);
}
if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
@ -13510,7 +13509,7 @@ function write_zip(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
/* TODO: something more intelligent with themes */
f = "xl/theme/theme1.xml";
zip.file(f, write_theme());
zip.file(f, write_theme(wb.Themes, opts));
ct.themes.push(f);
add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME);

83
xlsx.js
View File

@ -4614,7 +4614,6 @@ var parse_rs = (function parse_rs_factory() {
if(y[0].charCodeAt(1) !== 47) throw 'Unrecognized rich format ' + y[0];
}
}
/* TODO: These should be generated styles, not inline */
var style = [];
if(font.b) style.push("font-weight: bold;");
if(font.i) style.push("font-style: italic;");
@ -5020,12 +5019,8 @@ var XLMLPatternTypeMap = {
"ThinHorzCross": "lightGrid"
};
var styles = {}; // shared styles
var themes = {}; // shared themes
/* 18.8.21 fills CT_Fills */
function parse_fills(t, opts) {
function parse_fills(t, styles, opts) {
styles.Fills = [];
var fill = {};
t[0].match(tagregex).forEach(function(x) {
@ -5065,13 +5060,13 @@ function parse_fills(t, opts) {
break;
case '<fgColor/>': case '</fgColor>': break;
default: if(opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
default: if(opts && opts.WTF) throw new Error('unrecognized ' + y[0] + ' in fills');
}
});
}
/* 18.8.31 numFmts CT_NumFmts */
function parse_numFmts(t, opts) {
function parse_numFmts(t, styles, opts) {
styles.NumberFmt = [];
var k/*Array<number>*/ = (keys(SSF._table));
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
@ -5103,7 +5098,7 @@ function write_numFmts(NF, opts) {
}
/* 18.8.10 cellXfs CT_CellXfs */
function parse_cellXfs(t, opts) {
function parse_cellXfs(t, styles, opts) {
styles.CellXf = [];
t[0].match(tagregex).forEach(function(x) {
var y = parsexmltag(x);
@ -5147,24 +5142,25 @@ var cellXfRegex = /<cellXfs([^>]*)>.*<\/cellXfs>/;
var fillsRegex = /<fills([^>]*)>.*<\/fills>/;
return function parse_sty_xml(data, opts) {
var styles = {};
if(!data) return styles;
/* 18.8.39 styleSheet CT_Stylesheet */
var t;
/* numFmts CT_NumFmts ? */
if((t=data.match(numFmtRegex))) parse_numFmts(t, opts);
if((t=data.match(numFmtRegex))) parse_numFmts(t, styles, opts);
/* fonts CT_Fonts ? */
/*if((t=data.match(/<fonts([^>]*)>.*<\/fonts>/))) parse_fonts(t, opts);*/
/* fills CT_Fills */
if((t=data.match(fillsRegex))) parse_fills(t, opts);
if((t=data.match(fillsRegex))) parse_fills(t, styles, opts);
/* borders CT_Borders ? */
/* cellStyleXfs CT_CellStyleXfs ? */
/* cellXfs CT_CellXfs ? */
if((t=data.match(cellXfRegex))) parse_cellXfs(t, opts);
if((t=data.match(cellXfRegex))) parse_cellXfs(t, styles, opts);
/* dxfs CT_Dxfs ? */
/* tableStyles CT_TableStyles ? */
@ -5241,6 +5237,7 @@ function parse_BrtXF(data, length) {
/* [MS-XLSB] 2.1.7.50 Styles */
function parse_sty_bin(data, opts) {
var styles = {};
styles.NumberFmt = ([]);
for(var y in SSF._table) styles.NumberFmt[y] = SSF._table[y];
@ -5333,7 +5330,7 @@ function write_sty_bin(data, opts) {
RELS.THEME = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
/* 20.1.6.2 clrScheme CT_ColorScheme */
function parse_clrScheme(t, opts) {
function parse_clrScheme(t, themes, opts) {
themes.themeElements.clrScheme = [];
var color = {};
(t[0].match(tagregex)||[]).forEach(function(x) {
@ -5391,23 +5388,23 @@ function parse_clrScheme(t, opts) {
}
break;
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in clrScheme';
default: if(opts && opts.WTF) throw new Error('Unrecognized ' + y[0] + ' in clrScheme');
}
});
}
/* 20.1.4.1.18 fontScheme CT_FontScheme */
function parse_fontScheme(t, opts) { }
function parse_fontScheme(t, themes, opts) { }
/* 20.1.4.1.15 fmtScheme CT_StyleMatrix */
function parse_fmtScheme(t, opts) { }
function parse_fmtScheme(t, themes, opts) { }
var clrsregex = /<a:clrScheme([^>]*)>[^\u2603]*<\/a:clrScheme>/;
var fntsregex = /<a:fontScheme([^>]*)>[^\u2603]*<\/a:fontScheme>/;
var fmtsregex = /<a:fmtScheme([^>]*)>[^\u2603]*<\/a:fmtScheme>/;
/* 20.1.6.10 themeElements CT_BaseStyles */
function parse_themeElements(data, opts) {
function parse_themeElements(data, themes, opts) {
themes.themeElements = {};
var t;
@ -5421,7 +5418,7 @@ function parse_themeElements(data, opts) {
['fmtScheme', fmtsregex, parse_fmtScheme]
].forEach(function(m) {
if(!(t=data.match(m[1]))) throw new Error(m[0] + ' not found in themeElements');
m[2](t, opts);
m[2](t, themes, opts);
});
}
@ -5430,18 +5427,19 @@ var themeltregex = /<a:themeElements([^>]*)>[^\u2603]*<\/a:themeElements>/;
/* 14.2.7 Theme Part */
function parse_theme_xml(data, opts) {
/* 20.1.6.9 theme CT_OfficeStyleSheet */
if(!data || data.length === 0) return themes;
if(!data || data.length === 0) return parse_theme_xml(write_theme());
var t;
var themes = {};
/* themeElements CT_BaseStyles */
if(!(t=data.match(themeltregex))) throw 'themeElements not found in theme';
parse_themeElements(t[0], opts);
parse_themeElements(t[0], themes, opts);
return themes;
}
function write_theme() {
function write_theme(Themes, opts) {
var o = [XML_HEADER];
o[o.length] = '<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office Theme">';
o[o.length] = '<a:themeElements>';
@ -5596,22 +5594,22 @@ function write_theme() {
o[o.length] = '</a:gradFill>';
o[o.length] = '</a:bgFillStyleLst>';
o[o.length] = '</a:fmtScheme>';
o[o.length] = '</a:themeElements>';
o[o.length] = '<a:objectDefaults>';
o[o.length] = '<a:spDef>';
o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="1"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="3"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="2"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="lt1"/></a:fontRef></a:style>';
o[o.length] = '</a:spDef>';
o[o.length] = '<a:lnDef>';
o[o.length] = '<a:spPr/><a:bodyPr/><a:lstStyle/><a:style><a:lnRef idx="2"><a:schemeClr val="accent1"/></a:lnRef><a:fillRef idx="0"><a:schemeClr val="accent1"/></a:fillRef><a:effectRef idx="1"><a:schemeClr val="accent1"/></a:effectRef><a:fontRef idx="minor"><a:schemeClr val="tx1"/></a:fontRef></a:style>';
o[o.length] = '</a:lnDef>';
o[o.length] = '</a:lnDef>';
o[o.length] = '</a:objectDefaults>';
o[o.length] = '<a:extraClrSchemeLst/>';
o[o.length] = '</a:theme>';
return o.join("");
}
/* [MS-XLS] 2.4.326 TODO: payload is a zip file */
function parse_Theme(blob, length) {
function parse_Theme(blob, length, opts) {
var dwThemeVersion = blob.read_shift(4);
if(dwThemeVersion === 124226) return;
blob.l += length-4;
@ -8195,7 +8193,7 @@ function get_cell_style(styles, cell, opts) {
return len;
}
function safe_format(p, fmtid, fillid, opts) {
function safe_format(p, fmtid, fillid, opts, themes, styles) {
if(p.t === 'z') return;
if(p.t === 'd' && typeof p.v === 'string') p.v = new Date(p.v);
try {
@ -8239,7 +8237,7 @@ var hlinkregex = /<(?:\w*:)?hyperlink[^>]*\/>/g;
var dimregex = /"(\w*:\w*)"/;
var colregex = /<(?:\w*:)?col[^>]*\/>/g;
/* 18.3 Worksheets */
function parse_ws_xml(data, opts, rels) {
function parse_ws_xml(data, opts, rels, wb, themes, styles) {
if(!data) return data;
/* 18.3.1.99 worksheet CT_Worksheet */
var s = ({});
@ -8270,7 +8268,7 @@ function parse_ws_xml(data, opts, rels) {
/* 18.3.1.80 sheetData CT_SheetData ? */
var mtch=data.match(sheetdataregex);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess);
if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
/* 18.3.1.48 hyperlinks CT_Hyperlinks */
var hlink = data.match(hlinkregex);
@ -8404,7 +8402,7 @@ var parse_ws_xml_data = (function parse_ws_xml_data_factory() {
var refregex = /ref=["']([^"']*)["']/;
var match_v = matchtag("v"), match_f = matchtag("f");
return function parse_ws_xml_data(sdata, s, opts, guess) {
return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
var ri = 0, x = "", cells = [], cref = [], idx = 0, i=0, cc=0, d="", p;
var tag, tagr = 0, tagc = 0;
var sstr, ftag;
@ -8519,7 +8517,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess) {
if(opts.cellStyles && cf.fillId != null) fillid = cf.fillId;
}
}
safe_format(p, fmtid, fillid, opts);
safe_format(p, fmtid, fillid, opts, themes, styles);
s[tag.r] = p;
}
}
@ -8825,7 +8823,7 @@ function parse_BrtShrFmla(data, length, opts) {
}
/* [MS-XLSB] 2.1.7.61 Worksheet */
function parse_ws_bin(data, opts, rels, wb) {
function parse_ws_bin(data, opts, rels, wb, themes, styles) {
if(!data) return data;
if(!rels) rels = {'!id':{}};
var s = {};
@ -8880,7 +8878,7 @@ function parse_ws_bin(data, opts, rels, wb) {
case 'e': p.v = val[1]; p.w = BErr[p.v]; break;
case 'str': p.t = 's'; p.v = utf8read(val[1]); break;
}
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts);
if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.ifmt,null,opts, themes, styles);
s[encode_col(C=val[0].c) + rr] = p;
if(opts.cellFormula) {
af = false;
@ -9651,9 +9649,9 @@ function parse_wb(data, name, opts) {
return parse_wb_xml((data), opts);
}
function parse_ws(data, name, opts, rels, wb) {
if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, rels, wb);
return parse_ws_xml((data), opts, rels, wb);
function parse_ws(data, name, opts, rels, wb, themes, styles) {
if(name.slice(-4)===".bin") return parse_ws_bin((data), opts, rels, wb, themes, styles);
return parse_ws_xml((data), opts, rels, wb, themes, styles);
}
function parse_sty(data, name, opts) {
@ -10699,7 +10697,7 @@ function parse_workbook(blob, options) {
biff: 8, // BIFF version
codepage: 0, // CP from CodePage record
winlocked: 0, // fLockWn from WinProtect
wtf: false
WTF: !!options && !!options.wtf
});
if(options.password) opts.password = options.password;
var mergecells = [];
@ -12706,6 +12704,7 @@ var parse_content_xml = (function() {
var rept = 1, isstub = false;
var i = 0;
xlmlregex.lastIndex = 0;
str = str.replace(/<!--([^\u2603]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
case 'table': case '工作表': // 9.1.2 <table:table>
@ -13059,7 +13058,7 @@ var parse_content_xml = (function() {
if(Rn[2] === 'uof:') break; // TODO: uof
if(Rn[2] === '表:') break; // TODO: uof
if(Rn[2] === '字:') break; // TODO: uof
if(opts.WTF) throw Rn;
if(opts.WTF) throw new Error(Rn);
}
var out = {
Sheets: Sheets,
@ -13238,10 +13237,10 @@ function safe_parse_wbrels(wbrels, sheets) {
return !wbrels || wbrels.length === 0 ? null : wbrels;
}
function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts, wb) {
function safe_parse_ws(zip, path, relsPath, sheet, sheetRels, sheets, opts, wb, themes, styles) {
try {
sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb);
sheets[sheet]=parse_ws(getzipdata(zip, path),path,opts,sheetRels[sheet], wb, themes, styles);
} catch(e) { if(opts.WTF) throw e; }
}
@ -13274,14 +13273,14 @@ function parse_zip(zip, opts) {
if(dir.workbooks[0].slice(-3) == "bin") xlsb = true;
if(xlsb) set_cp(1200);
var themes = ({});
var styles = ({});
if(!opts.bookSheets && !opts.bookProps) {
strs = [];
if(dir.sst) strs=parse_sst(getzipdata(zip, dir.sst.replace(/^\//,'')), dir.sst, opts);
styles = {};
if(dir.style) styles = parse_sty(getzipdata(zip, dir.style.replace(/^\//,'')),dir.style, opts);
themes = {};
if(opts.cellStyles && dir.themes.length) themes = parse_theme(getzipstr(zip, dir.themes[0].replace(/^\//,''), true)||"",dir.themes[0], opts);
}
@ -13344,7 +13343,7 @@ function parse_zip(zip, opts) {
path = path.replace(/sheet0\./,"sheet.");
}
relsPath = path.replace(/^(.*)(\/)([^\/]*)$/, "$1/_rels/$3.rels");
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb);
safe_parse_ws(zip, path, relsPath, props.SheetNames[i], sheetRels, sheets, opts, wb, themes, styles);
}
if(dir.comments) parse_comments(zip, dir.comments, sheets, sheetRels, opts);
@ -13450,7 +13449,7 @@ f = "docProps/app.xml";
/* TODO: something more intelligent with themes */
f = "xl/theme/theme1.xml";
zip.file(f, write_theme());
zip.file(f, write_theme(wb.Themes, opts));
ct.themes.push(f);
add_rels(opts.wbrels, ++rId, "theme/theme1.xml", RELS.THEME);