@cj-tech-master/excelts 5.1.3 → 5.1.4

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.
@@ -224,8 +224,14 @@ export class WorkbookWriterBase {
224
224
  }
225
225
  addContentTypes() {
226
226
  return new Promise(resolve => {
227
+ const worksheets = this._worksheets.filter(Boolean);
228
+ // In the streaming path, ZIP entries use ws.id which is always sequential.
229
+ // Set fileIndex = id to satisfy the ContentTypesXform contract.
230
+ worksheets.forEach((ws) => {
231
+ ws.fileIndex = ws.id;
232
+ });
227
233
  const model = {
228
- worksheets: this._worksheets.filter(Boolean),
234
+ worksheets,
229
235
  sharedStrings: this.sharedStrings,
230
236
  commentRefs: this.commentRefs,
231
237
  media: this.media,
@@ -29,11 +29,9 @@ class ContentTypesXform extends BaseXform {
29
29
  PartName: toContentTypesPartName(OOXML_PATHS.xlWorkbook),
30
30
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
31
31
  });
32
- model.worksheets.forEach((worksheet, index) => {
33
- // Use fileIndex if set, otherwise use sequential index (1-based)
34
- const fileIndex = worksheet.fileIndex || index + 1;
32
+ model.worksheets.forEach((worksheet) => {
35
33
  xmlStream.leafNode("Override", {
36
- PartName: toContentTypesPartName(worksheetPath(fileIndex)),
34
+ PartName: toContentTypesPartName(worksheetPath(worksheet.fileIndex)),
37
35
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
38
36
  });
39
37
  });
@@ -167,25 +167,30 @@ class WorkSheetXform extends BaseXform {
167
167
  });
168
168
  });
169
169
  // prepare comment relationships
170
+ // Use fileIndex (sequential 1-based) for file naming instead of model.id
171
+ // (the workbook-level sheet ID) because model.id can have gaps when sheets
172
+ // have been deleted, causing a mismatch between the relationship targets
173
+ // and the actual ZIP entry paths written by addWorksheets().
174
+ const { fileIndex } = model;
170
175
  if (model.comments.length > 0) {
171
176
  const comment = {
172
177
  Id: nextRid(rels),
173
178
  Type: RelType.Comments,
174
- Target: commentsRelTargetFromWorksheet(model.id)
179
+ Target: commentsRelTargetFromWorksheet(fileIndex)
175
180
  };
176
181
  rels.push(comment);
177
182
  const vmlDrawing = {
178
183
  Id: nextRid(rels),
179
184
  Type: RelType.VmlDrawing,
180
- Target: vmlDrawingRelTargetFromWorksheet(model.id)
185
+ Target: vmlDrawingRelTargetFromWorksheet(fileIndex)
181
186
  };
182
187
  rels.push(vmlDrawing);
183
188
  model.comments.forEach(item => {
184
189
  item.refAddress = colCache.decodeAddress(item.ref);
185
190
  });
186
191
  options.commentRefs.push({
187
- commentName: `comments${model.id}`,
188
- vmlDrawing: `vmlDrawing${model.id}`
192
+ commentName: `comments${fileIndex}`,
193
+ vmlDrawing: `vmlDrawing${fileIndex}`
189
194
  });
190
195
  }
191
196
  // Handle pre-loaded drawing (from file read) that may contain charts or other non-image content.
@@ -338,7 +343,7 @@ class WorkSheetXform extends BaseXform {
338
343
  rels.push({
339
344
  Id: nextRid(rels),
340
345
  Type: RelType.VmlDrawing,
341
- Target: vmlDrawingRelTargetFromWorksheet(model.id)
346
+ Target: vmlDrawingRelTargetFromWorksheet(fileIndex)
342
347
  });
343
348
  }
344
349
  // Add hidden DrawingML shapes that bridge to the VML shape ids.
@@ -33,7 +33,7 @@ import { bufferToString, base64ToUint8Array } from "../../../utils/utils.browser
33
33
  import { StreamingZip, ZipDeflateFile } from "../../archive/zip/stream.js";
34
34
  import { ZipParser } from "../../archive/unzip/zip-parser.js";
35
35
  import { PassThrough, concatUint8Arrays } from "../../stream/index.browser.js";
36
- import { commentsPath, commentsRelTargetFromWorksheetName, ctrlPropPath, drawingPath, drawingRelsPath, OOXML_REL_TARGETS, pivotTableRelTargetFromWorksheetName, pivotCacheDefinitionRelTargetFromWorkbook, getCommentsIndexFromPath, getDrawingNameFromPath, getDrawingNameFromRelsPath, getMediaFilenameFromPath, mediaPath, getPivotCacheDefinitionNameFromPath, getPivotCacheDefinitionNameFromRelsPath, getPivotCacheRecordsNameFromPath, getPivotTableNameFromPath, getPivotTableNameFromRelsPath, pivotCacheDefinitionPath, pivotCacheDefinitionRelsPath, pivotCacheDefinitionRelTargetFromPivotTable, pivotCacheRecordsPath, pivotCacheRecordsRelTarget, pivotTablePath, pivotTableRelsPath, getTableNameFromPath, tablePath, tableRelTargetFromWorksheetName, themePath, getThemeNameFromPath, getVmlDrawingNameFromPath, getWorksheetNoFromWorksheetPath, getWorksheetNoFromWorksheetRelsPath, isBinaryEntryPath, normalizeZipPath, OOXML_PATHS, vmlDrawingRelTargetFromWorksheetName, vmlDrawingPath, worksheetPath, worksheetRelsPath } from "../utils/ooxml-paths.js";
36
+ import { commentsPath, commentsRelTargetFromWorksheetName, ctrlPropPath, drawingPath, drawingRelsPath, OOXML_REL_TARGETS, pivotTableRelTargetFromWorksheetName, pivotCacheDefinitionRelTargetFromWorkbook, getCommentsIndexFromPath, getDrawingNameFromPath, getDrawingNameFromRelsPath, getMediaFilenameFromPath, mediaPath, getPivotCacheDefinitionNameFromPath, getPivotCacheDefinitionNameFromRelsPath, getPivotCacheRecordsNameFromPath, getPivotTableNameFromPath, getPivotTableNameFromRelsPath, pivotCacheDefinitionPath, pivotCacheDefinitionRelsPath, pivotCacheDefinitionRelTargetFromPivotTable, pivotCacheRecordsPath, pivotCacheRecordsRelTarget, pivotTablePath, pivotTableRelsPath, getTableNameFromPath, tablePath, tableRelTargetFromWorksheetName, themePath, getThemeNameFromPath, getVmlDrawingNameFromPath, getWorksheetNoFromWorksheetPath, getWorksheetNoFromWorksheetRelsPath, isBinaryEntryPath, normalizeZipPath, OOXML_PATHS, vmlDrawingRelTargetFromWorksheetName, vmlDrawingPath, worksheetPath, worksheetRelsPath, worksheetRelTarget } from "../utils/ooxml-paths.js";
37
37
  import { PassthroughManager } from "../utils/passthrough-manager.js";
38
38
  class StreamingZipWriterAdapter {
39
39
  constructor(options) {
@@ -1050,13 +1050,13 @@ class XLSX {
1050
1050
  });
1051
1051
  }
1052
1052
  });
