forked from sheetjs/sheetjs
		
	unified autofilter defined name sync on export
This commit is contained in:
		
							parent
							
								
									5d18f82664
								
							
						
					
					
						commit
						83ddb4c120
					
				| @ -44,6 +44,17 @@ function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ | ||||
| /*:: if(typeof ce !== 'string') throw "unreachable"; */ | ||||
| 	return cs == ce ? cs : cs + ":" + ce; | ||||
| } | ||||
| function fix_range(a1/*:string*/)/*:string*/ { | ||||
| 	var s = decode_range(a1); | ||||
| 	return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r); | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| 
 | ||||
| function safe_decode_range(range/*:string*/)/*:Range*/ { | ||||
| 	var o = {s:{c:0,r:0},e:{c:0,r:0}}; | ||||
|  | ||||
| @ -304,3 +304,20 @@ var RBErr = { | ||||
| 	"#WTF?":         0xFF | ||||
| }; | ||||
| 
 | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| 
 | ||||
|  | ||||
| @ -669,22 +669,6 @@ function parse_ExternName(blob, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.150 TODO */ | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| function parse_Lbl(blob, length, opts) { | ||||
| 	var target = blob.l + length; | ||||
| 	var flags = blob.read_shift(2); | ||||
|  | ||||
| @ -29,8 +29,8 @@ var a1_to_rc = /*#__PURE__*/(function(){ | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) { | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			var R = $4 == "$" ? (r+1) : (r == 0 ? "" : "[" + r + "]"); | ||||
| 			var C = $2 == "$" ? (c+1) : (c == 0 ? "" : "[" + c + "]"); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| @ -697,12 +697,6 @@ function make_3d_range(start, end) { | ||||
| 	return start + ":" + end; | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ { | ||||
| 	if(!supbooks) return "SH33TJSERR0"; | ||||
| 	if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti]; | ||||
|  | ||||
| @ -228,7 +228,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	return writextag("autoFilter", null, {ref:ref}); | ||||
|  | ||||
| @ -938,9 +938,9 @@ function write_AUTOFILTER(ba, ws, wb, idx) { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref)  }); | ||||
| 
 | ||||
| 	write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref))); | ||||
| 	/* *FILTERCOLUMN */ | ||||
|  | ||||
| @ -140,5 +140,16 @@ function check_wb(wb) { | ||||
| 	var Sheets = (wb.Workbook && wb.Workbook.Sheets) || []; | ||||
| 	check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i); | ||||
| 	wb.SheetNames.forEach(function(n, i) { | ||||
| 		var ws = wb.Sheets[n]; | ||||
| 		if(!ws || !ws["!autofilter"]) return; | ||||
| 		var DN; | ||||
| 		if(!wb.Workbook) wb.Workbook = {}; | ||||
| 		if(!wb.Workbook.Names) wb.Workbook.Names = []; | ||||
| 		wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; }); | ||||
| 		var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref); | ||||
| 		if(DN) DN.Ref = nn; | ||||
| 		else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn}); | ||||
| 	}); | ||||
| 	/* TODO: validate workbook */ | ||||
| } | ||||
|  | ||||
| @ -159,6 +159,10 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 	if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID; | ||||
| } | ||||
| 
 | ||||
| function xlml_prefix_dname(dname) { | ||||
| 	return XLSLblBuiltIn.indexOf("_xlnm." + dname) > -1 ? "_xlnm." + dname : dname; | ||||
| } | ||||
| 
 | ||||
