diff --git a/bits/83_numbers.js b/bits/83_numbers.js
index bdafa36..e716f9f 100644
--- a/bits/83_numbers.js
+++ b/bits/83_numbers.js
@@ -411,37 +411,168 @@ function compress_iwa_file(buf) {
   }
   return u8concat(out);
 }
-function parse_old_storage(buf, sst, rsst, v) {
+var numbers_lut_new = function() {
+  return { sst: [], rsst: [], ofmt: [], nfmt: [] };
+};
+function numbers_format_cell(cell, t, flags, ofmt, nfmt) {
+  var _a, _b, _c, _d;
+  var ctype = t & 255, ver = t >> 8;
+  var fmt = ver >= 5 ? nfmt : ofmt;
+  dur:
+    if (flags & (ver > 4 ? 8 : 4) && cell.t == "n" && ctype == 7) {
+      var dstyle = ((_a = fmt[7]) == null ? void 0 : _a[0]) ? parse_varint49(fmt[7][0].data) : -1;
+      var dmin = ((_b = fmt[15]) == null ? void 0 : _b[0]) ? parse_varint49(fmt[15][0].data) : -1;
+      var dmax = ((_c = fmt[16]) == null ? void 0 : _c[0]) ? parse_varint49(fmt[16][0].data) : -1;
+      var auto = ((_d = fmt[40]) == null ? void 0 : _d[0]) ? parse_varint49(fmt[40][0].data) : -1;
+      if (dstyle == -1)
+        break dur;
+      var d = cell.v, dd = d;
+      autodur:
+        if (auto) {
+          if (d == 0) {
+            dmin = dmax = 2;
+            break autodur;
+          }
+          if (d >= 604800)
+            dmin = 1;
+          else if (d >= 86400)
+            dmin = 2;
+          else if (d >= 3600)
+            dmin = 4;
+          else if (d >= 60)
+            dmin = 8;
+          else if (d >= 1)
+            dmin = 16;
+          else
+            dmin = 32;
+          if (Math.floor(d) != d)
+            dmax = 32;
+          else if (d % 60)
+            dmax = 16;
+          else if (d % 3600)
+            dmax = 8;
+          else if (d % 86400)
+            dmax = 4;
+          else if (d % 604800)
+            dmax = 2;
+          if (dmax < dmin)
+            dmax = dmin;
+        }
+      if (dmin == -1 || dmax == -1)
+        break dur;
+      var dstr = [], zstr = [];
+      if (dmin == 1) {
+        dd = d / 604800;
+        if (dmax == 1) {
+          zstr.push('d"d"');
+        } else {
+          dd |= 0;
+          d -= 604800 * dd;
+        }
+        dstr.push(dd + (dstyle == 2 ? " week" + (dd == 1 ? "" : "s") : dstyle == 1 ? "w" : ""));
+      }
+      if (dmin <= 2 && dmax >= 2) {
+        dd = d / 86400;
+        if (dmax > 2) {
+          dd |= 0;
+          d -= 86400 * dd;
+        }
+        zstr.push('d"d"');
+        dstr.push(dd + (dstyle == 2 ? " day" + (dd == 1 ? "" : "s") : dstyle == 1 ? "d" : ""));
+      }
+      if (dmin <= 4 && dmax >= 4) {
+        dd = d / 3600;
+        if (dmax > 4) {
+          dd |= 0;
+          d -= 3600 * dd;
+        }
+        zstr.push((dmin >= 4 ? "[h]" : "h") + '"h"');
+        dstr.push(dd + (dstyle == 2 ? " hour" + (dd == 1 ? "" : "s") : dstyle == 1 ? "h" : ""));
+      }
+      if (dmin <= 8 && dmax >= 8) {
+        dd = d / 60;
+        if (dmax > 8) {
+          dd |= 0;
+          d -= 60 * dd;
+        }
+        zstr.push((dmin >= 8 ? "[m]" : "m") + '"m"');
+        if (dstyle == 0)
+          dstr.push((dmin == 8 && dmax == 8 || dd >= 10 ? "" : "0") + dd);
+        else
+          dstr.push(dd + (dstyle == 2 ? " minute" + (dd == 1 ? "" : "s") : dstyle == 1 ? "m" : ""));
+      }
+      if (dmin <= 16 && dmax >= 16) {
+        dd = d;
+        if (dmax > 16) {
+          dd |= 0;
+          d -= dd;
+        }
+        zstr.push((dmin >= 16 ? "[s]" : "s") + '"s"');
+        if (dstyle == 0)
+          dstr.push((dmax == 16 && dmin == 16 || dd >= 10 ? "" : "0") + dd);
+        else
+          dstr.push(dd + (dstyle == 2 ? " second" + (dd == 1 ? "" : "s") : dstyle == 1 ? "s" : ""));
+      }
+      if (dmax >= 32) {
+        dd = Math.round(1e3 * d);
+        if (dmin < 32)
+          zstr.push('.000"ms"');
+        if (dstyle == 0)
+          dstr.push((dd >= 100 ? "" : dd >= 10 ? "0" : "00") + dd);
+        else
+          dstr.push(dd + (dstyle == 2 ? " millisecond" + (dd == 1 ? "" : "s") : dstyle == 1 ? "ms" : ""));
+      }
+      cell.w = dstr.join(dstyle == 0 ? ":" : " ");
+      cell.z = zstr.join(dstyle == 0 ? '":"' : " ");
+      if (dstyle == 0)
+        cell.w = cell.w.replace(/:(\d\d\d)$/, ".$1");
+    }
+}
+function parse_old_storage(buf, lut, v) {
   var dv = u8_to_dataview(buf);
   var flags = dv.getUint32(4, true);
-  var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4;
-  var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
-  if (flags & 512) {
-    ridx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+  var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
+  var doff = v > 1 ? 12 : 8;
+  if (flags & 2) {
+    zidx = dv.getUint32(doff, true);
+    doff += 4;
   }
-  data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4;
+  doff += popcnt(flags & (v > 1 ? 3468 : 396)) * 4;
+  if (flags & 512) {
+    ridx = dv.getUint32(doff, true);
+    doff += 4;
+  }
+  doff += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4;
   if (flags & 16) {
-    sidx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+    sidx = dv.getUint32(doff, true);
+    doff += 4;
   }
   if (flags & 32) {
-    ieee = dv.getFloat64(data_offset, true);
-    data_offset += 8;
+    ieee = dv.getFloat64(doff, true);
+    doff += 8;
   }
   if (flags & 64) {
-    dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1e3);
-    data_offset += 8;
+    dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
+    doff += 8;
+  }
+  if (v > 1) {
+    flags = dv.getUint32(8, true) >>> 16;
+    if (flags & 255) {
+      if (zidx == -1)
+        zidx = dv.getUint32(doff, true);
+      doff += 4;
+    }
   }
   var ret;
-  switch (buf[2]) {
+  var t = buf[v >= 4 ? 1 : 2];
+  switch (t) {
     case 0:
       return void 0;
     case 2:
       ret = { t: "n", v: ieee };
       break;
     case 3:
-      ret = { t: "s", v: sst[sidx] };
+      ret = { t: "s", v: lut.sst[sidx] };
       break;
     case 5:
       ret = { t: "d", v: dt };
@@ -450,7 +581,7 @@ function parse_old_storage(buf, sst, rsst, v) {
       ret = { t: "b", v: ieee > 0 };
       break;
     case 7:
-      ret = { t: "n", v: ieee / 86400 };
+      ret = { t: "n", v: ieee };
       break;
     case 8:
       ret = { t: "e", v: 0 };
@@ -458,7 +589,7 @@ function parse_old_storage(buf, sst, rsst, v) {
     case 9:
       {
         if (ridx > -1)
-          ret = { t: "s", v: rsst[ridx] };
+          ret = { t: "s", v: lut.rsst[ridx] };
         else
           throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4)));
       }
@@ -466,42 +597,53 @@ function parse_old_storage(buf, sst, rsst, v) {
     default:
       throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4)));
   }
