version bump 0.18.7

This commit is contained in:
SheetJS 2022-04-25 18:13:46 -04:00
parent 694cdcb75a
commit eee39946e3
19 changed files with 611 additions and 226 deletions

@ -27,9 +27,11 @@ tmp
*.[uU][oO][sS] *.[uU][oO][sS]
*.[wW][kKqQbB][S1234567890] *.[wW][kKqQbB][S1234567890]
*.[qQ][pP][wW] *.[qQ][pP][wW]
*.[fF][mM][3tT]
*.[bB][iI][fF][fF][23458] *.[bB][iI][fF][fF][23458]
*.[rR][tT][fF] *.[rR][tT][fF]
*.[eE][tT][hH] *.[eE][tT][hH]
*.[nN][uU][mM][bB][eE][rR][sS]
*.123 *.123
*.htm *.htm
*.html *.html

@ -4,6 +4,10 @@ This log is intended to keep track of backwards-incompatible changes, including
but not limited to API changes and file location changes. Minor behavioral but not limited to API changes and file location changes. Minor behavioral
changes may not be included if they are not expected to break existing code. changes may not be included if they are not expected to break existing code.
## v0.18.7
* Normalized handling of `\r` and `\n` newline characters
## v0.18.6 ## v0.18.6
* Removed all npm dependencies * Removed all npm dependencies

@ -125,11 +125,11 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
Each standalone release script is available at <https://cdn.sheetjs.com/>. Each standalone release script is available at <https://cdn.sheetjs.com/>.
The current version is `0.18.6` and can be referenced as follows: The current version is `0.18.7` and can be referenced as follows:
```html ```html
<!-- use version 0.18.6 --> <!-- use version 0.18.7 -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.full.min.js"></script> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.full.min.js"></script>
``` ```
The `latest` tag references the latest version and updates with each release: The `latest` tag references the latest version and updates with each release:
@ -157,8 +157,8 @@ A slimmer build is generated at `dist/xlsx.mini.min.js`. Compared to full build:
These scripts are also available on the CDN: These scripts are also available on the CDN:
```html ```html
<!-- use xlsx.mini.min.js from version 0.18.6 --> <!-- use xlsx.mini.min.js from version 0.18.7 -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.mini.min.js"></script> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.mini.min.js"></script>
``` ```
</details> </details>
@ -208,11 +208,11 @@ a page with a `script` tag using `type="module"`:
```html ```html
<script type="module"> <script type="module">
import { read, writeFileXLSX } from "https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs"; import { read, writeFileXLSX } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
/* load the codepage support library for extended support with older formats */ /* load the codepage support library for extended support with older formats */
import { set_cptable } from "https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs"; import { set_cptable } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/cpexcel.full.mjs'; import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/cpexcel.full.mjs';
set_cptable(cptable); set_cptable(cptable);
</script> </script>
``` ```
@ -222,9 +222,9 @@ _Frameworks (Angular, VueJS, React) and Bundlers (webpack, etc)_
The NodeJS package is readily installed from the tarballs: The NodeJS package is readily installed from the tarballs:
```bash ```bash
$ npm install --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # npm $ npm install --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # npm
$ pnpm install --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # pnpm $ pnpm install --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # pnpm
$ yarn add --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # yarn $ yarn add --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # yarn
``` ```
Once installed, the library can be imported under the name `xlsx`: Once installed, the library can be imported under the name `xlsx`:
@ -243,11 +243,11 @@ set_cptable(cptable);
`xlsx.mjs` can be imported in Deno: `xlsx.mjs` can be imported in Deno:
```ts ```ts
// @deno-types="https://cdn.sheetjs.com/xlsx-0.18.6/package/types/index.d.ts" // @deno-types="https://cdn.sheetjs.com/xlsx-0.18.7/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs'; import * as XLSX from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs';
/* load the codepage support library for extended support with older formats */ /* load the codepage support library for extended support with older formats */
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/cpexcel.full.mjs'; import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/cpexcel.full.mjs';
XLSX.set_cptable(cptable); XLSX.set_cptable(cptable);
``` ```
@ -256,7 +256,7 @@ XLSX.set_cptable(cptable);
Tarballs are available on <https://cdn.sheetjs.com>. Tarballs are available on <https://cdn.sheetjs.com>.
Each individual version can be referenced using a similar URL pattern. Each individual version can be referenced using a similar URL pattern.
<https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz> is the URL for `0.18.6` <https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz> is the URL for `0.18.7`
<https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz> is a link to the latest <https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz> is a link to the latest
version and will refresh on each release. version and will refresh on each release.
@ -266,15 +266,15 @@ _Installation_
Tarballs can be directly installed using a package manager: Tarballs can be directly installed using a package manager:
```bash ```bash
$ npm install https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # npm $ npm install https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # npm
$ pnpm install https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # pnpm $ pnpm install https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # pnpm
$ yarn add https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # yarn $ yarn add https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # yarn
``` ```
For general stability, "vendoring" modules is the recommended approach: For general stability, "vendoring" modules is the recommended approach:
1) Download the tarball (`xlsx-0.18.6.tgz`) for the desired version. The current 1) Download the tarball (`xlsx-0.18.7.tgz`) for the desired version. The current
version is available at <https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz> version is available at <https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz>
2) Create a `vendor` subdirectory at the root of your project and move the 2) Create a `vendor` subdirectory at the root of your project and move the
tarball to that folder. Add it to your project repository. tarball to that folder. Add it to your project repository.
@ -282,9 +282,9 @@ For general stability, "vendoring" modules is the recommended approach:
3) Install the tarball using a package manager: 3) Install the tarball using a package manager:
```bash ```bash
$ npm install --save file:vendor/xlsx-0.18.6.tgz # npm $ npm install --save file:vendor/xlsx-0.18.7.tgz # npm
$ pnpm install --save file:vendor/xlsx-0.18.6.tgz # pnpm $ pnpm install --save file:vendor/xlsx-0.18.7.tgz # pnpm
$ yarn add file:vendor/xlsx-0.18.6.tgz # yarn $ yarn add file:vendor/xlsx-0.18.7.tgz # yarn
``` ```
The package will be installed and accessible as `xlsx`. The package will be installed and accessible as `xlsx`.
@ -320,7 +320,7 @@ XLSX.set_cptable(cpexcel);
#### Photoshop and InDesign #### Photoshop and InDesign
`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign. `dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign.
<https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.extendscript.js> is the <https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.extendscript.js> is the
current version. After downloading the script, it can be directly referenced current version. After downloading the script, it can be directly referenced
with a `#include` directive: with a `#include` directive:

@ -1 +1 @@
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';

27
dist/xlsx.core.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.core.min.map generated vendored

File diff suppressed because one or more lines are too long

250
dist/xlsx.extendscript.js generated vendored

