@cosmotech/core 1.11.5 → 1.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -630,7 +630,7 @@ var CSVUtils = {
630
630
  /*exported XLSX */
631
631
  /*global process:false, Buffer:false, ArrayBuffer:false, DataView:false, Deno:false */
632
632
  var XLSX = {};
633
- XLSX.version = '0.19.3';
633
+ XLSX.version = '0.20.0';
634
634
  var current_codepage = 1200;
635
635
  /*:: declare var cptable:any; */
636
636
  /*global cptable:true, window */
@@ -743,6 +743,26 @@ function Base64_encode_pass(input) {
743
743
  }
744
744
  return o;
745
745
  }
746
+ function Base64_encode_arr(input) {
747
+ var o = "";
748
+ var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
749
+ for (var i = 0; i < input.length; ) {
750
+ c1 = input[i++];
751
+ e1 = c1 >> 2;
752
+ c2 = input[i++];
753
+ e2 = (c1 & 3) << 4 | c2 >> 4;
754
+ c3 = input[i++];
755
+ e3 = (c2 & 15) << 2 | c3 >> 6;
756
+ e4 = c3 & 63;
757
+ if (isNaN(c2)) {
758
+ e3 = e4 = 64;
759
+ } else if (isNaN(c3)) {
760
+ e4 = 64;
761
+ }
762
+ o += Base64_map.charAt(e1) + Base64_map.charAt(e2) + Base64_map.charAt(e3) + Base64_map.charAt(e4);
763
+ }
764
+ return o;
765
+ }
746
766
  function Base64_decode(input) {
747
767
  var o = "";
748
768
  var c1 = 0, c2 = 0, c3 = 0, e1 = 0, e2 = 0, e3 = 0, e4 = 0;
@@ -1102,15 +1122,6 @@ function SSF_parse_date_code(v/*:number*/,opts/*:?any*/,b2/*:?boolean*/) {
1102
1122
  out.q = dow;
1103
1123
  return out;
1104
1124
  }
1105
- var SSFbasedate = /*#__PURE__*/new Date(1899, 11, 31, 0, 0, 0);
1106
- var SSFdnthresh = /*#__PURE__*/SSFbasedate.getTime();
1107
- var SSFbase1904 = /*#__PURE__*/new Date(1900, 2, 1, 0, 0, 0);
1108
- function datenum_local(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
1109
- var epoch = /*#__PURE__*/v.getTime();
1110
- if(date1904) epoch -= 1461*24*60*60*1000;
1111
- else if(v >= SSFbase1904) epoch += 24*60*60*1000;
1112
- return (epoch - (SSFdnthresh + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/SSFbasedate.getTimezoneOffset()) * 60000)) / (24 * 60 * 60 * 1000);
1113
- }
1114
1125
  /* ECMA-376 18.8.30 numFmt*/
1115
1126
  /* Note: `toPrecision` uses standard form when prec > E and E >= -6 */
1116
1127
  /* exponent >= -9 and <= 9 */
@@ -1168,7 +1179,7 @@ function SSF_general(v/*:any*/, opts/*:any*/) {
1168
1179
  case 'undefined': return "";
1169
1180
  case 'object':
1170
1181
  if(v == null) return "";
1171
- if(v instanceof Date) return SSF_format(14, datenum_local(v, opts && opts.date1904), opts);
1182
+ if(v instanceof Date) return SSF_format(14, datenum(v, opts && opts.date1904), opts);
1172
1183
  }
1173
1184
  throw new Error("unsupported value in General format: " + v);
1174
1185
  }
@@ -1854,7 +1865,7 @@ function SSF_format(fmt/*:string|number*/,v/*:any*/,o/*:?any*/) {
1854
1865
  break;
1855
1866
  }
1856
1867
  if(SSF_isgeneral(sfmt,0)) return SSF_general(v, o);
1857
- if(v instanceof Date) v = datenum_local(v, o.date1904);
1868
+ if(v instanceof Date) v = datenum(v, o.date1904);
1858
1869
  var f = choose_fmt(sfmt, v);
1859
1870
  if(SSF_isgeneral(f[1])) return SSF_general(v, o);
1860
1871
  if(v === true) v = "TRUE"; else if(v === false) v = "FALSE";
@@ -1931,6 +1942,7 @@ var dateNFregex = /[dD]+|[mM]+|[yYeE]+|[Hh]+|[Ss]+/g;
1931
1942
  function dateNF_regex(dateNF/*:string|number*/)/*:RegExp*/ {
1932
1943
  var fmt = typeof dateNF == "number" ? table_fmt[dateNF] : dateNF;
1933
1944
  fmt = fmt.replace(dateNFregex, "(\\d+)");
1945
+ dateNFregex.lastIndex = 0;
1934
1946
  return new RegExp("^" + fmt + "$");
1935
1947
  }
1936
1948
  function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/*:string*/ {
@@ -1943,6 +1955,7 @@ function dateNF_fix(str/*:string*/, dateNF/*:string*/, match/*:Array<string>*/)/
1943
1955
  case 'm': if(H >= 0) M = v; else m = v; break;
1944
1956
  }
1945
1957
  });
1958
+ dateNFregex.lastIndex = 0;
1946
1959
  if(S >= 0 && M == -1 && m >= 0) { M = m; m = -1; }
1947
1960
  var datestr = (("" + (Y>=0?Y: new Date().getFullYear())).slice(-4) + "-" + ("00" + (m>=1?m:1)).slice(-2) + "-" + ("00" + (d>=1?d:1)).slice(-2));
1948
1961
  if(datestr.length == 7) datestr = "0" + datestr;
@@ -3855,7 +3868,7 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
3855
3868
  /*:: declare var chrome: any; */
3856
3869
  if(typeof chrome === 'object' && typeof (chrome.downloads||{}).download == "function") {
3857
3870
  if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
3858
- return chrome.downloads.download({ url: url, filename: fname, saveAs: true});
3871
+ return chrome.downloads.download({ url: url, filename: fname, saveAs: true });
3859
3872
  }
3860
3873
  var a = document.createElement("a");
3861
3874
  if(a.download != null) {
@@ -3865,6 +3878,10 @@ function write_dl(fname/*:string*/, payload/*:any*/, enc/*:?string*/) {
3865
3878
  if(URL.revokeObjectURL && typeof setTimeout !== 'undefined') setTimeout(function() { URL.revokeObjectURL(url); }, 60000);
3866
3879
  return url;
3867
3880
  }
3881
+ } else if(typeof URL !== 'undefined' && !URL.createObjectURL && typeof chrome === 'object') {
3882
+ /* manifest v3 extensions -- no URL.createObjectURL */
3883
+ var b64 = "data:application/octet-stream;base64," + Base64_encode_arr(new Uint8Array(blobify(data)));
3884
+ return chrome.downloads.download({ url: b64, filename: fname, saveAs: true });
3868
3885
  }
3869
3886
  }
3870
3887
  // $FlowIgnore
@@ -3922,22 +3939,19 @@ function evert_arr(obj/*:any*/)/*:EvertArrType*/ {
3922
3939
  return o;
3923
3940
  }
3924
3941
 
3925
- var basedate = /*#__PURE__*/new Date(1899, 11, 30, 0, 0, 0); // 2209161600000
3942
+ var dnthresh = /*#__PURE__*/Date.UTC(1899, 11, 30, 0, 0, 0); // -2209161600000
3943
+ var dnthresh1 = /*#__PURE__*/Date.UTC(1899, 11, 31, 0, 0, 0); // -2209075200000
3944
+ var dnthresh2 = /*#__PURE__*/Date.UTC(1904, 0, 1, 0, 0, 0); // -2209075200000
3926
3945
  function datenum(v/*:Date*/, date1904/*:?boolean*/)/*:number*/ {
3927
3946
  var epoch = /*#__PURE__*/v.getTime();
3928
- if(date1904) epoch -= 1462*24*60*60*1000;
3929
- var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/v.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
3930
- return (epoch - dnthresh) / (24 * 60 * 60 * 1000);
3931
- }
3932
- var refdate = /*#__PURE__*/new Date();
3933
- var dnthresh = /*#__PURE__*/basedate.getTime() + (/*#__PURE__*/refdate.getTimezoneOffset() - /*#__PURE__*/basedate.getTimezoneOffset()) * 60000;
3934
- var refoffset = /*#__PURE__*/refdate.getTimezoneOffset();
3935
- function numdate(v/*:number*/)/*:Date*/ {
3947
+ var res = (epoch - dnthresh) / (24 * 60 * 60 * 1000);
3948
+ if(date1904) { res -= 1462; return res < -1402 ? res - 1 : res; }
3949
+ return res < 60 ? res - 1 : res;
3950
+ }
3951
+ function numdate(v/*:number*/)/*:Date|number*/ {
3952
+ if(v >= 60 && v < 61) return v;
3936
3953
  var out = new Date();
3937
- out.setTime(v * 24 * 60 * 60 * 1000 + dnthresh);
3938
- if (out.getTimezoneOffset() !== refoffset) {
3939
- out.setTime(out.getTime() + (out.getTimezoneOffset() - refoffset) * 60000);
3940
- }
3954
+ out.setTime((v>60 ? v : (v+1)) * 24 * 60 * 60 * 1000 + dnthresh);
3941
3955
  return out;
3942
3956
  }
3943
3957
 
@@ -3966,28 +3980,22 @@ function parse_isodur(s) {
3966
3980
  return sec;
3967
3981
  }
3968
3982
 
3969
- var good_pd_date_1 = /*#__PURE__*/new Date('2017-02-19T19:06:09.000Z');
3970
- var good_pd_date = /*#__PURE__*/isNaN(/*#__PURE__*/good_pd_date_1.getFullYear()) ? /*#__PURE__*/new Date('2/19/17') : good_pd_date_1;
3971
- var good_pd = /*#__PURE__*/good_pd_date.getFullYear() == 2017;
3972
- /* parses a date as a local date */
3973
- function parseDate(str/*:string|Date*/, fixdate/*:?number*/)/*:Date*/ {
3974
- var d = new Date(str);
3975
- if(good_pd) {
3976
- /*:: if(fixdate == null) fixdate = 0; */
3977
- if(fixdate > 0) d.setTime(d.getTime() + d.getTimezoneOffset() * 60 * 1000);
3978
- else if(fixdate < 0) d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000);
3979
- return d;
3980
- }
3983
+ /* Blame https://bugs.chromium.org/p/v8/issues/detail?id=7863 for the regexide */
3984
+ var pdre1 = /^(\d+):(\d+)(:\d+)?(\.\d+)?$/; // HH:MM[:SS[.UUU]]
3985
+ var pdre2 = /^(\d+)-(\d+)-(\d+)$/; // YYYY-mm-dd
3986
+ var pdre3 = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)?(\.\d+)?$/; // YYYY-mm-dd(T or space)HH:MM[:SS[.UUU]], sans "Z"
3987
+ /* parses a date string as a UTC date */
3988
+ function parseDate(str/*:string*/, date1904/*:boolean*/)/*:Date*/ {
3981
3989
  if(str instanceof Date) return str;
3982
- if(good_pd_date.getFullYear() == 1917 && !isNaN(d.getFullYear())) {
3983
- var s = d.getFullYear();
3984
- if(str.indexOf("" + s) > -1) return d;
3985
- d.setFullYear(d.getFullYear() + 100); return d;
3986
- }
3987
- var n = str.match(/\d+/g)||["2017","2","19","0","0","0"];
3988
- var out = new Date(+n[0], +n[1] - 1, +n[2], (+n[3]||0), (+n[4]||0), (+n[5]||0));
3989
- if(str.indexOf("Z") > -1) out = new Date(out.getTime() - out.getTimezoneOffset() * 60 * 1000);
3990
- return out;
3990
+ var m = str.match(pdre1);
3991
+ if(m) return new Date((date1904 ? dnthresh2 : dnthresh1) + ((parseInt(m[1], 10)*60 + parseInt(m[2], 10))*60 + (m[3] ? parseInt(m[3].slice(1), 10) : 0))*1000 + (m[4] ? parseInt((m[4]+"000").slice(1,4), 10) : 0));
3992
+ m = str.match(pdre2);
3993
+ if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], 0, 0, 0, 0));
3994
+ /* TODO: 1900-02-29T00:00:00.000 should return a flag to treat as a date code (affects xlml) */
3995
+ m = str.match(pdre3);
3996
+ if(m) return new Date(Date.UTC(+m[1], +m[2]-1, +m[3], +m[4], +m[5], ((m[6] && parseInt(m[6].slice(1), 10))|| 0), ((m[7] && parseInt(m[7].slice(1), 10))||0)));
3997
+ var d = new Date(str);
3998
+ return d;
3991
3999
  }
3992
4000
 
3993
4001
  function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
@@ -4018,8 +4026,18 @@ function cc2str(arr/*:Array<number>*/, debomit)/*:string*/ {
4018
4026
  return new TextDecoder("latin1").decode(arr).replace(/[€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ]/g, function(c) { return rev[c] || c; });
4019
4027
  } catch(e) {}
4020
4028
 
4021
- var o = [];
4022
- for(var i = 0; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
4029
+ var o = [], i = 0;
4030
+ // this cascade is for the browsers and runtimes of antiquity (and for modern runtimes that lack TextEncoder)
4031
+ try {
4032
+ for(i = 0; i < arr.length - 65536; i+=65536) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 65536)));
4033
+ o.push(String.fromCharCode.apply(0, arr.slice(i)));
4034
+ } catch(e) { try {
4035
+ for(; i < arr.length - 16384; i+=16384) o.push(String.fromCharCode.apply(0, arr.slice(i, i + 16384)));
4036
+ o.push(String.fromCharCode.apply(0, arr.slice(i)));
4037
+ } catch(e) {
4038
+ for(; i != arr.length; ++i) o.push(String.fromCharCode(arr[i]));
4039
+ }
4040
+ }
4023
4041
  return o.join("");
4024
4042
  }
4025
4043
 
@@ -4049,32 +4067,49 @@ function fuzzynum(s/*:string*/)/*:number*/ {
4049
4067
 
4050
4068
  /* NOTE: Chrome rejects bare times like 1:23 PM */
4051
4069
  var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/;
4070
+ var FDRE2 = /^([01]?\d|2[0-3])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))$/;
4071
+ var FDISO = /^(\d+)-(\d+)-(\d+)[T ](\d+):(\d+)(:\d+)(\.\d+)?[Z]?$/; // YYYY-mm-dd(T or space)HH:MM:SS[.UUU][Z]
4052
4072
 
4073
+ /* TODO: 1904 adjustment */
4074
+ var utc_append_works = new Date("6/9/69 00:00 UTC").valueOf() == -17798400000;
4053
4075
  function fuzzytime1(M) /*:Date*/ {
4054
- /* TODO: 1904 adjustment, keep in sync with base date */
4055
- if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0);
4056
- if(M[3]) {
4057
- if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000);
4058
- else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000);
4059
- }
4060
- else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0);
4061
- else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0);
4076
+ if(!M[2]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0));
4077
+ if(M[3]) {
4078
+ if(M[4]) return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000));
4079
+ else return new Date(Date.UTC(1899,11,31,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000));
4080
+ }
4081
+ else if(M[5]) return new Date(Date.UTC(1899,11,31, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
4082
+ else return new Date(Date.UTC(1899,11,31,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0));
4083
+ }
4084
+ function fuzzytime2(M) /*:Date*/ {
4085
+ if(!M[2]) return new Date(Date.UTC(1899,11,31,+M[1], 0, 0, 0));
4086
+ if(M[3]) {
4087
+ if(M[4]) return new Date(Date.UTC(1899,11,31,+M[1], +M[2], +M[4], parseFloat(M[3])*1000));
4088
+ else return new Date(Date.UTC(1899,11,31,0, +M[1], +M[2], parseFloat(M[3])*1000));
4089
+ }
4090
+ else if(M[5]) return new Date(Date.UTC(1899,11,31, +M[1], +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0));
4091
+ else return new Date(Date.UTC(1899,11,31,+M[1], +M[2], 0, 0));
4062
4092
  }
4063
4093
  var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
4064
4094
  function fuzzydate(s/*:string*/)/*:Date*/ {
4095
+ // See issue 2863 -- this is technically not supported in Excel but is otherwise useful
4096
+ if(FDISO.test(s)) return s.indexOf("Z") == -1 ? local_to_utc(new Date(s)) : new Date(s);
4065
4097
  var lower = s.toLowerCase();
4066
4098
  var lnos = lower.replace(/\s+/g, " ").trim();
4067
4099
  var M = lnos.match(FDRE1);
4068
4100
  if(M) return fuzzytime1(M);
4069
-
4070
- var o = new Date(s), n = new Date(NaN);
4101
+ M = lnos.match(FDRE2);
4102
+ if(M) return fuzzytime2(M);
4103
+ M = lnos.match(pdre3);
4104
+ if(M) return new Date(Date.UTC(+M[1], +M[2]-1, +M[3], +M[4], +M[5], ((M[6] && parseInt(M[6].slice(1), 10))|| 0), ((M[7] && parseInt(M[7].slice(1), 10))||0)));
4105
+ var o = new Date(utc_append_works && s.indexOf("UTC") == -1 ? s + " UTC": s), n = new Date(NaN);
4071
4106
  var y = o.getYear(); o.getMonth(); var d = o.getDate();
4072
4107
  if(isNaN(d)) return n;
4073
4108
  if(lower.match(/jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec/)) {
4074
4109
  lower = lower.replace(/[^a-z]/g,"").replace(/([^a-z]|^)[ap]m?([^a-z]|$)/,"");
4075
4110
  if(lower.length > 3 && lower_months.indexOf(lower) == -1) return n;
4076
4111
  } else if(lower.replace(/[ap]m?/, "").match(/[a-z]/)) return n;
4077
- if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\]/)) return n;
4112
+ if(y < 0 || y > 8099 || s.match(/[^-0-9:,\/\\\ ]/)) return n;
4078
4113
  return o;
4079
4114
  }
4080
4115
 
@@ -4087,6 +4122,13 @@ var split_regex = /*#__PURE__*/(function() {
4087
4122
  return o;
4088
4123
  };
4089
4124
  })();