+  if (zidx > -1)
+    numbers_format_cell(ret, t | v << 8, flags, lut.ofmt[zidx], lut.nfmt[zidx]);
+  if (t == 7)
+    ret.v /= 86400;
   return ret;
 }
-function parse_new_storage(buf, sst, rsst) {
+function parse_new_storage(buf, lut) {
   var dv = u8_to_dataview(buf);
   var flags = dv.getUint32(8, true);
-  var data_offset = 12;
-  var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
+  var doff = 12;
+  var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
   if (flags & 1) {
-    d128 = readDecimal128LE(buf, data_offset);
-    data_offset += 16;
+    d128 = readDecimal128LE(buf, doff);
+    doff += 16;
   }
   if (flags & 2) {
-    ieee = dv.getFloat64(data_offset, true);
-    data_offset += 8;
+    ieee = dv.getFloat64(doff, true);
+    doff += 8;
   }
   if (flags & 4) {
-    dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1e3);
-    data_offset += 8;
+    dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
+    doff += 8;
   }
   if (flags & 8) {
-    sidx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+    sidx = dv.getUint32(doff, true);
+    doff += 4;
   }
   if (flags & 16) {
-    ridx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+    ridx = dv.getUint32(doff, true);
+    doff += 4;
+  }
+  doff += popcnt(flags & 8160) * 4;
+  if (flags & 516096) {
+    if (zidx == -1)
+      zidx = dv.getUint32(doff, true);
+    doff += 4;
   }
   var ret;
-  switch (buf[1]) {
+  var t = buf[1];
+  switch (t) {
     case 0:
       return void 0;
     case 2:
       ret = { t: "n", v: d128 };
       break;
     case 3:
-      ret = { t: "s", v: sst[sidx] };
+      ret = { t: "s", v: lut.sst[sidx] };
       break;
     case 5:
       ret = { t: "d", v: dt };
@@ -510,7 +652,7 @@ function parse_new_storage(buf, sst, rsst) {
       ret = { t: "b", v: ieee > 0 };
       break;
     case 7:
-      ret = { t: "n", v: ieee / 86400 };
+      ret = { t: "n", v: ieee };
       break;
     case 8:
       ret = { t: "e", v: 0 };
@@ -518,7 +660,7 @@ function parse_new_storage(buf, sst, rsst) {
     case 9:
       {
         if (ridx > -1)
-          ret = { t: "s", v: rsst[ridx] };
+          ret = { t: "s", v: lut.rsst[ridx] };
         else
           throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf[subarray](0, 4)));
       }
@@ -529,6 +671,10 @@ function parse_new_storage(buf, sst, rsst) {
     default:
       throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf[subarray](0, 4)));
   }
+  if (zidx > -1)
+    numbers_format_cell(ret, t | 5 << 8, flags >> 13, lut.ofmt[zidx], lut.nfmt[zidx]);
+  if (t == 7)
+    ret.v /= 86400;
   return ret;
 }
 function write_new_storage(cell, sst) {
@@ -591,15 +737,16 @@ function write_old_storage(cell, sst) {
   dv.setUint32(4, flags, true);
   return out[subarray](0, l);
 }
-function parse_cell_storage(buf, sst, rsst) {
+function parse_cell_storage(buf, lut) {
   switch (buf[0]) {
     case 0:
     case 1:
     case 2:
     case 3:
-      return parse_old_storage(buf, sst, rsst, buf[0]);
+    case 4:
+      return parse_old_storage(buf, lut, buf[0]);
     case 5:
-      return parse_new_storage(buf, sst, rsst);
+      return parse_new_storage(buf, lut);
     default:
       throw new Error("Unsupported payload version ".concat(buf[0]));
   }
@@ -640,6 +787,11 @@ function parse_TST_TableDataList(M, root) {
           }).join("");
         }
         break;
+      case 2:
+        data[key] = parse_shallow(le[6][0].data);
+        break;
+      default:
+        throw type;
     }
   });
   return data;
