xlvane 1.0.0 → 1.1.0

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.
@@ -5830,6 +5830,7 @@ function parseWorkbookPart(xml, ctx) {
5830
5830
  location: { part: ctx.part },
5831
5831
  hint: "Every workbook must list its sheets. Re-save the file in a spreadsheet application."
5832
5832
  });
5833
+ const seenIds = /* @__PURE__ */ new Set();
5833
5834
  const sheets = childrenNamed(sheetsElement, ns, "sheet").map((el) => {
5834
5835
  const name = decodeXstring(el.attrs.get("name") ?? "");
5835
5836
  const rawState = el.attrs.get("state") ?? "visible";
@@ -5842,9 +5843,22 @@ function parseWorkbookPart(xml, ctx) {
5842
5843
  state = "visible";
5843
5844
  }
5844
5845
  const rawId = el.attrs.get("sheetId");
5846
+ let sheetId = rawId !== void 0 && /^\d{1,10}$/.test(rawId.trim()) ? Number(rawId.trim()) : null;
5847
+ if (sheetId !== null && sheetId > 4294967295) sheetId = null;
5848
+ if (sheetId === null) ctx.warnings.add("XLV_W_INVALID_VALUE", rawId === void 0 ? `Sheet "${name}" has no sheetId.` : `Sheet "${name}" has the invalid sheetId "${rawId.slice(0, 20)}".`, {
5849
+ part: ctx.part,
5850
+ sheet: name
5851
+ });
5852
+ else if (seenIds.has(sheetId)) {
5853
+ ctx.warnings.add("XLV_W_INVALID_VALUE", `Sheet "${name}" repeats the sheetId ${String(sheetId)} of an earlier sheet; its sheetId is read as null.`, {
5854
+ part: ctx.part,
5855
+ sheet: name
5856
+ });
5857
+ sheetId = null;
5858
+ } else seenIds.add(sheetId);
5845
5859
  return {
5846
5860
  name,
5847
- sheetId: rawId !== void 0 && /^\d{1,10}$/.test(rawId) ? Number(rawId) : null,
5861
+ sheetId,
5848
5862
  state,
5849
5863
  relId: el.attrs.get(relIdKey) ?? null
5850
5864
  };
@@ -6598,6 +6612,7 @@ function sheetHead(sheet, selected, dimension, xfOf) {
6598
6612
  xml += "><pane";
6599
6613
  if (split.x > 0) xml += attr("xSplit", split.x * 20);
6600
6614
  if (split.y > 0) xml += attr("ySplit", split.y * 20);
6615
+ if (split.topLeftCell !== void 0) xml += attr("topLeftCell", split.topLeftCell);
6601
6616
  xml += `${attr("activePane", pane)} state="split"/>`;
6602
6617
  const active = sheet.view?.activeCell;
6603
6618
  xml += active ? `<selection${attr("pane", pane)}${attr("activeCell", active)}${attr("sqref", active)}/></sheetView>` : "</sheetView>";
@@ -7156,6 +7171,21 @@ function nameTitles(definedNames) {
7156
7171
  return n.sheet === null ? name : `${quoteSheetName(n.sheet)}!${name}`;
7157
7172
  });
7158
7173
  }
7174
+ /**
7175
+ * The sheet ids to write: the given ones, and the lowest unused ids for the other sheets in sheet
7176
+ * order, so that sheets without given ids get 1, 2, 3, … (unique, as E-09 requires; D-F03).
7177
+ */
7178
+ function sheetIds(sheets) {
7179
+ const used = /* @__PURE__ */ new Set();
7180
+ for (const s of sheets) if (typeof s.sheetId === "number") used.add(s.sheetId);
7181
+ let next = 1;
7182
+ return sheets.map((s) => {
7183
+ if (typeof s.sheetId === "number") return s.sheetId;
7184
+ while (used.has(next)) next++;
7185
+ used.add(next);
7186
+ return next;
7187
+ });
7188
+ }
7159
7189
  /** The workbook part: date system, book view, sheets, and the autofilter and user defined names. */
7160
7190
  function workbookXml(sheets, dateSystem, definedNames = [], protection = null, extras = {}) {
7161
7191
  const active = sheets.findIndex((s) => s.state === "visible");
@@ -7180,8 +7210,9 @@ function workbookXml(sheets, dateSystem, definedNames = [], protection = null, e
7180
7210
  workbook += "</bookViews>";
7181
7211
  }
7182
7212
  workbook += "<sheets>";
7213
+ const ids = sheetIds(sheets);
7183
7214
  sheets.forEach((sheet, i) => {
7184
- workbook += `<sheet${attr("name", encodeXstring(sheet.name))}${attr("sheetId", i + 1)}`;
7215
+ workbook += `<sheet${attr("name", encodeXstring(sheet.name))}${attr("sheetId", ids[i] ?? i + 1)}`;
7185
7216
  if (sheet.state !== "visible") workbook += attr("state", sheet.state);
7186
7217
  workbook += `${attr("r:id", `rId${String(i + 1)}`)}/>`;
7187
7218
  });
@@ -7838,6 +7869,8 @@ const X14_NS = "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main";
7838
7869
  const XM_NS = "http://schemas.microsoft.com/office/excel/2006/main";
7839
7870
  /** `ext@uri` of the worksheet extension with `x14:conditionalFormattings` ([MS-XLSX] §2.2.4.12). */
7840
7871
  const X14_CF_URI = "{78C0D931-6437-407D-A8EE-F0AAD7539E65}";
7872
+ /** `ext@uri` of the worksheet extension with `x14:dataValidations` (§2.2.4.12). */
7873
+ const X14_DV_URI = "{CCE6A557-97BC-4B89-ADB6-D9C93CAAB3DF}";
7841
7874
  /** `ext@uri` of the cfRule extension with `x14:id` (§2.2.4.12). */
7842
7875
  const X14_ID_URI = "{B025F937-C7B1-47D3-B67F-A62EFF666E3E}";
7843
7876
  const parseBool = (raw, dflt) => {
@@ -9694,9 +9727,14 @@ function parseSplit(attrs, warn) {
9694
9727
  const x = position("xSplit");
9695
9728
  const y = position("ySplit");
9696
9729
  if (x === null || y === null || x === 0 && y === 0) return null;
9697
- return Object.freeze({
9730
+ const topLeft = parseCellRef((attrs.get("topLeftCell") ?? "").trim());
9731
+ return Object.freeze(topLeft === null ? {
9698
9732
  x,
9699
9733
  y
9734
+ } : {
9735
+ x,
9736
+ y,
9737
+ topLeftCell: formatCellRef(topLeft.row, topLeft.col)
9700
9738
  });
9701
9739
  }
9702
9740
  /**
@@ -10270,6 +10308,7 @@ var ReadSheet = class {
10270
10308
  state;
10271
10309
  part;
10272
10310
  data;
10311
+ sheetId;
10273
10312
  hyperlinks;
10274
10313
  notes;
10275
10314
  names;
@@ -10279,13 +10318,14 @@ var ReadSheet = class {
10279
10318
  backgroundImage = null;
10280
10319
  /** Tables of the sheet (TD-01). */
10281
10320
  tables = [];
10282
- constructor(name, index, kind, state, part, data, hyperlinks = [], notes = [], names = []) {
10321
+ constructor(name, index, kind, state, part, data, sheetId, hyperlinks = [], notes = [], names = []) {
10283
10322
  this.name = name;
10284
10323
  this.index = index;
10285
10324
  this.kind = kind;
10286
10325
  this.state = state;
10287
10326
  this.part = part;
10288
10327
  this.data = data;
10328
+ this.sheetId = sheetId;
10289
10329
  this.hyperlinks = hyperlinks;
10290
10330
  this.notes = notes;
10291
10331
  this.names = names;
@@ -10483,7 +10523,7 @@ function readWorkbook(data, options) {
10483
10523
  const links = data === null || entry.part === null ? [] : resolveHyperlinks(pkg, entry.part, entry.name, data, warnings);
10484
10524
  const notes = data === null || entry.part === null ? [] : readNotes(pkg, entry.part, entry.name, limits, warnings);
10485
10525
  if (data !== null) attachNotes(data.rows, notes);
10486
- const sheet = new ReadSheet(entry.name, entry.index, entry.kind, entry.state, entry.part, data, links, notes, book.definedNames);
10526
+ const sheet = new ReadSheet(entry.name, entry.index, entry.kind, entry.state, entry.part, data, entry.sheetId, links, notes, book.definedNames);
10487
10527
  if (data !== null && entry.part !== null) sheet.tables = readTables(pkg, entry.part, entry.name, limits, warnings);
10488
10528
  if (data !== null && entry.part !== null) {
10489
10529
  const drawing = readSheetDrawing(pkg, entry.part, entry.name, {
@@ -10747,6 +10787,7 @@ function analyzeWorkbook(pkg, limits, warnings) {
10747
10787
  return {
10748
10788
  name: entry.name,
10749
10789
  index,
10790
+ sheetId: entry.sheetId,
10750
10791
  kind,
10751
10792
  state: entry.state,
10752
10793
  part: null
@@ -10755,6 +10796,7 @@ function analyzeWorkbook(pkg, limits, warnings) {
10755
10796
  return {
10756
10797
  name: entry.name,
10757
10798
  index,
10799
+ sheetId: entry.sheetId,
10758
10800
  kind,
10759
10801
  state: entry.state,
10760
10802
  part: rel.target
@@ -11012,6 +11054,7 @@ function inspectSheet(sheet, options, warnings) {
11012
11054
  const base = {
11013
11055
  name: sheet.name,
11014
11056
  index: sheet.index,
11057
+ sheetId: sheet.sheetId,
11015
11058
  kind: sheet.kind,
11016
11059
  state: sheet.state,
11017
11060
  dimension: sheet.dimension,
@@ -11242,6 +11285,8 @@ function readOutline(o, current, what) {
11242
11285
  }
11243
11286
  /** Largest split position accepted, in points: an implementation bound, not a documented limit. */
11244
11287
  const MAX_SPLIT_POINTS = 1e6;
11288
+ /** Office uses sheet ids from 1 to 65534 ([MS-OI29500] §2.1.578; W2-20). */
11289
+ const MAX_SHEET_ID = 65534;
11245
11290
  /** Most characters a cell can contain (Excel specifications and limits, W-04). */
11246
11291
  const MAX_CELL_TEXT = 32767;
11247
11292
  /** Widest column, in characters (Excel specifications and limits, W-04). */
@@ -11364,6 +11409,8 @@ var NewSheet = class {
11364
11409
  book;
11365
11410
  /** Visibility of the sheet. */
11366
11411
  state;
11412
+ /** The id given to {@link NewWorkbook.addSheet}, or `null` when the lowest unused id is taken when writing. */
11413
+ sheetId;
11367
11414
  /** @internal */
11368
11415
  cellMap = /* @__PURE__ */ new Map();
11369
11416
  /** @internal */
@@ -11408,10 +11455,11 @@ var NewSheet = class {
11408
11455
  tableList = [];
11409
11456
  count = 0;
11410
11457
  /** @internal Use {@link NewWorkbook.addSheet}. */
11411
- constructor(name, state, book) {
11458
+ constructor(name, state, book, sheetId = null) {
11412
11459
  this.name = name;
11413
11460
  this.book = book;
11414
11461
  this.state = state;
11462
+ this.sheetId = sheetId;
11415
11463
  }
11416
11464
  /** Number of cells that have a value or a style. */
11417
11465
  get cellCount() {
@@ -11819,7 +11867,11 @@ var NewSheet = class {
11819
11867
  const split = o.get("split");
11820
11868
  if (split === null) next.split = null;
11821
11869
  else {
11822
- const p = readOptions$1(split, ["x", "y"], "view option \"split\"");
11870
+ const p = readOptions$1(split, [
11871
+ "x",
11872
+ "y",
11873
+ "topLeftCell"
11874
+ ], "view option \"split\"");
11823
11875
  const at = (key) => {
11824
11876
  const v = p.get(key) ?? 0;
11825
11877
  if (typeof v !== "number" || !Number.isFinite(v) || v < 0 || v > MAX_SPLIT_POINTS) throw invalidOption(`The split position "${key}" must be a number of points from 0 to ${String(MAX_SPLIT_POINTS)}.`, "For example { split: { x: 100, y: 50 } }.");
@@ -11828,10 +11880,20 @@ var NewSheet = class {
11828
11880
  const x = at("x");
11829
11881
  const y = at("y");
11830
11882
  if (x === 0 && y === 0) throw invalidOption("A split needs \"x\" or \"y\" greater than 0.", "For example { split: { y: 50 } }, or { split: null } to remove it.");
11831
- next.split = {
11883
+ const corner = p.get("topLeftCell");
11884
+ if (corner === void 0 || corner === null) next.split = {
11832
11885
  x,
11833
11886
  y
11834
11887
  };
11888
+ else {
11889
+ const cell = typeof corner === "string" ? parseCellRef(corner.toUpperCase()) : null;
11890
+ if (cell === null) throw invalidOption("The split option \"topLeftCell\" must be a cell reference such as \"F20\".", "For example { split: { x: 100, y: 50, topLeftCell: \"F20\" } }: the first column shown right of the vertical bar and the first row below the horizontal bar.");
11891
+ next.split = {
11892
+ x,
11893
+ y,
11894
+ topLeftCell: formatCellRef(cell.row, cell.col)
11895
+ };
11896
+ }
11835
11897
  unfreeze = true;
11836
11898
  }
11837
11899
  }
@@ -12218,6 +12280,7 @@ var NewSheet = class {
12218
12280
  return {
12219
12281
  name: this.name,
12220
12282
  state: this.state,
12283
+ sheetId: this.sheetId,
12221
12284
  cells: this.cellMap,
12222
12285
  columns: this.columnMap,
12223
12286
  rows: this.rowMap,
@@ -12690,11 +12753,12 @@ var NewWorkbook = class {
12690
12753
  *
12691
12754
  * const workbook = createWorkbook();
12692
12755
  * workbook.addSheet('Data');
12693
- * workbook.addSheet('Lookup', { state: 'hidden' });
12756
+ * workbook.addSheet('Lookup', { state: 'hidden', sheetId: 5 });
12694
12757
  * ```
12695
12758
  */
12696
12759
  addSheet(name, options) {
12697
- const state = readOptions$1(options, ["state"], "sheet options").get("state") ?? "visible";
12760
+ const o = readOptions$1(options, ["state", "sheetId"], "sheet options");
12761
+ const state = o.get("state") ?? "visible";
12698
12762
  if (state !== "visible" && state !== "hidden" && state !== "veryHidden") throw invalidOption(`Sheet state ${JSON.stringify(String(state).slice(0, 40))} is not valid.`, "Use \"visible\", \"hidden\" or \"veryHidden\".");
12699
12763
  const checked = checkSheetName(name);
12700
12764
  const lower = checked.toLowerCase();
@@ -12706,7 +12770,18 @@ var NewWorkbook = class {
12706
12770
  existing: existing.name
12707
12771
  }
12708
12772
  });
12709
- const sheet = new NewSheet(checked, state, this);
12773
+ let sheetId = null;
12774
+ if (o.has("sheetId")) {
12775
+ const id = o.get("sheetId");
12776
+ if (typeof id !== "number" || !Number.isInteger(id) || id < 1 || id > MAX_SHEET_ID) throw invalidOption(`The sheet option "sheetId" must be a whole number from 1 to ${String(MAX_SHEET_ID)}.`, "For example { sheetId: 3 }, or leave it out to take the lowest unused id.", { name: checked });
12777
+ const owner = this.list.find((s) => s.sheetId === id);
12778
+ if (owner) throw invalidOption(`Sheet "${owner.name}" already has the sheetId ${String(id)}.`, "Sheet ids must be unique in the workbook. Give another id, or leave it out to take the lowest unused id.", {
12779
+ name: checked,
12780
+ existing: owner.name
12781
+ });
12782
+ sheetId = id;
12783
+ }
12784
+ const sheet = new NewSheet(checked, state, this, sheetId);
12710
12785
  this.list.push(sheet);
12711
12786
  return sheet;
12712
12787
  }
@@ -13001,4 +13076,4 @@ function openInput(input, limits, onWarning) {
13001
13076
  if (onWarning !== void 0) for (const warning of workbook.warnings) onWarning(warning);
13002
13077
  return workbook;
13003
13078
  }
13004
- export { nameTitles as $, MAX_COLUMNS as $t, limitExceeded as A, mergeStyles as At, tokenize as B, hashPassword as Bt, Bytes as C, isXlvError as Cn, normalizeTable as Ct, TAIL_BYTES as D, parseStyles as Dt, NotLoaded as E, EMPTY_STYLES as Et, validateLocalHeaders as F, resolveLimits as Ft, buildStyles as G, MediaParts as Gt, SheetRels as H, verifyPassword as Ht, WarningCollector as I, suggest as It, createSharedStrings as J, metricsOf as Jt, cellXml as K, drawingParts as Kt, sheetNotFound as L, printNames as Lt, openZip as M, stableKey as Mt, readCentralDirectory as N, isDateFormat as Nt, checkSource as O, READING_ORDERS as Ot, unsupported as P, DEFAULT_READ_LIMITS as Pt, hyperlinksXml as Q, relationshipTypes as Qt, createWorksheetParser as R, printXml as Rt, workbookPartsToLoad as S, XlvError as Sn, TABLE_CONTENT_TYPE as St, HEAD_BYTES as T, checkUniqueName as Tt, attr as U, DRAWING_CONTENT_TYPE as Ut, DEFAULT_FONT as V, legacyPasswordHash as Vt, borderXml as W, IMAGE_CONTENT_TYPES as Wt, fontXml as X, SML_NS as Xt, fillXml as Y, resolveImage as Yt, formatNumber as Z, classifyRelationship as Zt, isoDate as _, encodeXstring as _n, parseSharedStrings as _t, DATE_FORMAT as a, parseRange as an, sheetRelsPartName as at, readWorkbook as b, ERROR_CODES as bn, partKey as bt, NewSheet as c, appPropertiesXml as cn, stringItemXml as ct, convertCellInput as d, childrenNamed as dn, workbookRelsXml as dt, MAX_ROWS as en, noteParts as et, createWorkbook as f, parseXmlTree as fn, workbookXml as ft, inspect as g, parseXml as gn, parseIsoDateTime as gt, detectHeader as h, normalizeLineEnds as hn, crc32 as ht, readOptions as i, parseCellRef as in, sheetHead as it, locateCentralDirectory as j, normalizeStyle as jt, corrupt as k, checkStyleCount as kt, NewWorkbook as l, corePropertiesXml as ln, tableParts as lt, writeWorkbook as m, decodeXml as mn, writeZip as mt, oneOfOption as n, formatCellRef as nn, rootRelsXml as nt, DATE_TIME_FORMAT as o, APP_PROPERTIES_PART as on, sheetRulesXml as ot, sortedNotes as p, createXmlByteStreamParser as pn, FormulaGroups as pt, contentTypesXml as q, imageFormat as qt, openInput as r, formatRange as rn, rowStart as rt, ERROR_VALUES as s, CORE_PROPERTIES_PART as sn, sheetTail as st, booleanOption as t, columnLetters as tn, reusableBuiltinNumFmt as tt, checkBookViews as u, childNamed as un, textElement as ut, analyzeWorkbook as v, escapeAttr as vn, openPackage as vt, CORRUPT_HINT as w, checkDefinedName as wt, toBytes as x, WARNING_CODES as xn, zipNameToPartName as xt, readNotes as y, escapeText as yn, relationshipsPartName as yt, shiftFormula as z, sheetProtectionXml as zt };
13079
+ export { fillXml as $, resolveImage as $t, limitExceeded as A, EMPTY_STYLES as At, tokenize as B, suggest as Bt, Bytes as C, escapeText as Cn, relationshipsPartName as Ct, TAIL_BYTES as D, isXlvError as Dn, normalizeTable as Dt, NotLoaded as E, XlvError as En, TABLE_CONTENT_TYPE as Et, validateLocalHeaders as F, normalizeStyle as Ft, DEFAULT_FONT as G, legacyPasswordHash as Gt, X14_DV_URI as H, printXml as Ht, WarningCollector as I, stableKey as It, borderXml as J, IMAGE_CONTENT_TYPES as Jt, SheetRels as K, verifyPassword as Kt, sheetNotFound as L, isDateFormat as Lt, openZip as M, READING_ORDERS as Mt, readCentralDirectory as N, checkStyleCount as Nt, checkSource as O, checkDefinedName as Ot, unsupported as P, mergeStyles as Pt, createSharedStrings as Q, metricsOf as Qt, createWorksheetParser as R, DEFAULT_READ_LIMITS as Rt, workbookPartsToLoad as S, escapeAttr as Sn, openPackage as St, HEAD_BYTES as T, WARNING_CODES as Tn, zipNameToPartName as Tt, X14_NS as U, sheetProtectionXml as Ut, X14_CF_URI as V, printNames as Vt, XM_NS as W, hashPassword as Wt, cellXml as X, drawingParts as Xt, buildStyles as Y, MediaParts as Yt, contentTypesXml as Z, imageFormat as Zt, isoDate as _, createXmlByteStreamParser as _n, FormulaGroups as _t, DATE_FORMAT as a, columnLetters as an, reusableBuiltinNumFmt as at, readWorkbook as b, parseXml as bn, parseIsoDateTime as bt, NewSheet as c, parseCellRef as cn, sheetHead as ct, convertCellInput as d, CORE_PROPERTIES_PART as dn, sheetTail as dt, SML_NS as en, fontXml as et, createWorkbook as f, appPropertiesXml as fn, stringItemXml as ft, inspect as g, parseXmlTree as gn, workbookXml as gt, detectHeader as h, childrenNamed as hn, workbookRelsXml as ht, readOptions as i, MAX_ROWS as in, noteParts as it, locateCentralDirectory as j, parseStyles as jt, corrupt as k, checkUniqueName as kt, NewWorkbook as l, parseRange as ln, sheetRelsPartName as lt, writeWorkbook as m, childNamed as mn, textElement as mt, oneOfOption as n, relationshipTypes as nn, hyperlinksXml as nt, DATE_TIME_FORMAT as o, formatCellRef as on, rootRelsXml as ot, sortedNotes as p, corePropertiesXml as pn, tableParts as pt, attr as q, DRAWING_CONTENT_TYPE as qt, openInput as r, MAX_COLUMNS as rn, nameTitles as rt, ERROR_VALUES as s, formatRange as sn, rowStart as st, booleanOption as t, classifyRelationship as tn, formatNumber as tt, checkBookViews as u, APP_PROPERTIES_PART as un, sheetRulesXml as ut, analyzeWorkbook as v, decodeXml as vn, writeZip as vt, CORRUPT_HINT as w, ERROR_CODES as wn, partKey as wt, toBytes as x, encodeXstring as xn, parseSharedStrings as xt, readNotes as y, normalizeLineEnds as yn, crc32 as yt, shiftFormula as z, resolveLimits as zt };