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