@@ -704,7 +856,7 @@ function parse_TST_Tile(M, root) {
   };
 }
 function parse_TST_TableModelArchive(M, root, ws) {
-  var _a, _b, _c;
+  var _a, _b, _c, _d, _e, _f;
   var pb = parse_shallow(root.data);
   var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
   range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
@@ -716,8 +868,15 @@ function parse_TST_TableModelArchive(M, root, ws) {
   ws["!ref"] = encode_range(range);
   var dense = Array.isArray(ws);
   var store = parse_shallow(pb[4][0].data);
-  var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
-  var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : [];
+  var lut = numbers_lut_new();
+  if ((_a = store[4]) == null ? void 0 : _a[0])
+    lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
+  if ((_b = store[11]) == null ? void 0 : _b[0])
+    lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]);
+  if ((_c = store[17]) == null ? void 0 : _c[0])
+    lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]);
+  if ((_d = store[22]) == null ? void 0 : _d[0])
+    lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
   var tile = parse_shallow(store[3][0].data);
   var _R = 0;
   tile[1].forEach(function(t) {
@@ -729,7 +888,7 @@ function parse_TST_TableModelArchive(M, root, ws) {
     var _tile = parse_TST_Tile(M, ref2);
     _tile.data.forEach(function(row, R) {
       row.forEach(function(buf, C) {
-        var res = parse_cell_storage(buf, sst, rsst);
+        var res = parse_cell_storage(buf, lut);
         if (res) {
           if (dense) {
             if (!ws[_R + R])
@@ -744,12 +903,12 @@ function parse_TST_TableModelArchive(M, root, ws) {
     });
     _R += _tile.nrows;
   });
-  if ((_b = store[13]) == null ? void 0 : _b[0]) {
+  if ((_e = store[13]) == null ? void 0 : _e[0]) {
     var ref = M[parse_TSP_Reference(store[13][0].data)][0];
     var mtype = varint_to_i32(ref.meta[1][0].data);
     if (mtype != 6144)
       throw new Error("Expected merge type 6144, found ".concat(mtype));
-    ws["!merges"] = (_c = parse_shallow(ref.data)) == null ? void 0 : _c[1].map(function(pi) {
+    ws["!merges"] = (_f = parse_shallow(ref.data)) == null ? void 0 : _f[1].map(function(pi) {
       var merge = parse_shallow(pi.data);
       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);
       return {
diff --git a/modules/83_numbers.js b/modules/83_numbers.js
index bdafa36..e716f9f 100644
--- a/modules/83_numbers.js
+++ b/modules/83_numbers.js
@@ -411,37 +411,168 @@ function compress_iwa_file(buf) {
   }
   return u8concat(out);
 }
-function parse_old_storage(buf, sst, rsst, v) {
+var numbers_lut_new = function() {
+  return { sst: [], rsst: [], ofmt: [], nfmt: [] };
+};
+function numbers_format_cell(cell, t, flags, ofmt, nfmt) {
+  var _a, _b, _c, _d;
+  var ctype = t & 255, ver = t >> 8;
+  var fmt = ver >= 5 ? nfmt : ofmt;
+  dur:
+    if (flags & (ver > 4 ? 8 : 4) && cell.t == "n" && ctype == 7) {
+      var dstyle = ((_a = fmt[7]) == null ? void 0 : _a[0]) ? parse_varint49(fmt[7][0].data) : -1;
+      var dmin = ((_b = fmt[15]) == null ? void 0 : _b[0]) ? parse_varint49(fmt[15][0].data) : -1;
+      var dmax = ((_c = fmt[16]) == null ? void 0 : _c[0]) ? parse_varint49(fmt[16][0].data) : -1;
+      var auto = ((_d = fmt[40]) == null ? void 0 : _d[0]) ? parse_varint49(fmt[40][0].data) : -1;
+      if (dstyle == -1)
+        break dur;
+      var d = cell.v, dd = d;
+      autodur:
+        if (auto) {
+          if (d == 0) {
+            dmin = dmax = 2;
+            break autodur;
+          }
+          if (d >= 604800)
+            dmin = 1;
+          else if (d >= 86400)
+            dmin = 2;
+          else if (d >= 3600)
+            dmin = 4;
+          else if (d >= 60)
+            dmin = 8;
+          else if (d >= 1)
+            dmin = 16;
+          else
+            dmin = 32;
+          if (Math.floor(d) != d)
+            dmax = 32;
+          else if (d % 60)
+            dmax = 16;
+          else if (d % 3600)
+            dmax = 8;
+          else if (d % 86400)
+            dmax = 4;
+          else if (d % 604800)
+            dmax = 2;
+          if (dmax < dmin)
+            dmax = dmin;
+        }
+      if (dmin == -1 || dmax == -1)
+        break dur;
+      var dstr = [], zstr = [];
+      if (dmin == 1) {
+        dd = d / 604800;
+        if (dmax == 1) {
+          zstr.push('d"d"');
+        } else {
+          dd |= 0;
+          d -= 604800 * dd;
+        }
+        dstr.push(dd + (dstyle == 2 ? " week" + (dd == 1 ? "" : "s") : dstyle == 1 ? "w" : ""));
+      }
+      if (dmin <= 2 && dmax >= 2) {
+        dd = d / 86400;
+        if (dmax > 2) {
+          dd |= 0;
+          d -= 86400 * dd;
+        }
+        zstr.push('d"d"');
+        dstr.push(dd + (dstyle == 2 ? " day" + (dd == 1 ? "" : "s") : dstyle == 1 ? "d" : ""));
+      }
+      if (dmin <= 4 && dmax >= 4) {
+        dd = d / 3600;
+        if (dmax > 4) {
+          dd |= 0;
+          d -= 3600 * dd;
+        }
+        zstr.push((dmin >= 4 ? "[h]" : "h") + '"h"');
+        dstr.push(dd + (dstyle == 2 ? " hour" + (dd == 1 ? "" : "s") : dstyle == 1 ? "h" : ""));
+      }
+      if (dmin <= 8 && dmax >= 8) {
+        dd = d / 60;
+        if (dmax > 8) {
+          dd |= 0;
+          d -= 60 * dd;
+        }
+        zstr.push((dmin >= 8 ? "[m]" : "m") + '"m"');
+        if (dstyle == 0)
+          dstr.push((dmin == 8 && dmax == 8 || dd >= 10 ? "" : "0") + dd);
+        else
+          dstr.push(dd + (dstyle == 2 ? " minute" + (dd == 1 ? "" : "s") : dstyle == 1 ? "m" : ""));
+      }
+      if (dmin <= 16 && dmax >= 16) {
+        dd = d;
+        if (dmax > 16) {
+          dd |= 0;
+          d -= dd;
+        }
+        zstr.push((dmin >= 16 ? "[s]" : "s") + '"s"');
+        if (dstyle == 0)
+          dstr.push((dmax == 16 && dmin == 16 || dd >= 10 ? "" : "0") + dd);
+        else
+          dstr.push(dd + (dstyle == 2 ? " second" + (dd == 1 ? "" : "s") : dstyle == 1 ? "s" : ""));
+      }
+      if (dmax >= 32) {
+        dd = Math.round(1e3 * d);
+        if (dmin < 32)
+          zstr.push('.000"ms"');
+        if (dstyle == 0)
+          dstr.push((dd >= 100 ? "" : dd >= 10 ? "0" : "00") + dd);
+        else
+          dstr.push(dd + (dstyle == 2 ? " millisecond" + (dd == 1 ? "" : "s") : dstyle == 1 ? "ms" : ""));
+      }
+      cell.w = dstr.join(dstyle == 0 ? ":" : " ");
+      cell.z = zstr.join(dstyle == 0 ? '":"' : " ");
+      if (dstyle == 0)
+        cell.w = cell.w.replace(/:(\d\d\d)$/, ".$1");
+    }
+}
+function parse_old_storage(buf, lut, v) {
   var dv = u8_to_dataview(buf);
   var flags = dv.getUint32(4, true);
-  var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 3470 : 398)) * 4;
-  var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
-  if (flags & 512) {
-    ridx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+  var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
+  var doff = v > 1 ? 12 : 8;
+  if (flags & 2) {
+    zidx = dv.getUint32(doff, true);
+    doff += 4;
   }
-  data_offset += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4;
+  doff += popcnt(flags & (v > 1 ? 3468 : 396)) * 4;
+  if (flags & 512) {
+    ridx = dv.getUint32(doff, true);
+    doff += 4;
+  }
+  doff += popcnt(flags & (v > 1 ? 12288 : 4096)) * 4;
   if (flags & 16) {
-    sidx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+    sidx = dv.getUint32(doff, true);
+    doff += 4;
   }
   if (flags & 32) {
-    ieee = dv.getFloat64(data_offset, true);
-    data_offset += 8;
+    ieee = dv.getFloat64(doff, true);
+    doff += 8;
   }
   if (flags & 64) {
-    dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1e3);
-    data_offset += 8;
+    dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
+    doff += 8;
+  }
+  if (v > 1) {
+    flags = dv.getUint32(8, true) >>> 16;
+    if (flags & 255) {
+      if (zidx == -1)
+        zidx = dv.getUint32(doff, true);
+      doff += 4;
+    }
   }
   var ret;
-  switch (buf[2]) {
+  var t = buf[v >= 4 ? 1 : 2];
+  switch (t) {
     case 0:
       return void 0;
     case 2:
       ret = { t: "n", v: ieee };
       break;
     case 3:
-      ret = { t: "s", v: sst[sidx] };
+      ret = { t: "s", v: lut.sst[sidx] };
       break;
     case 5:
       ret = { t: "d", v: dt };
@@ -450,7 +581,7 @@ function parse_old_storage(buf, sst, rsst, v) {
       ret = { t: "b", v: ieee > 0 };
       break;
     case 7:
-      ret = { t: "n", v: ieee / 86400 };
+      ret = { t: "n", v: ieee };
       break;
     case 8:
       ret = { t: "e", v: 0 };
@@ -458,7 +589,7 @@ function parse_old_storage(buf, sst, rsst, v) {
     case 9:
       {
         if (ridx > -1)
-          ret = { t: "s", v: rsst[ridx] };
+          ret = { t: "s", v: lut.rsst[ridx] };
         else
           throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4)));
       }
@@ -466,42 +597,53 @@ function parse_old_storage(buf, sst, rsst, v) {
     default:
       throw new Error("Unsupported cell type ".concat(buf[subarray](0, 4)));
   }
+  if (zidx > -1)
+    numbers_format_cell(ret, t | v << 8, flags, lut.ofmt[zidx], lut.nfmt[zidx]);
+  if (t == 7)
+    ret.v /= 86400;
   return ret;
 }
-function parse_new_storage(buf, sst, rsst) {
+function parse_new_storage(buf, lut) {
   var dv = u8_to_dataview(buf);
   var flags = dv.getUint32(8, true);
-  var data_offset = 12;
-  var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
+  var doff = 12;
+  var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
   if (flags & 1) {
-    d128 = readDecimal128LE(buf, data_offset);
-    data_offset += 16;
+    d128 = readDecimal128LE(buf, doff);
+    doff += 16;
   }
   if (flags & 2) {
-    ieee = dv.getFloat64(data_offset, true);
-    data_offset += 8;
+    ieee = dv.getFloat64(doff, true);
+    doff += 8;
   }
   if (flags & 4) {
-    dt.setTime(dt.getTime() + dv.getFloat64(data_offset, true) * 1e3);
-    data_offset += 8;
+    dt.setTime(dt.getTime() + dv.getFloat64(doff, true) * 1e3);
+    doff += 8;
   }
   if (flags & 8) {
-    sidx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+    sidx = dv.getUint32(doff, true);
+    doff += 4;
   }
   if (flags & 16) {
-    ridx = dv.getUint32(data_offset, true);
-    data_offset += 4;
+    ridx = dv.getUint32(doff, true);
+    doff += 4;
+  }
+  doff += popcnt(flags & 8160) * 4;
+  if (flags & 516096) {
+    if (zidx == -1)
+      zidx = dv.getUint32(doff, true);
+    doff += 4;
   }
   var ret;
-  switch (buf[1]) {
+  var t = buf[1];
+  switch (t) {
     case 0:
       return void 0;
     case 2:
       ret = { t: "n", v: d128 };
       break;
     case 3:
-      ret = { t: "s", v: sst[sidx] };
+      ret = { t: "s", v: lut.sst[sidx] };
       break;
     case 5:
       ret = { t: "d", v: dt };
@@ -510,7 +652,7 @@ function parse_new_storage(buf, sst, rsst) {
       ret = { t: "b", v: ieee > 0 };
       break;
     case 7:
-      ret = { t: "n", v: ieee / 86400 };
+      ret = { t: "n", v: ieee };
       break;
     case 8:
       ret = { t: "e", v: 0 };
@@ -518,7 +660,7 @@ function parse_new_storage(buf, sst, rsst) {
     case 9:
       {
         if (ridx > -1)
-          ret = { t: "s", v: rsst[ridx] };
+          ret = { t: "s", v: lut.rsst[ridx] };
         else
           throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf[subarray](0, 4)));
       }
@@ -529,6 +671,10 @@ function parse_new_storage(buf, sst, rsst) {
     default:
       throw new Error("Unsupported cell type ".concat(buf[1], " : ").concat(flags & 31, " : ").concat(buf[subarray](0, 4)));
   }
+  if (zidx > -1)
+    numbers_format_cell(ret, t | 5 << 8, flags >> 13, lut.ofmt[zidx], lut.nfmt[zidx]);
+  if (t == 7)
+    ret.v /= 86400;
   return ret;
 }
 function write_new_storage(cell, sst) {
@@ -591,15 +737,16 @@ function write_old_storage(cell, sst) {
   dv.setUint32(4, flags, true);
   return out[subarray](0, l);
 }
-function parse_cell_storage(buf, sst, rsst) {
+function parse_cell_storage(buf, lut) {
   switch (buf[0]) {
     case 0:
     case 1:
     case 2:
     case 3:
-      return parse_old_storage(buf, sst, rsst, buf[0]);
+    case 4:
+      return parse_old_storage(buf, lut, buf[0]);
     case 5:
-      return parse_new_storage(buf, sst, rsst);
+      return parse_new_storage(buf, lut);
     default:
       throw new Error("Unsupported payload version ".concat(buf[0]));
   }
@@ -640,6 +787,11 @@ function parse_TST_TableDataList(M, root) {
           }).join("");
         }
         break;
+      case 2:
+        data[key] = parse_shallow(le[6][0].data);
+        break;
+      default:
+        throw type;
     }
   });
   return data;
@@ -704,7 +856,7 @@ function parse_TST_Tile(M, root) {
   };
 }
 function parse_TST_TableModelArchive(M, root, ws) {
-  var _a, _b, _c;
+  var _a, _b, _c, _d, _e, _f;
   var pb = parse_shallow(root.data);
   var range = { s: { r: 0, c: 0 }, e: { r: 0, c: 0 } };
   range.e.r = (varint_to_i32(pb[6][0].data) >>> 0) - 1;
@@ -716,8 +868,15 @@ function parse_TST_TableModelArchive(M, root, ws) {
   ws["!ref"] = encode_range(range);
   var dense = Array.isArray(ws);
   var store = parse_shallow(pb[4][0].data);
-  var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
-  var rsst = ((_a = store[17]) == null ? void 0 : _a[0]) ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : [];
+  var lut = numbers_lut_new();
+  if ((_a = store[4]) == null ? void 0 : _a[0])
+    lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
+  if ((_b = store[11]) == null ? void 0 : _b[0])
+    lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]);
+  if ((_c = store[17]) == null ? void 0 : _c[0])
+    lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]);
+  if ((_d = store[22]) == null ? void 0 : _d[0])
+    lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
   var tile = parse_shallow(store[3][0].data);
   var _R = 0;
   tile[1].forEach(function(t) {
@@ -729,7 +888,7 @@ function parse_TST_TableModelArchive(M, root, ws) {
     var _tile = parse_TST_Tile(M, ref2);
     _tile.data.forEach(function(row, R) {
       row.forEach(function(buf, C) {
-        var res = parse_cell_storage(buf, sst, rsst);
+        var res = parse_cell_storage(buf, lut);
         if (res) {
           if (dense) {
             if (!ws[_R + R])
@@ -744,12 +903,12 @@ function parse_TST_TableModelArchive(M, root, ws) {
     });
     _R += _tile.nrows;
   });
-  if ((_b = store[13]) == null ? void 0 : _b[0]) {
+  if ((_e = store[13]) == null ? void 0 : _e[0]) {
     var ref = M[parse_TSP_Reference(store[13][0].data)][0];
     var mtype = varint_to_i32(ref.meta[1][0].data);
     if (mtype != 6144)
       throw new Error("Expected merge type 6144, found ".concat(mtype));
-    ws["!merges"] = (_c = parse_shallow(ref.data)) == null ? void 0 : _c[1].map(function(pi) {
+    ws["!merges"] = (_f = parse_shallow(ref.data)) == null ? void 0 : _f[1].map(function(pi) {
       var merge = parse_shallow(pi.data);
       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);
       return {
diff --git a/modules/83_numbers.ts b/modules/83_numbers.ts
index 5dcfc34..c5ca1b0 100644
--- a/modules/83_numbers.ts
+++ b/modules/83_numbers.ts
@@ -356,75 +356,174 @@ function compress_iwa_file(buf: Uint8Array): Uint8Array {
 }
 //<<export { decompress_iwa_file, compress_iwa_file };
 
-/** Parse "old storage" (version 0..3) */
-function parse_old_storage(buf: Uint8Array, sst: string[], rsst: string[], v: 0|1|2|3): CellObject | void {
+/** .TST.DataStore */
+interface DataLUT {
+	/** shared string table */
+	sst: string[];
+	/** rich string table table */
+	rsst: string[];
+	/** old format table */
+	ofmt: ProtoMessage[];
+	/** new format table */
+	nfmt: ProtoMessage[];
+}
+var numbers_lut_new = (): DataLUT => ({ sst: [], rsst: [], ofmt: [], nfmt: [] });
+
+function numbers_format_cell(cell: CellObject, t: number, flags: number, ofmt: ProtoMessage, nfmt: ProtoMessage): void {
+	var ctype = t & 0xFF, ver = t >> 8;
+	var fmt = ver >= 5 ? nfmt : ofmt;
+	dur: if((flags & (ver > 4 ? 8: 4)) && cell.t == "n" && ctype == 7) {
+		var dstyle =   (fmt[7]?.[0])  ? parse_varint49(fmt[7][0].data)  : -1;
+		if(dstyle == -1) break dur;
+		var dmin =     (fmt[15]?.[0]) ? parse_varint49(fmt[15][0].data) : -1;
+		var dmax =     (fmt[16]?.[0]) ? parse_varint49(fmt[16][0].data) : -1;
+		var auto =     (fmt[40]?.[0]) ? parse_varint49(fmt[40][0].data) : -1;
+		var d: number = cell.v as number, dd = d;
+		autodur: if(auto) { // TODO: check if numbers reformats on load
+			if(d == 0) { dmin = dmax = 2; break autodur; }
+			if(d >= 604800) dmin = 1;
+			else if(d >= 86400) dmin = 2;
+			else if(d >= 3600) dmin = 4;
+			else if(d >= 60) dmin = 8;
+			else if(d >= 1) dmin = 16;
+			else dmin = 32;
+			if(Math.floor(d) != d) dmax = 32;
+			else if(d % 60) dmax = 16;
+			else if(d % 3600) dmax = 8;
+			else if(d % 86400) dmax = 4;
+			else if(d % 604800) dmax = 2;
+			if(dmax < dmin) dmax = dmin;
+		}
+		if(dmin == -1 || dmax == -1) break dur;
+		var dstr: string[] = [], zstr: string[] = [];
+		/* TODO: plurality, SSF equivalents */
+		if(dmin == 1) {
+			dd = d / 604800;
+			if(dmax == 1) { zstr.push('d"d"'); } else { dd |= 0; d -= 604800 * dd; }
+			dstr.push(dd + (dstyle == 2 ? " week" + (dd == 1 ? "" : "s") : dstyle == 1 ? "w": ""));
+		}
+		if(dmin <= 2 && dmax >= 2) {
+			dd = d / 86400;
+			if(dmax > 2) { dd |= 0; d -= 86400 * dd; }
+			zstr.push("d" + '"d"');
+			dstr.push(dd + (dstyle == 2 ? " day" + (dd == 1 ? "" : "s") : dstyle == 1 ? "d" : ""));
+		}
+		if(dmin <= 4 && dmax >= 4) {
+			dd = d / 3600;
+			if(dmax > 4) { dd |= 0; d -= 3600 * dd; }
+			zstr.push((dmin >= 4 ? "[h]" : "h") + '"h"');
+			dstr.push(dd + (dstyle == 2 ? " hour" + (dd == 1 ? "" : "s") : dstyle == 1 ? "h" : ""));
+		}
+		if(dmin <= 8 && dmax >= 8) {
+			dd = d / 60;
+			if(dmax > 8) { dd |= 0; d -= 60 * dd; }
+			zstr.push((dmin >= 8 ? "[m]" : "m") + '"m"');
+			if(dstyle == 0) dstr.push(((dmin == 8 && dmax == 8 || dd >= 10) ? "" : "0") + dd)
+			else dstr.push(dd + (dstyle == 2 ? " minute" + (dd == 1 ? "" : "s") : dstyle == 1 ? "m" : ""));
+		}
+		if(dmin <= 16 && dmax >= 16) {
+			dd = d;
+			if(dmax > 16) { dd |= 0; d -= dd; }
+			zstr.push((dmin >= 16 ? "[s]" : "s") + '"s"');
+			if(dstyle == 0) dstr.push((dmax == 16 && dmin == 16 || dd >= 10 ? "" : "0") + dd)
+			else dstr.push(dd + (dstyle == 2 ? " second" + (dd == 1 ? "" : "s") : dstyle == 1 ? "s" : ""));
+		}
+		if(dmax >= 32) {
+			dd = Math.round(1000 * d);
+			if(dmin < 32) zstr.push(".000" + '"ms"');
+			if(dstyle == 0) dstr.push((dd >= 100 ? "" : dd >= 10 ? "0" : "00") + dd)
+			else dstr.push(dd + (dstyle == 2 ? " millisecond" + (dd == 1 ? "" : "s") : dstyle == 1 ? "ms" : ""));
+		}
+		cell.w = dstr.join(dstyle == 0 ? ":" : " "); cell.z = zstr.join(dstyle == 0 ? '":"': " ");
+		if(dstyle == 0) cell.w = cell.w.replace(/:(\d\d\d)$/, ".$1");
+	}
+}
+
+/** Parse "old storage" (version 0..4) */
+function parse_old_storage(buf: Uint8Array, lut: DataLUT, v: 0|1|2|3|4): CellObject | void {
 	var dv = u8_to_dataview(buf);
 	var flags = dv.getUint32(4, true);
 
-	/* TODO: find the correct field position of number formats, formulae, etc */
-	var data_offset = (v > 1 ? 12 : 8) + popcnt(flags & (v > 1 ? 0x0D8E : 0x018E)) * 4;
+	var ridx = -1, sidx = -1, zidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
+	var doff = (v > 1 ? 12 : 8);
+	if(flags & 0x0002) { zidx = dv.getUint32(doff,  true); doff += 4;}
+	doff += popcnt(flags & (v > 1 ? 0x0D8C : 0x018C)) * 4;
 
-	var ridx = -1, sidx = -1, ieee = NaN, dt = new Date(2001, 0, 1);
-	if(flags & 0x0200) { ridx = dv.getUint32(data_offset,  true); data_offset += 4; }
-	data_offset += popcnt(flags & (v > 1 ? 0x3000 : 0x1000)) * 4;
-	if(flags & 0x0010) { sidx = dv.getUint32(data_offset,  true); data_offset += 4; }
-	if(flags & 0x0020) { ieee = dv.getFloat64(data_offset, true); data_offset += 8; }
-	if(flags & 0x0040) { dt.setTime(dt.getTime() +  dv.getFloat64(data_offset, true) * 1000); data_offset += 8; }
+	if(flags & 0x0200) { ridx = dv.getUint32(doff,  true); doff += 4; }
+	doff += popcnt(flags & (v > 1 ? 0x3000 : 0x1000)) * 4;
+	if(flags & 0x0010) { sidx = dv.getUint32(doff,  true); doff += 4; }
+	if(flags & 0x0020) { ieee = dv.getFloat64(doff, true); doff += 8; }
+	if(flags & 0x0040) { dt.setTime(dt.getTime() +  dv.getFloat64(doff, true) * 1000); doff += 8; }
+
+	if(v > 1) {
+		flags = dv.getUint32(8, true) >>> 16;
+		/* TODO: stress test if a cell can have multiple sub-type formats */
+		if(flags & 0xFF) { if(zidx == -1) zidx = dv.getUint32(doff, true); doff += 4; }
+	}
 
 	var ret: CellObject;
-	switch(buf[2]) {
+	var t = buf[v >= 4 ? 1 : 2];
+	switch(t) {
 		case 0: return void 0; // return { t: "z" }; // blank?
 		case 2: ret = { t: "n", v: ieee }; break; // number
-		case 3: ret = { t: "s", v: sst[sidx] }; break; // string
+		case 3: ret = { t: "s", v: lut.sst[sidx] }; break; // string
 		case 5: ret = { t: "d", v: dt }; break; // date-time
 		case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean
-		case 7: ret = { t: "n", v: ieee / 86400 }; break; // duration in seconds TODO: emit [hh]:[mm] style format with adjusted value
+		case 7: ret = { t: "n", v: ieee }; break; // duration in seconds
 		case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents
 		case 9: { // "rich text"
-			if(ridx > -1) ret = { t: "s", v: rsst[ridx] };
+			if(ridx > -1) ret = { t: "s", v: lut.rsst[ridx] };
 			else throw new Error(`Unsupported cell type ${buf[subarray](0,4)}`);
 		} break;
 		default: throw new Error(`Unsupported cell type ${buf[subarray](0,4)}`);
 	}
-	/* TODO: Some fields appear after the cell data */
 
+	if(zidx > -1) numbers_format_cell(ret, t | (v<<8), flags, lut.ofmt[zidx], lut.nfmt[zidx]);
+	if(t == 7) (ret.v as number) /= 86400;
 	return ret;
 }
 
 /** Parse "new storage" (version 5) */
-function parse_new_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject | void {
+function parse_new_storage(buf: Uint8Array, lut: DataLUT): CellObject | void {
 	var dv = u8_to_dataview(buf);
 	var flags = dv.getUint32(8, true);
 
 	/* TODO: find the correct field position of number formats, formulae, etc */
-	var data_offset = 12;
+	var doff = 12;
 
-	var ridx = -1, sidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
+	var ridx = -1, sidx = -1, zidx = -1, d128 = NaN, ieee = NaN, dt = new Date(2001, 0, 1);
 
-	if(flags & 0x0001) { d128 = readDecimal128LE(buf, data_offset); data_offset += 16; }
-	if(flags & 0x0002) { ieee = dv.getFloat64(data_offset, true); data_offset += 8; }
-	if(flags & 0x0004) { dt.setTime(dt.getTime() +  dv.getFloat64(data_offset, true) * 1000); data_offset += 8; }
-	if(flags & 0x0008) { sidx = dv.getUint32(data_offset,  true); data_offset += 4; }
-	if(flags & 0x0010) { ridx = dv.getUint32(data_offset,  true); data_offset += 4; }
+	if(flags & 0x0001) { d128 = readDecimal128LE(buf, doff); doff += 16; }
+	if(flags & 0x0002) { ieee = dv.getFloat64(doff, true); doff += 8; }
+	if(flags & 0x0004) { dt.setTime(dt.getTime() +  dv.getFloat64(doff, true) * 1000); doff += 8; }
+	if(flags & 0x0008) { sidx = dv.getUint32(doff,  true); doff += 4; }
+	if(flags & 0x0010) { ridx = dv.getUint32(doff,  true); doff += 4; }
+
+	doff += popcnt(flags & 0x1FE0) * 4;
+
+	/* TODO: stress test if a cell can have multiple sub-type formats */
+	if(flags & 0x7E000) { if(zidx == -1) zidx = dv.getUint32(doff, true); doff += 4; }
 
 	var ret: CellObject;
-	switch(buf[1]) {
+	var t = buf[1];
+	switch(t) {
 		case 0: return void 0; // return { t: "z" }; // blank?
 		case 2: ret = { t: "n", v: d128 }; break; // number
-		case 3: ret = { t: "s", v: sst[sidx] }; break; // string
+		case 3: ret = { t: "s", v: lut.sst[sidx] }; break; // string
 		case 5: ret = { t: "d", v: dt }; break; // date-time
 		case 6: ret = { t: "b", v: ieee > 0 }; break; // boolean
-		case 7: ret = { t: "n", v: ieee / 86400 }; break;  // duration in seconds TODO: emit [hh]:[mm] style format with adjusted value
+		case 7: ret = { t: "n", v: ieee }; break;  // duration in seconds TODO: emit [hh]:[mm] style format with adjusted value
 		case 8: ret = { t: "e", v: 0}; break; // "formula error" TODO: enumerate and map errors to csf equivalents
 		case 9: { // "rich text"
-			if(ridx > -1) ret = { t: "s", v: rsst[ridx] };
+			if(ridx > -1) ret = { t: "s", v: lut.rsst[ridx] };
 			else throw new Error(`Unsupported cell type ${buf[1]} : ${flags & 0x1F} : ${buf[subarray](0,4)}`);
 		} break;
 		case 10: ret = { t: "n", v: d128 }; break; // currency
 		default: throw new Error(`Unsupported cell type ${buf[1]} : ${flags & 0x1F} : ${buf[subarray](0,4)}`);
 	}
-	/* TODO: All styling fields appear after the cell data */
 
+	if(zidx > -1) numbers_format_cell(ret, t | (5<<8), flags >> 13, lut.ofmt[zidx], lut.nfmt[zidx] );
+	if(t == 7) (ret.v as number) /= 86400;
 	return ret;
 }
 
@@ -459,11 +558,11 @@ function write_old_storage(cell: CellObject, sst: string[]): Uint8Array {
 	return out[subarray](0, l);
 }
 //<<export { write_new_storage, write_old_storage };
-function parse_cell_storage(buf: Uint8Array, sst: string[], rsst: string[]): CellObject | void {
+function parse_cell_storage(buf: Uint8Array, lut: DataLUT): CellObject | void {
 	switch(buf[0]) {
 		case 0: case 1:
-		case 2: case 3: return parse_old_storage(buf, sst, rsst, buf[0]);
-		case 5: return parse_new_storage(buf, sst, rsst);
+		case 2: case 3: case 4: return parse_old_storage(buf, lut, buf[0]);
+		case 5: return parse_new_storage(buf, lut);
 		default: throw new Error(`Unsupported payload version ${buf[0]}`);
 	}
 }
@@ -490,13 +589,13 @@ function write_TSP_Reference(idx: number): Uint8Array {
 type MessageSpace = {[id: number]: IWAMessage[]};
 
 /** Parse .TST.TableDataList */
-function parse_TST_TableDataList(M: MessageSpace, root: IWAMessage): string[] {
+function parse_TST_TableDataList(M: MessageSpace, root: IWAMessage): any[] {
 	var pb = parse_shallow(root.data);
 	// .TST.TableDataList.ListType
 	var type = varint_to_i32(pb[1][0].data);
 
 	var entries = pb[3];
-	var data: Array<string> = [];
+	var data: any[] = [];
 	(entries||[]).forEach(entry => {
 		// .TST.TableDataList.ListEntry
 		var le = parse_shallow(entry.data);
@@ -516,6 +615,8 @@ function parse_TST_TableDataList(M: MessageSpace, root: IWAMessage): string[] {
 
 				data[key] = tswpsa[3].map(x => u8str(x.data)).join("");
 			} break;
+			case 2: data[key] = parse_shallow(le[6][0].data); break;
+			default: throw type;
 		}
 	});
 	return data;
@@ -595,8 +696,11 @@ function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: Work
 	var dense = Array.isArray(ws);
 	// .TST.DataStore
 	var store = parse_shallow(pb[4][0].data);
-	var sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
-	var rsst: string[] = store[17]?.[0] ? parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]) : [];
+	var lut: DataLUT = numbers_lut_new();
+	if(store[4]?.[0]) lut.sst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[4][0].data)][0]);
+	if(store[11]?.[0]) lut.ofmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[11][0].data)][0]);
+	if(store[17]?.[0]) lut.rsst = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[17][0].data)][0]);
+	if(store[22]?.[0]) lut.nfmt = parse_TST_TableDataList(M, M[parse_TSP_Reference(store[22][0].data)][0]);
 
 	// .TST.TileStorage
 	var tile = parse_shallow(store[3][0].data);
@@ -611,7 +715,7 @@ function parse_TST_TableModelArchive(M: MessageSpace, root: IWAMessage, ws: Work
 		var _tile = parse_TST_Tile(M, ref);
 		_tile.data.forEach((row, R) => {
 			row.forEach((buf, C) => {
-				var res = parse_cell_storage(buf, sst, rsst);
+				var res = parse_cell_storage(buf, lut);
 				if(res) {
 					if(dense) {
 						if(!ws[_R + R]) ws[_R + R] = [];
diff --git a/test_files b/test_files
index f91c73f..787cc72 160000
--- a/test_files
+++ b/test_files
@@ -1 +1 @@
-Subproject commit f91c73f99ccb7919b7992e720f9ba7a730071770
+Subproject commit 787cc72932acf77ac58018d60d934b65847b16a3