| function xlml_clean_comment(comment/*:any*/) { | ||||
| 	comment.t = comment.v || ""; | ||||
| 	comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"); | ||||
| @ -366,7 +370,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			if(!Workbook.Names) Workbook.Names = []; | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName/*:DefinedName*/ = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Name: xlml_prefix_dname(_NamedRange.Name), | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) | ||||
| 			}/*:any*/); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| @ -956,7 +960,7 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name.slice(0,6) == "_xlnm." ? n.Name.slice(6) : n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb/*::, opts*/)/*:string*/ { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| @ -1209,6 +1213,8 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	/* WorksheetOptions */ | ||||
| 	o.push(write_ws_xlml_wsopts(ws, opts, idx, wb)); | ||||
| 
 | ||||
| 	if(ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 
 | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_xlml(wb, opts)/*:string*/ { | ||||
|  | ||||
| @ -44,7 +44,7 @@ can be installed with Bash on Windows or with `cygwin`. | ||||
| - [`nw.js application`](nwjs/) | ||||
| - [`Chrome / Chromium extensions`](chrome/) | ||||
| - [`Google Sheets API`](https://docs.sheetjs.com/docs/getting-started/demos/gsheet) | ||||
| - [`Adobe ExtendScript`](extendscript/) | ||||
| - [`Adobe Apps`](https://docs.sheetjs.com/docs/getting-started/demos/extendscript) | ||||
| - [`Headless Browsers`](headless/) | ||||
| - [`canvas-datagrid`](datagrid/) | ||||
| - [`x-spreadsheet`](xspreadsheet/) | ||||
|  | ||||
							
								
								
									
										1
									
								
								demos/extendscript/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								demos/extendscript/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1 +0,0 @@ | ||||
| xlsx.extendscript.js | ||||
| @ -1,16 +0,0 @@ | ||||
| APPS= aftereffects estoolkit illustrator indesign photoshop | ||||
| TARGETS=$(patsubst %,%.jsx,$(APPS)) | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: deps $(TARGETS) | ||||
| 
 | ||||
| .PHONY: deps | ||||
| deps: | ||||
| 	cp ../../dist/xlsx.extendscript.js . | ||||
| 
 | ||||
| %.base: | ||||
| 	echo "#target $*" > $@ | ||||
| 
 | ||||
| .PHONY: $(TARGETS) | ||||
| $(TARGETS):%.jsx:%.base test.jsx | ||||
| 	cat $^ > $@ | ||||
| @ -1,89 +1,7 @@ | ||||
| # Adobe ExtendScript | ||||
| 
 | ||||
| ExtendScript adds some features to a limited form of ECMAScript version 3.  With | ||||
| the included shim, the library can run within Photoshop and other Adobe apps! | ||||
| 
 | ||||
| The main file is `test.jsx`.  Target-specific files prepend target directives. | ||||
| Copy the `test.jsx` file as well as the `xlsx.extendscript.js` library script | ||||
| to wherever you want the scripts to reside. | ||||
| 
 | ||||
| 
 | ||||
| ## ExtendScript Quirks | ||||
| 
 | ||||
| There are numerous quirks in ExtendScript code parsing, especially related to | ||||
| Boolean and bit operations.  Most JS tooling will generate code that is not | ||||
| compatible with ExtendScript.  It is highly recommended to `#include` the `dist` | ||||
| file directly and avoid trying to minify or pack as part of a larger project. | ||||
| 
 | ||||
| 
 | ||||
| ## File I/O | ||||
| 
 | ||||
| Using the `"binary"` encoding, file operations will work with binary strings | ||||
| that play nice with the `"binary"` type of this library.  The `readFile` and | ||||
| `writeFile` library functions wrap the File logic: | ||||
| 
 | ||||
| ```js | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(filename); | ||||
| 
 | ||||
| /* Write file to disk */ | ||||
| XLSX.writeFile(workbook, filename); | ||||
| ``` | ||||
| 
 | ||||
| <details><summary><b>Implementation Details</b> (click to show)</summary> | ||||
| 
 | ||||
| The `readFile` and `writeFile` functions use `"binary"` encoding under the hood: | ||||
| 
 | ||||
| 
 | ||||
| ```js | ||||
| /* Read file from disk without using readFile */ | ||||
| var infile = File(filename); | ||||
| infile.open("r"); | ||||
| infile.encoding = "binary"; | ||||
| var data = infile.read(); | ||||
| var workbook = XLSX.read(data, {type:"binary"}); | ||||
| infile.close(); | ||||
| 
 | ||||
| /* Write file to disk without using writeFile */ | ||||
| var outFile = File(filename); | ||||
| outFile.open("w"); | ||||
| outFile.encoding = "binary"; | ||||
| outFile.write(workbook); | ||||
| outFile.close(); | ||||
| ``` | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ## Demo | ||||
| 
 | ||||
| The demo shows: | ||||
| 
 | ||||
| - loading the library in ExtendScript using `#include`: | ||||
| 
 | ||||
| ```js | ||||
| #include "xlsx.extendscript.js" | ||||
| ``` | ||||
| 
 | ||||
| - opening a file with `XLSX.readFile`: | ||||
| 
 | ||||
| ```js | ||||
| var workbook = XLSX.readFile("sheetjs.xlsx"); | ||||
| ``` | ||||
| 
 | ||||
| - converting a worksheet to an array of arrays: | ||||
| 
 | ||||
| ```js | ||||
| var first_sheet_name = workbook.SheetNames[0]; | ||||
| var first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| 
 | ||||
| alert(data); | ||||
| ``` | ||||
| 
 | ||||
| - writing a new workbook file: | ||||
| 
 | ||||
| ```js | ||||
| XLSX.writeFile(workbook, "sheetjs.slk"); | ||||
| ``` | ||||
| [The new demo](https://docs.sheetjs.com/docs/getting-started/demos/extendscript) | ||||
| has a more focused Photoshop example as well as notes about other extensibility | ||||
| frameworks shipping with newer versions of Creative Cloud apps. | ||||
| 
 | ||||
| [](https://github.com/SheetJS/js-xlsx) | ||||
|  | ||||
| @ -1 +0,0 @@ | ||||
| #target aftereffects | ||||
| @ -1,45 +0,0 @@ | ||||
| #target aftereffects | ||||
| var thisFile = new File($.fileName); | ||||
| var basePath = thisFile.path; | ||||
| 
 | ||||
| #include "xlsx.extendscript.js"; | ||||
| 
 | ||||
| var filename = "/sheetjs.xlsx"; | ||||
| 
 | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(basePath + filename, {cellDates:true}); | ||||
| 
 | ||||
| /* Display first worksheet */ | ||||
| var first_sheet_name = workbook.SheetNames[0], first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| alert(data); | ||||
| 
 | ||||
| var outfmts = [ | ||||
|   ["xlsb",  "testw.xlsb"], | ||||
|   ["biff8", "testw.xls"], | ||||
|   ["xlml",  "testw.xml"], | ||||
|   ["fods",  "testw.fods"], | ||||
|   ["csv",   "testw.csv"], | ||||
|   ["txt",   "testw.txt"], | ||||
|   ["slk",   "testw.slk"], | ||||
|   ["eth",   "testw.eth"], | ||||
|   ["htm",   "testw.htm"], | ||||
|   ["dif",   "testw.dif"], | ||||
|   ["ods",   "testw.ods"], | ||||
|   ["xlsx",  "testw.xlsx"] | ||||
| ]; | ||||
| for(var i = 0; i < outfmts.length; ++i) { | ||||
|   alert(outfmts[i][0]); | ||||
|   var fname = basePath + "/" + outfmts[i][1]; | ||||
| 
 | ||||
|   /* Write file to disk */ | ||||
|   XLSX.writeFile(workbook, fname); | ||||
| 
 | ||||
|   /* Read new file */ | ||||
|   var wb = XLSX.readFile(fname, {cellDates:true}); | ||||
| 
 | ||||
|   /* Display first worksheet */ | ||||
|   var f_sheet_name = wb.SheetNames[0], f_worksheet = wb.Sheets[f_sheet_name]; | ||||
|   var data = XLSX.utils.sheet_to_json(f_worksheet, {header:1, cellDates:true}); | ||||
|   alert(data); | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| #target estoolkit | ||||
| @ -1,45 +0,0 @@ | ||||
| #target estoolkit | ||||
| var thisFile = new File($.fileName); | ||||
| var basePath = thisFile.path; | ||||
| 
 | ||||
| #include "xlsx.extendscript.js"; | ||||
| 
 | ||||
| var filename = "/sheetjs.xlsx"; | ||||
| 
 | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(basePath + filename, {cellDates:true}); | ||||
| 
 | ||||
| /* Display first worksheet */ | ||||
| var first_sheet_name = workbook.SheetNames[0], first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| alert(data); | ||||
| 
 | ||||
| var outfmts = [ | ||||
|   ["xlsb",  "testw.xlsb"], | ||||
|   ["biff8", "testw.xls"], | ||||
|   ["xlml",  "testw.xml"], | ||||
|   ["fods",  "testw.fods"], | ||||
|   ["csv",   "testw.csv"], | ||||
|   ["txt",   "testw.txt"], | ||||
|   ["slk",   "testw.slk"], | ||||
|   ["eth",   "testw.eth"], | ||||
|   ["htm",   "testw.htm"], | ||||
|   ["dif",   "testw.dif"], | ||||
|   ["ods",   "testw.ods"], | ||||
|   ["xlsx",  "testw.xlsx"] | ||||
| ]; | ||||
| for(var i = 0; i < outfmts.length; ++i) { | ||||
|   alert(outfmts[i][0]); | ||||
|   var fname = basePath + "/" + outfmts[i][1]; | ||||
| 
 | ||||
|   /* Write file to disk */ | ||||
|   XLSX.writeFile(workbook, fname); | ||||
| 
 | ||||
|   /* Read new file */ | ||||
|   var wb = XLSX.readFile(fname, {cellDates:true}); | ||||
| 
 | ||||
|   /* Display first worksheet */ | ||||
|   var f_sheet_name = wb.SheetNames[0], f_worksheet = wb.Sheets[f_sheet_name]; | ||||
|   var data = XLSX.utils.sheet_to_json(f_worksheet, {header:1, cellDates:true}); | ||||
|   alert(data); | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| #target illustrator | ||||
| @ -1,45 +0,0 @@ | ||||
| #target illustrator | ||||
| var thisFile = new File($.fileName); | ||||
| var basePath = thisFile.path; | ||||
| 
 | ||||
| #include "xlsx.extendscript.js"; | ||||
| 
 | ||||
| var filename = "/sheetjs.xlsx"; | ||||
| 
 | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(basePath + filename, {cellDates:true}); | ||||
| 
 | ||||
| /* Display first worksheet */ | ||||
| var first_sheet_name = workbook.SheetNames[0], first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| alert(data); | ||||
| 
 | ||||
| var outfmts = [ | ||||
|   ["xlsb",  "testw.xlsb"], | ||||
|   ["biff8", "testw.xls"], | ||||
|   ["xlml",  "testw.xml"], | ||||
|   ["fods",  "testw.fods"], | ||||
|   ["csv",   "testw.csv"], | ||||
|   ["txt",   "testw.txt"], | ||||
|   ["slk",   "testw.slk"], | ||||
|   ["eth",   "testw.eth"], | ||||
|   ["htm",   "testw.htm"], | ||||
|   ["dif",   "testw.dif"], | ||||
|   ["ods",   "testw.ods"], | ||||
|   ["xlsx",  "testw.xlsx"] | ||||
| ]; | ||||
| for(var i = 0; i < outfmts.length; ++i) { | ||||
|   alert(outfmts[i][0]); | ||||
|   var fname = basePath + "/" + outfmts[i][1]; | ||||
| 
 | ||||
|   /* Write file to disk */ | ||||
|   XLSX.writeFile(workbook, fname); | ||||
| 
 | ||||
|   /* Read new file */ | ||||
|   var wb = XLSX.readFile(fname, {cellDates:true}); | ||||
| 
 | ||||
|   /* Display first worksheet */ | ||||
|   var f_sheet_name = wb.SheetNames[0], f_worksheet = wb.Sheets[f_sheet_name]; | ||||
|   var data = XLSX.utils.sheet_to_json(f_worksheet, {header:1, cellDates:true}); | ||||
|   alert(data); | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| #target indesign | ||||
| @ -1,45 +0,0 @@ | ||||
| #target indesign | ||||
| var thisFile = new File($.fileName); | ||||
| var basePath = thisFile.path; | ||||
| 
 | ||||
| #include "xlsx.extendscript.js"; | ||||
| 
 | ||||
| var filename = "/sheetjs.xlsx"; | ||||
| 
 | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(basePath + filename, {cellDates:true}); | ||||
| 
 | ||||
| /* Display first worksheet */ | ||||
| var first_sheet_name = workbook.SheetNames[0], first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| alert(data); | ||||
| 
 | ||||
| var outfmts = [ | ||||
|   ["xlsb",  "testw.xlsb"], | ||||
|   ["biff8", "testw.xls"], | ||||
|   ["xlml",  "testw.xml"], | ||||
|   ["fods",  "testw.fods"], | ||||
|   ["csv",   "testw.csv"], | ||||
|   ["txt",   "testw.txt"], | ||||
|   ["slk",   "testw.slk"], | ||||
|   ["eth",   "testw.eth"], | ||||
|   ["htm",   "testw.htm"], | ||||
|   ["dif",   "testw.dif"], | ||||
|   ["ods",   "testw.ods"], | ||||
|   ["xlsx",  "testw.xlsx"] | ||||
| ]; | ||||
| for(var i = 0; i < outfmts.length; ++i) { | ||||
|   alert(outfmts[i][0]); | ||||
|   var fname = basePath + "/" + outfmts[i][1]; | ||||
| 
 | ||||
|   /* Write file to disk */ | ||||
|   XLSX.writeFile(workbook, fname); | ||||
| 
 | ||||
|   /* Read new file */ | ||||
|   var wb = XLSX.readFile(fname, {cellDates:true}); | ||||
| 
 | ||||
|   /* Display first worksheet */ | ||||
|   var f_sheet_name = wb.SheetNames[0], f_worksheet = wb.Sheets[f_sheet_name]; | ||||
|   var data = XLSX.utils.sheet_to_json(f_worksheet, {header:1, cellDates:true}); | ||||
|   alert(data); | ||||
| } | ||||
| @ -1 +0,0 @@ | ||||
| #target photoshop | ||||
| @ -1,45 +0,0 @@ | ||||
| #target photoshop | ||||
| var thisFile = new File($.fileName); | ||||
| var basePath = thisFile.path; | ||||
| 
 | ||||
| #include "xlsx.extendscript.js"; | ||||
| 
 | ||||
| var filename = "/sheetjs.xlsx"; | ||||
| 
 | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(basePath + filename, {cellDates:true}); | ||||
| 
 | ||||
| /* Display first worksheet */ | ||||
| var first_sheet_name = workbook.SheetNames[0], first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| alert(data); | ||||
| 
 | ||||
| var outfmts = [ | ||||
|   ["xlsb",  "testw.xlsb"], | ||||
|   ["biff8", "testw.xls"], | ||||
|   ["xlml",  "testw.xml"], | ||||
|   ["fods",  "testw.fods"], | ||||
|   ["csv",   "testw.csv"], | ||||
|   ["txt",   "testw.txt"], | ||||
|   ["slk",   "testw.slk"], | ||||
|   ["eth",   "testw.eth"], | ||||
|   ["htm",   "testw.htm"], | ||||
|   ["dif",   "testw.dif"], | ||||
|   ["ods",   "testw.ods"], | ||||
|   ["xlsx",  "testw.xlsx"] | ||||
| ]; | ||||
| for(var i = 0; i < outfmts.length; ++i) { | ||||
|   alert(outfmts[i][0]); | ||||
|   var fname = basePath + "/" + outfmts[i][1]; | ||||
| 
 | ||||
|   /* Write file to disk */ | ||||
|   XLSX.writeFile(workbook, fname); | ||||
| 
 | ||||
|   /* Read new file */ | ||||
|   var wb = XLSX.readFile(fname, {cellDates:true}); | ||||
| 
 | ||||
|   /* Display first worksheet */ | ||||
|   var f_sheet_name = wb.SheetNames[0], f_worksheet = wb.Sheets[f_sheet_name]; | ||||
|   var data = XLSX.utils.sheet_to_json(f_worksheet, {header:1, cellDates:true}); | ||||
|   alert(data); | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| @ -1,44 +0,0 @@ | ||||
| var thisFile = new File($.fileName); | ||||
| var basePath = thisFile.path; | ||||
| 
 | ||||
| #include "xlsx.extendscript.js"; | ||||
| 
 | ||||
| var filename = "/sheetjs.xlsx"; | ||||
| 
 | ||||
| /* Read file from disk */ | ||||
| var workbook = XLSX.readFile(basePath + filename, {cellDates:true}); | ||||
| 
 | ||||
| /* Display first worksheet */ | ||||
| var first_sheet_name = workbook.SheetNames[0], first_worksheet = workbook.Sheets[first_sheet_name]; | ||||
| var data = XLSX.utils.sheet_to_json(first_worksheet, {header:1}); | ||||
| alert(data); | ||||
| 
 | ||||
| var outfmts = [ | ||||
|   ["xlsb",  "testw.xlsb"], | ||||
|   ["biff8", "testw.xls"], | ||||
|   ["xlml",  "testw.xml"], | ||||
|   ["fods",  "testw.fods"], | ||||
|   ["csv",   "testw.csv"], | ||||
|   ["txt",   "testw.txt"], | ||||
|   ["slk",   "testw.slk"], | ||||
|   ["eth",   "testw.eth"], | ||||
|   ["htm",   "testw.htm"], | ||||
|   ["dif",   "testw.dif"], | ||||
|   ["ods",   "testw.ods"], | ||||
|   ["xlsx",  "testw.xlsx"] | ||||
| ]; | ||||
| for(var i = 0; i < outfmts.length; ++i) { | ||||
|   alert(outfmts[i][0]); | ||||
|   var fname = basePath + "/" + outfmts[i][1]; | ||||
| 
 | ||||
|   /* Write file to disk */ | ||||
|   XLSX.writeFile(workbook, fname); | ||||
| 
 | ||||
|   /* Read new file */ | ||||
|   var wb = XLSX.readFile(fname, {cellDates:true}); | ||||
| 
 | ||||
|   /* Display first worksheet */ | ||||
|   var f_sheet_name = wb.SheetNames[0], f_worksheet = wb.Sheets[f_sheet_name]; | ||||
|   var data = XLSX.utils.sheet_to_json(f_worksheet, {header:1, cellDates:true}); | ||||
|   alert(data); | ||||
| } | ||||
							
								
								
									
										38
									
								
								test.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										38
									
								
								test.js
									
									
									
									
									
								
							| @ -1483,6 +1483,27 @@ describe('write features', function() { | ||||
| 		assert.equal(X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet2"}), "5,6\n7,8"); | ||||
| 		assert.throws(function() { X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet3"}); }); | ||||
| 	}); | ||||
| 	it('should create/update autofilter defined name on write', function() {[ | ||||
| 		"xlsx", "xlsb", /* "xls", */ "xlml" /*, "ods" */ | ||||
| 	].forEach(function(fmt) { | ||||
| 		var wb = X.utils.book_new(); | ||||
| 		var ws = X.utils.aoa_to_sheet([["A","B","C"],[1,2,3]]); | ||||
| 		ws["!autofilter"] = { ref: ws["!ref"] }; | ||||
| 		X.utils.book_append_sheet(wb, ws, "Sheet1"); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		var Name = void 0; | ||||
| 		((wb2.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert(!!Name, "Could not find _xlnm._FilterDatabases name WR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$2"); | ||||
| 		X.utils.sheet_add_aoa(wb2.Sheets.Sheet1, [[4,5,6]], { origin: -1 }); | ||||
| 		wb2.Sheets.Sheet1["!autofilter"].ref = wb2.Sheets.Sheet1["!ref"]; | ||||
| 		var wb3 = X.read(X.write(wb2, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		Name = void 0; | ||||
| 		((wb3.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert(!!Name, "Could not find _xlnm._FilterDatabases name WRWR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$3"); | ||||
| 		assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length); | ||||
| 	}); }); | ||||
| }); | ||||
| 
 | ||||
| function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ { | ||||
| @ -1742,6 +1763,23 @@ describe('roundtrip features', function() { | ||||
| 			Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); }); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	it('should preserve autofilter settings', function() {[ | ||||
| 		['xlsx', paths.afxlsx], | ||||
| 		['xlsb', paths.afxlsb], | ||||
| 		// TODO:
 | ||||
| 		//['xls',  paths.afxls],
 | ||||
| 		['xlml', paths.afxml] | ||||
| 		//['ods',  paths.afods]
 | ||||
| 	].forEach(function(w) { | ||||
| 		var wb = X.read(fs.readFileSync(w[1]), {type:TYPE}); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:w[0], type: TYPE}), {type:TYPE}); | ||||
| 		assert(!wb2.Sheets[wb2.SheetNames[0]]['!autofilter']); | ||||
| 		for(var i = 1; i < wb2.SheetNames.length; ++i) { | ||||
| 			assert(wb2.Sheets[wb2.SheetNames[i]]['!autofilter']); | ||||
| 			assert.equal(wb2.Sheets[wb2.SheetNames[i]]['!autofilter'].ref,"A1:E22"); | ||||
| 		} | ||||
| 	});	}); | ||||
| }); | ||||
| 
 | ||||
| //function password_file(x){return x.match(/^password.*\.xls$/); }
 | ||||
|  | ||||
							
								
								
									
										40
									
								
								test.mjs
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										40
									
								
								test.mjs
									
									
									
										generated
									
									
									
								
							| @ -1473,6 +1473,27 @@ describe('write features', function() { | ||||
| 		assert.equal(X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet2"}), "5,6\n7,8"); | ||||
| 		assert.throws(function() { X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet3"}); }); | ||||
| 	}); | ||||
| 	it('should create/update autofilter defined name on write', function() {[ | ||||
| 		"xlsx", "xlsb", /* "xls", */ "xlml" /*, "ods" */ | ||||
| 	].forEach(function(fmt) { | ||||
| 		var wb = X.utils.book_new(); | ||||
| 		var ws = X.utils.aoa_to_sheet([["A","B","C"],[1,2,3]]); | ||||
| 		ws["!autofilter"] = { ref: ws["!ref"] }; | ||||
| 		X.utils.book_append_sheet(wb, ws, "Sheet1"); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		var Name = void 0; | ||||
| 		((wb2.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert.ok(!!Name, "Could not find _xlnm._FilterDatabases name WR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$2"); | ||||
| 		X.utils.sheet_add_aoa(wb2.Sheets.Sheet1, [[4,5,6]], { origin: -1 }); | ||||
| 		wb2.Sheets.Sheet1["!autofilter"].ref = wb2.Sheets.Sheet1["!ref"]; | ||||
| 		var wb3 = X.read(X.write(wb2, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		Name = void 0; | ||||
| 		((wb3.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert.ok(!!Name, "Could not find _xlnm._FilterDatabases name WRWR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$3"); | ||||
| 		assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length); | ||||
| 	}); }); | ||||
| }); | ||||
| 
 | ||||
| function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ { | ||||
| @ -1703,7 +1724,7 @@ describe('roundtrip features', function() { | ||||
| 	describe('should preserve cell comments', function() { [ | ||||
| 			['xlsx', paths.cstxlsx], | ||||
| 			['xlsb', paths.cstxlsb], | ||||
| 			//['xls', paths.cstxlsx],
 | ||||
| 			//['xls', paths.cstxls],
 | ||||
| 			['xlml', paths.cstxml] | ||||
| 			//['ods', paths.cstods]
 | ||||
| 	].forEach(function(w) { | ||||
| @ -1729,6 +1750,23 @@ describe('roundtrip features', function() { | ||||
| 			Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); }); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	it('should preserve autofilter settings', function() {[ | ||||
| 		['xlsx', paths.afxlsx], | ||||
| 		['xlsb', paths.afxlsb], | ||||
| 		// TODO:
 | ||||
| 		//['xls',  paths.afxls],
 | ||||
| 		['xlml', paths.afxml] | ||||
| 		//['ods',  paths.afods]
 | ||||
| 	].forEach(function(w) { | ||||
| 		var wb = X.read(fs.readFileSync(w[1]), {type:TYPE}); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:w[0], type: TYPE}), {type:TYPE}); | ||||
| 		assert.ok(!wb2.Sheets[wb2.SheetNames[0]]['!autofilter']); | ||||
| 		for(var i = 1; i < wb2.SheetNames.length; ++i) { | ||||
| 			assert.ok(wb2.Sheets[wb2.SheetNames[i]]['!autofilter']); | ||||
| 			assert.equal(wb2.Sheets[wb2.SheetNames[i]]['!autofilter'].ref,"A1:E22"); | ||||
| 		} | ||||
| 	});	}); | ||||
| }); | ||||
| 
 | ||||
| //function password_file(x){return x.match(/^password.*\.xls$/); }
 | ||||
|  | ||||
							
								
								
									
										38
									
								
								test.ts
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										38
									
								
								test.ts
									
									
									
									
									
								
							| @ -1433,6 +1433,27 @@ Deno.test('write features', async function(t) { | ||||
| 		assert.equal(X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet2"}), "5,6\n7,8"); | ||||
| 		assert.throws(function() { X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet3"}); }); | ||||
| 	}); | ||||
| 	await t.step('should create/update autofilter defined name on write', async function() {([ | ||||
| 		"xlsx", "xlsb", /* "xls", */ "xlml" /*, "ods" */ | ||||
| 	] as Array<X.BookType>).forEach(function(fmt) { | ||||
| 		var wb = X.utils.book_new(); | ||||
| 		var ws = X.utils.aoa_to_sheet([["A","B","C"],[1,2,3]]); | ||||
| 		ws["!autofilter"] = { ref: (ws["!ref"] as string) }; | ||||
| 		X.utils.book_append_sheet(wb, ws, "Sheet1"); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		var Name: X.DefinedName = (null as any); | ||||
| 		((wb2.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert.assert(!!Name, "Could not find _xlnm._FilterDatabases name WR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$2"); | ||||
| 		X.utils.sheet_add_aoa(wb2.Sheets.Sheet1, [[4,5,6]], { origin: -1 }); | ||||
| 		(wb2.Sheets.Sheet1["!autofilter"] as any).ref = wb2.Sheets.Sheet1["!ref"]; | ||||
| 		var wb3 = X.read(X.write(wb2, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		Name = (null as any); | ||||
| 		((wb3.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert.assert(!!Name, "Could not find _xlnm._FilterDatabases name WRWR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$3"); | ||||
| 		assert.equal(((wb2.Workbook as any).Names as any).length, ((wb3.Workbook as any).Names as any).length); | ||||
| 	}); }); | ||||
| }); | ||||
| 
 | ||||
| function seq(end: number, start?: number): Array<number> { | ||||
| @ -1689,6 +1710,23 @@ Deno.test('roundtrip features', async function(t) { | ||||
| 			Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); }); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	await t.step('should preserve autofilter settings', async function() {[ | ||||
| 		['xlsx', paths.afxlsx], | ||||
| 		['xlsb', paths.afxlsb], | ||||
| 		// TODO:
 | ||||
| 		//['xls',  paths.afxls],
 | ||||
| 		['xlml', paths.afxml] | ||||
| 		//['ods',  paths.afods]
 | ||||
| 	].forEach(function(w) { | ||||
| 		var wb = X.read(fs.readFileSync(w[1]), {type:TYPE}); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:w[0], type: TYPE}), {type:TYPE}); | ||||
| 		assert.assert(!wb2.Sheets[wb2.SheetNames[0]]['!autofilter']); | ||||
| 		for(var i = 1; i < wb2.SheetNames.length; ++i) { | ||||
| 			assert.assert(wb2.Sheets[wb2.SheetNames[i]]['!autofilter']); | ||||
| 			assert.equal((wb2.Sheets[wb2.SheetNames[i]]['!autofilter'] as any).ref,"A1:E22"); | ||||
| 		} | ||||
| 	});	}); | ||||
| }); | ||||
| 
 | ||||
| //function password_file(x){return x.match(/^password.*\.xls$/); }
 | ||||
|  | ||||
							
								
								
									
										40
									
								
								tests/core.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										40
									
								
								tests/core.js
									
									
									
										generated
									
									
									
								
							| @ -1483,6 +1483,27 @@ describe('write features', function() { | ||||
| 		assert.equal(X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet2"}), "5,6\n7,8"); | ||||
| 		assert.throws(function() { X.write(wb, {type:"string", bookType:"csv", sheet:"Sheet3"}); }); | ||||
| 	}); | ||||
| 	it('should create/update autofilter defined name on write', function() {[ | ||||
| 		"xlsx", "xlsb", /* "xls", */ "xlml" /*, "ods" */ | ||||
| 	].forEach(function(fmt) { | ||||
| 		var wb = X.utils.book_new(); | ||||
| 		var ws = X.utils.aoa_to_sheet([["A","B","C"],[1,2,3]]); | ||||
| 		ws["!autofilter"] = { ref: ws["!ref"] }; | ||||
| 		X.utils.book_append_sheet(wb, ws, "Sheet1"); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		var Name = void 0; | ||||
| 		((wb2.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert(!!Name, "Could not find _xlnm._FilterDatabases name WR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$2"); | ||||
| 		X.utils.sheet_add_aoa(wb2.Sheets.Sheet1, [[4,5,6]], { origin: -1 }); | ||||
| 		wb2.Sheets.Sheet1["!autofilter"].ref = wb2.Sheets.Sheet1["!ref"]; | ||||
| 		var wb3 = X.read(X.write(wb2, {bookType:fmt, type:TYPE}), {type:TYPE}); | ||||
| 		Name = void 0; | ||||
| 		((wb3.Workbook||{}).Names || []).forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == 0) Name = dn; }); | ||||
| 		assert(!!Name, "Could not find _xlnm._FilterDatabases name WRWR"); | ||||
| 		assert.equal(Name.Ref, "Sheet1!$A$1:$C$3"); | ||||
| 		assert.equal(wb2.Workbook.Names.length, wb3.Workbook.Names.length); | ||||
| 	}); }); | ||||
| }); | ||||
| 
 | ||||
| function seq(end/*:number*/, start/*:?number*/)/*:Array<number>*/ { | ||||
| @ -1716,7 +1737,7 @@ describe('roundtrip features', function() { | ||||
| 	describe('should preserve cell comments', function() { [ | ||||
| 			['xlsx', paths.cstxlsx], | ||||
| 			['xlsb', paths.cstxlsb], | ||||
| 			//['xls', paths.cstxlsx],
 | ||||
| 			//['xls', paths.cstxls],
 | ||||
| 			['xlml', paths.cstxml] | ||||
| 			//['ods', paths.cstods]
 | ||||
| 	].forEach(function(w) { | ||||
| @ -1742,6 +1763,23 @@ describe('roundtrip features', function() { | ||||
| 			Object.keys(row).forEach(function(k) { assert.equal(row[k], o[i][k]); }); | ||||
| 		}); | ||||
| 	}); | ||||
| 
 | ||||
| 	it('should preserve autofilter settings', function() {[ | ||||
| 		['xlsx', paths.afxlsx], | ||||
| 		['xlsb', paths.afxlsb], | ||||
| 		// TODO:
 | ||||
| 		//['xls',  paths.afxls],
 | ||||
| 		['xlml', paths.afxml] | ||||
| 		//['ods',  paths.afods]
 | ||||
| 	].forEach(function(w) { | ||||
| 		var wb = X.read(fs.readFileSync(w[1]), {type:TYPE}); | ||||
| 		var wb2 = X.read(X.write(wb, {bookType:w[0], type: TYPE}), {type:TYPE}); | ||||
| 		assert(!wb2.Sheets[wb2.SheetNames[0]]['!autofilter']); | ||||
| 		for(var i = 1; i < wb2.SheetNames.length; ++i) { | ||||
| 			assert(wb2.Sheets[wb2.SheetNames[i]]['!autofilter']); | ||||
| 			assert.equal(wb2.Sheets[wb2.SheetNames[i]]['!autofilter'].ref,"A1:E22"); | ||||
| 		} | ||||
| 	});	}); | ||||
| }); | ||||
| 
 | ||||
| //function password_file(x){return x.match(/^password.*\.xls$/); }
 | ||||
|  | ||||
							
								
								
									
										81
									
								
								xlsx.flow.js
									
									
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										81
									
								
								xlsx.flow.js
									
									
									
									
									
								
							| @ -4259,6 +4259,17 @@ function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ | ||||
| /*:: if(typeof ce !== 'string') throw "unreachable"; */ | ||||
| 	return cs == ce ? cs : cs + ":" + ce; | ||||
| } | ||||
| function fix_range(a1/*:string*/)/*:string*/ { | ||||
| 	var s = decode_range(a1); | ||||
| 	return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r); | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| 
 | ||||
| function safe_decode_range(range/*:string*/)/*:Range*/ { | ||||
| 	var o = {s:{c:0,r:0},e:{c:0,r:0}}; | ||||
| @ -4999,6 +5010,23 @@ var RBErr = { | ||||
| 	"#WTF?":         0xFF | ||||
| }; | ||||
| 
 | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| 
 | ||||
| /* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */ | ||||
| /* 12.3 Part Summary <SpreadsheetML> */ | ||||
| /* 14.2 Part Summary <DrawingML> */ | ||||
| @ -7143,22 +7171,6 @@ function parse_ExternName(blob, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.150 TODO */ | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| function parse_Lbl(blob, length, opts) { | ||||
| 	var target = blob.l + length; | ||||
| 	var flags = blob.read_shift(2); | ||||
| @ -12417,8 +12429,8 @@ var a1_to_rc = /*#__PURE__*/(function(){ | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) { | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			var R = $4 == "$" ? (r+1) : (r == 0 ? "" : "[" + r + "]"); | ||||
| 			var C = $2 == "$" ? (c+1) : (c == 0 ? "" : "[" + c + "]"); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| @ -13145,12 +13157,6 @@ function make_3d_range(start, end) { | ||||
| 	return start + ":" + end; | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ { | ||||
| 	if(!supbooks) return "SH33TJSERR0"; | ||||
| 	if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti]; | ||||
| @ -15346,7 +15352,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	return writextag("autoFilter", null, {ref:ref}); | ||||
| @ -16711,9 +16717,9 @@ function write_AUTOFILTER(ba, ws, wb, idx) { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref)  }); | ||||
| 
 | ||||
| 	write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref))); | ||||
| 	/* *FILTERCOLUMN */ | ||||
| @ -17092,6 +17098,17 @@ function check_wb(wb) { | ||||
| 	var Sheets = (wb.Workbook && wb.Workbook.Sheets) || []; | ||||
| 	check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i); | ||||
| 	wb.SheetNames.forEach(function(n, i) { | ||||
| 		var ws = wb.Sheets[n]; | ||||
| 		if(!ws || !ws["!autofilter"]) return; | ||||
| 		var DN; | ||||
| 		if(!wb.Workbook) wb.Workbook = {}; | ||||
| 		if(!wb.Workbook.Names) wb.Workbook.Names = []; | ||||
| 		wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; }); | ||||
| 		var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref); | ||||
| 		if(DN) DN.Ref = nn; | ||||
| 		else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn}); | ||||
| 	}); | ||||
| 	/* TODO: validate workbook */ | ||||
| } | ||||
| /* 18.2 Workbook */ | ||||
| @ -17911,6 +17928,10 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 	if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID; | ||||
| } | ||||
| 
 | ||||
| function xlml_prefix_dname(dname) { | ||||
| 	return XLSLblBuiltIn.indexOf("_xlnm." + dname) > -1 ? "_xlnm." + dname : dname; | ||||
| } | ||||
| 
 | ||||
| function xlml_clean_comment(comment/*:any*/) { | ||||
| 	comment.t = comment.v || ""; | ||||
| 	comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"); | ||||
| @ -18118,7 +18139,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			if(!Workbook.Names) Workbook.Names = []; | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName/*:DefinedName*/ = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Name: xlml_prefix_dname(_NamedRange.Name), | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) | ||||
| 			}/*:any*/); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| @ -18708,7 +18729,7 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name.slice(0,6) == "_xlnm." ? n.Name.slice(6) : n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb/*::, opts*/)/*:string*/ { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| @ -18961,6 +18982,8 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	/* WorksheetOptions */ | ||||
| 	o.push(write_ws_xlml_wsopts(ws, opts, idx, wb)); | ||||
| 
 | ||||
| 	if(ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 
 | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_xlml(wb, opts)/*:string*/ { | ||||
|  | ||||
							
								
								
									
										81
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										81
									
								
								xlsx.js
									
									
									
										generated
									
									
									
								
							| @ -4174,6 +4174,17 @@ if(typeof cs !== 'string') cs = encode_cell((cs)); | ||||
| 	if(typeof ce !== 'string') ce = encode_cell((ce)); | ||||
| return cs == ce ? cs : cs + ":" + ce; | ||||
| } | ||||
| function fix_range(a1) { | ||||
| 	var s = decode_range(a1); | ||||
| 	return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r); | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname, opts) { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| 
 | ||||
| function safe_decode_range(range) { | ||||
| 	var o = {s:{c:0,r:0},e:{c:0,r:0}}; | ||||
| @ -4914,6 +4925,23 @@ var RBErr = { | ||||
| 	"#WTF?":         0xFF | ||||
| }; | ||||
| 
 | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| 
 | ||||
| /* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */ | ||||
| /* 12.3 Part Summary <SpreadsheetML> */ | ||||
| /* 14.2 Part Summary <DrawingML> */ | ||||
| @ -7054,22 +7082,6 @@ function parse_ExternName(blob, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.150 TODO */ | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| function parse_Lbl(blob, length, opts) { | ||||
| 	var target = blob.l + length; | ||||
| 	var flags = blob.read_shift(2); | ||||
| @ -12324,8 +12336,8 @@ var a1_to_rc = (function(){ | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) { | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			var R = $4 == "$" ? (r+1) : (r == 0 ? "" : "[" + r + "]"); | ||||
| 			var C = $2 == "$" ? (c+1) : (c == 0 ? "" : "[" + c + "]"); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| @ -13051,12 +13063,6 @@ function make_3d_range(start, end) { | ||||
| 	return start + ":" + end; | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname, opts) { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| function get_ixti_raw(supbooks, ixti, opts) { | ||||
| 	if(!supbooks) return "SH33TJSERR0"; | ||||
| 	if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti]; | ||||
| @ -15252,7 +15258,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx) { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	return writextag("autoFilter", null, {ref:ref}); | ||||
| @ -16616,9 +16622,9 @@ function write_AUTOFILTER(ba, ws, wb, idx) { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref)  }); | ||||
| 
 | ||||
| 	write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref))); | ||||
| 	/* *FILTERCOLUMN */ | ||||
| @ -16997,6 +17003,17 @@ function check_wb(wb) { | ||||
| 	var Sheets = (wb.Workbook && wb.Workbook.Sheets) || []; | ||||
| 	check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i); | ||||
| 	wb.SheetNames.forEach(function(n, i) { | ||||
| 		var ws = wb.Sheets[n]; | ||||
| 		if(!ws || !ws["!autofilter"]) return; | ||||
| 		var DN; | ||||
| 		if(!wb.Workbook) wb.Workbook = {}; | ||||
| 		if(!wb.Workbook.Names) wb.Workbook.Names = []; | ||||
| 		wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; }); | ||||
| 		var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref); | ||||
| 		if(DN) DN.Ref = nn; | ||||
| 		else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn}); | ||||
| 	}); | ||||
| 	/* TODO: validate workbook */ | ||||
| } | ||||
| /* 18.2 Workbook */ | ||||
| @ -17812,6 +17829,10 @@ function parse_xlml_data(xml, ss, data, cell, base, styles, csty, row, arrayf, o | ||||
| 	if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID; | ||||
| } | ||||
| 
 | ||||
| function xlml_prefix_dname(dname) { | ||||
| 	return XLSLblBuiltIn.indexOf("_xlnm." + dname) > -1 ? "_xlnm." + dname : dname; | ||||
| } | ||||
| 
 | ||||
| function xlml_clean_comment(comment) { | ||||
| 	comment.t = comment.v || ""; | ||||
| 	comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"); | ||||
| @ -18018,7 +18039,7 @@ for(var cma = c; cma <= cc; ++cma) { | ||||
| 			if(!Workbook.Names) Workbook.Names = []; | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Name: xlml_prefix_dname(_NamedRange.Name), | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) | ||||
| 			}); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| @ -18606,7 +18627,7 @@ function write_sty_xlml(wb, opts) { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name.slice(0,6) == "_xlnm." ? n.Name.slice(6) : n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb) { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| var names = wb.Workbook.Names; | ||||
| @ -18857,6 +18878,8 @@ function write_ws_xlml(idx, opts, wb) { | ||||
| 	/* WorksheetOptions */ | ||||
| 	o.push(write_ws_xlml_wsopts(ws, opts, idx, wb)); | ||||
| 
 | ||||
| 	if(ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 
 | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_xlml(wb, opts) { | ||||
|  | ||||
							
								
								
									
										238
									
								
								xlsx.mjs
									
									
									
										generated
									
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										238
									
								
								xlsx.mjs
									
									
									
										generated
									
									
									
								
							| @ -4254,6 +4254,17 @@ function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ | ||||
| /*:: if(typeof ce !== 'string') throw "unreachable"; */ | ||||
| 	return cs == ce ? cs : cs + ":" + ce; | ||||
| } | ||||
| function fix_range(a1/*:string*/)/*:string*/ { | ||||
| 	var s = decode_range(a1); | ||||
| 	return "$" + encode_col(s.s.c) + "$" + encode_row(s.s.r) + ":$" + encode_col(s.e.c) + "$" + encode_row(s.e.r); | ||||
| } | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname.replace(/'/g, "''") + "'"; | ||||
| 	return sname; | ||||
| } | ||||
| 
 | ||||
| function safe_decode_range(range/*:string*/)/*:Range*/ { | ||||
| 	var o = {s:{c:0,r:0},e:{c:0,r:0}}; | ||||
| @ -4994,6 +5005,23 @@ var RBErr = { | ||||
| 	"#WTF?":         0xFF | ||||
| }; | ||||
| 
 | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| 
 | ||||
| /* Parts enumerated in OPC spec, MS-XLSB and MS-XLSX */ | ||||
| /* 12.3 Part Summary <SpreadsheetML> */ | ||||
| /* 14.2 Part Summary <DrawingML> */ | ||||
| @ -7138,22 +7166,6 @@ function parse_ExternName(blob, length, opts) { | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLS] 2.4.150 TODO */ | ||||
| var XLSLblBuiltIn = [ | ||||
| 	"_xlnm.Consolidate_Area", | ||||
| 	"_xlnm.Auto_Open", | ||||
| 	"_xlnm.Auto_Close", | ||||
| 	"_xlnm.Extract", | ||||
| 	"_xlnm.Database", | ||||
| 	"_xlnm.Criteria", | ||||
| 	"_xlnm.Print_Area", | ||||
| 	"_xlnm.Print_Titles", | ||||
| 	"_xlnm.Recorder", | ||||
| 	"_xlnm.Data_Form", | ||||
| 	"_xlnm.Auto_Activate", | ||||
| 	"_xlnm.Auto_Deactivate", | ||||
| 	"_xlnm.Sheet_Title", | ||||
| 	"_xlnm._FilterDatabase" | ||||
| ]; | ||||
| function parse_Lbl(blob, length, opts) { | ||||
| 	var target = blob.l + length; | ||||
| 	var flags = blob.read_shift(2); | ||||
| @ -12412,8 +12424,8 @@ var a1_to_rc = /*#__PURE__*/(function(){ | ||||
| 		return fstr.replace(crefregex, function($0, $1, $2, $3, $4, $5) { | ||||
| 			var c = decode_col($3) - ($2 ? 0 : base.c); | ||||
| 			var r = decode_row($5) - ($4 ? 0 : base.r); | ||||
| 			var R = (r == 0 ? "" : !$4 ? "[" + r + "]" : (r+1)); | ||||
| 			var C = (c == 0 ? "" : !$2 ? "[" + c + "]" : (c+1)); | ||||
| 			var R = $4 == "$" ? (r+1) : (r == 0 ? "" : "[" + r + "]"); | ||||
| 			var C = $2 == "$" ? (c+1) : (c == 0 ? "" : "[" + c + "]"); | ||||
| 			return $1 + "R" + R + "C" + C; | ||||
| 		}); | ||||
| 	}; | ||||
| @ -13131,12 +13143,15 @@ var PtgBinOp = { | ||||
| 	PtgSub: "-" | ||||
| }; | ||||
| 
 | ||||
| // List of invalid characters needs to be tested further
 | ||||
| function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ { | ||||
| 	if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name"); | ||||
| 	if (/[^\w\u4E00-\u9FFF\u3040-\u30FF]/.test(sname)) return "'" + sname + "'"; | ||||
| 	return sname; | ||||
| // TODO: explore space
 | ||||
| function make_3d_range(start, end) { | ||||
| 	var s = start.lastIndexOf("!"), e = end.lastIndexOf("!"); | ||||
| 	if(s == -1 && e == -1) return start + ":" + end; | ||||
| 	if(s > 0 && e > 0 && start.slice(0, s).toLowerCase() == end.slice(0, e).toLowerCase()) return start + ":" + end.slice(e+1); | ||||
| 	console.error("Cannot hydrate range", start, end); | ||||
| 	return start + ":" + end; | ||||
| } | ||||
| 
 | ||||
| function get_ixti_raw(supbooks, ixti/*:number*/, opts)/*:string*/ { | ||||
| 	if(!supbooks) return "SH33TJSERR0"; | ||||
| 	if(opts.biff > 8 && (!supbooks.XTI || !supbooks.XTI[ixti])) return supbooks.SheetNames[ixti]; | ||||
| @ -13233,7 +13248,7 @@ function stringify_formula(formula/*Array<any>*/, range, cell/*:any*/, supbooks, | ||||
| 				break; | ||||
| 			case 'PtgRange': /* [MS-XLS] 2.5.198.83 */ | ||||
| 				e1 = stack.pop(); e2 = stack.pop(); | ||||
| 				stack.push(e2+":"+e1); | ||||
| 				stack.push(make_3d_range(e2,e1)); | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'PtgAttrChoose': /* [MS-XLS] 2.5.198.34 */ | ||||
| @ -13679,7 +13694,7 @@ function write_XLSBFormulaRef3D(str, wb) { | ||||
| 	var out = new_buf(17); | ||||
| 	out.write_shift(4, 9); | ||||
| 	out.write_shift(1, 0x1A | ((1)<<5)); | ||||
| 	out.write_shift(2, 1 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase())); | ||||
| 	out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase())); | ||||
| 	out.write_shift(4, cell.r); | ||||
| 	out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
 | ||||
| 	out.write_shift(4, 0); | ||||
| @ -13687,13 +13702,121 @@ function write_XLSBFormulaRef3D(str, wb) { | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* Writes a PtgRefErr3d */ | ||||
| function write_XLSBFormulaRefErr3D(str, wb) { | ||||
| 	var lastbang = str.lastIndexOf("!"); | ||||
| 	var sname = str.slice(0, lastbang); | ||||
| 	str = str.slice(lastbang+1); | ||||
| 	if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'"); | ||||
| 
 | ||||
| 	var out = new_buf(17); | ||||
| 	out.write_shift(4, 9); | ||||
| 	out.write_shift(1, 0x1C | ((1)<<5)); | ||||
| 	out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase())); | ||||
| 	out.write_shift(4, 0); | ||||
| 	out.write_shift(2, 0); // <== ColRelShort
 | ||||
| 	out.write_shift(4, 0); | ||||
| 
 | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* Writes a single sheet range [PtgRef PtgRef PtgRange] */ | ||||
| function write_XLSBFormulaRange(_str) { | ||||
| 	var parts = _str.split(":"), str = parts[0]; | ||||
| 
 | ||||
| 	var out = new_buf(23); | ||||
| 	out.write_shift(4, 15); | ||||
| 
 | ||||
| 	/* start cell */ | ||||
| 	str = parts[0]; var cell = decode_cell(str); | ||||
| 	out.write_shift(1, 0x04 | ((1)<<5)); | ||||
| 	out.write_shift(4, cell.r); | ||||
| 	out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
 | ||||
| 	out.write_shift(4, 0); | ||||
| 
 | ||||
| 	/* end cell */ | ||||
| 	str = parts[1]; cell = decode_cell(str); | ||||
| 	out.write_shift(1, 0x04 | ((1)<<5)); | ||||
| 	out.write_shift(4, cell.r); | ||||
| 	out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
 | ||||
| 	out.write_shift(4, 0); | ||||
| 
 | ||||
| 	/* PtgRange */ | ||||
| 	out.write_shift(1, 0x11); | ||||
| 
 | ||||
| 	out.write_shift(4, 0); | ||||
| 
 | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* Writes a range with explicit sheet name [PtgRef3D PtgRef3D PtgRange] */ | ||||
| function write_XLSBFormulaRangeWS(_str, wb) { | ||||
| 	var lastbang = _str.lastIndexOf("!"); | ||||
| 	var sname = _str.slice(0, lastbang); | ||||
| 	_str = _str.slice(lastbang+1); | ||||
| 	if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'"); | ||||
| 	var parts = _str.split(":"); str = parts[0]; | ||||
| 
 | ||||
| 	var out = new_buf(27); | ||||
| 	out.write_shift(4, 19); | ||||
| 
 | ||||
| 	/* start cell */ | ||||
| 	var str = parts[0], cell = decode_cell(str); | ||||
| 	out.write_shift(1, 0x1A | ((1)<<5)); | ||||
| 	out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase())); | ||||
| 	out.write_shift(4, cell.r); | ||||
| 	out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
 | ||||
| 
 | ||||
| 	/* end cell */ | ||||
| 	str = parts[1]; cell = decode_cell(str); | ||||
| 	out.write_shift(1, 0x1A | ((1)<<5)); | ||||
| 	out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase())); | ||||
| 	out.write_shift(4, cell.r); | ||||
| 	out.write_shift(2, cell.c | ((str.charAt(0) == "$" ? 0 : 1)<<14) | ((str.match(/\$\d/) ? 0 : 1)<<15)); // <== ColRelShort
 | ||||
| 
 | ||||
| 	/* PtgRange */ | ||||
| 	out.write_shift(1, 0x11); | ||||
| 
 | ||||
| 	out.write_shift(4, 0); | ||||
| 
 | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| /* Writes a range with explicit sheet name [PtgArea3d] */ | ||||
| function write_XLSBFormulaArea3D(_str, wb) { | ||||
| 	var lastbang = _str.lastIndexOf("!"); | ||||
| 	var sname = _str.slice(0, lastbang); | ||||
| 	_str = _str.slice(lastbang+1); | ||||
| 	if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'"); | ||||
| 	var range = decode_range(_str); | ||||
| 
 | ||||
| 	var out = new_buf(23); | ||||
| 	out.write_shift(4, 15); | ||||
| 
 | ||||
| 	out.write_shift(1, 0x1B | ((1)<<5)); | ||||
| 	out.write_shift(2, 2 + wb.SheetNames.map(function(n) { return n.toLowerCase(); }).indexOf(sname.toLowerCase())); | ||||
| 	out.write_shift(4, range.s.r); | ||||
| 	out.write_shift(4, range.e.r); | ||||
| 	out.write_shift(2, range.s.c); | ||||
| 	out.write_shift(2, range.e.c); | ||||
| 
 | ||||
| 	out.write_shift(4, 0); | ||||
| 
 | ||||
| 	return out; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* General Formula */ | ||||
| function write_XLSBFormula(val/*:string*/, wb) { | ||||
| 	if(/^#(DIV\/0!|GETTING_DATA|N\/A|NAME\?|NULL!|NUM!|REF!|VALUE!)$/.test(val)) return write_XLSBFormulaErr(+RBErr[val]); | ||||
| 	if(val.match(/^\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef(val); | ||||
| 	if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-_=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef3D(val, wb); | ||||
| 	if(val.match(/^".*"$/)) return write_XLSBFormulaStr(val); | ||||
| 	if(val.match(/^\d+$/)) return write_XLSBFormulaNum(parseInt(val, 10)); | ||||
| 	if(val.match(/^\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRange(val); | ||||
| 	if(val.match(/^#REF!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaArea3D(val, wb); | ||||
| 	if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRef3D(val, wb); | ||||
| 	if(val.match(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5}):\$?(?:[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D]|[A-Z]{1,2})\$?(?:10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})$/)) return write_XLSBFormulaRangeWS(val, wb); | ||||
| 	if(/^(?:'[^\\\/?*\[\]:]*'|[^'][^\\\/?*\[\]:'`~!@#$%^()\-=+{}|;,<.>]*)!#REF!$/.test(val)) return write_XLSBFormulaRefErr3D(val, wb); | ||||
| 	if(/^".*"$/.test(val)) return write_XLSBFormulaStr(val); | ||||
| 	if(/^[+-]\d+$/.test(val)) return write_XLSBFormulaNum(parseInt(val, 10)); | ||||
| 	throw "Formula |" + val + "| not supported for XLSB"; | ||||
| } | ||||
| var write_XLSBNameParsedFormula = write_XLSBFormula; | ||||
| @ -14841,6 +14964,8 @@ function ods_to_csf_formula(f/*:string*/)/*:string*/ { | ||||
| 	f = f.replace(/COM\.MICROSOFT\./g, ""); | ||||
| 	/* Part 3 Section 5.8 References */ | ||||
| 	f = f.replace(/\[((?:\.[A-Z]+[0-9]+)(?::\.[A-Z]+[0-9]+)?)\]/g, function($$, $1) { return $1.replace(/\./g,""); }); | ||||
| 	f = f.replace(/\$'([^']|'')+'/g, function($$) { return $$.slice(1); }); | ||||
| 	f = f.replace(/\$([^\]\. #$]+)/g, function($$, $1) { return ($1).match(/^([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])?(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})?$/) ? $$ : $1; }); | ||||
| 	/* TODO: something other than this */ | ||||
| 	f = f.replace(/\[.(#[A-Z]*[?!])\]/g, "$1"); | ||||
| 	return f.replace(/[;~]/g,",").replace(/\|/g,";"); | ||||
| @ -14853,6 +14978,8 @@ function csf_to_ods_formula(f/*:string*/)/*:string*/ { | ||||
| } | ||||
| 
 | ||||
| function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ { | ||||
| 	r = r.replace(/\$'([^']|'')+'/g, function($$) { return $$.slice(1); }); | ||||
| 	r = r.replace(/\$([^\]\. #$]+)/g, function($$, $1) { return ($1).match(/^([A-Z]{1,2}|[A-W][A-Z]{2}|X[A-E][A-Z]|XF[A-D])?(10[0-3]\d{4}|104[0-7]\d{3}|1048[0-4]\d{2}|10485[0-6]\d|104857[0-6]|[1-9]\d{0,5})?$/) ? $$ : $1; }); | ||||
| 	var a = r.split(":"); | ||||
| 	var s = a[0].split(".")[0]; | ||||
| 	return [s, a[0].split(".")[1] + (a.length > 1 ? (":" + (a[1].split(".")[1] || a[1].split(".")[0])) : "")]; | ||||
| @ -15220,7 +15347,7 @@ function write_ws_xml_autofilter(data, ws, wb, idx)/*:string*/ { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	return writextag("autoFilter", null, {ref:ref}); | ||||
| @ -16585,9 +16712,9 @@ function write_AUTOFILTER(ba, ws, wb, idx) { | ||||
| 		var name = names[i]; | ||||
| 		if(name.Name != '_xlnm._FilterDatabase') continue; | ||||
| 		if(name.Sheet != idx) continue; | ||||
| 		name.Ref = "'" + wb.SheetNames[idx] + "'!" + ref; break; | ||||
| 		name.Ref = formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref); break; | ||||
| 	} | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: "'" + wb.SheetNames[idx] + "'!" + ref  }); | ||||
| 	if(i == names.length) names.push({ Name: '_xlnm._FilterDatabase', Sheet: idx, Ref: formula_quote_sheet_name(wb.SheetNames[idx]) + "!" + fix_range(ref)  }); | ||||
| 
 | ||||
| 	write_record(ba, 0x00A1 /* BrtBeginAFilter */, write_UncheckedRfX(safe_decode_range(ref))); | ||||
| 	/* *FILTERCOLUMN */ | ||||
| @ -16966,6 +17093,17 @@ function check_wb(wb) { | ||||
| 	var Sheets = (wb.Workbook && wb.Workbook.Sheets) || []; | ||||
| 	check_wb_names(wb.SheetNames, Sheets, !!wb.vbaraw); | ||||
| 	for(var i = 0; i < wb.SheetNames.length; ++i) check_ws(wb.Sheets[wb.SheetNames[i]], wb.SheetNames[i], i); | ||||
| 	wb.SheetNames.forEach(function(n, i) { | ||||
| 		var ws = wb.Sheets[n]; | ||||
| 		if(!ws || !ws["!autofilter"]) return; | ||||
| 		var DN; | ||||
| 		if(!wb.Workbook) wb.Workbook = {}; | ||||
| 		if(!wb.Workbook.Names) wb.Workbook.Names = []; | ||||
| 		wb.Workbook.Names.forEach(function(dn) { if(dn.Name == "_xlnm._FilterDatabase" && dn.Sheet == i) DN = dn; }); | ||||
| 		var nn = formula_quote_sheet_name(n) + "!" + fix_range(ws["!autofilter"].ref); | ||||
| 		if(DN) DN.Ref = nn; | ||||
| 		else wb.Workbook.Names.push({Name: "_xlnm._FilterDatabase", Sheet: i, Ref: nn}); | ||||
| 	}); | ||||
| 	/* TODO: validate workbook */ | ||||
| } | ||||
| /* 18.2 Workbook */ | ||||
| @ -17281,12 +17419,13 @@ function parse_BrtFRTArchID$(data, length) { | ||||
| /* [MS-XLSB] 2.4.687 BrtName */ | ||||
| function parse_BrtName(data, length, opts) { | ||||
| 	var end = data.l + length; | ||||
| 	data.l += 4; //var flags = data.read_shift(4);
 | ||||
| 	var flags = data.read_shift(4); | ||||
| 	data.l += 1; //var chKey = data.read_shift(1);
 | ||||
| 	var itab = data.read_shift(4); | ||||
| 	var name = parse_XLNameWideString(data); | ||||
| 	var formula = parse_XLSBNameParsedFormula(data, 0, opts); | ||||
| 	var comment = parse_XLNullableWideString(data); | ||||
| 	if(flags & 0x20) name = "_xlnm." + name; | ||||
| 	//if(0 /* fProc */) {
 | ||||
| 		// unusedstring1: XLNullableWideString
 | ||||
| 		// description: XLNullableWideString
 | ||||
| @ -17294,23 +17433,26 @@ function parse_BrtName(data, length, opts) { | ||||
| 		// unusedstring2: XLNullableWideString
 | ||||
| 	//}
 | ||||
| 	data.l = end; | ||||
| 	var out = ({Name:name, Ptg:formula}/*:any*/); | ||||
| 	var out = ({Name:name, Ptg:formula, Flags: flags}/*:any*/); | ||||
| 	if(itab < 0xFFFFFFF) out.Sheet = itab; | ||||
| 	if(comment) out.Comment = comment; | ||||
| 	return out; | ||||
| } | ||||
| function write_BrtName(name, wb) { | ||||
| 	var o = new_buf(9); | ||||
| 	o.write_shift(4, 0); // flags
 | ||||
| 	var flags = 0; | ||||
| 	var dname = name.Name; | ||||
| 	if(XLSLblBuiltIn.indexOf(dname) > -1) { flags |= 0x20; dname = dname.slice(6); } | ||||
| 	o.write_shift(4, flags); // flags
 | ||||
| 	o.write_shift(1, 0); // chKey
 | ||||
| 	o.write_shift(4, name.Sheet == null ? 0xFFFFFFFF : name.Sheet); | ||||
| 
 | ||||
| 	var arr = [ | ||||
| 		o, | ||||
| 		write_XLWideString(name.Name), | ||||
| 		write_XLSBNameParsedFormula(name.Ref, wb), | ||||
| 		write_XLWideString(dname), | ||||
| 		write_XLSBNameParsedFormula(name.Ref, wb) | ||||
| 	]; | ||||
| 	if(name.Comment) arr.push(write_XLNullableWideString(name.Comment)) | ||||
| 	if(name.Comment) arr.push(write_XLNullableWideString(name.Comment)); | ||||
| 	else { | ||||
| 		var x = new_buf(4); | ||||
| 		x.write_shift(4, 0xFFFFFFFF); | ||||
| @ -17323,7 +17465,7 @@ function write_BrtName(name, wb) { | ||||
| 	// write_XLNullableWideString(helpTopic)
 | ||||
| 	// write_shift(4, 0xFFFFFFFF);
 | ||||
| 
 | ||||
| 	return bconcat(arr);  | ||||
| 	return bconcat(arr); | ||||
| } | ||||
| 
 | ||||
| /* [MS-XLSB] 2.1.7.61 Workbook */ | ||||
| @ -17492,6 +17634,7 @@ function write_BOOKVIEWS(ba, wb/*::, opts*/) { | ||||
| function write_BRTNAMES(ba, wb) { | ||||
| 	if(!wb.Workbook || !wb.Workbook.Names) return; | ||||
| 	wb.Workbook.Names.forEach(function(name) { try { | ||||
| 		if(name.Flags & 0x0e) return; // TODO: macro name write
 | ||||
| 		write_record(ba, 0x0027 /* BrtName */, write_BrtName(name, wb)); | ||||
| 	} catch(e) { | ||||
| 		console.error("Could not serialize defined name " + JSON.stringify(name)); | ||||
| @ -17500,9 +17643,10 @@ function write_BRTNAMES(ba, wb) { | ||||
| 
 | ||||
| function write_SELF_EXTERNS_xlsb(wb) { | ||||
| 	var L = wb.SheetNames.length; | ||||
| 	var o = new_buf(12 * L + 16); | ||||
| 	o.write_shift(4, L + 1); | ||||
| 	var o = new_buf(12 * L + 28); | ||||
| 	o.write_shift(4, L + 2); | ||||
| 	o.write_shift(4, 0); o.write_shift(4, -2); o.write_shift(4, -2); // workbook-level reference
 | ||||
| 	o.write_shift(4, 0); o.write_shift(4, -1); o.write_shift(4, -1); // #REF!...
 | ||||
| 	for(var i = 0; i < L; ++i) { | ||||
| 		o.write_shift(4, 0); o.write_shift(4, i); o.write_shift(4, i); | ||||
| 	} | ||||
| @ -17779,6 +17923,10 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a | ||||
| 	if(cell.StyleID !== undefined) cell.ixfe = cell.StyleID; | ||||
| } | ||||
| 
 | ||||
| function xlml_prefix_dname(dname) { | ||||
| 	return XLSLblBuiltIn.indexOf("_xlnm." + dname) > -1 ? "_xlnm." + dname : dname; | ||||
| } | ||||
| 
 | ||||
| function xlml_clean_comment(comment/*:any*/) { | ||||
| 	comment.t = comment.v || ""; | ||||
| 	comment.t = comment.t.replace(/\r\n/g,"\n").replace(/\r/g,"\n"); | ||||
| @ -17986,7 +18134,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ { | ||||
| 			if(!Workbook.Names) Workbook.Names = []; | ||||
| 			var _NamedRange = parsexmltag(Rn[0]); | ||||
| 			var _DefinedName/*:DefinedName*/ = ({ | ||||
| 				Name: _NamedRange.Name, | ||||
| 				Name: xlml_prefix_dname(_NamedRange.Name), | ||||
| 				Ref: rc_to_a1(_NamedRange.RefersTo.slice(1), {r:0, c:0}) | ||||
| 			}/*:any*/); | ||||
| 			if(Workbook.Sheets.length>0) _DefinedName.Sheet=Workbook.Sheets.length-1; | ||||
| @ -18576,7 +18724,7 @@ function write_sty_xlml(wb, opts)/*:string*/ { | ||||
| 	}); | ||||
| 	return writextag("Styles", styles.join("")); | ||||
| } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_name_xlml(n) { return writextag("NamedRange", null, {"ss:Name": n.Name.slice(0,6) == "_xlnm." ? n.Name.slice(6) : n.Name, "ss:RefersTo":"=" + a1_to_rc(n.Ref, {r:0,c:0})}); } | ||||
| function write_names_xlml(wb/*::, opts*/)/*:string*/ { | ||||
| 	if(!((wb||{}).Workbook||{}).Names) return ""; | ||||
| 	/*:: if(!wb || !wb.Workbook || !wb.Workbook.Names) throw new Error("unreachable"); */ | ||||
| @ -18829,6 +18977,8 @@ function write_ws_xlml(idx/*:number*/, opts, wb/*:Workbook*/)/*:string*/ { | ||||
| 	/* WorksheetOptions */ | ||||
| 	o.push(write_ws_xlml_wsopts(ws, opts, idx, wb)); | ||||
| 
 | ||||
| 	if(ws["!autofilter"]) o.push('<AutoFilter x:Range="' + a1_to_rc(fix_range(ws["!autofilter"].ref), {r:0,c:0}) + '" xmlns="urn:schemas-microsoft-com:office:excel"></AutoFilter>'); | ||||
| 
 | ||||
| 	return o.join(""); | ||||
| } | ||||
| function write_xlml(wb, opts)/*:string*/ { | ||||
| @ -21164,6 +21314,7 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 	/* ... */ | ||||
| 
 | ||||
| 	if(b8) ws['!links'] = []; | ||||
| 	var comments = []; | ||||
| 	for(var R = range.s.r; R <= range.e.r; ++R) { | ||||
| 		rr = encode_row(R); | ||||
| 		for(var C = range.s.c; C <= range.e.c; ++C) { | ||||
| @ -21174,10 +21325,13 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) { | ||||
| 			/* write cell */ | ||||
| 			write_ws_biff8_cell(ba, cell, R, C, opts); | ||||
| 			if(b8 && cell.l) ws['!links'].push([ref, cell.l]); | ||||
| 			if(b8 && cell.c) comments.push([ref, cell.c]); | ||||
| 		} | ||||
| 	} | ||||
| 	var cname/*:string*/ = _sheet.CodeName || _sheet.name || s; | ||||
| 	/* ... */ | ||||
| 	// if(b8) comments.forEach(function(comment) { write_biff_rec(ba, 0x001c /* Note */, write_NoteSh(comment)); });
 | ||||
| 	/* ... */ | ||||
| 	if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0])); | ||||
| 	/* ... */ | ||||
| 	if(b8 && (ws['!merges']||[]).length) write_biff_rec(ba, 0x00e5 /* MergeCells */, write_MergeCells(ws['!merges'])); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user