@ -160,7 +160,7 @@ var DO_NOT_EXPORT_CODEPAGE = true;
/*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ /*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {}; var XLSX = {};
function make_xlsx_lib(XLSX){ function make_xlsx_lib(XLSX){
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';
var current_codepage = 1200, current_ansi = 1252; var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true, window */ /*global cptable:true, window */
var $cptable; var $cptable;
@ -3674,15 +3674,19 @@ var rencoding = evert(encodings);
var unescapexml = (function() { var unescapexml = (function() {
/* 22.4.2.4 bstr (Basic String) */ /* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig; var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
return function unescapexml(text) { function raw_unescapexml(text) {
var s = text + '', i = s.indexOf("<![CDATA["); var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var j = s.indexOf("]]>"); var j = s.indexOf("]]>");
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3)); return raw_unescapexml(s.slice(0, i)) + s.slice(i+9,j) + raw_unescapexml(s.slice(j+3));
}
return function unescapexml(text, xlsx) {
var out = raw_unescapexml(text);
return xlsx ? out.replace(/\r\n/g, "\n") : out;
}; };
})(); })();
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g; var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f\uFFFE-\uFFFF]/g;
function escapexml(text){ function escapexml(text){
var s = text + ''; var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";}); return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
@ -3708,12 +3712,14 @@ var xlml_fixstr = (function() {
})(); })();
function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); } function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value) { function parsexmlbool(value) {
switch(value) { switch(value) {
case 1: case true: case '1': case 'true': case 'TRUE': return true; case 1: case true: case '1': case 'true': return true;
/* case '0': case 'false': case 'FALSE':*/ case 0: case false: case '0': case 'false': return false;
default: return false; //default: throw new Error("Invalid xsd:boolean " + value);
} }
return false;
} }
function utf8reada(orig) { function utf8reada(orig) {
@ -6060,6 +6066,7 @@ function parse_PropertySet(blob, PIDSI) {
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i); if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
} }
if(PIDSI) { if(PIDSI) {
if(Props[i][0] == 0 && Props.length > i+1 && Props[i][1] == Props[i+1][1]) continue; // R9
var piddsi = PIDSI[Props[i][0]]; var piddsi = PIDSI[Props[i][0]];
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true}); PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4); if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
@ -8515,10 +8522,9 @@ var PRN = (function() {
else sep = guess_sep(str.slice(0,1024)); else sep = guess_sep(str.slice(0,1024));
var R = 0, C = 0, v = 0; var R = 0, C = 0, v = 0;
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0); var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
str = str.replace(/\r\n/mg, "\n");
var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null; var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() { function finish_cell() {
var s = str.slice(start, end); var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}); var cell = ({});
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length === 0) cell.t = 'z'; if(s.length === 0) cell.t = 'z';
@ -8553,7 +8559,11 @@ var PRN = (function() {
} }
outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
case 0x22: if(startcc === 0x22) instr = !instr; break; case 0x22: if(startcc === 0x22) instr = !instr; break;
case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break; case 0x0d:
if(instr) break;
if(str.charCodeAt(end+1) == 0x0a) ++end;
/* falls through */
case sepcc: case 0x0a: if(!instr && finish_cell()) break outer; break;
default: break; default: break;
} }
if(end - start > 0) finish_cell(); if(end - start > 0) finish_cell();
@ -8669,6 +8679,7 @@ var WK_ = (function() {
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
var sheetRows = o.sheetRows || 0; var sheetRows = o.sheetRows || 0;
if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
if(d[2] == 0x00) { if(d[2] == 0x00) {
if(d[3] == 0x08 || d[3] == 0x09) { if(d[3] == 0x08 || d[3] == 0x09) {
if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file"); if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file");
@ -8682,12 +8693,17 @@ var WK_ = (function() {
o.vers = val; o.vers = val;
if(val >= 0x1000) o.qpro = true; if(val >= 0x1000) o.qpro = true;
break; break;
case 0xFF: /* BOF (works 3+) */
o.vers = val;
o.works = true;
break;
case 0x06: refguess = val; break; /* RANGE */ case 0x06: refguess = val; break; /* RANGE */
case 0xCC: if(val) next_n = val; break; /* SHEETNAMECS */ case 0xCC: if(val) next_n = val; break; /* SHEETNAMECS */
case 0xDE: next_n = val; break; /* SHEETNAMELP */ case 0xDE: next_n = val; break; /* SHEETNAMELP */
case 0x0F: /* LABEL */ case 0x0F: /* LABEL */
case 0x33: /* STRING */ case 0x33: /* STRING */
if(!o.qpro) val[1].v = val[1].v.slice(1); if((!o.qpro && !o.works || RT == 0x33) && val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1);
if(o.works || o.works2) val[1].v = val[1].v.replace(/\r\n/g, "\n");
/* falls through */ /* falls through */
case 0x0D: /* INTEGER */ case 0x0D: /* INTEGER */
case 0x0E: /* NUMBER */ case 0x0E: /* NUMBER */
@ -8721,6 +8737,7 @@ var WK_ = (function() {
s[val[0].r][val[0].c] = val[1]; s[val[0].r][val[0].c] = val[1];
} else s[encode_cell(val[0])] = val[1]; } else s[encode_cell(val[0])] = val[1];
break; break;
case 0x5405: o.works2 = true; break;
default: default:
}}, o); }}, o);
} else if(d[2] == 0x1A || d[2] == 0x0E) { } else if(d[2] == 0x1A || d[2] == 0x0E) {
@ -8729,7 +8746,9 @@ var WK_ = (function() {
lotushopper(d, function(val, R, RT) { switch(RT) { lotushopper(d, function(val, R, RT) { switch(RT) {
case 0xCC: n = val; break; /* SHEETNAMECS */ case 0xCC: n = val; break; /* SHEETNAMECS */
case 0x16: /* LABEL16 */ case 0x16: /* LABEL16 */
val[1].v = val[1].v.slice(1); if(val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1);
// TODO: R9 appears to encode control codes this way -- verify against other versions
val[1].v = val[1].v.replace(/\x0F./g, function($$) { return String.fromCharCode($$.charCodeAt(1) - 0x20); }).replace(/\r\n/g, "\n");
/* falls through */ /* falls through */
case 0x17: /* NUMBER17 */ case 0x17: /* NUMBER17 */
case 0x18: /* NUMBER18 */ case 0x18: /* NUMBER18 */
@ -8924,6 +8943,9 @@ var WK_ = (function() {
o[3] = blob.read_shift(1); o[3] = blob.read_shift(1);
o[0].r = blob.read_shift(2); o[0].r = blob.read_shift(2);
blob.l+=2; blob.l+=2;
} else if(opts.works) { // TODO: verify with more complex works3-4 examples
o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
o[2] = blob.read_shift(2);
} else { } else {
o[2] = blob.read_shift(1); o[2] = blob.read_shift(1);
o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2); o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
@ -8959,6 +8981,18 @@ var WK_ = (function() {
o.write_shift(1, 0); o.write_shift(1, 0);
return o; return o;
} }
function parse_STRING(blob, length, opts) {
var tgt = blob.l + length;
var o = parse_cell(blob, length, opts);
o[1].t = 's';
if(opts.vers == 0x5120) {
var len = blob.read_shift(1);
o[1].v = blob.read_shift(len, 'utf8');
return o;
}
o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
return o;
}
function parse_INTEGER(blob, length, opts) { function parse_INTEGER(blob, length, opts) {
var o = parse_cell(blob, length, opts); var o = parse_cell(blob, length, opts);
@ -9017,6 +9051,7 @@ var WK_ = (function() {
0x33: ["FALSE", 0], 0x33: ["FALSE", 0],
0x34: ["TRUE", 0], 0x34: ["TRUE", 0],
0x46: ["LEN", 1], 0x46: ["LEN", 1],
0x4A: ["CHAR", 1],
0x50: ["SUM", 69], 0x50: ["SUM", 69],
0x51: ["AVERAGEA", 69], 0x51: ["AVERAGEA", 69],
0x52: ["COUNTA", 69], 0x52: ["COUNTA", 69],
@ -9207,8 +9242,8 @@ var WK_ = (function() {
} }
function parse_FORMULA_28(blob, length) { function parse_FORMULA_28(blob, length) {
var o = parse_NUMBER_27(blob, 14); var o = parse_NUMBER_27(blob, 12);
blob.l += length - 10; /* TODO: formula */ blob.l += length - 12; /* TODO: formula */
return o; return o;
} }
@ -9298,7 +9333,7 @@ var WK_ = (function() {
0x0030: { n:"UNFORMATTED" }, 0x0030: { n:"UNFORMATTED" },
0x0031: { n:"CURSORW12" }, 0x0031: { n:"CURSORW12" },
0x0032: { n:"WINDOW" }, 0x0032: { n:"WINDOW" },
0x0033: { n:"STRING", f:parse_LABEL }, 0x0033: { n:"STRING", f:parse_STRING },
0x0037: { n:"PASSWORD" }, 0x0037: { n:"PASSWORD" },
0x0038: { n:"LOCKED" }, 0x0038: { n:"LOCKED" },
0x003C: { n:"QUERY" }, 0x003C: { n:"QUERY" },
@ -9322,6 +9357,7 @@ var WK_ = (function() {
0x0069: { n:"MRANGES??" }, 0x0069: { n:"MRANGES??" },
0x00CC: { n:"SHEETNAMECS", f:parse_SHEETNAMECS }, 0x00CC: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
0x00DE: { n:"SHEETNAMELP", f:parse_SHEETNAMELP }, 0x00DE: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
0x00FF: { n:"BOF", f:parseuint16 },
0xFFFF: { n:"" } 0xFFFF: { n:"" }
}; };
@ -9450,6 +9486,144 @@ var WK_ = (function() {
0x6F44: { n:"??" }, 0x6F44: { n:"??" },
0xFFFF: { n:"" } 0xFFFF: { n:"" }
}; };
/* QPW uses a different set of record types */
function qpw_to_workbook_buf(d, opts) {
prep_blob(d, 0);
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var s = ((o.dense ? [] : {}));
var SST = [], sname = "", formulae = [];
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
var cnt = 0, type = 0, C = 0, R = 0;
var wb = { SheetNames: [], Sheets: {} };
outer: while(d.l < d.length) {
var RT = d.read_shift(2), length = d.read_shift(2);
var p = d.slice(d.l, d.l + length);
prep_blob(p, 0);
switch(RT) {
case 0x01: /* BOF */
if(p.read_shift(4) != 0x39575051) throw "Bad QPW9 BOF!";
break;
case 0x02: /* EOF */ break outer;
/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TSTable */
case 0x0401: /* BON */ break;
case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
case 0x0407: { /* SST */
p.l += 12;
while(p.l < p.length) {
cnt = p.read_shift(2);
type = p.read_shift(1);
SST.push(p.read_shift(cnt, 'cstr'));
}
} break;
case 0x0408: { /* FORMULAE */
//p.l += 12;
//while(p.l < p.length) {
// cnt = p.read_shift(2);
// formulae.push(p.slice(p.l, p.l + cnt + 1)); p.l += cnt + 1;
//}
} break;
case 0x0601: { /* BOS */
var sidx = p.read_shift(2);
s = ((o.dense ? [] : {}));
range.s.c = p.read_shift(2);
range.e.c = p.read_shift(2);
range.s.r = p.read_shift(4);
range.e.r = p.read_shift(4);
p.l += 4;
if(p.l + 2 < p.length) {
cnt = p.read_shift(2);
type = p.read_shift(1);
sname = cnt == 0 ? "" : p.read_shift(cnt, 'cstr');
}
if(!sname) sname = XLSX.utils.encode_col(sidx);
/* TODO: backfill empty sheets */
} break;
case 0x0602: { /* EOS */
/* NOTE: QP valid range A1:IV1000000 */
if(range.s.c > 0xFF || range.s.r > 999999) break;
if(range.e.c < range.s.c) range.e.c = range.s.c;
if(range.e.r < range.s.r) range.e.r = range.s.r;
s["!ref"] = encode_range(range);
book_append_sheet(wb, s, sname); // TODO: a barrel roll
} break;
case 0x0A01: { /* COL (like XLS Row, modulo the layout transposition) */
C = p.read_shift(2);
if(range.e.c < C) range.e.c = C;
if(range.s.c > C) range.s.c = C;
R = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
R = p.read_shift(4);
if(range.e.r < R) range.e.r = R;
} break;
case 0x0C01: { /* MulCells (like XLS MulRK, but takes advantage of common column data patterns) */
R = p.read_shift(4), cnt = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
if(range.e.r < R + cnt - 1) range.e.r = R + cnt - 1;
while(p.l < p.length) {
var cell = { t: "z" };
var flags = p.read_shift(1);
if(flags & 0x80) p.l += 2;
var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
switch(flags & 0x1F) {
case 1: break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break;
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
}
var delta = 0;
if(flags & 0x20) switch(flags & 0x1F) {
case 2: delta = p.read_shift(2); break;
case 3: delta = p.read_shift(2, 'i'); break;
case 7: delta = p.read_shift(2); break;
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(Array.isArray(s)) {
if(!s[R]) s[R] = [];
s[R][C] = cell;
} else s[encode_cell({r:R, c:C})] = cell;
}
++R; --cnt;
while(mul-- > 0 && cnt >= 0) {
if(flags & 0x20) switch(flags & 0x1F) {
case 2: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; break;
case 3: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; if(cell.v > 0x7FFF) cell.v -= 0x10000; break;
case 7: cell = { t: "s", v: SST[type = (type + delta) >>> 0] }; break;
default: throw "Cannot apply delta for QPW cell type " + (flags & 0x1F);
} else switch(flags & 0x1F) {
case 1: cell = { t: "z" }; break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(Array.isArray(s)) {
if(!s[R]) s[R] = [];
s[R][C] = cell;
} else s[encode_cell({r:R, c:C})] = cell;
}
++R; --cnt;
}
}
} break;
default: break;
}
d.l += length;
}
return wb;
}
return { return {
sheet_to_wk1: sheet_to_wk1, sheet_to_wk1: sheet_to_wk1,
book_to_wk3: book_to_wk3, book_to_wk3: book_to_wk3,
@ -9636,14 +9810,14 @@ function parse_si(x, opts) {
/* 18.4.12 t ST_Xstring (Plaintext String) */ /* 18.4.12 t ST_Xstring (Plaintext String) */
// TODO: is whitespace actually valid here? // TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) { if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||"")); z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""), true);
z.r = utf8read(x); z.r = utf8read(x);
if(html) z.h = escapehtml(z.t); if(html) z.h = escapehtml(z.t);
} }
/* 18.4.4 r CT_RElt (Rich Text Run) */ /* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) { else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x); z.r = utf8read(x);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,""))); z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r)); if(html) z.h = rs_to_html(parse_rs(z.r));
} }
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */ /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -10075,27 +10249,33 @@ var RTF = (function() {
var o = opts || {}; var o = opts || {};
var ws = o.dense ? ([]) : ({}); var ws = o.dense ? ([]) : ({});
var rows = str.match(/\\trowd.*?\\row\b/g); var rows = str.match(/\\trowd[\s\S]*?\\row\b/g);
if(!rows.length) throw new Error("RTF missing table"); if(!rows.length) throw new Error("RTF missing table");
var range = ({s: {c:0, r:0}, e: {c:0, r:rows.length - 1}}); var range = ({s: {c:0, r:0}, e: {c:0, r:rows.length - 1}});
rows.forEach(function(rowtf, R) { rows.forEach(function(rowtf, R) {
if(Array.isArray(ws)) ws[R] = []; if(Array.isArray(ws)) ws[R] = [];
var rtfre = /\\\w+\b/g; var rtfre = /\\[\w\-]+\b/g;
var last_index = 0; var last_index = 0;
var res; var res;
var C = -1; var C = -1;
var payload = [];
while((res = rtfre.exec(rowtf))) { while((res = rtfre.exec(rowtf))) {
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
if(data.charCodeAt(0) == 0x20) data = data.slice(1);
if(data.length) payload.push(data);
switch(res[0]) { switch(res[0]) {
case "\\cell": case "\\cell":
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
if(data[0] == " ") data = data.slice(1);
++C; ++C;
if(data.length) { if(payload.length) {
// TODO: value parsing, including codepage adjustments // TODO: value parsing, including codepage adjustments
var cell = {v: data, t:"s"}; var cell = {v: payload.join(""), t:"s"};
if(Array.isArray(ws)) ws[R][C] = cell; if(Array.isArray(ws)) ws[R][C] = cell;
else ws[encode_cell({r:R, c:C})] = cell; else ws[encode_cell({r:R, c:C})] = cell;
} }
payload = [];
break;
case "\\par": // NOTE: Excel serializes both "\r" and "\n" as "\\par"
payload.push("\n");
break; break;
} }
last_index = rtfre.lastIndex; last_index = rtfre.lastIndex;
@ -10121,7 +10301,7 @@ var RTF = (function() {
var coord = encode_cell({r:R,c:C}); var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C]: ws[coord]; cell = dense ? (ws[R]||[])[C]: ws[coord];
if(!cell || cell.v == null && (!cell.f || cell.F)) continue; if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
o.push(" " + (cell.w || (format_cell(cell), cell.w))); o.push(" " + (cell.w || (format_cell(cell), cell.w)).replace(/[\r\n]/g, "\\par "));
o.push("\\cell"); o.push("\\cell");
} }
o.push("\\pard\\intbl\\row"); o.push("\\pard\\intbl\\row");
@ -14923,7 +15103,7 @@ function parse_ws_xml_sheetviews(data, wb) {
// $FlowIgnore // $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale; if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore // $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true; if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
}); });
} }
function write_ws_xml_sheetviews(ws, opts, idx, wb) { function write_ws_xml_sheetviews(ws, opts, idx, wb) {
@ -15015,7 +15195,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts.sheetRows && opts.sheetRows < tagr) continue; if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -15032,7 +15212,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts && opts.cellStyles) { if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -15065,7 +15245,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts.cellFormula) { if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && cref[1] !== '') { if((cref=d.match(match_f))!= null && cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */ /* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n"); p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f); if(!opts.xlfn) p.f = _xlfn(p.f);
if(cref[0].indexOf('t="array"') > -1) { if(cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1]; p.F = (d.match(refregex)||[])[1];
@ -15119,7 +15299,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
break; break;
case 'str': case 'str':
p.t = "s"; p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : ''; p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
if(opts.cellHTML) p.h = escapehtml(p.v); if(opts.cellHTML) p.h = escapehtml(p.v);
break; break;
case 'inlineStr': case 'inlineStr':
@ -16134,6 +16314,8 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
/* TODO: something useful -- this is a stub */ /* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen) { function write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen) {
var o = ({r:R, c:C});
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false; if(cell.v === undefined) return false;
var vv = ""; var vv = "";
switch(cell.t) { switch(cell.t) {
@ -16147,11 +16329,9 @@ function write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen) {
case 'n': case 'e': vv = ''+cell.v; break; case 'n': case 'e': vv = ''+cell.v; break;
default: vv = cell.v; break; default: vv = cell.v; break;
} }
var o = ({r:R, c:C});
/* TODO: cell style */ /* TODO: cell style */
o.s = get_cell_style(opts.cellXfs, cell, opts); o.s = get_cell_style(opts.cellXfs, cell, opts);
if(cell.l) ws['!links'].push([encode_cell(o), cell.l]); if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
switch(cell.t) { switch(cell.t) {
case 's': case 'str': case 's': case 'str':
if(opts.bookSST) { if(opts.bookSST) {
@ -23556,8 +23736,8 @@ function write_zip_xlsb(wb, opts) {
opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0; opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map(); if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; } else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = opts.bookType == "xlsb" ? "bin" : "xml"; var wbext = "bin";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1; var vbafmt = true;
var ct = new_ct(); var ct = new_ct();
fix_write_opts(opts = opts || {}); fix_write_opts(opts = opts || {});
var zip = zip_new(); var zip = zip_new();
@ -23755,10 +23935,10 @@ f = "docProps/app.xml";
carr[1].forEach(function(c) { if(c.T == true) needtc = true; }); carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
}); });
if(needtc) { if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + "." + wbext; cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts)); zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf); ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + "." + wbext, RELS.TCMNT); add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
} }
cf = "xl/comments" + rId + "." + wbext; cf = "xl/comments" + rId + "." + wbext;

28
dist/xlsx.full.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.full.min.map generated vendored

File diff suppressed because one or more lines are too long

16
dist/xlsx.mini.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.mini.min.map generated vendored

File diff suppressed because one or more lines are too long

@ -6,11 +6,11 @@
Each standalone release script is available at <https://cdn.sheetjs.com/>. Each standalone release script is available at <https://cdn.sheetjs.com/>.
The current version is `0.18.6` and can be referenced as follows: The current version is `0.18.7` and can be referenced as follows:
```html ```html
<!-- use version 0.18.6 --> <!-- use version 0.18.7 -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.full.min.js"></script> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.full.min.js"></script>
``` ```
The `latest` tag references the latest version and updates with each release: The `latest` tag references the latest version and updates with each release:
@ -38,8 +38,8 @@ A slimmer build is generated at `dist/xlsx.mini.min.js`. Compared to full build:
These scripts are also available on the CDN: These scripts are also available on the CDN:
```html ```html
<!-- use xlsx.mini.min.js from version 0.18.6 --> <!-- use xlsx.mini.min.js from version 0.18.7 -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.mini.min.js"></script> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.mini.min.js"></script>
``` ```
</details> </details>
@ -89,11 +89,11 @@ a page with a `script` tag using `type="module"`:
```html ```html
<script type="module"> <script type="module">
import { read, writeFileXLSX } from "https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs"; import { read, writeFileXLSX } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
/* load the codepage support library for extended support with older formats */ /* load the codepage support library for extended support with older formats */
import { set_cptable } from "https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs"; import { set_cptable } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/cpexcel.full.mjs'; import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/cpexcel.full.mjs';
set_cptable(cptable); set_cptable(cptable);
</script> </script>
``` ```
@ -103,9 +103,9 @@ _Frameworks (Angular, VueJS, React) and Bundlers (webpack, etc)_
The NodeJS package is readily installed from the tarballs: The NodeJS package is readily installed from the tarballs:
```bash ```bash
$ npm install --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # npm $ npm install --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # npm
$ pnpm install --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # pnpm $ pnpm install --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # pnpm
$ yarn add --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # yarn $ yarn add --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # yarn
``` ```
Once installed, the library can be imported under the name `xlsx`: Once installed, the library can be imported under the name `xlsx`:
@ -124,11 +124,11 @@ set_cptable(cptable);
`xlsx.mjs` can be imported in Deno: `xlsx.mjs` can be imported in Deno:
```ts ```ts
// @deno-types="https://cdn.sheetjs.com/xlsx-0.18.6/package/types/index.d.ts" // @deno-types="https://cdn.sheetjs.com/xlsx-0.18.7/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs'; import * as XLSX from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs';
/* load the codepage support library for extended support with older formats */ /* load the codepage support library for extended support with older formats */
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/cpexcel.full.mjs'; import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/cpexcel.full.mjs';
XLSX.set_cptable(cptable); XLSX.set_cptable(cptable);
``` ```
@ -137,7 +137,7 @@ XLSX.set_cptable(cptable);
Tarballs are available on <https://cdn.sheetjs.com>. Tarballs are available on <https://cdn.sheetjs.com>.
Each individual version can be referenced using a similar URL pattern. Each individual version can be referenced using a similar URL pattern.
<https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz> is the URL for `0.18.6` <https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz> is the URL for `0.18.7`
<https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz> is a link to the latest <https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz> is a link to the latest
version and will refresh on each release. version and will refresh on each release.
@ -147,15 +147,15 @@ _Installation_
Tarballs can be directly installed using a package manager: Tarballs can be directly installed using a package manager:
```bash ```bash
$ npm install https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # npm $ npm install https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # npm
$ pnpm install https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # pnpm $ pnpm install https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # pnpm
$ yarn add https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # yarn $ yarn add https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # yarn
``` ```
For general stability, "vendoring" modules is the recommended approach: For general stability, "vendoring" modules is the recommended approach:
1) Download the tarball (`xlsx-0.18.6.tgz`) for the desired version. The current 1) Download the tarball (`xlsx-0.18.7.tgz`) for the desired version. The current
version is available at <https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz> version is available at <https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz>
2) Create a `vendor` subdirectory at the root of your project and move the 2) Create a `vendor` subdirectory at the root of your project and move the
tarball to that folder. Add it to your project repository. tarball to that folder. Add it to your project repository.
@ -163,9 +163,9 @@ For general stability, "vendoring" modules is the recommended approach:
3) Install the tarball using a package manager: 3) Install the tarball using a package manager:
```bash ```bash
$ npm install --save file:vendor/xlsx-0.18.6.tgz # npm $ npm install --save file:vendor/xlsx-0.18.7.tgz # npm
$ pnpm install --save file:vendor/xlsx-0.18.6.tgz # pnpm $ pnpm install --save file:vendor/xlsx-0.18.7.tgz # pnpm
$ yarn add file:vendor/xlsx-0.18.6.tgz # yarn $ yarn add file:vendor/xlsx-0.18.7.tgz # yarn
``` ```
The package will be installed and accessible as `xlsx`. The package will be installed and accessible as `xlsx`.
@ -201,7 +201,7 @@ XLSX.set_cptable(cpexcel);
#### Photoshop and InDesign #### Photoshop and InDesign
`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign. `dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign.
<https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.extendscript.js> is the <https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.extendscript.js> is the
current version. After downloading the script, it can be directly referenced current version. After downloading the script, it can be directly referenced
with a `#include` directive: with a `#include` directive:

@ -122,11 +122,11 @@ port calculations to web apps; automate common spreadsheet tasks, and much more!
Each standalone release script is available at <https://cdn.sheetjs.com/>. Each standalone release script is available at <https://cdn.sheetjs.com/>.
The current version is `0.18.6` and can be referenced as follows: The current version is `0.18.7` and can be referenced as follows:
```html ```html
<!-- use version 0.18.6 --> <!-- use version 0.18.7 -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.full.min.js"></script> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.full.min.js"></script>
``` ```
The `latest` tag references the latest version and updates with each release: The `latest` tag references the latest version and updates with each release:
@ -152,8 +152,8 @@ A slimmer build is generated at `dist/xlsx.mini.min.js`. Compared to full build:
These scripts are also available on the CDN: These scripts are also available on the CDN:
```html ```html
<!-- use xlsx.mini.min.js from version 0.18.6 --> <!-- use xlsx.mini.min.js from version 0.18.7 -->
<script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.mini.min.js"></script> <script lang="javascript" src="https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.mini.min.js"></script>
``` ```
@ -199,11 +199,11 @@ a page with a `script` tag using `type="module"`:
```html ```html
<script type="module"> <script type="module">
import { read, writeFileXLSX } from "https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs"; import { read, writeFileXLSX } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
/* load the codepage support library for extended support with older formats */ /* load the codepage support library for extended support with older formats */
import { set_cptable } from "https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs"; import { set_cptable } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/cpexcel.full.mjs'; import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/cpexcel.full.mjs';
set_cptable(cptable); set_cptable(cptable);
</script> </script>
``` ```
@ -213,9 +213,9 @@ _Frameworks (Angular, VueJS, React) and Bundlers (webpack, etc)_
The NodeJS package is readily installed from the tarballs: The NodeJS package is readily installed from the tarballs:
```bash ```bash
$ npm install --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # npm $ npm install --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # npm
$ pnpm install --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # pnpm $ pnpm install --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # pnpm
$ yarn add --save https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # yarn $ yarn add --save https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # yarn
``` ```
Once installed, the library can be imported under the name `xlsx`: Once installed, the library can be imported under the name `xlsx`:
@ -234,11 +234,11 @@ set_cptable(cptable);
`xlsx.mjs` can be imported in Deno: `xlsx.mjs` can be imported in Deno:
```ts ```ts
// @deno-types="https://cdn.sheetjs.com/xlsx-0.18.6/package/types/index.d.ts" // @deno-types="https://cdn.sheetjs.com/xlsx-0.18.7/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/xlsx.mjs'; import * as XLSX from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs';
/* load the codepage support library for extended support with older formats */ /* load the codepage support library for extended support with older formats */
import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/cpexcel.full.mjs'; import * as cptable from 'https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/cpexcel.full.mjs';
XLSX.set_cptable(cptable); XLSX.set_cptable(cptable);
``` ```
@ -247,7 +247,7 @@ XLSX.set_cptable(cptable);
Tarballs are available on <https://cdn.sheetjs.com>. Tarballs are available on <https://cdn.sheetjs.com>.
Each individual version can be referenced using a similar URL pattern. Each individual version can be referenced using a similar URL pattern.
<https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz> is the URL for `0.18.6` <https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz> is the URL for `0.18.7`
<https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz> is a link to the latest <https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz> is a link to the latest
version and will refresh on each release. version and will refresh on each release.
@ -257,15 +257,15 @@ _Installation_
Tarballs can be directly installed using a package manager: Tarballs can be directly installed using a package manager:
```bash ```bash
$ npm install https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # npm $ npm install https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # npm
$ pnpm install https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # pnpm $ pnpm install https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # pnpm
$ yarn add https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz # yarn $ yarn add https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz # yarn
``` ```
For general stability, "vendoring" modules is the recommended approach: For general stability, "vendoring" modules is the recommended approach:
1) Download the tarball (`xlsx-0.18.6.tgz`) for the desired version. The current 1) Download the tarball (`xlsx-0.18.7.tgz`) for the desired version. The current
version is available at <https://cdn.sheetjs.com/xlsx-0.18.6/xlsx-0.18.6.tgz> version is available at <https://cdn.sheetjs.com/xlsx-0.18.7/xlsx-0.18.7.tgz>
2) Create a `vendor` subdirectory at the root of your project and move the 2) Create a `vendor` subdirectory at the root of your project and move the
tarball to that folder. Add it to your project repository. tarball to that folder. Add it to your project repository.
@ -273,9 +273,9 @@ For general stability, "vendoring" modules is the recommended approach:
3) Install the tarball using a package manager: 3) Install the tarball using a package manager:
```bash ```bash
$ npm install --save file:vendor/xlsx-0.18.6.tgz # npm $ npm install --save file:vendor/xlsx-0.18.7.tgz # npm
$ pnpm install --save file:vendor/xlsx-0.18.6.tgz # pnpm $ pnpm install --save file:vendor/xlsx-0.18.7.tgz # pnpm
$ yarn add file:vendor/xlsx-0.18.6.tgz # yarn $ yarn add file:vendor/xlsx-0.18.7.tgz # yarn
``` ```
The package will be installed and accessible as `xlsx`. The package will be installed and accessible as `xlsx`.
@ -311,7 +311,7 @@ XLSX.set_cptable(cpexcel);
#### Photoshop and InDesign #### Photoshop and InDesign
`dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign. `dist/xlsx.extendscript.js` is an ExtendScript build for Photoshop and InDesign.
<https://cdn.sheetjs.com/xlsx-0.18.6/package/dist/xlsx.extendscript.js> is the <https://cdn.sheetjs.com/xlsx-0.18.7/package/dist/xlsx.extendscript.js> is the
current version. After downloading the script, it can be directly referenced current version. After downloading the script, it can be directly referenced
with a `#include` directive: with a `#include` directive:

@ -1,6 +1,6 @@
{ {
"name": "xlsx", "name": "xlsx",
"version": "0.18.6", "version": "0.18.7",
"author": "sheetjs", "author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer", "description": "SheetJS Spreadsheet data parser and writer",
"keywords": [ "keywords": [

@ -4,7 +4,7 @@
/*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ /*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {}; var XLSX = {};
function make_xlsx_lib(XLSX){ function make_xlsx_lib(XLSX){
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';
var current_codepage = 1200, current_ansi = 1252; var current_codepage = 1200, current_ansi = 1252;
/*:: declare var cptable:any; */ /*:: declare var cptable:any; */
/*global cptable:true, window */ /*global cptable:true, window */

2
xlsx.js generated

@ -4,7 +4,7 @@
/*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ /*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {}; var XLSX = {};
function make_xlsx_lib(XLSX){ function make_xlsx_lib(XLSX){
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';
var current_codepage = 1200, current_ansi = 1252; var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true, window */ /*global cptable:true, window */
var $cptable; var $cptable;

@ -4,7 +4,7 @@
/*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ /*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {}; var XLSX = {};
function make_xlsx_lib(XLSX){ function make_xlsx_lib(XLSX){
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';
var current_codepage = 1200, current_ansi = 1252; var current_codepage = 1200, current_ansi = 1252;
var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ]; var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ];
@ -3571,15 +3571,19 @@ var rencoding = /*#__PURE__*/evert(encodings);
var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() { var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() {
/* 22.4.2.4 bstr (Basic String) */ /* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig; var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
return function unescapexml(text/*:string*/)/*:string*/ { function raw_unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("<![CDATA["); var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var j = s.indexOf("]]>"); var j = s.indexOf("]]>");
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3)); return raw_unescapexml(s.slice(0, i)) + s.slice(i+9,j) + raw_unescapexml(s.slice(j+3));
}
return function unescapexml(text/*:string*/, xlsx/*:boolean*/) {
var out = raw_unescapexml(text);
return xlsx ? out.replace(/\r\n/g, "\n") : out;
}; };
})(); })();
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g; var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f\uFFFE-\uFFFF]/g;
function escapexml(text/*:string*/)/*:string*/{ function escapexml(text/*:string*/)/*:string*/{
var s = text + ''; var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";}); return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
@ -3605,12 +3609,14 @@ var xlml_fixstr/*:StringConv*/ = /*#__PURE__*/(function() {
})(); })();
function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); } function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value/*:any*/)/*:boolean*/ { function parsexmlbool(value/*:any*/)/*:boolean*/ {
switch(value) { switch(value) {
case 1: case true: case '1': case 'true': case 'TRUE': return true; case 1: case true: case '1': case 'true': return true;
/* case '0': case 'false': case 'FALSE':*/ case 0: case false: case '0': case 'false': return false;
default: return false; //default: throw new Error("Invalid xsd:boolean " + value);
} }
return false;
} }
function utf8reada(orig/*:string*/)/*:string*/ { function utf8reada(orig/*:string*/)/*:string*/ {
@ -6288,10 +6294,9 @@ var PRN = /*#__PURE__*/(function() {
else sep = guess_sep(str.slice(0,1024)); else sep = guess_sep(str.slice(0,1024));
var R = 0, C = 0, v = 0; var R = 0, C = 0, v = 0;
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0); var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
str = str.replace(/\r\n/mg, "\n");
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null; var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() { function finish_cell() {
var s = str.slice(start, end); var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}/*:any*/); var cell = ({}/*:any*/);
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length === 0) cell.t = 'z'; if(s.length === 0) cell.t = 'z';
@ -6326,7 +6331,11 @@ var PRN = /*#__PURE__*/(function() {
} }
outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
case 0x22: if(startcc === 0x22) instr = !instr; break; case 0x22: if(startcc === 0x22) instr = !instr; break;
case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break; case 0x0d:
if(instr) break;
if(str.charCodeAt(end+1) == 0x0a) ++end;
/* falls through */
case sepcc: case 0x0a: if(!instr && finish_cell()) break outer; break;
default: break; default: break;
} }
if(end - start > 0) finish_cell(); if(end - start > 0) finish_cell();
@ -6586,14 +6595,14 @@ function parse_si(x, opts) {
/* 18.4.12 t ST_Xstring (Plaintext String) */ /* 18.4.12 t ST_Xstring (Plaintext String) */
// TODO: is whitespace actually valid here? // TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) { if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||"")); z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""), true);
z.r = utf8read(x); z.r = utf8read(x);
if(html) z.h = escapehtml(z.t); if(html) z.h = escapehtml(z.t);
} }
/* 18.4.4 r CT_RElt (Rich Text Run) */ /* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) { else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x); z.r = utf8read(x);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,""))); z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r)); if(html) z.h = rs_to_html(parse_rs(z.r));
} }
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */ /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -8392,7 +8401,7 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore // $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale; if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore // $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true; if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
}); });
} }
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ { function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
@ -8484,7 +8493,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.sheetRows && opts.sheetRows < tagr) continue; if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -8501,7 +8510,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts && opts.cellStyles) { if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -8534,7 +8543,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.cellFormula) { if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') { if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */ /* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n"); p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f); if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) { if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1]; p.F = (d.match(refregex)||[])[1];
@ -8588,7 +8597,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break; break;
case 'str': case 'str':
p.t = "s"; p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : ''; p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
if(opts.cellHTML) p.h = escapehtml(p.v); if(opts.cellHTML) p.h = escapehtml(p.v);
break; break;
case 'inlineStr': case 'inlineStr':
@ -10765,8 +10774,8 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0; opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map(); if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; } else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = opts.bookType == "xlsb" ? "bin" : "xml"; var wbext = "bin";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1; var vbafmt = true;
var ct = new_ct(); var ct = new_ct();
fix_write_opts(opts = opts || {}); fix_write_opts(opts = opts || {});
var zip = zip_new(); var zip = zip_new();
@ -10966,10 +10975,10 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; }); carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
}); });
if(needtc) { if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + "." + wbext; cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts)); zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf); ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + "." + wbext, RELS.TCMNT); add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
} }
cf = "xl/comments" + rId + "." + wbext; cf = "xl/comments" + rId + "." + wbext;

