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.
|
||||
|
||||
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](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 = [];
|
||||