@devmm/puredocs-excel 1.0.5 → 1.0.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.d.cts CHANGED
@@ -513,11 +513,13 @@ declare class Cell {
513
513
  getText(): string;
514
514
  /**
515
515
  * Returns the display text with the cell's number format applied, e.g. a
516
- * value of 4.5 under `$#,##0.00` renders as `$4.50`.
516
+ * value of 4.5 under `$#,##0.00` renders as `$4.50`, and a date under
517
+ * `dd/mm/yyyy` as `31/01/2025`.
517
518
  *
518
- * Falls back to {@link getText} for non-numeric values and for format codes
519
- * outside the supported subset (fractions, scientific notation, conditional
520
- * sections) — so the result is never a misleading rendering.
519
+ * Falls back to {@link getText} for values with no format and for format
520
+ * codes outside the supported subset (fractions, scientific notation,
521
+ * conditional sections, elapsed time) — so the result is never a misleading
522
+ * rendering.
521
523
  */
522
524
  getFormattedText(): string;
523
525
  /**
@@ -588,6 +590,45 @@ declare class Cell {
588
590
  }, ref: string): CellData;
589
591
  }
590
592
 
593
+ /** Describes one structural edit on a sheet. */
594
+ interface RefShift {
595
+ readonly dim: 'row' | 'col';
596
+ readonly kind: 'insert' | 'delete';
597
+ /** 1-based index of the first inserted/deleted row or column. */
598
+ readonly at: number;
599
+ /** Number of rows/columns inserted or deleted (>= 1). */
600
+ readonly count: number;
601
+ /** Name of the sheet the structural edit happened on. */
602
+ readonly sheetName: string;
603
+ }
604
+ /**
605
+ * Shifts one 1-based index. Returns `null` when the index falls inside a
606
+ * delete band (the row/column it pointed at no longer exists).
607
+ */
608
+ declare function shiftIndex(index: number, shift: RefShift): number | null;
609
+ /**
610
+ * Shifts an inclusive 1-based [start, end] span, clamping it against a delete
611
+ * band the way Excel does (endpoints move independently; a partially deleted
612
+ * span shrinks). Returns `null` when the span is entirely deleted.
613
+ */
614
+ declare function shiftSpan(start: number, end: number, shift: RefShift): {
615
+ start: number;
616
+ end: number;
617
+ } | null;
618
+ /**
619
+ * Shifts a plain "A1" or "A1:B2" reference (no `$` markers — this is for
620
+ * model metadata such as merges, autofilter and validation sqref parts, which
621
+ * never carry them). Returns `null` when the referenced area is entirely
622
+ * deleted.
623
+ */
624
+ declare function shiftRangeRef(ref: string, shift: RefShift): string | null;
625
+ /**
626
+ * Shifts a space-separated list of range references (the OOXML `sqref` shape
627
+ * used by data validations). Parts that are entirely deleted are dropped;
628
+ * returns `null` when nothing survives.
629
+ */
630
+ declare function shiftSqref(sqref: string, shift: RefShift): string | null;
631
+
591
632
  /** A part that a drawing anchor references (e.g. `xl/charts/chart1.xml`). */
592
633
  interface DrawingDependentPart {
593
634
  /** Package-relative path, no leading slash — e.g. `xl/charts/chart1.xml`. */
@@ -701,7 +742,23 @@ declare class Range {
701
742
  getValues(): CellValue[][];
702
743
  /** Clears all cells in the range (values only, preserves style). */
703
744
  clear(): void;
704
- /** Auto-fits all columns in the range. */
745
+ /** Clears values AND styles of all cells in the range. */
746
+ clearAll(): void;
747
+ /**
748
+ * Moves the whole range so its top-left cell lands on `destTopLeft`,
749
+ * carrying values, formulas, styles and spill anchors. The vacated cells
750
+ * are cleared and the destination block is fully replaced (empty source
751
+ * cells clear their destination). Overlapping source/destination is safe.
752
+ * Formula text is NOT adjusted for the new position.
753
+ *
754
+ * @example
755
+ * ws.getRange('A1:B3').moveTo('D1');
756
+ */
757
+ moveTo(destTopLeft: string): void;
758
+ /**
759
+ * Auto-fits all columns in the range. Measures every column in one sparse
760
+ * sweep rather than re-scanning the sheet per column.
761
+ */
705
762
  autoFit(): void;
706
763
  /** Applies a CellStyle to all cells in the range. Returns this for chaining. */
707
764
  setStyle(style: CellStyle): this;
@@ -734,6 +791,59 @@ declare class Range {
734
791
  */
735
792
 
736
793
  type SheetVisibility = 'visible' | 'hidden' | 'veryHidden';
794
+ /**
795
+ * What users may still do on a protected sheet. Named from the user's point of
796
+ * view — the same way Excel's "Protect Sheet" dialog lists its checkboxes —
797
+ * because the underlying OOXML attributes are inverted (`formatCells="1"` means
798
+ * formatting is *blocked*), which is a reliable source of bugs.
799
+ *
800
+ * Defaults match Excel: selecting cells stays allowed, everything else does not.
801
+ */
802
+ interface SheetProtection {
803
+ allowSelectLockedCells: boolean;
804
+ allowSelectUnlockedCells: boolean;
805
+ allowFormatCells: boolean;
806
+ allowFormatColumns: boolean;
807
+ allowFormatRows: boolean;
808
+ allowInsertRows: boolean;
809
+ allowInsertColumns: boolean;
810
+ allowInsertHyperlinks: boolean;
811
+ allowDeleteRows: boolean;
812
+ allowDeleteColumns: boolean;
813
+ allowSort: boolean;
814
+ allowAutoFilter: boolean;
815
+ allowPivotTables: boolean;
816
+ allowEditObjects: boolean;
817
+ allowEditScenarios: boolean;
818
+ }
819
+ /** A hyperlink attached to a cell or range. */
820
+ interface Hyperlink {
821
+ /** The cell or range the link covers, e.g. "A1" or "A1:B2". */
822
+ readonly ref: string;
823
+ /** External target, e.g. "https://example.com" or "mailto:a@b.c". */
824
+ readonly target?: string;
825
+ /** In-workbook destination, e.g. "Sheet2!A1" or a defined name. */
826
+ readonly location?: string;
827
+ /** Text to show instead of the cell's own value. */
828
+ readonly display?: string;
829
+ /** Hover tooltip. */
830
+ readonly tooltip?: string;
831
+ }
832
+ /** A classic cell comment (a "note" in current Excel versions). */
833
+ interface CellComment {
834
+ /** The cell the comment is attached to, e.g. "B4". */
835
+ readonly ref: string;
836
+ readonly text: string;
837
+ readonly author: string;
838
+ }
839
+ /** Outcome of a structural edit (insert/delete rows or columns). */
840
+ interface StructuralEditResult {
841
+ /**
842
+ * References (post-shift, on this sheet) of formula cells that now contain
843
+ * `#REF!` because something they pointed at was deleted.
844
+ */
845
+ readonly refErrors: readonly string[];
846
+ }
737
847
  declare class Worksheet {
738
848
  #private;
739
849
  /** @internal */
@@ -763,10 +873,46 @@ declare class Worksheet {
763
873
  getCellFormula(reference: string): string | null;
764
874
  /** Spill range (e.g. "A1:A3") of a dynamic-array anchor, or null. Supports A1#. */
765
875
  getSpillRange(reference: string): string | null;
876
+ /**
877
+ * Iterates the populated rows of the sheet in ascending row order, yielding
878
+ * each row's 1-based index and its cells (left to right). Rows and cells
879
+ * that were never written are skipped, so a sparse sheet iterates in
880
+ * O(populated cells) regardless of its bounds.
881
+ *
882
+ * @example
883
+ * for (const { rowIndex, cells } of ws.rows()) {
884
+ * for (const cell of cells) console.log(rowIndex, cell.reference, cell.getValue());
885
+ * }
886
+ */
887
+ rows(): IterableIterator<{
888
+ rowIndex: number;
889
+ cells: Cell[];
890
+ }>;
891
+ /**
892
+ * Iterates every populated cell of the sheet in row-major order. Sparse
893
+ * counterpart to scanning {@link usedBounds} with {@link tryGetCell}.
894
+ *
895
+ * @example
896
+ * for (const cell of ws.cells()) console.log(cell.reference, cell.getValue());
897
+ */
898
+ cells(): IterableIterator<Cell>;
899
+ /**
900
+ * @internal Visits the populated cells inside a rectangle, passing the
901
+ * coordinates it already knows so the callback never has to parse a
902
+ * reference. Backs the Range operations that must not create cells; probing
903
+ * every coordinate would cost O(area) even on an empty sheet.
904
+ */
905
+ forEachCellIn(startRow: number, startColumn: number, endRow: number, endColumn: number, action: (cell: Cell, row: number, column: number) => void): void;
906
+ /**
907
+ * @internal Moves a cell by coordinates, skipping the reference parsing that
908
+ * the public {@link moveCell} has to do. Used by bulk range moves.
909
+ */
910
+ moveCellRC(fromRow: number, fromColumn: number, toRow: number, toColumn: number): void;
766
911
  /**
767
912
  * Returns the 1-based extent of populated cells (largest row and column that
768
913
  * contain data). Returns zeros for an empty sheet. Useful for snapshotting a
769
- * sheet into a dense 2D array.
914
+ * sheet into a dense 2D array — though {@link rows} and {@link cells} are
915
+ * cheaper when a dense shape is not actually required.
770
916
  */
771
917
  get usedBounds(): {
772
918
  rowCount: number;
@@ -774,6 +920,19 @@ declare class Worksheet {
774
920
  };
775
921
  /** Sets the width of a column (1-based index). */
776
922
  setColumnWidth(columnIndex: number, width: number): void;
923
+ /**
924
+ * Removes the explicit width of a column so it falls back to the sheet
925
+ * default. Counterpart to {@link setColumnWidth}; afterwards
926
+ * {@link getColumnWidth} returns `undefined`. A hidden column stays hidden.
927
+ */
928
+ resetColumnWidth(columnIndex: number): void;
929
+ /**
930
+ * Shows or hides a column (1-based index). Hidden columns round-trip to the
931
+ * file as `<col hidden="1">` and keep any explicit width.
932
+ */
933
+ setColumnHidden(columnIndex: number, hidden?: boolean): void;
934
+ /** True if the given 1-based column is hidden. */
935
+ isColumnHidden(columnIndex: number): boolean;
777
936
  /**
778
937
  * Returns the explicit width of a column (1-based index), or `undefined` when
779
938
  * the column uses the sheet default. Counterpart to {@link setColumnWidth};
@@ -783,6 +942,11 @@ declare class Worksheet {
783
942
  getColumnWidth(columnIndex: number): number | undefined;
784
943
  /** Auto-fits column width based on content (approximate). */
785
944
  autoFitColumn(columnIndex: number): void;
945
+ /**
946
+ * Auto-fits an inclusive span of columns (1-based) in a single pass over the
947
+ * populated cells, instead of re-scanning the sheet once per column.
948
+ */
949
+ autoFitColumns(firstColumn: number, lastColumn: number): void;
786
950
  /** Sets the height of a row (1-based index). */
787
951
  setRowHeight(rowIndex: number, height: number): void;
788
952
  /**
@@ -790,10 +954,90 @@ declare class Worksheet {
790
954
  * the row uses the sheet default. Counterpart to {@link setRowHeight}.
791
955
  */
792
956
  getRowHeight(rowIndex: number): number | undefined;
957
+ /**
958
+ * Removes the explicit height of a row so it falls back to the sheet
959
+ * default. Counterpart to {@link setRowHeight}; afterwards
960
+ * {@link getRowHeight} returns `undefined`. A hidden row stays hidden.
961
+ */
962
+ resetRowHeight(rowIndex: number): void;
793
963
  /** Shows or hides a row (1-based index). Hidden rows affect SUBTOTAL(101-111). */
794
964
  setRowHidden(rowIndex: number, hidden?: boolean): void;
795
965
  /** True if the given 1-based row is hidden. */
796
966
  isRowHidden(rowIndex: number): boolean;
967
+ /**
968
+ * The 1-based indices of every hidden row, ascending. Sparse counterpart to
969
+ * probing {@link isRowHidden} across {@link usedBounds}.
970
+ */
971
+ get hiddenRows(): readonly number[];
972
+ /**
973
+ * The 1-based indices of every hidden column, ascending. Counterpart to
974
+ * {@link isColumnHidden}, in the same spirit as {@link hiddenRows}.
975
+ */
976
+ get hiddenColumns(): readonly number[];
977
+ /**
978
+ * Inserts `count` empty rows starting at row `at` (1-based). Everything at
979
+ * or below `at` moves down: cell values, formulas (references are rewritten
980
+ * the way Excel does), styles, row heights, hidden flags, merges,
981
+ * autofilter and data-validation ranges.
982
+ *
983
+ * Frozen panes are a view property and stay put. Drawing/chart anchors
984
+ * preserved from a loaded file are opaque XML and do NOT shift — images
985
+ * keep their absolute position (known limitation).
986
+ *
987
+ * When formulas on OTHER sheets reference this sheet, use the
988
+ * Workbook-level counterpart so they are rewritten too, or call
989
+ * `applyExternalShift` on each sheet yourself. If a RecalcEngine is
990
+ * attached, notify it afterwards (e.g. `engine.onRowsInserted(...)`).
991
+ *
992
+ * @example
993
+ * ws.insertRows(3, 2); // pushes row 3 and below down by two rows
994
+ */
995
+ insertRows(at: number, count?: number): StructuralEditResult;
996
+ /**
997
+ * Deletes `count` rows starting at row `at` (1-based). Rows below move up;
998
+ * formulas referencing the deleted band get `#REF!` (fully inside) or
999
+ * shrink (partially inside), exactly like Excel. See {@link insertRows}
1000
+ * for the shifting rules and known limitations.
1001
+ */
1002
+ deleteRows(at: number, count?: number): StructuralEditResult;
1003
+ /**
1004
+ * Inserts `count` empty columns starting at column `at` (1-based).
1005
+ * Column-level counterpart to {@link insertRows}; widths and hidden flags
1006
+ * shift with the columns.
1007
+ */
1008
+ insertColumns(at: number, count?: number): StructuralEditResult;
1009
+ /**
1010
+ * Deletes `count` columns starting at column `at` (1-based).
1011
+ * Column-level counterpart to {@link deleteRows}.
1012
+ */
1013
+ deleteColumns(at: number, count?: number): StructuralEditResult;
1014
+ /**
1015
+ * @internal Rewrites formulas on THIS sheet after a structural edit on a
1016
+ * DIFFERENT sheet (named by `shift.sheetName`), so qualified references
1017
+ * like `'Data'!A5` stay correct. Cell positions here do not change.
1018
+ */
1019
+ applyExternalShift(shift: RefShift): StructuralEditResult;
1020
+ /**
1021
+ * Moves a cell's full contents — value, formula, style and spill anchor —
1022
+ * to another cell, overwriting the destination and clearing the source.
1023
+ * A missing source clears the destination. This is a literal move: formula
1024
+ * text is NOT adjusted for the new position.
1025
+ *
1026
+ * @example
1027
+ * ws.moveCell('A1', 'C5');
1028
+ */
1029
+ moveCell(from: string, to: string): void;
1030
+ /**
1031
+ * Copies a cell's value, formula and style to another cell, overwriting the
1032
+ * destination and leaving the source untouched. A missing source clears the
1033
+ * destination. This is a literal copy: formula references are NOT adjusted,
1034
+ * and the spill anchor (`arrayRef`) is not copied — a recalc engine
1035
+ * re-establishes it.
1036
+ *
1037
+ * @example
1038
+ * ws.copyCell('A1', 'C5');
1039
+ */
1040
+ copyCell(from: string, to: string): void;
797
1041
  /** Merges cells in the given range (e.g. "A1:B2"). */
798
1042
  mergeCells(rangeReference: string): void;
799
1043
  /** Removes a merge for the given range reference. */
@@ -821,6 +1065,82 @@ declare class Worksheet {
821
1065
  /** Sets the visibility state of this worksheet. */
822
1066
  setVisibility(state: SheetVisibility): void;
823
1067
  get visibility(): SheetVisibility;
1068
+ /**
1069
+ * Turns on sheet protection, optionally relaxing individual permissions.
1070
+ * Cells are locked by default in Excel, so protecting a sheet makes all of
1071
+ * them read-only; clear a cell style's `locked` flag to leave a cell editable.
1072
+ *
1073
+ * Excel's sheet protection is a UI guard, **not** security: the contents stay
1074
+ * readable to anything that opens the file. This library therefore never
1075
+ * creates a protection password. A password read from an existing file is
1076
+ * preserved so the sheet round-trips unchanged.
1077
+ *
1078
+ * @example
1079
+ * ws.protect(); // lock everything
1080
+ * ws.protect({ allowSort: true, allowAutoFilter: true });
1081
+ */
1082
+ protect(options?: Partial<SheetProtection>): void;
1083
+ /** Turns off sheet protection, discarding any password read from a file. */
1084
+ unprotect(): void;
1085
+ /** True when this sheet is protected. */
1086
+ get isProtected(): boolean;
1087
+ /** The active permissions, or `undefined` when the sheet is not protected. */
1088
+ get protection(): Readonly<SheetProtection> | undefined;
1089
+ /**
1090
+ * Attaches a hyperlink to a cell or range. Give `target` for an external
1091
+ * destination or `location` for one inside the workbook; passing both keeps
1092
+ * the external target and uses the location as its fragment, which is how
1093
+ * Excel links to an anchor within a document.
1094
+ *
1095
+ * A cell's displayed text still comes from its own value — set that
1096
+ * separately; `display` only overrides what Excel shows in the edit bar.
1097
+ *
1098
+ * @example
1099
+ * ws.getCell('A1').setValue('Anthropic');
1100
+ * ws.setHyperlink('A1', { target: 'https://anthropic.com', tooltip: 'Open site' });
1101
+ * ws.setHyperlink('B1', { location: "'Sheet2'!A1" });
1102
+ */
1103
+ setHyperlink(ref: string, link: {
1104
+ target?: string;
1105
+ location?: string;
1106
+ display?: string;
1107
+ tooltip?: string;
1108
+ }): void;
1109
+ /** The hyperlink covering exactly this ref, or undefined. */
1110
+ getHyperlink(ref: string): Hyperlink | undefined;
1111
+ /** Removes the hyperlink on this ref. Returns true if one was there. */
1112
+ removeHyperlink(ref: string): boolean;
1113
+ /** Every hyperlink on the sheet, including ones read from a file. */
1114
+ get hyperlinks(): readonly Hyperlink[];
1115
+ /**
1116
+ * Attaches a comment (a "note" in current Excel versions) to a cell,
1117
+ * replacing any comment already there.
1118
+ *
1119
+ * Note that writing comments makes this sheet regenerate its comment and
1120
+ * legacy-drawing parts on save. If the file was opened with other legacy
1121
+ * drawing content on the same sheet — form controls, for instance — that
1122
+ * content is not reproduced. Reading comments has no such effect.
1123
+ *
1124
+ * @example
1125
+ * ws.setComment('B4', 'Check this figure', { author: 'Bill' });
1126
+ */
1127
+ setComment(ref: string, text: string, options?: {
1128
+ author?: string;
1129
+ }): void;
1130
+ /** The comment on a cell, or undefined. */
1131
+ getComment(ref: string): CellComment | undefined;
1132
+ /** Removes the comment on a cell. Returns true if one was there. */
1133
+ removeComment(ref: string): boolean;
1134
+ /** Every comment on the sheet, including ones read from a file. */
1135
+ get comments(): readonly CellComment[];
1136
+ /** @internal True when this sheet must write its own comment parts. */
1137
+ get ownsCommentParts(): boolean;
1138
+ /**
1139
+ * @internal True when the sheet took over its comment parts and any preserved
1140
+ * originals must be dropped — including the case where every comment was
1141
+ * deleted and nothing replaces them.
1142
+ */
1143
+ get commentPartsReplaced(): boolean;
824
1144
  /**
825
1145
  * Attaches a drawing provider (e.g. a chart) to this worksheet.
826
1146
  * Satellite packages such as `@devmm/puredocs-excel-charts` call this; the core
@@ -858,12 +1178,47 @@ declare class Worksheet {
858
1178
  * clear every preserved id so the two sets cannot collide.
859
1179
  */
860
1180
  get drawingRelId(): string;
1181
+ /**
1182
+ * @internal Relationship ids for the parts this sheet generates itself.
1183
+ *
1184
+ * Derived purely from the model so the worksheet XML and the sheet's rels part
1185
+ * — which are written by different code — cannot disagree about an id. Order is
1186
+ * fixed: drawing, then external hyperlinks in insertion order, then the
1187
+ * comments part and its legacy VML drawing.
1188
+ */
1189
+ generatedRels(): {
1190
+ drawing?: string;
1191
+ hyperlinks: Map<string, string>;
1192
+ comments?: string;
1193
+ vmlDrawing?: string;
1194
+ };
861
1195
  /** @internal Captures round-trip state from the source package. */
862
1196
  loadPreservedState(worksheetXml: string, relationships: readonly Relationship[]): void;
1197
+ /**
1198
+ * @internal Package paths of the comment parts this sheet read at load time.
1199
+ * The save pipeline drops them from the preserved set once the sheet takes
1200
+ * ownership, so they are not written twice.
1201
+ */
1202
+ commentPartPaths(): string[];
1203
+ /**
1204
+ * @internal The relationship pointing at this sheet's comments part, if the
1205
+ * sheet was loaded from a file that had one.
1206
+ */
1207
+ commentsPartPath(): string | undefined;
863
1208
  /** Builds the xl/worksheets/sheetN.xml string. */
864
1209
  buildXml(): string;
865
1210
  /** Parses xl/worksheets/sheetN.xml and loads cells into memory. */
866
1211
  loadFromXml(xml: string): void;
1212
+ /** @internal Parses an `xl/comments*.xml` part into this sheet's comments. */
1213
+ loadCommentsXml(xml: string): void;
1214
+ /** @internal The comments part content, when this sheet owns it. */
1215
+ buildCommentsXml(): string;
1216
+ /**
1217
+ * @internal The legacy VML drawing that positions the comment boxes. Excel
1218
+ * needs it to draw the note indicator and popup; the comments part alone
1219
+ * carries only the text.
1220
+ */
1221
+ buildCommentsVml(): string;
867
1222
  }
868
1223
 
869
1224
  /**
@@ -959,6 +1314,23 @@ declare class Workbook {
959
1314
  * Returns a worksheet by name. Throws if not found.
960
1315
  */
961
1316
  getWorksheet(name: string): Worksheet;
1317
+ /**
1318
+ * Inserts rows on one sheet and keeps the whole workbook consistent:
1319
+ * formulas on OTHER sheets that reference the edited sheet, and defined
1320
+ * names, are rewritten too. Prefer this over `Worksheet.insertRows` in a
1321
+ * multi-sheet workbook.
1322
+ *
1323
+ * @returns The edited sheet's result; `refErrors` additionally includes
1324
+ * sheet-qualified refs (e.g. `"Other!B2"`) for affected formula
1325
+ * cells on other sheets.
1326
+ */
1327
+ insertRows(sheetName: string, at: number, count?: number): StructuralEditResult;
1328
+ /** Workbook-wide counterpart to `Worksheet.deleteRows`. See {@link insertRows}. */
1329
+ deleteRows(sheetName: string, at: number, count?: number): StructuralEditResult;
1330
+ /** Workbook-wide counterpart to `Worksheet.insertColumns`. See {@link insertRows}. */
1331
+ insertColumns(sheetName: string, at: number, count?: number): StructuralEditResult;
1332
+ /** Workbook-wide counterpart to `Worksheet.deleteColumns`. See {@link insertRows}. */
1333
+ deleteColumns(sheetName: string, at: number, count?: number): StructuralEditResult;
962
1334
  /**
963
1335
  * Defines (or replaces) a named range.
964
1336
  *
@@ -1006,6 +1378,10 @@ declare class Workbook {
1006
1378
  *
1007
1379
  * Port of TVE.PureDocs.Excel.CellReference (C#)
1008
1380
  */
1381
+ /** Largest 1-based row index a worksheet can have (Excel limit). */
1382
+ declare const EXCEL_MAX_ROWS = 1048576;
1383
+ /** Largest 1-based column index a worksheet can have (column XFD). */
1384
+ declare const EXCEL_MAX_COLUMNS = 16384;
1009
1385
  interface ParsedCellRef {
1010
1386
  readonly row: number;
1011
1387
  readonly column: number;
@@ -1047,6 +1423,15 @@ declare function columnLetter(column: number): string;
1047
1423
  * columnNumber("AA") // 27
1048
1424
  */
1049
1425
  declare function columnNumber(letters: string): number;
1426
+ /**
1427
+ * Formats start/end coordinates as a range reference string. Collapses to a
1428
+ * single cell reference when start and end are the same cell.
1429
+ *
1430
+ * @example
1431
+ * formatRangeRef(1, 1, 10, 2) // "A1:B10"
1432
+ * formatRangeRef(1, 1, 1, 1) // "A1"
1433
+ */
1434
+ declare function formatRangeRef(startRow: number, startColumn: number, endRow: number, endColumn: number): string;
1050
1435
  /**
1051
1436
  * Parses a range reference string like "A1:B10" into start/end coordinates.
1052
1437
  */
@@ -1057,6 +1442,24 @@ declare function parseRangeRef(rangeReference: string): {
1057
1442
  endColumn: number;
1058
1443
  };
1059
1444
 
1445
+ interface FormulaRewriteResult {
1446
+ /** The rewritten formula text (without leading '='). */
1447
+ readonly text: string;
1448
+ /** True when any reference was actually rewritten. */
1449
+ readonly changed: boolean;
1450
+ /** True when at least one reference was replaced by `#REF!`. */
1451
+ readonly hasRefError: boolean;
1452
+ }
1453
+ /**
1454
+ * Rewrites the references in one formula for a structural edit.
1455
+ *
1456
+ * @param formula Formula text without the leading '='.
1457
+ * @param shift The structural edit that happened.
1458
+ * @param formulaSheet Name of the sheet this formula lives on — unqualified
1459
+ * references resolve against it.
1460
+ */
1461
+ declare function shiftFormulaRefs(formula: string, shift: RefShift, formulaSheet: string): FormulaRewriteResult;
1462
+
1060
1463
  /**
1061
1464
  * OLE Automation Date (OADate) helpers.
1062
1465
  *
@@ -1102,8 +1505,8 @@ declare function isDateFormatCode(formatCode: string): boolean;
1102
1505
  * raw value rather than display something wrong.
1103
1506
  *
1104
1507
  * Not handled (returns null): fractions (`# ?/?`), scientific (`0.00E+00`),
1105
- * date/time codes (handled by the date path in Cell), and conditional sections
1106
- * such as `[<=9999999]###-####`.
1508
+ * date/time codes (see date-format-renderer.ts, which Cell routes Date values
1509
+ * to), and conditional sections such as `[<=9999999]###-####`.
1107
1510
  */
1108
1511
  /**
1109
1512
  * Applies `formatCode` to `value`.
@@ -1113,6 +1516,30 @@ declare function isDateFormatCode(formatCode: string): boolean;
1113
1516
  */
1114
1517
  declare function formatNumberWithCode(value: number, formatCode: string): string | null;
1115
1518
 
1519
+ /**
1520
+ * Renders a Date through an OOXML date/time format code.
1521
+ *
1522
+ * Deliberately a *subset* of the full spec, mirroring the philosophy of
1523
+ * number-format-renderer: it covers the codes an editor actually round-trips
1524
+ * (`yyyy`, `yy`, `m`→`mmmm`, `d`→`dddd`, `h`/`hh`, `s`/`ss`, `AM/PM`, quoted
1525
+ * literals, separators) and returns `null` for anything it does not
1526
+ * understand — elapsed-time brackets (`[h]`), fractional seconds (`ss.00`),
1527
+ * era codes — so callers can fall back rather than display something wrong.
1528
+ *
1529
+ * The `m` month-vs-minute ambiguity uses the standard OOXML rule: `m`/`mm`
1530
+ * means minutes when the previous time token is hours or the next one is
1531
+ * seconds; otherwise it means month.
1532
+ */
1533
+ /**
1534
+ * Formats a Date with an OOXML date/time format code, e.g. a value of
1535
+ * 2025-01-31 under `dd/mm/yyyy` renders as `31/01/2025`.
1536
+ *
1537
+ * Returns `null` when the code uses constructs outside the supported subset
1538
+ * (elapsed time `[h]`, fractional seconds, era codes) — callers should fall
1539
+ * back to a locale default rather than render something misleading.
1540
+ */
1541
+ declare function formatDateCode(date: Date, formatCode: string): string | null;
1542
+
1116
1543
  /**
1117
1544
  * Cross-platform XML parser.
1118
1545
  *
@@ -1131,6 +1558,12 @@ type XmlElement = {
1131
1558
  /**
1132
1559
  * Parses an XML string into a simple XmlElement tree.
1133
1560
  */
1561
+ /**
1562
+ * Decodes the five predefined XML entities. `&amp;` is expanded last so that an
1563
+ * escaped entity such as `&amp;lt;` decodes to the literal text `&lt;` rather
1564
+ * than being expanded twice.
1565
+ */
1566
+ declare function decodeXmlEntities(value: string): string;
1134
1567
  declare function parseXml(xmlString: string): XmlElement;
1135
1568
  /**
1136
1569
  * Decodes a Uint8Array to a UTF-8 string.
@@ -1196,6 +1629,8 @@ declare const REL_TYPES: {
1196
1629
  readonly chart: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart";
1197
1630
  readonly drawing: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";
1198
1631
  readonly hyperlink: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
1632
+ readonly comments: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
1633
+ readonly vmlDrawing: "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing";
1199
1634
  };
1200
1635
  declare const CONTENT_TYPES: {
1201
1636
  readonly workbook: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
@@ -1206,6 +1641,8 @@ declare const CONTENT_TYPES: {
1206
1641
  readonly chart: "application/vnd.openxmlformats-officedocument.drawingml.chart+xml";
1207
1642
  readonly relationships: "application/vnd.openxmlformats-package.relationships+xml";
1208
1643
  readonly coreProperties: "application/vnd.openxmlformats-package.core-properties+xml";
1644
+ readonly comments: "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml";
1645
+ readonly vmlDrawing: "application/vnd.openxmlformats-officedocument.vmlDrawing";
1209
1646
  };
1210
1647
 
1211
1648
  /**
@@ -1229,4 +1666,4 @@ declare function setXmlEntry(entries: ZipInput, path: string, xml: string): void
1229
1666
  */
1230
1667
  declare function setBinaryEntry(entries: ZipInput, path: string, bytes: Uint8Array): void;
1231
1668
 
1232
- export { CONTENT_TYPES, Cell, type CellData, CellStyle, type CellValue, type ColorXmlAttrs, type DefinedName, DefinedNameManager, type DrawingDependentPart, type DrawingProvider, ExcelAlignment, ExcelBorder, ExcelBorderEdge, ExcelBorderStyle, ExcelColor, ExcelFill, ExcelFont, type ExcelFontOptions, ExcelHorizontalAlignment, ExcelNumberFormat, ExcelPatternType, ExcelReadingOrder, ExcelUnderline, ExcelVerticalAlignRun, ExcelVerticalAlignment, NS, type ParsedCellRef, REL_TYPES, Range, type SheetVisibility, StyleManager, WORKSHEET_DRAWING_REL_ID, Workbook, Worksheet, type XmlAttrs, XmlBuilder, type XmlElement, type ZipEntries, type ZipInput, buildDrawingXml, buildRelsXml, cellRefFromRowCol, columnLetter, columnNumber, decodeUtf8, encodeUtf8, escapeXml, formatNumberWithCode, fromOADate, getAttr, getElementsByTagName, isDateFormatCode, isDateFormatId, listEntries, parseCellRef, parseRangeRef, parseXml, readXmlEntry, requireXmlEntry, setBinaryEntry, setXmlEntry, toOADate, unzipXlsx, xml, zipXlsx };
1669
+ export { CONTENT_TYPES, Cell, type CellComment, type CellData, CellStyle, type CellValue, type ColorXmlAttrs, type DefinedName, DefinedNameManager, type DrawingDependentPart, type DrawingProvider, EXCEL_MAX_COLUMNS, EXCEL_MAX_ROWS, ExcelAlignment, ExcelBorder, ExcelBorderEdge, ExcelBorderStyle, ExcelColor, ExcelFill, ExcelFont, type ExcelFontOptions, ExcelHorizontalAlignment, ExcelNumberFormat, ExcelPatternType, ExcelReadingOrder, ExcelUnderline, ExcelVerticalAlignRun, ExcelVerticalAlignment, type FormulaRewriteResult, type Hyperlink, NS, type ParsedCellRef, REL_TYPES, Range, type RefShift, type SheetProtection, type SheetVisibility, type StructuralEditResult, StyleManager, WORKSHEET_DRAWING_REL_ID, Workbook, Worksheet, type XmlAttrs, XmlBuilder, type XmlElement, type ZipEntries, type ZipInput, buildDrawingXml, buildRelsXml, cellRefFromRowCol, columnLetter, columnNumber, decodeUtf8, decodeXmlEntities, encodeUtf8, escapeXml, formatDateCode, formatNumberWithCode, formatRangeRef, fromOADate, getAttr, getElementsByTagName, isDateFormatCode, isDateFormatId, listEntries, parseCellRef, parseRangeRef, parseXml, readXmlEntry, requireXmlEntry, setBinaryEntry, setXmlEntry, shiftFormulaRefs, shiftIndex, shiftRangeRef, shiftSpan, shiftSqref, toOADate, unzipXlsx, xml, zipXlsx };