/** * Worksheet form controls (VML `legacyDrawing` + `x:ClientData`). * * Scope: P2 CheckBox / ComboBox / OptionButton plus P3 Button, ListBox, * GroupBox, FormLabel, ScrollBar, SpinButton, EditBox. * Write path is VML-only. MS-XLSX `formControlPr` / ctrlProp parts are * read/preserve only when present as foreign VML or package content. * * Citations: * - docs/api/FORM-CONTROLS-PROPOSAL.md; docs/specs/form-controls.md * - XlsIO CheckBoxShapeSerializator / ComboBoxShapeSerializator / * OptionButtonShapeSerializator / Vml.cs (P2); P3 ClientData vocabulary from * `vml-spreadsheetDrawing.xsd` ST_ObjectType + CT_ClientData children * - sml CT_Worksheet `legacyDrawing` after `drawing` * - VML namespaces: `urn:schemas-microsoft-com:vml` (v), * `urn:schemas-microsoft-com:office:office` (o), * `urn:schemas-microsoft-com:office:excel` (x) * * Package side effects (vmlDrawing part + sheet relationship) defer to * flush/save (API-RULES R5.1). DrawingML text/shapes/images/charts stay on * ``; this module never shares that part. * * @private implementation; public types exported via index. */ import { OpcPackage } from '../core/package/opc-package'; import { OpcRelationship } from '../core/package/relationships'; /** Specifies the selection state of a checkbox or radio button. */ export declare type CheckState = 'unchecked' | 'checked' | 'mixed'; /** * Specifies how a dropdown behaves: a plain list, an editable combo, or a * list shown only while open. */ export declare type ComboDropStyle = 'combo' | 'comboedit' | 'simple'; /** * Horizontal caption alignment for form controls with a text label. * Wire: `x:TextHAlign` (Left|Center|Right|Justify) and caption div `text-align`. * Citation: `vml-spreadsheetDrawing.xsd` CT_ClientData/TextHAlign. */ export declare type FormControlHorizontalAlignment = 'left' | 'center' | 'right' | 'justify'; /** * Vertical caption alignment for form controls with a text label. * Wire: `x:TextVAlign` (Top|Center|Bottom|Justify). * Citation: `vml-spreadsheetDrawing.xsd` CT_ClientData/TextVAlign. */ export declare type FormControlVerticalAlignment = 'top' | 'center' | 'bottom' | 'justify'; /** * Caption typeface style for form-control labels (Excel Format Control → Font → * Font style). Whole-caption only — not mixed rich runs. * Wire: nested HTML inside VML caption `font` — plain / `` / `` / * `…`. * Citation: Excel-authored VML `output/_excel-form-font-effects.xlsx`. */ export declare type FormControlFontStyle = 'regular' | 'italic' | 'bold' | 'boldItalic'; /** * Caption underline for form-control labels (Excel Format Control → Font → * Underline). Whole-caption only. * Wire: none = no tag; single = ``; double = `` * (Excel double-underline class on form-control captions). * Citation: Excel-authored VML `output/_excel-form-font-effects.xlsx`. */ export declare type FormControlUnderline = 'none' | 'single' | 'double'; /** * Common settings shared by all form controls placed on a worksheet, such as * name, visibility, position, and size. */ export interface FormControlBase { /** The name that identifies the control — for example `'CheckBox1'`. */ name: string; /** Whether the control is visible on the worksheet. */ isVisible: boolean; /** * The alt text describing the control for accessibility tools; * `undefined` when not set. */ alternativeText: string | undefined; /** * The row the control's top edge is anchored to — 1-based, like Excel * rows. */ readonly row: number; /** * The column the control's left edge is anchored to — 1-based, like * Excel columns. */ readonly column: number; /** * The width of the control in points (72 pt = 1 in). */ readonly width: number; /** * The height of the control in points (72 pt = 1 in). */ readonly height: number; /** * The macro that runs when the control is activated. The name is stored * only; this library never executes it. */ onAction: string | undefined; /** * Whether the control is printed with the worksheet. * Wire: `x:PrintObject` (`ST_TrueFalseBlank`; default true — omitted when true). */ printObject: boolean; /** * Whether the control shape is locked when the sheet is protected. * Wire: `x:Locked` (default true). Distinct from caption `isTextLocked` / * `x:LockText`. */ isLocked: boolean; /** * Whether the control moves when cells under its anchor are inserted or * deleted. Wire: `x:MoveWithCells` (`ST_TrueFalseBlank`; default true). */ moveWithCells: boolean; /** * Whether the control resizes when cells under its anchor change size. * Wire: `x:SizeWithCells` (`ST_TrueFalseBlank`). Defaults true for caption * kinds; false for combo, list, scroll, and spin (XlsIO-aligned). */ sizeWithCells: boolean; } /** * Visual style for form controls that show a text label (checkbox, option, * button, group, label, edit). Wire: VML `fillcolor`/`filled`, caption * `font` face/size/color plus nested effect tags (`b`/`i`/`u`/`s`/`sup`/`sub`), * `x:TextHAlign` / `x:TextVAlign`, div `text-align`. * Citation: Excel Format Control → Font; VML fixture * `output/_excel-form-font-effects.xlsx`. */ export interface FormControlStyle { /** * Solid fill color as `RRGGBB`, or `undefined` for no fill (`filled="f"`). * Accepts `#RRGGBB` or `AARRGGBB` on set (alpha stripped). */ fillColor: string | undefined; /** Caption font family (default `Calibri`). Wire: `font@face`. */ fontName: string; /** * Caption font size in points (default `10`). Wire: `font@size` in * half-points (`pt * 20`). */ fontSize: number; /** * Caption font color as `RRGGBB`, or `undefined` for automatic * (`color="auto"`). Accepts `#RRGGBB` or `AARRGGBB` on set. */ fontColor: string | undefined; /** * Caption typeface style (default `'regular'`). * Wire: nested `` / `` inside caption `font`. */ fontStyle: FormControlFontStyle; /** * Caption underline (default `'none'`). * Wire: `` (single) or `` (double). */ underline: FormControlUnderline; /** * Whether the caption is struck through (default `false`). * Wire: nested `` inside caption `font`. */ isStrikethrough: boolean; /** * Whether the caption is superscript (default `false`). Mutually exclusive * with `isSubscript` — setting one true clears the other. * Wire: nested ``. */ isSuperscript: boolean; /** * Whether the caption is subscript (default `false`). Mutually exclusive * with `isSuperscript` — setting one true clears the other. * Wire: nested ``. */ isSubscript: boolean; /** * Excel Format Control → Font → **Normal font**. * There is no discrete VML attribute; enabling (`true`) resets face/size/ * color and font effects to caption defaults (Calibri 10 pt, auto color, * regular, no underline/effects). Reading returns `true` when the caption * already matches those defaults. */ isNormalFont: boolean; /** * Horizontal caption alignment (default `'left'`). */ horizontalAlignment: FormControlHorizontalAlignment; /** * Vertical caption alignment. Default `'center'` for checkbox, option, and * button; `'top'` for group, label, and edit. */ verticalAlignment: FormControlVerticalAlignment; } /** * Represents a checkbox placed on a worksheet, letting you set its label, * checked state, and the cell it is linked to. */ export interface CheckBox extends FormControlBase, FormControlStyle { /** The label shown beside the checkbox. */ text: string; /** Whether the checkbox is checked, unchecked, or in the mixed state. */ checkState: CheckState; /** * The cell that reflects the checkbox's state, such as `A1`. When the user * checks or clears the box, Excel writes TRUE or FALSE into this cell. */ linkedCell: string | undefined; /** Whether the control is drawn with a 3-D shaded look. */ isDisplay3DShading: boolean; /** Whether the label text is locked against editing when the sheet is protected. */ isTextLocked: boolean; } /** * Represents a dropdown list placed on a worksheet, letting you set its * source range, selection, and the cell it is linked to. */ export interface ComboBox extends FormControlBase { /** The cell range the dropdown's items come from, such as `Sheet1!A1:A5`. */ listFillRange: string | undefined; /** * The cell that receives the chosen item's text (or its index, depending * on the viewer), such as `B1`. */ linkedCell: string | undefined; /** Which item is selected, counted from 1; `0` means nothing is selected. */ selectedIndex: number; /** How many items the dropdown shows at once before scrolling. */ dropDownLines: number; /** * How the dropdown behaves: a plain list, an editable combo, or a list * shown only while open. */ dropStyle: ComboDropStyle; /** Whether the control is drawn with a 3-D shaded look. */ isDisplay3DShading: boolean; /** The displayed text of the selected item. Not currently supported; always `undefined`. */ readonly selectedValue: string | undefined; } /** * Represents a radio button placed on a worksheet, letting you set its * label, selection state, and the cell it is linked to. */ export interface OptionButton extends FormControlBase, FormControlStyle { /** The text shown next to the option button. */ text: string; /** * The button's selection state: `'checked'`, `'unchecked'`, or * `'mixed'` (a state neither on nor off, as in tri-state checkbox * scenarios). */ checkState: CheckState; /** * The cell the selection is written to. `undefined` when the button is * not linked to a cell. */ linkedCell: string | undefined; /** Whether the button is drawn with a three-dimensional appearance. */ isDisplay3DShading: boolean; /** * Whether this button is the first in its group — the anchor that links * the group's buttons together. */ isFirstButton: boolean; /** Whether the button's text cannot be edited by the user. */ isTextLocked: boolean; } /** * Specifies how many items a list box lets the user select at once. * Not part of the shipped package surface (`stripInternal`). * * @private */ export declare type ListSelectionType = 'single' | 'multi' | 'extended'; /** * Restricts what a user can type into a text box, such as only numbers or * only references. */ export declare type EditValidation = 'text' | 'integer' | 'number' | 'reference' | 'formula'; /** * Represents a push button placed on a worksheet, letting you set its label * and the macro or action it runs when clicked. */ export interface FormButton extends FormControlBase, FormControlStyle { /** The text shown on the button. */ text: string; /** Whether the button's text cannot be edited by the user. */ isTextLocked: boolean; } /** * Represents a list box placed on a worksheet, letting you set its source * range, selection mode, and the cell it is linked to. */ export interface ListBox extends FormControlBase { /** * The cells the list's entries come from, given as a range address. * `undefined` when the list is not filled from the sheet. */ listFillRange: string | undefined; /** * The cell the selected list entry is written to. `undefined` when the * list is not linked to a cell. */ linkedCell: string | undefined; /** * The position of the selected entry — 1-based; `0` means nothing is * selected. Applies when a single entry can be selected. */ selectedIndex: number; /** * The positions of the selected entries — 1-based — when the list allows * selecting several entries at once. */ selectedIndices: ReadonlyArray; /** * How many entries can be selected at once: one (`'single'`), several by * clicking (`'multi'`), or several with Shift/Ctrl (`'extended'`). * Not part of the shipped package surface (`stripInternal`). * * @private */ selectionType: ListSelectionType; /** Whether the list is drawn with a three-dimensional appearance. */ isDisplay3DShading: boolean; /** * The value stored with the list, used by forms that read the selection * as a number. */ value: number; } /** * Represents a group box placed on a worksheet, used to visually arrange * related controls such as option buttons. */ export interface GroupBox extends FormControlBase, FormControlStyle { /** The caption shown at the top of the group box border. */ text: string; /** * The cell the group's option-button selection is written to, taking * precedence over each option button's own `linkedCell`. `undefined` * when the group is not linked to a cell. */ groupLinkedCell: string | undefined; } /** * Represents a text label placed on a worksheet, letting you set its caption * and the cell it is linked to. */ export interface FormLabel extends FormControlBase, FormControlStyle { /** The text shown on the label. */ text: string; /** * The cell the label's text is linked to, so the label always shows the * cell's value. `undefined` when not linked. */ textLink: string | undefined; /** Whether the label's text cannot be edited by the user. */ isTextLocked: boolean; } /** * Represents a scroll bar placed on a worksheet, letting you set its range, * step size, orientation, and the cell it is linked to. */ export interface ScrollBar extends FormControlBase { /** * The cell the scroll bar's current position is written to. * `undefined` when the scroll bar is not linked to a cell. */ linkedCell: string | undefined; /** The scroll bar's current position. */ value: number; /** The lowest position the scroll bar can be moved to. */ min: number; /** The highest position the scroll bar can be moved to. */ max: number; /** * How far the position moves when an arrow at either end is clicked. */ incrementalChange: number; /** * How far the position moves when the bar's track is clicked, like * flipping a page. */ pageChange: number; /** Whether the bar is oriented horizontally instead of vertically. */ isHorizontal: boolean; } /** * Represents a spin button placed on a worksheet, letting users increase or * decrease a linked cell's value one step at a time. */ export interface SpinButton extends FormControlBase { /** * The cell the spin button's current position is written to. * `undefined` when the spin button is not linked to a cell. */ linkedCell: string | undefined; /** The spin button's current position. */ value: number; /** The lowest position the spin button can be moved to. */ min: number; /** The highest position the spin button can be moved to. */ max: number; /** * How far the position moves each time an arrow is clicked. */ incrementalChange: number; } /** * Represents a text input box placed on a worksheet, letting you set its * contents and restrict what users can type into it. */ export interface EditBox extends FormControlBase, FormControlStyle { /** The text shown in the edit box. */ text: string; /** * The cell the edit box's text is linked to, so the cell always shows * what the user typed. `undefined` when not linked. */ textLink: string | undefined; /** * Whether users can type multiple lines of text in the edit box, using * line breaks. */ isMultiLine: boolean; /** * The kind of entry the edit box expects: normal text (`'text'`), whole * numbers (`'integer'`), any number (`'number'`), a cell or range * reference (`'reference'`), or a formula (`'formula'`). */ validation: EditValidation; /** * Whether the edit box masks the typed text, like a password field. */ isPassword: boolean; /** Whether the edit box's text cannot be edited by the user. */ isTextLocked: boolean; } /** Host callbacks for dirty + package access. */ export interface FormControlsHost { markDirty(): void; readonly package: OpcPackage; readonly sheetPartName: string | undefined; } declare type FormControlKind = 'checkbox' | 'combo' | 'option' | 'button' | 'list' | 'group' | 'label' | 'scroll' | 'spin' | 'edit'; /** * Internal entry for one form control. * @private */ export interface FormControlEntry { kind: FormControlKind; shapeId: number; name: string; isVisible: boolean; alternativeText?: string | undefined; /** 0-based OOXML anchor row. */ fromRow0: number; /** 0-based OOXML anchor col. */ fromCol0: number; widthEmu: number; heightEmu: number; zIndex: number; onAction?: string | undefined; /** Wire `x:PrintObject` — default true. */ printObject: boolean; /** Wire `x:Locked` — default true; distinct from isTextLocked. */ isLocked: boolean; /** Wire `x:MoveWithCells` — default true. */ moveWithCells: boolean; /** Wire `x:SizeWithCells` — kind-defaulted. */ sizeWithCells: boolean; /** VML `@fillcolor` RRGGBB when filled. */ fillColor?: string | undefined; fontName: string; /** Caption font size in points. */ fontSize: number; fontColor?: string | undefined; fontStyle: FormControlFontStyle; underline: FormControlUnderline; isStrikethrough: boolean; isSuperscript: boolean; isSubscript: boolean; horizontalAlignment: FormControlHorizontalAlignment; verticalAlignment: FormControlVerticalAlignment; text: string; checkState: CheckState; linkedCell?: string | undefined; isDisplay3DShading: boolean; isTextLocked: boolean; listFillRange?: string | undefined; selectedIndex: number; dropDownLines: number; dropStyle: ComboDropStyle; isFirstButton: boolean; /** Group box link. Wire `x:FmlaGroup`. */ groupLinkedCell?: string | undefined; /** Label / edit text link. Wire `x:FmlaTxbx`. */ textLink?: string | undefined; selectionType: ListSelectionType; selectedIndices: number[]; value: number; min: number; max: number; incrementalChange: number; pageChange: number; isHorizontal: boolean; isMultiLine: boolean; validation: EditValidation; isPassword: boolean; /** Opaque full shape XML when loaded from a foreign/unknown control. */ foreignShapeXml?: string | undefined; } /** * Result of materializing the VML drawing part + sheet legacyDrawing relationship. * @private */ export interface FormControlsMaterializeResult { /** Relationships to keep (non-VML-drawing). */ readonly sheetRelsWithoutVmlDrawing: ReadonlyArray; /** New or retained VML drawing relationship, if any shapes remain. */ readonly vmlDrawingRel: OpcRelationship | undefined; /** `r:id` for worksheet `` when present. */ readonly legacyDrawingRelationshipId: string | undefined; /** Whether the model owns/emits legacyDrawing (strip bag duplicates). */ readonly ownsLegacyDrawingElement: boolean; } /** * Mutable form-control collection for one worksheet (P2 + P3 kinds). * @private */ export declare class FormControlsImpl { private readonly entries; private readonly checkBoxHandles; private readonly comboHandles; private readonly optionHandles; private readonly buttonHandles; private readonly listHandles; private readonly groupHandles; private readonly labelHandles; private readonly scrollHandles; private readonly spinHandles; private readonly editHandles; private host; private foreignShapesXml; private foreignRootExtra; private vmlPartName; private vmlRelId; private loaded; private dirty; private nextShapeId; private nextCheckBoxName; private nextComboName; private nextOptionName; private nextButtonName; private nextListName; private nextGroupName; private nextLabelName; private nextScrollName; private nextSpinName; private nextEditName; private nextZIndex; /** @private */ bindHost(host: FormControlsHost): void; /** * Load VML drawing part for this sheet (if any). Call after sheet XML parse. * @private */ loadFromPackage(pkg: OpcPackage, sheetPartName: string | undefined): void; private noteLoadedIds; listCheckBoxes(): ReadonlyArray; listComboBoxes(): ReadonlyArray; listOptionButtons(): ReadonlyArray; listButtons(): ReadonlyArray; listListBoxes(): ReadonlyArray; listGroupBoxes(): ReadonlyArray; listFormLabels(): ReadonlyArray; listScrollBars(): ReadonlyArray; listSpinButtons(): ReadonlyArray; listEditBoxes(): ReadonlyArray; /** * Add a check box. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, text, checkState, linkedCell, isDisplay3DShading (default true). */ addCheckBox(row: number, column: number, width: number, height: number, name?: string, text?: string, checkState?: CheckState, linkedCell?: string, isDisplay3DShading?: boolean): CheckBox; /** * Add a combo / drop control. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, listFillRange, linkedCell, selectedIndex (default 0), * dropDownLines (default 8), dropStyle (default `'combo'`), isDisplay3DShading (default true). */ addComboBox(row: number, column: number, width: number, height: number, name?: string, listFillRange?: string, linkedCell?: string, selectedIndex?: number, dropDownLines?: number, dropStyle?: ComboDropStyle, isDisplay3DShading?: boolean): ComboBox; /** * Add an option button. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, text, checkState, linkedCell, isDisplay3DShading (default true), * isFirstButton (default false). Mixed checkState is coerced to unchecked. */ addOptionButton(row: number, column: number, width: number, height: number, name?: string, text?: string, checkState?: CheckState, linkedCell?: string, isDisplay3DShading?: boolean, isFirstButton?: boolean): OptionButton; /** * Add a button. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, text, onAction. */ addButton(row: number, column: number, width: number, height: number, name?: string, text?: string, onAction?: string): FormButton; /** * Add a list box. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, listFillRange, linkedCell, selectedIndex (default 0), * selectionType (default `'single'`), selectedIndices, isDisplay3DShading (default true), value. */ addListBox(row: number, column: number, width: number, height: number, name?: string, listFillRange?: string, linkedCell?: string, selectedIndex?: number, selectionType?: 'single' | 'multi' | 'extended', selectedIndices?: ReadonlyArray, isDisplay3DShading?: boolean, value?: number): ListBox; /** * Add a group box. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, text, groupLinkedCell. */ addGroupBox(row: number, column: number, width: number, height: number, name?: string, text?: string, groupLinkedCell?: string): GroupBox; /** * Add a form label. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, text, textLink. */ addFormLabel(row: number, column: number, width: number, height: number, name?: string, text?: string, textLink?: string): FormLabel; /** * Add a scroll bar. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, linkedCell, value, min, max, incrementalChange, * pageChange, isHorizontal (default false / vertical). */ addScrollBar(row: number, column: number, width: number, height: number, name?: string, linkedCell?: string, value?: number, min?: number, max?: number, incrementalChange?: number, pageChange?: number, isHorizontal?: boolean): ScrollBar; /** * Add a spin button. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, linkedCell, value, min, max, incrementalChange. */ addSpinButton(row: number, column: number, width: number, height: number, name?: string, linkedCell?: string, value?: number, min?: number, max?: number, incrementalChange?: number): SpinButton; /** * Add an edit box. Geometry is 1-based row/column + positive size in points. * Optional trailing args: name, text, textLink, isMultiLine, validation (default `'text'`), * isPassword. */ addEditBox(row: number, column: number, width: number, height: number, name?: string, text?: string, textLink?: string, isMultiLine?: boolean, validation?: EditValidation, isPassword?: boolean): EditBox; removeCheckBox(target: CheckBox | number): void; removeComboBox(target: ComboBox | number): void; removeOptionButton(target: OptionButton | number): void; removeButton(target: FormButton | number): void; removeListBox(target: ListBox | number): void; removeGroupBox(target: GroupBox | number): void; removeFormLabel(target: FormLabel | number): void; removeScrollBar(target: ScrollBar | number): void; removeSpinButton(target: SpinButton | number): void; removeEditBox(target: EditBox | number): void; private removeByKind; /** * True when the model should emit/replace worksheet ``. * @private */ readonly ownsLegacyDrawingElement: boolean; /** * Replace VML `ObjectType="Note"` shapes with one note shape per anchor. * Used by threaded-comments flush so Excel shows the comment indicator / * threaded-comment chrome. Non-Note foreign shapes are preserved. * * Call **before** {@link materializeOnFlush} on the same flush pass. * Anchors are 0-based row/column (SpreadsheetML `x:Row` / `x:Column`). * * @private */ syncCommentNoteShapes(anchors: ReadonlyArray<{ readonly row0: number; readonly col0: number; }>): void; /** * Visibility / size chrome for classic comment notes, keyed * `"row0:col0"` (0-based SpreadsheetML `x:Row` / `x:Column`). * @private */ noteChromeByKey(): Map; /** * Replace VML Note shapes (and stray t202 shapetype fragments) with the * provided overlay XML from classic comments materialize. Non-Note foreign * shapes are preserved. Empty overlay clears note chrome only. * * Call **before** {@link materializeOnFlush} on the same flush pass. * @private */ setCommentNoteShapes(overlayXml: ReadonlyArray): void; /** * Allocate the next VML shape id for a classic comment note overlay. * @private */ allocateNoteShapeId(): number; /** * Write/remove VML drawing part and compute sheet legacyDrawing relationship. * Call during worksheet flush after DrawingML materialization. * * @param sheetRelsCurrent Relationships already retained (may include drawing); * VML drawing types are stripped here and re-added when needed. * @private */ materializeOnFlush(sheetRelsCurrent: ReadonlyArray): FormControlsMaterializeResult; private requireAddGeometry; private createEntry; private markDirty; private checkBoxHandleFor; private comboHandleFor; private optionHandleFor; private buttonHandleFor; private listHandleFor; private groupHandleFor; private labelHandleFor; private scrollHandleFor; private spinHandleFor; private editHandleFor; } /** * Successors after `legacyDrawing` in CT_Worksheet (drawing successors minus self). * Citation: sml CT_Worksheet sequence. */ export declare const LEGACY_DRAWING_SUCCESSORS: ReadonlyArray; /** * Index to insert modeled `` among after-sheetData siblings. * @private */ export declare function findLegacyDrawingInsertIndex(afterSheetDataLocals: ReadonlyArray): number; /** * Serialize worksheet legacyDrawing element. * @private */ export declare function serializeLegacyDrawingElementXml(relationshipId: string): string; /** * Visibility and size chrome extracted from a VML note shape. * @private */ export interface NoteShapeInfo { /** Whether the note balloon is visible (not `visibility:hidden`). */ readonly isVisible: boolean; /** Optional width in EMUs when recoverable from style or Anchor. */ readonly widthEmu?: number; /** Optional height in EMUs when recoverable from style or Anchor. */ readonly heightEmu?: number; } export {};