4125
+
4126
+ function utc_to_local(utc) {
4127
+ return new Date(utc.getUTCFullYear(), utc.getUTCMonth(), utc.getUTCDate(), utc.getUTCHours(), utc.getUTCMinutes(), utc.getUTCSeconds(), utc.getUTCMilliseconds());
4128
+ }
4129
+ function local_to_utc(local) {
4130
+ return new Date(Date.UTC(local.getFullYear(), local.getMonth(), local.getDate(), local.getHours(), local.getMinutes(), local.getSeconds(), local.getMilliseconds()));
4131
+ }
4090
4132
  function getdatastr(data)/*:?string*/ {
4091
4133
  if(!data) return null;
4092
4134
  if(data.content && data.type) return cc2str(data.content, true);
@@ -4983,6 +5025,7 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
4983
5025
  else if(typeof cell.v === 'boolean') cell.t = 'b';
4984
5026
  else if(cell.v instanceof Date) {
4985
5027
  cell.z = o.dateNF || table_fmt[14];
5028
+ if(!o.UTC) cell.v = local_to_utc(cell.v);
4986
5029
  if(o.cellDates) { cell.t = 'd'; cell.w = SSF_format(cell.z, datenum(cell.v, o.date1904)); }
4987
5030
  else { cell.t = 'n'; cell.v = datenum(cell.v, o.date1904); cell.w = SSF_format(cell.z, cell.v); }
4988
5031
  }
@@ -7107,11 +7150,22 @@ function parse_LongRGB(blob, length) { var x = parse_LongRGBA(blob); x[3] = 0; r
7107
7150
 
7108
7151
 
7109
7152
  /* [MS-XLS] 2.5.19 */
7110
- function parse_XLSCell(blob/*::, length*/)/*:Cell*/ {
7153
+ function parse_XLSCell(blob, length, opts)/*:Cell*/ {
7111
7154
  var rw = blob.read_shift(2); // 0-indexed
7112
7155
  var col = blob.read_shift(2);
7113
- var ixfe = blob.read_shift(2);
7114
- return ({r:rw, c:col, ixfe:ixfe}/*:any*/);
7156
+ var ret = ({r:rw, c:col, ixfe:0}/*:any*/);
7157
+ if(opts && opts.biff == 2 || length == 7) {
7158
+ /* TODO: pass back flags */
7159
+ var flags = blob.read_shift(1);
7160
+ ret.ixfe = flags & 0x3F;
7161
+ blob.l += 2;
7162
+ /*
7163
+ var ifntifmt = blob.read_shift(1);
7164
+ var ifmt = ifntifmt & 0x3f, ifnt = ifntifmt >> 6;
7165
+ var flags3 = blob.read_shift(1);
7166
+ */
7167
+ } else ret.ixfe = blob.read_shift(2);
7168
+ return ret;
7115
7169
  }
7116
7170
  function write_XLSCell(R/*:number*/, C/*:number*/, ixfe/*:?number*/, o) {
7117
7171
  if(!o) o = new_buf(6);
@@ -7336,6 +7390,12 @@ function parse_WsBool(blob, length, opts) {
7336
7390
 
7337
7391
  /* [MS-XLS] 2.4.28 */
7338
7392
  function parse_BoundSheet8(blob, length, opts) {
7393
+ var name = "";
7394
+ if(opts.biff == 4) {
7395
+ name = parse_ShortXLUnicodeString(blob, 0, opts);
7396
+ if(name.length === 0) name = "Sheet1";
7397
+ return { name:name };
7398
+ }
7339
7399
  var pos = blob.read_shift(4);
7340
7400
  var hidden = blob.read_shift(1) & 0x03;
7341
7401
  var dt = blob.read_shift(1);
@@ -7345,7 +7405,7 @@ function parse_BoundSheet8(blob, length, opts) {
7345
7405
  case 2: dt = 'Chartsheet'; break;
7346
7406
  case 6: dt = 'VBAModule'; break;
7347
7407
  }
7348
- var name = parse_ShortXLUnicodeString(blob, 0, opts);
7408
+ name = parse_ShortXLUnicodeString(blob, 0, opts);
7349
7409
  if(name.length === 0) name = "Sheet1";
7350
7410
  return { pos:pos, hs:hidden, dt:dt, name:name };
7351
7411
  }
@@ -7516,8 +7576,8 @@ function write_Font(data, opts) {
7516
7576
  }
7517
7577
 
7518
7578
  /* [MS-XLS] 2.4.149 */
7519
- function parse_LabelSst(blob) {
7520
- var cell = parse_XLSCell(blob);
7579
+ function parse_LabelSst(blob, length, opts) {
7580
+ var cell = parse_XLSCell(blob, length, opts);
7521
7581
  cell.isst = blob.read_shift(4);
7522
7582
  return cell;
7523
7583
  }
@@ -7532,8 +7592,7 @@ function write_LabelSst(R/*:number*/, C/*:number*/, v/*:number*/, os/*:number*/
7532
7592
  function parse_Label(blob, length, opts) {
7533
7593
  if(opts.biffguess && opts.biff == 2) opts.biff = 5;
7534
7594
  var target = blob.l + length;
7535
- var cell = parse_XLSCell(blob);
7536
- if(opts.biff == 2) blob.l++;
7595
+ var cell = parse_XLSCell(blob, length, opts);
7537
7596
  var str = parse_XLUnicodeString(blob, target - blob.l, opts);
7538
7597
  cell.val = str;
7539
7598
  return cell;
@@ -7567,6 +7626,19 @@ function write_Format(i/*:number*/, f/*:string*/, opts, o) {
7567
7626
  return out;
7568
7627
  }
7569
7628
  var parse_BIFF2Format = parse_XLUnicodeString2;
7629
+ function write_BIFF2Format(f/*:string*/) {
7630
+ var o = new_buf(1 + f.length);
7631
+ o.write_shift(1, f.length);
7632
+ o.write_shift(f.length, f, "sbcs");
7633
+ return o;
7634
+ }
7635
+ function write_BIFF4Format(f/*:string*/) {
7636
+ var o = new_buf(3 + f.length);
7637
+ o.l += 2;
7638
+ o.write_shift(1, f.length);
7639
+ o.write_shift(f.length, f, "sbcs");
7640
+ return o;
7641
+ }
7570
7642
 
7571
7643
  /* [MS-XLS] 2.4.90 */
7572
7644
  function parse_Dimensions(blob, length, opts) {
@@ -7690,6 +7762,44 @@ function write_XF(data, ixfeP, opts, o) {
7690
7762
  o.write_shift(2, 0);
7691
7763
  return o;
7692
7764
  }
7765
+ function parse_BIFF2XF(blob/*::, length, opts*/) {
7766
+ var o = {};
7767
+ o.ifnt = blob.read_shift(1); blob.l++; o.flags = blob.read_shift(1);
7768
+ o.numFmtId = o.flags & 0x3F; o.flags>>=6;
7769
+ o.fStyle = 0;
7770
+ o.data = {}; // TODO
7771
+ return o;
7772
+ }
7773
+ function write_BIFF2XF(xf) {
7774
+ var o = new_buf(4);
7775
+ o.l+=2;
7776
+ o.write_shift(1, xf.numFmtId);
7777
+ o.l++;
7778
+ return o;
7779
+ }
7780
+ function write_BIFF3XF(xf) {
7781
+ var o = new_buf(12);
7782
+ o.l++;
7783
+ o.write_shift(1, xf.numFmtId);
7784
+ o.l += 10;
7785
+ return o;
7786
+ }
7787
+ /* TODO: check other fields */
7788
+ var write_BIFF4XF = write_BIFF3XF;
7789
+ function parse_BIFF3XF(blob/*::, length, opts*/) {
7790
+ var o = {};
7791
+ o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
7792
+ o.fStyle = (o.flags >> 2) & 0x01;
7793
+ o.data = {}; // TODO
7794
+ return o;
7795
+ }
7796
+ function parse_BIFF4XF(blob/*::, length, opts*/) {
7797
+ var o = {};
7798
+ o.ifnt = blob.read_shift(1); o.numFmtId = blob.read_shift(1); o.flags = blob.read_shift(2);
7799
+ o.fStyle = (o.flags >> 2) & 0x01;
7800
+ o.data = {}; // TODO
7801
+ return o;
7802
+ }
7693
7803
 
7694
7804
  /* [MS-XLS] 2.4.134 */
7695
7805
  function parse_Guts(blob) {
@@ -7710,8 +7820,7 @@ function write_Guts(guts/*:Array<number>*/) {
7710
7820
 
7711
7821
  /* [MS-XLS] 2.4.24 */
7712
7822
  function parse_BoolErr(blob, length, opts) {
7713
- var cell = parse_XLSCell(blob);
7714
- if(opts.biff == 2 || length == 9) ++blob.l;
7823
+ var cell = parse_XLSCell(blob, 6, opts);
7715
7824
  var val = parse_Bes(blob);
7716
7825
  cell.val = val;
7717
7826
  cell.t = (val === true || val === false) ? 'b' : 'e';
@@ -7727,7 +7836,7 @@ function write_BoolErr(R/*:number*/, C/*:number*/, v, os/*:number*/, opts, t/*:s
7727
7836
  /* [MS-XLS] 2.4.180 Number */
7728
7837
  function parse_Number(blob, length, opts) {
7729
7838
  if(opts.biffguess && opts.biff == 2) opts.biff = 5;
7730
- var cell = parse_XLSCell(blob);
7839
+ var cell = parse_XLSCell(blob, 6, opts);
7731
7840
  var xnum = parse_Xnum(blob);
7732
7841
  cell.val = xnum;
7733
7842
  return cell;
@@ -7860,21 +7969,34 @@ function parse_MTRSettings(blob) {
7860
7969
  return [fMTREnabled, fUserSetThreadCount, cUserThreadCount];
7861
7970
  }
7862
7971
 
7863
- /* [MS-XLS] 2.5.186 TODO: BIFF5 */
7972
+ /* [MS-XLS] 2.5.186 */
7864
7973
  function parse_NoteSh(blob, length, opts) {
7865
- if(opts.biff < 8) return;
7866
7974
  var row = blob.read_shift(2), col = blob.read_shift(2);
7867
7975
  var flags = blob.read_shift(2), idObj = blob.read_shift(2);
7868
7976
  var stAuthor = parse_XLUnicodeString2(blob, 0, opts);
7869
- if(opts.biff < 8) blob.read_shift(1);
7870
7977
  return [{r:row,c:col}, stAuthor, idObj, flags];
7871
7978
  }
7872
7979
 
7873
7980
  /* [MS-XLS] 2.4.179 */
7874
7981
  function parse_Note(blob, length, opts) {
7982
+ if(opts && (opts.biff < 8)) {
7983
+ var row = blob.read_shift(2), col = blob.read_shift(2);
7984
+ if(row == 0xFFFF || row == -1) return; // TODO: test continuation
7985
+ var cch = blob.read_shift(2);
7986
+ var cmnt = blob.read_shift(Math.min(cch,2048), 'cpstr');
7987
+ return [{r:row, c:col}, cmnt];
7988
+ }
7875
7989
  /* TODO: Support revisions */
7876
7990
  return parse_NoteSh(blob, length, opts);
7877
7991
  }
7992
+ function write_NOTE_BIFF2(text/*:string*/, R/*:number*/, C/*:number*/, len/*?:number*/) {
7993
+ var o = new_buf(6 + (len || text.length));
7994
+ o.write_shift(2, R);
7995
+ o.write_shift(2, C);
7996
+ o.write_shift(2, len || text.length);
7997
+ o.write_shift(text.length, text, "sbcs");
7998
+ return o;
7999
+ }
7878
8000
 
7879
8001
  /* [MS-XLS] 2.4.168 */
7880
8002
  function parse_MergeCells(blob, length)/*:Array<Range>*/ {
@@ -8124,43 +8246,50 @@ function parse_ImData(blob) {
8124
8246
  return o;
8125
8247
  }
8126
8248
 
8249
+ function write_BIFF2Cell(out, r/*:number*/, c/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
8250
+ if(!out) out = new_buf(7);
8251
+ out.write_shift(2, r);
8252
+ out.write_shift(2, c);
8253
+ out.write_shift(1, ixfe||0/* & 0x3F */);
8254
+ out.write_shift(1, ifmt||0/* & 0x3F */);
8255
+ out.write_shift(1, 0);
8256
+ return out;
8257
+ }
8258
+
8127
8259
  /* BIFF2_??? where ??? is the name from [XLS] */
8128
8260
  function parse_BIFF2STR(blob, length, opts) {
8129
8261
  if(opts.biffguess && opts.biff == 5) opts.biff = 2;
8130
- var cell = parse_XLSCell(blob);
8131
- ++blob.l;
8262
+ var cell = parse_XLSCell(blob, 7, opts);
8132
8263
  var str = parse_XLUnicodeString2(blob, length-7, opts);
8133
8264
  cell.t = 'str';
8134
8265
  cell.val = str;
8135
8266
  return cell;
8136
8267
  }
8137
8268
 
8138
- function parse_BIFF2NUM(blob/*::, length*/) {
8139
- var cell = parse_XLSCell(blob);
8140
- ++blob.l;
8269
+ function parse_BIFF2NUM(blob, length, opts) {
8270
+ var cell = parse_XLSCell(blob, 7, opts);
8141
8271
  var num = parse_Xnum(blob);
8142
8272
  cell.t = 'n';
8143
8273
  cell.val = num;
8144
8274
  return cell;
8145
8275
  }
8146
- function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/) {
8276
+ function write_BIFF2NUM(r/*:number*/, c/*:number*/, val/*:number*/, ixfe, ifmt) {
8147
8277
  var out = new_buf(15);
8148
- write_BIFF2Cell(out, r, c);
8278
+ write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
8149
8279
  out.write_shift(8, val, 'f');
8150
8280
  return out;
8151
8281
  }
8152
8282
 
8153
- function parse_BIFF2INT(blob) {
8154
- var cell = parse_XLSCell(blob);
8155
- ++blob.l;
8283
+ function parse_BIFF2INT(blob, length, opts) {
8284
+ var cell = parse_XLSCell(blob, 7, opts);
8156
8285
  var num = blob.read_shift(2);
8157
8286
  cell.t = 'n';
8158
8287
  cell.val = num;
8159
8288
  return cell;
8160
8289
  }
8161
- function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/) {
8290
+ function write_BIFF2INT(r/*:number*/, c/*:number*/, val/*:number*/, ixfe/*:number*/, ifmt/*:number*/) {
8162
8291
  var out = new_buf(9);
8163
- write_BIFF2Cell(out, r, c);
8292
+ write_BIFF2Cell(out, r, c, ixfe||0, ifmt||0);
8164
8293
  out.write_shift(2, val);
8165
8294
  return out;
8166
8295
  }
@@ -8171,6 +8300,16 @@ function parse_BIFF2STRING(blob) {
8171
8300
  return blob.read_shift(cch, 'sbcs-cont');
8172
8301
  }
8173
8302
 
8303
+ function parse_BIFF2BOOLERR(blob, length, opts) {
8304
+ var bestart = blob.l + 7;
8305
+ var cell = parse_XLSCell(blob, 6, opts);
8306
+ blob.l = bestart;
8307
+ var val = parse_Bes(blob);
8308
+ cell.val = val;
8309
+ cell.t = (val === true || val === false) ? 'b' : 'e';
8310
+ return cell;
8311
+ }
8312
+
8174
8313
  /* TODO: convert to BIFF8 font struct */
8175
8314
  function parse_BIFF2FONTXTRA(blob, length) {
8176
8315
  blob.l += 6; // unknown
@@ -8184,7 +8323,7 @@ function parse_BIFF2FONTXTRA(blob, length) {
8184
8323
  /* TODO: parse rich text runs */
8185
8324
  function parse_RString(blob, length, opts) {
8186
8325
  var end = blob.l + length;
8187
- var cell = parse_XLSCell(blob);
8326
+ var cell = parse_XLSCell(blob, 6, opts);
8188
8327
  var cch = blob.read_shift(2);
8189
8328
  var str = parse_XLUnicodeStringNoCch(blob, cch, opts);
8190
8329
  blob.l = end;
@@ -8192,7 +8331,13 @@ function parse_RString(blob, length, opts) {
8192
8331
  cell.val = str;
8193
8332
  return cell;
8194
8333
  }
8195
- var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
8334
+
8335
+ function parse_BIFF4SheetInfo(blob/*::, length, opts*/) {
8336
+ var flags = blob.read_shift(4);
8337
+ var cch = blob.read_shift(1), name = blob.read_shift(cch, "sbcs");
8338
+ if(name.length === 0) name = "Sheet1";
8339
+ return { flags: flags, name:name };
8340
+ }var DBF_SUPPORTED_VERSIONS = [0x02, 0x03, 0x30, 0x31, 0x83, 0x8B, 0x8C, 0xF5];
8196
8341
  var DBF = /*#__PURE__*/(function() {
8197
8342
  var dbf_codepage_map = {
8198
8343
  /* Code Pages Supported by Visual FoxPro */
@@ -8373,7 +8518,10 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
8373
8518
  if(s.trim().length) out[R][C] = s.replace(/\s+$/,"");
8374
8519
  break;
8375
8520
  case 'D':
8376
- if(s.length === 8) out[R][C] = new Date(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8));
8521
+ if(s.length === 8) {
8522
+ out[R][C] = new Date(Date.UTC(+s.slice(0,4), +s.slice(4,6)-1, +s.slice(6,8), 0, 0, 0, 0));
8523
+ if(!(opts && opts.UTC)) { out[R][C] = utc_to_local(out[R][C]); }
8524
+ }
8377
8525
  else out[R][C] = s;
8378
8526
  break;
8379
8527
  case 'F': out[R][C] = parseFloat(s.trim()); break;
@@ -8396,7 +8544,12 @@ function dbf_to_aoa(buf, opts)/*:AOA*/ {
8396
8544
  // NOTE: dBASE specs appear to be incorrect
8397
8545
  out[R][C] = new Date(dd.read_shift(-8, 'f') - 0x388317533400);
8398
8546
  break;
8399
- case 'T': out[R][C] = new Date((dd.read_shift(4) - 0x253D8C) * 0x5265C00 + dd.read_shift(4)); break;
8547
+ case 'T': {
8548
+ var hi = dd.read_shift(4), lo = dd.read_shift(4);
8549
+ if(hi == 0 && lo == 0) break;
8550
+ out[R][C] = new Date((hi - 0x253D8C) * 0x5265C00 + lo);
8551
+ if(!(opts && opts.UTC)) out[R][C] = utc_to_local(out[R][C]);
8552
+ } break;
8400
8553
  case 'Y': out[R][C] = dd.read_shift(4,'i')/1e4 + (dd.read_shift(4, 'i')/1e4)*Math.pow(2,32); break;
8401
8554
  case 'O': out[R][C] = -dd.read_shift(-8, 'f'); break;
8402
8555
  case 'B': if(vfp && fields[C].len == 8) { out[R][C] = dd.read_shift(8,'f'); break; }
@@ -8599,6 +8752,8 @@ var SYLK = /*#__PURE__*/(function() {
8599
8752
  var sylk_char_fn = function(_, $1){ var o = sylk_escapes[$1]; return typeof o == "number" ? _getansi(o) : o; };
8600
8753
  var decode_sylk_char = function($$, $1, $2) { var newcc = (($1.charCodeAt(0) - 0x20)<<4) | ($2.charCodeAt(0) - 0x30); return newcc == 59 ? $$ : _getansi(newcc); };
8601
8754
  sylk_escapes["|"] = 254;
8755
+ /* TODO: evert the escape map */
8756
+ var encode_sylk_str = function($$) { return $$.replace(/\n/g, "\x1b :").replace(/\r/g, "\x1b ="); };
8602
8757
  /* https://oss.sheetjs.com/notes/sylk/ for more details */
8603
8758
  function sylk_to_aoa(d/*:RawData*/, opts)/*:[AOA, Worksheet]*/ {
8604
8759
  switch(opts.type) {
@@ -8651,8 +8806,9 @@ var SYLK = /*#__PURE__*/(function() {
8651
8806
  // case 'NU': // ??
8652
8807
  case 'C': /* cell */
8653
8808
  var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z";
8809
+ var cmnt = "";
8654
8810
  for(rj=1; rj<record.length; ++rj) switch(record[rj].charAt(0)) {
8655
- case 'A': break; // TODO: comment
8811
+ case 'A': cmnt = record[rj].slice(1); break; // TODO: comment
8656
8812
  case 'X': C = parseInt(record[rj].slice(1), 10)-1; C_seen_X = true; break;
8657
8813
  case 'Y':
8658
8814
  R = parseInt(record[rj].slice(1), 10)-1; if(!C_seen_X) C = 0;
@@ -8664,10 +8820,9 @@ var SYLK = /*#__PURE__*/(function() {
8664
8820
  else if(val === 'TRUE' || val === 'FALSE') { val = val === 'TRUE'; cell_t = "b"; }
8665
8821
  else if(!isNaN(fuzzynum(val))) {
8666
8822
  val = fuzzynum(val); cell_t = "n";
8667
- if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) { val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = "d"; }
8668
- } else if(!isNaN(fuzzydate(val).getDate())) {
8669
- val = parseDate(val); cell_t = "d";
8670
- if(!opts.cellDates) { cell_t = "n"; val = datenum(val, wb.Workbook.WBProps.date1904); }
8823
+ if(next_cell_format !== null && fmt_is_date(next_cell_format) && opts.cellDates) {
8824
+ val = numdate(wb.Workbook.WBProps.date1904 ? val + 1462 : val); cell_t = typeof val == "number" ? "n" : "d";
8825
+ }
8671
8826
  }
8672
8827
  C_seen_K = true;
8673
8828
  break;
@@ -8702,6 +8857,10 @@ var SYLK = /*#__PURE__*/(function() {
8702
8857
  if(!arr[R][C]) arr[R][C] = { t: 'n', f: formula };
8703
8858
  else arr[R][C].f = formula;
8704
8859
  }
8860
+ if(cmnt) {
8861
+ if(!arr[R][C]) arr[R][C] = { t: 'z' };
8862
+ arr[R][C].c = [{a:"SheetJSYLK", t: cmnt}];
8863
+ }
8705
8864
  break;
8706
8865
  case 'F': /* Format */
8707
8866
  var F_seen = 0;
@@ -8763,7 +8922,7 @@ var SYLK = /*#__PURE__*/(function() {
8763
8922
  return outwb;
8764
8923
  }
8765
8924
 
8766
- function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*//*::, opts*/)/*:string*/ {
8925
+ function write_ws_cell_sylk(cell/*:Cell*/, ws/*:Worksheet*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/)/*:string*/ {
8767
8926
  var o = "C;Y" + (R+1) + ";X" + (C+1) + ";K";
8768
8927
  switch(cell.t) {
8769
8928
  case 'n':
@@ -8771,12 +8930,19 @@ var SYLK = /*#__PURE__*/(function() {
8771
8930
  if(cell.f && !cell.F) o += ";E" + a1_to_rc(cell.f, {r:R, c:C}); break;
8772
8931
  case 'b': o += cell.v ? "TRUE" : "FALSE"; break;
8773
8932
  case 'e': o += cell.w || cell.v; break;
8774
- case 'd': o += '"' + (cell.w || cell.v) + '"'; break;
8933
+ case 'd': o += datenum(parseDate(cell.v, date1904), date1904); break;
8775
8934
  case 's': o += '"' + (cell.v == null ? "" : String(cell.v)).replace(/"/g,"").replace(/;/g, ";;") + '"'; break;
8776
8935
  }
8777
8936
  return o;
8778
8937
  }
8779
8938
 
8939
+ function write_ws_cmnt_sylk(cmnt/*:Comment*/, R/*:number*/, C/*:number*/)/*:string*/ {
8940
+ var o = "C;Y" + (R+1) + ";X" + (C+1) + ";A";
8941
+ /* TODO: max length? */
8942
+ o += encode_sylk_str(cmnt.map(function(c) { return c.t; }).join(""));
8943
+ return o;
8944
+ }
8945
+
8780
8946
  function write_ws_cols_sylk(out, cols) {
8781
8947
  cols.forEach(function(col, i) {
8782
8948
  var rec = "F;W" + (i+1) + " " + (i+1) + " ";
@@ -8801,6 +8967,7 @@ var SYLK = /*#__PURE__*/(function() {
8801
8967
  }
8802
8968
 
8803
8969
  function sheet_to_sylk(ws/*:Worksheet*/, opts/*:?any*/, wb/*:?WorkBook*/)/*:string*/ {
8970
+ if(!opts) opts = {}; opts._formats = ["General"];
8804
8971
  /* TODO: codepage */
8805
8972
  var preamble/*:Array<string>*/ = ["ID;PSheetJS;N;E"], o/*:Array<string>*/ = [];
8806
8973
  var r = safe_decode_range(ws['!ref']), cell/*:Cell*/;
@@ -8808,23 +8975,44 @@ var SYLK = /*#__PURE__*/(function() {
8808
8975
  var RS = "\r\n";
8809
8976
  var d1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
8810
8977
 
8978
+ var _lastfmt = "General";
8811
8979
  preamble.push("P;PGeneral");
8812
- preamble.push("F;P0;DG0G8;M255");
8813
- if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
8814
- if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
8815
-
8816
- preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
8817
- preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
8818
- for(var R = r.s.r; R <= r.e.r; ++R) {
8980
+ /* Excel has been inconsistent in comment placement */
8981
+ var R = r.s.r, C = r.s.c, p = [];
8982
+ for(R = r.s.r; R <= r.e.r; ++R) {
8819
8983
  if(dense && !ws["!data"][R]) continue;
8820
- var p = [];
8821
- for(var C = r.s.c; C <= r.e.c; ++C) {
8984
+ p = [];
8985
+ for(C = r.s.c; C <= r.e.c; ++C) {
8986
+ cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
8987
+ if(!cell || !cell.c) continue;
8988
+ p.push(write_ws_cmnt_sylk(cell.c, R, C));
8989
+ }
8990
+ if(p.length) o.push(p.join(RS));
8991
+ }
8992
+ for(R = r.s.r; R <= r.e.r; ++R) {
8993
+ if(dense && !ws["!data"][R]) continue;
8994
+ p = [];
8995
+ for(C = r.s.c; C <= r.e.c; ++C) {
8822
8996
  cell = dense ? ws["!data"][R][C] : ws[encode_col(C) + encode_row(R)];
8823
8997
  if(!cell || (cell.v == null && (!cell.f || cell.F))) continue;
8824
- p.push(write_ws_cell_sylk(cell, ws, R, C)); // TODO: pass date1904 info
8998
+ if((cell.z||(cell.t == "d" ? table_fmt[14] : "General")) != _lastfmt) {
8999
+ var ifmt = opts._formats.indexOf(cell.z);
9000
+ if(ifmt == -1) { opts._formats.push(cell.z); ifmt = opts._formats.length - 1; preamble.push("P;P" + cell.z.replace(/;/g, ";;")); }
9001
+ p.push("F;P" + ifmt + ";Y" + (R+1) + ";X" + (C+1));
9002
+ }
9003
+ p.push(write_ws_cell_sylk(cell, ws, R, C, opts, d1904));
8825
9004
  }
8826
9005
  o.push(p.join(RS));
8827
9006
  }
9007
+
9008
+ preamble.push("F;P0;DG0G8;M255");
9009
+ if(ws['!cols']) write_ws_cols_sylk(preamble, ws['!cols']);
9010
+ if(ws['!rows']) write_ws_rows_sylk(preamble, ws['!rows']);
9011
+
9012
+ preamble.push("B;Y" + (r.e.r - r.s.r + 1) + ";X" + (r.e.c - r.s.c + 1) + ";D" + [r.s.c,r.s.r,r.e.c,r.e.r].join(" "));
9013
+ preamble.push("O;L;D;B" + (d1904 ? ";V4" : "") + ";K47;G100 0.001");
9014
+
9015
+ delete opts._formats;
8828
9016
  return preamble.join(RS) + RS + o.join(RS) + RS + "E" + RS;
8829
9017
  }
8830
9018
 
@@ -8864,7 +9052,10 @@ var DIF = /*#__PURE__*/(function() {
8864
9052
  if(data === 'TRUE') arr[R][C] = true;
8865
9053
  else if(data === 'FALSE') arr[R][C] = false;
8866
9054
  else if(!isNaN(fuzzynum(value))) arr[R][C] = fuzzynum(value);
8867
- else if(!isNaN(fuzzydate(value).getDate())) arr[R][C] = parseDate(value);
9055
+ else if(!isNaN(fuzzydate(value).getDate())) {
9056
+ arr[R][C] = parseDate(value);
9057
+ if(!(opts && opts.UTC)) { arr[R][C] = utc_to_local(arr[R][C]); }
9058
+ }
8868
9059
  else arr[R][C] = value;
8869
9060
  ++C; break;
8870
9061
  case 1:
@@ -9139,9 +9330,11 @@ var PRN = /*#__PURE__*/(function() {
9139
9330
  var start = 0, end = 0, sepcc = sep.charCodeAt(0), instr = false, cc=0, startcc=str.charCodeAt(0);
9140
9331
  var _re/*:?RegExp*/ = o.dateNF != null ? dateNF_regex(o.dateNF) : null;
9141
9332
  function finish_cell() {
9333
+ /* TODO: fuzzy parsers should pass back assumed number format */
9142
9334
  var s = str.slice(start, end); if(s.slice(-1) == "\r") s = s.slice(0, -1);
9143
9335
  var cell = ({}/*:any*/);
9144
9336
  if(s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') s = s.slice(1,-1).replace(/""/g,'"');
9337
+ if(o.cellText !== false) cell.w = s;
9145
9338
  if(s.length === 0) cell.t = 'z';
9146
9339
  else if(o.raw) { cell.t = 's'; cell.v = s; }
9147
9340
  else if(s.trim().length === 0) { cell.t = 's'; cell.v = s; }
@@ -9151,14 +9344,14 @@ var PRN = /*#__PURE__*/(function() {
9151
9344
  else { cell.t = 's'; cell.v = s; } }
9152
9345
  else if(s == "TRUE") { cell.t = 'b'; cell.v = true; }
9153
9346
  else if(s == "FALSE") { cell.t = 'b'; cell.v = false; }
9154
- else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; }
9347
+ else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; cell.v = v; }
9155
9348
  else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) {
9156
9349
  cell.z = o.dateNF || table_fmt[14];
9157
- var k = 0;
9158
- if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); }
9350
+ if(_re && s.match(_re)){ var news=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); v = parseDate(news); if(o && o.UTC === false) v = utc_to_local(v); }
9351
+ else if(o && o.UTC === false) v = utc_to_local(v);
9352
+ else if(o.cellText !== false && o.dateNF) cell.w = SSF_format(cell.z, v);
9159
9353
  if(o.cellDates) { cell.t = 'd'; cell.v = v; }
9160
9354
  else { cell.t = 'n'; cell.v = datenum(v); }
9161
- if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v);
9162
9355
  if(!o.cellNF) delete cell.z;
9163
9356
  } else {
9164
9357
  cell.t = 's';
@@ -9283,6 +9476,22 @@ var WK_ = /*#__PURE__*/(function() {
9283
9476
  throw "Unsupported type " + opts.type;
9284
9477
  }
9285
9478
 
9479
+ /* NOTE: this list intentionally starts at 1 */
9480
+ var LOTUS_DATE_FMTS = [
9481
+ "mmmm",
9482
+ "dd-mmm-yyyy",
9483
+ "dd-mmm",
9484
+ "mmm-yyyy",
9485
+ "@", // "text"?
9486
+ "mm/dd",
9487
+ "hh:mm:ss AM/PM", // 7
9488
+ "hh:mm AM/PM",
9489
+ "mm/dd/yyyy",
9490
+ "mm/dd",
9491
+ "hh:mm:ss",
9492
+ "hh:mm" // 12
9493
+ ];
9494
+
9286
9495
  function lotus_to_workbook_buf(d, opts)/*:Workbook*/ {
9287
9496
  if(!d) return d;
9288
9497
  var o = opts || {};
@@ -9292,6 +9501,7 @@ var WK_ = /*#__PURE__*/(function() {
9292
9501
 
9293
9502
  var refguess = {s: {r:0, c:0}, e: {r:0, c:0} };
9294
9503
  var sheetRows = o.sheetRows || 0;
9504
+ var lastcell = {};
9295
9505
 
9296
9506
  if(d[4] == 0x51 && d[5] == 0x50 && d[6] == 0x57) return qpw_to_workbook_buf(d, opts);
9297
9507
  if(d[2] == 0x00) {
@@ -9323,9 +9533,9 @@ var WK_ = /*#__PURE__*/(function() {
9323
9533
  case 0x0E: /* NUMBER */
9324
9534
  case 0x10: /* FORMULA */
9325
9535
  /* TODO: actual translation of the format code */
9326
- if(RT == 0x0E && (val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
9327
- val[1].z = o.dateNF || table_fmt[14];
9328
- if(o.cellDates) { val[1].t = 'd'; val[1].v = numdate(val[1].v); }
9536
+ if((val[2] & 0x70) == 0x70 && (val[2] & 0x0F) > 1 && (val[2] & 0x0F) < 15) {
9537
+ val[1].z = o.dateNF || LOTUS_DATE_FMTS[(val[2] & 0x0F)-1] || table_fmt[14];
9538
+ if(o.cellDates) { val[1].v = numdate(val[1].v); val[1].t = typeof val[1].v == "number" ? 'n' : 'd'; }
9329
9539
  }
9330
9540
 
9331
9541
  if(o.qpro) {
@@ -9344,14 +9554,25 @@ var WK_ = /*#__PURE__*/(function() {
9344
9554
  tmpcell.t = val[1].t; tmpcell.v = val[1].v;
9345
9555
  if(val[1].z != null) tmpcell.z = val[1].z;
9346
9556
  if(val[1].f != null) tmpcell.f = val[1].f;
9557
+ lastcell = tmpcell;
9347
9558
  break;
9348
9559
  }
9349
9560
  if(o.dense) {
9350
9561
  if(!sdata[val[0].r]) sdata[val[0].r] = [];
9351
9562
  sdata[val[0].r][val[0].c] = val[1];
9352
9563
  } else s[encode_cell(val[0])] = val[1];
9564
+ lastcell = val[1];
9353
9565
  break;
9354
9566
  case 0x5405: o.works2 = true; break;
9567
+ case 0x5402: {
9568
+ /* TODO: enumerate all extended number formats */
9569
+ if(val == 0x14a1) {
9570
+ lastcell.z = "hh:mm:ss";
9571
+ if(o.cellDates && lastcell.t == "n") {
9572
+ lastcell.v = numdate(lastcell.v); lastcell.t = typeof lastcell.v == "number" ? 'n' : 'd';
9573
+ }
9574
+ }
9575
+ } break;
9355
9576
  }}, o);
9356
9577
  } else if(d[2] == 0x1A || d[2] == 0x0E) {
9357
9578
  o.Enum = WK3Enum;
@@ -9427,10 +9648,17 @@ var WK_ = /*#__PURE__*/(function() {
9427
9648
  var cell = dense ? (ws["!data"][R]||[])[C] : ws[cols[C] + rr];
9428
9649
  if(!cell || cell.t == "z") continue;
9429
9650
  /* TODO: formula records */
9430
- if(cell.t == "n") {
9431
- if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell.v));
9432
- else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell.v));
9433
- } else {
9651
+ switch(cell.t) {
9652
+ case "n":
9653
+ if((cell.v|0)==cell.v && cell.v >= -32768 && cell.v <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, cell));
9654
+ else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, cell));
9655
+ break;
9656
+ case "d":
9657
+ var dc = datenum(cell.v);
9658
+ if((dc|0)==dc && dc >= -32768 && dc <= 32767) write_biff_rec(ba, 0x0d, write_INTEGER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
9659
+ else write_biff_rec(ba, 0x0e, write_NUMBER(R, C, {t:"n", v:dc, z:cell.z || table_fmt[14]}));
9660
+ break;
9661
+ default:
9434
9662
  var str = format_cell(cell);
9435
9663
  write_biff_rec(ba, 0x0F, write_LABEL(R, C, str.slice(0, 239)));
9436
9664
  }
@@ -9564,11 +9792,18 @@ var WK_ = /*#__PURE__*/(function() {
9564
9792
  return o;
9565
9793
  }
9566
9794
 
9795
+ function get_wk1_fmt(cell)/*:number*/ {
9796
+ /* TODO: some fuzzy matching on the number format */
9797
+ if(cell.z && fmt_is_date(cell.z)) {
9798
+ return 0xf0 | (LOTUS_DATE_FMTS.indexOf(cell.z) + 1 || 2);
9799
+ }
9800
+ return 0xFF;
9801
+ }
9567
9802
  function parse_LABEL(blob, length, opts) {
9568
9803
  var tgt = blob.l + length;
9569
9804
  var o = parse_cell(blob, length, opts);
9570
9805
  o[1].t = 's';
9571
- if(opts.vers == 0x5120) {
9806
+ if((opts.vers & 0xFFFE) == 0x5120) { // WQ1 / WQ2
9572
9807
  blob.l++;
9573
9808
  var len = blob.read_shift(1);
9574
9809
  o[1].v = blob.read_shift(len, 'utf8');
@@ -9610,12 +9845,12 @@ var WK_ = /*#__PURE__*/(function() {
9610
9845
  o[1].v = blob.read_shift(2, 'i');
9611
9846
  return o;
9612
9847
  }
9613
- function write_INTEGER(R, C, v) {
9848
+ function write_INTEGER(R, C, cell) {
9614
9849
  var o = new_buf(7);
9615
- o.write_shift(1, 0xFF);
9850
+ o.write_shift(1, get_wk1_fmt(cell));
9616
9851
  o.write_shift(2, C);
9617
9852
  o.write_shift(2, R);
9618
- o.write_shift(2, v, 'i');
9853
+ o.write_shift(2, cell.v, 'i');
9619
9854
  return o;
9620
9855
  }
9621
9856
 
@@ -9624,12 +9859,12 @@ var WK_ = /*#__PURE__*/(function() {
9624
9859
  o[1].v = blob.read_shift(8, 'f');
9625
9860
  return o;
9626
9861
  }
9627
- function write_NUMBER(R, C, v) {
9862
+ function write_NUMBER(R, C, cell) {
9628
9863
  var o = new_buf(13);
9629
- o.write_shift(1, 0xFF);
9864
+ o.write_shift(1, get_wk1_fmt(cell));
9630
9865
  o.write_shift(2, C);
9631
9866
  o.write_shift(2, R);
9632
- o.write_shift(8, v, 'f');
9867
+ o.write_shift(8, cell.v, 'f');
9633
9868
  return o;
9634
9869
  }
9635
9870
 
@@ -9682,7 +9917,7 @@ var WK_ = /*#__PURE__*/(function() {
9682
9917
  0x33: ["FALSE", 0],
9683
9918
  0x34: ["TRUE", 0],
9684
9919
  0x35: ["RAND", 0],
9685
- // 0x36 DATE
9920
+ 0x36: ["DATE", 3],
9686
9921
  // 0x37 NOW
9687
9922
  // 0x38 PMT
9688
9923
  // 0x39 PV
@@ -9692,7 +9927,7 @@ var WK_ = /*#__PURE__*/(function() {
9692
9927
  // 0x3D MONTH
9693
9928
  // 0x3E YEAR
9694
9929
  0x3F: ["ROUND", 2],
9695
- // 0x40 TIME
9930
+ 0x40: ["TIME", 3],
9696
9931
  // 0x41 HOUR
9697
9932
  // 0x42 MINUTE
9698
9933
  // 0x43 SECOND
@@ -10034,13 +10269,24 @@ var WK_ = /*#__PURE__*/(function() {
10034
10269
  /*::[*/0x0048/*::]*/: { n:"ACOMM" },
10035
10270
  /*::[*/0x0049/*::]*/: { n:"AMACRO" },
10036
10271
  /*::[*/0x004A/*::]*/: { n:"PARSE" },
10272
+ // 0x0064
10037
10273
  /*::[*/0x0066/*::]*/: { n:"PRANGES??" },
10038
10274
  /*::[*/0x0067/*::]*/: { n:"RRANGES??" },
10039
10275
  /*::[*/0x0068/*::]*/: { n:"FNAME??" },
10040
10276
  /*::[*/0x0069/*::]*/: { n:"MRANGES??" },
10277
+ // 0x0096
10278
+ // 0x0099
10279
+ // 0x009A
10280
+ // 0x009B
10281
+ // 0x009C
10282
+ // 0x00C0
10283
+ // 0x00C7
10284
+ // 0x00C9
10041
10285
  /*::[*/0x00CC/*::]*/: { n:"SHEETNAMECS", f:parse_SHEETNAMECS },
10286
+ // 0x00CD
10042
10287
  /*::[*/0x00DE/*::]*/: { n:"SHEETNAMELP", f:parse_SHEETNAMELP },
10043
10288
  /*::[*/0x00FF/*::]*/: { n:"BOF", f:parseuint16 },
10289
+ /*::[*/0x5402/*::]*/: { n:"WKSNF", f:parseuint16 },
10044
10290
  /*::[*/0xFFFF/*::]*/: { n:"" }
10045
10291
  };
10046
10292
 
@@ -10170,6 +10416,24 @@ var WK_ = /*#__PURE__*/(function() {
10170
10416
  /*::[*/0xFFFF/*::]*/: { n:"" }
10171
10417
  };
10172
10418
 
10419
+ /* TODO: fill out and verify this table across QP versions */
10420
+ var QPWNFTable = {
10421
+ /*::[*/0x05/*::*/: "dd-mmm-yy",
10422
+ /*::[*/0x06/*::*/: "dd-mmm",
10423
+ /*::[*/0x07/*::*/: "mmm-yy",
10424
+ /*::[*/0x08/*::*/: "mm/dd/yy", // Long Date Intl
10425
+ /*::[*/0x0A/*::*/: "hh:mm:ss AM/PM",
10426
+ /*::[*/0x0B/*::*/: "hh:mm AM/PM",
10427
+ /*::[*/0x0E/*::*/: "dd-mmm-yyyy",
10428
+ /*::[*/0x0F/*::*/: "mmm-yyyy",
10429
+
10430
+ /*::[*/0x22/*::*/: "0.00",
10431
+ /*::[*/0x32/*::*/: "0.00;[Red]0.00",
10432
+ /*::[*/0x42/*::*/: "0.00;\(0.00\)",
10433
+ /*::[*/0x52/*::*/: "0.00;[Red]\(0.00\)",
10434
+
10435
+ /*::[*/162/*::*/: '"$"#,##0;\\("$"#,##0\\)' // slightly different from SSF 5
10436
+ };
10173
10437
  /* QPW uses a different set of record types */
10174
10438
  function qpw_to_workbook_buf(d, opts)/*:Workbook*/ {
10175
10439
  prep_blob(d, 0);
@@ -10179,6 +10443,7 @@ var WK_ = /*#__PURE__*/(function() {
10179
10443
  var range = {s:{r:-1,c:-1}, e:{r:-1,c:-1}};
10180
10444
  var cnt = 0, type = 0, C = 0, R = 0;
10181
10445
  var wb = { SheetNames: [], Sheets: {} };
10446
+ var FMTS = [];
10182
10447
  outer: while(d.l < d.length) {
10183
10448
  var RT = d.read_shift(2), length = d.read_shift(2);
10184
10449
  var p = d.slice(d.l, d.l + length);
@@ -10189,6 +10454,22 @@ var WK_ = /*#__PURE__*/(function() {
10189
10454
  break;
10190
10455
  case 0x02: /* EOF */ break outer;
10191
10456
 
10457
+ case 0x08: /* NF */ break; // TODO: this is tied to custom number formats
10458
+
10459
+ case 0x0A: /* FORMATS */ {
10460
+ var fcnt = p.read_shift(4);
10461
+ var step = ((p.length - p.l)/ fcnt)|0;
10462
+ for(var ifmt = 0; ifmt < fcnt; ++ifmt) {
10463
+ var end = p.l + step;
10464
+ var fmt = {};
10465
+ p.l += 2;
10466
+ fmt.numFmtId = p.read_shift(2);
10467
+ if(QPWNFTable[fmt.numFmtId]) fmt.z = QPWNFTable[fmt.numFmtId];
10468
+ p.l = end;
10469
+ FMTS.push(fmt);
10470
+ }
10471
+ } break;
10472
+
10192
10473
  /* TODO: The behavior here should be consistent with Numbers: QP Notebook ~ .TN.SheetArchive, QP Sheet ~ .TST.TableModelArchive */
10193
10474
  case 0x0401: /* BON */ break;
10194
10475
  case 0x0402: /* EON */ /* TODO: backfill missing sheets based on BON cnt */ break;
@@ -10245,18 +10526,21 @@ var WK_ = /*#__PURE__*/(function() {
10245
10526
  var CC = encode_col(C);
10246
10527
  while(p.l < p.length) {
10247
10528
  var cell = { t: "z" };
10248
- var flags = p.read_shift(1);
10249
- if(flags & 0x80) p.l += 2;
10529
+ var flags = p.read_shift(1), fmtidx = -1;
10530
+ if(flags & 0x80) fmtidx = p.read_shift(2);
10250
10531
  var mul = (flags & 0x40) ? p.read_shift(2) - 1: 0;
10251
10532
  switch(flags & 0x1F) {
10533
+ case 0: break;
10252
10534
  case 1: break;
10253
10535
  case 2: cell = { t: "n", v: p.read_shift(2) }; break;
10254
10536
  case 3: cell = { t: "n", v: p.read_shift(2, 'i') }; break;
10537
+ case 4: cell = { t: "n", v: parse_RkNumber(p) }; break;
10255
10538
  case 5: cell = { t: "n", v: p.read_shift(8, 'f') }; break;
10256
10539
  case 7: cell = { t: "s", v: SST[type = p.read_shift(4) - 1] }; break;
10257
10540
  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;
10258
10541
  default: throw "Unrecognized QPW cell type " + (flags & 0x1F);
10259
10542
  }
10543
+ if(fmtidx != -1 && (FMTS[fmtidx - 1]||{}).z) cell.z = FMTS[fmtidx-1].z;
10260
10544
  var delta = 0;
10261
10545
  if(flags & 0x20) switch(flags & 0x1F) {
10262
10546
  case 2: delta = p.read_shift(2); break;
@@ -10265,10 +10549,14 @@ var WK_ = /*#__PURE__*/(function() {
10265
10549
  default: throw "Unsupported delta for QPW cell type " + (flags & 0x1F);
10266
10550
  }
10267
10551
  if(!(!o.sheetStubs && cell.t == "z")) {
10552
+ var newcell = dup(cell);
10553
+ if(cell.t == "n" && cell.z && fmt_is_date(cell.z) && o.cellDates) {
10554
+ newcell.v = numdate(cell.v); newcell.t = typeof newcell.v == "number" ? 'n' : 'd';
10555
+ }
10268
10556
  if(s["!data"] != null) {
10269
10557
  if(!s["!data"][R]) s["!data"][R] = [];
10270
- s["!data"][R][C] = cell;
10271
- } else s[CC + encode_row(R)] = cell;
10558
+ s["!data"][R][C] = newcell;
10559
+ } else s[CC + encode_row(R)] = newcell;
10272
10560
  }
10273
10561
  ++R; --cnt;
10274
10562
  while(mul-- > 0 && cnt >= 0) {
@@ -12615,7 +12903,45 @@ function parse_drawing(data, rels/*:any*/) {
12615
12903
  }
12616
12904
 
12617
12905
  /* L.5.5.2 SpreadsheetML Comments + VML Schema */
12618
- function write_vml(rId/*:number*/, comments) {
12906
+ var shapevmlregex = /<(?:\w+:)?shape(?:[^\w][^>]*)?>([\s\S]*?)<\/(?:\w+:)?shape>/g;
12907
+ function parse_vml(data/*:string*/, sheet, comments) {
12908
+ var cidx = 0;
12909
+ (data.match(shapevmlregex)||[]).forEach(function(m) {
12910
+ var type = "";
12911
+ var hidden = true;
12912
+ var aidx = -1;
12913
+ var R = -1, C = -1;
12914
+ m.replace(tagregex, function(x/*:string*/, idx/*:number*/) {
12915
+ var y = parsexmltag(x);
12916
+ switch(strip_ns(y[0])) {
12917
+ case '<ClientData': if(y.ObjectType) type = y.ObjectType; break;
12918
+
12919
+ case '<Visible': case '<Visible/>': hidden = false; break;
12920
+
12921
+ case '<Row': case '<Row>': aidx = idx + x.length; break;
12922
+ case '</Row>': R = +m.slice(aidx, idx).trim(); break;
12923
+
12924
+ case '<Column': case '<Column>': aidx = idx + x.length; break;
12925
+ case '</Column>': C = +m.slice(aidx, idx).trim(); break;
12926
+ }
12927
+ return "";
12928
+ });
12929
+ switch(type) {
12930
+ case 'Note':
12931
+ var cell = ws_get_cell_stub(sheet, ((R>=0 && C>=0) ? encode_cell({r:R,c:C}) : comments[cidx].ref));
12932
+ if(cell.c) {
12933
+ cell.c.hidden = hidden;
12934
+ }
12935
+ ++cidx;
12936
+ break;
12937
+ }
12938
+
12939
+ });
12940
+ }
12941
+
12942
+
12943
+ /* comment boxes */
12944
+ function write_vml(rId/*:number*/, comments, ws) {
12619
12945
  var csize = [21600, 21600];
12620
12946
  /* L.5.2.1.2 Path Attribute */
12621
12947
  var bbox = ["m0,0l0",csize[1],csize[0],csize[1],csize[0],"0xe"].join(",");
@@ -12637,7 +12963,7 @@ function write_vml(rId/*:number*/, comments) {
12637
12963
  return o.join("");
12638
12964
  }
12639
12965
 
12640
- function write_vml_comment(x, _shapeid)/*:string*/ {
12966
+ function write_vml_comment(x, _shapeid, ws)/*:string*/ {
12641
12967
  var c = decode_cell(x[0]);
12642
12968
  var fillopts = /*::(*/{'color2':"#BEFF82", 'type':"gradient"}/*:: :any)*/;
12643
12969
  if(fillopts.type == "gradient") fillopts.angle = "-180";
@@ -12775,6 +13101,7 @@ function write_comments_xml(data/*::, opts*/) {
12775
13101
  o.push('</text></comment>');
12776
13102
  });
12777
13103
  } else {
13104
+ if(d[1][0] && d[1][0].T && d[1][0].ID) lastauthor = iauthor.indexOf("tc=" + d[1][0].ID);
12778
13105
  /* based on Threaded Comments -> Comments projection */
12779
13106
  o.push('<comment ref="' + d[0] + '" authorId="' + lastauthor + '"><text>');
12780
13107
  var t = "Comment:\n " + (ts[0]) + "\n";
@@ -12970,6 +13297,10 @@ function write_comments_bin(data/*::, opts*/) {
12970
13297
  if(iauthor.indexOf(c.a) > -1) return;
12971
13298
  iauthor.push(c.a.slice(0,54));
12972
13299
  write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor(c.a));
13300
+ if(c.T && c.ID && iauthor.indexOf("tc=" + c.ID) == -1) {
13301
+ iauthor.push("tc=" + c.ID);
13302
+ write_record(ba, 0x0278 /* BrtCommentAuthor */, write_BrtCommentAuthor("tc=" + c.ID));
13303
+ }
12973
13304
  });
12974
13305
  });
12975
13306
  write_record(ba, 0x0277 /* BrtEndCommentAuthors */);
@@ -12977,7 +13308,11 @@ function write_comments_bin(data/*::, opts*/) {
12977
13308
  write_record(ba, 0x0279 /* BrtBeginCommentList */);
12978
13309
  data.forEach(function(comment) {
12979
13310
  comment[1].forEach(function(c) {
12980
- c.iauthor = iauthor.indexOf(c.a);
13311
+ var _ia = -1;
13312
+ if(c.ID) _ia = iauthor.indexOf("tc=" + c.ID);
13313
+ if(_ia == -1 && comment[1][0].T && comment[1][0].ID) _ia = iauthor.indexOf("tc=" + comment[1][0].ID);
13314
+ if(_ia == -1) _ia = iauthor.indexOf(c.a);
13315
+ c.iauthor = _ia;
12981
13316
  var range = {s:decode_cell(comment[0]),e:decode_cell(comment[0])};
12982
13317
  write_record(ba, 0x027B /* BrtBeginComment */, write_BrtBeginComment([range, c]));
12983
13318
  if(c.t && c.t.length > 0) write_record(ba, 0x027D /* BrtCommentText */, write_BrtCommentText(c));
@@ -14191,8 +14526,7 @@ function write_FormulaValue(value) {
14191
14526
  /* [MS-XLS] 2.4.127 TODO */
14192
14527
  function parse_Formula(blob, length, opts) {
14193
14528
  var end = blob.l + length;
14194
- var cell = parse_XLSCell(blob);
14195
- if(opts.biff == 2) ++blob.l;
14529
+ var cell = parse_XLSCell(blob, 6, opts);
14196
14530
  var val = parse_FormulaValue(blob);
14197
14531
  var flags = blob.read_shift(1);
14198
14532
  if(opts.biff != 2) {
@@ -14386,7 +14720,7 @@ function write_XLSBFormulaRangeWS(_str, wb) {
14386
14720
  var sname = _str.slice(0, lastbang);
14387
14721
  _str = _str.slice(lastbang+1);
14388
14722
  if(sname.charAt(0) == "'") sname = sname.slice(1, -1).replace(/''/g, "'");
14389
- var parts = _str.split(":"); str = parts[0];
14723
+ var parts = _str.split(":");
14390
14724
 
14391
14725
  var out = new_buf(27);
14392
14726
  out.write_shift(4, 19);
@@ -15619,7 +15953,7 @@ function ods_to_csf_3D(r/*:string*/)/*:[string, string]*/ {
15619
15953
  }
15620
15954
 
15621
15955
  function csf_to_ods_3D(r/*:string*/)/*:string*/ {
15622
- return r.replace(/!/,".");
15956
+ return r.replace(/!/,".").replace(/:/, ":.");
15623
15957
  }
15624
15958
 
15625
15959
  var strs = {}; // shared strings
@@ -15705,7 +16039,7 @@ function get_cell_style(styles/*:Array<any>*/, cell/*:Cell*/, opts) {
15705
16039
  return len;
15706
16040
  }
15707
16041
 
15708
- function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles) {
16042
+ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, themes, styles, date1904) {
15709
16043
  try {
15710
16044
  if(opts.cellNF) p.z = table_fmt[fmtid];
15711
16045
  } catch(e) { if(opts.WTF) throw e; }
@@ -15720,14 +16054,14 @@ function safe_format(p/*:Cell*/, fmtid/*:number*/, fillid/*:?number*/, opts, the
15720
16054
  else p.w = SSF_general_num(p.v);
15721
16055
  }
15722
16056
  else if(p.t === 'd') {
15723
- var dd = datenum(p.v);
16057
+ var dd = datenum(p.v, !!date1904);
15724
16058
  if((dd|0) === dd) p.w = dd.toString(10);
15725
16059
  else p.w = SSF_general_num(dd);
15726
16060
  }
15727
16061
  else if(p.v === undefined) return "";
15728
16062
  else p.w = SSF_general(p.v,_ssfopts);
15729
16063
  }
15730
- else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v),_ssfopts);
16064
+ else if(p.t === 'd') p.w = SSF_format(fmtid,datenum(p.v, !!date1904),_ssfopts);
15731
16065
  else p.w = SSF_format(fmtid,p.v,_ssfopts);
15732
16066
  } catch(e) { if(opts.WTF) throw e; }
15733
16067
  if(!opts.cellStyles) return;
@@ -15806,7 +16140,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
15806
16140
  }
15807
16141
 
15808
16142
  /* 18.3.1.80 sheetData CT_SheetData ? */
15809
- if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles);
16143
+ if(mtch) parse_ws_xml_data(mtch[1], s, opts, refguess, themes, styles, wb);
15810
16144
 
15811
16145
  /* 18.3.1.2 autoFilter CT_AutoFilter */
15812
16146
  var afilter = data2.match(afregex);
@@ -15826,6 +16160,10 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
15826
16160
  var margins = data2.match(marginregex);
15827
16161
  if(margins) s['!margins'] = parse_ws_xml_margins(parsexmltag(margins[0]));
15828
16162
 
16163
+ /* legacyDrawing */
16164
+ var m;
16165
+ if((m = data2.match(/legacyDrawing r:id="(.*?)"/))) s['!legrel'] = m[1];
16166
+
15829
16167
  if(opts && opts.nodim) refguess.s.c = refguess.s.r = 0;
15830
16168
  if(!s["!ref"] && refguess.e.c >= refguess.s.c && refguess.e.r >= refguess.s.r) s["!ref"] = encode_range(refguess);
15831
16169
  if(opts.sheetRows > 0 && s["!ref"]) {
@@ -15842,6 +16180,7 @@ function parse_ws_xml(data/*:?string*/, opts, idx/*:number*/, rels, wb/*:WBWBPro
15842
16180
  }
15843
16181
  if(columns.length > 0) s["!cols"] = columns;
15844
16182
  if(merges.length > 0) s["!merges"] = merges;
16183
+ if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
15845
16184
  return s;
15846
16185
  }
15847
16186
 
@@ -16008,21 +16347,27 @@ function write_ws_xml_sheetviews(ws, opts, idx, wb)/*:string*/ {
16008
16347
  return writextag("sheetViews", writextag("sheetView", null, sview), {});
16009
16348
  }
16010
16349
 
16011
- function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts/*::, idx, wb*/)/*:string*/ {
16350
+ function write_ws_xml_cell(cell/*:Cell*/, ref, ws, opts, idx, wb, date1904)/*:string*/ {
16012
16351
  if(cell.c) ws['!comments'].push([ref, cell.c]);
16013
16352
  if((cell.v === undefined || cell.t === "z" && !(opts||{}).sheetStubs) && typeof cell.f !== "string" && typeof cell.z == "undefined") return "";
16014
16353
  var vv = "";
16015
16354
  var oldt = cell.t, oldv = cell.v;
16016
16355
  if(cell.t !== "z") switch(cell.t) {
16017
16356
  case 'b': vv = cell.v ? "1" : "0"; break;
16018
- case 'n': vv = ''+cell.v; break;
16357
+ case 'n':
16358
+ if(isNaN(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x24]; } // #NUM!
16359
+ else if(!isFinite(cell.v)) { cell.t = "e"; vv = BErr[cell.v = 0x07]; } // #DIV/0!
16360
+ else vv = ''+cell.v; break;
16019
16361
  case 'e': vv = BErr[cell.v]; break;
16020
16362
  case 'd':
16021
- if(opts && opts.cellDates) vv = parseDate(cell.v, -1).toISOString();
16022
- else {
16363
+ if(opts && opts.cellDates) {
16364
+ var _vv = parseDate(cell.v, date1904);
16365
+ vv = _vv.toISOString();
16366
+ if(_vv.getUTCFullYear() < 1900) vv = vv.slice(vv.indexOf("T") + 1).replace("Z","");
16367
+ } else {
16023
16368
  cell = dup(cell);
16024
16369
  cell.t = 'n';
16025
- vv = ''+(cell.v = datenum(parseDate(cell.v)));
16370
+ vv = ''+(cell.v = datenum(parseDate(cell.v, date1904), date1904));
16026
16371
  }
16027
16372
  if(typeof cell.z === 'undefined') cell.z = table_fmt[14];
16028
16373
  break;
@@ -16065,7 +16410,7 @@ var parse_ws_xml_data = /*#__PURE__*/(function() {
16065
16410
  var refregex = /ref=["']([^"']*)["']/;
16066
16411
  var match_v = matchtag("v"), match_f = matchtag("f");
16067
16412
 
16068
- return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles) {
16413
+ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, themes, styles, wb) {
16069
16414
  var ri = 0, x = "", cells/*:Array<string>*/ = [], cref/*:?Array<string>*/ = [], idx=0, i=0, cc=0, d="", p/*:any*/;
16070
16415
  var tag, tagr = 0, tagc = 0;
16071
16416
  var sstr, ftag;
@@ -16076,6 +16421,7 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
16076
16421
  var dense = s["!data"] != null;
16077
16422
  var rows/*:Array<RowInfo>*/ = [], rowobj = {}, rowrite = false;
16078
16423
  var sheetStubs = !!opts.sheetStubs;
16424
+ var date1904 = !!((wb||{}).WBProps||{}).date1904;
16079
16425
  for(var marr = sdata.split(rowregex), mt = 0, marrlen = marr.length; mt != marrlen; ++mt) {
16080
16426
  x = marr[mt].trim();
16081
16427
  var xlen = x.length;
@@ -16143,19 +16489,27 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
16143
16489
 
16144
16490
  if((cref=d.match(match_v))!= null && /*::cref != null && */cref[1] !== '') p.v=unescapexml(cref[1]);
16145
16491
  if(opts.cellFormula) {
16146
- if((cref=d.match(match_f))!= null && /*::cref != null && */cref[1] !== '') {
16147
- /* TODO: match against XLSXFutureFunctions */
16148
- p.f=unescapexml(utf8read(cref[1]), true);
16149
- if(!opts.xlfn) p.f = _xlfn(p.f);
16150
- if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
16151
- p.F = (d.match(refregex)||[])[1];
16152
- if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
16153
- } else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
16154
- // TODO: parse formula
16155
- ftag = parsexmltag(cref[0]);
16156
- var ___f = unescapexml(utf8read(cref[1]));
16157
- if(!opts.xlfn) ___f = _xlfn(___f);
16158
- sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
16492
+ if((cref=d.match(match_f))!= null /*:: && cref != null*/) {
16493
+ if(cref[1] == "") {
16494
+ if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
16495
+ // TODO: parse formula
16496
+ ftag = parsexmltag(cref[0]);
16497
+ if(sharedf[ftag.si]) p.f = shift_formula_xlsx(sharedf[ftag.si][1], sharedf[ftag.si][2]/*[0].ref*/, tag.r);
16498
+ }
16499
+ } else {
16500
+ /* TODO: match against XLSXFutureFunctions */
16501
+ p.f=unescapexml(utf8read(cref[1]), true);
16502
+ if(!opts.xlfn) p.f = _xlfn(p.f);
16503
+ if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="array"') > -1) {
16504
+ p.F = (d.match(refregex)||[])[1];
16505
+ if(p.F.indexOf(":") > -1) arrayf.push([safe_decode_range(p.F), p.F]);
16506
+ } else if(/*::cref != null && cref[0] != null && */cref[0].indexOf('t="shared"') > -1) {
16507
+ // TODO: parse formula
16508
+ ftag = parsexmltag(cref[0]);
16509
+ var ___f = unescapexml(utf8read(cref[1]));
16510
+ if(!opts.xlfn) ___f = _xlfn(___f);
16511
+ sharedf[parseInt(ftag.si, 10)] = [ftag, ___f, tag.r];
16512
+ }
16159
16513
  }
16160
16514
  } else if((cref=d.match(/<f[^>]*\/>/))) {
16161
16515
  ftag = parsexmltag(cref[0]);
@@ -16212,8 +16566,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
16212
16566
  break;
16213
16567
  case 'b': p.v = parsexmlbool(p.v); break;
16214
16568
  case 'd':
16215
- if(opts.cellDates) p.v = parseDate(p.v, 1);
16216
- else { p.v = datenum(parseDate(p.v, 1)); p.t = 'n'; }
16569
+ if(opts.cellDates) p.v = parseDate(p.v, date1904);
16570
+ else { p.v = datenum(parseDate(p.v, date1904), date1904); p.t = 'n'; }
16217
16571
  break;
16218
16572
  /* error string in .w, number in .v */
16219
16573
  case 'e':
@@ -16232,8 +16586,8 @@ return function parse_ws_xml_data(sdata/*:string*/, s, opts, guess/*:Range*/, th
16232
16586
  }
16233
16587
  }
16234
16588
  }
16235
- safe_format(p, fmtid, fillid, opts, themes, styles);
16236
- if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.t = 'd'; p.v = numdate(p.v); }
16589
+ safe_format(p, fmtid, fillid, opts, themes, styles, date1904);
16590
+ if(opts.cellDates && do_format && p.t == 'n' && fmt_is_date(table_fmt[fmtid])) { p.v = numdate(p.v + (date1904 ? 1462 : 0)); p.t = typeof p.v == "number" ? 'n' : 'd'; }
16237
16591
  if(tag.cm && opts.xlmeta) {
16238
16592
  var cm = (opts.xlmeta.Cell||[])[+tag.cm-1];
16239
16593
  if(cm && cm.type == 'XLDAPR') p.D = true;
@@ -16258,6 +16612,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
16258
16612
  var o/*:Array<string>*/ = [], r/*:Array<string>*/ = [], range = safe_decode_range(ws['!ref']), cell="", ref, rr = "", cols/*:Array<string>*/ = [], R=0, C=0, rows = ws['!rows'];
16259
16613
  var dense = ws["!data"] != null;
16260
16614
  var params = ({r:rr}/*:any*/), row/*:RowInfo*/, height = -1;
16615
+ var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
16261
16616
  for(C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
16262
16617
  for(R = range.s.r; R <= range.e.r; ++R) {
16263
16618
  r = [];
@@ -16266,7 +16621,7 @@ function write_ws_xml_data(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workbook
16266
16621
  ref = cols[C] + rr;
16267
16622
  var _cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
16268
16623
  if(_cell === undefined) continue;
16269
- if((cell = write_ws_xml_cell(_cell, ref, ws, opts)) != null) r.push(cell);
16624
+ if((cell = write_ws_xml_cell(_cell, ref, ws, opts, idx, wb, date1904)) != null) r.push(cell);
16270
16625
  }
16271
16626
  if(r.length > 0 || (rows && rows[R])) {
16272
16627
  params = ({r:rr}/*:any*/);
@@ -16336,7 +16691,7 @@ function write_ws_xml(idx/*:number*/, opts, wb/*:Workbook*/, rels)/*:string*/ {
16336
16691
  o[sidx = o.length] = '<sheetData/>';
16337
16692
  ws['!links'] = [];
16338
16693
  if(ws['!ref'] != null) {
16339
- rdata = write_ws_xml_data(ws, opts);
16694
+ rdata = write_ws_xml_data(ws, opts, idx, wb);
16340
16695
  if(rdata.length > 0) o[o.length] = (rdata);
16341
16696
  }
16342
16697
  if(o.length>sidx+1) { o[o.length] = ('</sheetData>'); o[sidx]=o[sidx].replace("/>",">"); }
@@ -16958,6 +17313,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
16958
17313
  XLSBRecordEnum[0x0010] = { n:"BrtShortReal", f:parse_BrtShortReal };
16959
17314
 
16960
17315
  var cm;
17316
+ var date1904 = 1462 * +!!((wb||{}).WBProps||{}).date1904;
16961
17317
 
16962
17318
  recordhopper(data, function ws_parse(val, RR, RT) {
16963
17319
  if(end) return;
@@ -17001,7 +17357,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
17001
17357
  case 'str': p.t = 's'; p.v = val[1]; break;
17002
17358
  case 'is': p.t = 's'; p.v = val[1].t; break;
17003
17359
  }
17004
- if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles);
17360
+ if((cf = styles.CellXf[val[0].iStyleRef])) safe_format(p,cf.numFmtId,null,opts, themes, styles, date1904>0);
17005
17361
  C = val[0].c == -1 ? C + 1 : val[0].c;
17006
17362
  if(opts.dense) { if(!s["!data"][R]) s["!data"][R] = []; s["!data"][R][C] = p; }
17007
17363
  else s[encode_col(C) + rr] = p;
@@ -17022,7 +17378,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
17022
17378
  if(refguess.e.r < row.r) refguess.e.r = row.r;
17023
17379
  if(refguess.e.c < C) refguess.e.c = C;
17024
17380
  if(opts.cellDates && cf && p.t == 'n' && fmt_is_date(table_fmt[cf.numFmtId])) {
17025
- var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
17381
+ var _d = SSF_parse_date_code(p.v + date1904); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
17026
17382
  }
17027
17383
  if(cm) {
17028
17384
  if(cm.type == 'XLDAPR') p.D = true;
@@ -17100,6 +17456,10 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
17100
17456
  }
17101
17457
  break;
17102
17458
 
17459
+ case 0x0227: /* 'BrtLegacyDrawing' */
17460
+ if(val) s["!legrel"] = val;
17461
+ break;
17462
+
17103
17463
  case 0x00A1: /* 'BrtBeginAFilter' */
17104
17464
  s['!autofilter'] = { ref:encode_range(val) };
17105
17465
  break;
@@ -17156,7 +17516,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
17156
17516
  case 0x0499: /* 'BrtFilter14' */
17157
17517
  case 0x00A9: /* 'BrtIconFilter' */
17158
17518
  case 0x049D: /* 'BrtIconFilter14' */
17159
- case 0x0227: /* 'BrtLegacyDrawing' */
17160
17519
  case 0x0228: /* 'BrtLegacyDrawingHF' */
17161
17520
  case 0x0295: /* 'BrtListPart' */
17162
17521
  case 0x027F: /* 'BrtOleObject' */
@@ -17215,11 +17574,12 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
17215
17574
  if(merges.length > 0) s["!merges"] = merges;
17216
17575
  if(colinfo.length > 0) s["!cols"] = colinfo;
17217
17576
  if(rowinfo.length > 0) s["!rows"] = rowinfo;
17577
+ if(rels['!id'][s['!legrel']]) s['!legdrawel'] = rels['!id'][s['!legrel']];
17218
17578
  return s;
17219
17579
  }
17220
17580
 
17221
17581
  /* TODO: something useful -- this is a stub */
17222
- function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/)/*:boolean*/ {
17582
+ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, ws/*:Worksheet*/, last_seen/*:boolean*/, date1904/*:boolean*/)/*:boolean*/ {
17223
17583
  var o/*:any*/ = ({r:R, c:C}/*:any*/);
17224
17584
  if(cell.c) ws['!comments'].push([encode_cell(o), cell.c]);
17225
17585
  if(cell.v === undefined) return false;
@@ -17229,7 +17589,7 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
17229
17589
  case 'd': // no BrtCellDate :(
17230
17590
  cell = dup(cell);
17231
17591
  cell.z = cell.z || table_fmt[14];
17232
- cell.v = datenum(parseDate(cell.v)); cell.t = 'n';
17592
+ cell.v = datenum(parseDate(cell.v, date1904), date1904); cell.t = 'n';
17233
17593
  break;
17234
17594
  /* falls through */
17235
17595
  case 'n': case 'e': vv = ''+cell.v; break;
@@ -17256,6 +17616,12 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
17256
17616
  if(cell.v == (cell.v | 0) && cell.v > -1000 && cell.v < 1000) {
17257
17617
  if(last_seen) write_record(ba, 0x000D /* BrtShortRk */, write_BrtShortRk(cell, o));
17258
17618
  else write_record(ba, 0x0002 /* BrtCellRk */, write_BrtCellRk(cell, o));
17619
+ } else if(isNaN(cell.v)) {
17620
+ if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x24}, o)); // #NUM!
17621
+ else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x24}, o)); // #NUM!
17622
+ } else if(!isFinite(cell.v)) {
17623
+ if(last_seen) write_record(ba, 0x000E /* BrtShortError */, write_BrtShortError({t:"e", v: 0x07}, o)); // #DIV/0!
17624
+ else write_record(ba, 0x0003 /* BrtCellError */, write_BrtCellError({t:"e", v: 0x07}, o)); // #DIV/0!
17259
17625
  } else {
17260
17626
  if(last_seen) write_record(ba, 0x0010 /* BrtShortReal */, write_BrtShortReal(cell, o));
17261
17627
  else write_record(ba, 0x0005 /* BrtCellReal */, write_BrtCellReal(cell, o));
@@ -17276,8 +17642,9 @@ function write_ws_bin_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:num
17276
17642
  return true;
17277
17643
  }
17278
17644
 
17279
- function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
17645
+ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
17280
17646
  var range = safe_decode_range(ws['!ref'] || "A1"), ref, rr = "", cols/*:Array<string>*/ = [];
17647
+ var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
17281
17648
  write_record(ba, 0x0091 /* BrtBeginSheetData */);
17282
17649
  var dense = ws["!data"] != null;
17283
17650
  var cap = range.e.r;
@@ -17295,7 +17662,7 @@ function write_CELLTABLE(ba, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Work
17295
17662
  var cell = dense ? (ws["!data"][R]||[])[C] : ws[ref];
17296
17663
  if(!cell) { last_seen = false; continue; }
17297
17664
  /* write cell */
17298
- last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen);
17665
+ last_seen = write_ws_bin_cell(ba, cell, R, C, opts, ws, last_seen, date1904);
17299
17666
  }
17300
17667
  }
17301
17668
  write_record(ba, 0x0092 /* BrtEndSheetData */);
@@ -17405,7 +17772,7 @@ function write_ws_bin(idx/*:number*/, opts, wb/*:Workbook*/, rels) {
17405
17772
  write_record(ba, 0x0094 /* BrtWsDim */, write_BrtWsDim(r));
17406
17773
  write_WSVIEWS2(ba, ws, wb.Workbook);
17407
17774
  write_COLINFOS(ba, ws);
17408
- write_CELLTABLE(ba, ws, idx, opts);
17775
+ write_CELLTABLE(ba, ws, idx, opts, wb);
17409
17776
  /* [BrtSheetCalcProp] */
17410
17777
  write_SHEETPROTECT(ba, ws);
17411
17778
  /* *([BrtRangeProtectionIso] BrtRangeProtection) */
@@ -18447,10 +18814,10 @@ function xlml_parsexmltagobj(tag/*:string*/) {
18447
18814
  /* map from xlml named formats to SSF TODO: localize */
18448
18815
  var XLMLFormatMap/*: {[string]:string}*/;
18449
18816
 
18450
- function xlml_format(format, value)/*:string*/ {
18817
+ function xlml_format(format, value, date1904)/*:string*/ {
18451
18818
  var fmt = XLMLFormatMap[format] || unescapexml(format);
18452
18819
  if(fmt === "General") return SSF_general(value);
18453
- return SSF_format(fmt, value);
18820
+ return SSF_format(fmt, value, {date1904: !!date1904});
18454
18821
  }
18455
18822
 
18456
18823
  function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
@@ -18466,7 +18833,7 @@ function xlml_set_custprop(Custprops, key, cp, val/*:string*/) {
18466
18833
  Custprops[unescapexml(key)] = oval;
18467
18834
  }
18468
18835
 
18469
- function safe_format_xlml(cell/*:Cell*/, nf, o) {
18836
+ function safe_format_xlml(cell/*:Cell*/, nf, o, date1904) {
18470
18837
  if(cell.t === 'z') return;
18471
18838
  if(!o || o.cellText !== false) try {
18472
18839
  if(cell.t === 'e') { cell.w = cell.w || BErr[cell.v]; }
@@ -18477,13 +18844,13 @@ function safe_format_xlml(cell/*:Cell*/, nf, o) {
18477
18844
  }
18478
18845
  else cell.w = SSF_general(cell.v);
18479
18846
  }
18480
- else cell.w = xlml_format(nf||"General", cell.v);
18847
+ else cell.w = xlml_format(nf||"General", cell.v, date1904);
18481
18848
  } catch(e) { if(o.WTF) throw e; }
18482
18849
  try {
18483
18850
  var z = XLMLFormatMap[nf]||nf||"General";
18484
18851
  if(o.cellNF) cell.z = z;
18485
18852
  if(o.cellDates && cell.t == 'n' && fmt_is_date(z)) {
18486
- var _d = SSF_parse_date_code(cell.v); if(_d) { cell.t = 'd'; cell.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
18853
+ var _d = SSF_parse_date_code(cell.v + (date1904 ? 1462 : 0)); if(_d) { cell.t = 'd'; cell.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
18487
18854
  }
18488
18855
  } catch(e) { if(o.WTF) throw e; }
18489
18856
  }
@@ -18499,7 +18866,7 @@ function process_style_xlml(styles, stag, opts) {
18499
18866
  }
18500
18867
 
18501
18868
  /* TODO: there must exist some form of OSP-blessed spec */
18502
- function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o) {
18869
+ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, arrayf, o, date1904) {
18503
18870
  var nf = "General", sid = cell.StyleID, S = {}; o = o || {};
18504
18871
  var interiors = [];
18505
18872
  var i = 0;
@@ -18522,9 +18889,8 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
18522
18889
  break;
18523
18890
  case 'DateTime':
18524
18891
  if(xml.slice(-1) != "Z") xml += "Z";
18525
- cell.v = (parseDate(xml) - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
18892
+ cell.v = datenum(parseDate(xml, date1904), date1904);
18526
18893
  if(cell.v !== cell.v) cell.v = unescapexml(xml);
18527
- else if(cell.v<60) cell.v = cell.v -1;
18528
18894
  if(!nf || nf == "General") nf = "yyyy-mm-dd";
18529
18895
  /* falls through */
18530
18896
  case 'Number':
@@ -18537,7 +18903,7 @@ function parse_xlml_data(xml, ss, data, cell/*:any*/, base, styles, csty, row, a
18537
18903
  else { cell.t = 's'; cell.v = xlml_fixstr(ss||xml); }
18538
18904
  break;
18539
18905
  }
18540
- safe_format_xlml(cell, nf, o);
18906
+ safe_format_xlml(cell, nf, o, date1904);
18541
18907
  if(o.cellFormula !== false) {
18542
18908
  if(cell.Formula) {
18543
18909
  var fstr = unescapexml(cell.Formula);
@@ -18637,7 +19003,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
18637
19003
  break;
18638
19004
  }
18639
19005
  if(state[state.length-1][1]) break;
18640
- if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts);
19006
+ if(Rn[1]==='/') parse_xlml_data(str.slice(didx, Rn.index), ss, dtag, state[state.length-1][0]==/*"Comment"*/"comment"?comment:cell, {c:c,r:r}, styles, cstys[c], row, arrayf, opts, Workbook.WBProps.date1904);
18641
19007
  else { ss = ""; dtag = xlml_parsexmltag(Rn[0]); didx = Rn.index + Rn[0].length; }
18642
19008
  break;
18643
19009
  case 'cell' /*case 'Cell'*/:
@@ -18848,6 +19214,7 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
18848
19214
  } else {
18849
19215
  state.push([Rn[3], false]);
18850
19216
  tmp = xlml_parsexmltag(Rn[0]);
19217
+ if(!parsexmlbool(tmp["ShowAlways"]||"0")) comments.hidden = true;
18851
19218
  comment = ({a:tmp.Author}/*:any*/);
18852
19219
  }
18853
19220
  break;
@@ -18939,6 +19306,9 @@ function parse_xlml_xml(d, _opts)/*:Workbook*/ {
18939
19306
  /*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
18940
19307
  Workbook.WBProps.date1904 = true;
18941
19308
  break;
19309
+ case 'hidehorizontalscrollbar' /*case 'HideHorizontalScrollBar'*/: break;
19310
+ case 'hideverticalscrollbar' /*case 'HideVerticalScrollBar'*/: break;
19311
+ case 'hideworkbooktabs' /*case 'HideWorkbookTabs'*/: break;
18942
19312
  case 'windowheight' /*case 'WindowHeight'*/: break;
18943
19313
  case 'windowwidth' /*case 'WindowWidth'*/: break;
18944
19314
  case 'windowtopx' /*case 'WindowTopX'*/: break;
@@ -19507,11 +19877,15 @@ function write_ws_xlml_wsopts(ws/*:Worksheet*/, opts, idx/*:number*/, wb/*:Workb
19507
19877
  return writextag("WorksheetOptions", o.join(""), {xmlns:XLMLNS.x});
19508
19878
  }
19509
19879
  function write_ws_xlml_comment(comments/*:Array<any>*/)/*:string*/ {
19880
+ /* TODO: test multiple comments */
19510
19881
  return comments.map(function(c) {
19511
19882
  // TODO: formatted text
19512
19883
  var t = xlml_unfixstr(c.t||"");
19513
19884
  var d =writextag("ss:Data", t, {"xmlns":"http://www.w3.org/TR/REC-html40"});
19514
- return writextag("Comment", d, {"ss:Author":c.a});
19885
+ var p = {};
19886
+ if(c.a) p["ss:Author"] = c.a;
19887
+ if(!comments.hidden) p["ss:ShowAlways"] = "1";
19888
+ return writextag("Comment", d, p);
19515
19889
  }).join("");
19516
19890
  }
19517
19891
  function write_ws_xlml_cell(cell, ref/*:string*/, ws, opts, idx/*:number*/, wb, addr)/*:string*/{
@@ -19732,7 +20106,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
19732
20106
  var fmtid = 0;
19733
20107
  try {
19734
20108
  fmtid = p.z || p.XF.numFmtId || 0;
19735
- if(opts.cellNF) p.z = table_fmt[fmtid];
20109
+ if(opts.cellNF && p.z == null) p.z = table_fmt[fmtid];
19736
20110
  } catch(e) { if(opts.WTF) throw e; }
19737
20111
  if(!opts || opts.cellText !== false) try {
19738
20112
  if(p.t === 'e') { p.w = p.w || BErr[p.v]; }
@@ -19746,7 +20120,7 @@ function safe_format_xf(p/*:any*/, opts/*:ParseOpts*/, date1904/*:?boolean*/) {
19746
20120
  else p.w = SSF_format(fmtid,p.v, {date1904:!!date1904, dateNF: opts && opts.dateNF});
19747
20121
  } catch(e) { if(opts.WTF) throw e; }
19748
20122
  if(opts.cellDates && fmtid && p.t == 'n' && fmt_is_date(table_fmt[fmtid] || String(fmtid))) {
19749
- var _d = SSF_parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
20123
+ var _d = SSF_parse_date_code(p.v + (date1904 ? 1462 : 0)); if(_d) { p.t = 'd'; p.v = new Date(Date.UTC(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u)); }
19750
20124
  }
19751
20125
  }
19752
20126
 
@@ -19773,6 +20147,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
19773
20147
  var XFs = []; /* XF records */
19774
20148
  var palette/*:Array<[number, number, number]>*/ = [];
19775
20149
  var Workbook/*:WBWBProps*/ = ({ Sheets:[], WBProps:{date1904:false}, Views:[{}] }/*:any*/), wsprops = {};
20150
+ var biff4w = false;
19776
20151
  var get_rgb = function getrgb(icv/*:number*/)/*:[number, number, number]*/ {
19777
20152
  if(icv < 8) return XLSIcv[icv];
19778
20153
  if(icv < 64) return palette[icv-8] || XLSIcv[icv];
@@ -19788,7 +20163,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
19788
20163
  if((t = rgb2Hex(get_rgb(xfd.icvBack)))) { line.s.bgColor = {rgb:t}; }
19789
20164
  };
19790
20165
  var addcell = function addcell(cell/*:any*/, line/*:any*/, options/*:any*/) {
19791
- if(file_depth > 1) return;
20166
+ if(!biff4w && file_depth > 1) return;
19792
20167
  if(options.sheetRows && cell.r >= options.sheetRows) return;
19793
20168
  if(options.cellStyles && line.XF && line.XF.data) process_cell_style(cell, line, options);
19794
20169
  delete line.ixfe; delete line.XF;
@@ -19919,6 +20294,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
19919
20294
  if(!val.fBelow) (out["!outline"] || (out["!outline"] = {})).above = true;
19920
20295
  if(!val.fRight) (out["!outline"] || (out["!outline"] = {})).left = true;
19921
20296
  break; // TODO
20297
+ case 0x0043: /* BIFF2XF */ case 0x0243: /* BIFF3XF */ case 0x0443: /* BIFF4XF */
19922
20298
  case 0x00e0 /* XF */:
19923
20299
  XFs.push(val); break;
19924
20300
  case 0x01ae /* SupBook */:
@@ -19953,11 +20329,11 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
19953
20329
  case 0x0012 /* Protect */: out["!protect"] = val; break; /* for sheet or book */
19954
20330
  case 0x0013 /* Password */: if(val !== 0 && opts.WTF) console.error("Password verifier: " + val); break;
19955
20331
  case 0x0085 /* BoundSheet8 */: {
19956
- Directory[val.pos] = val;
20332
+ Directory[opts.biff == 4 ? opts.snames.length : val.pos] = val;
19957
20333
  opts.snames.push(val.name);
19958
20334
  } break;
19959
20335
  case 0x000a /* EOF */: {
19960
- if(--file_depth) break;
20336
+ if(--file_depth ? !biff4w : biff4w) break;
19961
20337
  if(range.e) {
19962
20338
  if(range.e.r > 0 && range.e.c > 0) {
19963
20339
  range.e.r--; range.e.c--;
@@ -19996,13 +20372,15 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
19996
20372
  }[val.BIFFVer] || 8;
19997
20373
  opts.biffguess = val.BIFFVer == 0;
19998
20374
  if(val.BIFFVer == 0 && val.dt == 0x1000) { opts.biff = 5; seen_codepage = true; set_cp(opts.codepage = 28591); }
20375
+ if(opts.biff == 4 && val.dt & 0x100) biff4w = true;
19999
20376
  if(opts.biff == 8 && val.BIFFVer == 0 && val.dt == 16) opts.biff = 2;
20000
- if(file_depth++) break;
20377
+ if(file_depth++ && !biff4w) break;
20001
20378
  out = ({}/*:any*/); if(options.dense) out["!data"] = [];
20002
20379
 
20003
20380
  if(opts.biff < 8 && !seen_codepage) { seen_codepage = true; set_cp(opts.codepage = options.codepage || 1252); }
20004
-
20005
- if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
20381
+ if(opts.biff == 4 && biff4w) {
20382
+ cur_sheet = (Directory[opts.snames.indexOf(cur_sheet)+1] || {name:""}).name;
20383
+ } else if(opts.biff < 5 || val.BIFFVer == 0 && val.dt == 0x1000) {
20006
20384
  if(cur_sheet === "") cur_sheet = "Sheet1";
20007
20385
  range = {s:{r:0,c:0},e:{r:0,c:0}};
20008
20386
  /* fake BoundSheet8 */
@@ -20023,19 +20401,19 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20023
20401
  case 0x0203 /* Number */: case 0x0003 /* BIFF2NUM */: case 0x0002 /* BIFF2INT */: {
20024
20402
  if(out["!type"] == "chart") if(options.dense ? (out["!data"][val.r]||[])[val.c]: out[encode_col(val.c) + encode_row(val.r)]) ++val.c;
20025
20403
  temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe]||{}, v:val.val, t:'n'}/*:any*/);
20026
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20404
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20027
20405
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20028
20406
  addcell({c:val.c, r:val.r}, temp_val, options);
20029
20407
  } break;
20030
20408
  case 0x0005: case 0x0205 /* BoolErr */: {
20031
20409
  temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.val, t:val.t}/*:any*/);
20032
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20410
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20033
20411
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20034
20412
  addcell({c:val.c, r:val.r}, temp_val, options);
20035
20413
  } break;
20036
20414
  case 0x027e /* RK */: {
20037
20415
  temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], v:val.rknum, t:'n'}/*:any*/);
20038
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20416
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20039
20417
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20040
20418
  addcell({c:val.c, r:val.r}, temp_val, options);
20041
20419
  } break;
@@ -20043,7 +20421,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20043
20421
  for(var j = val.c; j <= val.C; ++j) {
20044
20422
  var ixfe = val.rkrec[j-val.c][0];
20045
20423
  temp_val= ({ixfe:ixfe, XF:XFs[ixfe], v:val.rkrec[j-val.c][1], t:'n'}/*:any*/);
20046
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20424
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20047
20425
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20048
20426
  addcell({c:j, r:val.r}, temp_val, options);
20049
20427
  }
@@ -20061,7 +20439,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20061
20439
  else temp_val.F = ((options.dense ? (out["!data"][_fr]||[])[_fc]: out[_fe]) || {}).F;
20062
20440
  } else temp_val.f = ""+stringify_formula(val.formula,range,val.cell,supbooks, opts);
20063
20441
  }
20064
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20442
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20065
20443
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20066
20444
  addcell(val.cell, temp_val, options);
20067
20445
  last_formula = val;
@@ -20074,7 +20452,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20074
20452
  if(options.cellFormula) {
20075
20453
  temp_val.f = ""+stringify_formula(last_formula.formula, range, last_formula.cell, supbooks, opts);
20076
20454
  }
20077
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20455
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20078
20456
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20079
20457
  addcell(last_formula.cell, temp_val, options);
20080
20458
  last_formula = null;
@@ -20105,13 +20483,13 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20105
20483
  temp_val=make_cell(sst[val.isst].t, val.ixfe, 's');
20106
20484
  if(sst[val.isst].h) temp_val.h = sst[val.isst].h;
20107
20485
  temp_val.XF = XFs[temp_val.ixfe];
20108
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20486
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20109
20487
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20110
20488
  addcell({c:val.c, r:val.r}, temp_val, options);
20111
20489
  break;
20112
20490
  case 0x0201 /* Blank */: if(options.sheetStubs) {
20113
20491
  temp_val = ({ixfe: val.ixfe, XF: XFs[val.ixfe], t:'z'}/*:any*/);
20114
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20492
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20115
20493
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20116
20494
  addcell({c:val.c, r:val.r}, temp_val, options);
20117
20495
  } break;
@@ -20119,7 +20497,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20119
20497
  for(var _j = val.c; _j <= val.C; ++_j) {
20120
20498
  var _ixfe = val.ixfe[_j-val.c];
20121
20499
  temp_val= ({ixfe:_ixfe, XF:XFs[_ixfe], t:'z'}/*:any*/);
20122
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20500
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20123
20501
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20124
20502
  addcell({c:_j, r:val.r}, temp_val, options);
20125
20503
  }
@@ -20128,7 +20506,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20128
20506
  case 0x0204 /* Label */: case 0x0004 /* BIFF2STR */:
20129
20507
  temp_val=make_cell(val.val, val.ixfe, 's');
20130
20508
  temp_val.XF = XFs[temp_val.ixfe];
20131
- if(BIFF2Fmt > 0) temp_val.z = BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20509
+ if(BIFF2Fmt > 0) temp_val.z = (temp_val.XF && temp_val.XF.numFmtId) && BIFF2FmtTable[temp_val.XF.numFmtId] || BIFF2FmtTable[(temp_val.ixfe>>8) & 0x3F];
20132
20510
  safe_format_xf(temp_val, options, wb.opts.Date1904);
20133
20511
  addcell({c:val.c, r:val.r}, temp_val, options);
20134
20512
  break;
@@ -20140,7 +20518,7 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20140
20518
  sst = val;
20141
20519
  } break;
20142
20520
  case 0x041e /* Format */: { /* val = [id, fmt] */
20143
- if(opts.biff == 4) {
20521
+ if(opts.biff >= 3 && opts.biff <= 4) {
20144
20522
  BIFF2FmtTable[BIFF2Fmt++] = val[1];
20145
20523
  for(var b4idx = 0; b4idx < BIFF2Fmt + 163; ++b4idx) if(table_fmt[b4idx] == val[1]) break;
20146
20524
  if(b4idx >= 163) SSF__load(val[1], BIFF2Fmt + 163);
@@ -20174,9 +20552,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20174
20552
  }
20175
20553
  } break;
20176
20554
  case 0x001c /* Note */: {
20177
- if(opts.biff <= 5 && opts.biff >= 2) break; /* TODO: BIFF5 */
20555
+ /* TODO: comment continuation (row == -1 / 0xFFFF) */
20178
20556
  cc = options.dense ? (out["!data"][val[0].r]||[])[val[0].c] : out[encode_cell(val[0])];
20179
- var noteobj = objects[val[2]];
20180
20557
  if(!cc) {
20181
20558
  if(options.dense) {
20182
20559
  if(!out["!data"][val[0].r]) out["!data"][val[0].r] = [];
@@ -20190,7 +20567,12 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
20190
20567
  range.s.c = Math.min(range.s.c, val[0].c);
20191
20568
  }
20192
20569
  if(!cc.c) cc.c = [];
20193
- cmnt = {a:val[1],t:noteobj.TxO.t};
20570
+ if(opts.biff <= 5 && opts.biff >= 2) cmnt = {a:"SheetJ5", t:val[1]};
20571
+ else {
20572
+ var noteobj = objects[val[2]];
20573
+ cmnt = {a:val[1],t:noteobj.TxO.t};
20574
+ if(val[3] != null && !(val[3] & 0x02)) cc.c.hidden = true;
20575
+ }
20194
20576
  cc.c.push(cmnt);
20195
20577
  } break;
20196
20578
  case 0x087d /* XFExt */: update_xfext(XFs[val.ixfe], val.ext); break;
@@ -20863,7 +21245,7 @@ var XLSBRecordEnum = {
20863
21245
  /*::[*/0x0224/*::]*/: { /* n:"BrtFileSharing" */ },
20864
21246
  /*::[*/0x0225/*::]*/: { /* n:"BrtOleSize" */ },
20865
21247
  /*::[*/0x0226/*::]*/: { /* n:"BrtDrawing", */ f:parse_RelID },
20866
- /*::[*/0x0227/*::]*/: { /* n:"BrtLegacyDrawing" */ },
21248
+ /*::[*/0x0227/*::]*/: { /* n:"BrtLegacyDrawing", */ f:parse_XLNullableWideString },
20867
21249
  /*::[*/0x0228/*::]*/: { /* n:"BrtLegacyDrawingHF" */ },
20868
21250
  /*::[*/0x0229/*::]*/: { /* n:"BrtWebOpt" */ },
20869
21251
  /*::[*/0x022A/*::]*/: { /* n:"BrtBeginWebPubItems", */ T:1 },
@@ -21602,7 +21984,7 @@ var XLSRecordEnum = {
21602
21984
  /*::[*/0x0002/*::]*/: { /* n:"BIFF2INT", */ f:parse_BIFF2INT },
21603
21985
  /*::[*/0x0003/*::]*/: { /* n:"BIFF2NUM", */ f:parse_BIFF2NUM },
21604
21986
  /*::[*/0x0004/*::]*/: { /* n:"BIFF2STR", */ f:parse_BIFF2STR },
21605
- /*::[*/0x0005/*::]*/: { /* n:"BoolErr", */ f:parse_BoolErr },
21987
+ /*::[*/0x0005/*::]*/: { /* n:"BIFF2BOOLERR", */ f:parse_BIFF2BOOLERR },
21606
21988
  /*::[*/0x0007/*::]*/: { /* n:"String", */ f:parse_BIFF2STRING },
21607
21989
  /*::[*/0x0008/*::]*/: { /* n:"BIFF2ROW", */ },
21608
21990
  /*::[*/0x0009/*::]*/: { /* n:"BOF", */ f:parse_BOF },
@@ -21614,34 +21996,34 @@ var XLSRecordEnum = {
21614
21996
  /*::[*/0x0021/*::]*/: { /* n:"Array", */ f:parse_Array },
21615
21997
  /*::[*/0x0024/*::]*/: { /* n:"COLWIDTH", */ },
21616
21998
  /*::[*/0x0025/*::]*/: { /* n:"DefaultRowHeight", */ f:parse_DefaultRowHeight },
21617
- // 0x2c ??
21618
- // 0x2d ??
21619
- // 0x2e ??
21620
- // 0x30 FONTCOUNT: number of fonts
21999
+ // 0x002c ??
22000
+ // 0x002d ??
22001
+ // 0x002e ??
22002
+ // 0x0030 FONTCOUNT: number of fonts
21621
22003
  /*::[*/0x0032/*::]*/: { /* n:"BIFF2FONTXTRA", */ f:parse_BIFF2FONTXTRA },
21622
- // 0x35: INFOOPTS
21623
- // 0x36: TABLE (BIFF2 only)
21624
- // 0x37: TABLE2 (BIFF2 only)
21625
- // 0x38: WNDESK
21626
- // 0x39 ??
21627
- // 0x3a: BEGINPREF
21628
- // 0x3b: ENDPREF
22004
+ // 0x0035: INFOOPTS
22005
+ // 0x0036: TABLE (BIFF2 only)
22006
+ // 0x0037: TABLE2 (BIFF2 only)
22007
+ // 0x0038: WNDESK
22008
+ // 0x0039 ??
22009
+ // 0x003a: BEGINPREF
22010
+ // 0x003b: ENDPREF
21629
22011
  /*::[*/0x003e/*::]*/: { /* n:"BIFF2WINDOW2", */ },
21630
- // 0x3f ??
21631
- // 0x46: SHOWSCROLL
21632
- // 0x47: SHOWFORMULA
21633
- // 0x48: STATUSBAR
21634
- // 0x49: SHORTMENUS
21635
- // 0x4A:
21636
- // 0x4B:
21637
- // 0x4C:
21638
- // 0x4E:
21639
- // 0x4F:
21640
- // 0x58: TOOLBAR (BIFF3)
22012
+ // 0x003f ??
22013
+ // 0x0046: SHOWSCROLL
22014
+ // 0x0047: SHOWFORMULA
22015
+ // 0x0048: STATUSBAR
22016
+ // 0x0049: SHORTMENUS
22017
+ // 0x004A:
22018
+ // 0x004B:
22019
+ // 0x004C:
22020
+ // 0x004E:
22021
+ // 0x004F:
22022
+ // 0x0058: TOOLBAR (BIFF3)
21641
22023
 
21642
22024
  /* - - - */
21643
22025
  /*::[*/0x0034/*::]*/: { /* n:"DDEObjName", */ },
21644
- /*::[*/0x0043/*::]*/: { /* n:"BIFF2XF", */ },
22026
+ /*::[*/0x0043/*::]*/: { /* n:"BIFF2XF", */ f:parse_BIFF2XF },
21645
22027
  /*::[*/0x0044/*::]*/: { /* n:"BIFF2XFINDEX", */ f:parseuint16 },
21646
22028
  /*::[*/0x0045/*::]*/: { /* n:"BIFF2FONTCLR", */ },
21647
22029
  /*::[*/0x0056/*::]*/: { /* n:"BIFF4FMTCNT", */ }, /* 16-bit cnt, similar to BIFF2 */
@@ -21653,7 +22035,7 @@ var XLSRecordEnum = {
21653
22035
  // 0x8A
21654
22036
  // 0x8B LH: alternate menu key flag (BIFF3/4)
21655
22037
  // 0x8E
21656
- // 0x8F
22038
+ /*::[*/0x008F/*::]*/: { /* n:"BIFF4SheetInfo", */ f:parse_BIFF4SheetInfo },
21657
22039
  /*::[*/0x0091/*::]*/: { /* n:"Sub", */ },
21658
22040
  // 0x93 STYLE
21659
22041
  /*::[*/0x0094/*::]*/: { /* n:"LHRecord", */ },
@@ -21679,10 +22061,10 @@ var XLSRecordEnum = {
21679
22061
  /*::[*/0x0218/*::]*/: { /* n:"Lbl", */ f:parse_Lbl },
21680
22062
  /*::[*/0x0223/*::]*/: { /* n:"ExternName", */ f:parse_ExternName },
21681
22063
  /*::[*/0x0231/*::]*/: { /* n:"Font", */ },
21682
- /*::[*/0x0243/*::]*/: { /* n:"BIFF3XF", */ },
22064
+ /*::[*/0x0243/*::]*/: { /* n:"BIFF3XF", */ f:parse_BIFF3XF },
21683
22065
  /*::[*/0x0406/*::]*/: { /* n:"Formula", */ f:parse_Formula },
21684
22066
  /*::[*/0x0409/*::]*/: { /* n:"BOF", */ f:parse_BOF },
21685
- /*::[*/0x0443/*::]*/: { /* n:"BIFF4XF", */ },
22067
+ /*::[*/0x0443/*::]*/: { /* n:"BIFF4XF", */ f:parse_BIFF4XF },
21686
22068
  /*::[*/0x086d/*::]*/: { /* n:"FeatInfo", */ },
21687
22069
  /*::[*/0x0873/*::]*/: { /* n:"FeatInfo11", */ },
21688
22070
  /*::[*/0x0881/*::]*/: { /* n:"SXAddl12", */ },
@@ -21746,16 +22128,7 @@ function write_biff_continue(ba/*:BufArray*/, type/*:number*/, payload, length/*
21746
22128
  }
21747
22129
  }
21748
22130
 
21749
- function write_BIFF2Cell(out, r/*:number*/, c/*:number*/) {
21750
- if(!out) out = new_buf(7);
21751
- out.write_shift(2, r);
21752
- out.write_shift(2, c);
21753
- out.write_shift(2, 0);
21754
- out.write_shift(1, 0);
21755
- return out;
21756
- }
21757
-
21758
- function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:?string*/) {
22131
+ function write_BIFF2BERR(r/*:number*/, c/*:number*/, val, t/*:string*/) {
21759
22132
  var out = new_buf(9);
21760
22133
  write_BIFF2Cell(out, r, c);
21761
22134
  write_Bes(val, t || 'b', out);
@@ -21771,25 +22144,59 @@ function write_BIFF2LABEL(r/*:number*/, c/*:number*/, val) {
21771
22144
  return out.l < out.length ? out.slice(0, out.l) : out;
21772
22145
  }
21773
22146
 
21774
- function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*//*::, opts*/) {
22147
+ function write_comments_biff2(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
22148
+ comments.forEach(function(data) {
22149
+ var text = data[0].map(function(cc) { return cc.t; }).join("");
22150
+ // TODO: should '\n' be translated to '\r' to correct for Excel 5.0 bug when exporting to BIFF2/3 ?
22151
+ if(text.length <= 2048) return write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text, data[1], data[2]));
22152
+ write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(0, 2048), data[1], data[2], text.length));
22153
+ for(var i = 2048; i < text.length; i += 2048)
22154
+ write_biff_rec(ba, 0x001C, write_NOTE_BIFF2(text.slice(i, Math.min(i+2048, text.length)), -1, -1, Math.min(2048, text.length - i)));
22155
+ });
22156
+ }
22157
+
22158
+ /* TODO: BIFF3/4 use different records -- see comments*/
22159
+ function write_ws_biff2_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
22160
+ var ifmt = 0;
22161
+ if(cell.z != null) {
22162
+ ifmt = opts._BIFF2FmtTable.indexOf(cell.z);
22163
+ if(ifmt == -1) { opts._BIFF2FmtTable.push(cell.z); ifmt = opts._BIFF2FmtTable.length - 1; }
22164
+ }
22165
+ var ixfe = 0;
22166
+ if(cell.z != null) {
22167
+ for(; ixfe < opts.cellXfs.length; ++ixfe) if(opts.cellXfs[ixfe].numFmtId == ifmt) break;
22168
+ if(ixfe == opts.cellXfs.length) opts.cellXfs.push({numFmtId: ifmt});
22169
+ }
21775
22170
  if(cell.v != null) switch(cell.t) {
21776
22171
  case 'd': case 'n':
21777
- var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
21778
- if((v == (v|0)) && (v >= 0) && (v < 65536))
21779
- write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v));
22172
+ var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
22173
+ if(opts.biff == 2 && (v == (v|0)) && (v >= 0) && (v < 65536))
22174
+ // 0x027E (RK) in BIFF3/4
22175
+ write_biff_rec(ba, 0x0002, write_BIFF2INT(R, C, v, ixfe, ifmt));
22176
+ else if(isNaN(v))
22177
+ // 0x0205 in BIFF3/4
22178
+ write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x24, "e")); // #NUM!
22179
+ else if(!isFinite(v))
22180
+ // 0x0205 in BIFF3/4
22181
+ write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, 0x07, "e")); // #DIV/0!
21780
22182
  else
21781
- write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v));
22183
+ // 0x0203 in BIFF3/4
22184
+ write_biff_rec(ba, 0x0003, write_BIFF2NUM(R,C, v, ixfe, ifmt));
21782
22185
  return;
21783
- case 'b': case 'e': write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
22186
+ case 'b': case 'e':
22187
+ // 0x0205 in BIFF3/4
22188
+ write_biff_rec(ba, 0x0005, write_BIFF2BERR(R, C, cell.v, cell.t)); return;
21784
22189
  /* TODO: codepage, sst */
21785
22190
  case 's': case 'str':
22191
+ // 0x0204 in BIFF3/4
21786
22192
  write_biff_rec(ba, 0x0004, write_BIFF2LABEL(R, C, cell.v == null ? "" : String(cell.v).slice(0,255)));
21787
22193
  return;
21788
22194
  }
22195
+ // 0x0201 in BIFF3/4
21789
22196
  write_biff_rec(ba, 0x0001, write_BIFF2Cell(null, R, C));
21790
22197
  }
21791
22198
 
21792
- function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/*::, wb:Workbook*/) {
22199
+ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts, wb/*:Workbook*/) {
21793
22200
  var dense = ws["!data"] != null;
21794
22201
  var range = safe_decode_range(ws['!ref'] || "A1"), rr = "", cols/*:Array<string>*/ = [];
21795
22202
  if(range.e.c > 0xFF || range.e.r > 0x3FFF) {
@@ -21797,7 +22204,9 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
21797
22204
  range.e.c = Math.min(range.e.c, 0xFF);
21798
22205
  range.e.r = Math.min(range.e.c, 0x3FFF);
21799
22206
  }
21800
- var row = [];
22207
+ var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
22208
+ var row = [], comments = [];
22209
+ /* TODO: 0x0000 / 0x0200 dimensions? */
21801
22210
  for(var C = range.s.c; C <= range.e.c; ++C) cols[C] = encode_col(C);
21802
22211
  for(var R = range.s.r; R <= range.e.r; ++R) {
21803
22212
  if(dense) row = ws["!data"][R] || [];
@@ -21806,26 +22215,300 @@ function write_ws_biff2(ba/*:BufArray*/, ws/*:Worksheet*/, idx/*:number*/, opts/
21806
22215
  var cell = dense ? row[C] : ws[cols[C] + rr];
21807
22216
  if(!cell) continue;
21808
22217
  /* write cell */
21809
- write_ws_biff2_cell(ba, cell, R, C);
22218
+ write_ws_biff2_cell(ba, cell, R, C, opts, date1904);
22219
+ if(cell.c) comments.push([cell.c, R, C]);
21810
22220
  }
21811
22221
  }
22222
+
22223
+ /* ... 0x12 0x19 0x13 (Password) */
22224
+ write_comments_biff2(ba, comments);
22225
+ /* 0x3d (Window1) ... */
21812
22226
  }
21813
22227
 
21814
22228
  /* Based on test files */
21815
22229
  function write_biff2_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
21816
22230
  var o = opts || {};
22231
+
21817
22232
  var ba = buf_array();
21818
22233
  var idx = 0;
21819
22234
  for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
21820
22235
  if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
21821
22236
  write_biff_rec(ba, (o.biff == 4 ? 0x0409 : (o.biff == 3 ? 0x0209 : 0x0009)), write_BOF(wb, 0x10, o));
21822
- /* ... */
21823
- write_ws_biff2(ba, wb.Sheets[wb.SheetNames[idx]], idx, o);
21824
- /* ... */
22237
+ if(((wb.Workbook||{}).WBProps||{}).date1904) write_biff_rec(ba, 0x0022, writebool(true));
22238
+ o.cellXfs = [{numFmtId: 0}];
22239
+ o._BIFF2FmtTable/*:Array<string>*/ = ["General"]; o._Fonts = [];
22240
+ var body = buf_array();
22241
+ write_ws_biff2(body, wb.Sheets[wb.SheetNames[idx]], idx, o, wb);
22242
+
22243
+ o._BIFF2FmtTable.forEach(function(f) {
22244
+ if(o.biff <= 3) write_biff_rec(ba, 0x001E, write_BIFF2Format(f));
22245
+ else write_biff_rec(ba, 0x041E, write_BIFF4Format(f));
22246
+ });
22247
+ o.cellXfs.forEach(function(xf) {
22248
+ switch(o.biff) {
22249
+ case 2: write_biff_rec(ba, 0x0043, write_BIFF2XF(xf)); break;
22250
+ case 3: write_biff_rec(ba, 0x0243, write_BIFF3XF(xf)); break;
22251
+ case 4: write_biff_rec(ba, 0x0443, write_BIFF4XF(xf)); break;
22252
+ }
22253
+ });
22254
+ delete o._BIFF2FmtTable; delete o.cellXfs; delete o._Fonts;
22255
+
22256
+ ba.push(body.end());
21825
22257
  write_biff_rec(ba, 0x000A);
21826
22258
  return ba.end();
21827
22259
  }
21828
22260
 
22261
+ var b8oid = 1, b8ocnts/*:Array<[number, number, number]>*/ = [];
22262
+ function write_MsoDrawingGroup() {
22263
+ var buf = new_buf(82 + 8 * b8ocnts.length);
22264
+ /* [MS-ODRAW] 2.2.12 OfficeArtDggContainer */
22265
+ buf.write_shift(2, 0x0F);
22266
+ buf.write_shift(2, 0xF000);
22267
+ buf.write_shift(4, 74 + 8 * b8ocnts.length);
22268
+ /* 2.2.48 OfficeArtFDGGBlock */
22269
+ {
22270
+ buf.write_shift(2, 0);
22271
+ buf.write_shift(2, 0xF006);
22272
+ buf.write_shift(4, 16 + 8 * b8ocnts.length);
22273
+ /* 2.2.47 OfficeArtFDGG */
22274
+ {
22275
+ buf.write_shift(4, b8oid);
22276
+ buf.write_shift(4, b8ocnts.length+1);
22277
+ var acc = 0; for(var i = 0; i < b8ocnts.length; ++i) acc += (b8ocnts[i] && b8ocnts[i][1] || 0); buf.write_shift(4, acc);
22278
+ buf.write_shift(4, b8ocnts.length);
22279
+ }
22280
+ /* 2.2.46 OfficeArtIDCL + */
22281
+ b8ocnts.forEach(function(b8) {
22282
+ buf.write_shift(4, b8[0]);
22283
+ buf.write_shift(4, b8[2]);
22284
+ });
22285
+ }
22286
+ /* 2.2.9 OfficeArtFOPT */
22287
+ {
22288
+ buf.write_shift(2, 0x33); // 0x03 | (3 << 4)
22289
+ buf.write_shift(2, 0xF00B);
22290
+ buf.write_shift(4, 0x12); // 3 * 6
22291
+ /* 2.3.21.15 Text Boolean Properties */
22292
+ buf.write_shift(2, 0xBF); buf.write_shift(4, 0x00080008);
22293
+ /* 2.3.7.2 fillColor */
22294
+ buf.write_shift(2, 0x0181); buf.write_shift(4, 0x08000041);
22295
+ /* 2.3.8.1 lineColor */
22296
+ buf.write_shift(2, 0x01C0); buf.write_shift(4, 0x08000040);
22297
+ }
22298
+ /* 2.2.45 OfficeArtSplitMenuColorContainer */
22299
+ {
22300
+ buf.write_shift(2, 0x40);
22301
+ buf.write_shift(2, 0xF11E);
22302
+ buf.write_shift(4, 16);
22303
+ buf.write_shift(4, 0x0800000D);
22304
+ buf.write_shift(4, 0x0800000C);
22305
+ buf.write_shift(4, 0x08000017);
22306
+ buf.write_shift(4, 0x100000F7);
22307
+ }
22308
+ return buf;
22309
+ }
22310
+ function write_comments_biff8(ba/*:BufArray*/, comments/*:Array<[Comment[], number, number]>*/) {
22311
+ var notes/*:Array<RawData>*/ = [], sz = 0, pl = buf_array(), baseid = b8oid;
22312
+ var _oasc;
22313
+ comments.forEach(function(c, ci) {
22314
+ var author = "";
22315
+ var text = c[0].map(function(t) { if(t.a && !author) author = t.a; return t.t; }).join("");
22316
+ ++b8oid;
22317
+
22318
+ /* 2.2.14 OfficeArtSpContainer */
22319
+ {
22320
+ var oasc = new_buf(0x96);
22321
+ oasc.write_shift(2, 0x0F);
22322
+ oasc.write_shift(2, 0xF004);
22323
+ oasc.write_shift(4, 0x96);
22324
+ /* 2.2.40 OfficeArtFSP */
22325
+ {
22326
+ oasc.write_shift(2, 0xca2); // 0x02 | (0xca << 4)
22327
+ oasc.write_shift(2, 0xF00A);
22328
+ oasc.write_shift(4, 8);
22329
+ oasc.write_shift(4, b8oid);
22330
+ oasc.write_shift(4, 0xA00);
22331
+ }
22332
+ /* 2.2.9 OfficeArtFOPT */
22333
+ {
22334
+ oasc.write_shift(2, 0xE3); // 0x03 | (14 << 4)
22335
+ oasc.write_shift(2, 0xF00B);
22336
+ oasc.write_shift(4, 0x54); // 14 * 6
22337
+ /* 2.3.21.1 ITxid */
22338
+ oasc.write_shift(2, 0x80); oasc.write_shift(4, 0);
22339
+ /* 2.3.21.12 txdir */
22340
+ oasc.write_shift(2, 0x8B); oasc.write_shift(4, 0x02);
22341
+ /* 2.3.21.15 Text Boolean Properties */
22342
+ oasc.write_shift(2, 0xBF); oasc.write_shift(4, 0x00080008);
22343
+ /* 2.3.6.30 cxk */
22344
+ oasc.write_shift(2, 0x0158); oasc.l += 4;
22345
+ /* 2.3.7.2 fillColor */
22346
+ oasc.write_shift(2, 0x0181); oasc.write_shift(4, 0x08000050);
22347
+ /* 2.3.7.4 fillBackColor */
22348
+ oasc.write_shift(2, 0x0183); oasc.write_shift(4, 0x08000050);
22349
+ /* 2.3.7.6 fillCrMod */
22350
+ oasc.write_shift(2, 0x0185); oasc.write_shift(4, 0x100000F4);
22351
+ /* 2.3.7.43 Fill Style Boolean Properties */
22352
+ oasc.write_shift(2, 0x01BF); oasc.write_shift(4, 0x00100010);
22353
+ /* 2.3.8.1 lineColor */
22354
+ oasc.write_shift(2, 0x01C0); oasc.write_shift(4, 0x08000051);
22355
+ /* 2.3.8.4 lineCrMod */
22356
+ oasc.write_shift(2, 0x01C3); oasc.write_shift(4, 0x100000F4);
22357
+ /* 2.3.13.2 shadowColor */
22358
+ oasc.write_shift(2, 0x0201); oasc.write_shift(4, 0x08000051);
22359
+ /* 2.3.13.4 shadowCrMod */
22360
+ oasc.write_shift(2, 0x0203); oasc.write_shift(4, 0x100000F4);
22361
+ /* 2.3.13.23 Shadow Style Boolean Properties */
22362
+ oasc.write_shift(2, 0x023F); oasc.write_shift(4, 0x00030001);
22363
+ /* 2.3.4.44 Group Shape Boolean Properties */
22364
+ oasc.write_shift(2, 0x03BF); oasc.write_shift(4, 0x00020000 | (c[0].hidden ? 2 : 0));
22365
+ }
22366
+ /* [MS-XLS] 2.5.193 OfficeArtClientAnchorSheet */
22367
+ {
22368
+ oasc.l += 2;
22369
+ oasc.write_shift(2, 0xF010);
22370
+ oasc.write_shift(4, 0x12);
22371
+ oasc.write_shift(2, 0x3); // do not move or size with cells
22372
+ oasc.write_shift(2, c[2] + 2); oasc.l += 2;
22373
+ oasc.write_shift(2, c[1] + 1); oasc.l += 2;
22374
+ oasc.write_shift(2, c[2] + 4); oasc.l += 2;
22375
+ oasc.write_shift(2, c[1] + 5); oasc.l += 2;
22376
+ }
22377
+ /* [MS-XLS] 2.5.194 OfficeArtClientData */
22378
+ {
22379
+ oasc.l += 2;
22380
+ oasc.write_shift(2, 0xF011);
22381
+ oasc.l += 4;
22382
+ }
22383
+ oasc.l = 0x96;
22384
+ if(ci == 0) /* write_biff_rec(pl, 0x003C, oasc); */ _oasc = oasc;
22385
+ else write_biff_rec(pl, 0x00EC, oasc);
22386
+ }
22387
+ sz += 0x96;
22388
+
22389
+ /* [MS-XLS] 2.4.181 Obj */
22390
+ {
22391
+ var obj = new_buf(52); // 22 + 26 + 4
22392
+ /* [MS-XLS] 2.5.143 FtCmo */
22393
+ obj.write_shift(2, 0x15);
22394
+ obj.write_shift(2, 0x12);
22395
+ obj.write_shift(2, 0x19);
22396
+ obj.write_shift(2, b8oid);
22397
+ obj.write_shift(2, 0);
22398
+ obj.l = 22;
22399
+ /* [MS-XLS] 2.5.149 FtNts */
22400
+ obj.write_shift(2, 0x0D);
22401
+ obj.write_shift(2, 0x16);
22402
+ obj.write_shift(4, 0x62726272);
22403
+ obj.write_shift(4, 0x95374305);
22404
+ obj.write_shift(4, 0x80301328);
22405
+ obj.write_shift(4, 0x69696904 + b8oid*256);
22406
+ obj.write_shift(2,0);
22407
+ obj.write_shift(4,0);
22408
+ // reserved
22409
+ obj.l += 4;
22410
+ write_biff_rec(pl, 0x005D, obj);
22411
+ }
22412
+
22413
+ /* [MS-XLS] 2.5.195 OfficeArtClientTextbox */
22414
+ {
22415
+ var oact = new_buf(8);
22416
+ oact.l += 2;
22417
+ oact.write_shift(2, 0xF00D);
22418
+ oact.l += 4;
22419
+ write_biff_rec(pl, 0x00EC, oact);
22420
+ }
22421
+ sz += 8;
22422
+
22423
+ /* [MS-XLS] 2.4.329 TxO */
22424
+ {
22425
+ var txo = new_buf(18);
22426
+ txo.write_shift(2, 0x12);
22427
+ txo.l += 8;
22428
+ txo.write_shift(2, text.length);
22429
+ txo.write_shift(2, 0x10);
22430
+ txo.l += 4;
22431
+ write_biff_rec(pl, 0x01b6, txo);
22432
+ /* text continue record TODO: switch to wide strings */
22433
+ {
22434
+ var cont = new_buf(1 + text.length);
22435
+ cont.write_shift(1, 0);
22436
+ cont.write_shift(text.length, text, "sbcs");
22437
+ write_biff_rec(pl, 0x003C, cont);
22438
+ }
22439
+ /* formatting continue records */
22440
+ {
22441
+ var conf = new_buf(0x10);
22442
+ conf.l += 8;
22443
+ conf.write_shift(2, text.length);
22444
+ conf.l += 6;
22445
+ write_biff_rec(pl, 0x003C, conf);
22446
+ }
22447
+ }
22448
+
22449
+ /* 2.4.179 Note */
22450
+ {
22451
+ var notesh = new_buf(12 + author.length);
22452
+ notesh.write_shift(2, c[1]);
22453
+ notesh.write_shift(2, c[2]);
22454
+ notesh.write_shift(2, 0 | (c[0].hidden ? 0 : 2));
22455
+ notesh.write_shift(2, b8oid);
22456
+ notesh.write_shift(2, author.length);
22457
+ notesh.write_shift(1, 0);
22458
+ notesh.write_shift(author.length, author, "sbcs");
22459
+ notesh.l ++;
22460
+ notes.push(notesh);
22461
+ }
22462
+ });
22463
+ /* [MS-ODRAW] 2.2.13 OfficeArtDgContainer */
22464
+ {
22465
+ var hdr = new_buf(80);
22466
+ hdr.write_shift(2, 0x0F);
22467
+ hdr.write_shift(2, 0xF002);
22468
+ hdr.write_shift(4, sz + hdr.length - 8);
22469
+ /* [MS-ODRAW] 2.2.49 OfficeArtFDG */
22470
+ {
22471
+ hdr.write_shift(2, 0x10);
22472
+ hdr.write_shift(2, 0xF008);
22473
+ hdr.write_shift(4, 0x08);
22474
+ hdr.write_shift(4, comments.length + 1);
22475
+ hdr.write_shift(4, b8oid);
22476
+ }
22477
+ /* [MS-ODRAW] 2.2.16 OfficeArtSpgrContainer */
22478
+ {
22479
+ hdr.write_shift(2, 0x0f);
22480
+ hdr.write_shift(2, 0xF003);
22481
+ hdr.write_shift(4, sz + 0x30);
22482
+ /* [MS-ODRAW] 2.2.14 OfficeArtSpContainer */
22483
+ {
22484
+ hdr.write_shift(2, 0x0f);
22485
+ hdr.write_shift(2, 0xF004);
22486
+ hdr.write_shift(4, 0x28);
22487
+ /* [MS-ODRAW] 2.2.38 OfficeArtFSPGR */
22488
+ {
22489
+ hdr.write_shift(2, 0x01);
22490
+ hdr.write_shift(2, 0xF009);
22491
+ hdr.write_shift(4, 0x10);
22492
+ hdr.l += 16;
22493
+ }
22494
+ /* [MS-ODRAW] 2.2.40 OfficeArtFSP */
22495
+ {
22496
+ hdr.write_shift(2, 0x02);
22497
+ hdr.write_shift(2, 0xF00A);
22498
+ hdr.write_shift(4, 0x08);
22499
+ hdr.write_shift(4, baseid);
22500
+ hdr.write_shift(4, 0x05);
22501
+ }
22502
+ }
22503
+ }
22504
+ write_biff_rec(ba, 0x00EC, /* hdr */ _oasc ? bconcat([hdr, _oasc]) : hdr);
22505
+ }
22506
+ ba.push(pl.end());
22507
+ notes.forEach(function(n) { write_biff_rec(ba, 0x001C, n); });
22508
+ b8ocnts.push([baseid, comments.length + 1, b8oid]);
22509
+ ++b8oid;
22510
+ }
22511
+
21829
22512
  function write_FONTS_biff8(ba, data, opts) {
21830
22513
  write_biff_rec(ba, 0x0031 /* Font */, write_Font({
21831
22514
  sz:12,
@@ -21887,7 +22570,7 @@ function write_ws_cols_biff8(ba, cols) {
21887
22570
  });
21888
22571
  }
21889
22572
 
21890
- function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts) {
22573
+ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:number*/, opts, date1904/*:boolean*/) {
21891
22574
  var os = 16 + get_cell_style(opts.cellXfs, cell, opts);
21892
22575
  if(cell.v == null && !cell.bf) {
21893
22576
  write_biff_rec(ba, 0x0201 /* Blank */, write_XLSCell(R, C, os));
@@ -21896,9 +22579,11 @@ function write_ws_biff8_cell(ba/*:BufArray*/, cell/*:Cell*/, R/*:number*/, C/*:n
21896
22579
  if(cell.bf) write_biff_rec(ba, 0x0006 /* Formula */, write_Formula(cell, R, C, opts, os));
21897
22580
  else switch(cell.t) {
21898
22581
  case 'd': case 'n':
21899
- var v = cell.t == 'd' ? datenum(parseDate(cell.v)) : cell.v;
22582
+ var v = cell.t == 'd' ? datenum(parseDate(cell.v, date1904), date1904) : cell.v;
22583
+ if(isNaN(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x24, os, opts, "e")); // #NUM!
22584
+ else if(!isFinite(v)) write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, 0x07, os, opts, "e")); // #DIV/0!
21900
22585
  /* TODO: emit RK as appropriate */
21901
- write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os));
22586
+ else write_biff_rec(ba, 0x0203 /* Number */, write_Number(R, C, v, os));
21902
22587
  break;
21903
22588
  case 'b': case 'e':
21904
22589
  write_biff_rec(ba, 0x0205 /* BoolErr */, write_BoolErr(R, C, cell.v, os, opts, cell.t));
@@ -21955,6 +22640,7 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
21955
22640
  write_biff_rec(ba, 0x0200 /* Dimensions */, write_Dimensions(range, opts));
21956
22641
  /* ... */
21957
22642
 
22643
+ var date1904 = (((wb||{}).Workbook||{}).WBProps||{}).date1904;
21958
22644
  if(b8) ws['!links'] = [];
21959
22645
  var comments = [];
21960
22646
  var row = [];
@@ -21967,14 +22653,14 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
21967
22653
  var cell = dense ? row[C] : ws[ref];
21968
22654
  if(!cell) continue;
21969
22655
  /* write cell */
21970
- write_ws_biff8_cell(ba, cell, R, C, opts);
22656
+ write_ws_biff8_cell(ba, cell, R, C, opts, date1904);
21971
22657
  if(b8 && cell.l) ws['!links'].push([ref, cell.l]);
21972
- if(b8 && cell.c) comments.push([ref, cell.c]);
22658
+ if(cell.c) comments.push([cell.c, R, C]);
21973
22659
  }
21974
22660
  }
21975
22661
  var cname/*:string*/ = _sheet.CodeName || _sheet.name || s;
21976
22662
  /* ... */
21977
- // if(b8) comments.forEach(function(comment) { write_biff_rec(ba, 0x001c /* Note */, write_NoteSh(comment)); });
22663
+ if(b8) write_comments_biff8(ba, comments); else write_comments_biff2(ba, comments);
21978
22664
  /* ... */
21979
22665
  if(b8) write_biff_rec(ba, 0x023e /* Window2 */, write_Window2((_WB.Views||[])[0]));
21980
22666
  /* ... */
@@ -22044,8 +22730,10 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
22044
22730
  var C = buf_array();
22045
22731
  /* METADATA [MTRSettings] [ForceFullCalculation] */
22046
22732
  if(b8) write_biff_rec(C, 0x008C /* Country */, write_Country());
22047
- /* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture *MSODRAWINGGROUP */
22733
+ /* *SUPBOOK *LBL *RTD [RecalcId] *HFPicture */
22048
22734
 
22735
+ /* BIFF8: MsoDrawingGroup [*Continue] */
22736
+ if(b8 && b8ocnts.length) write_biff_rec(C, 0x00EB /* MsoDrawingGroup */, write_MsoDrawingGroup());
22049
22737
  /* BIFF8: [SST *Continue] ExtSST */
22050
22738
  if(b8 && opts.Strings) write_biff_continue(C, 0x00FC /* SST */, write_SST(opts.Strings));
22051
22739
 
@@ -22088,6 +22776,7 @@ function write_biff8_buf(wb/*:Workbook*/, opts/*:WriteOpts*/) {
22088
22776
  o.ssf = wb.SSF;
22089
22777
  }
22090
22778
 
22779
+ b8oid = 1; b8ocnts = [];
22091
22780
  o.Strings = /*::((*/[]/*:: :any):SST)*/; o.Strings.Count = 0; o.Strings.Unique = 0;
22092
22781
  fix_write_opts(o);
22093
22782
 
@@ -22165,9 +22854,11 @@ function html_to_sheet(str/*:string*/, _opts)/*:Workbook*/ {
22165
22854
  else if(!isNaN(fuzzynum(m))) o = {t:'n', v:fuzzynum(m)};
22166
22855
  else if(!isNaN(fuzzydate(m).getDate())) {
22167
22856
  o = ({t:'d', v:parseDate(m)}/*:any*/);
22857
+ if(opts.UTC === false) o.v = utc_to_local(o.v);
22168
22858
  if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
22169
22859
  o.z = opts.dateNF || table_fmt[14];
22170
22860
  }
22861
+ if(o.cellText !== false) o.w = m;
22171
22862
  if(dense) { if(!ws["!data"][R]) ws["!data"][R] = []; ws["!data"][R][C] = o; }
22172
22863
  else ws[encode_cell({r:R, c:C})] = o;
22173
22864
  C += CS;
@@ -22201,7 +22892,8 @@ function make_html_row(ws/*:Worksheet*/, r/*:Range*/, R/*:number*/, o/*:Sheet2HT
22201
22892
  if(o.editable) w = '<span contenteditable="true">' + w + '</span>';
22202
22893
  else if(cell) {
22203
22894
  sp["data-t"] = cell && cell.t || 'z';
22204
- if(cell.v != null) sp["data-v"] = cell.v;
22895
+ // note: data-v is unaffected by the timezone interpretation
22896
+ if(cell.v != null) sp["data-v"] = cell.v instanceof Date ? cell.v.toISOString() : cell.v;
22205
22897
  if(cell.z != null) sp["data-z"] = cell.z;
22206
22898
  if(cell.l && (cell.l.Target || "#").charAt(0) != "#") w = '<a href="' + escapehtml(cell.l.Target) +'">' + w + '</a>';
22207
22899
  }
@@ -22307,6 +22999,7 @@ function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/
22307
22999
  else if(!isNaN(fuzzynum(v))) o = {t:'n', v:fuzzynum(v)};
22308
23000
  else if(!isNaN(fuzzydate(v).getDate())) {
22309
23001
  o = ({t:'d', v:parseDate(v)}/*:any*/);
23002
+ if(opts.UTC) o.v = local_to_utc(o.v);
22310
23003
  if(!opts.cellDates) o = ({t:'n', v:datenum(o.v)}/*:any*/);
22311
23004
  o.z = opts.dateNF || table_fmt[14];
22312
23005
  }
@@ -22606,8 +23299,8 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22606
23299
  var ws = ({}/*:any*/); if(opts.dense) ws["!data"] = [];
22607
23300
  var Rn, q/*:: :any = ({t:"", v:null, z:null, w:"",c:[],}:any)*/;
22608
23301
  var ctag = ({value:""}/*:any*/);
22609
- var textp = "", textpidx = 0;
22610
- var textR = [];
23302
+ var textp = "", textpidx = 0, oldtextp = "", oldtextpidx = 0;
23303
+ var textR = [], oldtextR = [];
22611
23304
  var R = -1, C = -1, range = {s: {r:1000000,c:10000000}, e: {r:0, c:0}};
22612
23305
  var row_ol = 0;
22613
23306
  var number_format_map = _nfm || {}, styles = {};
@@ -22621,7 +23314,6 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22621
23314
  var creator = "", creatoridx = 0;
22622
23315
  var isstub = false, intable = false;
22623
23316
  var i = 0;
22624
- var baddate = 0;
22625
23317
  xlmlregex.lastIndex = 0;
22626
23318
  str = str.replace(/<!--([\s\S]*?)-->/mg,"").replace(/<!DOCTYPE[^\[]*\[[^\]]*\]>/gm,"");
22627
23319
  while((Rn = xlmlregex.exec(str))) switch((Rn[3]=Rn[3].replace(/_.*$/,""))) {
@@ -22692,7 +23384,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22692
23384
  C+= colpeat-1;
22693
23385
  } else if(Rn[1]!=='/') {
22694
23386
  ++C;
22695
- textp = ""; textpidx = 0; textR = [];
23387
+ textp = oldtextp = ""; textpidx = oldtextpidx = 0; textR = []; oldtextR = [];
22696
23388
  colpeat = 1;
22697
23389
  var rptR = rowpeat ? R + rowpeat - 1 : R;
22698
23390
  if(C > range.e.c) range.e.c = C;
@@ -22728,19 +23420,23 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22728
23420
  /* 19.675.2 table:number-columns-repeated */
22729
23421
  if(ctag['number-columns-repeated']) colpeat = parseInt(ctag['number-columns-repeated'], 10);
22730
23422
 
22731
- /* 19.385 office:value-type */
23423
+ /* 19.385 office:value-type TODO: verify ODS and UOS */
22732
23424
  switch(q.t) {
22733
23425
  case 'boolean': q.t = 'b'; q.v = parsexmlbool(ctag['boolean-value']) || (+ctag['boolean-value'] >= 1); break;
22734
- case 'float': q.t = 'n'; q.v = parseFloat(ctag.value); break;
23426
+ case 'float': q.t = 'n'; q.v = parseFloat(ctag.value);
23427
+ if(opts.cellDates && q.z && fmt_is_date(q.z)) { q.v = numdate(q.v + (WB.WBProps.date1904 ? 1462 : 0)); q.t = typeof q.v == "number" ? 'n' : 'd'; }
23428
+ break;
22735
23429
  case 'percentage': q.t = 'n'; q.v = parseFloat(ctag.value); break;
22736
23430
  case 'currency': q.t = 'n'; q.v = parseFloat(ctag.value); break;
22737
- case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value']);
22738
- if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904) - baddate; }
23431
+ case 'date': q.t = 'd'; q.v = parseDate(ctag['date-value'], WB.WBProps.date1904);
23432
+ if(!opts.cellDates) { q.t = 'n'; q.v = datenum(q.v, WB.WBProps.date1904); }
22739
23433
  if(!q.z) q.z = 'm/d/yy'; break;
23434
+ /* NOTE: for `time`, Excel ODS export incorrectly uses durations relative to 1900 epoch even if 1904 is specified */
22740
23435
  case 'time': q.t = 'n'; q.v = parse_isodur(ctag['time-value'])/86400;
22741
- if(opts.cellDates) { q.t = 'd'; q.v = numdate(q.v); }
23436
+ if(opts.cellDates) { q.v = numdate(q.v); q.t = typeof q.v == "number" ? 'n' : 'd'; }
22742
23437
  if(!q.z) q.z = 'HH:MM:SS'; break;
22743
- case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']); break;
23438
+ case 'number': q.t = 'n'; q.v = parseFloat(ctag['数据数值']);
23439
+ break;
22744
23440
  default:
22745
23441
  if(q.t === 'string' || q.t === 'text' || !q.t) {
22746
23442
  q.t = 's';
@@ -22801,10 +23497,17 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22801
23497
  if(textR.length) /*::(*/comment/*:: :any)*/.R = textR;
22802
23498
  comment.a = creator;
22803
23499
  comments.push(comment);
23500
+ textp = oldtextp; textpidx = oldtextpidx; textR = oldtextR;
23501
+ }
23502
+ else if(Rn[0].charAt(Rn[0].length-2) !== '/') {
23503
+ state.push([Rn[3], false]);
23504
+ var annotag = parsexmltag(Rn[0], true);
23505
+ /* office:display TODO: check if there is a global override */
23506
+ if(!(annotag["display"] && parsexmlbool(annotag["display"]))) comments.hidden = true;
23507
+ oldtextp = textp; oldtextpidx = textpidx; oldtextR = textR;
23508
+ textp = ""; textpidx = 0; textR = [];
22804
23509
  }
22805
- else if(Rn[0].charAt(Rn[0].length-2) !== '/') {state.push([Rn[3], false]);}
22806
23510
  creator = ""; creatoridx = 0;
22807
- textp = ""; textpidx = 0; textR = [];
22808
23511
  break;
22809
23512
 
22810
23513
  case 'creator': // 4.3.2.7 <dc:creator>
@@ -22930,9 +23633,7 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22930
23633
  case 'null-date': // 9.4.2 <table:null-date>
22931
23634
  tag = parsexmltag(Rn[0], false);
22932
23635
  switch(tag["date-value"]) {
22933
- case "1904-01-01": WB.WBProps.date1904 = true;
22934
- /* falls through */
22935
- case "1900-01-01": baddate = 0;
23636
+ case "1904-01-01": WB.WBProps.date1904 = true; break;
22936
23637
  }
22937
23638
  break;
22938
23639
 
@@ -22954,6 +23655,9 @@ function parse_content_xml(d/*:string*/, _opts, _nfm)/*:Workbook*/ {
22954
23655
  if(Rn[1]==='/' && (!ctag || !ctag['string-value'])) {
22955
23656
  var ptp = parse_text_p(str.slice(textpidx,Rn.index));
22956
23657
  textp = (textp.length > 0 ? textp + "\n" : "") + ptp[0];
23658
+ } else if(Rn[0].slice(-2) == "/>") {
23659
+ /* TODO: is self-closing 文本串 valid? */
23660
+ textp += "\n";
22957
23661
  } else { parsexmltag(Rn[0], false); textpidx = Rn.index + Rn[0].length; }
22958
23662
  break; // <text:p>
22959
23663
  case 's': break; // <text:s>
@@ -23238,7 +23942,9 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
23238
23942
  while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
23239
23943
  payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
23240
23944
  break;
23241
- case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
23945
+ case '\\': c = nf[++i];
23946
+ payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
23947
+ case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
23242
23948
  default: console.error("unrecognized character " + c + " in ODF format " + nf);
23243
23949
  }
23244
23950
  if(!has_time) break j;
@@ -23265,7 +23971,7 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
23265
23971
  while(nf[++i] != '"' || nf[++i] == '"') c += nf[i]; --i;
23266
23972
  payload += '<number:text>' + escapexml(c.slice(1).replace(/""/g, '"')) + '</number:text>';
23267
23973
  break;
23268
- case '/': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
23974
+ case '/': case ':': payload += '<number:text>' + escapexml(c) + '</number:text>'; break;
23269
23975
  case "a":
23270
23976
  if(nf.slice(i, i+3).toLowerCase() == "a/p") { payload += '<number:am-pm/>'; i += 2; break; } // Note: ODF does not support A/P
23271
23977
  if(nf.slice(i, i+5).toLowerCase() == "am/pm") { payload += '<number:am-pm/>'; i += 4; break; }
@@ -23321,10 +24027,15 @@ function write_number_format_ods(nf/*:string*/, nfidx/*:string*/)/*:string*/ {
23321
24027
  }
23322
24028
 
23323
24029
  function write_names_ods(Names, SheetNames, idx) {
23324
- var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
24030
+ //var scoped = Names.filter(function(name) { return name.Sheet == (idx == -1 ? null : idx); });
24031
+ var scoped = []; for(var namei = 0; namei < Names.length; ++namei) {
24032
+ var name = Names[namei];
24033
+ if(!name) continue;
24034
+ if(name.Sheet == (idx == -1 ? null : idx)) scoped.push(name);
24035
+ }
23325
24036
  if(!scoped.length) return "";
23326
24037
  return " <table:named-expressions>\n" + scoped.map(function(name) {
23327
- var odsref = csf_to_ods_3D(name.Ref);
24038
+ var odsref = (idx == -1 ? "$" : "") + csf_to_ods_3D(name.Ref);
23328
24039
  return " " + writextag("table:named-range", null, {
23329
24040
  "table:name": name.Name,
23330
24041
  "table:cell-range-address": odsref,
@@ -23343,8 +24054,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
23343
24054
  };
23344
24055
 
23345
24056
  var null_cell_xml = ' <table:table-cell />\n';
23346
- var covered_cell_xml = ' <table:covered-table-cell/>\n';
23347
- var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs)/*:string*/ {
24057
+ var write_ws = function(ws, wb/*:Workbook*/, i/*:number*/, opts, nfs, date1904)/*:string*/ {
23348
24058
  /* Section 9 Tables */
23349
24059
  var o/*:Array<string>*/ = [];
23350
24060
  o.push(' <table:table table:name="' + escapexml(wb.SheetNames[i]) + '" table:style-name="ta1">\n');
@@ -23375,7 +24085,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
23375
24085
  ct['table:number-rows-spanned'] = (marr[mi].e.r - marr[mi].s.r + 1);
23376
24086
  break;
23377
24087
  }
23378
- if(skip) { o.push(covered_cell_xml); continue; }
24088
+ if(skip) { o.push(' <table:covered-table-cell/>\n'); continue; }
23379
24089
  var ref = encode_cell({r:R, c:C}), cell = dense ? (ws["!data"][R]||[])[C]: ws[ref];
23380
24090
  if(cell && cell.f) {
23381
24091
  ct['table:formula'] = escapexml(csf_to_ods_formula(cell.f));
@@ -23404,13 +24114,13 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
23404
24114
  ct['office:value-type'] = "string";
23405
24115
  break;
23406
24116
  case 'd':
23407
- textp = (cell.w||(parseDate(cell.v).toISOString()));
24117
+ textp = (cell.w||(parseDate(cell.v, date1904).toISOString()));
23408
24118
  ct['office:value-type'] = "date";
23409
- ct['office:date-value'] = (parseDate(cell.v).toISOString());
24119
+ ct['office:date-value'] = (parseDate(cell.v, date1904).toISOString());
23410
24120
  ct['table:style-name'] = "ce1";
23411
24121
  break;
23412
- //case 'e':
23413
- default: o.push(null_cell_xml); continue;
24122
+ //case 'e': // TODO: translate to ODS errors
24123
+ default: o.push(null_cell_xml); continue; // TODO: empty cell with comments
23414
24124
  }
23415
24125
  var text_p = write_text_p(textp);
23416
24126
  if(cell.l && cell.l.Target) {
@@ -23421,7 +24131,17 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
23421
24131
  text_p = writextag('text:a', text_p, {'xlink:href': _tgt.replace(/&/g, "&amp;")});
23422
24132
  }
23423
24133
  if(nfs[cell.z]) ct["table:style-name"] = "ce" + nfs[cell.z].slice(1);
23424
- o.push(' ' + writextag('table:table-cell', writextag('text:p', text_p, {}), ct) + '\n');
24134
+ var payload = writextag('text:p', text_p, {});
24135
+ if(cell.c) {
24136
+ var acreator = "", apayload = "", aprops = {};
24137
+ for(var ci = 0; ci < cell.c.length; ++ci) {
24138
+ if(!acreator && cell.c[ci].a) acreator = cell.c[ci].a;
24139
+ apayload += "<text:p>" + write_text_p(cell.c[ci].t) + "</text:p>";
24140
+ }
24141
+ if(!cell.c.hidden) aprops["office:display"] = true;
24142
+ payload = writextag('office:annotation', apayload, aprops) + payload;
24143
+ }
24144
+ o.push(' ' + writextag('table:table-cell', payload, ct) + '\n');
23425
24145
  }
23426
24146
  o.push(' </table:table-row>\n');
23427
24147
  }
@@ -23566,7 +24286,7 @@ var write_content_ods/*:{(wb:any, opts:any):string}*/ = /* @__PURE__ */(function
23566
24286
  o.push(' <office:body>\n');
23567
24287
  o.push(' <office:spreadsheet>\n');
23568
24288
  if(((wb.Workbook||{}).WBProps||{}).date1904) o.push(' <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false">\n <table:null-date table:date-value="1904-01-01"/>\n </table:calculation-settings>\n');
23569
- for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs));
24289
+ for(var i = 0; i != wb.SheetNames.length; ++i) o.push(write_ws(wb.Sheets[wb.SheetNames[i]], wb, i, opts, nfs, ((wb.Workbook||{}).WBProps||{}).date1904));
23570
24290
  if((wb.Workbook||{}).Names) o.push(write_names_ods(wb.Workbook.Names, wb.SheetNames, -1));
23571
24291
  o.push(' </office:spreadsheet>\n');
23572
24292
  o.push(' </office:body>\n');
@@ -23767,19 +24487,18 @@ function write_packed_varints(nums) {
23767
24487
  }
23768
24488
  function varint_to_i32(buf) {
23769
24489
  var l = 0, i32 = buf[l] & 127;
23770
- varint:
23771
- if (buf[l++] >= 128) {
23772
- i32 |= (buf[l] & 127) << 7;
23773
- if (buf[l++] < 128)
23774
- break varint;
23775
- i32 |= (buf[l] & 127) << 14;
23776
- if (buf[l++] < 128)
23777
- break varint;
23778
- i32 |= (buf[l] & 127) << 21;
23779
- if (buf[l++] < 128)
23780
- break varint;
23781
- i32 |= (buf[l] & 127) << 28;
23782
- }
24490
+ if (buf[l++] < 128)
24491
+ return i32;
24492
+ i32 |= (buf[l] & 127) << 7;
24493
+ if (buf[l++] < 128)
24494
+ return i32;
24495
+ i32 |= (buf[l] & 127) << 14;
24496
+ if (buf[l++] < 128)
24497
+ return i32;
24498
+ i32 |= (buf[l] & 127) << 21;
24499
+ if (buf[l++] < 128)
24500
+ return i32;
24501
+ i32 |= (buf[l] & 15) << 28;
23783
24502
  return i32;
23784
24503
  }
23785
24504
  function parse_shallow(buf) {
@@ -24039,7 +24758,7 @@ function compress_iwa_file(buf) {
24039
24758
  return u8concat(out);
24040
24759
  }
24041
24760
  var numbers_lut_new = function() {
24042
- return { sst: [], rsst: [], ofmt: [], nfmt: [] };
24761
+ return { sst: [], rsst: [], ofmt: [], nfmt: [], fmla: [], ferr: [], cmnt: [] };
24043
24762
  };
24044
24763
  function numbers_format_cell(cell, t, flags, ofmt, nfmt) {
24045
24764
  var _a, _b, _c, _d;
@@ -24155,10 +24874,10 @@ function numbers_format_cell(cell, t, flags, ofmt, nfmt) {
24155
24874
  cell.w = cell.w.replace(/:(\d\d\d)$/, ".$1");
24156
24875
  }
24157
24876
  }
24158
- function parse_old_storage(buf, lut, v) {
24877
+ function parse_old_storage(buf, lut, v, opts) {
24159
24878
  var dv = u8_to_dataview(buf);
24160
24879
  var flags = dv.getUint32(4, true);
24161
- var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
24880
+ var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1));
24162
24881
  var doff = v > 1 ? 12 : 8;
24163
24882
  if (flags & 2) {
24164
24883
  zidx = dv.getUint32(doff, true);
@@ -24179,7 +24898,7 @@ function parse_old_storage(buf, lut, v) {
24179
24898
  doff += 8;
24180
24899
  }
24181
24900
  if (flags & 64) {
24182
- dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
24901
+ dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1e3);
24183
24902
  doff += 8;
24184
24903
  }
24185
24904
  if (v > 1) {
@@ -24202,7 +24921,12 @@ function parse_old_storage(buf, lut, v) {
24202
24921
  ret = { t: "s", v: lut.sst[sidx] };
24203
24922
  break;
24204
24923
  case 5:
24205
- ret = { t: "d", v: dt };
24924
+ {
24925
+ if (opts == null ? void 0 : opts.cellDates)
24926
+ ret = { t: "d", v: dt };
24927
+ else
24928
+ ret = { t: "n", v: dc / 86400 + 35430, z: table_fmt[14] };
24929
+ }
24206
24930
  break;
24207
24931
  case 6:
24208
24932
  ret = { t: "b", v: ieee > 0 };
@@ -24215,9 +24939,12 @@ function parse_old_storage(buf, lut, v) {
24215
24939
  break;
24216
24940
  case 9:
24217
24941
  {
24218
- if (ridx > -1)
24219
- ret = { t: "s", v: lut.rsst[ridx] };
24220
- else
24942
+ if (ridx > -1) {
24943
+ var rts = lut.rsst[ridx];
24944
+ ret = { t: "s", v: rts.v };
24945
+ if (rts.l)
24946
+ ret.l = { Target: rts.l };
24947
+ } else
24221
24948
  throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4)));
24222
24949
  }
24223
24950
  break;
@@ -24230,12 +24957,12 @@ function parse_old_storage(buf, lut, v) {
24230
24957
  ret.v /= 86400;
24231
24958
  return ret;
24232
24959
  }
24233
- function parse_new_storage(buf, lut) {
24960
+ function parse_new_storage(buf, lut, opts) {
24234
24961
  var dv = u8_to_dataview(buf);
24235
24962
  dv.getUint32(4, true);
24236
24963
  var fields = dv.getUint32(8, true);
24237
24964
  var doff = 12;
24238
- var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
24965
+ var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dc = 0, dt = new Date(Date.UTC(2001, 0, 1));
24239
24966
  if (fields & 1) {
24240
24967
  d128 = readDecimal128LE(buf, doff);
24241
24968
  doff += 16;
@@ -24245,7 +24972,7 @@ function parse_new_storage(buf, lut) {
24245
24972
  doff += 8;
24246
24973
  }
24247
24974
  if (fields & 4) {
24248
- dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
24975
+ dt.setTime(dt.getTime() + (dc = dv.getFloat64(doff, true)) * 1e3);
24249
24976
  doff += 8;
24250
24977
  }
24251
24978
  if (fields & 8) {
@@ -24256,11 +24983,22 @@ function parse_new_storage(buf, lut) {
24256
24983
  ridx = dv.getUint32(doff, true);
24257
24984
  doff += 4;
24258
24985
  }
24986
+ doff += popcnt(fields & 480) * 4;
24987
+ if (fields & 512) {
24988
+ dv.getUint32(doff, true);
24989
+ doff += 4;
24990
+ }
24991
+ doff += popcnt(fields & 1024) * 4;
24992
+ if (fields & 2048) {
24993
+ dv.getUint32(doff, true);
24994
+ doff += 4;
24995
+ }
24259
24996
  var ret;
24260
24997
  var t = buf[1];
24261
24998
  switch (t) {
24262
24999
  case 0:
24263
- return void 0;
25000
+ ret = { t: "z" };
25001
+ break;
24264
25002
  case 2:
24265
25003
  ret = { t: "n", v: d128 };
24266
25004
  break;
@@ -24268,7 +25006,12 @@ function parse_new_storage(buf, lut) {
24268
25006
  ret = { t: "s", v: lut.sst[sidx] };
24269
25007
  break;
24270
25008
  case 5:
24271
- ret = { t: "d", v: dt };
25009
+ {
25010
+ if (opts == null ? void 0 : opts.cellDates)
25011
+ ret = { t: "d", v: dt };
25012
+ else
25013
+ ret = { t: "n", v: dc / 86400 + 35430, z: table_fmt[14] };
25014
+ }
24272
25015
  break;
24273
25016
  case 6:
24274
25017
  ret = { t: "b", v: ieee > 0 };
@@ -24280,7 +25023,15 @@ function parse_new_storage(buf, lut) {
24280
25023
  ret = { t: "e", v: 0 };
24281
25024
  break;
24282
25025
  case 9:
24283
- ret = { t: "s", v: lut.rsst[ridx] };
25026
+ {
25027
+ if (ridx > -1) {
25028
+ var rts = lut.rsst[ridx];
25029
+ ret = { t: "s", v: rts.v };
25030
+ if (rts.l)
25031
+ ret.l = { Target: rts.l };
25032
+ } else
25033
+ throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4)));
25034
+ }
24284
25035
  break;
24285
25036
  case 10:
24286
25037
  ret = { t: "n", v: d128 };
@@ -24288,92 +25039,185 @@ function parse_new_storage(buf, lut) {
24288
25039
  default:
24289
25040
  throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(fields & 31, " : ").concat(buf[subarray](0, 4)));
24290
25041
  }
24291
- doff += popcnt(fields & 8160) * 4;
25042
+ doff += popcnt(fields & 4096) * 4;
24292
25043
  if (fields & 516096) {
24293
25044
  if (zidx == -1)
24294
25045
  zidx = dv.getUint32(doff, true);
24295
25046
  doff += 4;
24296
25047
  }
25048
+ if (fields & 524288) {
25049
+ var cmntidx = dv.getUint32(doff, true);
25050
+ doff += 4;
25051
+ if (lut.cmnt[cmntidx])
25052
+ ret.c = iwa_to_s5s_comment(lut.cmnt[cmntidx]);
25053
+ }
24297
25054
  if (zidx > -1)
24298
25055
  numbers_format_cell(ret, t | 5 << 8, fields >> 13, lut.ofmt[zidx], lut.nfmt[zidx]);
24299
25056
  if (t == 7)
24300
25057
  ret.v /= 86400;
24301
25058
  return ret;
24302
25059
  }
24303
- function write_new_storage(cell, sst) {
24304
- var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0;
25060
+ function write_new_storage(cell, lut) {
25061
+ var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0;
24305
25062
  out[0] = 5;
24306
25063
  switch (cell.t) {
24307
25064
  case "n":
24308
- out[1] = 2;
24309
- writeDecimal128LE(out, l, cell.v);
24310
- flags |= 1;
24311
- l += 16;
25065
+ if (cell.z && fmt_is_date(cell.z)) {
25066
+ out[1] = 5;
25067
+ dv.setFloat64(l, (numdate(cell.v + 1462).getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
25068
+ fields |= 4;
25069
+ l += 8;
25070
+ break;
25071
+ } else {
25072
+ out[1] = 2;
25073
+ writeDecimal128LE(out, l, cell.v);
25074
+ fields |= 1;
25075
+ l += 16;
25076
+ }
24312
25077
  break;
24313
25078
  case "b":
24314
25079
  out[1] = 6;
24315
25080
  dv.setFloat64(l, cell.v ? 1 : 0, true);
24316
- flags |= 2;
25081
+ fields |= 2;
24317
25082
  l += 8;
24318
25083
  break;
24319
25084
  case "s":
24320
- var s = cell.v == null ? "" : String(cell.v);
24321
- var isst = sst.indexOf(s);
24322
- if (isst == -1)
24323
- sst[isst = sst.length] = s;
24324
- out[1] = 3;
24325
- dv.setUint32(l, isst, true);
24326
- flags |= 8;
24327
- l += 4;
25085
+ {
25086
+ var s = cell.v == null ? "" : String(cell.v);
25087
+ if (cell.l) {
25088
+ var irsst = lut.rsst.findIndex(function(v) {
25089
+ var _a;
25090
+ return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target);
25091
+ });
25092
+ if (irsst == -1)
25093
+ lut.rsst[irsst = lut.rsst.length] = { v: s, l: cell.l.Target };
25094
+ out[1] = 9;
25095
+ dv.setUint32(l, irsst, true);
25096
+ fields |= 16;
25097
+ l += 4;
25098
+ } else {
25099
+ var isst = lut.sst.indexOf(s);
25100
+ if (isst == -1)
25101
+ lut.sst[isst = lut.sst.length] = s;
25102
+ out[1] = 3;
25103
+ dv.setUint32(l, isst, true);
25104
+ fields |= 8;
25105
+ l += 4;
25106
+ }
25107
+ }
25108
+ break;
25109
+ case "d":
25110
+ out[1] = 5;
25111
+ dv.setFloat64(l, (cell.v.getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
25112
+ fields |= 4;
25113
+ l += 8;
25114
+ break;
25115
+ case "z":
25116
+ out[1] = 0;
24328
25117
  break;
24329
25118
  default:
24330
25119
  throw "unsupported cell type " + cell.t;
24331
25120
  }
24332
- dv.setUint32(8, flags, true);
25121
+ if (cell.c) {
25122
+ lut.cmnt.push(s5s_to_iwa_comment(cell.c));
25123
+ dv.setUint32(l, lut.cmnt.length - 1, true);
25124
+ fields |= 524288;
25125
+ l += 4;
25126
+ }
25127
+ dv.setUint32(8, fields, true);
24333
25128
  return out[subarray](0, l);
24334
25129
  }
24335
- function write_old_storage(cell, sst) {
24336
- var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, flags = 0;
25130
+ function write_old_storage(cell, lut) {
25131
+ var out = new Uint8Array(32), dv = u8_to_dataview(out), l = 12, fields = 0, s = "";
24337
25132
  out[0] = 4;
24338
25133
  switch (cell.t) {
24339
25134
  case "n":
24340
- out[2] = 2;
25135
+ break;
25136
+ case "b":
25137
+ break;
25138
+ case "s":
25139
+ {
25140
+ s = cell.v == null ? "" : String(cell.v);
25141
+ if (cell.l) {
25142
+ var irsst = lut.rsst.findIndex(function(v) {
25143
+ var _a;
25144
+ return v.v == s && v.l == ((_a = cell.l) == null ? void 0 : _a.Target);
25145
+ });
25146
+ if (irsst == -1)
25147
+ lut.rsst[irsst = lut.rsst.length] = { v: s, l: cell.l.Target };
25148
+ out[1] = 9;
25149
+ dv.setUint32(l, irsst, true);
25150
+ fields |= 512;
25151
+ l += 4;
25152
+ }
25153
+ }
25154
+ break;
25155
+ case "d":
25156
+ break;
25157
+ case "e":
25158
+ break;
25159
+ case "z":
25160
+ break;
25161
+ default:
25162
+ throw "unsupported cell type " + cell.t;
25163
+ }
25164
+ if (cell.c) {
25165
+ dv.setUint32(l, lut.cmnt.length - 1, true);
25166
+ fields |= 4096;
25167
+ l += 4;
25168
+ }
25169
+ switch (cell.t) {
25170
+ case "n":
25171
+ out[1] = 2;
24341
25172
  dv.setFloat64(l, cell.v, true);
24342
- flags |= 32;
25173
+ fields |= 32;
24343
25174
  l += 8;
24344
25175
  break;
24345
25176
  case "b":
24346
- out[2] = 6;
25177
+ out[1] = 6;
24347
25178
  dv.setFloat64(l, cell.v ? 1 : 0, true);
24348
- flags |= 32;
25179
+ fields |= 32;
24349
25180
  l += 8;
24350
25181
  break;
24351
25182
  case "s":
24352
- var s = cell.v == null ? "" : String(cell.v);
24353
- var isst = sst.indexOf(s);
24354
- if (isst == -1)
24355
- sst[isst = sst.length] = s;
24356
- out[2] = 3;
24357
- dv.setUint32(l, isst, true);
24358
- flags |= 16;
24359
- l += 4;
25183
+ {
25184
+ s = cell.v == null ? "" : String(cell.v);
25185
+ if (cell.l) ; else {
25186
+ var isst = lut.sst.indexOf(s);
25187
+ if (isst == -1)
25188
+ lut.sst[isst = lut.sst.length] = s;
25189
+ out[1] = 3;
25190
+ dv.setUint32(l, isst, true);
25191
+ fields |= 16;
25192
+ l += 4;
25193
+ }
25194
+ }
25195
+ break;
25196
+ case "d":
25197
+ out[1] = 5;
25198
+ dv.setFloat64(l, (cell.v.getTime() - Date.UTC(2001, 0, 1)) / 1e3, true);
25199
+ fields |= 64;
25200
+ l += 8;
25201
+ break;
25202
+ case "z":
25203
+ out[1] = 0;
24360
25204
  break;
24361
25205
  default:
24362
25206
  throw "unsupported cell type " + cell.t;
24363
25207
  }
24364
- dv.setUint32(8, flags, true);
25208
+ dv.setUint32(8, fields, true);
24365
25209
  return out[subarray](0, l);
24366
25210
  }
24367
- function parse_cell_storage(buf, lut) {
25211
+ function parse_cell_storage(buf, lut, opts) {
24368
25212
  switch (buf[0]) {
24369
25213
  case 0:
24370
25214
  case 1:
24371
25215
  case 2:
24372
25216
  case 3:
24373
25217
  case 4:
24374
- return parse_old_storage(buf, lut, buf[0]);
25218
+ return parse_old_storage(buf, lut, buf[0], opts);
24375
25219
  case 5:
24376
- return parse_new_storage(buf, lut);
25220
+ return parse_new_storage(buf, lut, opts);
24377
25221
  default:
24378
25222
  throw new Error("Unsupported payload version ".concat(buf[0]));
24379
25223
  }
@@ -24410,6 +25254,7 @@ function parse_TST_TableDataList(M, root) {
24410
25254
  var entries = pb[3];
24411
25255
  var data = [];
24412
25256
  (entries || []).forEach(function(entry) {
25257
+ var _a, _b;
24413
25258
  var le = parse_shallow(entry.data);
24414
25259
  if (!le[1])
24415
25260
  return;
@@ -24427,14 +25272,49 @@ function parse_TST_TableDataList(M, root) {
24427
25272
  if (mtype != 2001)
24428
25273
  throw new Error("2000 unexpected reference to ".concat(mtype));
24429
25274
  var tswpsa = parse_shallow(rtpref.data);
24430
- data[key] = tswpsa[3].map(function(x) {
25275
+ var richtext = { v: tswpsa[3].map(function(x) {
24431
25276
  return u8str(x.data);
24432
- }).join("");
25277
+ }).join("") };
25278
+ data[key] = richtext;
25279
+ sfields:
25280
+ if ((_a = tswpsa == null ? void 0 : tswpsa[11]) == null ? void 0 : _a[0]) {
25281
+ var smartfields = (_b = parse_shallow(tswpsa[11][0].data)) == null ? void 0 : _b[1];
25282
+ if (!smartfields)
25283
+ break sfields;
25284
+ smartfields.forEach(function(sf) {
25285
+ var _a2, _b2, _c;
25286
+ var attr = parse_shallow(sf.data);
25287
+ if ((_a2 = attr[2]) == null ? void 0 : _a2[0]) {
25288
+ var obj = M[parse_TSP_Reference((_b2 = attr[2]) == null ? void 0 : _b2[0].data)][0];
25289
+ var objtype = varint_to_i32(obj.meta[1][0].data);
25290
+ switch (objtype) {
25291
+ case 2032:
25292
+ var hlink = parse_shallow(obj.data);
25293
+ if (((_c = hlink == null ? void 0 : hlink[2]) == null ? void 0 : _c[0]) && !richtext.l)
25294
+ richtext.l = u8str(hlink[2][0].data);
25295
+ break;
25296
+ case 2039:
25297
+ break;
25298
+ default:
25299
+ console.log("unrecognized ObjectAttribute type ".concat(objtype));
25300
+ }
25301
+ }
25302
+ });
25303
+ }
24433
25304
  }
24434
25305
  break;
24435
25306
  case 2:
24436
25307
  data[key] = parse_shallow(le[6][0].data);
24437
25308
  break;
25309
+ case 3:
25310
+ data[key] = parse_shallow(le[5][0].data);
25311
+ break;
25312
+ case 10:
25313
+ {
25314
+ var cs = M[parse_TSP_Reference(le[10][0].data)][0];
25315
+ data[key] = parse_TSD_CommentStorageArchive(M, cs.data);
25316
+ }
25317
+ break;
24438
25318
  default:
24439
25319
  throw type;
24440
25320
  }
@@ -24500,8 +25380,50 @@ function parse_TST_Tile(M, root) {
24500
25380
  }, [])
24501
25381
  };
24502
25382
  }
24503
- function parse_TST_TableModelArchive(M, root, ws) {
24504
- var _a, _b, _c, _d, _e, _f;
25383
+ function parse_TSD_CommentStorageArchive(M, data) {
25384
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
25385
+ var out = { t: "", a: "" };
25386
+ var csp = parse_shallow(data);
25387
+ if ((_b = (_a = csp == null ? void 0 : csp[1]) == null ? void 0 : _a[0]) == null ? void 0 : _b.data)
25388
+ out.t = u8str((_d = (_c = csp == null ? void 0 : csp[1]) == null ? void 0 : _c[0]) == null ? void 0 : _d.data) || "";
25389
+ if ((_f = (_e = csp == null ? void 0 : csp[3]) == null ? void 0 : _e[0]) == null ? void 0 : _f.data) {
25390
+ var as = M[parse_TSP_Reference((_h = (_g = csp == null ? void 0 : csp[3]) == null ? void 0 : _g[0]) == null ? void 0 : _h.data)][0];
25391
+ var asp = parse_shallow(as.data);
25392
+ if ((_j = (_i = asp[1]) == null ? void 0 : _i[0]) == null ? void 0 : _j.data)
25393
+ out.a = u8str(asp[1][0].data);
25394
+ }
25395
+ if (csp == null ? void 0 : csp[4]) {
25396
+ out.replies = [];
25397
+ csp[4].forEach(function(pi) {
25398
+ var cs = M[parse_TSP_Reference(pi.data)][0];
25399
+ out.replies.push(parse_TSD_CommentStorageArchive(M, cs.data));
25400
+ });
25401
+ }
25402
+ return out;
25403
+ }
25404
+ function iwa_to_s5s_comment(iwa) {
25405
+ var out = [];
25406
+ out.push({ t: iwa.t || "", a: iwa.a, T: iwa.replies && iwa.replies.length > 0 });
25407
+ if (iwa.replies)
25408
+ iwa.replies.forEach(function(reply) {
25409
+ out.push({ t: reply.t || "", a: reply.a, T: true });
25410
+ });
25411
+ return out;
25412
+ }
25413
+ function s5s_to_iwa_comment(s5s) {
25414
+ var out = { a: "", t: "", replies: [] };
25415
+ for (var i = 0; i < s5s.length; ++i) {
25416
+ if (i == 0) {
25417
+ out.a = s5s[i].a;
25418
+ out.t = s5s[i].t;
25419
+ } else {
25420
+ out.replies.push({ a: s5s[i].a, t: s5s[i].t });
25421
+ }
25422
+ }
25423
+ return out;
25424
+ }
25425
+ function parse_TST_TableModelArchive(M, root, ws, opts) {
25426
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
24505
25427
  var pb = parse_shallow(root.data);
24506
25428
  var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
24507
25429
  range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
@@ -24516,11 +25438,17 @@ function parse_TST_TableModelArchive(M, root, ws) {
24516
25438
  var lut = numbers_lut_new();
24517
25439
  if ((_a = store[4]) == null ? void 0 : _a[0])
24518
25440
  lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
24519
- if ((_b = store[11]) == null ? void 0 : _b[0])
25441
+ if ((_b = store[6]) == null ? void 0 : _b[0])
25442
+ lut.fmla = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[6][0].data)][0]);
25443
+ if ((_c = store[11]) == null ? void 0 : _c[0])
24520
25444
  lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]);
24521
- if ((_c = store[17]) == null ? void 0 : _c[0])
25445
+ if ((_d = store[12]) == null ? void 0 : _d[0])
25446
+ lut.ferr = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[12][0].data)][0]);
25447
+ if ((_e = store[17]) == null ? void 0 : _e[0])
24522
25448
  lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]);
24523
- if ((_d = store[22]) == null ? void 0 : _d[0])
25449
+ if ((_f = store[19]) == null ? void 0 : _f[0])
25450
+ lut.cmnt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[19][0].data)][0]);
25451
+ if ((_g = store[22]) == null ? void 0 : _g[0])
24524
25452
  lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
24525
25453
  var tile = parse_shallow(store[3][0].data);
24526
25454
  var _R = 0;
@@ -24533,7 +25461,7 @@ function parse_TST_TableModelArchive(M, root, ws) {
24533
25461
  var _tile = parse_TST_Tile(M, ref2);
24534
25462
  _tile.data.forEach(function(row, R) {
24535
25463
  row.forEach(function(buf, C) {
24536
- var res = parse_cell_storage(buf, lut);
25464
+ var res = parse_cell_storage(buf, lut, opts);
24537
25465
  if (res) {
24538
25466
  if (dense) {
24539
25467
  if (!dws["!data"][_R + R])
@@ -24547,12 +25475,12 @@ function parse_TST_TableModelArchive(M, root, ws) {
24547
25475
  });
24548
25476
  _R += _tile.nrows;
24549
25477
  });
24550
- if ((_e = store[13]) == null ? void 0 : _e[0]) {
25478
+ if ((_h = store[13]) == null ? void 0 : _h[0]) {
24551
25479
  var ref = M[parse_TSP_Reference(store[13][0].data)][0];
24552
25480
  var mtype = varint_to_i32(ref.meta[1][0].data);
24553
25481
  if (mtype != 6144)
24554
25482
  throw new Error("Expected merge type 6144, found ".concat(mtype));
24555
- ws["!merges"] = (_f = parse_shallow(ref.data)) == null ? void 0 : _f[1].map(function(pi) {
25483
+ ws["!merges"] = (_i = parse_shallow(ref.data)) == null ? void 0 : _i[1].map(function(pi) {
24556
25484
  var merge = parse_shallow(pi.data);
24557
25485
  var origin = u8_to_dataview(parse_shallow(merge[1][0].data)[1][0].data), size = u8_to_dataview(parse_shallow(merge[2][0].data)[1][0].data);
24558
25486
  return {
@@ -24574,7 +25502,7 @@ function parse_TST_TableInfoArchive(M, root, opts) {
24574
25502
  var mtype = varint_to_i32(tableref[0].meta[1][0].data);
24575
25503
  if (mtype != 6001)
24576
25504
  throw new Error("6000 unexpected reference to ".concat(mtype));
24577
- parse_TST_TableModelArchive(M, tableref[0], out);
25505
+ parse_TST_TableModelArchive(M, tableref[0], out, opts);
24578
25506
  return out;
24579
25507
  }
24580
25508
  function parse_TN_SheetArchive(M, root, opts) {
@@ -24597,6 +25525,7 @@ function parse_TN_SheetArchive(M, root, opts) {
24597
25525
  function parse_TN_DocumentArchive(M, root, opts) {
24598
25526
  var _a;
24599
25527
  var out = book_new();
25528
+ out.Workbook = { WBProps: { date1904: true } };
24600
25529
  var pb = parse_shallow(root.data);
24601
25530
  if ((_a = pb[2]) == null ? void 0 : _a[0])
24602
25531
  throw new Error("Keynote presentations are not supported");
@@ -24667,8 +25596,8 @@ function parse_numbers_iwa(cfb, opts) {
24667
25596
  throw new Error("Cannot find Document root");
24668
25597
  return parse_TN_DocumentArchive(M, docroot, opts);
24669
25598
  }
24670
- function write_TST_TileRowInfo(data, SST, wide) {
24671
- var _a, _b;
25599
+ function write_TST_TileRowInfo(data, lut, wide) {
25600
+ var _a, _b, _c;
24672
25601
  var tri = [
24673
25602
  [],
24674
25603
  [{ type: 0, data: write_varint49(0) }],
@@ -24701,7 +25630,7 @@ function write_TST_TileRowInfo(data, SST, wide) {
24701
25630
  var _dv = u8_to_dataview(tri[4][0].data), _last_offset = 0, _cell_storage = [];
24702
25631
  var width = wide ? 4 : 1;
24703
25632
  for (var C = 0; C < data.length; ++C) {
24704
- if (data[C] == null) {
25633
+ if (data[C] == null || data[C].t == "z" && !((_c = data[C].c) == null ? void 0 : _c.length) || data[C].t == "e") {
24705
25634
  dv.setUint16(C * 2, 65535, true);
24706
25635
  _dv.setUint16(C * 2, 65535);
24707
25636
  continue;
@@ -24709,25 +25638,24 @@ function write_TST_TileRowInfo(data, SST, wide) {
24709
25638
  dv.setUint16(C * 2, last_offset / width, true);
24710
25639
  _dv.setUint16(C * 2, _last_offset / width, true);
24711
25640
  var celload, _celload;
24712
- switch (typeof data[C]) {
24713
- case "string":
24714
- celload = write_new_storage({ t: "s", v: data[C] }, SST);
24715
- _celload = write_old_storage({ t: "s", v: data[C] }, SST);
24716
- break;
24717
- case "number":
24718
- celload = write_new_storage({ t: "n", v: data[C] }, SST);
24719
- _celload = write_old_storage({ t: "n", v: data[C] }, SST);
25641
+ switch (data[C].t) {
25642
+ case "d":
25643
+ if (data[C].v instanceof Date) {
25644
+ celload = write_new_storage(data[C], lut);
25645
+ _celload = write_old_storage(data[C], lut);
25646
+ break;
25647
+ }
25648
+ celload = write_new_storage(data[C], lut);
25649
+ _celload = write_old_storage(data[C], lut);
24720
25650
  break;
24721
- case "boolean":
24722
- celload = write_new_storage({ t: "b", v: data[C] }, SST);
24723
- _celload = write_old_storage({ t: "b", v: data[C] }, SST);
25651
+ case "s":
25652
+ case "n":
25653
+ case "b":
25654
+ case "z":
25655
+ celload = write_new_storage(data[C], lut);
25656
+ _celload = write_old_storage(data[C], lut);
24724
25657
  break;
24725
25658
  default:
24726
- if (data[C] instanceof Date) {
24727
- celload = write_new_storage({ t: "s", v: data[C].toISOString() }, SST);
24728
- _celload = write_old_storage({ t: "s", v: data[C].toISOString() }, SST);
24729
- break;
24730
- }
24731
25659
  throw new Error("Unsupported value " + data[C]);
24732
25660
  }
24733
25661
  cell_storage.push(celload);
@@ -24805,6 +25733,34 @@ function build_numbers_deps(cfb) {
24805
25733
  });
24806
25734
  return dependents;
24807
25735
  }
25736
+ function write_TSP_Color_RGB(r, g, b) {
25737
+ return write_shallow([
25738
+ [],
25739
+ [{ type: 0, data: write_varint49(1) }],
25740
+ [],
25741
+ [{ type: 5, data: new Uint8Array(Float32Array.from([r / 255]).buffer) }],
25742
+ [{ type: 5, data: new Uint8Array(Float32Array.from([g / 255]).buffer) }],
25743
+ [{ type: 5, data: new Uint8Array(Float32Array.from([b / 255]).buffer) }],
25744
+ [{ type: 5, data: new Uint8Array(Float32Array.from([1]).buffer) }],
25745
+ [],
25746
+ [],
25747
+ [],
25748
+ [],
25749
+ [],
25750
+ [{ type: 0, data: write_varint49(1) }]
25751
+ ]);
25752
+ }
25753
+ function get_author_color(n) {
25754
+ switch (n) {
25755
+ case 0:
25756
+ return write_TSP_Color_RGB(99, 222, 171);
25757
+ case 1:
25758
+ return write_TSP_Color_RGB(162, 197, 240);
25759
+ case 2:
25760
+ return write_TSP_Color_RGB(255, 189, 189);
25761
+ }
25762
+ return write_TSP_Color_RGB(Math.random() * 255, Math.random() * 255, Math.random() * 255);
25763
+ }
24808
25764
  function write_numbers_iwa(wb, opts) {
24809
25765
  if (!opts || !opts.numbers)
24810
25766
  throw new Error("Must pass a `numbers` option -- check the README");
@@ -24848,6 +25804,85 @@ function numbers_iwa_find(cfb, deps, id) {
24848
25804
  });
24849
25805
  return ainfo;
24850
25806
  }
25807
+ function numbers_add_meta(mlist, newid, newloc) {
25808
+ mlist[3].push({ type: 2, data: write_shallow([
25809
+ [],
25810
+ [{ type: 0, data: write_varint49(newid) }],
25811
+ [{ type: 2, data: stru8(newloc.replace(/-.*$/, "")) }],
25812
+ [{ type: 2, data: stru8(newloc) }],
25813
+ [{ type: 2, data: new Uint8Array([2, 0, 0]) }],
25814
+ [{ type: 2, data: new Uint8Array([2, 0, 0]) }],
25815
+ [],
25816
+ [],
25817
+ [],
25818
+ [],
25819
+ [{ type: 0, data: write_varint49(0) }],
25820
+ [],
25821
+ [{ type: 0, data: write_varint49(0) }]
25822
+ ]) });
25823
+ mlist[1] = [{ type: 0, data: write_varint49(Math.max(newid + 1, varint_to_i32(mlist[1][0].data))) }];
25824
+ }
25825
+ function numbers_add_msg(cfb, type, msg, path, deps, id) {
25826
+ if (!id)
25827
+ id = get_unique_msgid({ deps: [], location: "", type: type }, deps);
25828
+ var loc = "".concat(path, "-").concat(id, ".iwa");
25829
+ deps[id].location = "Root Entry" + loc;
25830
+ CFB.utils.cfb_add(cfb, loc, compress_iwa_file(write_iwa_file([{
25831
+ id: id,
25832
+ messages: [write_iwam(type, write_shallow(msg))]
25833
+ }])));
25834
+ var newloc = loc.replace(/^[\/]/, "").replace(/^Index\//, "").replace(/\.iwa$/, "");
25835
+ numbers_iwa_doit(cfb, deps, 2, function(ai) {
25836
+ var mlist = parse_shallow(ai.messages[0].data);
25837
+ numbers_add_meta(mlist, id || 0, newloc);
25838
+ ai.messages[0].data = write_shallow(mlist);
25839
+ });
25840
+ return id;
25841
+ }
25842
+ function numbers_meta_add_dep(mlist, deps, id, dep) {
25843
+ var loc = deps[id].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, "");
25844
+ var parentidx = mlist[3].findIndex(function(m) {
25845
+ var _a, _b;
25846
+ var mm = parse_shallow(m.data);
25847
+ if ((_a = mm[3]) == null ? void 0 : _a[0])
25848
+ return u8str(mm[3][0].data) == loc;
25849
+ if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc)
25850
+ return true;
25851
+ return false;
25852
+ });
25853
+ var parent = parse_shallow(mlist[3][parentidx].data);
25854
+ if (!parent[6])
25855
+ parent[6] = [];
25856
+ (Array.isArray(dep) ? dep : [dep]).forEach(function(dep2) {
25857
+ parent[6].push({
25858
+ type: 2,
25859
+ data: write_shallow([
25860
+ [],
25861
+ [{ type: 0, data: write_varint49(dep2) }]
25862
+ ])
25863
+ });
25864
+ });
25865
+ mlist[3][parentidx].data = write_shallow(parent);
25866
+ }
25867
+ function numbers_meta_del_dep(mlist, deps, id, dep) {
25868
+ var loc = deps[id].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, "");
25869
+ var parentidx = mlist[3].findIndex(function(m) {
25870
+ var _a, _b;
25871
+ var mm = parse_shallow(m.data);
25872
+ if ((_a = mm[3]) == null ? void 0 : _a[0])
25873
+ return u8str(mm[3][0].data) == loc;
25874
+ if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc)
25875
+ return true;
25876
+ return false;
25877
+ });
25878
+ var parent = parse_shallow(mlist[3][parentidx].data);
25879
+ if (!parent[6])
25880
+ parent[6] = [];
25881
+ parent[6] = parent[6].filter(function(m) {
25882
+ return varint_to_i32(parse_shallow(m.data)[1][0].data) != dep;
25883
+ });
25884
+ mlist[3][parentidx].data = write_shallow(parent);
25885
+ }
24851
25886
  function numbers_add_ws(cfb, deps, wsidx) {
24852
25887
  var sheetref = -1, newsheetref = -1;
24853
25888
  var remap = {};
@@ -24886,31 +25921,9 @@ function numbers_add_ws(cfb, deps, wsidx) {
24886
25921
  if (deps[drawables[0]].location == deps[newsheetref].location)
24887
25922
  arch.push(tia);
24888
25923
  else {
24889
- var loc2 = deps[newsheetref].location;
24890
- loc2 = loc2.replace(/^Root Entry\//, "");
24891
- loc2 = loc2.replace(/^Index\//, "").replace(/\.iwa$/, "");
24892
25924
  numbers_iwa_doit(cfb, deps, 2, function(ai) {
24893
25925
  var mlist = parse_shallow(ai.messages[0].data);
24894
- var parentidx = mlist[3].findIndex(function(m) {
24895
- var _a, _b;
24896
- var mm = parse_shallow(m.data);
24897
- if ((_a = mm[3]) == null ? void 0 : _a[0])
24898
- return u8str(mm[3][0].data) == loc2;
24899
- if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc2)
24900
- return true;
24901
- return false;
24902
- });
24903
- var parent = parse_shallow(mlist[3][parentidx].data);
24904
- if (!parent[6])
24905
- parent[6] = [];
24906
- parent[6].push({
24907
- type: 2,
24908
- data: write_shallow([
24909
- [],
24910
- [{ type: 0, data: write_varint49(tiaref) }]
24911
- ])
24912
- });
24913
- mlist[3][parentidx].data = write_shallow(parent);
25926
+ numbers_meta_add_dep(mlist, deps, newsheetref, tiaref);
24914
25927
  ai.messages[0].data = write_shallow(mlist);
24915
25928
  });
24916
25929
  numbers_iwa_doit(cfb, deps, tiaref, function(_, x) {
@@ -24944,13 +25957,10 @@ function numbers_add_ws(cfb, deps, wsidx) {
24944
25957
  });
24945
25958
  tiaroot.messages[0].data = write_shallow(tia);
24946
25959
  });
24947
- var loc = deps[tmaref].location;
24948
- loc = loc.replace(/^Root Entry\//, "");
24949
- loc = loc.replace(/^Index\//, "").replace(/\.iwa$/, "");
24950
25960
  numbers_iwa_doit(cfb, deps, tmaref, function(tmaroot, arch) {
24951
25961
  var _a, _b;
24952
25962
  var tma = parse_shallow(tmaroot.messages[0].data);
24953
- var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(wsidx.toString(16).padStart(4, "0")));
25963
+ var uuid = u8str(tma[1][0].data), new_uuid = uuid.replace(/-[A-Z0-9]*/, "-".concat(("0000" + wsidx.toString(16)).slice(-4)));
24954
25964
  tma[1][0].data = stru8(new_uuid);
24955
25965
  [12, 13, 29, 31, 32, 33, 39, 44, 47, 81, 82, 84].forEach(function(n) {
24956
25966
  return delete tma[n];
@@ -25028,47 +26038,11 @@ function numbers_add_ws(cfb, deps, wsidx) {
25028
26038
  if (deps[newref].location == deps[oldref].location)
25029
26039
  deps[newref].location = deps[newref].location.replace(/\.iwa/, "-".concat(newref, ".iwa"));
25030
26040
  CFB.utils.cfb_add(cfb, deps[newref].location, compress_iwa_file(write_iwa_file([msg])));
25031
- var newloc = deps[newref].location;
25032
- newloc = newloc.replace(/^Root Entry\//, "");
25033
- newloc = newloc.replace(/^Index\//, "").replace(/\.iwa$/, "");
26041
+ var newloc = deps[newref].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, "");
25034
26042
  numbers_iwa_doit(cfb, deps, 2, function(ai) {
25035
26043
  var mlist = parse_shallow(ai.messages[0].data);
25036
- mlist[3].push({ type: 2, data: write_shallow([
25037
- [],
25038
- [{ type: 0, data: write_varint49(newref) }],
25039
- [{ type: 2, data: stru8(newloc.replace(/-.*$/, "")) }],
25040
- [{ type: 2, data: stru8(newloc) }],
25041
- [{ type: 2, data: new Uint8Array([2, 0, 0]) }],
25042
- [{ type: 2, data: new Uint8Array([2, 0, 0]) }],
25043
- [],
25044
- [],
25045
- [],
25046
- [],
25047
- [{ type: 0, data: write_varint49(0) }],
25048
- [],
25049
- [{ type: 0, data: write_varint49(0) }]
25050
- ]) });
25051
- mlist[1] = [{ type: 0, data: write_varint49(Math.max(newref + 1, varint_to_i32(mlist[1][0].data))) }];
25052
- var parentidx = mlist[3].findIndex(function(m) {
25053
- var _a3, _b2;
25054
- var mm = parse_shallow(m.data);
25055
- if ((_a3 = mm[3]) == null ? void 0 : _a3[0])
25056
- return u8str(mm[3][0].data) == loc;
25057
- if (((_b2 = mm[2]) == null ? void 0 : _b2[0]) && u8str(mm[2][0].data) == loc)
25058
- return true;
25059
- return false;
25060
- });
25061
- var parent = parse_shallow(mlist[3][parentidx].data);
25062
- if (!parent[6])
25063
- parent[6] = [];
25064
- parent[6].push({
25065
- type: 2,
25066
- data: write_shallow([
25067
- [],
25068
- [{ type: 0, data: write_varint49(newref) }]
25069
- ])
25070
- });
25071
- mlist[3][parentidx].data = write_shallow(parent);
26044
+ numbers_add_meta(mlist, newref, newloc);
26045
+ numbers_meta_add_dep(mlist, deps, tmaref, newref);
25072
26046
  ai.messages[0].data = write_shallow(mlist);
25073
26047
  });
25074
26048
  }
@@ -25091,47 +26065,11 @@ function numbers_add_ws(cfb, deps, wsidx) {
25091
26065
  if (deps[newref].location == deps[oldref].location)
25092
26066
  deps[newref].location = deps[newref].location.replace(/\.iwa/, "-".concat(newref, ".iwa"));
25093
26067
  CFB.utils.cfb_add(cfb, deps[newref].location, compress_iwa_file(write_iwa_file([msg])));
25094
- var newloc = deps[newref].location;
25095
- newloc = newloc.replace(/^Root Entry\//, "");
25096
- newloc = newloc.replace(/^Index\//, "").replace(/\.iwa$/, "");
26068
+ var newloc = deps[newref].location.replace(/^Root Entry\//, "").replace(/^Index\//, "").replace(/\.iwa$/, "");
25097
26069
  numbers_iwa_doit(cfb, deps, 2, function(ai) {
25098
26070
  var mlist = parse_shallow(ai.messages[0].data);
25099
- mlist[3].push({ type: 2, data: write_shallow([
25100
- [],
25101
- [{ type: 0, data: write_varint49(newref) }],
25102
- [{ type: 2, data: stru8(newloc.replace(/-.*$/, "")) }],
25103
- [{ type: 2, data: stru8(newloc) }],
25104
- [{ type: 2, data: new Uint8Array([2, 0, 0]) }],
25105
- [{ type: 2, data: new Uint8Array([2, 0, 0]) }],
25106
- [],
25107
- [],
25108
- [],
25109
- [],
25110
- [{ type: 0, data: write_varint49(0) }],
25111
- [],
25112
- [{ type: 0, data: write_varint49(0) }]
25113
- ]) });
25114
- mlist[1] = [{ type: 0, data: write_varint49(Math.max(newref + 1, varint_to_i32(mlist[1][0].data))) }];
25115
- var parentidx = mlist[3].findIndex(function(m) {
25116
- var _a2, _b2;
25117
- var mm = parse_shallow(m.data);
25118
- if ((_a2 = mm[3]) == null ? void 0 : _a2[0])
25119
- return u8str(mm[3][0].data) == loc;
25120
- if (((_b2 = mm[2]) == null ? void 0 : _b2[0]) && u8str(mm[2][0].data) == loc)
25121
- return true;
25122
- return false;
25123
- });
25124
- var parent = parse_shallow(mlist[3][parentidx].data);
25125
- if (!parent[6])
25126
- parent[6] = [];
25127
- parent[6].push({
25128
- type: 2,
25129
- data: write_shallow([
25130
- [],
25131
- [{ type: 0, data: write_varint49(newref) }]
25132
- ])
25133
- });
25134
- mlist[3][parentidx].data = write_shallow(parent);
26071
+ numbers_add_meta(mlist, newref, newloc);
26072
+ numbers_meta_add_dep(mlist, deps, tmaref, newref);
25135
26073
  ai.messages[0].data = write_shallow(mlist);
25136
26074
  });
25137
26075
  }
@@ -25172,26 +26110,7 @@ function numbers_add_ws(cfb, deps, wsidx) {
25172
26110
  [{ type: 0, data: write_varint49(0) }]
25173
26111
  ]) });
25174
26112
  mlist[1] = [{ type: 0, data: write_varint49(Math.max(newtileref + 1, varint_to_i32(mlist[1][0].data))) }];
25175
- var parentidx = mlist[3].findIndex(function(m) {
25176
- var _a2, _b2;
25177
- var mm = parse_shallow(m.data);
25178
- if ((_a2 = mm[3]) == null ? void 0 : _a2[0])
25179
- return u8str(mm[3][0].data) == loc;
25180
- if (((_b2 = mm[2]) == null ? void 0 : _b2[0]) && u8str(mm[2][0].data) == loc)
25181
- return true;
25182
- return false;
25183
- });
25184
- var parent = parse_shallow(mlist[3][parentidx].data);
25185
- if (!parent[6])
25186
- parent[6] = [];
25187
- parent[6].push({
25188
- type: 2,
25189
- data: write_shallow([
25190
- [],
25191
- [{ type: 0, data: write_varint49(newtileref) }]
25192
- ])
25193
- });
25194
- mlist[3][parentidx].data = write_shallow(parent);
26113
+ numbers_meta_add_dep(mlist, deps, tmaref, newtileref);
25195
26114
  ai.messages[0].data = write_shallow(mlist);
25196
26115
  });
25197
26116
  }
@@ -25236,11 +26155,33 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25236
26155
  }
25237
26156
  if (trunc)
25238
26157
  console.error("Truncating to ".concat(encode_range(range)));
25239
- var data = sheet_to_json(ws, { range: range, header: 1 });
25240
- var SST = ["~Sh33tJ5~"];
25241
- var loc = deps[tmaref].location;
25242
- loc = loc.replace(/^Root Entry\//, "");
25243
- loc = loc.replace(/^Index\//, "").replace(/\.iwa$/, "");
26158
+ var data = [];
26159
+ if (ws["!data"])
26160
+ data = ws["!data"];
26161
+ else {
26162
+ var colstr = [];
26163
+ for (var _C = 0; _C <= range.e.c; ++_C)
26164
+ colstr[_C] = encode_col(_C);
26165
+ for (var R_ = 0; R_ <= range.e.r; ++R_) {
26166
+ data[R_] = [];
26167
+ var _R = "" + (R_ + 1);
26168
+ for (_C = 0; _C <= range.e.c; ++_C) {
26169
+ var _cell = ws[colstr[_C] + _R];
26170
+ if (!_cell)
26171
+ continue;
26172
+ data[R_][_C] = _cell;
26173
+ }
26174
+ }
26175
+ }
26176
+ var LUT = {
26177
+ cmnt: [{ a: "~54ee77S~", t: "... the people who are crazy enough to think they can change the world, are the ones who do." }],
26178
+ ferr: [],
26179
+ fmla: [],
26180
+ nfmt: [],
26181
+ ofmt: [],
26182
+ rsst: [{ v: "~54ee77S~", l: "https://sheetjs.com/" }],
26183
+ sst: ["~Sh33tJ5~"]
26184
+ };
25244
26185
  var pb = parse_shallow(tmaroot.messages[0].data);
25245
26186
  {
25246
26187
  pb[6][0].data = write_varint49(range.e.r + 1);
@@ -25294,22 +26235,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25294
26235
  mlist[3] = mlist[3].filter(function(m) {
25295
26236
  return varint_to_i32(parse_shallow(m.data)[1][0].data) != tileref;
25296
26237
  });
25297
- var parentidx = mlist[3].findIndex(function(m) {
25298
- var _a, _b;
25299
- var mm = parse_shallow(m.data);
25300
- if ((_a = mm[3]) == null ? void 0 : _a[0])
25301
- return u8str(mm[3][0].data) == loc;
25302
- if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc)
25303
- return true;
25304
- return false;
25305
- });
25306
- var parent = parse_shallow(mlist[3][parentidx].data);
25307
- if (!parent[6])
25308
- parent[6] = [];
25309
- parent[6] = parent[6].filter(function(m) {
25310
- return varint_to_i32(parse_shallow(m.data)[1][0].data) != tileref;
25311
- });
25312
- mlist[3][parentidx].data = write_shallow(parent);
26238
+ numbers_meta_del_dep(mlist, deps, tmaref, tileref);
25313
26239
  ai.messages[0].data = write_shallow(mlist);
25314
26240
  });
25315
26241
  numbers_del_oref(tmaroot, tileref);
@@ -25335,7 +26261,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25335
26261
  [{ type: 0, data: write_varint49(1 ) }]
25336
26262
  ];
25337
26263
  for (var R = tidx * tstride; R <= Math.min(range.e.r, (tidx + 1) * tstride - 1); ++R) {
25338
- var tilerow = write_TST_TileRowInfo(data[R], SST, USE_WIDE_ROWS);
26264
+ var tilerow = write_TST_TileRowInfo(data[R], LUT, USE_WIDE_ROWS);
25339
26265
  tilerow[1][0].data = write_varint49(R - tidx * tstride);
25340
26266
  tiledata[5].push({ data: write_shallow(tilerow), type: 2 });
25341
26267
  }
@@ -25368,26 +26294,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25368
26294
  [{ type: 0, data: write_varint49(save_token) }]
25369
26295
  ]) });
25370
26296
  mlist[1] = [{ type: 0, data: write_varint49(Math.max(newtileid + 1, varint_to_i32(mlist[1][0].data))) }];
25371
- var parentidx = mlist[3].findIndex(function(m) {
25372
- var _a, _b;
25373
- var mm = parse_shallow(m.data);
25374
- if ((_a = mm[3]) == null ? void 0 : _a[0])
25375
- return u8str(mm[3][0].data) == loc;
25376
- if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc)
25377
- return true;
25378
- return false;
25379
- });
25380
- var parent = parse_shallow(mlist[3][parentidx].data);
25381
- if (!parent[6])
25382
- parent[6] = [];
25383
- parent[6].push({
25384
- type: 2,
25385
- data: write_shallow([
25386
- [],
25387
- [{ type: 0, data: write_varint49(newtileid) }]
25388
- ])
25389
- });
25390
- mlist[3][parentidx].data = write_shallow(parent);
26297
+ numbers_meta_add_dep(mlist, deps, tmaref, newtileid);
25391
26298
  ai.messages[0].data = write_shallow(mlist);
25392
26299
  });
25393
26300
  numbers_add_oref(tmaroot, newtileid);
@@ -25429,26 +26336,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25429
26336
  store[13] = [{ type: 2, data: write_TSP_Reference(mergeid) }];
25430
26337
  numbers_iwa_doit(cfb, deps, 2, function(ai) {
25431
26338
  var mlist = parse_shallow(ai.messages[0].data);
25432
- var parentidx = mlist[3].findIndex(function(m) {
25433
- var _a, _b;
25434
- var mm = parse_shallow(m.data);
25435
- if ((_a = mm[3]) == null ? void 0 : _a[0])
25436
- return u8str(mm[3][0].data) == loc;
25437
- if (((_b = mm[2]) == null ? void 0 : _b[0]) && u8str(mm[2][0].data) == loc)
25438
- return true;
25439
- return false;
25440
- });
25441
- var parent = parse_shallow(mlist[3][parentidx].data);
25442
- if (!parent[6])
25443
- parent[6] = [];
25444
- parent[6].push({
25445
- type: 2,
25446
- data: write_shallow([
25447
- [],
25448
- [{ type: 0, data: write_varint49(mergeid) }]
25449
- ])
25450
- });
25451
- mlist[3][parentidx].data = write_shallow(parent);
26339
+ numbers_meta_add_dep(mlist, deps, tmaref, mergeid);
25452
26340
  ai.messages[0].data = write_shallow(mlist);
25453
26341
  });
25454
26342
  numbers_add_oref(tmaroot, mergeid);
@@ -25459,7 +26347,7 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25459
26347
  var sstdata = parse_shallow(sstroot.messages[0].data);
25460
26348
  {
25461
26349
  sstdata[3] = [];
25462
- SST.forEach(function(str, i) {
26350
+ LUT.sst.forEach(function(str, i) {
25463
26351
  if (i == 0)
25464
26352
  return;
25465
26353
  sstdata[3].push({ type: 2, data: write_shallow([
@@ -25472,6 +26360,197 @@ function write_numbers_tma(cfb, deps, ws, tmaroot, tmafile, tmaref) {
25472
26360
  }
25473
26361
  sstroot.messages[0].data = write_shallow(sstdata);
25474
26362
  });
26363
+ var rsstref = parse_TSP_Reference(store[17][0].data);
26364
+ numbers_iwa_doit(cfb, deps, rsstref, function(rsstroot) {
26365
+ var rsstdata = parse_shallow(rsstroot.messages[0].data);
26366
+ rsstdata[3] = [];
26367
+ var style_indices = [
26368
+ 904980,
26369
+ 903835,
26370
+ 903815,
26371
+ 903845
26372
+ ];
26373
+ LUT.rsst.forEach(function(rsst, i) {
26374
+ if (i == 0)
26375
+ return;
26376
+ var tswpsa = [
26377
+ [],
26378
+ [{ type: 0, data: new Uint8Array([5]) }],
26379
+ [],
26380
+ [{ type: 2, data: stru8(rsst.v) }]
26381
+ ];
26382
+ tswpsa[10] = [{ type: 0, data: new Uint8Array([1]) }];
26383
+ tswpsa[19] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 18, 2, 101, 110]) }];
26384
+ tswpsa[5] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 155, 149, 55]) }];
26385
+ tswpsa[2] = [{ type: 2, data: new Uint8Array([8, 148, 158, 55]) }];
26386
+ tswpsa[6] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }];
26387
+ tswpsa[7] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 135, 149, 55]) }];
26388
+ tswpsa[8] = [{ type: 2, data: new Uint8Array([10, 8, 8, 0, 18, 4, 8, 165, 149, 55]) }];
26389
+ tswpsa[14] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }];
26390
+ tswpsa[24] = [{ type: 2, data: new Uint8Array([10, 6, 8, 0, 16, 0, 24, 0]) }];
26391
+ var tswpsaid = get_unique_msgid({ deps: [], location: "", type: 2001 }, deps);
26392
+ var tswpsarefs = [];
26393
+ if (rsst.l) {
26394
+ var newhlinkid = numbers_add_msg(cfb, 2032, [
26395
+ [],
26396
+ [],
26397
+ [{ type: 2, data: stru8(rsst.l) }]
26398
+ ], "/Index/Tables/DataList", deps);
26399
+ tswpsa[11] = [];
26400
+ var smartfield = [[], []];
26401
+ if (!smartfield[1])
26402
+ smartfield[1] = [];
26403
+ smartfield[1].push({ type: 2, data: write_shallow([
26404
+ [],
26405
+ [{ type: 0, data: write_varint49(0) }],
26406
+ [{ type: 2, data: write_TSP_Reference(newhlinkid) }]
26407
+ ]) });
26408
+ tswpsa[11][0] = { type: 2, data: write_shallow(smartfield) };
26409
+ tswpsarefs.push(newhlinkid);
26410
+ }
26411
+ numbers_add_msg(cfb, 2001, tswpsa, "/Index/Tables/DataList", deps, tswpsaid);
26412
+ numbers_iwa_doit(cfb, deps, tswpsaid, function(iwa) {
26413
+ style_indices.forEach(function(ref) {
26414
+ return numbers_add_oref(iwa, ref);
26415
+ });
26416
+ tswpsarefs.forEach(function(ref) {
26417
+ return numbers_add_oref(iwa, ref);
26418
+ });
26419
+ });
26420
+ var rtpaid = numbers_add_msg(cfb, 6218, [
26421
+ [],
26422
+ [{ type: 2, data: write_TSP_Reference(tswpsaid) }],
26423
+ [],
26424
+ [{ type: 2, data: new Uint8Array([13, 255, 255, 255, 0, 18, 10, 16, 255, 255, 1, 24, 255, 255, 255, 255, 7]) }]
26425
+ ], "/Index/Tables/DataList", deps);
26426
+ numbers_iwa_doit(cfb, deps, rtpaid, function(iwa) {
26427
+ return numbers_add_oref(iwa, tswpsaid);
26428
+ });
26429
+ rsstdata[3].push({ type: 2, data: write_shallow([
26430
+ [],
26431
+ [{ type: 0, data: write_varint49(i) }],
26432
+ [{ type: 0, data: write_varint49(1) }],
26433
+ [],
26434
+ [],
26435
+ [],
26436
+ [],
26437
+ [],
26438
+ [],
26439
+ [{ type: 2, data: write_TSP_Reference(rtpaid) }]
26440
+ ]) });
26441
+ numbers_add_oref(rsstroot, rtpaid);
26442
+ numbers_iwa_doit(cfb, deps, 2, function(ai) {
26443
+ var mlist = parse_shallow(ai.messages[0].data);
26444
+ numbers_meta_add_dep(mlist, deps, rsstref, rtpaid);
26445
+ numbers_meta_add_dep(mlist, deps, rtpaid, tswpsaid);
26446
+ numbers_meta_add_dep(mlist, deps, tswpsaid, tswpsarefs);
26447
+ numbers_meta_add_dep(mlist, deps, tswpsaid, style_indices);
26448
+ ai.messages[0].data = write_shallow(mlist);
26449
+ });
26450
+ });
26451
+ rsstroot.messages[0].data = write_shallow(rsstdata);
26452
+ });
26453
+ if (LUT.cmnt.length > 1) {
26454
+ var cmntref = parse_TSP_Reference(store[19][0].data);
26455
+ var authors = {}, iauthor = 0;
26456
+ numbers_iwa_doit(cfb, deps, cmntref, function(cmntroot) {
26457
+ var cmntdata = parse_shallow(cmntroot.messages[0].data);
26458
+ {
26459
+ cmntdata[3] = [];
26460
+ LUT.cmnt.forEach(function(cc, i) {
26461
+ if (i == 0)
26462
+ return;
26463
+ var replies = [];
26464
+ if (cc.replies)
26465
+ cc.replies.forEach(function(c) {
26466
+ if (!authors[c.a || ""])
26467
+ authors[c.a || ""] = numbers_add_msg(cfb, 212, [
26468
+ [],
26469
+ [{ type: 2, data: stru8(c.a || "") }],
26470
+ [{ type: 2, data: get_author_color(++iauthor) }],
26471
+ [],
26472
+ [{ type: 0, data: write_varint49(0) }]
26473
+ ], "/Index/Tables/DataList", deps);
26474
+ var aaaid2 = authors[c.a || ""];
26475
+ var csaid2 = numbers_add_msg(cfb, 3056, [
26476
+ [],
26477
+ [{ type: 2, data: stru8(c.t || "") }],
26478
+ [{ type: 2, data: write_shallow([
26479
+ [],
26480
+ [{ type: 1, data: new Uint8Array([0, 0, 0, 128, 116, 109, 182, 65]) }]
26481
+ ]) }],
26482
+ [{ type: 2, data: write_TSP_Reference(aaaid2) }]
26483
+ ], "/Index/Tables/DataList", deps);
26484
+ numbers_iwa_doit(cfb, deps, csaid2, function(iwa) {
26485
+ return numbers_add_oref(iwa, aaaid2);
26486
+ });
26487
+ replies.push(csaid2);
26488
+ numbers_iwa_doit(cfb, deps, 2, function(ai) {
26489
+ var mlist = parse_shallow(ai.messages[0].data);
26490
+ numbers_meta_add_dep(mlist, deps, csaid2, aaaid2);
26491
+ ai.messages[0].data = write_shallow(mlist);
26492
+ });
26493
+ });
26494
+ if (!authors[cc.a || ""])
26495
+ authors[cc.a || ""] = numbers_add_msg(cfb, 212, [
26496
+ [],
26497
+ [{ type: 2, data: stru8(cc.a || "") }],
26498
+ [{ type: 2, data: get_author_color(++iauthor) }],
26499
+ [],
26500
+ [{ type: 0, data: write_varint49(0) }]
26501
+ ], "/Index/Tables/DataList", deps);
26502
+ var aaaid = authors[cc.a || ""];
26503
+ var csaid = numbers_add_msg(cfb, 3056, [
26504
+ [],
26505
+ [{ type: 2, data: stru8(cc.t || "") }],
26506
+ [{ type: 2, data: write_shallow([
26507
+ [],
26508
+ [{ type: 1, data: new Uint8Array([0, 0, 0, 128, 116, 109, 182, 65]) }]
26509
+ ]) }],
26510
+ [{ type: 2, data: write_TSP_Reference(aaaid) }],
26511
+ replies.map(function(r) {
26512
+ return { type: 2, data: write_TSP_Reference(r) };
26513
+ }),
26514
+ [{ type: 2, data: write_shallow([
26515
+ [],
26516
+ [{ type: 0, data: write_varint49(i) }],
26517
+ [{ type: 0, data: write_varint49(0) }]
26518
+ ]) }]
26519
+ ], "/Index/Tables/DataList", deps);
26520
+ numbers_iwa_doit(cfb, deps, csaid, function(iwa) {
26521
+ numbers_add_oref(iwa, aaaid);
26522
+ replies.forEach(function(r) {
26523
+ return numbers_add_oref(iwa, r);
26524
+ });
26525
+ });
26526
+ cmntdata[3].push({ type: 2, data: write_shallow([
26527
+ [],
26528
+ [{ type: 0, data: write_varint49(i) }],
26529
+ [{ type: 0, data: write_varint49(1) }],
26530
+ [],
26531
+ [],
26532
+ [],
26533
+ [],
26534
+ [],
26535
+ [],
26536
+ [],
26537
+ [{ type: 2, data: write_TSP_Reference(csaid) }]
26538
+ ]) });
26539
+ numbers_add_oref(cmntroot, csaid);
26540
+ numbers_iwa_doit(cfb, deps, 2, function(ai) {
26541
+ var mlist = parse_shallow(ai.messages[0].data);
26542
+ numbers_meta_add_dep(mlist, deps, cmntref, csaid);
26543
+ numbers_meta_add_dep(mlist, deps, csaid, aaaid);
26544
+ if (replies.length)
26545
+ numbers_meta_add_dep(mlist, deps, csaid, replies);
26546
+ ai.messages[0].data = write_shallow(mlist);
26547
+ });
26548
+ });
26549
+ }
26550
+ cmntdata[2][0].data = write_varint49(LUT.cmnt.length + 1);
26551
+ cmntroot.messages[0].data = write_shallow(cmntdata);
26552
+ });
26553
+ }
25475
26554
  }
25476
26555
  pb[4][0].data = write_shallow(store);
25477
26556
  }
@@ -25538,6 +26617,13 @@ function safe_parse_wbrels(wbrels, sheets) {
25538
26617
  return !wbrels || wbrels.length === 0 ? null : wbrels;
25539
26618
  }
25540
26619
 
26620
+ function parse_sheet_legacy_drawing(sheet, type, zip, path, idx, opts, wb, comments) {
26621
+ if(!sheet || !sheet['!legdrawel']) return;
26622
+ var dfile = resolve_path(sheet['!legdrawel'].Target, path);
26623
+ var draw = getzipstr(zip, dfile, true);
26624
+ if(draw) parse_vml(utf8read(draw), sheet, comments||[]);
26625
+ }
26626
+
25541
26627
  function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/*:number*/, sheetRels, sheets, stype/*:string*/, opts, wb, themes, styles) {
25542
26628
  try {
25543
26629
  sheetRels[sheet]=parse_rels(getzipstr(zip, relsPath, true), path);
@@ -25576,6 +26662,7 @@ function safe_parse_sheet(zip, path/*:string*/, relsPath/*:string*/, sheet, idx/
25576
26662
  }
25577
26663
  });
25578
26664
  if(tcomments && tcomments.length) sheet_insert_comments(_ws, tcomments, true, opts.people || []);
26665
+ parse_sheet_legacy_drawing(_ws, stype, zip, path, idx, opts, wb, comments);
25579
26666
  } catch(e) { if(opts.WTF) throw e; }
25580
26667
  }
25581
26668
 
@@ -25878,6 +26965,9 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
25878
26965
  add_rels(opts.rels, 4, f, RELS.CUST_PROPS);
25879
26966
  }
25880
26967
 
26968
+ var people = ["SheetJ5"];
26969
+ opts.tcid = 0;
26970
+
25881
26971
  for(rId=1;rId <= wb.SheetNames.length; ++rId) {
25882
26972
  var wsrels = {'!id':{}};
25883
26973
  var ws = wb.Sheets[wb.SheetNames[rId-1]];
@@ -25897,6 +26987,17 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
25897
26987
  var need_vml = false;
25898
26988
  var cf = "";
25899
26989
  if(comments && comments.length > 0) {
26990
+ var needtc = false;
26991
+ comments.forEach(function(carr) {
26992
+ carr[1].forEach(function(c) { if(c.T == true) needtc = true; });
26993
+ });
26994
+ if(needtc) {
26995
+ cf = "xl/threadedComments/threadedComment" + rId + ".xml";
26996
+ zip_add_file(zip, cf, write_tcmnt_xml(comments, people, opts));
26997
+ ct.threadedcomments.push(cf);
26998
+ add_rels(wsrels, -1, "../threadedComments/threadedComment" + rId + ".xml", RELS.TCMNT);
26999
+ }
27000
+
25900
27001
  cf = "xl/comments" + rId + "." + wbext;
25901
27002
  zip_add_file(zip, cf, write_comments_bin(comments));
25902
27003
  ct.comments.push(cf);
@@ -25952,6 +27053,13 @@ function write_zip_xlsb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:ZIP*/ {
25952
27053
  ct.metadata.push(f);
25953
27054
  add_rels(opts.wbrels, -1, "metadata." + wbext, RELS.XLMETA);
25954
27055
 
27056
+ if(people.length > 1) {
27057
+ f = "xl/persons/person.xml";
27058
+ zip_add_file(zip, f, write_people_xml(people));
27059
+ ct.people.push(f);
27060
+ add_rels(opts.wbrels, -1, "persons/person.xml", RELS.PEOPLE);
27061
+ }
27062
+
25955
27063
  zip_add_file(zip, "[Content_Types].xml", write_ct(ct, opts));
25956
27064
  zip_add_file(zip, '_rels/.rels', write_rels(opts.rels));
25957
27065
  zip_add_file(zip, 'xl/_rels/workbook.' + wbext + '.rels', write_rels(opts.wbrels));
@@ -26408,7 +27516,7 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
26408
27516
  }
26409
27517
  if(!dense || sheet["!data"][R]) for (var C = r.s.c; C <= r.e.c; ++C) {
26410
27518
  var val = dense ? (sheet["!data"][R]||[])[C] : sheet[cols[C] + rr];
26411
- if(val === undefined || val.t === undefined) {
27519
+ if(val == null || val.t === undefined) {
26412
27520
  if(defval === undefined) continue;
26413
27521
  if(hdr[C] != null) { row[hdr[C]] = defval; }
26414
27522
  continue;
@@ -26417,7 +27525,12 @@ function make_json_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Ar
26417
27525
  switch(val.t){
26418
27526
  case 'z': if(v == null) break; continue;
26419
27527
  case 'e': v = (v == 0 ? null : void 0); break;
26420
- case 's': case 'd': case 'b': case 'n': break;
27528
+ case 's': case 'b':
27529
+ case 'n': if(!val.z || !fmt_is_date(val.z)) break;
27530
+ v = numdate(v); // TODO: date1904 setting should also be stored in worksheet object
27531
+ if(typeof v == "number") break;
27532
+ /* falls through */
27533
+ case 'd': if(!(o && o.UTC)) v = utc_to_local(v); break;
26421
27534
  default: throw new Error('unrecognized type ' + val.t);
26422
27535
  }
26423
27536
  if(hdr[C] != null) {
@@ -26624,6 +27737,7 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
26624
27737
  else if(typeof v == 'string') t = 's';
26625
27738
  else if(v instanceof Date) {
26626
27739
  t = 'd';
27740
+ if(!o.UTC) v = local_to_utc(v);
26627
27741
  if(!o.cellDates) { t = 'n'; v = datenum(v); }
26628
27742
  z = (cell != null && cell.z && fmt_is_date(cell.z)) ? cell.z : (o.dateNF || table_fmt[14]);
26629
27743
  }