1053
- model.worksheets.forEach((worksheet, index) => {
1053
+ model.worksheets.forEach((worksheet) => {
1054
1054
  worksheet.rId = `rId${count++}`;
1055
- worksheet.fileIndex = index + 1;
1055
+ // fileIndex is assigned once in prepareModel() — use it directly
1056
1056
  relationships.push({
1057
1057
  Id: worksheet.rId,
1058
1058
  Type: XLSX.RelType.Worksheet,
1059
- Target: `worksheets/sheet${worksheet.fileIndex}.xml`
1059
+ Target: worksheetRelTarget(worksheet.fileIndex)
1060
1060
  });
1061
1061
  });
1062
1062
  const xform = new RelationshipsXform();
@@ -1091,8 +1091,8 @@ class XLSX {
1091
1091
  const commentsXform = new CommentsXform();
1092
1092
  const vmlDrawingXform = new VmlDrawingXform();
1093
1093
  const ctrlPropXform = new CtrlPropXform();
1094
- model.worksheets.forEach((worksheet, index) => {
1095
- const fileIndex = worksheet.fileIndex || index + 1;
1094
+ model.worksheets.forEach((worksheet) => {
1095
+ const { fileIndex } = worksheet;
1096
1096
  let xmlStream = new XmlStream();
1097
1097
  worksheetXform.render(xmlStream, worksheet);
1098
1098
  zip.append(xmlStream.xml, { name: worksheetPath(fileIndex) });
@@ -1299,7 +1299,12 @@ class XLSX {
1299
1299
  worksheetOptions.formControlRefs = model.formControlRefs = [];
1300
1300
  let tableCount = 0;
1301
1301
  model.tables = [];
1302
- model.worksheets.forEach((worksheet) => {
1302
+ model.worksheets.forEach((worksheet, index) => {
1303
+ // Assign fileIndex early so that worksheet-xform.prepare() can use it
1304
+ // for comment/VML relationship targets and content type names.
1305
+ // This ensures consistency with addWorksheets() which writes ZIP entries
1306
+ // using the same fileIndex.
1307
+ worksheet.fileIndex = index + 1;
1303
1308
  worksheet.tables.forEach((table) => {
1304
1309
  tableCount++;
1305
1310
  table.target = `table${tableCount}.xml`;
@@ -227,8 +227,14 @@ class WorkbookWriterBase {
227
227
  }
228
228
  addContentTypes() {
229
229
  return new Promise(resolve => {
230
+ const worksheets = this._worksheets.filter(Boolean);
231
+ // In the streaming path, ZIP entries use ws.id which is always sequential.
232
+ // Set fileIndex = id to satisfy the ContentTypesXform contract.
233
+ worksheets.forEach((ws) => {
234
+ ws.fileIndex = ws.id;
235
+ });
230
236
  const model = {
231
- worksheets: this._worksheets.filter(Boolean),
237
+ worksheets,
232
238
  sharedStrings: this.sharedStrings,
233
239
  commentRefs: this.commentRefs,
234
240
  media: this.media,
@@ -32,11 +32,9 @@ class ContentTypesXform extends base_xform_1.BaseXform {
32
32
  PartName: (0, ooxml_paths_1.toContentTypesPartName)(ooxml_paths_1.OOXML_PATHS.xlWorkbook),
33
33
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
34
34
  });
35
- model.worksheets.forEach((worksheet, index) => {
36
- // Use fileIndex if set, otherwise use sequential index (1-based)
37
- const fileIndex = worksheet.fileIndex || index + 1;
35
+ model.worksheets.forEach((worksheet) => {
38
36
  xmlStream.leafNode("Override", {
39
- PartName: (0, ooxml_paths_1.toContentTypesPartName)((0, ooxml_paths_1.worksheetPath)(fileIndex)),
37
+ PartName: (0, ooxml_paths_1.toContentTypesPartName)((0, ooxml_paths_1.worksheetPath)(worksheet.fileIndex)),
40
38
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
41
39
  });
42
40
  });
@@ -170,25 +170,30 @@ class WorkSheetXform extends base_xform_1.BaseXform {
170
170
  });
171
171
  });
172
172
  // prepare comment relationships
173
+ // Use fileIndex (sequential 1-based) for file naming instead of model.id
174
+ // (the workbook-level sheet ID) because model.id can have gaps when sheets
175
+ // have been deleted, causing a mismatch between the relationship targets
176
+ // and the actual ZIP entry paths written by addWorksheets().
177
+ const { fileIndex } = model;
173
178
  if (model.comments.length > 0) {
174
179
  const comment = {
175
180
  Id: nextRid(rels),
176
181
  Type: rel_type_1.RelType.Comments,
177
- Target: (0, ooxml_paths_1.commentsRelTargetFromWorksheet)(model.id)
182
+ Target: (0, ooxml_paths_1.commentsRelTargetFromWorksheet)(fileIndex)
178
183
  };
179
184
  rels.push(comment);
180
185
  const vmlDrawing = {
181
186
  Id: nextRid(rels),
182
187
  Type: rel_type_1.RelType.VmlDrawing,
183
- Target: (0, ooxml_paths_1.vmlDrawingRelTargetFromWorksheet)(model.id)
188
+ Target: (0, ooxml_paths_1.vmlDrawingRelTargetFromWorksheet)(fileIndex)
184
189
  };
185
190
  rels.push(vmlDrawing);
186
191
  model.comments.forEach(item => {
187
192
  item.refAddress = col_cache_1.colCache.decodeAddress(item.ref);
188
193
  });
189
194
  options.commentRefs.push({
190
- commentName: `comments${model.id}`,
191
- vmlDrawing: `vmlDrawing${model.id}`
195
+ commentName: `comments${fileIndex}`,
196
+ vmlDrawing: `vmlDrawing${fileIndex}`
192
197
  });
193
198
  }
194
199
  // Handle pre-loaded drawing (from file read) that may contain charts or other non-image content.
@@ -341,7 +346,7 @@ class WorkSheetXform extends base_xform_1.BaseXform {
341
346
  rels.push({
342
347
  Id: nextRid(rels),
343
348
  Type: rel_type_1.RelType.VmlDrawing,
344
- Target: (0, ooxml_paths_1.vmlDrawingRelTargetFromWorksheet)(model.id)
349
+ Target: (0, ooxml_paths_1.vmlDrawingRelTargetFromWorksheet)(fileIndex)
345
350
  });
346
351
  }
347
352
  // Add hidden DrawingML shapes that bridge to the VML shape ids.
@@ -1053,13 +1053,13 @@ class XLSX {
1053
1053
  });
1054
1054
  }
1055
1055
  });
1056
- model.worksheets.forEach((worksheet, index) => {
1056
+ model.worksheets.forEach((worksheet) => {
1057
1057
  worksheet.rId = `rId${count++}`;
1058
- worksheet.fileIndex = index + 1;
1058
+ // fileIndex is assigned once in prepareModel() — use it directly
1059
1059
  relationships.push({
1060
1060
  Id: worksheet.rId,
1061
1061
  Type: XLSX.RelType.Worksheet,
1062
- Target: `worksheets/sheet${worksheet.fileIndex}.xml`
1062
+ Target: (0, ooxml_paths_1.worksheetRelTarget)(worksheet.fileIndex)
1063
1063
  });
1064
1064
  });
1065
1065
  const xform = new relationships_xform_1.RelationshipsXform();
@@ -1094,8 +1094,8 @@ class XLSX {
1094
1094
  const commentsXform = new comments_xform_1.CommentsXform();
1095
1095
  const vmlDrawingXform = new vml_drawing_xform_1.VmlDrawingXform();
1096
1096
  const ctrlPropXform = new ctrl_prop_xform_1.CtrlPropXform();
1097
- model.worksheets.forEach((worksheet, index) => {
1098
- const fileIndex = worksheet.fileIndex || index + 1;
1097
+ model.worksheets.forEach((worksheet) => {
1098
+ const { fileIndex } = worksheet;
1099
1099
  let xmlStream = new xml_stream_1.XmlStream();
1100
1100
  worksheetXform.render(xmlStream, worksheet);
1101
1101
  zip.append(xmlStream.xml, { name: (0, ooxml_paths_1.worksheetPath)(fileIndex) });
@@ -1302,7 +1302,12 @@ class XLSX {
1302
1302
  worksheetOptions.formControlRefs = model.formControlRefs = [];
1303
1303
  let tableCount = 0;
1304
1304
  model.tables = [];
1305
- model.worksheets.forEach((worksheet) => {
1305
+ model.worksheets.forEach((worksheet, index) => {
1306
+ // Assign fileIndex early so that worksheet-xform.prepare() can use it
1307
+ // for comment/VML relationship targets and content type names.
1308
+ // This ensures consistency with addWorksheets() which writes ZIP entries
1309
+ // using the same fileIndex.
1310
+ worksheet.fileIndex = index + 1;
1306
1311
  worksheet.tables.forEach((table) => {
1307
1312
  tableCount++;
1308
1313
  table.target = `table${tableCount}.xml`;
@@ -224,8 +224,14 @@ export class WorkbookWriterBase {
224
224
  }
225
225
  addContentTypes() {
226
226
  return new Promise(resolve => {
227
+ const worksheets = this._worksheets.filter(Boolean);
228
+ // In the streaming path, ZIP entries use ws.id which is always sequential.
229
+ // Set fileIndex = id to satisfy the ContentTypesXform contract.
230
+ worksheets.forEach((ws) => {
231
+ ws.fileIndex = ws.id;
232
+ });
227
233
  const model = {
228
- worksheets: this._worksheets.filter(Boolean),
234
+ worksheets,
229
235
  sharedStrings: this.sharedStrings,
230
236
  commentRefs: this.commentRefs,
231
237
  media: this.media,
@@ -29,11 +29,9 @@ class ContentTypesXform extends BaseXform {
29
29
  PartName: toContentTypesPartName(OOXML_PATHS.xlWorkbook),
30
30
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
31
31
  });
32
- model.worksheets.forEach((worksheet, index) => {
33
- // Use fileIndex if set, otherwise use sequential index (1-based)
34
- const fileIndex = worksheet.fileIndex || index + 1;
32
+ model.worksheets.forEach((worksheet) => {
35
33
  xmlStream.leafNode("Override", {
36
- PartName: toContentTypesPartName(worksheetPath(fileIndex)),
34
+ PartName: toContentTypesPartName(worksheetPath(worksheet.fileIndex)),
37
35
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
38
36
  });
39
37
  });
@@ -167,25 +167,30 @@ class WorkSheetXform extends BaseXform {
167
167
  });
168
168
  });
169
169
  // prepare comment relationships
170
+ // Use fileIndex (sequential 1-based) for file naming instead of model.id
171
+ // (the workbook-level sheet ID) because model.id can have gaps when sheets
172
+ // have been deleted, causing a mismatch between the relationship targets
173
+ // and the actual ZIP entry paths written by addWorksheets().
174
+ const { fileIndex } = model;
170
175
  if (model.comments.length > 0) {
171
176
  const comment = {
172
177
  Id: nextRid(rels),
173
178
  Type: RelType.Comments,
174
- Target: commentsRelTargetFromWorksheet(model.id)
179
+ Target: commentsRelTargetFromWorksheet(fileIndex)
175
180
  };
176
181
  rels.push(comment);
177
182
  const vmlDrawing = {
178
183
  Id: nextRid(rels),
179
184
  Type: RelType.VmlDrawing,
180
- Target: vmlDrawingRelTargetFromWorksheet(model.id)
185
+ Target: vmlDrawingRelTargetFromWorksheet(fileIndex)
181
186
  };
182
187
  rels.push(vmlDrawing);
183
188
  model.comments.forEach(item => {
184
189
  item.refAddress = colCache.decodeAddress(item.ref);
185
190
  });
186
191
  options.commentRefs.push({
187
- commentName: `comments${model.id}`,
188
- vmlDrawing: `vmlDrawing${model.id}`
192
+ commentName: `comments${fileIndex}`,
193
+ vmlDrawing: `vmlDrawing${fileIndex}`
189
194
  });
190
195
  }
191
196
  // Handle pre-loaded drawing (from file read) that may contain charts or other non-image content.
@@ -338,7 +343,7 @@ class WorkSheetXform extends BaseXform {
338
343
  rels.push({
339
344
  Id: nextRid(rels),
340
345
  Type: RelType.VmlDrawing,
341
- Target: vmlDrawingRelTargetFromWorksheet(model.id)
346
+ Target: vmlDrawingRelTargetFromWorksheet(fileIndex)
342
347
  });
343
348
  }
344
349
  // Add hidden DrawingML shapes that bridge to the VML shape ids.
@@ -33,7 +33,7 @@ import { bufferToString, base64ToUint8Array } from "../../../utils/utils.js";
33
33
  import { StreamingZip, ZipDeflateFile } from "../../archive/zip/stream.js";
34
34
  import { ZipParser } from "../../archive/unzip/zip-parser.js";
35
35
  import { PassThrough, concatUint8Arrays } from "../../stream/index.js";
36
- import { commentsPath, commentsRelTargetFromWorksheetName, ctrlPropPath, drawingPath, drawingRelsPath, OOXML_REL_TARGETS, pivotTableRelTargetFromWorksheetName, pivotCacheDefinitionRelTargetFromWorkbook, getCommentsIndexFromPath, getDrawingNameFromPath, getDrawingNameFromRelsPath, getMediaFilenameFromPath, mediaPath, getPivotCacheDefinitionNameFromPath, getPivotCacheDefinitionNameFromRelsPath, getPivotCacheRecordsNameFromPath, getPivotTableNameFromPath, getPivotTableNameFromRelsPath, pivotCacheDefinitionPath, pivotCacheDefinitionRelsPath, pivotCacheDefinitionRelTargetFromPivotTable, pivotCacheRecordsPath, pivotCacheRecordsRelTarget, pivotTablePath, pivotTableRelsPath, getTableNameFromPath, tablePath, tableRelTargetFromWorksheetName, themePath, getThemeNameFromPath, getVmlDrawingNameFromPath, getWorksheetNoFromWorksheetPath, getWorksheetNoFromWorksheetRelsPath, isBinaryEntryPath, normalizeZipPath, OOXML_PATHS, vmlDrawingRelTargetFromWorksheetName, vmlDrawingPath, worksheetPath, worksheetRelsPath } from "../utils/ooxml-paths.js";
36
+ import { commentsPath, commentsRelTargetFromWorksheetName, ctrlPropPath, drawingPath, drawingRelsPath, OOXML_REL_TARGETS, pivotTableRelTargetFromWorksheetName, pivotCacheDefinitionRelTargetFromWorkbook, getCommentsIndexFromPath, getDrawingNameFromPath, getDrawingNameFromRelsPath, getMediaFilenameFromPath, mediaPath, getPivotCacheDefinitionNameFromPath, getPivotCacheDefinitionNameFromRelsPath, getPivotCacheRecordsNameFromPath, getPivotTableNameFromPath, getPivotTableNameFromRelsPath, pivotCacheDefinitionPath, pivotCacheDefinitionRelsPath, pivotCacheDefinitionRelTargetFromPivotTable, pivotCacheRecordsPath, pivotCacheRecordsRelTarget, pivotTablePath, pivotTableRelsPath, getTableNameFromPath, tablePath, tableRelTargetFromWorksheetName, themePath, getThemeNameFromPath, getVmlDrawingNameFromPath, getWorksheetNoFromWorksheetPath, getWorksheetNoFromWorksheetRelsPath, isBinaryEntryPath, normalizeZipPath, OOXML_PATHS, vmlDrawingRelTargetFromWorksheetName, vmlDrawingPath, worksheetPath, worksheetRelsPath, worksheetRelTarget } from "../utils/ooxml-paths.js";
37
37
  import { PassthroughManager } from "../utils/passthrough-manager.js";
38
38
  class StreamingZipWriterAdapter {
39
39
  constructor(options) {
@@ -1050,13 +1050,13 @@ class XLSX {
1050
1050
  });
1051
1051
  }
1052
1052
  });
1053
- model.worksheets.forEach((worksheet, index) => {
1053
+ model.worksheets.forEach((worksheet) => {
1054
1054
  worksheet.rId = `rId${count++}`;
1055
- worksheet.fileIndex = index + 1;
1055
+ // fileIndex is assigned once in prepareModel() — use it directly
1056
1056
  relationships.push({
1057
1057
  Id: worksheet.rId,
1058
1058
  Type: XLSX.RelType.Worksheet,
1059
- Target: `worksheets/sheet${worksheet.fileIndex}.xml`
1059
+ Target: worksheetRelTarget(worksheet.fileIndex)
1060
1060
  });
1061
1061
  });
1062
1062
  const xform = new RelationshipsXform();
@@ -1091,8 +1091,8 @@ class XLSX {
1091
1091
  const commentsXform = new CommentsXform();
1092
1092
  const vmlDrawingXform = new VmlDrawingXform();
1093
1093
  const ctrlPropXform = new CtrlPropXform();
1094
- model.worksheets.forEach((worksheet, index) => {
1095
- const fileIndex = worksheet.fileIndex || index + 1;
1094
+ model.worksheets.forEach((worksheet) => {
1095
+ const { fileIndex } = worksheet;
1096
1096
  let xmlStream = new XmlStream();
1097
1097
  worksheetXform.render(xmlStream, worksheet);
1098
1098
  zip.append(xmlStream.xml, { name: worksheetPath(fileIndex) });
@@ -1299,7 +1299,12 @@ class XLSX {
1299
1299
  worksheetOptions.formControlRefs = model.formControlRefs = [];
1300
1300
  let tableCount = 0;
1301
1301
  model.tables = [];
1302
- model.worksheets.forEach((worksheet) => {
1302
+ model.worksheets.forEach((worksheet, index) => {
1303
+ // Assign fileIndex early so that worksheet-xform.prepare() can use it
1304
+ // for comment/VML relationship targets and content type names.
1305
+ // This ensures consistency with addWorksheets() which writes ZIP entries
1306
+ // using the same fileIndex.
1307
+ worksheet.fileIndex = index + 1;
1303
1308
  worksheet.tables.forEach((table) => {
1304
1309
  tableCount++;
1305
1310
  table.target = `table${tableCount}.xml`;
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @cj-tech-master/excelts v5.1.3
2
+ * @cj-tech-master/excelts v5.1.4
3
3
  * TypeScript Excel Workbook Manager - Read and Write xlsx and csv Files.
4
4
  * (c) 2026 cjnoname
5
5
  * Released under the MIT License
@@ -10733,10 +10733,9 @@ var ExcelTS = (function(exports) {
10733
10733
  PartName: toContentTypesPartName(OOXML_PATHS.xlWorkbook),
10734
10734
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
10735
10735
  });
10736
- model.worksheets.forEach((worksheet, index) => {
10737
- const fileIndex = worksheet.fileIndex || index + 1;
10736
+ model.worksheets.forEach((worksheet) => {
10738
10737
  xmlStream.leafNode("Override", {
10739
- PartName: toContentTypesPartName(worksheetPath(fileIndex)),
10738
+ PartName: toContentTypesPartName(worksheetPath(worksheet.fileIndex)),
10740
10739
  ContentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
10741
10740
  });
10742
10741
  });
@@ -14239,25 +14238,26 @@ var ExcelTS = (function(exports) {
14239
14238
  TargetMode: "External"
14240
14239
  });
14241
14240
  });
14241
+ const { fileIndex } = model;
14242
14242
  if (model.comments.length > 0) {
14243
14243
  const comment = {
14244
14244
  Id: nextRid(rels),
14245
14245
  Type: RelType.Comments,
14246
- Target: commentsRelTargetFromWorksheet(model.id)
14246
+ Target: commentsRelTargetFromWorksheet(fileIndex)
14247
14247
  };
14248
14248
  rels.push(comment);
14249
14249
  const vmlDrawing = {
14250
14250
  Id: nextRid(rels),
14251
14251
  Type: RelType.VmlDrawing,
14252
- Target: vmlDrawingRelTargetFromWorksheet(model.id)
14252
+ Target: vmlDrawingRelTargetFromWorksheet(fileIndex)
14253
14253
  };
14254
14254
  rels.push(vmlDrawing);
14255
14255
  model.comments.forEach((item) => {
14256
14256
  item.refAddress = colCache.decodeAddress(item.ref);
14257
14257
  });
14258
14258
  options.commentRefs.push({
14259
- commentName: `comments${model.id}`,
14260
- vmlDrawing: `vmlDrawing${model.id}`
14259
+ commentName: `comments${fileIndex}`,
14260
+ vmlDrawing: `vmlDrawing${fileIndex}`
14261
14261
  });
14262
14262
  }
14263
14263
  if (model.drawing && model.drawing.anchors) {
@@ -14375,7 +14375,7 @@ var ExcelTS = (function(exports) {
14375
14375
  if (model.comments.length === 0) rels.push({
14376
14376
  Id: nextRid(rels),
14377
14377
  Type: RelType.VmlDrawing,
14378
- Target: vmlDrawingRelTargetFromWorksheet(model.id)
14378
+ Target: vmlDrawingRelTargetFromWorksheet(fileIndex)
14379
14379
  });
14380
14380
  const toNativePos = (p) => ({
14381
14381
  nativeCol: p.col,
@@ -22319,13 +22319,12 @@ var ExcelTS = (function(exports) {
22319
22319
  });
22320
22320
  }
22321
22321
  });
22322
- model.worksheets.forEach((worksheet, index) => {
22322
+ model.worksheets.forEach((worksheet) => {
22323
22323
  worksheet.rId = `rId${count++}`;
22324
- worksheet.fileIndex = index + 1;
22325
22324
  relationships.push({
22326
22325
  Id: worksheet.rId,
22327
22326
  Type: XLSX.RelType.Worksheet,
22328
- Target: `worksheets/sheet${worksheet.fileIndex}.xml`
22327
+ Target: worksheetRelTarget(worksheet.fileIndex)
22329
22328
  });
22330
22329
  });
22331
22330
  const xml = new RelationshipsXform().toXml(relationships);
@@ -22353,8 +22352,8 @@ var ExcelTS = (function(exports) {
22353
22352
  const commentsXform = new CommentsXform();
22354
22353
  const vmlDrawingXform = new VmlDrawingXform();
22355
22354
  const ctrlPropXform = new CtrlPropXform();
22356
- model.worksheets.forEach((worksheet, index) => {
22357
- const fileIndex = worksheet.fileIndex || index + 1;
22355
+ model.worksheets.forEach((worksheet) => {
22356
+ const { fileIndex } = worksheet;
22358
22357
  let xmlStream = new XmlStream();
22359
22358
  worksheetXform.render(xmlStream, worksheet);
22360
22359
  zip.append(xmlStream.xml, { name: worksheetPath(fileIndex) });
@@ -22517,7 +22516,8 @@ var ExcelTS = (function(exports) {
22517
22516
  worksheetOptions.formControlRefs = model.formControlRefs = [];
22518
22517
  let tableCount = 0;
22519
22518
  model.tables = [];
22520
- model.worksheets.forEach((worksheet) => {
22519
+ model.worksheets.forEach((worksheet, index) => {
22520
+ worksheet.fileIndex = index + 1;
22521
22521
  worksheet.tables.forEach((table) => {
22522
22522
  tableCount++;
22523
22523
  table.target = `table${tableCount}.xml`;
@@ -24646,8 +24646,12 @@ var ExcelTS = (function(exports) {
24646
24646
  }
24647
24647
  addContentTypes() {
24648
24648
  return new Promise((resolve) => {
24649
+ const worksheets = this._worksheets.filter(Boolean);
24650
+ worksheets.forEach((ws) => {
24651
+ ws.fileIndex = ws.id;
24652
+ });
24649
24653
  const model = {
24650
- worksheets: this._worksheets.filter(Boolean),
24654
+ worksheets,
24651
24655
  sharedStrings: this.sharedStrings,
24652
24656
  commentRefs: this.commentRefs,
24653
24657
  media: this.media,