@ -4,7 +4,7 @@
/*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ /*global exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {}; var XLSX = {};
function make_xlsx_lib(XLSX){ function make_xlsx_lib(XLSX){
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';
var current_codepage = 1200, current_ansi = 1252; var current_codepage = 1200, current_ansi = 1252;
var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ]; var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ];
@ -3498,15 +3498,19 @@ var rencoding = evert(encodings);
var unescapexml = (function() { var unescapexml = (function() {
/* 22.4.2.4 bstr (Basic String) */ /* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig; var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
return function unescapexml(text) { function raw_unescapexml(text) {
var s = text + '', i = s.indexOf("<![CDATA["); var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var j = s.indexOf("]]>"); var j = s.indexOf("]]>");
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3)); return raw_unescapexml(s.slice(0, i)) + s.slice(i+9,j) + raw_unescapexml(s.slice(j+3));
}
return function unescapexml(text, xlsx) {
var out = raw_unescapexml(text);
return xlsx ? out.replace(/\r\n/g, "\n") : out;
}; };
})(); })();
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g; var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f\uFFFE-\uFFFF]/g;
function escapexml(text){ function escapexml(text){
var s = text + ''; var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";}); return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
@ -3532,12 +3536,14 @@ var xlml_fixstr = (function() {
})(); })();
function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); } function xlml_unfixstr(str) { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value) { function parsexmlbool(value) {
switch(value) { switch(value) {
case 1: case true: case '1': case 'true': case 'TRUE': return true; case 1: case true: case '1': case 'true': return true;
/* case '0': case 'false': case 'FALSE':*/ case 0: case false: case '0': case 'false': return false;
default: return false; //default: throw new Error("Invalid xsd:boolean " + value);
} }
return false;
} }
function utf8reada(orig) { function utf8reada(orig) {
@ -6203,10 +6209,9 @@ var PRN = (function() {
else sep = guess_sep(str.slice(0,1024)); else sep = guess_sep(str.slice(0,1024));
var R = 0, C = 0, v = 0; var R = 0, C = 0, v = 0;
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0); var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
str = str.replace(/\r\n/mg, "\n");
var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null; var _re = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() { function finish_cell() {
var s = str.slice(start, end); var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}); var cell = ({});
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length === 0) cell.t = 'z'; if(s.length === 0) cell.t = 'z';
@ -6241,7 +6246,11 @@ var PRN = (function() {
} }
outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
case 0x22: if(startcc === 0x22) instr = !instr; break; case 0x22: if(startcc === 0x22) instr = !instr; break;
case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break; case 0x0d:
if(instr) break;
if(str.charCodeAt(end+1) == 0x0a) ++end;
/* falls through */
case sepcc: case 0x0a: if(!instr && finish_cell()) break outer; break;
default: break; default: break;
} }
if(end - start > 0) finish_cell(); if(end - start > 0) finish_cell();
@ -6501,14 +6510,14 @@ function parse_si(x, opts) {
/* 18.4.12 t ST_Xstring (Plaintext String) */ /* 18.4.12 t ST_Xstring (Plaintext String) */
// TODO: is whitespace actually valid here? // TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) { if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||"")); z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""), true);
z.r = utf8read(x); z.r = utf8read(x);
if(html) z.h = escapehtml(z.t); if(html) z.h = escapehtml(z.t);
} }
/* 18.4.4 r CT_RElt (Rich Text Run) */ /* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) { else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x); z.r = utf8read(x);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,""))); z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r)); if(html) z.h = rs_to_html(parse_rs(z.r));
} }
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */ /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -8307,7 +8316,7 @@ function parse_ws_xml_sheetviews(data, wb) {
// $FlowIgnore // $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale; if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore // $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true; if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
}); });
} }
function write_ws_xml_sheetviews(ws, opts, idx, wb) { function write_ws_xml_sheetviews(ws, opts, idx, wb) {
@ -8399,7 +8408,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts.sheetRows && opts.sheetRows < tagr) continue; if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -8416,7 +8425,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts && opts.cellStyles) { if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -8449,7 +8458,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
if(opts.cellFormula) { if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && cref[1] !== '') { if((cref=d.match(match_f))!= null && cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */ /* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n"); p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f); if(!opts.xlfn) p.f = _xlfn(p.f);
if(cref[0].indexOf('t="array"') > -1) { if(cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1]; p.F = (d.match(refregex)||[])[1];
@ -8503,7 +8512,7 @@ return function parse_ws_xml_data(sdata, s, opts, guess, themes, styles) {
break; break;
case 'str': case 'str':
p.t = "s"; p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : ''; p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
if(opts.cellHTML) p.h = escapehtml(p.v); if(opts.cellHTML) p.h = escapehtml(p.v);
break; break;
case 'inlineStr': case 'inlineStr':
@ -10676,8 +10685,8 @@ function write_zip_xlsb(wb, opts) {
opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0; opts.Strings = []; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map(); if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; } else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = opts.bookType == "xlsb" ? "bin" : "xml"; var wbext = "bin";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1; var vbafmt = true;
var ct = new_ct(); var ct = new_ct();
fix_write_opts(opts = opts || {}); fix_write_opts(opts = opts || {});
var zip = zip_new(); var zip = zip_new();
@ -10875,10 +10884,10 @@ f = "docProps/app.xml";
carr[1].forEach(function(c) { if(c.T == true) needtc = true; }); carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
}); });
if(needtc) { if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + "." + wbext; cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts)); zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf); ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + "." + wbext, RELS.TCMNT); add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
} }
cf = "xl/comments" + rId + "." + wbext; cf = "xl/comments" + rId + "." + wbext;

250
xlsx.mjs generated

@ -3,7 +3,7 @@
/*exported XLSX */ /*exported XLSX */
/*global process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */ /*global process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
var XLSX = {}; var XLSX = {};
XLSX.version = '0.18.6'; XLSX.version = '0.18.7';
var current_codepage = 1200, current_ansi = 1252; var current_codepage = 1200, current_ansi = 1252;
var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ]; var VALID_ANSI = [ 874, 932, 936, 949, 950, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 10000 ];
@ -3580,15 +3580,19 @@ var rencoding = /*#__PURE__*/evert(encodings);
var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() { var unescapexml/*:StringConv*/ = /*#__PURE__*/(function() {
/* 22.4.2.4 bstr (Basic String) */ /* 22.4.2.4 bstr (Basic String) */
var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig; var encregex = /&(?:quot|apos|gt|lt|amp|#x?([\da-fA-F]+));/ig, coderegex = /_x([\da-fA-F]{4})_/ig;
return function unescapexml(text/*:string*/)/*:string*/ { function raw_unescapexml(text/*:string*/)/*:string*/ {
var s = text + '', i = s.indexOf("<![CDATA["); var s = text + '', i = s.indexOf("<![CDATA[");
if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));}); if(i == -1) return s.replace(encregex, function($$, $1) { return encodings[$$]||String.fromCharCode(parseInt($1,$$.indexOf("x")>-1?16:10))||$$; }).replace(coderegex,function(m,c) {return String.fromCharCode(parseInt(c,16));});
var j = s.indexOf("]]>"); var j = s.indexOf("]]>");
return unescapexml(s.slice(0, i)) + s.slice(i+9,j) + unescapexml(s.slice(j+3)); return raw_unescapexml(s.slice(0, i)) + s.slice(i+9,j) + raw_unescapexml(s.slice(j+3));
}
return function unescapexml(text/*:string*/, xlsx/*:boolean*/) {
var out = raw_unescapexml(text);
return xlsx ? out.replace(/\r\n/g, "\n") : out;
}; };
})(); })();
var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f]/g; var decregex=/[&<>'"]/g, charegex = /[\u0000-\u0008\u000b-\u001f\uFFFE-\uFFFF]/g;
function escapexml(text/*:string*/)/*:string*/{ function escapexml(text/*:string*/)/*:string*/{
var s = text + ''; var s = text + '';
return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";}); return s.replace(decregex, function(y) { return rencoding[y]; }).replace(charegex,function(s) { return "_x" + ("000"+s.charCodeAt(0).toString(16)).slice(-4) + "_";});
@ -3614,12 +3618,14 @@ var xlml_fixstr/*:StringConv*/ = /*#__PURE__*/(function() {
})(); })();
function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); } function xlml_unfixstr(str/*:string*/)/*:string*/ { return str.replace(/(\r\n|[\r\n])/g,"\&#10;"); }
/* note: xsd:boolean valid values: true / 1 / false / 0 */
function parsexmlbool(value/*:any*/)/*:boolean*/ { function parsexmlbool(value/*:any*/)/*:boolean*/ {
switch(value) { switch(value) {
case 1: case true: case '1': case 'true': case 'TRUE': return true; case 1: case true: case '1': case 'true': return true;
/* case '0': case 'false': case 'FALSE':*/ case 0: case false: case '0': case 'false': return false;
default: return false; //default: throw new Error("Invalid xsd:boolean " + value);
} }
return false;
} }
function utf8reada(orig/*:string*/)/*:string*/ { function utf8reada(orig/*:string*/)/*:string*/ {
@ -5980,6 +5986,7 @@ function parse_PropertySet(blob, PIDSI) {
if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i); if(fail) throw new Error("Read Error: Expected address " + Props[i][1] + ' at ' + blob.l + ' :' + i);
} }
if(PIDSI) { if(PIDSI) {
if(Props[i][0] == 0 && Props.length > i+1 && Props[i][1] == Props[i+1][1]) continue; // R9
var piddsi = PIDSI[Props[i][0]]; var piddsi = PIDSI[Props[i][0]];
PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true}); PropH[piddsi.n] = parse_TypedPropertyValue(blob, piddsi.t, {raw:true});
if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4); if(piddsi.p === 'version') PropH[piddsi.n] = String(PropH[piddsi.n] >> 16) + "." + ("0000" + String(PropH[piddsi.n] & 0xFFFF)).slice(-4);
@ -8437,10 +8444,9 @@ var PRN = /*#__PURE__*/(function() {
else sep = guess_sep(str.slice(0,1024)); else sep = guess_sep(str.slice(0,1024));
var R = 0, C = 0, v = 0; var R = 0, C = 0, v = 0;
var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0); var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
str = str.replace(/\r\n/mg, "\n");
var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null; var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
function finish_cell() { function finish_cell() {
var s = str.slice(start, end); var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
var cell = ({}/*:any*/); var cell = ({}/*:any*/);
if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"'); if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
if(s.length === 0) cell.t = 'z'; if(s.length === 0) cell.t = 'z';
@ -8475,7 +8481,11 @@ var PRN = /*#__PURE__*/(function() {
} }
outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) { outer: for(;end < str.length;++end) switch((cc=str.charCodeAt(end))) {
case 0x22: if(startcc === 0x22) instr = !instr; break; case 0x22: if(startcc === 0x22) instr = !instr; break;
case sepcc: case 0x0a: case 0x0d: if(!instr && finish_cell()) break outer; break; case 0x0d:
if(instr) break;
if(str.charCodeAt(end+1) == 0x0a) ++end;
/* falls through */
case sepcc: case 0x0a: if(!instr && finish_cell()) break outer; break;
default: break; default: break;
} }
if(end - start > 0) finish_cell(); if(end - start > 0) finish_cell();
@ -8591,6 +8601,7 @@ var WK_ = /*#__PURE__*/(function() {
var refguess = {s: {r:0, c:0}, e: {r:0, c:0} }; var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
var sheetRows = o.sheetRows || 0; var sheetRows = o.sheetRows || 0;
if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
if(d[2] == 0x00) { if(d[2] == 0x00) {
if(d[3] == 0x08 || d[3] == 0x09) { if(d[3] == 0x08 || d[3] == 0x09) {
if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file"); if(d.length >= 16 && d[14] == 0x05 && d[15] === 0x6c) throw new Error("Unsupported Works 3 for Mac file");
@ -8604,12 +8615,17 @@ var WK_ = /*#__PURE__*/(function() {
o.vers = val; o.vers = val;
if(val >= 0x1000) o.qpro = true; if(val >= 0x1000) o.qpro = true;
break; break;
case 0xFF: /* BOF (works 3+) */
o.vers = val;
o.works = true;
break;
case 0x06: refguess = val; break; /* RANGE */ case 0x06: refguess = val; break; /* RANGE */
case 0xCC: if(val) next_n = val; break; /* SHEETNAMECS */ case 0xCC: if(val) next_n = val; break; /* SHEETNAMECS */
case 0xDE: next_n = val; break; /* SHEETNAMELP */ case 0xDE: next_n = val; break; /* SHEETNAMELP */
case 0x0F: /* LABEL */ case 0x0F: /* LABEL */
case 0x33: /* STRING */ case 0x33: /* STRING */
if(!o.qpro) val[1].v = val[1].v.slice(1); if((!o.qpro && !o.works || RT == 0x33) && val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1);
if(o.works || o.works2) val[1].v = val[1].v.replace(/\r\n/g, "\n");
/* falls through */ /* falls through */
case 0x0D: /* INTEGER */ case 0x0D: /* INTEGER */
case 0x0E: /* NUMBER */ case 0x0E: /* NUMBER */
@ -8643,6 +8659,7 @@ var WK_ = /*#__PURE__*/(function() {
s[val[0].r][val[0].c] = val[1]; s[val[0].r][val[0].c] = val[1];
} else s[encode_cell(val[0])] = val[1]; } else s[encode_cell(val[0])] = val[1];
break; break;
case 0x5405: o.works2 = true; break;
default: default:
}}, o); }}, o);
} else if(d[2] == 0x1A || d[2] == 0x0E) { } else if(d[2] == 0x1A || d[2] == 0x0E) {
@ -8651,7 +8668,9 @@ var WK_ = /*#__PURE__*/(function() {
lotushopper(d, function(val, R, RT) { switch(RT) { lotushopper(d, function(val, R, RT) { switch(RT) {
case 0xCC: n = val; break; /* SHEETNAMECS */ case 0xCC: n = val; break; /* SHEETNAMECS */
case 0x16: /* LABEL16 */ case 0x16: /* LABEL16 */
val[1].v = val[1].v.slice(1); if(val[1].v.charCodeAt(0) < 0x30) val[1].v = val[1].v.slice(1);
// TODO: R9 appears to encode control codes this way -- verify against other versions
val[1].v = val[1].v.replace(/\x0F./g, function($$) { return String.fromCharCode($$.charCodeAt(1) - 0x20); }).replace(/\r\n/g, "\n");
/* falls through */ /* falls through */
case 0x17: /* NUMBER17 */ case 0x17: /* NUMBER17 */
case 0x18: /* NUMBER18 */ case 0x18: /* NUMBER18 */
@ -8846,6 +8865,9 @@ var WK_ = /*#__PURE__*/(function() {
o[3] = blob.read_shift(1); o[3] = blob.read_shift(1);
o[0].r = blob.read_shift(2); o[0].r = blob.read_shift(2);
blob.l+=2; blob.l+=2;
} else if(opts.works) { // TODO: verify with more complex works3-4 examples
o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
o[2] = blob.read_shift(2);
} else { } else {
o[2] = blob.read_shift(1); o[2] = blob.read_shift(1);
o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2); o[0].c = blob.read_shift(2); o[0].r = blob.read_shift(2);
@ -8881,6 +8903,18 @@ var WK_ = /*#__PURE__*/(function() {
o.write_shift(1, 0); o.write_shift(1, 0);
return o; return o;
} }
function parse_STRING(blob, length, opts) {
var tgt = blob.l + length;
var o = parse_cell(blob, length, opts);
o[1].t = 's';
if(opts.vers == 0x5120) {
var len = blob.read_shift(1);
o[1].v = blob.read_shift(len, 'utf8');
return o;
}
o[1].v = blob.read_shift(tgt - blob.l, 'cstr');
return o;
}
function parse_INTEGER(blob, length, opts) { function parse_INTEGER(blob, length, opts) {
var o = parse_cell(blob, length, opts); var o = parse_cell(blob, length, opts);
@ -8939,6 +8973,7 @@ var WK_ = /*#__PURE__*/(function() {
0x33: ["FALSE", 0], 0x33: ["FALSE", 0],
0x34: ["TRUE", 0], 0x34: ["TRUE", 0],
0x46: ["LEN", 1], 0x46: ["LEN", 1],
0x4A: ["CHAR", 1],
0x50: ["SUM", 69], 0x50: ["SUM", 69],
0x51: ["AVERAGEA", 69], 0x51: ["AVERAGEA", 69],
0x52: ["COUNTA", 69], 0x52: ["COUNTA", 69],
@ -9129,8 +9164,8 @@ var WK_ = /*#__PURE__*/(function() {
} }
function parse_FORMULA_28(blob, length) { function parse_FORMULA_28(blob, length) {
var o = parse_NUMBER_27(blob, 14); var o = parse_NUMBER_27(blob, 12);
blob.l += length - 10; /* TODO: formula */ blob.l += length - 12; /* TODO: formula */
return o; return o;
} }
@ -9220,7 +9255,7 @@ var WK_ = /*#__PURE__*/(function() {
/*::[*/0x0030/*::]*/: { n:"UNFORMATTED" }, /*::[*/0x0030/*::]*/: { n:"UNFORMATTED" },
/*::[*/0x0031/*::]*/: { n:"CURSORW12" }, /*::[*/0x0031/*::]*/: { n:"CURSORW12" },
/*::[*/0x0032/*::]*/: { n:"WINDOW" }, /*::[*/0x0032/*::]*/: { n:"WINDOW" },
/*::[*/0x0033/*::]*/: { n:"STRING", f:parse_LABEL }, /*::[*/0x0033/*::]*/: { n:"STRING", f:parse_STRING },
/*::[*/0x0037/*::]*/: { n:"PASSWORD" }, /*::[*/0x0037/*::]*/: { n:"PASSWORD" },
/*::[*/0x0038/*::]*/: { n:"LOCKED" }, /*::[*/0x0038/*::]*/: { n:"LOCKED" },
/*::[*/0x003C/*::]*/: { n:"QUERY" }, /*::[*/0x003C/*::]*/: { n:"QUERY" },
@ -9244,6 +9279,7 @@ var WK_ = /*#__PURE__*/(function() {
/*::[*/0x0069/*::]*/: { n:"MRANGES??" }, /*::[*/0x0069/*::]*/: { n:"MRANGES??" },
/*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS }, /*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
/*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP }, /*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
/*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 },
/*::[*/0xFFFF/*::]*/: { n:"" } /*::[*/0xFFFF/*::]*/: { n:"" }
}; };
@ -9372,6 +9408,144 @@ var WK_ = /*#__PURE__*/(function() {
/*::[*/0x6F44/*::]*/: { n:"??" }, /*::[*/0x6F44/*::]*/: { n:"??" },
/*::[*/0xFFFF/*::]*/: { n:"" } /*::[*/0xFFFF/*::]*/: { n:"" }
}; };
/* QPW uses a different set of record types */
function qpw_to_workbook_buf(d, opts)/*:Workbook*/ {
prep_blob(d, 0);
var o = opts || {};
if(DENSE != null && o.dense == null) o.dense = DENSE;
var s/*:Worksheet*/ = ((o.dense ? [] : {})/*:any*/);
var SST = [], sname = "", formulae = [];
var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
var cnt = 0, type = 0, C = 0, R = 0;
var wb = { SheetNames: [], Sheets: {} };
outer: while(d.l < d.length) {
var RT = d.read_shift(2), length = d.read_shift(2);
var p = d.slice(d.l, d.l + length);
prep_blob(p, 0);
switch(RT) {
case 0x01: /* BOF */
if(p.read_shift(4) != 0x39575051) throw "Bad QPW9 BOF!";
break;
case 0x02: /* EOF */ break outer;
/* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TSTable */
case 0x0401: /* BON */ break;
case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
case 0x0407: { /* SST */
p.l += 12;
while(p.l < p.length) {
cnt = p.read_shift(2);
type = p.read_shift(1);
SST.push(p.read_shift(cnt, 'cstr'));
}
} break;
case 0x0408: { /* FORMULAE */
//p.l += 12;
//while(p.l < p.length) {
// cnt = p.read_shift(2);
// formulae.push(p.slice(p.l, p.l + cnt + 1)); p.l += cnt + 1;
//}
} break;
case 0x0601: { /* BOS */
var sidx = p.read_shift(2);
s = ((o.dense ? [] : {})/*:any*/);
range.s.c = p.read_shift(2);
range.e.c = p.read_shift(2);
range.s.r = p.read_shift(4);
range.e.r = p.read_shift(4);
p.l += 4;
if(p.l + 2 < p.length) {
cnt = p.read_shift(2);
type = p.read_shift(1);
sname = cnt == 0 ? "" : p.read_shift(cnt, 'cstr');
}
if(!sname) sname = XLSX.utils.encode_col(sidx);
/* TODO: backfill empty sheets */
} break;
case 0x0602: { /* EOS */
/* NOTE: QP valid range A1:IV1000000 */
if(range.s.c > 0xFF || range.s.r > 999999) break;
if(range.e.c < range.s.c) range.e.c = range.s.c;
if(range.e.r < range.s.r) range.e.r = range.s.r;
s["!ref"] = encode_range(range);
book_append_sheet(wb, s, sname); // TODO: a barrel roll
} break;
case 0x0A01: { /* COL (like XLS Row, modulo the layout transposition) */
C = p.read_shift(2);
if(range.e.c < C) range.e.c = C;
if(range.s.c > C) range.s.c = C;
R = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
R = p.read_shift(4);
if(range.e.r < R) range.e.r = R;
} break;
case 0x0C01: { /* MulCells (like XLS MulRK, but takes advantage of common column data patterns) */
R = p.read_shift(4), cnt = p.read_shift(4);
if(range.s.r > R) range.s.r = R;
if(range.e.r < R + cnt - 1) range.e.r = R + cnt - 1;
while(p.l < p.length) {
var cell = { t: "z" };
var flags = p.read_shift(1);
if(flags & 0x80) p.l += 2;
var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
switch(flags & 0x1F) {
case 1: break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
case 8: cell = { t: "n", v: p.read_shift(8, 'f') }; p.l += 2; /* cell.f = formulae[p.read_shift(4)]; */ p.l += 4; break;
default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
}
var delta = 0;
if(flags & 0x20) switch(flags & 0x1F) {
case 2: delta = p.read_shift(2); break;
case 3: delta = p.read_shift(2, 'i'); break;
case 7: delta = p.read_shift(2); break;
default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(Array.isArray(s)) {
if(!s[R]) s[R] = [];
s[R][C] = cell;
} else s[encode_cell({r:R, c:C})] = cell;
}
++R; --cnt;
while(mul-- > 0 && cnt >= 0) {
if(flags & 0x20) switch(flags & 0x1F) {
case 2: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; break;
case 3: cell = { t: "n", v: (cell.v + delta) & 0xFFFF }; if(cell.v > 0x7FFF) cell.v -= 0x10000; break;
case 7: cell = { t: "s", v: SST[type = (type + delta) >>> 0] }; break;
default: throw "Cannot apply delta for QPW cell type " + (flags & 0x1F);
} else switch(flags & 0x1F) {
case 1: cell = { t: "z" }; break;
case 2: cell = { t: "n", v: p.read_shift(2) }; break;
case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
default: throw "Cannot apply repeat for QPW cell type " + (flags & 0x1F);
}
if(!(!o.sheetStubs && cell.t == "z")) {
if(Array.isArray(s)) {
if(!s[R]) s[R] = [];
s[R][C] = cell;
} else s[encode_cell({r:R, c:C})] = cell;
}
++R; --cnt;
}
}
} break;
default: break;
}
d.l += length;
}
return wb;
}
return { return {
sheet_to_wk1: sheet_to_wk1, sheet_to_wk1: sheet_to_wk1,
book_to_wk3: book_to_wk3, book_to_wk3: book_to_wk3,
@ -9558,14 +9732,14 @@ function parse_si(x, opts) {
/* 18.4.12 t ST_Xstring (Plaintext String) */ /* 18.4.12 t ST_Xstring (Plaintext String) */
// TODO: is whitespace actually valid here? // TODO: is whitespace actually valid here?
if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) { if(x.match(/^\s*<(?:\w+:)?t[^>]*>/)) {
z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||"")); z.t = unescapexml(utf8read(x.slice(x.indexOf(">")+1).split(/<\/(?:\w+:)?t>/)[0]||""), true);
z.r = utf8read(x); z.r = utf8read(x);
if(html) z.h = escapehtml(z.t); if(html) z.h = escapehtml(z.t);
} }
/* 18.4.4 r CT_RElt (Rich Text Run) */ /* 18.4.4 r CT_RElt (Rich Text Run) */
else if((/*y = */x.match(sirregex))) { else if((/*y = */x.match(sirregex))) {
z.r = utf8read(x); z.r = utf8read(x);
z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,""))); z.t = unescapexml(utf8read((x.replace(sirphregex, '').match(sitregex)||[]).join("").replace(tagregex,"")), true);
if(html) z.h = rs_to_html(parse_rs(z.r)); if(html) z.h = rs_to_html(parse_rs(z.r));
} }
/* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */ /* 18.4.3 phoneticPr CT_PhoneticPr (TODO: needed for Asian support) */
@ -9998,27 +10172,33 @@ var RTF = /*#__PURE__*/(function() {
var o = opts || {}; var o = opts || {};
var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/); var ws/*:Worksheet*/ = o.dense ? ([]/*:any*/) : ({}/*:any*/);
var rows = str.match(/\\trowd.*?\\row\b/g); var rows = str.match(/\\trowd[\s\S]*?\\row\b/g);
if(!rows.length) throw new Error("RTF missing table"); if(!rows.length) throw new Error("RTF missing table");
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:rows.length - 1}}/*:any*/); var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:rows.length - 1}}/*:any*/);
rows.forEach(function(rowtf, R) { rows.forEach(function(rowtf, R) {
if(Array.isArray(ws)) ws[R] = []; if(Array.isArray(ws)) ws[R] = [];
var rtfre = /\\\w+\b/g; var rtfre = /\\[\w\-]+\b/g;
var last_index = 0; var last_index = 0;
var res; var res;
var C = -1; var C = -1;
var payload = [];
while((res = rtfre.exec(rowtf))) { while((res = rtfre.exec(rowtf))) {
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
if(data.charCodeAt(0) == 0x20) data = data.slice(1);
if(data.length) payload.push(data);
switch(res[0]) { switch(res[0]) {
case "\\cell": case "\\cell":
var data = rowtf.slice(last_index, rtfre.lastIndex - res[0].length);
if(data[0] == " ") data = data.slice(1);
++C; ++C;
if(data.length) { if(payload.length) {
// TODO: value parsing, including codepage adjustments // TODO: value parsing, including codepage adjustments
var cell = {v: data, t:"s"}; var cell = {v: payload.join(""), t:"s"};
if(Array.isArray(ws)) ws[R][C] = cell; if(Array.isArray(ws)) ws[R][C] = cell;
else ws[encode_cell({r:R, c:C})] = cell; else ws[encode_cell({r:R, c:C})] = cell;
} }
payload = [];
break;
case "\\par": // NOTE: Excel serializes both "\r" and "\n" as "\\par"
payload.push("\n");
break; break;
} }
last_index = rtfre.lastIndex; last_index = rtfre.lastIndex;
@ -10044,7 +10224,7 @@ var RTF = /*#__PURE__*/(function() {
var coord = encode_cell({r:R,c:C}); var coord = encode_cell({r:R,c:C});
cell = dense ? (ws[R]||[])[C]: ws[coord]; cell = dense ? (ws[R]||[])[C]: ws[coord];
if(!cell || cell.v == null && (!cell.f || cell.F)) continue; if(!cell || cell.v == null && (!cell.f || cell.F)) continue;
o.push(" " + (cell.w || (format_cell(cell), cell.w))); o.push(" " + (cell.w || (format_cell(cell), cell.w)).replace(/[\r\n]/g, "\\par "));
o.push("\\cell"); o.push("\\cell");
} }
o.push("\\pard\\intbl\\row"); o.push("\\pard\\intbl\\row");
@ -14849,7 +15029,7 @@ function parse_ws_xml_sheetviews(data, wb/*:WBWBProps*/) {
// $FlowIgnore // $FlowIgnore
if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale; if(+tag.zoomScale) wb.Views[i].zoom = +tag.zoomScale;
// $FlowIgnore // $FlowIgnore
if(parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true; if(tag.rightToLeft && parsexmlbool(tag.rightToLeft)) wb.Views[i].RTL = true;
}); });
} }
function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ { function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
@ -14941,7 +15121,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.sheetRows && opts.sheetRows < tagr) continue; if(opts.sheetRows && opts.sheetRows < tagr) continue;
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -14958,7 +15138,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts && opts.cellStyles) { if(opts && opts.cellStyles) {
rowobj = {}; rowrite = false; rowobj = {}; rowrite = false;
if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); } if(tag.ht) { rowrite = true; rowobj.hpt = parseFloat(tag.ht); rowobj.hpx = pt2px(rowobj.hpt); }
if(tag.hidden == "1") { rowrite = true; rowobj.hidden = true; } if(tag.hidden && parsexmlbool(tag.hidden)) { rowrite = true; rowobj.hidden = true; }
if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; } if(tag.outlineLevel != null) { rowrite = true; rowobj.level = +tag.outlineLevel; }
if(rowrite) rows[tagr-1] = rowobj; if(rowrite) rows[tagr-1] = rowobj;
} }
@ -14991,7 +15171,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
if(opts.cellFormula) { if(opts.cellFormula) {
if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') { if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
/* TODO: match against XLSXFutureFunctions */ /* TODO: match against XLSXFutureFunctions */
p.f=unescapexml(utf8read(cref[1])).replace(/\r\n/g, "\n"); p.f=unescapexml(utf8read(cref[1]), true);
if(!opts.xlfn) p.f = _xlfn(p.f); if(!opts.xlfn) p.f = _xlfn(p.f);
if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) { if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
p.F = (d.match(refregex)||[])[1]; p.F = (d.match(refregex)||[])[1];
@ -15045,7 +15225,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
break; break;
case 'str': case 'str':
p.t = "s"; p.t = "s";
p.v = (p.v!=null) ? utf8read(p.v) : ''; p.v = (p.v!=null) ? unescapexml(utf8read(p.v), true) : '';
if(opts.cellHTML) p.h = escapehtml(p.v); if(opts.cellHTML) p.h = escapehtml(p.v);
break; break;
case 'inlineStr': case 'inlineStr':
@ -16061,6 +16241,8 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
/* TODO: something useful -- this is a stub */ /* TODO: something useful -- this is a stub */
function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ { function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
var o/*:any*/ = ({r:R, c:C}/*:any*/);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
if(cell.v === undefined) return false; if(cell.v === undefined) return false;
var vv = ""; var vv = "";
switch(cell.t) { switch(cell.t) {
@ -16074,11 +16256,9 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
case 'n': case 'e': vv = ''+cell.v; break; case 'n': case 'e': vv = ''+cell.v; break;
default: vv = cell.v; break; default: vv = cell.v; break;
} }
var o/*:any*/ = ({r:R, c:C}/*:any*/);
/* TODO: cell style */ /* TODO: cell style */
o.s = get_cell_style(opts.cellXfs, cell, opts); o.s = get_cell_style(opts.cellXfs, cell, opts);
if(cell.l) ws['!links'].push([encode_cell(o), cell.l]); if(cell.l) ws['!links'].push([encode_cell(o), cell.l]);
if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
switch(cell.t) { switch(cell.t) {
case 's': case 'str': case 's': case 'str':
if(opts.bookSST) { if(opts.bookSST) {
@ -23500,8 +23680,8 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0; opts.Strings = /*::((*/[]/*:: :any):SST)*/; opts.Strings.Count = 0; opts.Strings.Unique = 0;
if(browser_has_Map) opts.revStrings = new Map(); if(browser_has_Map) opts.revStrings = new Map();
else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; } else { opts.revStrings = {}; opts.revStrings.foo = []; delete opts.revStrings.foo; }
var wbext = opts.bookType == "xlsb" ? "bin" : "xml"; var wbext = "bin";
var vbafmt = VBAFMTS.indexOf(opts.bookType) > -1; var vbafmt = true;
var ct = new_ct(); var ct = new_ct();
fix_write_opts(opts = opts || {}); fix_write_opts(opts = opts || {});
var zip = zip_new(); var zip = zip_new();
@ -23701,10 +23881,10 @@ function write_zip_xlsx(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
carr[1].forEach(function(c) { if(c.T == true) needtc = true; }); carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
}); });
if(needtc) { if(needtc) {
cf = "xl/threadedComments/threadedComment" + rId + "." + wbext; cf = "xl/threadedComments/threadedComment" + rId + ".xml";
zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts)); zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
ct.threadedcomments.push(cf); ct.threadedcomments.push(cf);
add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + "." + wbext, RELS.TCMNT); add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
} }
cf = "xl/comments" + rId + "." + wbext; cf = "xl/comments" + rId + "." + wbext;