{"version":3,"file":"han-excel.cjs","sources":["../src/utils/EventEmitter.ts","../src/types/compat.types.ts","../src/types/core.types.ts","../src/core/Worksheet.ts","../src/types/builder.types.ts","../src/core/ExcelBuilder.ts","../src/types/reader.types.ts","../src/core/ExcelReader.ts","../src/styles/StyleBuilder.ts","../src/types/cell.types.ts","../src/types/worksheet.types.ts","../src/types/style.types.ts"],"sourcesContent":["/**\r\n * Simple EventEmitter implementation\r\n */\r\n\r\n/**\r\n * Event listener function type\r\n */\r\nexport type EventListener<T = any> = (event: T) => void | Promise<void>;\r\n\r\n/**\r\n * Event listener options\r\n */\r\nexport interface EventListenerOptions {\r\n  /** Whether to execute the listener only once */\r\n  once?: boolean;\r\n  /** Whether to execute the listener asynchronously */\r\n  async?: boolean;\r\n  /** Priority of the listener (higher = executed first) */\r\n  priority?: number;\r\n  /** Whether to stop event propagation */\r\n  stopPropagation?: boolean;\r\n}\r\n\r\n/**\r\n * Event listener registration\r\n */\r\nexport interface EventListenerRegistration {\r\n  /** Event type */\r\n  type: string;\r\n  /** Listener function */\r\n  listener: EventListener;\r\n  /** Listener options */\r\n  options: EventListenerOptions;\r\n  /** Registration ID */\r\n  id: string;\r\n  /** Whether the listener is active */\r\n  active: boolean;\r\n  /** Registration timestamp */\r\n  timestamp: Date;\r\n}\r\n\r\n/**\r\n * EventEmitter class for handling events\r\n */\r\nexport class EventEmitter {\r\n  private listeners: Map<string, EventListenerRegistration[]> = new Map();\r\n\r\n  /**\r\n   * Add an event listener\r\n   */\r\n  on<T = any>(type: string, listener: EventListener<T>, options: EventListenerOptions = {}): string {\r\n    if (!this.listeners.has(type)) {\r\n      this.listeners.set(type, []);\r\n    }\r\n\r\n    const registration: EventListenerRegistration = {\r\n      type,\r\n      listener: listener as EventListener,\r\n      options: {\r\n        once: false,\r\n        async: false,\r\n        priority: 0,\r\n        stopPropagation: false,\r\n        ...options\r\n      },\r\n      id: this.generateId(),\r\n      active: true,\r\n      timestamp: new Date()\r\n    };\r\n\r\n    this.listeners.get(type)!.push(registration);\r\n    \r\n    // Sort by priority (higher priority first)\r\n    this.listeners.get(type)!.sort((a, b) => (b.options.priority || 0) - (a.options.priority || 0));\r\n\r\n    return registration.id;\r\n  }\r\n\r\n  /**\r\n   * Add a one-time event listener\r\n   */\r\n  once<T = any>(type: string, listener: EventListener<T>, options: EventListenerOptions = {}): string {\r\n    return this.on(type, listener, { ...options, once: true });\r\n  }\r\n\r\n  /**\r\n   * Remove an event listener\r\n   */\r\n  off(type: string, listenerId: string): boolean {\r\n    const listeners = this.listeners.get(type);\r\n    if (!listeners) {\r\n      return false;\r\n    }\r\n\r\n    const index = listeners.findIndex(reg => reg.id === listenerId);\r\n    if (index === -1) {\r\n      return false;\r\n    }\r\n\r\n    listeners.splice(index, 1);\r\n    return true;\r\n  }\r\n\r\n  /**\r\n   * Remove all listeners for an event type\r\n   */\r\n  offAll(type: string): number {\r\n    const listeners = this.listeners.get(type);\r\n    if (!listeners) {\r\n      return 0;\r\n    }\r\n\r\n    const count = listeners.length;\r\n    this.listeners.delete(type);\r\n    return count;\r\n  }\r\n\r\n  /**\r\n   * Emit an event\r\n   */\r\n  async emit<T = any>(event: T): Promise<void> {\r\n    const type = (event as any).type || 'default';\r\n    const listeners = this.listeners.get(type);\r\n    \r\n    if (!listeners || listeners.length === 0) {\r\n      return;\r\n    }\r\n\r\n    const activeListeners = listeners.filter(reg => reg.active);\r\n    \r\n    for (const registration of activeListeners) {\r\n      try {\r\n        if (registration.options.once) {\r\n          registration.active = false;\r\n        }\r\n\r\n        if (registration.options.async) {\r\n          await registration.listener(event);\r\n        } else {\r\n          registration.listener(event);\r\n        }\r\n\r\n        if (registration.options.stopPropagation) {\r\n          break;\r\n        }\r\n      } catch (error) {\r\n        console.error(`Error in event listener for ${type}:`, error);\r\n      }\r\n    }\r\n\r\n    // Clean up inactive listeners\r\n    this.cleanupInactiveListeners(type);\r\n  }\r\n\r\n  /**\r\n   * Emit an event synchronously\r\n   */\r\n  emitSync<T = any>(event: T): void {\r\n    const type = (event as any).type || 'default';\r\n    const listeners = this.listeners.get(type);\r\n    \r\n    if (!listeners || listeners.length === 0) {\r\n      return;\r\n    }\r\n\r\n    const activeListeners = listeners.filter(reg => reg.active);\r\n    \r\n    for (const registration of activeListeners) {\r\n      try {\r\n        if (registration.options.once) {\r\n          registration.active = false;\r\n        }\r\n\r\n        registration.listener(event);\r\n\r\n        if (registration.options.stopPropagation) {\r\n          break;\r\n        }\r\n      } catch (error) {\r\n        console.error(`Error in event listener for ${type}:`, error);\r\n      }\r\n    }\r\n\r\n    // Clean up inactive listeners\r\n    this.cleanupInactiveListeners(type);\r\n  }\r\n\r\n  /**\r\n   * Clear all listeners\r\n   */\r\n  clear(): void {\r\n    this.listeners.clear();\r\n  }\r\n\r\n  /**\r\n   * Get listeners for an event type\r\n   */\r\n  getListeners(type: string): EventListenerRegistration[] {\r\n    return this.listeners.get(type) || [];\r\n  }\r\n\r\n  /**\r\n   * Get listener count for an event type\r\n   */\r\n  getListenerCount(type: string): number {\r\n    return this.listeners.get(type)?.length || 0;\r\n  }\r\n\r\n  /**\r\n   * Get all registered event types\r\n   */\r\n  getEventTypes(): string[] {\r\n    return Array.from(this.listeners.keys());\r\n  }\r\n\r\n  // Private methods\r\n\r\n  private generateId(): string {\r\n    return Math.random().toString(36).substr(2, 9);\r\n  }\r\n\r\n  private cleanupInactiveListeners(type: string): void {\r\n    const listeners = this.listeners.get(type);\r\n    if (listeners) {\r\n      const activeListeners = listeners.filter(reg => reg.active);\r\n      if (activeListeners.length !== listeners.length) {\r\n        this.listeners.set(type, activeListeners);\r\n      }\r\n    }\r\n  }\r\n}\r\n\r\n","/**\r\n * Tipos de compatibilidad para mantener la misma API pública\r\n * Estos son aliases de los tipos compartidos de han-documents-core\r\n */\r\n\r\nimport { \r\n  IDocumentMetadata, \r\n  IExcelMetadata,\r\n  Result as CoreResult,\r\n  ISuccessResult as CoreISuccessResult,\r\n  IErrorResult as CoreIErrorResult,\r\n  IError as CoreIError,\r\n  ErrorType as CoreErrorType,\r\n  Color as CoreColor\r\n} from '@hannndler/core';\r\n\r\n/**\r\n * Alias para compatibilidad con código existente\r\n * IWorkbookMetadata ahora es IDocumentMetadata\r\n */\r\nexport type IWorkbookMetadata = IExcelMetadata;\r\n\r\n/**\r\n * Re-exportar Result como alias para compatibilidad\r\n */\r\nexport type Result<T = unknown> = CoreResult<T>;\r\nexport type ISuccessResult<T = unknown> = CoreISuccessResult<T>;\r\nexport type IErrorResult = CoreIErrorResult;\r\nexport type IError = CoreIError;\r\n\r\n/**\r\n * Re-exportar ErrorType con tipos adicionales específicos de Excel\r\n */\r\nexport enum ErrorType {\r\n  VALIDATION_ERROR = 'VALIDATION_ERROR',\r\n  BUILD_ERROR = 'BUILD_ERROR',\r\n  STYLE_ERROR = 'STYLE_ERROR',\r\n  FILE_ERROR = 'FILE_ERROR',\r\n  TYPE_ERROR = 'TYPE_ERROR',\r\n  CONFIG_ERROR = 'CONFIG_ERROR',\r\n  WORKSHEET_ERROR = 'WORKSHEET_ERROR',\r\n  CELL_ERROR = 'CELL_ERROR'\r\n}\r\n\r\n/**\r\n * Re-exportar Color como alias\r\n */\r\nexport type Color = CoreColor;\r\n\r\n","/**\r\n * Core type definitions for Han Excel Builder\r\n * Adaptado para usar tipos compartidos de han-documents-core\r\n */\r\n\r\nimport { CellValue } from 'exceljs';\r\nimport { Color } from '@hannndler/core';\r\nimport { IWorkbookMetadata, Result, ErrorType, ISuccessResult, IErrorResult } from './compat.types';\r\n\r\n// Re-export tipos compartidos\r\nexport type { Color, Result, IWorkbookMetadata, ISuccessResult, IErrorResult } from './compat.types';\r\nexport { ErrorType } from './compat.types';\r\n\r\n/**\r\n * Supported cell data types\r\n */\r\nexport enum CellType {\r\n  STRING = 'string',\r\n  NUMBER = 'number',\r\n  BOOLEAN = 'boolean',\r\n  DATE = 'date',\r\n  PERCENTAGE = 'percentage',\r\n  CURRENCY = 'currency',\r\n  LINK = 'link',\r\n  FORMULA = 'formula'\r\n}\r\n\r\n/**\r\n * Number format options\r\n */\r\nexport enum NumberFormat {\r\n  GENERAL = 'General',\r\n  NUMBER = '#,##0',\r\n  NUMBER_DECIMALS = '#,##0.00',\r\n  CURRENCY = '$#,##0.00',\r\n  CURRENCY_INTEGER = '$#,##0',\r\n  PERCENTAGE = '0%',\r\n  PERCENTAGE_DECIMALS = '0.00%',\r\n  DATE = 'dd/mm/yyyy',\r\n  DATE_TIME = 'dd/mm/yyyy hh:mm',\r\n  TIME = 'hh:mm:ss',\r\n  CUSTOM = 'custom'\r\n}\r\n\r\n/**\r\n * Horizontal alignment options\r\n */\r\nexport enum HorizontalAlignment {\r\n  LEFT = 'left',\r\n  CENTER = 'center',\r\n  RIGHT = 'right',\r\n  FILL = 'fill',\r\n  JUSTIFY = 'justify',\r\n  CENTER_CONTINUOUS = 'centerContinuous',\r\n  DISTRIBUTED = 'distributed'\r\n}\r\n\r\n/**\r\n * Vertical alignment options\r\n */\r\nexport enum VerticalAlignment {\r\n  TOP = 'top',\r\n  MIDDLE = 'middle',\r\n  BOTTOM = 'bottom',\r\n  DISTRIBUTED = 'distributed',\r\n  JUSTIFY = 'justify'\r\n}\r\n\r\n/**\r\n * Border style options\r\n */\r\nexport enum BorderStyle {\r\n  THIN = 'thin',\r\n  MEDIUM = 'medium',\r\n  THICK = 'thick',\r\n  DOTTED = 'dotted',\r\n  DASHED = 'dashed',\r\n  DOUBLE = 'double',\r\n  HAIR = 'hair',\r\n  MEDIUM_DASHED = 'mediumDashed',\r\n  DASH_DOT = 'dashDot',\r\n  MEDIUM_DASH_DOT = 'mediumDashDot',\r\n  DASH_DOT_DOT = 'dashDotDot',\r\n  MEDIUM_DASH_DOT_DOT = 'mediumDashDotDot',\r\n  SLANT_DASH_DOT = 'slantDashDot'\r\n}\r\n\r\n/**\r\n * Font style options\r\n */\r\nexport enum FontStyle {\r\n  NORMAL = 'normal',\r\n  BOLD = 'bold',\r\n  ITALIC = 'italic',\r\n  BOLD_ITALIC = 'bold italic'\r\n}\r\n\r\n/**\r\n * Base cell properties interface\r\n */\r\nexport interface IBaseCell {\r\n  /** Unique identifier for the cell */\r\n  key: string;\r\n  /** Cell data type */\r\n  type: CellType;\r\n  /** Cell value */\r\n  value: CellValue;\r\n  /** Optional cell reference (e.g., A1, B2) */\r\n  reference?: string;\r\n  /** Whether to merge this cell with others */\r\n  mergeCell?: boolean;\r\n  /** Number of columns to merge (if mergeCell is true) */\r\n  mergeTo?: number;\r\n  /** Row height for this cell */\r\n  rowHeight?: number;\r\n  /** Column width for this cell */\r\n  colWidth?: number;\r\n  /** Whether to move to next row after this cell */\r\n  jump?: boolean;\r\n  /**\r\n   * Copy merge configuration from another cell in the same data structure.\r\n   * Example: { fromKey: 'otherColumnKey' } will copy the merge settings\r\n   * from the cell with key 'otherColumnKey' into this cell when rendering.\r\n   */\r\n  mergeAs?: {\r\n    /** Key of the source cell to copy merge from */\r\n    fromKey?: string;\r\n    /** Number of additional rows to merge vertically (excludes current row). */\r\n    rows?: number;\r\n    /**\r\n     * Tipo de merge a copiar: 'horizontal' copiará `mergeTo` (merge en la misma fila),\r\n     * 'vertical' copiará el span vertical calculado por `calculateRowSpan`.\r\n     * Si no se especifica, el comportamiento intenta inferir (vertical preferido).\r\n     */\r\n    type?: 'horizontal' | 'vertical';\r\n  };\r\n  /** Hyperlink URL */\r\n  link?: string;\r\n  /** Text mask for hyperlink (displayed text when link is present) */\r\n  mask?: string;\r\n  /** Excel formula */\r\n  formula?: string;\r\n  /** Number format for numeric cells */\r\n  numberFormat?: NumberFormat | string;\r\n  /** Custom number format string */\r\n  customNumberFormat?: string;\r\n  /** Whether the cell is protected */\r\n  protected?: boolean;\r\n  /** Whether the cell is hidden */\r\n  hidden?: boolean;\r\n  /** Cell comment */\r\n  comment?: string;\r\n  /** Data validation rules */\r\n  validation?: IDataValidation;\r\n  /** Optional styles for the cell */\r\n  styles?: import('./style.types').IStyle;\r\n  /** Predefined style name (references a style added via addCellStyle) */\r\n  styleName?: string;\r\n  /** Legacy children cells */\r\n  childrens?: IBaseCell[];\r\n  /** Modern children cells */\r\n  children?: IBaseCell[];\r\n}\r\n\r\n/**\r\n * Data validation interface\r\n */\r\nexport interface IDataValidation {\r\n  /** Validation type */\r\n  type: 'list' | 'whole' | 'decimal' | 'textLength' | 'date' | 'time' | 'custom';\r\n  /** Validation operator */\r\n  operator?: 'between' | 'notBetween' | 'equal' | 'notEqual' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual';\r\n  /** List values for dropdowns (used when type is 'list') */\r\n  values?: Array<string | number>;\r\n  /** Validation formula or values */\r\n  formula1?: string | number | Date;\r\n  /** Second validation formula or value (for between/notBetween) */\r\n  formula2?: string | number | Date;\r\n  /** Whether to show error message */\r\n  showErrorMessage?: boolean;\r\n  /** Error message text */\r\n  errorMessage?: string;\r\n  /** Whether to show input message */\r\n  showInputMessage?: boolean;\r\n  /** Input message text */\r\n  inputMessage?: string;\r\n  /** Whether to allow blank values */\r\n  allowBlank?: boolean;\r\n}\r\n\r\n","/**\r\n * Worksheet - Representa una hoja de cálculo dentro del builder\r\n * Adaptado para usar tipos compartidos de han-documents-core\r\n */\r\n\r\nimport * as ExcelJS from 'exceljs';\r\nimport { Result, success, error, ErrorType as CoreErrorType } from '@hannndler/core';\r\nimport {\r\n  IWorksheet,\r\n  IWorksheetConfig,\r\n  ITable,\r\n  IWorksheetImage,\r\n  IExcelTable,\r\n  IPivotTable,\r\n  ISlicer,\r\n  IWatermark,\r\n  IDataConnection\r\n} from '../types/worksheet.types';\r\nimport {\r\n  IDataCell,\r\n  IHeaderCell,\r\n  IFooterCell,\r\n  ICellRange,\r\n  IRichTextRun\r\n} from '../types/cell.types';\r\nimport { IBuildOptions } from '../types/builder.types';\r\nimport { ErrorType } from '../types/compat.types';\r\nimport { CellType, IDataValidation } from '../types/core.types';\r\nimport { IConditionalFormat } from '../types/style.types';\r\n\r\n/**\r\n * Worksheet - Representa una hoja de cálculo dentro del builder\r\n *\r\n2 * Soporta headers, subheaders anidados, rows, footers, children y estilos por celda.\r\n */\r\nexport class Worksheet implements IWorksheet {\r\n  public config: IWorksheetConfig;\r\n  public tables: ITable[] = [];\r\n  public currentRow = 1;\r\n  public currentCol = 1;\r\n  public headerPointers: Map<string, any> = new Map();\r\n  public isBuilt = false;\r\n\r\n  // Estructuras temporales para la tabla actual\r\n  private headers: IHeaderCell[] = [];\r\n  private subHeaders: IHeaderCell[] = [];\r\n  private body: IDataCell[] = [];\r\n  private footers: IFooterCell[] = [];\r\n\r\n  // Features adicionales\r\n  private images: IWorksheetImage[] = [];\r\n  private rowGroups: Array<{ start: number; end: number; collapsed?: boolean }> = [];\r\n  private columnGroups: Array<{ start: number; end: number; collapsed?: boolean }> = [];\r\n  private namedRanges: Array<{ name: string; range: string; scope?: string }> = [];\r\n  private excelTables: IExcelTable[] = [];\r\n  private hiddenRows: Set<number> = new Set();\r\n  private hiddenColumns: Set<number> = new Set();\r\n  private pivotTables: IPivotTable[] = [];\r\n  private slicers: ISlicer[] = [];\r\n  private watermarks: IWatermark[] = [];\r\n  private dataConnections: IDataConnection[] = [];\r\n\r\n  // Estilos y tema del workbook (no se guardan en el objeto de ExcelJS)\r\n  private customStyles?: Record<string, import('../types/style.types').IStyle>;\r\n  private theme?: import('../types/builder.types').IWorkbookTheme;\r\n\r\n  constructor(config: IWorksheetConfig) {\r\n    this.config = config;\r\n  }\r\n\r\n  /**\r\n   * Agrega un header principal\r\n   */\r\n  addHeader(header: IHeaderCell): this {\r\n    this.headers.push(header);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega subheaders (ahora soporta anidación)\r\n   */\r\n  addSubHeaders(subHeaders: IHeaderCell[]): this {\r\n    this.subHeaders.push(...subHeaders);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega una fila de datos (puede ser jerárquica con childrens)\r\n   */\r\n  addRow(row: IDataCell[] | IDataCell): this {\r\n    if (Array.isArray(row)) {\r\n      this.body.push(...row);\r\n    } else {\r\n      this.body.push(row);\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega un footer o varios\r\n   */\r\n  addFooter(footer: IFooterCell[] | IFooterCell): this {\r\n    if (Array.isArray(footer)) {\r\n      this.footers.push(...footer);\r\n    } else {\r\n      this.footers.push(footer);\r\n    }\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Crea una nueva tabla y la agrega al worksheet\r\n   */\r\n  addTable(tableConfig: Partial<ITable> = {}): this {\r\n    const table: ITable = {\r\n      name: tableConfig.name || `Table_${this.tables.length + 1}`,\r\n      headers: tableConfig.headers || [],\r\n      subHeaders: tableConfig.subHeaders || [],\r\n      body: tableConfig.body || [],\r\n      footers: tableConfig.footers || [],\r\n      showBorders: tableConfig.showBorders !== false,\r\n      showStripes: tableConfig.showStripes !== false,\r\n      style: tableConfig.style || 'TableStyleLight1',\r\n      ...tableConfig\r\n    };\r\n\r\n    this.tables.push(table);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Finaliza la tabla actual agregando todos los elementos temporales a la última tabla\r\n   */\r\n  finalizeTable(): this {\r\n    if (this.tables.length === 0) {\r\n      // Si no hay tablas, crear una nueva con los datos temporales\r\n      this.addTable();\r\n    }\r\n\r\n    const currentTable = this.tables[this.tables.length - 1];\r\n    if (!currentTable) {\r\n      throw new Error('No se pudo obtener la tabla actual');\r\n    }\r\n\r\n    // Agregar headers, subheaders, body y footers a la tabla actual\r\n    if (this.headers.length > 0) {\r\n      currentTable.headers = [...(currentTable.headers || []), ...this.headers];\r\n    }\r\n\r\n    if (this.subHeaders.length > 0) {\r\n      currentTable.subHeaders = [...(currentTable.subHeaders || []), ...this.subHeaders];\r\n    }\r\n\r\n    if (this.body.length > 0) {\r\n      currentTable.body = [...(currentTable.body || []), ...this.body];\r\n    }\r\n\r\n    if (this.footers.length > 0) {\r\n      currentTable.footers = [...(currentTable.footers || []), ...this.footers];\r\n    }\r\n\r\n    // Limpiar las estructuras temporales\r\n    this.headers = [];\r\n    this.subHeaders = [];\r\n    this.body = [];\r\n    this.footers = [];\r\n\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Obtiene una tabla por nombre\r\n   */\r\n  getTable(name: string): ITable | undefined {\r\n    return this.tables.find(table => table.name === name);\r\n  }\r\n\r\n  /**\r\n   * Agrega una imagen al worksheet\r\n   */\r\n  addImage(image: IWorksheetImage): this {\r\n    this.images.push(image);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrupa filas (crea esquema colapsable)\r\n   */\r\n  groupRows(startRow: number, endRow: number, collapsed: boolean = false): this {\r\n    this.rowGroups.push({ start: startRow, end: endRow, collapsed });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrupa columnas (crea esquema colapsable)\r\n   */\r\n  groupColumns(startCol: number, endCol: number, collapsed: boolean = false): this {\r\n    this.columnGroups.push({ start: startCol, end: endCol, collapsed });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega un rango con nombre\r\n   */\r\n  addNamedRange(name: string, range: string | ICellRange, scope?: string): this {\r\n    let rangeString: string;\r\n\r\n    if (typeof range === 'string') {\r\n      rangeString = range;\r\n    } else {\r\n      // Convertir ICellRange a string (e.g., \"A1:B10\")\r\n      const startRef = range.start.reference || `${this.numberToColumnLetter(range.start.col)}${range.start.row}`;\r\n      const endRef = range.end.reference || `${this.numberToColumnLetter(range.end.col)}${range.end.row}`;\r\n      rangeString = `${startRef}:${endRef}`;\r\n    }\r\n\r\n    const namedRange: { name: string; range: string; scope?: string } = { name, range: rangeString };\r\n    if (scope !== undefined) {\r\n      namedRange.scope = scope;\r\n    }\r\n    this.namedRanges.push(namedRange);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega una tabla estructurada de Excel\r\n   */\r\n  addExcelTable(table: IExcelTable): this {\r\n    this.excelTables.push(table);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Oculta filas\r\n   */\r\n  hideRows(rows: number | number[]): this {\r\n    const rowsArray = Array.isArray(rows) ? rows : [rows];\r\n    rowsArray.forEach(row => this.hiddenRows.add(row));\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Muestra filas\r\n   */\r\n  showRows(rows: number | number[]): this {\r\n    const rowsArray = Array.isArray(rows) ? rows : [rows];\r\n    rowsArray.forEach(row => this.hiddenRows.delete(row));\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Oculta columnas\r\n   */\r\n  hideColumns(columns: number | string | (number | string)[]): this {\r\n    const columnsArray = Array.isArray(columns) ? columns : [columns];\r\n    columnsArray.forEach(col => {\r\n      const colNum = typeof col === 'string' ? this.columnLetterToNumber(col) : col;\r\n      this.hiddenColumns.add(colNum);\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Muestra columnas\r\n   */\r\n  showColumns(columns: number | string | (number | string)[]): this {\r\n    const columnsArray = Array.isArray(columns) ? columns : [columns];\r\n    columnsArray.forEach(col => {\r\n      const colNum = typeof col === 'string' ? this.columnLetterToNumber(col) : col;\r\n      this.hiddenColumns.delete(colNum);\r\n    });\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega una tabla dinámica (pivot table)\r\n   */\r\n  addPivotTable(pivotTable: IPivotTable): this {\r\n    this.pivotTables.push(pivotTable);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega un slicer a una tabla o tabla dinámica\r\n   */\r\n  addSlicer(slicer: ISlicer): this {\r\n    this.slicers.push(slicer);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega una marca de agua al worksheet\r\n   */\r\n  addWatermark(watermark: IWatermark): this {\r\n    this.watermarks.push(watermark);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Agrega una conexión de datos\r\n   */\r\n  addDataConnection(connection: IDataConnection): this {\r\n    this.dataConnections.push(connection);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Construye la hoja en el workbook de ExcelJS\r\n   */\r\n  async build(workbook: ExcelJS.Workbook, _options: IBuildOptions = {}): Promise<void> {\r\n    const ws = workbook.addWorksheet(this.config.name, {\r\n      properties: {\r\n        defaultRowHeight: this.config.defaultRowHeight || 20,\r\n        tabColor: this.config.tabColor as any\r\n      },\r\n      pageSetup: this.config.pageSetup as any\r\n    });\r\n\r\n    // Guardar estilos predefinidos y tema en la instancia de Worksheet (no en el objeto de ExcelJS)\r\n    this.customStyles = (workbook as any).__customStyles;\r\n    this.theme = (workbook as any).__theme;\r\n\r\n    let rowPointer = 1;\r\n\r\n    // Si hay tablas definidas, construir cada tabla\r\n    if (this.tables.length > 0) {\r\n      let tableStartRow = rowPointer;\r\n      for (let i = 0; i < this.tables.length; i++) {\r\n        const table = this.tables[i];\r\n        if (table) {\r\n          tableStartRow = rowPointer;\r\n          rowPointer = await this.buildTable(ws, table, rowPointer, i > 0);\r\n\r\n          // Aplicar filtro automático a la tabla si está configurado\r\n          if (table.autoFilter && rowPointer > tableStartRow) {\r\n            this.applyAutoFilter(ws, table, tableStartRow, rowPointer - 1);\r\n          }\r\n        }\r\n      }\r\n    } else {\r\n      // Construcción tradicional para compatibilidad hacia atrás\r\n      rowPointer = await this.buildLegacyContent(ws, rowPointer);\r\n    }\r\n\r\n    // Aplicar filtro automático a nivel de worksheet si está configurado\r\n    if (this.config.autoFilter?.enabled) {\r\n      this.applyWorksheetAutoFilter(ws, rowPointer);\r\n    }\r\n\r\n    // Aplicar views (freeze panes, split panes, sheet views)\r\n    this.applyViews(ws);\r\n\r\n    // Aplicar protección si está configurada\r\n    if (this.config.protected) {\r\n      ws.protect(this.config.protectionPassword || '', {\r\n        selectLockedCells: false,\r\n        selectUnlockedCells: true,\r\n        formatCells: false,\r\n        formatColumns: false,\r\n        formatRows: false,\r\n        insertColumns: false,\r\n        insertRows: false,\r\n        insertHyperlinks: false,\r\n        deleteColumns: false,\r\n        deleteRows: false,\r\n        sort: false,\r\n        autoFilter: false,\r\n        pivotTables: false\r\n      });\r\n    }\r\n\r\n    // Aplicar imágenes\r\n    for (const image of this.images) {\r\n      await this.applyImage(ws, image);\r\n    }\r\n\r\n    // Aplicar agrupación de filas\r\n    for (const group of this.rowGroups) {\r\n      this.applyRowGrouping(ws, group.start, group.end, group.collapsed);\r\n    }\r\n\r\n    // Aplicar agrupación de columnas\r\n    for (const group of this.columnGroups) {\r\n      this.applyColumnGrouping(ws, group.start, group.end, group.collapsed);\r\n    }\r\n\r\n    // Aplicar rangos con nombre\r\n    for (const namedRange of this.namedRanges) {\r\n      // ExcelJS addDefinedName - solo acepta name y range (scope se maneja de otra manera)\r\n      workbook.definedNames.add(namedRange.name, namedRange.range);\r\n    }\r\n\r\n    // Aplicar tablas estructuradas de Excel\r\n    for (const excelTable of this.excelTables) {\r\n      this.applyExcelTable(ws, excelTable);\r\n    }\r\n\r\n    // Aplicar configuración de impresión avanzada\r\n    this.applyAdvancedPrintSettings(ws);\r\n\r\n    // Aplicar filas y columnas ocultas\r\n    this.applyHiddenRowsColumns(ws);\r\n\r\n    // Aplicar tablas dinámicas\r\n    for (const pivotTable of this.pivotTables) {\r\n      await this.applyPivotTable(ws, pivotTable);\r\n    }\r\n\r\n    // Aplicar slicers\r\n    for (const slicer of this.slicers) {\r\n      await this.applySlicer(ws, slicer);\r\n    }\r\n\r\n    // Aplicar marcas de agua\r\n    for (const watermark of this.watermarks) {\r\n      await this.applyWatermark(ws, watermark);\r\n    }\r\n\r\n    // Aplicar conexiones de datos\r\n    for (const connection of this.dataConnections) {\r\n      await this.applyDataConnection(workbook, connection);\r\n    }\r\n\r\n    this.isBuilt = true;\r\n  }\r\n\r\n  /**\r\n   * Construye una tabla individual en el worksheet\r\n   */\r\n  private async buildTable(ws: ExcelJS.Worksheet, table: ITable, startRow: number, addSpacing: boolean = false): Promise<number> {\r\n    let rowPointer = startRow;\r\n\r\n    // Agregar espacio entre tablas si no es la primera\r\n    if (addSpacing) {\r\n      rowPointer += 2; // 2 filas de espacio\r\n    }\r\n\r\n    // Headers principales de la tabla\r\n    if (table.headers && table.headers.length > 0) {\r\n      for (const header of table.headers) {\r\n        const cell = ws.getRow(rowPointer).getCell(1);\r\n\r\n        // Aplicar rich text si existe\r\n        if ((header as any).richText && (header as any).richText.length > 0) {\r\n          cell.value = {\r\n            richText: (header as any).richText.map((run: IRichTextRun) => ({\r\n              text: run.text,\r\n              font: run.font ? { name: run.font } : undefined,\r\n              size: run.size,\r\n              color: run.color ? this.convertColorToExcelJS(run.color) : undefined,\r\n              bold: run.bold,\r\n              italic: run.italic,\r\n              underline: run.underline,\r\n              strike: run.strikethrough\r\n            })).filter((run: any) => run.text !== undefined)\r\n          } as any;\r\n        } else {\r\n          cell.value = this.processCellValue(header);\r\n        }\r\n\r\n        if (header.mergeCell) {\r\n          const maxCols = this.calculateTableMaxColumns(table);\r\n          ws.mergeCells(rowPointer, 1, rowPointer, maxCols);\r\n        }\r\n        if (header.styles) {\r\n          ws.getRow(rowPointer).eachCell((cell: any) => {\r\n            cell.style = this.convertStyle(header.styles);\r\n          });\r\n        }\r\n\r\n        // Aplicar protección de celda si existe\r\n        if ((header as any).cellProtection) {\r\n          cell.protection = {\r\n            locked: (header as any).cellProtection.locked ?? true,\r\n            hidden: (header as any).cellProtection.hidden ?? false\r\n          };\r\n        } else if (header.protected !== undefined) {\r\n          cell.protection = {\r\n            locked: header.protected,\r\n            hidden: false\r\n          };\r\n        }\r\n\r\n        // Aplicar dimensiones de celda\r\n        this.applyCellDimensions(ws, rowPointer, 1, header);\r\n        // Aplicar comentario si existe\r\n        if (header.comment) {\r\n          this.applyCellComment(ws, rowPointer, 1, header.comment);\r\n        }\r\n        // Aplicar validación de datos si existe\r\n        if (header.validation) {\r\n          this.applyDataValidation(ws, rowPointer, 1, header.validation);\r\n        }\r\n        // Aplicar formato condicional si existe\r\n        if (header.styles?.conditionalFormats) {\r\n          this.applyConditionalFormatting(ws, rowPointer, 1, header.styles.conditionalFormats);\r\n        }\r\n        rowPointer++;\r\n      }\r\n    }\r\n\r\n    // SubHeaders con soporte para anidación\r\n    if (table.subHeaders && table.subHeaders.length > 0) {\r\n      rowPointer = this.buildNestedHeaders(ws, rowPointer, table.subHeaders);\r\n    }\r\n\r\n    // Body (soporta children)\r\n    if (table.body && table.body.length > 0) {\r\n      for (let i = 0; i < table.body.length; i++) {\r\n        const row = table.body[i];\r\n        rowPointer = this.addDataRowRecursive(ws, rowPointer, row, table.body, i, table.subHeaders);\r\n      }\r\n    }\r\n\r\n    // Footers\r\n    if (table.footers && table.footers.length > 0) {\r\n      for (const footer of table.footers) {\r\n        rowPointer = this.addFooterRow(ws, rowPointer, footer, table.subHeaders);\r\n      }\r\n    }\r\n\r\n    // Aplicar estilo de tabla si está configurado\r\n    if (table.showBorders || table.showStripes) {\r\n      this.applyTableStyle(ws, table, startRow, rowPointer - 1);\r\n    }\r\n\r\n    // Nota: El filtro automático se aplica en el método build() después de construir todas las tablas\r\n    // para tener el rowPointer final correcto\r\n\r\n    return rowPointer;\r\n  }\r\n\r\n  /**\r\n   * Construcción tradicional para compatibilidad hacia atrás\r\n   */\r\n  private async buildLegacyContent(ws: ExcelJS.Worksheet, startRow: number): Promise<number> {\r\n    let rowPointer = startRow;\r\n\r\n    // Headers principales\r\n    if (this.headers.length > 0) {\r\n      this.headers.forEach(header => {\r\n        ws.addRow([this.processCellValue(header)]);\r\n        if (header.mergeCell) {\r\n          ws.mergeCells(rowPointer, 1, rowPointer, (this.getMaxColumns() || 1));\r\n        }\r\n        if (header.styles) {\r\n          ws.getRow(rowPointer).eachCell((cell: any) => {\r\n            cell.style = this.convertStyle(header.styles);\r\n          });\r\n        }\r\n        // Aplicar dimensiones de celda\r\n        this.applyCellDimensions(ws, rowPointer, 1, header);\r\n        // Aplicar comentario si existe\r\n        if (header.comment) {\r\n          this.applyCellComment(ws, rowPointer, 1, header.comment);\r\n        }\r\n        // Aplicar validación de datos si existe\r\n        if (header.validation) {\r\n          this.applyDataValidation(ws, rowPointer, 1, header.validation);\r\n        }\r\n        // Aplicar formato condicional si existe\r\n        if (header.styles?.conditionalFormats) {\r\n          this.applyConditionalFormatting(ws, rowPointer, 1, header.styles.conditionalFormats);\r\n        }\r\n        rowPointer++;\r\n      });\r\n    }\r\n\r\n    // SubHeaders con soporte para anidación\r\n    if (this.subHeaders.length > 0) {\r\n      rowPointer = this.buildNestedHeaders(ws, rowPointer, this.subHeaders);\r\n    }\r\n\r\n    // Body (soporta children)\r\n    for (let i = 0; i < this.body.length; i++) {\r\n      const row = this.body[i];\r\n      rowPointer = this.addDataRowRecursive(ws, rowPointer, row, this.body, i, this.subHeaders);\r\n    }\r\n\r\n    // Footers\r\n    if (this.footers.length > 0) {\r\n      for (const footer of this.footers) {\r\n        rowPointer = this.addFooterRow(ws, rowPointer, footer, this.subHeaders);\r\n      }\r\n    }\r\n\r\n    return rowPointer;\r\n  }\r\n\r\n  /**\r\n   * Calcula el número máximo de columnas para una tabla\r\n   */\r\n  private calculateTableMaxColumns(table: ITable): number {\r\n    let maxCols = 0;\r\n\r\n    if (table.subHeaders && table.subHeaders.length > 0) {\r\n      for (const header of table.subHeaders) {\r\n        maxCols += this.calculateHeaderColSpan(header);\r\n      }\r\n    }\r\n\r\n    return maxCols || 1;\r\n  }\r\n\r\n  /**\r\n   * Aplica el estilo de tabla a un rango específico\r\n   */\r\n  private applyTableStyle(ws: ExcelJS.Worksheet, table: ITable, startRow: number, endRow: number): void {\r\n    const maxCols = this.calculateTableMaxColumns(table);\r\n\r\n    // Aplicar bordes si está configurado\r\n    if (table.showBorders) {\r\n      for (let row = startRow; row <= endRow; row++) {\r\n        for (let col = 1; col <= maxCols; col++) {\r\n          const cell = ws.getRow(row).getCell(col);\r\n          if (!cell.style) cell.style = {};\r\n          if (!cell.style.border) {\r\n            cell.style.border = {\r\n              top: { style: 'thin', color: { argb: 'FF8EAADB' } },\r\n              left: { style: 'thin', color: { argb: 'FF8EAADB' } },\r\n              bottom: { style: 'thin', color: { argb: 'FF8EAADB' } },\r\n              right: { style: 'thin', color: { argb: 'FF8EAADB' } }\r\n            };\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    // Aplicar rayas alternadas si está configurado\r\n    if (table.showStripes) {\r\n      for (let row = startRow; row <= endRow; row++) {\r\n        if ((row - startRow) % 2 === 1) { // Filas impares (empezando desde 0)\r\n          for (let col = 1; col <= maxCols; col++) {\r\n            const cell = ws.getRow(row).getCell(col);\r\n            if (!cell.style) cell.style = {};\r\n            if (!cell.style.fill) {\r\n              cell.style.fill = {\r\n                type: 'pattern',\r\n                pattern: 'solid',\r\n                fgColor: { argb: 'FFF2F2F2' }\r\n              };\r\n            }\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Construye headers anidados recursivamente\r\n   * @param ws - Worksheet de ExcelJS\r\n   * @param startRow - Fila inicial\r\n   * @param headers - Array de headers a procesar\r\n   * @returns La siguiente fila disponible\r\n   */\r\n  private buildNestedHeaders(ws: ExcelJS.Worksheet, startRow: number, headers: IHeaderCell[]): number {\r\n    let currentRow = startRow;\r\n    const maxDepth = this.getMaxHeaderDepth(headers);\r\n\r\n    // Crear filas para cada nivel de profundidad\r\n    for (let depth = 0; depth < maxDepth; depth++) {\r\n      // Crear la fila primero\r\n      const row = ws.getRow(currentRow);\r\n\r\n      // Procesar cada header en este nivel\r\n      let colIndex = 1;\r\n      for (const header of headers) {\r\n        if (depth === 0) {\r\n          // Nivel principal del header\r\n          const headerInfo = this.getHeaderAtDepth(header, depth, colIndex);\r\n          const cell = row.getCell(colIndex);\r\n          cell.value = this.processCellValue(header);\r\n          if (headerInfo.style) {\r\n            cell.style = this.convertStyle(headerInfo.style);\r\n          }\r\n          // Aplicar dimensiones de celda\r\n          this.applyCellDimensions(ws, currentRow, colIndex, header);\r\n          // Aplicar comentario si existe\r\n          if (header.comment) {\r\n            this.applyCellComment(ws, currentRow, colIndex, header.comment);\r\n          }\r\n          // Aplicar validación de datos si existe\r\n          if (header.validation) {\r\n            this.applyDataValidation(ws, currentRow, colIndex, header.validation);\r\n          }\r\n          // Aplicar formato condicional si existe\r\n          if (header.styles?.conditionalFormats) {\r\n            this.applyConditionalFormatting(ws, currentRow, colIndex, header.styles.conditionalFormats);\r\n          }\r\n          colIndex += headerInfo.colSpan;\r\n        } else {\r\n          // Nivel de children - procesar todos los children directos\r\n          if (header.children && header.children.length > 0) {\r\n            for (const child of header.children) {\r\n              const cell = row.getCell(colIndex);\r\n              cell.value = this.processCellValue(child);\r\n              if (child.styles || header.styles) {\r\n                cell.style = this.convertStyle(child.styles || header.styles);\r\n              }\r\n              // Aplicar dimensiones de celda para children\r\n              this.applyCellDimensions(ws, currentRow, colIndex, child);\r\n              // Aplicar comentario si existe\r\n              if (child.comment) {\r\n                this.applyCellComment(ws, currentRow, colIndex, child.comment);\r\n              }\r\n              // Aplicar validación de datos si existe\r\n              if (child.validation) {\r\n                this.applyDataValidation(ws, currentRow, colIndex, child.validation);\r\n              }\r\n              // Aplicar formato condicional si existe\r\n              if (child.styles?.conditionalFormats) {\r\n                this.applyConditionalFormatting(ws, currentRow, colIndex, child.styles.conditionalFormats);\r\n              }\r\n              colIndex += this.calculateHeaderColSpan(child);\r\n            }\r\n          } else {\r\n            // Si no tiene children, agregar celda vacía\r\n            const cell = row.getCell(colIndex);\r\n            cell.value = null;\r\n            colIndex += 1;\r\n          }\r\n        }\r\n      }\r\n\r\n      currentRow++;\r\n    }\r\n\r\n    // Aplicar todos los merges después de crear todas las filas\r\n    this.applyAllMerges(ws, startRow, currentRow - 1, headers);\r\n\r\n    return currentRow;\r\n  }\r\n\r\n  /**\r\n   * Obtiene información del header en una profundidad específica\r\n   */\r\n  private getHeaderAtDepth(header: IHeaderCell, depth: number, startCol: number): {\r\n    value: string | null;\r\n    style: any;\r\n    colSpan: number;\r\n    mergeRange?: { start: number; end: number } | null;\r\n  } {\r\n    const colSpan = this.calculateHeaderColSpan(header);\r\n    if (depth === 0) {\r\n      // Nivel principal del header\r\n      const mergeRange = colSpan > 1 ? { start: startCol, end: startCol + colSpan - 1 } : null;\r\n      return {\r\n        value: typeof header.value === 'string' ? header.value : String(header.value || ''),\r\n        style: header.styles,\r\n        colSpan,\r\n        mergeRange: mergeRange\r\n      };\r\n    } else if (header.children && header.children.length > 0) {\r\n      // Nivel de children\r\n      const child = header.children[depth];\r\n      if (child) {\r\n        const childColSpan = this.calculateHeaderColSpan(child);\r\n        // Los children también pueden hacer merge si tienen múltiples childrens\r\n        const mergeRange = childColSpan > 1 ? { start: startCol, end: startCol + childColSpan - 1 } : null;\r\n\r\n        return {\r\n          value: typeof child.value === 'string' ? child.value : String(child.value || ''),\r\n          style: child.styles || header.styles,\r\n          colSpan: childColSpan,\r\n          mergeRange: mergeRange\r\n        };\r\n      }\r\n    }\r\n\r\n    // Celda vacía para mantener alineación\r\n    return {\r\n      value: null,\r\n      style: null,\r\n      colSpan: 1\r\n    };\r\n  }\r\n\r\n\r\n\r\n\r\n  /**\r\n   * Aplica todos los merges (horizontales y verticales) después de crear todas las filas\r\n   */\r\n  private applyAllMerges(ws: ExcelJS.Worksheet, startRow: number, endRow: number, headers: IHeaderCell[]): void {\r\n    const maxDepth = this.getMaxHeaderDepth(headers);\r\n\r\n    // Solo aplicar merges si hay más de una fila de headers\r\n    if (maxDepth <= 1) return;\r\n\r\n    // Aplicar merges inteligentes basados en la estructura\r\n    this.applySmartMerges(ws, startRow, endRow, headers);\r\n  }\r\n\r\n  /**\r\n   * Aplica merges inteligentes basados en la estructura de headers\r\n   */\r\n  private applySmartMerges(ws: ExcelJS.Worksheet, startRow: number, endRow: number, headers: IHeaderCell[]): void {\r\n    const maxDepth = this.getMaxHeaderDepth(headers);\r\n\r\n    // Solo aplicar merges si hay más de una fila de headers\r\n    if (maxDepth <= 1) return;\r\n\r\n    // Aplicar merges para cada header\r\n    let colIndex = 1;\r\n    for (const header of headers) {\r\n      this.applySmartMergesForHeader(ws, startRow, endRow, header, colIndex);\r\n      colIndex += this.calculateHeaderColSpan(header);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica merges inteligentes para un header específico\r\n   */\r\n  private applySmartMergesForHeader(ws: ExcelJS.Worksheet, startRow: number, endRow: number, header: IHeaderCell, startCol: number): void {\r\n    const headerColSpan = this.calculateHeaderColSpan(header);\r\n\r\n    if (!header.children || header.children.length === 0) {\r\n      // Si no tiene children, hacer merge vertical desde la primera fila hasta la última\r\n      ws.mergeCells(startRow, startCol, endRow, startCol + headerColSpan - 1);\r\n    } else {\r\n      // Si tiene children, aplicar merge horizontal en la primera fila\r\n      if (headerColSpan > 1) {\r\n        ws.mergeCells(startRow, startCol, startRow, startCol + headerColSpan - 1);\r\n      }\r\n\r\n      // Procesar children recursivamente\r\n      let childColIndex = startCol;\r\n      for (const child of header.children) {\r\n        this.applySmartMergesForHeader(ws, startRow + 1, endRow, child, childColIndex);\r\n        childColIndex += this.calculateHeaderColSpan(child);\r\n      }\r\n    }\r\n  }\r\n\r\n\r\n\r\n  /**\r\n   * Calcula el span de columnas para un header\r\n   */\r\n  private calculateHeaderColSpan(header: IHeaderCell): number {\r\n    if (!header.children || header.children.length === 0) {\r\n      return 1;\r\n    }\r\n\r\n    return header.children.reduce((total, child) => {\r\n      return total + this.calculateHeaderColSpan(child);\r\n    }, 0);\r\n  }\r\n\r\n  /**\r\n   * Obtiene la profundidad máxima de headers anidados\r\n   */\r\n  private getMaxHeaderDepth(headers: IHeaderCell[]): number {\r\n    let maxDepth = 1;\r\n\r\n    for (const header of headers) {\r\n      if (header.children && header.children.length > 0) {\r\n        const childDepth = this.getMaxHeaderDepth(header.children);\r\n        maxDepth = Math.max(maxDepth, childDepth + 1);\r\n      }\r\n    }\r\n\r\n    return maxDepth;\r\n  }\r\n\r\n  /**\r\n   * Obtiene el número máximo de columnas\r\n   */\r\n  private getMaxColumns(): number {\r\n    let maxCols = 0;\r\n\r\n    for (const header of this.subHeaders) {\r\n      maxCols += this.calculateHeaderColSpan(header);\r\n    }\r\n\r\n    return maxCols;\r\n  }\r\n\r\n  /**\r\n   * Valida la hoja\r\n   */\r\n  validate(): Result<boolean> {\r\n    if (this.tables.length === 0 && this.headers.length === 0 && this.body.length === 0) {\r\n      return error(CoreErrorType.VALIDATION_ERROR, 'Worksheet is empty', 'EMPTY_WORKSHEET');\r\n    }\r\n    return success(true);\r\n  }\r\n\r\n  /**\r\n   * Calcula las posiciones de columnas para los datos basándose en la estructura de subheaders.\r\n   * Soporta múltiples niveles de anidación (children dentro de children).\r\n   */\r\n  private calculateDataColumnPositions(subHeaders?: IHeaderCell[]): { [key: string]: number } {\r\n    const positions: { [key: string]: number } = {};\r\n    let currentCol = 1;\r\n\r\n    const headers = subHeaders && subHeaders.length > 0 ? subHeaders : this.subHeaders;\r\n\r\n    const collectLeafPositions = (headerList: IHeaderCell[]): void => {\r\n      for (const header of headerList) {\r\n        if (header.children && header.children.length > 0) {\r\n          // Header con children: añadir su key en la primera columna del grupo (para merge/celdas span)\r\n          const firstCol = currentCol;\r\n          if (header.key) {\r\n            positions[header.key] = firstCol;\r\n          }\r\n          if (header.value) {\r\n            positions[String(header.value)] = firstCol;\r\n          }\r\n          // Recursivamente procesar children (soporta children dentro de children)\r\n          collectLeafPositions(header.children);\r\n        } else {\r\n          // Header hoja: ocupa una columna\r\n          if (header.key) {\r\n            positions[header.key] = currentCol;\r\n          }\r\n          if (header.value) {\r\n            positions[String(header.value)] = currentCol;\r\n          }\r\n          currentCol++;\r\n        }\r\n      }\r\n    };\r\n\r\n    collectLeafPositions(headers);\r\n    return positions;\r\n  }\r\n\r\n  /**\r\n   * Agrega una fila de footer\r\n   * @returns el siguiente rowPointer disponible\r\n   */\r\n  private addFooterRow(ws: ExcelJS.Worksheet, rowPointer: number, footer: IFooterCell, contextSubHeaders?: IHeaderCell[]): number {\r\n    // Calcular las columnas basándose en la estructura de subheaders\r\n    const columnPositions = this.calculateDataColumnPositions(contextSubHeaders);\r\n\r\n    // Buscar la columna correcta para el footer\r\n    let footerColPosition: number | undefined;\r\n\r\n    // Intentar encontrar por key primero\r\n    if (footer.key && columnPositions[footer.key]) {\r\n      footerColPosition = columnPositions[footer.key];\r\n    }\r\n    // Si no se encuentra por key, intentar por header\r\n    else if (footer.header && columnPositions[footer.header]) {\r\n      footerColPosition = columnPositions[footer.header];\r\n    }\r\n\r\n    // Si no se encuentra la posición, usar columna 1 por defecto\r\n    if (footerColPosition === undefined) {\r\n      footerColPosition = 1;\r\n    }\r\n\r\n    // Escribir el footer en la columna correcta\r\n    const excelRow = ws.getRow(rowPointer);\r\n    const footerCell = excelRow.getCell(footerColPosition);\r\n    footerCell.value = this.processCellValue(footer);\r\n    // Aplicar estilo: primero explícito, luego styleName, luego tema\r\n    if (footer.styles) {\r\n      footerCell.style = this.convertStyle(footer.styles);\r\n    } else if (footer.styleName) {\r\n      const style = this.getPredefinedStyle(footer.styleName);\r\n      if (style) {\r\n        footerCell.style = this.convertStyle(style);\r\n      }\r\n    } else {\r\n      // Aplicar estilo del tema si está disponible y auto-apply está habilitado\r\n      const themeStyle = this.getThemeStyle('footer');\r\n      if (themeStyle) {\r\n        footerCell.style = this.convertStyle(themeStyle);\r\n      }\r\n    }\r\n    if (footer.numberFormat) {\r\n      footerCell.numFmt = footer.numberFormat;\r\n    }\r\n\r\n    // Aplicar dimensiones de celda\r\n    this.applyCellDimensions(ws, rowPointer, footerColPosition, footer);\r\n    // Aplicar comentario si existe\r\n    if (footer.comment) {\r\n      this.applyCellComment(ws, rowPointer, footerColPosition, footer.comment);\r\n    }\r\n    // Aplicar validación de datos si existe\r\n    if (footer.validation) {\r\n      this.applyDataValidation(ws, rowPointer, footerColPosition, footer.validation);\r\n    }\r\n    // Aplicar formato condicional si existe\r\n    if (footer.styles?.conditionalFormats) {\r\n      this.applyConditionalFormatting(ws, rowPointer, footerColPosition, footer.styles.conditionalFormats);\r\n    }\r\n\r\n    // Aplicar merge si está configurado\r\n    if (footer.mergeCell && footer.mergeTo) {\r\n      ws.mergeCells(rowPointer, footerColPosition, rowPointer, footer.mergeTo);\r\n    }\r\n\r\n    // Si hay children, escribirlos en las columnas correspondientes\r\n    if (footer.children && footer.children.length > 0) {\r\n      for (const child of footer.children) {\r\n        if (child) {\r\n          // Buscar la columna correcta basándose en el header del child\r\n          let colPosition: number | undefined;\r\n\r\n          // Intentar encontrar por key primero\r\n          if (child.key && columnPositions[child.key]) {\r\n            colPosition = columnPositions[child.key];\r\n          }\r\n          // Si no se encuentra por key, intentar por header\r\n          else if (child.header && columnPositions[child.header]) {\r\n            colPosition = columnPositions[child.header];\r\n          }\r\n\r\n          if (colPosition !== undefined) {\r\n            const childCell = excelRow.getCell(colPosition);\r\n            childCell.value = this.processCellValue(child);\r\n            if (child.styles) {\r\n              childCell.style = this.convertStyle(child.styles);\r\n            }\r\n            if (child.numberFormat) {\r\n              childCell.numFmt = child.numberFormat;\r\n            }\r\n\r\n            // Aplicar dimensiones de celda para children\r\n            this.applyCellDimensions(ws, rowPointer, colPosition, child);\r\n            // Aplicar comentario si existe\r\n            if (child.comment) {\r\n              this.applyCellComment(ws, rowPointer, colPosition, child.comment);\r\n            }\r\n            // Aplicar validación de datos si existe\r\n            if (child.validation) {\r\n              this.applyDataValidation(ws, rowPointer, colPosition, child.validation);\r\n            }\r\n            // Aplicar formato condicional si existe\r\n            if (child.styles?.conditionalFormats) {\r\n              this.applyConditionalFormatting(ws, rowPointer, colPosition, child.styles.conditionalFormats);\r\n            }\r\n          }\r\n        }\r\n      }\r\n    }\r\n\r\n    // Incrementar rowPointer solo si el footer tiene la propiedad jump\r\n    if (footer.jump) {\r\n      return rowPointer + 1;\r\n    }\r\n\r\n    return rowPointer;\r\n  }\r\n\r\n  /**\r\n   * Aplica width y height a una celda/fila\r\n   */\r\n  private applyCellDimensions(ws: ExcelJS.Worksheet, row: number, col: number, cell: IDataCell | IHeaderCell | IFooterCell): void {\r\n    // Aplicar rowHeight si está definido\r\n    if (cell.rowHeight !== undefined) {\r\n      const excelRow = ws.getRow(row);\r\n      excelRow.height = cell.rowHeight;\r\n    }\r\n\r\n    // Aplicar colWidth si está definido\r\n    if (cell.colWidth !== undefined) {\r\n      const excelCol = ws.getColumn(col);\r\n      excelCol.width = cell.colWidth;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica comentario a una celda\r\n   */\r\n  private applyCellComment(ws: ExcelJS.Worksheet, row: number, col: number, comment: string): void {\r\n    if (!comment || comment.trim() === '') {\r\n      return;\r\n    }\r\n\r\n    const cell = ws.getRow(row).getCell(col);\r\n\r\n    // ExcelJS usa 'note' para comentarios\r\n    // Puede ser string o objeto con más propiedades\r\n    if (typeof comment === 'string') {\r\n      cell.note = comment;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica validación de datos a una celda\r\n   */\r\n  private applyDataValidation(ws: ExcelJS.Worksheet, row: number, col: number, validation: IDataValidation): void {\r\n    if (!validation) {\r\n      return;\r\n    }\r\n\r\n    const cell = ws.getRow(row).getCell(col);\r\n\r\n    // ExcelJS usa dataValidation para validaciones\r\n    // Nota: ExcelJS no soporta 'time' como tipo, se convierte a 'date'\r\n    const validationType = validation.type === 'time' ? 'date' : validation.type;\r\n\r\n    const dataValidation: ExcelJS.DataValidation = {\r\n      type: validationType as 'list' | 'whole' | 'decimal' | 'textLength' | 'date' | 'custom',\r\n      allowBlank: validation.allowBlank ?? true,\r\n      formulae: [] // Inicializar como array vacío, se llenará si hay fórmulas\r\n    };\r\n\r\n    // Agregar operador si existe\r\n    if (validation.operator) {\r\n      dataValidation.operator = validation.operator;\r\n    }\r\n\r\n    // Agregar fórmulas/valores\r\n    if (validation.type === 'list' && validation.values && validation.values.length > 0) {\r\n      // Excel list formula: \"A,B,C\"\r\n      const escaped = validation.values\r\n        .map(v => String(v).replace(/\"/g, '\"\"'))\r\n        .join(',');\r\n      dataValidation.formulae = [`\"${escaped}\"`];\r\n    } else if (validation.formula1 !== undefined) {\r\n      if (typeof validation.formula1 === 'string') {\r\n        dataValidation.formulae = [validation.formula1];\r\n      } else if (validation.formula1 instanceof Date) {\r\n        dataValidation.formulae = [validation.formula1.toISOString()];\r\n      } else {\r\n        dataValidation.formulae = [validation.formula1];\r\n      }\r\n    }\r\n\r\n    if (validation.formula2 !== undefined) {\r\n      if (!dataValidation.formulae) {\r\n        dataValidation.formulae = [];\r\n      }\r\n      if (typeof validation.formula2 === 'string') {\r\n        dataValidation.formulae.push(validation.formula2);\r\n      } else if (validation.formula2 instanceof Date) {\r\n        dataValidation.formulae.push(validation.formula2.toISOString());\r\n      } else {\r\n        dataValidation.formulae.push(validation.formula2);\r\n      }\r\n    }\r\n\r\n    // Agregar mensajes de error e input\r\n    if (validation.showErrorMessage) {\r\n      dataValidation.showErrorMessage = true;\r\n      if (validation.errorMessage) {\r\n        dataValidation.error = validation.errorMessage;\r\n      }\r\n    }\r\n\r\n    if (validation.showInputMessage) {\r\n      dataValidation.showInputMessage = true;\r\n      if (validation.inputMessage) {\r\n        dataValidation.prompt = validation.inputMessage;\r\n      }\r\n    }\r\n\r\n    cell.dataValidation = dataValidation;\r\n  }\r\n\r\n  /**\r\n   * Aplica formato condicional a una celda\r\n   */\r\n  private applyConditionalFormatting(ws: ExcelJS.Worksheet, row: number, col: number, conditionalFormats?: IConditionalFormat[]): void {\r\n    if (!conditionalFormats || conditionalFormats.length === 0) {\r\n      return;\r\n    }\r\n\r\n    const cell = ws.getRow(row).getCell(col);\r\n    const cellAddress = cell.address;\r\n\r\n    // ExcelJS usa addConditionalFormatting para agregar formato condicional\r\n    conditionalFormats.forEach((format, index) => {\r\n      const rule: any = {\r\n        type: format.type,\r\n        priority: format.priority ?? (index + 1),\r\n        stopIfTrue: format.stopIfTrue ?? false\r\n      };\r\n\r\n      // Agregar operador si existe\r\n      if (format.operator) {\r\n        rule.operator = format.operator;\r\n      }\r\n\r\n      // Agregar fórmulas/valores\r\n      if (format.formula) {\r\n        rule.formulae = [format.formula];\r\n      } else if (format.values && format.values.length > 0) {\r\n        rule.formulae = format.values.map(v => {\r\n          if (typeof v === 'string') {\r\n            return v;\r\n          } else if (v instanceof Date) {\r\n            return v.toISOString();\r\n          } else {\r\n            return String(v);\r\n          }\r\n        });\r\n      }\r\n\r\n      // Convertir el estilo si existe y aplicarlo a la regla\r\n      if (format.style) {\r\n        const style = this.convertStyle(format.style);\r\n        // ExcelJS aplica el estilo directamente en la regla\r\n        rule.style = style;\r\n      }\r\n\r\n      // Agregar la regla de formato condicional usando addConditionalFormatting\r\n      ws.addConditionalFormatting({\r\n        ref: cellAddress,\r\n        rules: [rule]\r\n      });\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Aplica filtro automático a una tabla\r\n   */\r\n  private applyAutoFilter(ws: ExcelJS.Worksheet, table: ITable, startRow: number, endRow: number): void {\r\n    if (!table.autoFilter) {\r\n      return;\r\n    }\r\n\r\n    // Calcular el rango de columnas\r\n    const maxCols = this.calculateTableMaxColumns(table);\r\n\r\n    // Aplicar filtro automático al rango de la tabla\r\n    // El filtro se aplica desde la fila de headers hasta la última fila de datos\r\n    const headerRow = startRow;\r\n    const dataEndRow = endRow;\r\n\r\n    if (maxCols > 0 && dataEndRow >= headerRow) {\r\n      ws.autoFilter = {\r\n        from: {\r\n          row: headerRow,\r\n          column: 1\r\n        },\r\n        to: {\r\n          row: dataEndRow,\r\n          column: maxCols\r\n        }\r\n      };\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica filtro automático a nivel de worksheet\r\n   */\r\n  private applyWorksheetAutoFilter(ws: ExcelJS.Worksheet, lastRow: number): void {\r\n    const autoFilterConfig = this.config.autoFilter;\r\n    if (!autoFilterConfig || !autoFilterConfig.enabled) {\r\n      return;\r\n    }\r\n\r\n    // Si hay un rango específico, usarlo\r\n    if (autoFilterConfig.range) {\r\n      ws.autoFilter = {\r\n        from: {\r\n          row: autoFilterConfig.range.start?.row || 1,\r\n          column: autoFilterConfig.range.start?.col || 1\r\n        },\r\n        to: {\r\n          row: autoFilterConfig.range.end?.row || lastRow,\r\n          column: autoFilterConfig.range.end?.col || ws.columnCount || 1\r\n        }\r\n      };\r\n      return;\r\n    }\r\n\r\n    // Si hay configuración de filas/columnas específicas\r\n    if (autoFilterConfig.startRow !== undefined || autoFilterConfig.endRow !== undefined ||\r\n      autoFilterConfig.startColumn !== undefined || autoFilterConfig.endColumn !== undefined) {\r\n      ws.autoFilter = {\r\n        from: {\r\n          row: autoFilterConfig.startRow || 1,\r\n          column: autoFilterConfig.startColumn || 1\r\n        },\r\n        to: {\r\n          row: autoFilterConfig.endRow || lastRow,\r\n          column: autoFilterConfig.endColumn || ws.columnCount || 1\r\n        }\r\n      };\r\n      return;\r\n    }\r\n\r\n    // Por defecto, aplicar a todo el contenido (desde la primera fila hasta la última)\r\n    // Excluyendo headers si existen\r\n    const startRow = this.headers.length > 0 ? this.headers.length + (this.subHeaders.length > 0 ? this.getMaxHeaderDepth(this.subHeaders) : 0) : 1;\r\n    const maxCols = this.getMaxColumns() || ws.columnCount || 1;\r\n\r\n    if (lastRow >= startRow && maxCols > 0) {\r\n      ws.autoFilter = {\r\n        from: {\r\n          row: startRow,\r\n          column: 1\r\n        },\r\n        to: {\r\n          row: lastRow,\r\n          column: maxCols\r\n        }\r\n      };\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Procesa el valor de una celda considerando links y máscaras\r\n   * Si el tipo es LINK o hay un link, crea un hipervínculo en Excel\r\n   */\r\n  private processCellValue(cell: IDataCell | IHeaderCell | IFooterCell): ExcelJS.CellValue {\r\n    // Si hay un link o el tipo es LINK, crear hipervínculo\r\n    if (cell.link || cell.type === CellType.LINK) {\r\n      const linkUrl = cell.link || (typeof cell.value === 'string' ? cell.value : '');\r\n\r\n      // Si no hay URL válida, retornar el valor normal\r\n      if (!linkUrl || linkUrl.trim() === '') {\r\n        return cell.value;\r\n      }\r\n\r\n      // Determinar el texto visible: usar máscara si existe, sino usar value, sino usar la URL\r\n      const displayText = cell.mask || cell.value || linkUrl;\r\n\r\n      // Crear objeto de hipervínculo para ExcelJS\r\n      return {\r\n        text: String(displayText),\r\n        hyperlink: linkUrl\r\n      } as any;\r\n    }\r\n\r\n    // Si no hay link, retornar el valor normal\r\n    return cell.value;\r\n  }\r\n\r\n  /**\r\n   * Agrega una fila de datos y sus children recursivamente\r\n   * @returns el siguiente rowPointer disponible\r\n   */\r\n  private addDataRowRecursive(\r\n    ws: ExcelJS.Worksheet,\r\n    rowPointer: number,\r\n    row: IDataCell,\r\n    contextRows?: IDataCell[],\r\n    contextIndex?: number,\r\n    contextSubHeaders?: IHeaderCell[]\r\n  ): number {\r\n    // Calcular las columnas basándose en la estructura de subheaders\r\n    const columnPositions = this.calculateDataColumnPositions(contextSubHeaders);\r\n\r\n    // Buscar la columna correcta para el dato principal\r\n    let mainColPosition: number | undefined;\r\n\r\n    // Intentar encontrar por key primero\r\n    if (row.key && columnPositions[row.key]) {\r\n      mainColPosition = columnPositions[row.key];\r\n    }\r\n    // Si no se encuentra por key, intentar por header\r\n    else if (row.header && columnPositions[row.header]) {\r\n      mainColPosition = columnPositions[row.header];\r\n    }\r\n\r\n    // Si no se encuentra la posición, usar columna 1 por defecto\r\n    if (mainColPosition === undefined) {\r\n      mainColPosition = 1;\r\n    }\r\n\r\n    // Escribir el dato principal en la columna correcta\r\n    const excelRow = ws.getRow(rowPointer);\r\n    const mainCell = excelRow.getCell(mainColPosition);\r\n\r\n    // Aplicar rich text si existe\r\n    if ((row as any).richText && (row as any).richText.length > 0) {\r\n      mainCell.value = {\r\n        richText: (row as any).richText.map((run: IRichTextRun) => ({\r\n          text: run.text,\r\n          font: run.font ? { name: run.font } : undefined,\r\n          size: run.size,\r\n          color: run.color ? this.convertColorToExcelJS(run.color) : undefined,\r\n          bold: run.bold,\r\n          italic: run.italic,\r\n          underline: run.underline,\r\n          strike: run.strikethrough\r\n        })).filter((run: any) => run.text !== undefined)\r\n      } as any;\r\n    } else {\r\n      mainCell.value = this.processCellValue(row);\r\n    }\r\n\r\n    // Aplicar estilo: primero explícito, luego styleName, luego tema\r\n    if (row.styles) {\r\n      mainCell.style = this.convertStyle(row.styles);\r\n    } else if (row.styleName) {\r\n      const style = this.getPredefinedStyle(row.styleName);\r\n      if (style) {\r\n        mainCell.style = this.convertStyle(style);\r\n      }\r\n    } else {\r\n      // Aplicar estilo del tema si está disponible y auto-apply está habilitado\r\n      // Usar el número de fila actual como índice para alternar\r\n      const themeStyle = this.getThemeStyle('body', rowPointer);\r\n      if (themeStyle) {\r\n        mainCell.style = this.convertStyle(themeStyle);\r\n      }\r\n    }\r\n    if (row.numberFormat) {\r\n      mainCell.numFmt = row.numberFormat;\r\n    }\r\n\r\n    // Calcular cuántas filas ocuparán esta fila y sus childrens (incluye la fila principal)\r\n    const rowsNeeded = this.calculateRowSpan(row);\r\n    const endRow = rowPointer + Math.max(1, rowsNeeded) - 1;\r\n\r\n    // Manejo de merge: mergeAs (fromKey o rows explícitos), mergeCell legacy, o por rowsNeeded\r\n    const mergeAs = (row as any).mergeAs;\r\n    if (mergeAs?.fromKey) {\r\n      // mergeAs con fromKey: copiar estructura de otra celda\r\n      const explicitRows = Number(mergeAs?.rows);\r\n      let spanRows: number | undefined;\r\n\r\n      if (Number.isFinite(explicitRows) && explicitRows >= 0) {\r\n        spanRows = explicitRows + 1;\r\n      } else if (contextRows && typeof contextIndex === 'number') {\r\n        const nextRow = contextRows[contextIndex + 1];\r\n        if (nextRow && (nextRow as any).key === mergeAs.fromKey) {\r\n          spanRows = this.calculateRowSpan(nextRow as IDataCell);\r\n        }\r\n      }\r\n      if (spanRows === undefined) spanRows = rowsNeeded;\r\n      const safeSpan = spanRows ?? 1;\r\n      this.safeMerge(ws, rowPointer, mainColPosition, rowPointer + Math.max(1, safeSpan) - 1, mainColPosition);\r\n    } else if (mergeAs && Number.isFinite(Number(mergeAs.rows)) && Number(mergeAs.rows) >= 0) {\r\n      // mergeAs con rows explícitos: merge vertical de N+1 filas (ej: unidad con múltiples fichas)\r\n      const spanRows = Number(mergeAs.rows) + 1;\r\n      this.safeMerge(ws, rowPointer, mainColPosition, rowPointer + spanRows - 1, mainColPosition);\r\n    } else {\r\n      // Legacy: mergeCell/mergeTo o por rowsNeeded (children anidados)\r\n      // No hacer merge en columnas ficha (fichaId, fichaCode, etc.): cada fila tiene datos distintos\r\n      const headerStr = row.header ? String(row.header) : '';\r\n      const noMerge = (row as any).noMerge === true || headerStr.startsWith('ficha');\r\n      if (!noMerge) {\r\n        if ((row as any).mergeCell && (row as any).mergeTo) {\r\n          if (rowsNeeded > 1) this.safeMerge(ws, rowPointer, mainColPosition, endRow, (row as any).mergeTo);\r\n          else this.safeMerge(ws, rowPointer, mainColPosition, rowPointer, (row as any).mergeTo);\r\n        } else if (rowsNeeded > 1) {\r\n          this.safeMerge(ws, rowPointer, mainColPosition, endRow, mainColPosition);\r\n        }\r\n      }\r\n    }\r\n\r\n    // Aplicar protección de celda si existe\r\n    if ((row as any).cellProtection) {\r\n      mainCell.protection = {\r\n        locked: (row as any).cellProtection.locked ?? true,\r\n        hidden: (row as any).cellProtection.hidden ?? false\r\n      };\r\n    } else if (row.protected !== undefined) {\r\n      // Soporte legacy\r\n      mainCell.protection = {\r\n        locked: row.protected,\r\n        hidden: false\r\n      };\r\n    }\r\n\r\n    // Aplicar dimensiones de celda\r\n    this.applyCellDimensions(ws, rowPointer, mainColPosition, row);\r\n    // Aplicar comentario si existe\r\n    if (row.comment) {\r\n      this.applyCellComment(ws, rowPointer, mainColPosition, row.comment);\r\n    }\r\n    // Aplicar validación de datos si existe\r\n    if (row.validation) {\r\n      this.applyDataValidation(ws, rowPointer, mainColPosition, row.validation);\r\n    }\r\n    // Aplicar formato condicional si existe\r\n    if (row.styles?.conditionalFormats) {\r\n      this.applyConditionalFormatting(ws, rowPointer, mainColPosition, row.styles.conditionalFormats);\r\n    }\r\n\r\n    // Si hay children, procesarlos recursivamente (soporta children dentro de children)\r\n    if (row.children && row.children.length > 0) {\r\n      let childRowPointer = rowPointer;\r\n      for (let i = 0; i < row.children.length; i++) {\r\n        const child = row.children[i];\r\n        if (child) {\r\n          // Llamada recursiva: procesa el child y sus nested children, retorna el siguiente rowPointer\r\n          childRowPointer = this.addDataRowRecursive(\r\n            ws,\r\n            childRowPointer,\r\n            child,\r\n            row.children,\r\n            i,\r\n            contextSubHeaders\r\n          );\r\n        }\r\n      }\r\n      // Cuando hay children, el rowPointer debe avanzar al último row usado + 1.\r\n      // Si la fila tiene jump: true o mergeAs, garantizar avance de al menos 1 (children\r\n      // horizontales pueden no avanzar childRowPointer si ninguno tiene jump).\r\n      const hasMergeOrJump = row.jump || !!(row as any).mergeAs;\r\n      const nextPointer = hasMergeOrJump\r\n        ? Math.max(childRowPointer, rowPointer + 1)\r\n        : childRowPointer;\r\n      return nextPointer;\r\n    }\r\n\r\n    // Sin children: incrementar rowPointer solo si la celda tiene la propiedad jump\r\n    return row.jump ? rowPointer + 1 : rowPointer;\r\n  }\r\n\r\n  /**\r\n   * Merge helper that avoids attempting to merge a range that's already merged.\r\n   */\r\n  private safeMerge(ws: ExcelJS.Worksheet, startRow: number, startCol: number, endRow: number, endCol: number): void {\r\n    if (endRow < startRow || endCol < startCol) return;\r\n    if (endRow === startRow && endCol === startCol) return;\r\n    try {\r\n      const startColLetter = this.numberToColumnLetter(startCol);\r\n      const endColLetter = this.numberToColumnLetter(endCol);\r\n      const range = `${startColLetter}${startRow}:${endColLetter}${endRow}`;\r\n      if ((ws as any)._merges && typeof (ws as any)._merges.has === 'function') {\r\n        if ((ws as any)._merges.has(range)) return;\r\n      }\r\n      ws.mergeCells(startRow, startCol, endRow, endCol);\r\n    } catch (e) {\r\n      // Ignore merge errors (e.g., overlapping/duplicate merges)\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Convierte un color a formato ExcelJS (ARGB)\r\n   */\r\n  private convertColor(color: any): any {\r\n    if (!color) return undefined;\r\n\r\n    // Si ya es un objeto con argb, retornarlo\r\n    if (typeof color === 'object' && color.argb) {\r\n      return color;\r\n    }\r\n\r\n    // Si es un objeto con r, g, b\r\n    if (typeof color === 'object' && 'r' in color && 'g' in color && 'b' in color) {\r\n      const r = color.r.toString(16).padStart(2, '0');\r\n      const g = color.g.toString(16).padStart(2, '0');\r\n      const b = color.b.toString(16).padStart(2, '0');\r\n      return { argb: `FF${r}${g}${b}`.toUpperCase() };\r\n    }\r\n\r\n    // Si es un string (hex)\r\n    if (typeof color === 'string') {\r\n      // Remover # si existe\r\n      let hex = color.replace('#', '');\r\n\r\n      // Si es formato corto (RGB), expandirlo\r\n      if (hex.length === 3) {\r\n        hex = hex.split('').map(c => c + c).join('');\r\n      }\r\n\r\n      // Asegurar que tenga alpha (FF = completamente opaco)\r\n      if (hex.length === 6) {\r\n        hex = 'FF' + hex.toUpperCase();\r\n      }\r\n\r\n      return { argb: hex };\r\n    }\r\n\r\n    // Si es un objeto theme\r\n    if (typeof color === 'object' && 'theme' in color) {\r\n      return color;\r\n    }\r\n\r\n    return undefined;\r\n  }\r\n\r\n  /**\r\n   * Calcula cuántas filas ocupará una celda considerando children y jumps.\r\n   */\r\n  private calculateRowSpan(row: IDataCell | IHeaderCell | IFooterCell): number {\r\n    if (!row) return 1;\r\n    let span = 1;\r\n    const children = (row as any).children as Array<any> | undefined;\r\n    if (!children || children.length === 0) return span;\r\n\r\n    // Contar filas adicionales introducidas por children con `jump`\r\n    let current = 1;\r\n    for (const c of children) {\r\n      if (!c) continue;\r\n      const childSpan = this.calculateRowSpan(c as IDataCell);\r\n      if (c.jump) {\r\n        current = Math.max(current, 1) + childSpan;\r\n      } else {\r\n        current = Math.max(current, childSpan);\r\n      }\r\n    }\r\n    span = Math.max(span, current);\r\n    return span;\r\n  }\r\n\r\n  /**\r\n   * Busca recursivamente una celda (por key) dentro de una definición de fila/header/footer\r\n   */\r\n  private findCellInRow(row: IDataCell | IHeaderCell | IFooterCell, key: string): IDataCell | IHeaderCell | IFooterCell | undefined {\r\n    if (!row) return undefined;\r\n    if ((row as any).key === key) return row as any;\r\n    const children = (row as any).children as Array<any> | undefined;\r\n    if (!children || children.length === 0) return undefined;\r\n    for (const c of children) {\r\n      if (!c) continue;\r\n      if (c.key === key) return c;\r\n      const found = this.findCellInRow(c, key);\r\n      if (found) return found;\r\n    }\r\n    return undefined;\r\n  }\r\n\r\n  /**\r\n   * Convierte el estilo personalizado a formato compatible con ExcelJS\r\n   */\r\n  private convertStyle(style: any): Partial<ExcelJS.Style> {\r\n    if (!style) return {};\r\n\r\n    const converted: Partial<ExcelJS.Style> = {};\r\n\r\n    if (style.font) {\r\n      converted.font = {\r\n        name: style.font.family || style.font.name,\r\n        size: style.font.size,\r\n        bold: style.font.bold,\r\n        italic: style.font.italic,\r\n        underline: style.font.underline,\r\n        color: this.convertColor(style.font.color)\r\n      };\r\n    }\r\n\r\n    if (style.fill) {\r\n      // En ExcelJS, para patrón sólido, el color de fondo debe ir en fgColor\r\n      // backgroundColor es el color que queremos mostrar como fondo de la celda\r\n      const pattern = style.fill.pattern || 'solid';\r\n\r\n      // Para patrón sólido: backgroundColor va en fgColor (es el color visible)\r\n      // Para otros patrones: foregroundColor es el color del patrón, backgroundColor es el fondo\r\n      const fgColor = pattern === 'solid'\r\n        ? (style.fill.backgroundColor || style.fill.foregroundColor)\r\n        : (style.fill.foregroundColor || style.fill.backgroundColor);\r\n\r\n      // bgColor solo es relevante para patrones no sólidos\r\n      const bgColor = pattern !== 'solid' ? style.fill.backgroundColor : undefined;\r\n\r\n      converted.fill = {\r\n        type: style.fill.type || 'pattern',\r\n        pattern: pattern,\r\n        fgColor: this.convertColor(fgColor),\r\n        bgColor: bgColor ? this.convertColor(bgColor) : undefined\r\n      };\r\n\r\n      // Limpiar bgColor si es undefined para evitar problemas\r\n      if (!converted.fill.bgColor) {\r\n        delete converted.fill.bgColor;\r\n      }\r\n    }\r\n\r\n    if (style.border) {\r\n      converted.border = {};\r\n\r\n      if (style.border.top) {\r\n        converted.border.top = {\r\n          style: style.border.top.style,\r\n          color: this.convertColor(style.border.top.color)\r\n        };\r\n      }\r\n\r\n      if (style.border.left) {\r\n        converted.border.left = {\r\n          style: style.border.left.style,\r\n          color: this.convertColor(style.border.left.color)\r\n        };\r\n      }\r\n\r\n      if (style.border.bottom) {\r\n        converted.border.bottom = {\r\n          style: style.border.bottom.style,\r\n          color: this.convertColor(style.border.bottom.color)\r\n        };\r\n      }\r\n\r\n      if (style.border.right) {\r\n        converted.border.right = {\r\n          style: style.border.right.style,\r\n          color: this.convertColor(style.border.right.color)\r\n        };\r\n      }\r\n    }\r\n\r\n    // Conditional formatting se aplica directamente a la celda, no al estilo base\r\n    // Se maneja en applyConditionalFormatting()\r\n\r\n    if (style.alignment) {\r\n      converted.alignment = {};\r\n\r\n      // Horizontal alignment - validar valores permitidos\r\n      if (style.alignment.horizontal !== undefined) {\r\n        const validHorizontal = ['left', 'center', 'right', 'fill', 'justify', 'centerContinuous', 'distributed'];\r\n        if (validHorizontal.includes(style.alignment.horizontal)) {\r\n          converted.alignment.horizontal = style.alignment.horizontal as any;\r\n        }\r\n      }\r\n\r\n      // Vertical alignment - validar valores permitidos\r\n      if (style.alignment.vertical !== undefined) {\r\n        const validVertical = ['top', 'middle', 'bottom', 'distributed', 'justify'];\r\n        if (validVertical.includes(style.alignment.vertical)) {\r\n          converted.alignment.vertical = style.alignment.vertical as any;\r\n        }\r\n      }\r\n\r\n      // Wrap text\r\n      if (style.alignment.wrapText !== undefined) {\r\n        converted.alignment.wrapText = Boolean(style.alignment.wrapText);\r\n      }\r\n\r\n      // Shrink to fit\r\n      if (style.alignment.shrinkToFit !== undefined) {\r\n        converted.alignment.shrinkToFit = Boolean(style.alignment.shrinkToFit);\r\n      }\r\n\r\n      // Indent\r\n      if (style.alignment.indent !== undefined && typeof style.alignment.indent === 'number') {\r\n        converted.alignment.indent = style.alignment.indent;\r\n      }\r\n\r\n      // Text rotation (0-180 grados)\r\n      if (style.alignment.textRotation !== undefined && typeof style.alignment.textRotation === 'number') {\r\n        converted.alignment.textRotation = style.alignment.textRotation;\r\n      }\r\n\r\n      // Reading order\r\n      if (style.alignment.readingOrder !== undefined) {\r\n        const validReadingOrder = ['left-to-right', 'right-to-left', 'context'];\r\n        if (validReadingOrder.includes(style.alignment.readingOrder)) {\r\n          converted.alignment.readingOrder = style.alignment.readingOrder as any;\r\n        }\r\n      }\r\n\r\n      // Solo agregar alignment si tiene al menos una propiedad\r\n      if (Object.keys(converted.alignment).length === 0) {\r\n        delete converted.alignment;\r\n      }\r\n    }\r\n\r\n    if (style.numFmt) {\r\n      converted.numFmt = style.numFmt;\r\n    }\r\n\r\n    return converted;\r\n  }\r\n\r\n  /**\r\n   * Convierte un número de columna a letra (1 = A, 2 = B, etc.)\r\n   */\r\n  private numberToColumnLetter(columnNumber: number): string {\r\n    let result = '';\r\n    while (columnNumber > 0) {\r\n      columnNumber--;\r\n      result = String.fromCharCode(65 + (columnNumber % 26)) + result;\r\n      columnNumber = Math.floor(columnNumber / 26);\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Convierte letra de columna a número (A = 1, B = 2, etc.)\r\n   */\r\n  private columnLetterToNumber(columnLetter: string): number {\r\n    let result = 0;\r\n    for (let i = 0; i < columnLetter.length; i++) {\r\n      result = result * 26 + (columnLetter.charCodeAt(i) - 64);\r\n    }\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Aplica una imagen al worksheet\r\n   */\r\n  private async applyImage(ws: ExcelJS.Worksheet, image: IWorksheetImage): Promise<void> {\r\n    try {\r\n      // Convertir posición\r\n      let row: number;\r\n      let col: number;\r\n\r\n      if (typeof image.position.row === 'string') {\r\n        // Parsear referencia de celda (e.g., \"A1\" -> row 1)\r\n        const match = image.position.row.match(/([A-Z]+)(\\d+)/);\r\n        if (match && match[1] && match[2]) {\r\n          col = this.columnLetterToNumber(match[1]);\r\n          row = parseInt(match[2], 10);\r\n        } else {\r\n          row = parseInt(image.position.row, 10) || 1;\r\n          col = typeof image.position.col === 'string'\r\n            ? this.columnLetterToNumber(image.position.col)\r\n            : (typeof image.position.col === 'number' ? image.position.col : 1);\r\n        }\r\n      } else {\r\n        row = image.position.row;\r\n        col = typeof image.position.col === 'string'\r\n          ? this.columnLetterToNumber(image.position.col)\r\n          : (typeof image.position.col === 'number' ? image.position.col : 1);\r\n      }\r\n\r\n      // Preparar el buffer de imagen\r\n      let imageBuffer: Uint8Array;\r\n      if (typeof image.buffer === 'string') {\r\n        // Base64 string\r\n        let base64Data: string;\r\n        if (image.buffer.startsWith('data:')) {\r\n          // Data URL - extraer base64\r\n          const parts = image.buffer.split(',');\r\n          base64Data = parts[1] || image.buffer;\r\n        } else {\r\n          // Base64 directo\r\n          base64Data = image.buffer;\r\n        }\r\n        // Convertir base64 a Uint8Array\r\n        const binaryString = atob(base64Data);\r\n        const bytes = new Uint8Array(binaryString.length);\r\n        for (let i = 0; i < binaryString.length; i++) {\r\n          bytes[i] = binaryString.charCodeAt(i);\r\n        }\r\n        imageBuffer = bytes;\r\n      } else if (image.buffer instanceof ArrayBuffer) {\r\n        imageBuffer = new Uint8Array(image.buffer);\r\n      } else {\r\n        imageBuffer = image.buffer;\r\n      }\r\n\r\n      // Calcular posición y tamaño\r\n      const imagePosition: any = {\r\n        tl: { col: col - 1, row: row - 1 }\r\n      };\r\n\r\n      if (image.size) {\r\n        if (image.size.width && image.size.height) {\r\n          imagePosition.ext = {\r\n            width: image.size.width,\r\n            height: image.size.height\r\n          };\r\n        } else if (image.size.scaleX && image.size.scaleY) {\r\n          // Usar escala si no hay dimensiones absolutas\r\n          // Nota: ExcelJS no soporta escala directamente, necesitamos calcular dimensiones\r\n          imagePosition.ext = {\r\n            width: 100 * (image.size.scaleX || 1),\r\n            height: 100 * (image.size.scaleY || 1)\r\n          };\r\n        }\r\n      }\r\n\r\n      // ExcelJS addImage - primer parámetro es el objeto con buffer y extension, segundo es la posición\r\n      ws.addImage({\r\n        buffer: imageBuffer,\r\n        extension: image.extension\r\n      } as any, imagePosition as any);\r\n\r\n      // Agregar hipervínculo si existe\r\n      if (image.hyperlink) {\r\n        const cell = ws.getRow(row).getCell(col);\r\n        cell.value = {\r\n          text: image.description || '',\r\n          hyperlink: image.hyperlink\r\n        } as any;\r\n      }\r\n    } catch (error) {\r\n      console.warn('Error adding image to worksheet:', error);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica agrupación de filas\r\n   */\r\n  private applyRowGrouping(ws: ExcelJS.Worksheet, startRow: number, endRow: number, collapsed: boolean = false): void {\r\n    for (let row = startRow; row <= endRow; row++) {\r\n      const excelRow = ws.getRow(row);\r\n      if (!excelRow.outlineLevel) {\r\n        excelRow.outlineLevel = 1;\r\n      }\r\n      // Nota: collapsed es read-only en ExcelJS, se maneja a través de outlineLevel\r\n      if (collapsed && row === startRow) {\r\n        try {\r\n          (excelRow as any).collapsed = true;\r\n        } catch {\r\n          // Ignorar si no está disponible\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica agrupación de columnas\r\n   */\r\n  private applyColumnGrouping(ws: ExcelJS.Worksheet, startCol: number, endCol: number, collapsed: boolean = false): void {\r\n    for (let col = startCol; col <= endCol; col++) {\r\n      const excelCol = ws.getColumn(col);\r\n      if (!excelCol.outlineLevel) {\r\n        excelCol.outlineLevel = 1;\r\n      }\r\n      // Nota: collapsed es read-only en ExcelJS, se maneja a través de outlineLevel\r\n      if (collapsed && col === startCol) {\r\n        try {\r\n          (excelCol as any).collapsed = true;\r\n        } catch {\r\n          // Ignorar si no está disponible\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica una tabla estructurada de Excel\r\n   */\r\n  private applyExcelTable(ws: ExcelJS.Worksheet, table: IExcelTable): void {\r\n    try {\r\n      const range = `${table.range.start}:${table.range.end}`;\r\n\r\n      const tableConfig: any = {\r\n        name: table.name,\r\n        ref: range,\r\n        headerRow: table.headerRow !== false,\r\n        totalsRow: table.totalRow === true\r\n      };\r\n\r\n      if (table.style) {\r\n        tableConfig.style = {\r\n          theme: table.style,\r\n          showFirstColumn: false,\r\n          showLastColumn: false,\r\n          showRowStripes: true,\r\n          showColumnStripes: false\r\n        };\r\n      }\r\n\r\n      if (table.columns && table.columns.length > 0) {\r\n        tableConfig.columns = table.columns.map(col => ({\r\n          name: col.name,\r\n          filterButton: col.filterButton !== false,\r\n          totalsRowFunction: col.totalsRowFunction || 'none',\r\n          totalsRowFormula: col.totalsRowFormula\r\n        }));\r\n      }\r\n\r\n      ws.addTable(tableConfig);\r\n    } catch (error) {\r\n      console.warn('Error adding Excel table:', error);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica configuración avanzada de impresión\r\n   */\r\n  private applyAdvancedPrintSettings(ws: ExcelJS.Worksheet): void {\r\n    // Headers y footers\r\n    if (this.config.printHeadersFooters) {\r\n      const headerFooter: any = {};\r\n\r\n      if (this.config.printHeadersFooters.header) {\r\n        const left = this.config.printHeadersFooters.header.left || '';\r\n        const center = this.config.printHeadersFooters.header.center || '';\r\n        const right = this.config.printHeadersFooters.header.right || '';\r\n        headerFooter.oddHeader = `${left}&C${center}&R${right}`;\r\n      }\r\n\r\n      if (this.config.printHeadersFooters.footer) {\r\n        const left = this.config.printHeadersFooters.footer.left || '';\r\n        const center = this.config.printHeadersFooters.footer.center || '';\r\n        const right = this.config.printHeadersFooters.footer.right || '';\r\n        headerFooter.oddFooter = `${left}&C${center}&R${right}`;\r\n      }\r\n\r\n      if (Object.keys(headerFooter).length > 0) {\r\n        ws.headerFooter = headerFooter;\r\n      }\r\n    }\r\n\r\n    // Repeat rows/columns\r\n    if (this.config.printRepeat) {\r\n      if (this.config.printRepeat.rows) {\r\n        if (Array.isArray(this.config.printRepeat.rows)) {\r\n          const rowsStr = this.config.printRepeat.rows.map(r => r.toString()).join(':');\r\n          ws.pageSetup.printTitlesRow = `$${rowsStr}`;\r\n        } else {\r\n          ws.pageSetup.printTitlesRow = `$${this.config.printRepeat.rows}`;\r\n        }\r\n      }\r\n\r\n      if (this.config.printRepeat.columns) {\r\n        if (Array.isArray(this.config.printRepeat.columns)) {\r\n          const colsStr = this.config.printRepeat.columns\r\n            .map(c => typeof c === 'number' ? this.numberToColumnLetter(c) : c)\r\n            .join(':');\r\n          ws.pageSetup.printTitlesColumn = `$${colsStr}`;\r\n        } else {\r\n          ws.pageSetup.printTitlesColumn = `$${this.config.printRepeat.columns}`;\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica filas y columnas ocultas\r\n   */\r\n  private applyHiddenRowsColumns(ws: ExcelJS.Worksheet): void {\r\n    // Ocultar filas\r\n    for (const rowNum of this.hiddenRows) {\r\n      const row = ws.getRow(rowNum);\r\n      row.hidden = true;\r\n    }\r\n\r\n    // Ocultar columnas\r\n    for (const colNum of this.hiddenColumns) {\r\n      const column = ws.getColumn(colNum);\r\n      column.hidden = true;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica una tabla dinámica (pivot table)\r\n   */\r\n  private async applyPivotTable(ws: ExcelJS.Worksheet, pivotTable: IPivotTable): Promise<void> {\r\n    try {\r\n      // Verificar si la hoja de origen existe si es diferente\r\n      if (pivotTable.sourceSheet) {\r\n        const workbook = ws.workbook;\r\n        const sourceSheet = workbook.getWorksheet(pivotTable.sourceSheet);\r\n        if (!sourceSheet) {\r\n          console.warn(`Source sheet \"${pivotTable.sourceSheet}\" not found for pivot table \"${pivotTable.name}\"`);\r\n          return;\r\n        }\r\n      }\r\n\r\n      // Construir la configuración de la tabla dinámica\r\n      const pivotConfig: any = {\r\n        name: pivotTable.name,\r\n        ref: pivotTable.ref,\r\n        sourceRange: pivotTable.sourceRange,\r\n        fields: {}\r\n      };\r\n\r\n      // Configurar campos\r\n      if (pivotTable.fields.rows && pivotTable.fields.rows.length > 0) {\r\n        pivotConfig.fields.rows = pivotTable.fields.rows;\r\n      }\r\n\r\n      if (pivotTable.fields.columns && pivotTable.fields.columns.length > 0) {\r\n        pivotConfig.fields.columns = pivotTable.fields.columns;\r\n      }\r\n\r\n      if (pivotTable.fields.values && pivotTable.fields.values.length > 0) {\r\n        pivotConfig.fields.values = pivotTable.fields.values.map(v => ({\r\n          name: v.name,\r\n          stat: v.stat\r\n        }));\r\n      }\r\n\r\n      if (pivotTable.fields.filters && pivotTable.fields.filters.length > 0) {\r\n        pivotConfig.fields.filters = pivotTable.fields.filters;\r\n      }\r\n\r\n      // Opciones\r\n      if (pivotTable.options) {\r\n        pivotConfig.options = pivotTable.options;\r\n      }\r\n\r\n      // Agregar la tabla dinámica\r\n      // ExcelJS addPivotTable - verificar si existe el método\r\n      if ((ws as any).addPivotTable) {\r\n        (ws as any).addPivotTable(pivotConfig);\r\n      } else {\r\n        console.warn('Pivot tables require ExcelJS 4.5.0+. Feature may not be fully supported.');\r\n      }\r\n    } catch (error) {\r\n      console.warn('Error adding pivot table:', error);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Convierte un color a formato ExcelJS\r\n   */\r\n  private convertColorToExcelJS(color: string | { r: number; g: number; b: number } | { theme: number }): any {\r\n    if (typeof color === 'string') {\r\n      // Hex color\r\n      if (color.startsWith('#')) {\r\n        const hex = color.substring(1);\r\n        return { argb: `FF${hex.toUpperCase()}` };\r\n      }\r\n      // Named color - intentar convertir\r\n      return { argb: 'FF000000' };\r\n    } else if ('r' in color && 'g' in color && 'b' in color) {\r\n      // RGB object\r\n      const hex = [color.r, color.g, color.b].map(x => {\r\n        const hex = x.toString(16);\r\n        return hex.length === 1 ? '0' + hex : hex;\r\n      }).join('').toUpperCase();\r\n      return { argb: `FF${hex}` };\r\n    } else if ('theme' in color) {\r\n      // Theme color\r\n      return { theme: color.theme };\r\n    }\r\n    return { argb: 'FF000000' };\r\n  }\r\n\r\n  /**\r\n   * Aplica views (freeze panes, split panes, sheet views)\r\n   */\r\n  private applyViews(ws: ExcelJS.Worksheet): void {\r\n    const views: ExcelJS.WorksheetView[] = [];\r\n\r\n    // Freeze panes\r\n    if (this.config.freezePanes) {\r\n      const freezeView: any = {\r\n        state: 'frozen',\r\n        xSplit: this.config.freezePanes.col - 1,\r\n        ySplit: this.config.freezePanes.row - 1,\r\n        topLeftCell: this.config.freezePanes.reference || this.numberToColumnLetter(this.config.freezePanes.col) + String(this.config.freezePanes.row),\r\n        activeCell: this.config.freezePanes.reference || this.numberToColumnLetter(this.config.freezePanes.col) + String(this.config.freezePanes.row)\r\n      };\r\n      views.push(freezeView);\r\n    }\r\n    // Split panes\r\n    else if (this.config.splitPanes) {\r\n      const splitConfig = this.config.splitPanes;\r\n      const splitView: any = {\r\n        state: 'split',\r\n        xSplit: splitConfig.xSplit || 0,\r\n        ySplit: splitConfig.ySplit || 0\r\n      };\r\n\r\n      if (splitConfig.topLeftCell) {\r\n        splitView.topLeftCell = splitConfig.topLeftCell;\r\n      }\r\n\r\n      if (splitConfig.activePane) {\r\n        const paneMap: Record<string, string> = {\r\n          'topLeft': 'topLeft',\r\n          'topRight': 'topRight',\r\n          'bottomLeft': 'bottomLeft',\r\n          'bottomRight': 'bottomRight'\r\n        };\r\n        splitView.activePane = paneMap[splitConfig.activePane] || 'topLeft';\r\n      }\r\n\r\n      views.push(splitView);\r\n    }\r\n    // Sheet views (normal, pageBreakPreview, pageLayout)\r\n    else if (this.config.views) {\r\n      const viewConfig = this.config.views;\r\n      const view: any = {\r\n        state: viewConfig.state === 'pageBreakPreview' || viewConfig.state === 'pageLayout' ? 'normal' : (viewConfig.state || 'normal')\r\n      };\r\n\r\n      if (viewConfig.zoomScale !== undefined) {\r\n        view.zoomScale = viewConfig.zoomScale;\r\n      }\r\n\r\n      if (viewConfig.zoomScaleNormal !== undefined) {\r\n        view.zoomScaleNormal = viewConfig.zoomScaleNormal;\r\n      }\r\n\r\n      if (viewConfig.showGridLines !== undefined) {\r\n        view.showGridLines = viewConfig.showGridLines;\r\n      }\r\n\r\n      if (viewConfig.showRowColHeaders !== undefined) {\r\n        view.showRowColHeaders = viewConfig.showRowColHeaders;\r\n      }\r\n\r\n      if (viewConfig.showRuler !== undefined) {\r\n        view.showRuler = viewConfig.showRuler;\r\n      }\r\n\r\n      if (viewConfig.rightToLeft !== undefined) {\r\n        view.rightToLeft = viewConfig.rightToLeft;\r\n      }\r\n\r\n      views.push(view);\r\n    }\r\n    // Default view if zoom is set\r\n    else if (this.config.zoom) {\r\n      views.push({\r\n        state: 'normal',\r\n        zoomScale: this.config.zoom\r\n      } as any);\r\n    }\r\n\r\n    // Apply views if any were configured\r\n    if (views.length > 0) {\r\n      ws.views = views;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Obtiene un estilo predefinido del workbook\r\n   */\r\n  private getPredefinedStyle(styleName: string): import('../types/style.types').IStyle | undefined {\r\n    if (this.customStyles && this.customStyles[styleName]) {\r\n      return this.customStyles[styleName];\r\n    }\r\n    return undefined;\r\n  }\r\n\r\n  /**\r\n   * Obtiene un estilo del tema para una sección específica\r\n   */\r\n  private getThemeStyle(section: 'header' | 'subHeader' | 'body' | 'footer', rowIndex?: number): import('../types/style.types').IStyle | undefined {\r\n    if (!this.theme || this.theme.autoApplySectionStyles === false) {\r\n      return undefined;\r\n    }\r\n\r\n    if (!this.customStyles) {\r\n      return undefined;\r\n    }\r\n\r\n    // Mapear sección a nombre de estilo del tema\r\n    let styleName = '';\r\n    if (section === 'header') {\r\n      styleName = '__theme_header';\r\n    } else if (section === 'subHeader') {\r\n      styleName = '__theme_subHeader';\r\n    } else if (section === 'body') {\r\n      // Para body, alternar entre normal y alternativo si está disponible\r\n      if (rowIndex !== undefined && rowIndex % 2 === 1 && this.customStyles['__theme_body_alt']) {\r\n        styleName = '__theme_body_alt';\r\n      } else {\r\n        styleName = '__theme_body';\r\n      }\r\n    } else if (section === 'footer') {\r\n      styleName = '__theme_footer';\r\n    }\r\n\r\n    return this.customStyles[styleName];\r\n  }\r\n\r\n  /**\r\n   * Aplica un slicer a una tabla o tabla dinámica\r\n   */\r\n  private async applySlicer(ws: ExcelJS.Worksheet, slicer: ISlicer): Promise<void> {\r\n    try {\r\n      // ExcelJS no tiene soporte directo para slicers en la API pública\r\n      // Se puede implementar usando la estructura XML subyacente, pero es complejo\r\n      // Por ahora, documentamos la funcionalidad y dejamos un placeholder\r\n      // Nota: Los slicers requieren manipulación directa del XML de Excel\r\n      console.warn('Slicers require advanced ExcelJS XML manipulation. Feature documented but not fully implemented.');\r\n\r\n      // Intentar agregar como comentario o nota en la celda de posición\r\n      const colNum = typeof slicer.position.col === 'string'\r\n        ? this.columnLetterToNumber(slicer.position.col)\r\n        : slicer.position.col;\r\n\r\n      const cell = ws.getRow(slicer.position.row).getCell(colNum);\r\n      cell.note = `Slicer: ${slicer.name} for table \"${slicer.targetTable}\" on column \"${slicer.column}\"`;\r\n    } catch (error) {\r\n      console.warn('Error adding slicer:', error);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica una marca de agua al worksheet\r\n   */\r\n  private async applyWatermark(ws: ExcelJS.Worksheet, watermark: IWatermark): Promise<void> {\r\n    try {\r\n      if (watermark.image) {\r\n        // Usar imagen como marca de agua\r\n        const imageConfig: IWorksheetImage = {\r\n          ...watermark.image,\r\n          position: watermark.position ? {\r\n            row: watermark.position.vertical === 'top' ? 1 : watermark.position.vertical === 'bottom' ? 1000 : 500,\r\n            col: watermark.position.horizontal === 'left' ? 1 : watermark.position.horizontal === 'right' ? 20 : 10\r\n          } : { row: 500, col: 10 },\r\n          size: watermark.image.size || {\r\n            width: 400,\r\n            height: 300,\r\n            scaleX: watermark.opacity || 0.3,\r\n            scaleY: watermark.opacity || 0.3\r\n          }\r\n        };\r\n        await this.applyImage(ws, imageConfig);\r\n      } else if (watermark.text) {\r\n        // Crear marca de agua de texto usando una imagen generada\r\n        // Nota: En un entorno real, necesitarías generar una imagen del texto\r\n        // Por ahora, agregamos el texto como comentario en una celda central\r\n        const centerRow = Math.floor((ws.rowCount || 100) / 2);\r\n        const centerCol = Math.floor((ws.columnCount || 20) / 2);\r\n        const cell = ws.getRow(centerRow).getCell(centerCol);\r\n        cell.value = watermark.text;\r\n        cell.style = {\r\n          font: {\r\n            size: watermark.fontSize || 72,\r\n            color: { argb: this.convertColorToExcelJS(watermark.fontColor || '#CCCCCC').argb },\r\n            italic: true\r\n          },\r\n          alignment: {\r\n            horizontal: 'center',\r\n            vertical: 'middle'\r\n          }\r\n        } as any;\r\n      }\r\n    } catch (error) {\r\n      console.warn('Error adding watermark:', error);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Aplica una conexión de datos\r\n   */\r\n  private async applyDataConnection(workbook: ExcelJS.Workbook, connection: IDataConnection): Promise<void> {\r\n    try {\r\n      // ExcelJS no tiene soporte directo para conexiones de datos\r\n      // Las conexiones de datos requieren manipulación del XML de Excel\r\n      // Por ahora, documentamos la funcionalidad\r\n      console.warn('Data connections require advanced ExcelJS XML manipulation. Feature documented but not fully implemented.');\r\n\r\n      // Guardar información de la conexión en los metadatos del workbook\r\n      if (!workbook.model) {\r\n        (workbook as any).model = {};\r\n      }\r\n      if (!(workbook as any).model.dataConnections) {\r\n        (workbook as any).model.dataConnections = [];\r\n      }\r\n      (workbook as any).model.dataConnections.push({\r\n        name: connection.name,\r\n        type: connection.type,\r\n        connectionString: connection.connectionString,\r\n        commandText: connection.commandText,\r\n        refresh: connection.refresh,\r\n        credentials: connection.credentials ? {\r\n          username: connection.credentials.username,\r\n          integratedSecurity: connection.credentials.integratedSecurity\r\n          // No guardar password por seguridad\r\n        } : undefined\r\n      });\r\n    } catch (error) {\r\n      console.warn('Error adding data connection:', error);\r\n    }\r\n  }\r\n}","/**\r\n * Builder-specific type definitions\r\n * Adaptado para usar tipos compartidos de han-documents-core\r\n */\r\n\r\nimport { IWorkbookMetadata, Result, Color } from './core.types';\r\nimport { IWorksheet, IWorksheetConfig } from './worksheet.types';\r\nimport { IStyle } from './style.types';\r\n\r\n// Re-export ErrorType for convenience\r\nexport { ErrorType } from './core.types';\r\n\r\n// Re-export IWorkbookMetadata for convenience\r\nexport type { IWorkbookMetadata } from './core.types';\r\n\r\n/**\r\n * Excel builder configuration interface\r\n */\r\nexport interface IExcelBuilderConfig {\r\n  /** Workbook metadata */\r\n  metadata?: IWorkbookMetadata;\r\n  /** Default worksheet configuration */\r\n  defaultWorksheetConfig?: Partial<IWorksheetConfig>;\r\n  /** Default styles */\r\n  defaultStyles?: {\r\n    header?: IStyle;\r\n    subheader?: IStyle;\r\n    data?: IStyle;\r\n    footer?: IStyle;\r\n    total?: IStyle;\r\n  };\r\n  /** Whether to enable validation */\r\n  enableValidation?: boolean;\r\n  /** Whether to enable events */\r\n  enableEvents?: boolean;\r\n  /** Whether to enable performance monitoring */\r\n  enablePerformanceMonitoring?: boolean;\r\n  /** Maximum number of worksheets */\r\n  maxWorksheets?: number;\r\n  /** Maximum number of rows per worksheet */\r\n  maxRowsPerWorksheet?: number;\r\n  /** Maximum number of columns per worksheet */\r\n  maxColumnsPerWorksheet?: number;\r\n  /** Memory limit in bytes */\r\n  memoryLimit?: number;\r\n}\r\n\r\n/**\r\n * Build options interface\r\n */\r\nexport interface IBuildOptions {\r\n  /** Output format */\r\n  format?: 'xlsx' | 'xls' | 'csv';\r\n  /** Whether to include styles */\r\n  includeStyles?: boolean;\r\n  /** Whether to include formulas */\r\n  includeFormulas?: boolean;\r\n  /** Whether to include comments */\r\n  includeComments?: boolean;\r\n  /** Whether to include data validation */\r\n  includeValidation?: boolean;\r\n  /** Whether to include conditional formatting */\r\n  includeConditionalFormatting?: boolean;\r\n  /** Compression level (0-9) */\r\n  compressionLevel?: number;\r\n  /** Whether to optimize for size */\r\n  optimizeForSize?: boolean;\r\n  /** Whether to optimize for speed */\r\n  optimizeForSpeed?: boolean;\r\n}\r\n\r\n/**\r\n * Download options interface\r\n */\r\nexport interface IDownloadOptions extends IBuildOptions {\r\n  /** File name */\r\n  fileName?: string;\r\n  /** Whether to show download progress */\r\n  showProgress?: boolean;\r\n  /** Progress callback */\r\n  onProgress?: (progress: number) => void;\r\n  /** Whether to auto-download */\r\n  autoDownload?: boolean;\r\n  /** MIME type */\r\n  mimeType?: string;\r\n}\r\n\r\n/**\r\n * Save file options interface (for Node.js)\r\n */\r\nexport interface ISaveFileOptions extends IBuildOptions {\r\n  /** Whether to create parent directories if they don't exist (default: true) */\r\n  createDir?: boolean;\r\n  /** File encoding (default: 'binary') */\r\n  encoding?: 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'latin1' | 'binary' | 'hex';\r\n}\r\n\r\n/**\r\n * Excel builder interface\r\n */\r\nexport interface IExcelBuilder {\r\n  /** Builder configuration */\r\n  config: IExcelBuilderConfig;\r\n  /** Worksheets in the workbook */\r\n  worksheets: Map<string, IWorksheet>;\r\n  /** Current worksheet */\r\n  currentWorksheet: IWorksheet | undefined;\r\n  /** Whether the builder is building */\r\n  isBuilding: boolean;\r\n  /** Build statistics */\r\n  stats: IBuildStats;\r\n\r\n  /** Add a new worksheet */\r\n  addWorksheet(name: string, config?: Partial<IWorksheetConfig>): IWorksheet;\r\n  /** Get a worksheet by name */\r\n  getWorksheet(name: string): IWorksheet | undefined;\r\n  /** Remove a worksheet */\r\n  removeWorksheet(name: string): boolean;\r\n  /** Set the current worksheet */\r\n  setCurrentWorksheet(name: string): boolean;\r\n  /** Build the workbook */\r\n  build(options?: IBuildOptions): Promise<Result<ArrayBuffer>>;\r\n  /** Generate and download the file */\r\n  generateAndDownload(fileName: string, options?: IDownloadOptions): Promise<Result<void>>;\r\n  /** Save file to disk (Node.js only) - Similar to generateAndDownload but for Node.js */\r\n  saveToFile(filePath: string, options?: ISaveFileOptions): Promise<Result<void>>;\r\n  /** Save to stream (Node.js only) - For large files */\r\n  saveToStream(writeStream: { write: (chunk: any, callback?: (error?: Error | null) => void) => boolean }, options?: IBuildOptions): Promise<Result<void>>;\r\n  /** Get workbook as buffer */\r\n  toBuffer(options?: IBuildOptions): Promise<Result<ArrayBuffer>>;\r\n  /** Get workbook as blob */\r\n  toBlob(options?: IBuildOptions): Promise<Result<Blob>>;\r\n  /** Validate the workbook */\r\n  validate(): Result<boolean>;\r\n  /** Clear all worksheets */\r\n  clear(): void;\r\n  /** Get workbook statistics */\r\n  getStats(): IBuildStats;\r\n  /** Add a predefined cell style */\r\n  addCellStyle(name: string, style: IStyle): this;\r\n  /** Get a predefined cell style by name */\r\n  getCellStyle(name: string): IStyle | undefined;\r\n  /** Set workbook theme */\r\n  setTheme(theme: IWorkbookTheme): this;\r\n  /** Get current workbook theme */\r\n  getTheme(): IWorkbookTheme | undefined;\r\n}\r\n\r\n/**\r\n * Build statistics interface\r\n */\r\nexport interface IBuildStats {\r\n  /** Total number of worksheets */\r\n  totalWorksheets: number;\r\n  /** Total number of cells */\r\n  totalCells: number;\r\n  /** Total memory usage in bytes */\r\n  memoryUsage: number;\r\n  /** Build time in milliseconds */\r\n  buildTime: number;\r\n  /** File size in bytes */\r\n  fileSize: number;\r\n  /** Number of styles used */\r\n  stylesUsed: number;\r\n  /** Number of formulas used */\r\n  formulasUsed: number;\r\n  /** Number of conditional formats used */\r\n  conditionalFormatsUsed: number;\r\n  /** Performance metrics */\r\n  performance: {\r\n    /** Time spent building headers */\r\n    headersTime: number;\r\n    /** Time spent building data */\r\n    dataTime: number;\r\n    /** Time spent applying styles */\r\n    stylesTime: number;\r\n    /** Time spent writing to buffer */\r\n    writeTime: number;\r\n  };\r\n}\r\n\r\n/**\r\n * Builder event types\r\n */\r\nexport enum BuilderEventType {\r\n  WORKSHEET_ADDED = 'worksheetAdded',\r\n  WORKSHEET_REMOVED = 'worksheetRemoved',\r\n  WORKSHEET_UPDATED = 'worksheetUpdated',\r\n  BUILD_STARTED = 'buildStarted',\r\n  BUILD_PROGRESS = 'buildProgress',\r\n  BUILD_COMPLETED = 'buildCompleted',\r\n  BUILD_ERROR = 'buildError',\r\n  DOWNLOAD_STARTED = 'downloadStarted',\r\n  DOWNLOAD_PROGRESS = 'downloadProgress',\r\n  DOWNLOAD_COMPLETED = 'downloadCompleted',\r\n  DOWNLOAD_ERROR = 'downloadError'\r\n}\r\n\r\n/**\r\n * Builder event interface\r\n */\r\nexport interface IBuilderEvent {\r\n  type: BuilderEventType;\r\n  data?: Record<string, unknown>;\r\n  timestamp: Date;\r\n}\r\n\r\n/**\r\n * Builder event listener interface\r\n */\r\nexport interface IBuilderEventListener {\r\n  (event: IBuilderEvent): void;\r\n}\r\n\r\n/**\r\n * Builder validation result interface\r\n */\r\nexport interface IBuilderValidationResult {\r\n  /** Whether the builder is valid */\r\n  isValid: boolean;\r\n  /** Validation errors */\r\n  errors: string[];\r\n  /** Validation warnings */\r\n  warnings: string[];\r\n  /** Worksheet validation results */\r\n  worksheetResults: Map<string, boolean>;\r\n}\r\n\r\n/**\r\n * Workbook theme configuration\r\n */\r\nexport interface IWorkbookTheme {\r\n  /** Theme name */\r\n  name?: string;\r\n  /** Color scheme */\r\n  colors?: {\r\n    /** Dark 1 color */\r\n    dark1?: Color;\r\n    /** Light 1 color */\r\n    light1?: Color;\r\n    /** Dark 2 color */\r\n    dark2?: Color;\r\n    /** Light 2 color */\r\n    light2?: Color;\r\n    /** Accent 1 color */\r\n    accent1?: Color;\r\n    /** Accent 2 color */\r\n    accent2?: Color;\r\n    /** Accent 3 color */\r\n    accent3?: Color;\r\n    /** Accent 4 color */\r\n    accent4?: Color;\r\n    /** Accent 5 color */\r\n    accent5?: Color;\r\n    /** Accent 6 color */\r\n    accent6?: Color;\r\n    /** Hyperlink color */\r\n    hyperlink?: Color;\r\n    /** Followed hyperlink color */\r\n    followedHyperlink?: Color;\r\n  };\r\n  /** Font scheme */\r\n  fonts?: {\r\n    /** Major font (headings) */\r\n    major?: {\r\n      latin?: string;\r\n      eastAsian?: string;\r\n      complexScript?: string;\r\n    };\r\n    /** Minor font (body) */\r\n    minor?: {\r\n      latin?: string;\r\n      eastAsian?: string;\r\n      complexScript?: string;\r\n    };\r\n  };\r\n  /** Section styles - automatically applied to headers, footers, body, etc. */\r\n  sectionStyles?: {\r\n    /** Style for main headers */\r\n    header?: {\r\n      backgroundColor?: Color;\r\n      fontColor?: Color;\r\n      fontSize?: number;\r\n      fontBold?: boolean;\r\n      borderColor?: Color;\r\n    };\r\n    /** Style for subheaders */\r\n    subHeader?: {\r\n      backgroundColor?: Color;\r\n      fontColor?: Color;\r\n      fontSize?: number;\r\n      fontBold?: boolean;\r\n      borderColor?: Color;\r\n    };\r\n    /** Style for body/data rows */\r\n    body?: {\r\n      backgroundColor?: Color;\r\n      fontColor?: Color;\r\n      fontSize?: number;\r\n      alternatingRowColor?: Color;\r\n      borderColor?: Color;\r\n    };\r\n    /** Style for footers */\r\n    footer?: {\r\n      backgroundColor?: Color;\r\n      fontColor?: Color;\r\n      fontSize?: number;\r\n      fontBold?: boolean;\r\n      borderColor?: Color;\r\n    };\r\n  };\r\n  /** Whether to automatically apply section styles (default: true) */\r\n  autoApplySectionStyles?: boolean;\r\n}\r\n\r\n","/**\r\n * ExcelBuilder - Main class for creating Excel workbooks\r\n * \r\n * This class provides a fluent API for creating complex Excel files with multiple worksheets,\r\n * advanced styling, themes, and comprehensive features. It works in both browser and Node.js environments.\r\n * \r\n * @example\r\n * ```typescript\r\n * const builder = new ExcelBuilder({\r\n *   metadata: {\r\n *     title: 'Sales Report',\r\n *     author: 'My Company'\r\n *   }\r\n * });\r\n * \r\n * const worksheet = builder.addWorksheet('Sales');\r\n * worksheet.addHeader({ key: 'title', value: 'Monthly Report', type: CellType.STRING });\r\n * \r\n * // Browser\r\n * await builder.generateAndDownload('report.xlsx');\r\n * \r\n * // Node.js\r\n * await builder.saveToFile('./output/report.xlsx');\r\n * ```\r\n */\r\n\r\nimport * as ExcelJS from 'exceljs';\r\nimport saveAs from 'file-saver';\r\nimport { \r\n  IDocumentMetadata, \r\n  Result, \r\n  success, \r\n  error, \r\n  ErrorType as CoreErrorType,\r\n  IDocumentBuilder,\r\n  IFileBuilder,\r\n  IDownloadBuilder\r\n} from '@hannndler/core';\r\nimport { EventEmitter } from '../utils/EventEmitter';\r\nimport { Worksheet } from './Worksheet';\r\nimport {\r\n  IExcelBuilder,\r\n  IExcelBuilderConfig,\r\n  IBuildOptions,\r\n  IDownloadOptions,\r\n  ISaveFileOptions,\r\n  IBuildStats,\r\n  BuilderEventType,\r\n  IBuilderEvent,\r\n  ErrorType,\r\n  IWorkbookTheme,\r\n  IWorkbookMetadata\r\n} from '../types/builder.types';\r\nimport { Color, ISuccessResult, IErrorResult } from '../types/core.types';\r\nimport {\r\n  IWorksheet,\r\n  IWorksheetConfig\r\n} from '../types/worksheet.types';\r\n\r\n/**\r\n * ExcelBuilder class for creating Excel workbooks\r\n * \r\n * Main entry point for creating Excel files. Supports multiple worksheets, themes,\r\n * predefined styles, and comprehensive Excel features.\r\n * \r\n * @class ExcelBuilder\r\n * @implements {IExcelBuilder}\r\n * @implements {IDocumentBuilder<IBuildOptions, ArrayBuffer>}\r\n * @implements {IFileBuilder<ISaveFileOptions>}\r\n * @implements {IDownloadBuilder<IDownloadOptions>}\r\n */\r\nexport class ExcelBuilder implements \r\n  IExcelBuilder,\r\n  IDocumentBuilder<IBuildOptions, ArrayBuffer>,\r\n  IFileBuilder<ISaveFileOptions>,\r\n  IDownloadBuilder<IDownloadOptions> {\r\n  public config: IExcelBuilderConfig;\r\n  public worksheets: Map<string, IWorksheet> = new Map();\r\n  public currentWorksheet: IWorksheet | undefined;\r\n  public isBuilding = false;\r\n  public stats: IBuildStats;\r\n\r\n  private eventEmitter: EventEmitter;\r\n  private cellStyles: Map<string, import('../types/style.types').IStyle> = new Map();\r\n  private theme: IWorkbookTheme | undefined;\r\n\r\n  /**\r\n   * Creates a new ExcelBuilder instance\r\n   * \r\n   * @param {IExcelBuilderConfig} config - Configuration options for the builder\r\n   * @param {IWorkbookMetadata} [config.metadata] - Workbook metadata (title, author, description, etc.)\r\n   * @param {Partial<IWorksheetConfig>} [config.defaultWorksheetConfig] - Default configuration for all worksheets\r\n   * @param {boolean} [config.enableValidation=true] - Enable data validation\r\n   * @param {boolean} [config.enableEvents=true] - Enable event system\r\n   * @param {boolean} [config.enablePerformanceMonitoring=false] - Enable performance monitoring\r\n   * @param {number} [config.maxWorksheets=255] - Maximum number of worksheets allowed\r\n   * @param {number} [config.maxRowsPerWorksheet=1048576] - Maximum rows per worksheet\r\n   * @param {number} [config.maxColumnsPerWorksheet=16384] - Maximum columns per worksheet\r\n   * @param {number} [config.memoryLimit=104857600] - Memory limit in bytes (100MB default)\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const builder = new ExcelBuilder({\r\n   *   metadata: {\r\n   *     title: 'Annual Report',\r\n   *     author: 'John Doe',\r\n   *     description: 'Company annual report for 2024'\r\n   *   },\r\n   *   enableValidation: true,\r\n   *   enableEvents: true\r\n   * });\r\n   * ```\r\n   */\r\n  constructor(config: IExcelBuilderConfig = {}) {\r\n    this.config = {\r\n      enableValidation: true,\r\n      enableEvents: true,\r\n      enablePerformanceMonitoring: false,\r\n      maxWorksheets: 255,\r\n      maxRowsPerWorksheet: 1048576,\r\n      maxColumnsPerWorksheet: 16384,\r\n      memoryLimit: 100 * 1024 * 1024, // 100MB\r\n      ...config\r\n    };\r\n\r\n    this.stats = this.initializeStats();\r\n    this.eventEmitter = new EventEmitter();\r\n  }\r\n\r\n  /**\r\n   * Add a new worksheet to the workbook\r\n   * \r\n   * Creates a new worksheet with the specified name and configuration. The worksheet\r\n   * becomes the current worksheet automatically. If a worksheet with the same name\r\n   * already exists, an error is thrown.\r\n   * \r\n   * @param {string} name - Unique name for the worksheet (required, must be unique)\r\n   * @param {Partial<IWorksheetConfig>} [worksheetConfig={}] - Configuration for the worksheet\r\n   * @param {string} [worksheetConfig.tabColor] - Tab color (hex format, e.g., '#FF0000')\r\n   * @param {number} [worksheetConfig.defaultRowHeight=20] - Default row height in points\r\n   * @param {number} [worksheetConfig.defaultColWidth=10] - Default column width in characters\r\n   * @param {boolean} [worksheetConfig.hidden=false] - Whether the worksheet is hidden\r\n   * @param {boolean} [worksheetConfig.protected=false] - Whether the worksheet is protected\r\n   * @param {string} [worksheetConfig.protectionPassword] - Password for worksheet protection\r\n   * @param {boolean} [worksheetConfig.showGridLines=true] - Show grid lines\r\n   * @param {boolean} [worksheetConfig.showRowColHeaders=true] - Show row and column headers\r\n   * @param {number} [worksheetConfig.zoom] - Zoom level (10-400)\r\n   * \r\n   * @returns {IWorksheet} The newly created worksheet instance\r\n   * \r\n   * @throws {Error} If a worksheet with the same name already exists\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Simple worksheet\r\n   * const sheet1 = builder.addWorksheet('Sales');\r\n   * \r\n   * // Worksheet with configuration\r\n   * const sheet2 = builder.addWorksheet('Summary', {\r\n   *   tabColor: '#4472C4',\r\n   *   defaultRowHeight: 25,\r\n   *   defaultColWidth: 15,\r\n   *   protected: true,\r\n   *   protectionPassword: 'mypassword'\r\n   * });\r\n   * ```\r\n   */\r\n  addWorksheet(name: string, worksheetConfig: Partial<IWorksheetConfig> = {}): IWorksheet {\r\n    if (this.worksheets.has(name)) {\r\n      throw new Error(`Worksheet \"${name}\" already exists`);\r\n    }\r\n\r\n    const config: IWorksheetConfig = {\r\n      name,\r\n      defaultRowHeight: 20,\r\n      defaultColWidth: 10,\r\n      ...this.config.defaultWorksheetConfig,\r\n      ...worksheetConfig\r\n    };\r\n\r\n    const worksheet = new Worksheet(config);\r\n    this.worksheets.set(name, worksheet);\r\n    this.currentWorksheet = worksheet;\r\n    \r\n    this.emitEvent(BuilderEventType.WORKSHEET_ADDED, { worksheetName: name });\r\n    \r\n    return worksheet;\r\n  }\r\n\r\n  /**\r\n   * Get a worksheet by name\r\n   * \r\n   * Retrieves an existing worksheet from the workbook by its name.\r\n   * Returns undefined if the worksheet doesn't exist.\r\n   * \r\n   * @param {string} name - Name of the worksheet to retrieve\r\n   * @returns {IWorksheet | undefined} The worksheet if found, undefined otherwise\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const worksheet = builder.getWorksheet('Sales');\r\n   * if (worksheet) {\r\n   *   worksheet.addRow([...]);\r\n   * }\r\n   * ```\r\n   */\r\n  getWorksheet(name: string): IWorksheet | undefined {\r\n    return this.worksheets.get(name);\r\n  }\r\n\r\n  /**\r\n   * Remove a worksheet by name\r\n   * \r\n   * Removes a worksheet from the workbook. If the removed worksheet was the current\r\n   * worksheet, the current worksheet is cleared.\r\n   * \r\n   * @param {string} name - Name of the worksheet to remove\r\n   * @returns {boolean} True if the worksheet was found and removed, false otherwise\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const removed = builder.removeWorksheet('OldSheet');\r\n   * if (removed) {\r\n   *   console.log('Worksheet removed successfully');\r\n   * }\r\n   * ```\r\n   */\r\n  removeWorksheet(name: string): boolean {\r\n    const worksheet = this.worksheets.get(name);\r\n    if (!worksheet) {\r\n      return false;\r\n    }\r\n\r\n    this.worksheets.delete(name);\r\n    \r\n    // If this was the current worksheet, clear it\r\n    if (this.currentWorksheet === worksheet) {\r\n      this.currentWorksheet = undefined;\r\n    }\r\n    \r\n    this.emitEvent(BuilderEventType.WORKSHEET_REMOVED, { worksheetName: name });\r\n    \r\n    return true;\r\n  }\r\n\r\n  /**\r\n   * Set the current worksheet\r\n   * \r\n   * Sets the active worksheet. Operations like addRow() will be performed on the\r\n   * current worksheet. When you add a new worksheet, it automatically becomes the current one.\r\n   * \r\n   * @param {string} name - Name of the worksheet to set as current\r\n   * @returns {boolean} True if the worksheet was found and set, false otherwise\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * builder.addWorksheet('Sheet1');\r\n   * builder.addWorksheet('Sheet2');\r\n   * \r\n   * // Switch back to Sheet1\r\n   * builder.setCurrentWorksheet('Sheet1');\r\n   * ```\r\n   */\r\n  setCurrentWorksheet(name: string): boolean {\r\n    const worksheet = this.worksheets.get(name);\r\n    if (!worksheet) {\r\n      return false;\r\n    }\r\n    \r\n    this.currentWorksheet = worksheet;\r\n    return true;\r\n  }\r\n\r\n  /**\r\n   * Set metadata for the workbook\r\n   * \r\n   * Updates the workbook metadata. This method is part of the IDocumentBuilder interface\r\n   * and allows setting metadata after the builder has been created.\r\n   * \r\n   * @param {IDocumentMetadata} metadata - Document metadata to set\r\n   * @returns {this} This builder instance for method chaining\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * builder.setMetadata({\r\n   *   title: 'Annual Report',\r\n   *   author: 'John Doe',\r\n   *   description: 'Company annual report for 2024'\r\n   * });\r\n   * ```\r\n   */\r\n  setMetadata(metadata: IDocumentMetadata): this {\r\n    this.config.metadata = metadata as IWorkbookMetadata;\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Build the workbook and return as ArrayBuffer\r\n   * \r\n   * Compiles all worksheets, applies themes and styles, and generates the Excel file\r\n   * as an ArrayBuffer. This is the core method that all export methods use internally.\r\n   * \r\n   * The build process:\r\n   * 1. Creates a new ExcelJS workbook\r\n   * 2. Applies workbook metadata\r\n   * 3. Applies theme (if set)\r\n   * 4. Adds predefined cell styles\r\n   * 5. Builds each worksheet\r\n   * 6. Writes to buffer with compression\r\n   * \r\n   * @param {IBuildOptions} [options={}] - Build options\r\n   * @param {'xlsx' | 'xls' | 'csv'} [options.format='xlsx'] - Output format\r\n   * @param {boolean} [options.includeStyles=true] - Include cell styles\r\n   * @param {number} [options.compressionLevel=6] - Compression level (0-9, higher = more compression)\r\n   * @param {boolean} [options.optimizeForSpeed=false] - Optimize for speed over file size\r\n   * \r\n   * @returns {Promise<Result<ArrayBuffer>>} Result containing the Excel file as ArrayBuffer\r\n   * \r\n   * @throws {Error} If build is already in progress (prevents concurrent builds)\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Basic build\r\n   * const result = await builder.build();\r\n   * if (result.success) {\r\n   *   const buffer = result.data;\r\n   *   // Use buffer...\r\n   * }\r\n   * \r\n   * // Build with options\r\n   * const result = await builder.build({\r\n   *   compressionLevel: 9, // Maximum compression\r\n   *   optimizeForSpeed: true\r\n   * });\r\n   * ```\r\n   */\r\n  async build(options: IBuildOptions = {}): Promise<Result<ArrayBuffer>> {\r\n    if (this.isBuilding) {\r\n      return error(\r\n        CoreErrorType.BUILD_ERROR,\r\n        'Build already in progress',\r\n        'BUILD_IN_PROGRESS'\r\n      );\r\n    }\r\n\r\n    this.isBuilding = true;\r\n    const startTime = Date.now();\r\n    \r\n    try {\r\n      this.emitEvent(BuilderEventType.BUILD_STARTED);\r\n      \r\n      const workbook = new ExcelJS.Workbook();\r\n      \r\n      // Add metadata using IDocumentMetadata from core\r\n      if (this.config.metadata) {\r\n        const metadata = this.config.metadata as IWorkbookMetadata;\r\n        workbook.creator = metadata.author || 'Han Excel Builder';\r\n        workbook.lastModifiedBy = metadata.author || 'Han Excel Builder';\r\n        workbook.created = metadata.created || new Date();\r\n        workbook.modified = metadata.modified || new Date();\r\n        if (metadata.title) workbook.title = metadata.title;\r\n        if (metadata.subject) workbook.subject = metadata.subject;\r\n        if (metadata.keywords) workbook.keywords = Array.isArray(metadata.keywords) ? metadata.keywords.join(', ') : metadata.keywords;\r\n        if (metadata.category) workbook.category = metadata.category;\r\n        if (metadata.description) workbook.description = metadata.description;\r\n        if (metadata.company) workbook.company = metadata.company;\r\n        if (metadata.hyperlinkBase) {\r\n          // hyperlinkBase is not directly available in ExcelJS WorkbookProperties\r\n          // Store it in custom properties if needed\r\n          (workbook as any).hyperlinkBase = metadata.hyperlinkBase;\r\n        }\r\n      }\r\n\r\n      // Apply theme if set\r\n      if (this.theme) {\r\n        this.applyTheme(workbook, this.theme);\r\n      }\r\n\r\n      // Add predefined cell styles\r\n      for (const [name, style] of this.cellStyles.entries()) {\r\n        this.addStyleToWorkbook(workbook, name, style);\r\n      }\r\n\r\n      // Build each worksheet\r\n      for (const worksheet of this.worksheets.values()) {\r\n        await (worksheet as Worksheet).build(workbook, options);\r\n      }\r\n\r\n      // Write to buffer\r\n      const buffer = await workbook.xlsx.writeBuffer({\r\n        compression: options.compressionLevel || 6\r\n      } as any);\r\n\r\n      const endTime = Date.now();\r\n      this.stats.buildTime = endTime - startTime;\r\n      this.stats.fileSize = buffer.byteLength;\r\n      \r\n      this.emitEvent(BuilderEventType.BUILD_COMPLETED, {\r\n        buildTime: this.stats.buildTime,\r\n        fileSize: this.stats.fileSize\r\n      });\r\n\r\n      return success(buffer);\r\n\r\n    } catch (err: any) {\r\n      const errorResult = error(\r\n        CoreErrorType.BUILD_ERROR,\r\n        err.message || 'Failed to build workbook',\r\n        'BUILD_FAILED',\r\n        { originalError: err }\r\n      );\r\n\r\n      this.emitEvent(BuilderEventType.BUILD_ERROR, {\r\n        error: err.message\r\n      });\r\n\r\n      return errorResult;\r\n    } finally {\r\n      this.isBuilding = false;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Generate and download the file (Browser only)\r\n   * \r\n   * Builds the Excel file and automatically triggers a download in the user's browser.\r\n   * This is the simplest method for browser environments - just one method call!\r\n   * \r\n   * **Note**: This method is designed for browser environments. For Node.js, use `saveToFile()` instead.\r\n   * \r\n   * @param {string} fileName - Name of the file to download (e.g., 'report.xlsx')\r\n   * @param {IDownloadOptions} [options={}] - Download options\r\n   * @param {string} [options.mimeType] - MIME type (default: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')\r\n   * @param {number} [options.compressionLevel=6] - Compression level (0-9)\r\n   * @param {boolean} [options.includeStyles=true] - Include cell styles\r\n   * \r\n   * @returns {Promise<Result<void>>} Result indicating success or failure\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Simple download\r\n   * const result = await builder.generateAndDownload('sales-report.xlsx');\r\n   * \r\n   * if (result.success) {\r\n   *   console.log('File downloaded successfully!');\r\n   * } else {\r\n   *   console.error('Download failed:', result.error);\r\n   * }\r\n   * \r\n   * // With options\r\n   * await builder.generateAndDownload('report.xlsx', {\r\n   *   compressionLevel: 9,\r\n   *   mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'\r\n   * });\r\n   * ```\r\n   */\r\n  async generateAndDownload(fileName: string, options: IDownloadOptions = {}): Promise<Result<void>> {\r\n    const buildResult = await this.build(options);\r\n    \r\n    if (!buildResult.success) {\r\n      return buildResult;\r\n    }\r\n\r\n    try {\r\n      this.emitEvent(BuilderEventType.DOWNLOAD_STARTED, { fileName });\r\n      \r\n      const blob = new Blob([buildResult.data], { \r\n        type: options.mimeType || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' \r\n      });\r\n      \r\n      saveAs(blob, fileName);\r\n      \r\n      this.emitEvent(BuilderEventType.DOWNLOAD_COMPLETED, { fileName });\r\n      \r\n      return success(undefined);\r\n\r\n    } catch (err: any) {\r\n      const errorResult = error(\r\n        CoreErrorType.FILE_ERROR,\r\n        err.message || 'Download failed',\r\n        'DOWNLOAD_FAILED'\r\n      );\r\n\r\n      this.emitEvent(BuilderEventType.DOWNLOAD_ERROR, { error: err.message });\r\n      return errorResult;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Save file to disk (Node.js only)\r\n   * \r\n   * Builds the Excel file and saves it directly to the file system. This is the Node.js\r\n   * equivalent of `generateAndDownload()` - just as simple! Automatically creates parent\r\n   * directories if they don't exist.\r\n   * \r\n   * **Note**: This method only works in Node.js environments. For browsers, use `generateAndDownload()`.\r\n   * \r\n   * @param {string} filePath - Full path where to save the file (e.g., './output/report.xlsx')\r\n   * @param {ISaveFileOptions} [options={}] - Save options\r\n   * @param {boolean} [options.createDir=true] - Create parent directories if they don't exist\r\n   * @param {string} [options.encoding='binary'] - File encoding ('binary', 'base64', etc.)\r\n   * @param {number} [options.compressionLevel=6] - Compression level (0-9)\r\n   * @param {boolean} [options.includeStyles=true] - Include cell styles\r\n   * \r\n   * @returns {Promise<Result<void>>} Result indicating success or failure\r\n   * \r\n   * @throws {Error} If called in browser environment (use `generateAndDownload()` instead)\r\n   * @throws {Error} If Node.js modules (fs, path, buffer) are not available\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Simple save - creates directories automatically\r\n   * const result = await builder.saveToFile('./output/report.xlsx');\r\n   * \r\n   * if (result.success) {\r\n   *   console.log('File saved successfully!');\r\n   * }\r\n   * \r\n   * // With options\r\n   * await builder.saveToFile('./reports/sales.xlsx', {\r\n   *   createDir: true,  // Create ./reports/ if it doesn't exist\r\n   *   encoding: 'binary',\r\n   *   compressionLevel: 9\r\n   * });\r\n   * ```\r\n   */\r\n  async saveToFile(filePath: string, options: ISaveFileOptions = {}): Promise<Result<void>> {\r\n    const buildResult = await this.build(options);\r\n    \r\n    if (!buildResult.success) {\r\n      return buildResult;\r\n    }\r\n\r\n    try {\r\n      // Check if we're in Node.js\r\n      if (typeof window !== 'undefined') {\r\n        return error(\r\n          CoreErrorType.FILE_ERROR,\r\n          'saveToFile() is only available in Node.js. Use generateAndDownload() in the browser.',\r\n          'BROWSER_ENVIRONMENT'\r\n        );\r\n      }\r\n\r\n      this.emitEvent(BuilderEventType.DOWNLOAD_STARTED, { fileName: filePath });\r\n      \r\n      // Dynamic import of Node.js modules to avoid issues in browser builds\r\n      const nodeModules = await (async () => {\r\n        try {\r\n          // Prefer require() at runtime when available to avoid Vite externalization\r\n          // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n          const fsReq = typeof require === 'function' ? (require as any)('fs/promises') : undefined;\r\n          // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n          const pathReq = typeof require === 'function' ? (require as any)('path') : undefined;\r\n          // eslint-disable-next-line @typescript-eslint/no-var-requires\r\n          const bufferReq = typeof require === 'function' ? (require as any)('buffer') : undefined;\r\n\r\n          const fsMod = fsReq ?? (await import('fs/promises'));\r\n          const pathMod = pathReq ?? (await import('path'));\r\n          const bufferMod = bufferReq ?? (await import('buffer'));\r\n\r\n          // Some bundlers/targets may wrap CommonJS modules under a `.default` property.\r\n          const fs = (fsMod as any).default ?? fsMod;\r\n          const path = (pathMod as any).default ?? pathMod;\r\n          const Buffer = (bufferMod as any).default?.Buffer ?? (bufferMod as any).Buffer ?? (bufferMod as any);\r\n\r\n          return { fs, path, Buffer };\r\n        } catch {\r\n          throw new Error('Node.js modules not available. saveToFile() requires Node.js environment.');\r\n        }\r\n      })();\r\n      \r\n      // Create directory if needed\r\n      if (options.createDir !== false) {\r\n        const dir = nodeModules.path.dirname(filePath);\r\n        try {\r\n          await nodeModules.fs.mkdir(dir, { recursive: true });\r\n        } catch (error: any) {\r\n          // Ignore error if directory already exists\r\n          if (error?.code !== 'EEXIST') {\r\n            throw error;\r\n          }\r\n        }\r\n      }\r\n      \r\n      // Convert ArrayBuffer to Buffer and write to file\r\n      const buffer = nodeModules.Buffer.from(buildResult.data);\r\n      await nodeModules.fs.writeFile(filePath, buffer, { encoding: options.encoding || 'binary' });\r\n      \r\n      this.emitEvent(BuilderEventType.DOWNLOAD_COMPLETED, { fileName: filePath });\r\n      \r\n      return success(undefined);\r\n\r\n    } catch (err: any) {\r\n      const errorResult = error(\r\n        CoreErrorType.FILE_ERROR,\r\n        err.message || 'Failed to save file',\r\n        'SAVE_FAILED'\r\n      );\r\n\r\n      this.emitEvent(BuilderEventType.DOWNLOAD_ERROR, { error: err.message });\r\n      return errorResult;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Save to stream (Node.js only) - For large files\r\n   * \r\n   * Builds the Excel file and writes it directly to a writable stream. This is ideal\r\n   * for very large files or when you need to stream the data (e.g., HTTP responses,\r\n   * file uploads, etc.).\r\n   * \r\n   * **Note**: This method only works in Node.js environments.\r\n   * \r\n   * @param {NodeJS.WritableStream} writeStream - Writable stream to write the file to\r\n   * @param {IBuildOptions} [options={}] - Build options\r\n   * @param {number} [options.compressionLevel=6] - Compression level (0-9)\r\n   * @param {boolean} [options.includeStyles=true] - Include cell styles\r\n   * \r\n   * @returns {Promise<Result<void>>} Result indicating success or failure\r\n   * \r\n   * @throws {Error} If called in browser environment\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * import fs from 'fs';\r\n   * \r\n   * // Save to file stream\r\n   * const writeStream = fs.createWriteStream('./output/report.xlsx');\r\n   * const result = await builder.saveToStream(writeStream);\r\n   * \r\n   * if (result.success) {\r\n   *   writeStream.end();\r\n   *   console.log('File streamed successfully!');\r\n   * }\r\n   * \r\n   * // HTTP response stream\r\n   * app.get('/download', async (req, res) => {\r\n   *   res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');\r\n   *   await builder.saveToStream(res);\r\n   * });\r\n   * ```\r\n   */\r\n  async saveToStream(writeStream: { write: (chunk: any, callback?: (error?: Error | null) => void) => boolean }, options: IBuildOptions = {}): Promise<Result<void>> {\r\n    const buildResult = await this.build(options);\r\n    \r\n    if (!buildResult.success) {\r\n      return buildResult;\r\n    }\r\n\r\n    try {\r\n      // Check if we're in Node.js\r\n      if (typeof window !== 'undefined') {\r\n        return error(\r\n          CoreErrorType.FILE_ERROR,\r\n          'saveToStream() is only available in Node.js.',\r\n          'BROWSER_ENVIRONMENT'\r\n        );\r\n      }\r\n\r\n      this.emitEvent(BuilderEventType.DOWNLOAD_STARTED, { fileName: 'stream' });\r\n      \r\n      // Dynamic import of Node.js buffer module\r\n      // @ts-ignore - Dynamic import for Node.js only\r\n      const bufferModule = await import('buffer');\r\n      const buffer = bufferModule.Buffer.from(buildResult.data);\r\n      \r\n      return new Promise((resolve) => {\r\n        writeStream.write(buffer, (error: any) => {\r\n          if (error) {\r\n            const errorResult = error(\r\n              CoreErrorType.FILE_ERROR,\r\n              error.message || 'Failed to write to stream',\r\n              'STREAM_WRITE_FAILED'\r\n            );\r\n            this.emitEvent(BuilderEventType.DOWNLOAD_ERROR, { error: error.message });\r\n            resolve(errorResult);\r\n          } else {\r\n            this.emitEvent(BuilderEventType.DOWNLOAD_COMPLETED, { fileName: 'stream' });\r\n            resolve(success(undefined));\r\n          }\r\n        });\r\n      });\r\n\r\n    } catch (err: any) {\r\n      const errorResult = error(\r\n        CoreErrorType.FILE_ERROR,\r\n        err.message || 'Failed to save to stream',\r\n        'STREAM_FAILED'\r\n      );\r\n\r\n      this.emitEvent(BuilderEventType.DOWNLOAD_ERROR, { error: err.message });\r\n      return errorResult;\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Get workbook as ArrayBuffer\r\n   * \r\n   * Builds the Excel file and returns it as an ArrayBuffer. This is useful when you need\r\n   * the raw binary data for custom handling (e.g., sending via WebSocket, processing with\r\n   * other libraries, manual file operations, etc.).\r\n   * \r\n   * Works in both browser and Node.js environments.\r\n   * \r\n   * @param {IBuildOptions} [options={}] - Build options\r\n   * @param {number} [options.compressionLevel=6] - Compression level (0-9)\r\n   * @param {boolean} [options.includeStyles=true] - Include cell styles\r\n   * \r\n   * @returns {Promise<Result<ArrayBuffer>>} Result containing the Excel file as ArrayBuffer\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Browser: Get buffer for custom handling\r\n   * const result = await builder.toBuffer();\r\n   * if (result.success) {\r\n   *   const buffer = result.data;\r\n   *   // Upload to server, send via WebSocket, etc.\r\n   * }\r\n   * \r\n   * // Node.js: Get buffer for manual file write\r\n   * const result = await builder.toBuffer();\r\n   * if (result.success) {\r\n   *   const fs = await import('fs/promises');\r\n   *   await fs.writeFile('./report.xlsx', Buffer.from(result.data));\r\n   * }\r\n   * ```\r\n   */\r\n  async toBuffer(options: IBuildOptions = {}): Promise<Result<ArrayBuffer>> {\r\n    return this.build(options);\r\n  }\r\n\r\n  /**\r\n   * Get workbook as Blob\r\n   * \r\n   * Builds the Excel file and returns it as a Blob object. This is useful in browser\r\n   * environments when you need to upload to a server, create object URLs for preview,\r\n   * or handle the file programmatically without triggering an automatic download.\r\n   * \r\n   * **Note**: Blob is a browser API. In Node.js, use `toBuffer()` instead.\r\n   * \r\n   * @param {IBuildOptions} [options={}] - Build options\r\n   * @param {number} [options.compressionLevel=6] - Compression level (0-9)\r\n   * @param {boolean} [options.includeStyles=true] - Include cell styles\r\n   * \r\n   * @returns {Promise<Result<Blob>>} Result containing the Excel file as Blob\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Get as Blob for upload\r\n   * const result = await builder.toBlob();\r\n   * if (result.success) {\r\n   *   const blob = result.data;\r\n   *   \r\n   *   // Upload to server\r\n   *   const formData = new FormData();\r\n   *   formData.append('file', blob, 'report.xlsx');\r\n   *   await fetch('/api/upload', { method: 'POST', body: formData });\r\n   *   \r\n   *   // Or create preview URL\r\n   *   const url = URL.createObjectURL(blob);\r\n   *   window.open(url);\r\n   * }\r\n   * ```\r\n   */\r\n  async toBlob(options: IBuildOptions = {}): Promise<Result<Blob>> {\r\n    const buildResult = await this.build(options);\r\n    \r\n    if (!buildResult.success) {\r\n      return buildResult;\r\n    }\r\n\r\n    const blob = new Blob([buildResult.data], { \r\n      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' \r\n    });\r\n    \r\n    return success(blob);\r\n  }\r\n\r\n  /**\r\n   * Validate the workbook\r\n   * \r\n   * Performs validation checks on the workbook to ensure it's ready for building.\r\n   * Validates that worksheets exist and each worksheet is valid.\r\n   * \r\n   * @returns {Result<boolean>} Result indicating if the workbook is valid\r\n   * - `success: true` - Workbook is valid and ready to build\r\n   * - `success: false` - Validation errors found (check `error.message` for details)\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const validation = builder.validate();\r\n   * if (!validation.success) {\r\n   *   console.error('Validation errors:', validation.error?.message);\r\n   *   return;\r\n   * }\r\n   * \r\n   * // Safe to build\r\n   * await builder.build();\r\n   * ```\r\n   */\r\n  validate(): Result<boolean> {\r\n    const errors: string[] = [];\r\n    \r\n    if (this.worksheets.size === 0) {\r\n      errors.push('No worksheets found');\r\n    }\r\n\r\n    // Validate each worksheet\r\n    for (const [name, worksheet] of this.worksheets.entries()) {\r\n      const worksheetValidation = (worksheet as Worksheet).validate();\r\n      if (!worksheetValidation.success) {\r\n        errors.push(`Worksheet \"${name}\": ${worksheetValidation.error?.message}`);\r\n      }\r\n    }\r\n\r\n    if (errors.length > 0) {\r\n      return error(\r\n        CoreErrorType.VALIDATION_ERROR,\r\n        errors.join('; '),\r\n        'VALIDATION_FAILED'\r\n      );\r\n    }\r\n\r\n    return success(true);\r\n  }\r\n\r\n  /**\r\n   * Clear all worksheets and reset the builder\r\n   * \r\n   * Removes all worksheets, clears predefined cell styles, resets the theme,\r\n   * and clears the current worksheet. This effectively resets the builder to\r\n   * its initial state.\r\n   * \r\n   * @returns {void}\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Clear everything and start fresh\r\n   * builder.clear();\r\n   * \r\n   * // Now add new worksheets\r\n   * builder.addWorksheet('NewSheet');\r\n   * ```\r\n   */\r\n  clear(): void {\r\n    this.worksheets.clear();\r\n    this.currentWorksheet = undefined;\r\n    this.cellStyles.clear();\r\n    this.theme = undefined;\r\n    this.stats = this.initializeStats();\r\n  }\r\n\r\n  /**\r\n   * Get workbook statistics\r\n   * \r\n   * Returns build statistics including build time, file size, number of worksheets,\r\n   * cells, styles used, and performance metrics. Statistics are updated after each build.\r\n   * \r\n   * @returns {IBuildStats} Statistics object containing:\r\n   * - `totalWorksheets` - Number of worksheets\r\n   * - `totalCells` - Total number of cells\r\n   * - `memoryUsage` - Memory usage in bytes\r\n   * - `buildTime` - Last build time in milliseconds\r\n   * - `fileSize` - Last build file size in bytes\r\n   * - `stylesUsed` - Number of unique styles used\r\n   * - `formulasUsed` - Number of formulas\r\n   * - `conditionalFormatsUsed` - Number of conditional formats\r\n   * - `performance` - Performance breakdown by operation\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * await builder.build();\r\n   * const stats = builder.getStats();\r\n   * \r\n   * console.log(`Build time: ${stats.buildTime}ms`);\r\n   * console.log(`File size: ${stats.fileSize} bytes`);\r\n   * console.log(`Worksheets: ${stats.totalWorksheets}`);\r\n   * ```\r\n   */\r\n  getStats(): IBuildStats {\r\n    return { ...this.stats };\r\n  }\r\n\r\n  /**\r\n   * Add a predefined cell style\r\n   * \r\n   * Defines a reusable cell style that can be referenced by name in cells using\r\n   * the `styleName` property. This is useful for maintaining consistent styling\r\n   * across the workbook and reducing code duplication.\r\n   * \r\n   * Styles are stored at the workbook level and can be used in any worksheet.\r\n   * \r\n   * @param {string} name - Unique name for the style (used to reference it later)\r\n   * @param {IStyle} style - Style object created with StyleBuilder\r\n   * @returns {this} Returns the builder instance for method chaining\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Define reusable styles\r\n   * builder.addCellStyle('headerStyle', StyleBuilder.create()\r\n   *   .font({ name: 'Arial', size: 14, bold: true })\r\n   *   .fill({ backgroundColor: '#4472C4' })\r\n   *   .fontColor('#FFFFFF')\r\n   *   .build()\r\n   * );\r\n   * \r\n   * // Use in cells\r\n   * worksheet.addHeader({\r\n   *   key: 'title',\r\n   *   value: 'Report',\r\n   *   type: CellType.STRING,\r\n   *   styleName: 'headerStyle' // Reference the predefined style\r\n   * });\r\n   * ```\r\n   */\r\n  addCellStyle(name: string, style: import('../types/style.types').IStyle): this {\r\n    this.cellStyles.set(name, style);\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Get a predefined cell style by name\r\n   * \r\n   * Retrieves a previously defined cell style by its name. Returns undefined\r\n   * if the style doesn't exist.\r\n   * \r\n   * @param {string} name - Name of the style to retrieve\r\n   * @returns {IStyle | undefined} The style if found, undefined otherwise\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const style = builder.getCellStyle('headerStyle');\r\n   * if (style) {\r\n   *   console.log('Style found:', style);\r\n   * }\r\n   * ```\r\n   */\r\n  getCellStyle(name: string): import('../types/style.types').IStyle | undefined {\r\n    return this.cellStyles.get(name);\r\n  }\r\n\r\n  /**\r\n   * Set workbook theme\r\n   * \r\n   * Applies a color and font theme to the entire workbook. Themes affect all\r\n   * worksheets and can automatically apply styles to table sections (header, body, footer)\r\n   * if `autoApplySectionStyles` is enabled.\r\n   * \r\n   * Themes include:\r\n   * - Color palette (dark1, light1, dark2, light2, accent1-6, hyperlink colors)\r\n   * - Font families (major and minor fonts for latin, eastAsian, complexScript)\r\n   * - Optional section styles for automatic styling\r\n   * \r\n   * @param {IWorkbookTheme} theme - Theme configuration object\r\n   * @param {string} [theme.name] - Theme name\r\n   * @param {object} [theme.colors] - Color palette\r\n   * @param {object} [theme.fonts] - Font configuration\r\n   * @param {object} [theme.sectionStyles] - Styles for table sections\r\n   * @param {boolean} [theme.autoApplySectionStyles=true] - Auto-apply section styles\r\n   * \r\n   * @returns {this} Returns the builder instance for method chaining\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * builder.setTheme({\r\n   *   name: 'Corporate Theme',\r\n   *   colors: {\r\n   *     dark1: '#000000',\r\n   *     light1: '#FFFFFF',\r\n   *     accent1: '#4472C4',\r\n   *     accent2: '#ED7D31'\r\n   *   },\r\n   *   fonts: {\r\n   *     major: { latin: 'Calibri' },\r\n   *     minor: { latin: 'Calibri' }\r\n   *   },\r\n   *   autoApplySectionStyles: true\r\n   * });\r\n   * ```\r\n   */\r\n  setTheme(theme: IWorkbookTheme): this {\r\n    this.theme = theme;\r\n    return this;\r\n  }\r\n\r\n  /**\r\n   * Get current workbook theme\r\n   * \r\n   * Retrieves the currently active theme, if one has been set.\r\n   * \r\n   * @returns {IWorkbookTheme | undefined} The current theme, or undefined if no theme is set\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const theme = builder.getTheme();\r\n   * if (theme) {\r\n   *   console.log('Active theme:', theme.name);\r\n   * }\r\n   * ```\r\n   */\r\n  getTheme(): IWorkbookTheme | undefined {\r\n    return this.theme;\r\n  }\r\n\r\n  /**\r\n   * Register an event listener\r\n   * \r\n   * Subscribes to builder events to monitor the build process. Returns a listener ID\r\n   * that can be used to remove the listener later.\r\n   * \r\n   * Available events:\r\n   * - `build:started` - Build process started\r\n   * - `build:completed` - Build completed successfully\r\n   * - `build:error` - Build failed with error\r\n   * - `download:started` - File download/save started\r\n   * - `download:completed` - File download/save completed\r\n   * - `download:error` - File download/save failed\r\n   * - `worksheet:added` - New worksheet added\r\n   * - `worksheet:removed` - Worksheet removed\r\n   * \r\n   * @param {BuilderEventType} eventType - Type of event to listen for\r\n   * @param {(event: IBuilderEvent) => void} listener - Callback function to execute when event fires\r\n   * @returns {string} Listener ID (use with `off()` to remove the listener)\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const listenerId = builder.on('build:started', (event) => {\r\n   *   console.log('Build started at', event.timestamp);\r\n   * });\r\n   * \r\n   * builder.on('build:completed', (event) => {\r\n   *   console.log('Build completed:', event.data);\r\n   * });\r\n   * \r\n   * builder.on('build:error', (event) => {\r\n   *   console.error('Build error:', event.data.error);\r\n   * });\r\n   * ```\r\n   */\r\n  on(eventType: BuilderEventType, listener: (event: IBuilderEvent) => void): string {\r\n    return this.eventEmitter.on(eventType, listener);\r\n  }\r\n\r\n  /**\r\n   * Remove an event listener\r\n   * \r\n   * Unsubscribes from a specific event by removing the listener with the given ID.\r\n   * \r\n   * @param {BuilderEventType} eventType - Type of event\r\n   * @param {string} listenerId - Listener ID returned from `on()`\r\n   * @returns {boolean} True if the listener was found and removed, false otherwise\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * const listenerId = builder.on('build:started', handler);\r\n   * \r\n   * // Later, remove the listener\r\n   * builder.off('build:started', listenerId);\r\n   * ```\r\n   */\r\n  off(eventType: BuilderEventType, listenerId: string): boolean {\r\n    return this.eventEmitter.off(eventType, listenerId);\r\n  }\r\n\r\n  /**\r\n   * Remove all event listeners\r\n   * \r\n   * Removes all listeners for a specific event type, or all listeners for all events\r\n   * if no event type is specified.\r\n   * \r\n   * @param {BuilderEventType} [eventType] - Event type to clear listeners for. If omitted, clears all listeners\r\n   * @returns {void}\r\n   * \r\n   * @example\r\n   * ```typescript\r\n   * // Remove all listeners for 'build:started' event\r\n   * builder.removeAllListeners('build:started');\r\n   * \r\n   * // Remove all listeners for all events\r\n   * builder.removeAllListeners();\r\n   * ```\r\n   */\r\n  removeAllListeners(eventType?: BuilderEventType): void {\r\n    if (eventType) {\r\n      this.eventEmitter.offAll(eventType);\r\n    } else {\r\n      this.eventEmitter.clear();\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Private methods\r\n   */\r\n  \r\n  /**\r\n   * Emit an event to all registered listeners\r\n   * @private\r\n   */\r\n  private emitEvent(type: BuilderEventType, data?: Record<string, unknown>): void {\r\n    if (!this.config.enableEvents) return;\r\n    \r\n    const event: IBuilderEvent = {\r\n      type,\r\n      data: data || {},\r\n      timestamp: new Date()\r\n    };\r\n    this.eventEmitter.emitSync(event);\r\n  }\r\n\r\n  /**\r\n   * Initialize build statistics\r\n   * @private\r\n   */\r\n  private initializeStats(): IBuildStats {\r\n    return {\r\n      totalWorksheets: 0,\r\n      totalCells: 0,\r\n      memoryUsage: 0,\r\n      buildTime: 0,\r\n      fileSize: 0,\r\n      stylesUsed: 0,\r\n      formulasUsed: 0,\r\n      conditionalFormatsUsed: 0,\r\n      performance: {\r\n        headersTime: 0,\r\n        dataTime: 0,\r\n        stylesTime: 0,\r\n        writeTime: 0\r\n      }\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Apply theme to workbook\r\n   * \r\n   * Internal method that applies the theme configuration to the ExcelJS workbook.\r\n   * Converts theme colors and fonts to ExcelJS format.\r\n   * \r\n   * @private\r\n   * @param {ExcelJS.Workbook} workbook - ExcelJS workbook instance\r\n   * @param {IWorkbookTheme} theme - Theme configuration\r\n   */\r\n  private applyTheme(workbook: ExcelJS.Workbook, theme: IWorkbookTheme): void {\r\n    if (!workbook.model) {\r\n      return;\r\n    }\r\n\r\n    // ExcelJS theme structure\r\n    const excelTheme: any = {\r\n      name: theme.name || 'Custom Theme'\r\n    };\r\n\r\n    if (theme.colors) {\r\n      excelTheme.colors = {};\r\n      if (theme.colors.dark1) excelTheme.colors.dark1 = this.convertColorToTheme(theme.colors.dark1);\r\n      if (theme.colors.light1) excelTheme.colors.light1 = this.convertColorToTheme(theme.colors.light1);\r\n      if (theme.colors.dark2) excelTheme.colors.dark2 = this.convertColorToTheme(theme.colors.dark2);\r\n      if (theme.colors.light2) excelTheme.colors.light2 = this.convertColorToTheme(theme.colors.light2);\r\n      if (theme.colors.accent1) excelTheme.colors.accent1 = this.convertColorToTheme(theme.colors.accent1);\r\n      if (theme.colors.accent2) excelTheme.colors.accent2 = this.convertColorToTheme(theme.colors.accent2);\r\n      if (theme.colors.accent3) excelTheme.colors.accent3 = this.convertColorToTheme(theme.colors.accent3);\r\n      if (theme.colors.accent4) excelTheme.colors.accent4 = this.convertColorToTheme(theme.colors.accent4);\r\n      if (theme.colors.accent5) excelTheme.colors.accent5 = this.convertColorToTheme(theme.colors.accent5);\r\n      if (theme.colors.accent6) excelTheme.colors.accent6 = this.convertColorToTheme(theme.colors.accent6);\r\n      if (theme.colors.hyperlink) excelTheme.colors.hyperlink = this.convertColorToTheme(theme.colors.hyperlink);\r\n      if (theme.colors.followedHyperlink) excelTheme.colors.followedHyperlink = this.convertColorToTheme(theme.colors.followedHyperlink);\r\n    }\r\n\r\n    if (theme.fonts) {\r\n      excelTheme.fonts = {};\r\n      if (theme.fonts.major) {\r\n        excelTheme.fonts.major = {\r\n          latin: theme.fonts.major.latin || 'Calibri',\r\n          eastAsian: theme.fonts.major.eastAsian || theme.fonts.major.latin || 'Calibri',\r\n          complexScript: theme.fonts.major.complexScript || theme.fonts.major.latin || 'Calibri'\r\n        };\r\n      }\r\n      if (theme.fonts.minor) {\r\n        excelTheme.fonts.minor = {\r\n          latin: theme.fonts.minor.latin || 'Calibri',\r\n          eastAsian: theme.fonts.minor.eastAsian || theme.fonts.minor.latin || 'Calibri',\r\n          complexScript: theme.fonts.minor.complexScript || theme.fonts.minor.latin || 'Calibri'\r\n        };\r\n      }\r\n    }\r\n\r\n    // Apply theme to workbook (ExcelJS stores theme in model)\r\n    (workbook as any).model = (workbook as any).model || {};\r\n    (workbook as any).model.theme = excelTheme;\r\n  }\r\n\r\n  /**\r\n   * Convert color to theme format\r\n   * \r\n   * Converts a Color value (hex string, RGB object, or theme color) to the format\r\n   * expected by ExcelJS themes (hex string without #).\r\n   * \r\n   * @private\r\n   * @param {Color} color - Color to convert\r\n   * @returns {string} Hex color string without # prefix\r\n   */\r\n  private convertColorToTheme(color: Color): string {\r\n    if (typeof color === 'string') {\r\n      // Remove # if present\r\n      return color.startsWith('#') ? color.substring(1) : color;\r\n    }\r\n    if ('r' in color && 'g' in color && 'b' in color) {\r\n      return `${color.r.toString(16).padStart(2, '0')}${color.g.toString(16).padStart(2, '0')}${color.b.toString(16).padStart(2, '0')}`;\r\n    }\r\n    return '000000';\r\n  }\r\n\r\n  /**\r\n   * Add style to workbook\r\n   * \r\n   * Stores a predefined style in the workbook so it can be accessed during worksheet\r\n   * building. ExcelJS doesn't support named styles directly, so we store them in a custom\r\n   * property that worksheets can access when building cells.\r\n   * \r\n   * @private\r\n   * @param {ExcelJS.Workbook} workbook - ExcelJS workbook instance\r\n   * @param {string} name - Style name\r\n   * @param {IStyle} style - Style object\r\n   * \r\n   * @remarks\r\n   * ExcelJS applies styles per cell, not as named styles. This method stores styles\r\n   * in a way that worksheets can retrieve them when building cells that reference\r\n   * the style by name.\r\n   */\r\n  private addStyleToWorkbook(workbook: ExcelJS.Workbook, name: string, style: import('../types/style.types').IStyle): void {\r\n    (workbook as any).__customStyles = (workbook as any).__customStyles || {};\r\n    (workbook as any).__customStyles[name] = style;\r\n  }\r\n}\r\n","/**\r\n * Types for Excel Reader functionality\r\n */\r\n\r\nimport { Result, ISuccessResult, IErrorResult } from \"./core.types\";\r\nimport { success } from '../../../han-documents-core/src/types/result.types';\r\n\r\n/**\r\n * Output format types\r\n */\r\nexport enum OutputFormat {\r\n  /** Format by worksheet (structured with sheets, rows, cells) */\r\n  WORKSHEET = \"worksheet\",\r\n  /** Detailed format with text, column, row information */\r\n  DETAILED = \"detailed\",\r\n  /** Flat format - just the data without structure */\r\n  FLAT = \"flat\",\r\n}\r\n\r\n/**\r\n * Mapper function types for different output formats\r\n */\r\nexport type WorksheetMapper = (data: IJsonWorkbook) => unknown;\r\nexport type DetailedMapper = (data: IDetailedFormat) => unknown;\r\nexport type FlatMapper = (data: IFlatFormat | IFlatFormatMultiSheet) => unknown;\r\n/** Unified mapper receiving all formats at once */\r\nexport type UnifiedMapper = (data: IUnifiedFormat) => unknown;\r\n\r\n/**\r\n * Base options for reading Excel files\r\n */\r\ninterface IBaseExcelReaderOptions {\r\n  /** Whether to include empty rows */\r\n  includeEmptyRows?: boolean;\r\n  /** Whether to use first row as headers */\r\n  useFirstRowAsHeaders?: boolean;\r\n  /** Custom headers mapping (column index -> header name) */\r\n  headers?: string[] | Record<number, string>;\r\n  /** Sheet name or index to read (if not specified, reads all sheets) */\r\n  sheetName?: string | number;\r\n  /** Starting row (1-based, default: 1) */\r\n  startRow?: number;\r\n  /** Ending row (1-based, if not specified, reads until end) */\r\n  endRow?: number;\r\n  /** Starting column (1-based, default: 1) */\r\n  startColumn?: number;\r\n  /** Ending column (1-based, if not specified, reads until end) */\r\n  endColumn?: number;\r\n  /** Whether to include cell formatting information */\r\n  includeFormatting?: boolean;\r\n  /** Whether to include formulas */\r\n  includeFormulas?: boolean;\r\n  /** Date format for date cells */\r\n  dateFormat?: string;\r\n  /** Whether to convert dates to ISO strings */\r\n  datesAsISO?: boolean;\r\n}\r\n\r\n/**\r\n * Options for reading Excel files with worksheet format\r\n */\r\nexport interface IExcelReaderWorksheetOptions extends IBaseExcelReaderOptions {\r\n  /** Output format - worksheet */\r\n  outputFormat?: OutputFormat.WORKSHEET | \"worksheet\";\r\n  /** Mapper function to transform the response data */\r\n  mapper?: UnifiedMapper;\r\n}\r\n\r\n/**\r\n * Options for reading Excel files with detailed format\r\n */\r\nexport interface IExcelReaderDetailedOptions extends IBaseExcelReaderOptions {\r\n  /** Output format - detailed */\r\n  outputFormat: OutputFormat.DETAILED | \"detailed\";\r\n  /** Mapper function to transform the response data */\r\n  mapper?: UnifiedMapper;\r\n}\r\n\r\n/**\r\n * Options for reading Excel files with flat format\r\n */\r\nexport interface IExcelReaderFlatOptions extends IBaseExcelReaderOptions {\r\n  /** Output format - flat */\r\n  outputFormat: OutputFormat.FLAT | \"flat\";\r\n  /** Mapper function to transform the response data */\r\n  mapper?: UnifiedMapper;\r\n}\r\n\r\n/**\r\n * Type helper to extract output format from options\r\n */\r\nexport type ExtractOutputFormat<T> = T extends IExcelReaderDetailedOptions\r\n  ? OutputFormat.DETAILED\r\n  : T extends IExcelReaderFlatOptions\r\n    ? OutputFormat.FLAT\r\n    : OutputFormat.WORKSHEET;\r\n\r\n/**\r\n * Options for reading Excel files\r\n */\r\nexport type IExcelReaderOptions =\r\n  | IExcelReaderWorksheetOptions\r\n  | IExcelReaderDetailedOptions\r\n  | IExcelReaderFlatOptions;\r\n\r\n/**\r\n * Unified format containing all representations at once.\r\n * - `workbook`: structured by sheets/rows/cells\r\n * - `detailed`: flat list of cells with position metadata\r\n * - `flat`: row-oriented data (per-sheet or single sheet)\r\n */\r\nexport interface IUnifiedFormat {\r\n  workbook?: IJsonWorkbook;\r\n  detailed?: IDetailedFormat;\r\n  flat?: IFlatFormat | IFlatFormatMultiSheet;\r\n}\r\n\r\n/**\r\n * Public interface for ExcelReader instances.\r\n *\r\n * Cada método está documentado con el tipo de respuesta que devuelve:\r\n * - `fromBuffer(...)`/`fromFile(...)`/`fromBlob(...)` admiten sobrecargas\r\n *   y su resultado depende de `options.outputFormat` (worksheet/detailed/flat).\r\n * - Métodos auxiliares `fromBufferDetailed` / `fromBufferFlat` retornan\r\n *   explícitamente `DETAILED` o `FLAT` respectivamente, para uso en consumidores\r\n *   que quieran una firma no ambigua.\r\n */\r\nexport interface IExcelReader {\r\n  /**\r\n   * Leer desde Buffer/ArrayBuffer.\r\n   * - Si `options.outputFormat` es `DETAILED` el resultado es `IDetailedFormat`.\r\n   * - Si `options.outputFormat` es `FLAT` el resultado es `IFlatFormat | IFlatFormatMultiSheet`.\r\n   * - Si no se especifica, el resultado es `IJsonWorkbook` (WORKSHEET).\r\n   */\r\n  fromBuffer(\r\n    buffer: any,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.DETAILED>>;\r\n  fromBuffer(\r\n    buffer: any,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.FLAT>>;\r\n  fromBuffer(\r\n    buffer: any,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.WORKSHEET>>;\r\n  fromBuffer(\r\n    buffer: any,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n\r\n  /** Conveniencia: siempre devuelve `DETAILED` */\r\n  fromBufferDetailed(\r\n    buffer: any,\r\n    options?: Omit<IExcelReaderDetailedOptions, \"outputFormat\">,\r\n  ): Promise<ExcelReaderResult<OutputFormat.DETAILED>>;\r\n\r\n  /** Conveniencia: siempre devuelve `FLAT` */\r\n  fromBufferFlat(\r\n    buffer: any,\r\n    options?: Omit<IExcelReaderFlatOptions, \"outputFormat\">,\r\n  ): Promise<ExcelReaderResult<OutputFormat.FLAT>>;\r\n\r\n  fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.DETAILED>>;\r\n  fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.FLAT>>;\r\n  fromBlob(\r\n    blob: Blob,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.WORKSHEET>>;\r\n  fromBlob(\r\n    blob: Blob,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n\r\n  fromFile(\r\n    file: File,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.DETAILED>>;\r\n  fromFile(\r\n    file: File,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.FLAT>>;\r\n  fromFile(\r\n    file: File,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.WORKSHEET>>;\r\n  fromFile(\r\n    file: File,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n\r\n  fromNodeBuffer(\r\n    buffer: any,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.DETAILED>>;\r\n  fromNodeBuffer(\r\n    buffer: any,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.FLAT>>;\r\n  fromNodeBuffer(\r\n    buffer: any,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.WORKSHEET>>;\r\n  fromNodeBuffer(\r\n    buffer: any,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n\r\n  fromPath(\r\n    filePath: string,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.DETAILED>>;\r\n  fromPath(\r\n    filePath: string,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.FLAT>>;\r\n  fromPath(\r\n    filePath: string,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResult<OutputFormat.WORKSHEET>>;\r\n  fromPath(\r\n    filePath: string,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n}\r\n\r\n/**\r\n * Cell data in JSON format\r\n */\r\nexport interface IJsonCell {\r\n  /** Cell value */\r\n  value: string | number | boolean | Date | null;\r\n  /** Cell type */\r\n  type?: string;\r\n  /** Cell reference (e.g., A1) */\r\n  reference?: string;\r\n  /** Formatted value (if includeFormatting is true) */\r\n  formattedValue?: string;\r\n  /** Formula (if includeFormulas is true) */\r\n  formula?: string;\r\n  /** Cell comment */\r\n  comment?: string;\r\n}\r\n\r\n/**\r\n * Row data in JSON format\r\n */\r\nexport interface IJsonRow {\r\n  /** Row number (1-based) */\r\n  rowNumber: number;\r\n  /** Cells in the row */\r\n  cells: IJsonCell[];\r\n  /** Row as object (if useFirstRowAsHeaders is true) */\r\n  data?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Sheet data in JSON format\r\n */\r\nexport interface IJsonSheet {\r\n  /** Sheet name */\r\n  name: string;\r\n  /** Sheet index */\r\n  index: number;\r\n  /** Rows in the sheet */\r\n  rows: IJsonRow[];\r\n  /** Headers (if useFirstRowAsHeaders is true) */\r\n  headers?: string[];\r\n  /** Total number of rows */\r\n  totalRows: number;\r\n  /** Total number of columns */\r\n  totalColumns: number;\r\n}\r\n\r\n/**\r\n * Workbook data in JSON format\r\n */\r\nexport interface IJsonWorkbook {\r\n  /** Workbook metadata */\r\n  metadata?: {\r\n    title?: string;\r\n    author?: string;\r\n    company?: string;\r\n    created?: Date | string;\r\n    modified?: Date | string;\r\n    description?: string;\r\n  };\r\n  /** Sheets in the workbook */\r\n  sheets: IJsonSheet[];\r\n  /** Total number of sheets */\r\n  totalSheets: number;\r\n}\r\n\r\n/**\r\n * Detailed cell format - includes position information\r\n */\r\nexport interface IDetailedCell {\r\n  /** Cell value */\r\n  value: string | number | boolean | Date | null;\r\n  /** Cell text (string representation) */\r\n  text: string;\r\n  /** Column number (1-based) */\r\n  column: number;\r\n  /** Column letter (e.g., A, B, C) */\r\n  columnLetter: string;\r\n  /** Row number (1-based) */\r\n  row: number;\r\n  /** Cell reference (e.g., A1) */\r\n  reference: string;\r\n  /** Sheet name */\r\n  sheet: string;\r\n  /** Cell type */\r\n  type?: string;\r\n  /** Formatted value (if includeFormatting is true) */\r\n  formattedValue?: string;\r\n  /** Formula (if includeFormulas is true) */\r\n  formula?: string;\r\n  /** Cell comment */\r\n  comment?: string;\r\n}\r\n\r\n/**\r\n * Detailed format result - array of cells with position\r\n */\r\nexport interface IDetailedFormat {\r\n  /** Array of all cells with detailed information */\r\n  cells: IDetailedCell[];\r\n  /** Total number of cells */\r\n  totalCells: number;\r\n  /** Workbook metadata */\r\n  metadata?: {\r\n    title?: string;\r\n    author?: string;\r\n    company?: string;\r\n    created?: Date | string;\r\n    modified?: Date | string;\r\n    description?: string;\r\n  };\r\n}\r\n\r\n/**\r\n * Flat format result - just the data values\r\n */\r\nexport interface IFlatFormat {\r\n  /** Array of row data (as objects if useFirstRowAsHeaders is true, or as arrays) */\r\n  data: Array<Record<string, unknown> | unknown[]>;\r\n  /** Headers (if useFirstRowAsHeaders is true) */\r\n  headers?: string[];\r\n  /** Sheet name */\r\n  sheet?: string;\r\n  /** Total number of rows */\r\n  totalRows: number;\r\n}\r\n\r\n/**\r\n * Flat format result for multiple sheets\r\n */\r\nexport interface IFlatFormatMultiSheet {\r\n  /** Data organized by sheet name */\r\n  sheets: Record<string, IFlatFormat>;\r\n  /** Total number of sheets */\r\n  totalSheets: number;\r\n  /** Workbook metadata */\r\n  metadata?: {\r\n    title?: string;\r\n    author?: string;\r\n    company?: string;\r\n    created?: Date | string;\r\n    modified?: Date | string;\r\n    description?: string;\r\n  };\r\n}\r\n\r\n/**\r\n * Success result with processing time for detailed format\r\n */\r\nexport interface IDetailedSuccessResult extends ISuccessResult<IDetailedFormat> {\r\n  processingTime?: number;\r\n}\r\n\r\n/**\r\n * Success result with processing time for flat format\r\n */\r\nexport interface IFlatSuccessResult extends ISuccessResult<\r\n  IFlatFormat | IFlatFormatMultiSheet\r\n> {\r\n  processingTime?: number;\r\n}\r\n\r\n/**\r\n * Success result with processing time for worksheet format\r\n */\r\nexport interface IWorksheetSuccessResult extends ISuccessResult<IJsonWorkbook> {\r\n  processingTime?: number;\r\n}\r\n\r\n/**\r\n * Error result with processing time\r\n */\r\nexport interface IErrorResultWithTime extends IErrorResult {\r\n  processingTime?: number;\r\n}\r\n\r\n/**\r\n * Reader result - generic type based on output format\r\n * This type ensures TypeScript correctly infers the data type based on the output format\r\n *\r\n * Using explicit interfaces instead of intersections to preserve discriminated union structure\r\n */\r\n/**\r\n * Result returned by reader methods. Always includes a unified data payload\r\n * with `workbook`, `detailed` and `flat` representations so consumers have\r\n * access to every format without conditional typing.\r\n */\r\n/**\r\n * Result returned by reader methods. Generic mapped type based on requested output format.\r\n * - If `T` is `DETAILED`, returns `IDetailedSuccessResult | IErrorResultWithTime`\r\n * - If `T` is `FLAT`, returns `IFlatSuccessResult | IErrorResultWithTime`\r\n * - Otherwise, returns `IWorksheetSuccessResult | IErrorResultWithTime`\r\n */\r\n/**\r\n * Success result containing all representations at once (unified payload).\r\n * The data property contains optional `workbook`, `detailed` and `flat` fields.\r\n */\r\nexport interface IUnifiedSuccessResult extends ISuccessResult<IUnifiedFormat> {\r\n  processingTime?: number;\r\n}\r\n\r\n/** Result type exposing all representations at once (explicit alias). */\r\nexport type ExcelReaderUnifiedResult =\r\n  | IUnifiedSuccessResult\r\n  | IErrorResultWithTime;\r\n\r\nexport interface ExcelReaderDetailedResult extends ISuccessResult<IDetailedFormat> {\r\n  processingTime?: number;\r\n}\r\n\r\nexport interface ExcelReaderFlatResult extends ISuccessResult<\r\n  IFlatFormat | IFlatFormatMultiSheet\r\n> {\r\n  processingTime?: number;\r\n}\r\nexport interface ExcelReaderWorksheetResult extends ISuccessResult<IJsonWorkbook> {\r\n  processingTime?: number;\r\n}\r\n/**\r\n * ExcelReaderResult:\r\n * - If a specific `T extends OutputFormat` is provided, returns the narrowed success type\r\n *   (DETAILED | FLAT | WORKSHEET) or an error with processing time.\r\n * - Default is `WORKSHEET` so conditional `extends` checks behave predictably.\r\n */\r\nexport type ExcelReaderResult<T extends OutputFormat = OutputFormat.WORKSHEET> =\r\n  T extends OutputFormat.DETAILED\r\n    ? IDetailedSuccessResult | IErrorResultWithTime\r\n    : T extends OutputFormat.FLAT\r\n      ? IFlatSuccessResult | IErrorResultWithTime\r\n      : IWorksheetSuccessResult | IErrorResultWithTime;\r\n\r\n/**\r\n * Legacy reader result (for backward compatibility)\r\n */\r\nexport type IExcelReaderResult = Result<IJsonWorkbook> & {\r\n  /** Processing time in milliseconds */\r\n  processingTime?: number;\r\n};\r\n\r\n\r\nexport interface IExcelReaderResultUnified  { \r\n  success: boolean;\r\n  data:IUnifiedFormat;\r\n  processingTime?: number;\r\n\r\n}\r\nexport type ExcelReaderResultUnified  =  IExcelReaderResultUnified |  IErrorResultWithTime;","/**\r\n * ExcelReader - Class for reading Excel files and converting them to JSON\r\n */\r\n\r\nimport * as ExcelJS from \"exceljs\";\r\nimport {\r\n  Result,\r\n  success,\r\n  error,\r\n  ErrorType as CoreErrorType,\r\n} from \"@hannndler/core\";\r\nimport {\r\n  IExcelReaderOptions,\r\n  IExcelReaderDetailedOptions,\r\n  IExcelReaderFlatOptions,\r\n  IExcelReaderWorksheetOptions,\r\n  IJsonWorkbook,\r\n  IJsonSheet,\r\n  IJsonRow,\r\n  IJsonCell,\r\n  OutputFormat,\r\n  IDetailedFormat,\r\n  IUnifiedFormat,\r\n  IDetailedCell,\r\n  IFlatFormat,\r\n  IFlatFormatMultiSheet,\r\n  ExcelReaderResult,\r\n  ExcelReaderUnifiedResult,\r\n  ExcelReaderDetailedResult,\r\n  ExcelReaderFlatResult,\r\n  ExcelReaderWorksheetResult,\r\n  ExcelReaderResultUnified,\r\n} from \"../types/reader.types\";\r\nimport { ErrorType, IErrorResult } from \"../types/compat.types\";\r\n\r\n/**\r\n * ExcelReader class for reading Excel files and converting to JSON\r\n *\r\n * @example\r\n * ```typescript\r\n * // Using instance methods\r\n * const reader = new ExcelReader({\r\n *   outputFormat: OutputFormat.FLAT,\r\n *   useFirstRowAsHeaders: true\r\n * });\r\n *\r\n * const result = await reader.fromBuffer(arrayBuffer);\r\n *\r\n * // Using static methods (convenience)\r\n * const result2 = await ExcelReader.fromBuffer(arrayBuffer, { outputFormat: OutputFormat.DETAILED });\r\n * ```\r\n */\r\nexport class ExcelReader {\r\n  private defaultOptions: IExcelReaderOptions;\r\n\r\n  /**\r\n   * Creates a new ExcelReader instance with default options\r\n   *\r\n   * @param defaultOptions - Default options to use for all read operations\r\n   */\r\n  constructor(defaultOptions: IExcelReaderOptions = {}) {\r\n    this.defaultOptions = defaultOptions;\r\n  }\r\n\r\n  /**\r\n   * Helper to create error result with correct typing\r\n   */\r\n  private createErrorResult(\r\n    errorType: CoreErrorType,\r\n    message: string,\r\n    code: string,\r\n    details?: Record<string, unknown>,\r\n    processingTime: number = 0,\r\n  ): ExcelReaderResultUnified {\r\n    const errorResult = error(errorType, message, code, details);\r\n    return {\r\n      ...errorResult,\r\n      processingTime,\r\n    } as ExcelReaderResultUnified;\r\n  }\r\n\r\n  /**\r\n   * Read Excel file from Node.js Buffer or ArrayBuffer\r\n   *\r\n   * @param buffer - Node.js Buffer (preferred) or ArrayBuffer\r\n   * @param options - Reading options\r\n   * @returns Promise with the read result\r\n   *\r\n   * @example\r\n   * ```typescript\r\n   * // With detailed format - TypeScript knows the result type\r\n   * const result = await reader.fromBuffer(buffer, {\r\n   *   outputFormat: OutputFormat.DETAILED\r\n   * });\r\n   * if (result.success) {\r\n   *   result.data.cells; // TypeScript knows this is IDetailedFormat\r\n   * }\r\n   *\r\n   * // With Node.js Buffer (from multer, fs, etc.)\r\n   * const result = await reader.fromBuffer(req.file.buffer);\r\n   * ```\r\n   */\r\n  async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any, // Node.js Buffer (preferred) or ArrayBuffer\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n\r\n  async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any, // Node.js Buffer (preferred) or ArrayBuffer\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    options: any = {}, // Accept any to work with overloads\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    // Merge options - TypeScript needs help inferring the combined type\r\n    const mergedOptions: IExcelReaderOptions = {\r\n      ...this.defaultOptions,\r\n      ...options,\r\n    } as IExcelReaderOptions;\r\n    const startTime = Date.now();\r\n\r\n    try {\r\n      const workbook = new ExcelJS.Workbook();\r\n      // ExcelJS can accept Buffer directly, but we ensure it's in the right format\r\n      // Convert Buffer to ArrayBuffer if needed (for compatibility)\r\n      // If buffer has a .buffer property, it's a Node.js Buffer/Uint8Array\r\n      // Otherwise, assume it's already an ArrayBuffer\r\n      const arrayBuffer = buffer.buffer\r\n        ? buffer.buffer.slice(\r\n            buffer.byteOffset,\r\n            buffer.byteOffset + buffer.byteLength,\r\n          )\r\n        : buffer;\r\n      await workbook.xlsx.load(arrayBuffer);\r\n\r\n      const outputFormat = (mergedOptions.outputFormat ||\r\n        OutputFormat.WORKSHEET) as OutputFormat;\r\n      const processingTime = Date.now() - startTime;\r\n\r\n      let result:\r\n        | IDetailedFormat\r\n        | IFlatFormat\r\n        | IFlatFormatMultiSheet\r\n        | IJsonWorkbook;\r\n\r\n      switch (outputFormat) {\r\n        case OutputFormat.DETAILED:\r\n          result = this.convertToDetailedFormat(workbook, mergedOptions);\r\n          break;\r\n        case OutputFormat.FLAT:\r\n          result = this.convertToFlatFormat(workbook, mergedOptions);\r\n          break;\r\n        case OutputFormat.WORKSHEET:\r\n        default:\r\n          result = this.convertWorkbookToJson(workbook, mergedOptions);\r\n          break;\r\n      }\r\n\r\n      // Apply mapper function if provided\r\n      if (mergedOptions.mapper) {\r\n        try {\r\n          // Apply mapper based on output format\r\n          switch (outputFormat) {\r\n            case OutputFormat.DETAILED:\r\n              result = (\r\n                mergedOptions.mapper as (data: IDetailedFormat) => unknown\r\n              )(result as IDetailedFormat) as IDetailedFormat;\r\n              break;\r\n            case OutputFormat.FLAT:\r\n              result = (\r\n                mergedOptions.mapper as (\r\n                  data: IFlatFormat | IFlatFormatMultiSheet,\r\n                ) => unknown\r\n              )(result as IFlatFormat | IFlatFormatMultiSheet) as\r\n                | IFlatFormat\r\n                | IFlatFormatMultiSheet;\r\n              break;\r\n            case OutputFormat.WORKSHEET:\r\n            default:\r\n              result = (\r\n                mergedOptions.mapper as (data: IJsonWorkbook) => unknown\r\n              )(result as IJsonWorkbook) as IJsonWorkbook;\r\n              break;\r\n          }\r\n        } catch (mapperError) {\r\n          return this.createErrorResult(\r\n            CoreErrorType.VALIDATION_ERROR,\r\n            mapperError instanceof Error\r\n              ? `Mapper function error: ${mapperError.message}`\r\n              : \"Error in mapper function\",\r\n            \"MAPPER_ERROR\",\r\n            { originalError: mapperError },\r\n            Date.now() - startTime,\r\n          );\r\n        }\r\n      }\r\n\r\n      // Create success result with correct type based on outputFormat\r\n      // We need to preserve the discriminated union structure for TypeScript\r\n      switch (outputFormat) {\r\n        case OutputFormat.DETAILED: {\r\n          // Wrap in unified payload so declarations expose all formats\r\n          const unified: IUnifiedFormat = {\r\n            detailed: result as IDetailedFormat,\r\n          };\r\n          const successResult = success(unified);\r\n          return {\r\n            ...successResult,\r\n            processingTime,\r\n          } as ExcelReaderResultUnified;\r\n        }\r\n        case OutputFormat.FLAT: {\r\n          const unified: IUnifiedFormat = {\r\n            flat: result as IFlatFormat | IFlatFormatMultiSheet,\r\n          };\r\n          const successResult = success(unified);\r\n          return {\r\n            ...successResult,\r\n            processingTime,\r\n          } as ExcelReaderResultUnified;\r\n        }\r\n        case OutputFormat.WORKSHEET:\r\n        default: {\r\n          const unified: IUnifiedFormat = { workbook: result as IJsonWorkbook };\r\n          const successResult = success(unified);\r\n          return {\r\n            ...successResult,\r\n            processingTime,\r\n          } as ExcelReaderResultUnified;\r\n        }\r\n      }\r\n    } catch (err: any) {\r\n      return this.createErrorResult(\r\n        CoreErrorType.FILE_ERROR,\r\n        err.message || \"Failed to read Excel file\",\r\n        \"READ_FAILED\",\r\n        { originalError: err },\r\n        Date.now() - startTime,\r\n      );\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Read Excel file from Blob\r\n   */\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const arrayBuffer = await blob.arrayBuffer();\r\n    return this.fromBuffer(arrayBuffer, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Read Excel file from File (browser)\r\n   */\r\n  async fromFile(\r\n    file: File,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromFile(\r\n    file: File,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromFile(\r\n    file: File,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromFile(\r\n    file: File,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromFile(\r\n    file: File,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromFile(\r\n    file: File,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromFile(\r\n    file: File,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    return this.fromBlob(file, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Read Excel file from Node.js Buffer (Node.js only)\r\n   * Useful when receiving files from multer or other Node.js file upload libraries\r\n   * Note: This method only works in Node.js environment\r\n   * @deprecated Use fromBuffer() directly, as it now accepts Buffer\r\n   */\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any, // Node.js Buffer type (available in Node.js runtime)\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    return this.fromBuffer(buffer, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Convenience static method that always returns the unified payload\r\n   * for Blob input.\r\n   */\r\n  static async fromBlobUnified(\r\n    blob: Blob,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderUnifiedResult> {\r\n    const reader = new ExcelReader();\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    return reader.fromBlob(\r\n      blob,\r\n      options as any,\r\n    ) as Promise<ExcelReaderUnifiedResult>;\r\n  }\r\n\r\n  /**\r\n   * Read Excel file from path (Node.js only)\r\n   * Note: This method only works in Node.js environment\r\n   */\r\n  async fromPath(\r\n    filePath: string,\r\n    options: IExcelReaderDetailedOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromPath(\r\n    filePath: string,\r\n    options: IExcelReaderFlatOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromPath(\r\n    filePath: string,\r\n    options?: IExcelReaderWorksheetOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  async fromPath(\r\n    filePath: string,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    try {\r\n      const fs = await import(\"fs/promises\");\r\n      const buffer = await fs.readFile(filePath);\r\n      return this.fromBuffer(buffer, options as any) as Promise<\r\n        ExcelReaderResultUnified\r\n      >;\r\n    } catch (err: any) {\r\n      const isBrowserError =\r\n        err instanceof Error &&\r\n        (err.message.includes(\"Cannot find module\") ||\r\n          err.message.includes(\"fs\") ||\r\n          typeof window !== \"undefined\");\r\n\r\n      return this.createErrorResult(\r\n        CoreErrorType.FILE_ERROR,\r\n        isBrowserError\r\n          ? \"fromPath() method requires Node.js environment. Use fromFile() or fromBlob() in browser.\"\r\n          : err.message || \"Error reading file from path\",\r\n        \"PATH_READ_FAILED\",\r\n        { originalError: err },\r\n        0,\r\n      );\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Static method: Read Excel file from Node.js Buffer or ArrayBuffer (convenience method)\r\n   */\r\n  static async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  static async fromBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any, // Node.js Buffer (preferred) or ArrayBuffer\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromBuffer(buffer, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Convenience static method that always returns the unified payload\r\n   * exposing `workbook`, `detailed` and `flat` optionally.\r\n   */\r\n  static async fromBufferUnified(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    return reader.fromBuffer(buffer, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Static method: Read Excel file from Blob (convenience method)\r\n   */\r\n  static async fromBlob(\r\n    blob: Blob,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  static async fromBlob(\r\n    blob: Blob,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromBlob(blob, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Static method: Read Excel file from File (convenience method)\r\n   */\r\n  static async fromFile(\r\n    file: File,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  static async fromFile(\r\n    file: File,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromFile(file, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Convenience static method that always returns the unified payload\r\n   * for File input.\r\n   */\r\n  static async fromFileUnified(\r\n    file: File,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromFile(file, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Static method: Read Excel file from Node.js Buffer (convenience method)\r\n   * @deprecated Use fromBuffer() directly, as it now accepts Buffer\r\n   */\r\n  static async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  static async fromNodeBuffer(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any, // Node.js Buffer type (available in Node.js runtime)\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromNodeBuffer(buffer, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Convenience static method that always returns the unified payload\r\n   * for Node Buffer input.\r\n   */\r\n  static async fromNodeBufferUnified(\r\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n    buffer: any,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromBuffer(buffer, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Static method: Read Excel file from path (convenience method)\r\n   */\r\n  static async fromPath(\r\n    filePath: string,\r\n    options?: IExcelReaderOptions,\r\n  ): Promise<ExcelReaderResultUnified>;\r\n  static async fromPath(\r\n    filePath: string,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromPath(filePath, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Convenience static method that always returns the unified payload\r\n   * for path input.\r\n   */\r\n  static async fromPathUnified(\r\n    filePath: string,\r\n    options: IExcelReaderOptions = {},\r\n  ): Promise<ExcelReaderResultUnified> {\r\n    const reader = new ExcelReader();\r\n    return reader.fromPath(filePath, options as any) as Promise<\r\n      ExcelReaderResultUnified\r\n    >;\r\n  }\r\n\r\n  /**\r\n   * Convert ExcelJS Workbook to JSON\r\n   */\r\n  private convertWorkbookToJson(\r\n    workbook: ExcelJS.Workbook,\r\n    options: IExcelReaderOptions,\r\n  ): IJsonWorkbook {\r\n    const {\r\n      includeEmptyRows = false,\r\n      useFirstRowAsHeaders = false,\r\n      headers,\r\n      sheetName,\r\n      startRow = 1,\r\n      endRow,\r\n      startColumn = 1,\r\n      endColumn,\r\n      includeFormatting = false,\r\n      includeFormulas = false,\r\n      datesAsISO = true,\r\n    } = options;\r\n\r\n    // Get metadata\r\n    const metadata = {\r\n      title: workbook.title,\r\n      author: workbook.creator,\r\n      company: workbook.company,\r\n      created: workbook.created,\r\n      modified: workbook.modified,\r\n      description: workbook.description,\r\n    };\r\n\r\n    // Filter sheets\r\n    let sheetsToProcess: ExcelJS.Worksheet[] = [];\r\n\r\n    if (sheetName !== undefined) {\r\n      if (typeof sheetName === \"number\") {\r\n        const sheet = workbook.worksheets[sheetName];\r\n        if (sheet) sheetsToProcess.push(sheet);\r\n      } else {\r\n        const sheet = workbook.getWorksheet(sheetName);\r\n        if (sheet) sheetsToProcess.push(sheet);\r\n      }\r\n    } else {\r\n      sheetsToProcess = workbook.worksheets;\r\n    }\r\n\r\n    // Convert each sheet\r\n    const sheets: IJsonSheet[] = sheetsToProcess.map((worksheet) => {\r\n      const sheetOptions: {\r\n        includeEmptyRows: boolean;\r\n        useFirstRowAsHeaders: boolean;\r\n        headers?: string[] | Record<number, string>;\r\n        startRow: number;\r\n        endRow?: number;\r\n        startColumn: number;\r\n        endColumn?: number;\r\n        includeFormatting: boolean;\r\n        includeFormulas: boolean;\r\n        datesAsISO: boolean;\r\n      } = {\r\n        includeEmptyRows: includeEmptyRows ?? false,\r\n        useFirstRowAsHeaders: useFirstRowAsHeaders ?? false,\r\n        startRow: startRow ?? 1,\r\n        startColumn: startColumn ?? 1,\r\n        includeFormatting: includeFormatting ?? false,\r\n        includeFormulas: includeFormulas ?? false,\r\n        datesAsISO: datesAsISO ?? true,\r\n      };\r\n\r\n      if (headers !== undefined) {\r\n        sheetOptions.headers = headers;\r\n      }\r\n      if (endRow !== undefined) {\r\n        sheetOptions.endRow = endRow;\r\n      }\r\n      if (endColumn !== undefined) {\r\n        sheetOptions.endColumn = endColumn;\r\n      }\r\n\r\n      return this.convertSheetToJson(worksheet, sheetOptions);\r\n    });\r\n\r\n    const workbookResult: IJsonWorkbook = {\r\n      sheets,\r\n      totalSheets: sheets.length,\r\n    };\r\n\r\n    // Only add metadata if it has at least one property\r\n    const hasMetadata = Object.values(metadata).some(\r\n      (val) => val !== undefined && val !== null,\r\n    );\r\n    if (hasMetadata) {\r\n      workbookResult.metadata = metadata;\r\n    }\r\n\r\n    return workbookResult;\r\n  }\r\n\r\n  /**\r\n   * Convert ExcelJS Worksheet to JSON\r\n   */\r\n  private convertSheetToJson(\r\n    worksheet: ExcelJS.Worksheet,\r\n    options: {\r\n      includeEmptyRows: boolean;\r\n      useFirstRowAsHeaders: boolean;\r\n      headers?: string[] | Record<number, string>;\r\n      startRow: number;\r\n      endRow?: number;\r\n      startColumn: number;\r\n      endColumn?: number;\r\n      includeFormatting: boolean;\r\n      includeFormulas: boolean;\r\n      datesAsISO: boolean;\r\n    },\r\n  ): IJsonSheet {\r\n    const {\r\n      includeEmptyRows,\r\n      useFirstRowAsHeaders,\r\n      headers,\r\n      startRow,\r\n      endRow,\r\n      startColumn,\r\n      endColumn,\r\n      includeFormatting,\r\n      includeFormulas,\r\n      datesAsISO,\r\n    } = options;\r\n\r\n    const rows: IJsonRow[] = [];\r\n    let headerRow: string[] | undefined;\r\n    let maxColumns = 0;\r\n\r\n    // Determine row range\r\n    const actualStartRow = Math.max(startRow, 1);\r\n    const actualEndRow =\r\n      endRow || worksheet.rowCount || worksheet.lastRow?.number || 1;\r\n    const actualStartCol = Math.max(startColumn, 1);\r\n    const actualEndCol =\r\n      endColumn || worksheet.columnCount || worksheet.lastColumn?.number || 1;\r\n\r\n    // Process rows\r\n    for (let rowNum = actualStartRow; rowNum <= actualEndRow; rowNum++) {\r\n      const excelRow = worksheet.getRow(rowNum);\r\n      const cells: IJsonCell[] = [];\r\n      let hasData = false;\r\n\r\n      // Process cells in row\r\n      for (let colNum = actualStartCol; colNum <= actualEndCol; colNum++) {\r\n        const cell = excelRow.getCell(colNum);\r\n\r\n        // Skip if cell is empty and we're not including empty rows\r\n        if (!cell.value && !includeEmptyRows) {\r\n          continue;\r\n        }\r\n\r\n        const jsonCell = this.convertCellToJson(cell, {\r\n          includeFormatting,\r\n          includeFormulas,\r\n          datesAsISO,\r\n        });\r\n\r\n        cells.push(jsonCell);\r\n        hasData = true;\r\n      }\r\n\r\n      // Track max columns\r\n      if (cells.length > maxColumns) {\r\n        maxColumns = cells.length;\r\n      }\r\n\r\n      // Skip empty rows if configured\r\n      if (!hasData && !includeEmptyRows) {\r\n        continue;\r\n      }\r\n\r\n      // Handle headers\r\n      if (useFirstRowAsHeaders && rowNum === actualStartRow) {\r\n        headerRow = cells.map((cell) => {\r\n          if (headers && Array.isArray(headers)) {\r\n            return headers[cells.indexOf(cell)] || String(cell.value || \"\");\r\n          } else if (headers && typeof headers === \"object\") {\r\n            return (\r\n              headers[actualStartCol + cells.indexOf(cell)] ||\r\n              String(cell.value || \"\")\r\n            );\r\n          }\r\n          return String(cell.value || \"\");\r\n        });\r\n        continue; // Skip header row in data\r\n      }\r\n\r\n      // Create row data object if headers are used\r\n      let rowData: Record<string, unknown> | undefined;\r\n      if (useFirstRowAsHeaders && headerRow) {\r\n        rowData = {};\r\n        cells.forEach((cell, index) => {\r\n          const header = headerRow![index] || `column_${index + 1}`;\r\n          rowData![header] = cell.value;\r\n        });\r\n      }\r\n\r\n      const jsonRow: IJsonRow = {\r\n        rowNumber: rowNum,\r\n        cells,\r\n      };\r\n\r\n      if (rowData) {\r\n        jsonRow.data = rowData;\r\n      }\r\n\r\n      rows.push(jsonRow);\r\n    }\r\n\r\n    const sheet: IJsonSheet = {\r\n      name: worksheet.name,\r\n      index: worksheet.id || 0,\r\n      rows,\r\n      totalRows: rows.length,\r\n      totalColumns: maxColumns,\r\n    };\r\n\r\n    if (headerRow) {\r\n      sheet.headers = headerRow;\r\n    }\r\n\r\n    return sheet;\r\n  }\r\n\r\n  /**\r\n   * Convert ExcelJS Cell to JSON\r\n   */\r\n  private convertCellToJson(\r\n    cell: ExcelJS.Cell,\r\n    options: {\r\n      includeFormatting: boolean;\r\n      includeFormulas: boolean;\r\n      datesAsISO: boolean;\r\n    },\r\n  ): IJsonCell {\r\n    const { includeFormatting, includeFormulas, datesAsISO } = options;\r\n\r\n    let value: unknown = cell.value;\r\n    let type: string | undefined;\r\n\r\n    // Determine type and convert value\r\n    if (\r\n      cell.type === ExcelJS.ValueType.Null ||\r\n      cell.value === null ||\r\n      cell.value === undefined\r\n    ) {\r\n      value = null;\r\n      type = \"null\";\r\n    } else if (cell.type === ExcelJS.ValueType.Number) {\r\n      value = cell.value as number;\r\n      type = \"number\";\r\n    } else if (cell.type === ExcelJS.ValueType.String) {\r\n      value = cell.value as string;\r\n      type = \"string\";\r\n    } else if (cell.type === ExcelJS.ValueType.Date) {\r\n      const dateValue = cell.value as Date;\r\n      value = datesAsISO ? dateValue.toISOString() : dateValue;\r\n      type = \"date\";\r\n    } else if (cell.type === ExcelJS.ValueType.Boolean) {\r\n      value = cell.value as boolean;\r\n      type = \"boolean\";\r\n    } else if (cell.type === ExcelJS.ValueType.Formula) {\r\n      // Always try to get formula if includeFormulas is true\r\n      if (includeFormulas) {\r\n        value = cell.result || cell.value;\r\n        type = \"formula\";\r\n      } else {\r\n        value = cell.result || cell.value;\r\n        type =\r\n          typeof cell.result === \"number\"\r\n            ? \"number\"\r\n            : typeof cell.result === \"string\"\r\n              ? \"string\"\r\n              : \"unknown\";\r\n      }\r\n    } else if (cell.type === ExcelJS.ValueType.Hyperlink) {\r\n      // Handle hyperlink - ExcelJS stores hyperlinks as objects with text and hyperlink properties\r\n      const hyperlinkValue = cell.value as\r\n        | { text?: string; hyperlink?: string }\r\n        | string;\r\n      if (typeof hyperlinkValue === \"object\" && hyperlinkValue !== null) {\r\n        value = hyperlinkValue.text || hyperlinkValue.hyperlink || cell.value;\r\n      } else {\r\n        value = hyperlinkValue;\r\n      }\r\n      type = \"hyperlink\";\r\n    } else {\r\n      value = cell.value;\r\n      type = \"unknown\";\r\n    }\r\n\r\n    const jsonCell: IJsonCell = {\r\n      value: value as string | number | boolean | Date | null,\r\n      type,\r\n      reference: cell.address,\r\n    };\r\n\r\n    // Add formatted value if requested - use cell.text which is the actual displayed text\r\n    if (includeFormatting) {\r\n      // cell.text is the formatted text as it appears in Excel\r\n      jsonCell.formattedValue = cell.text || String(value);\r\n    }\r\n\r\n    // Add formula if requested\r\n    if (includeFormulas) {\r\n      // Try to get formula from cell\r\n      if (cell.formula) {\r\n        jsonCell.formula = cell.formula;\r\n      } else if (cell.type === ExcelJS.ValueType.Formula) {\r\n        // For formula cells, try to get formula from the cell\r\n        jsonCell.formula = (cell as any).formula || undefined;\r\n      }\r\n    }\r\n\r\n    // Add comment if exists\r\n    if (cell.note) {\r\n      // ExcelJS stores comments as Note objects or strings\r\n      const note = cell.note;\r\n      if (typeof note === \"string\") {\r\n        jsonCell.comment = note;\r\n      } else if (note && typeof note === \"object\" && \"texts\" in note) {\r\n        // Note object with texts array\r\n        const texts = (note as any).texts;\r\n        if (Array.isArray(texts) && texts.length > 0) {\r\n          jsonCell.comment = texts.map((t: any) => t.text || \"\").join(\"\");\r\n        }\r\n      } else if (note && typeof note === \"object\" && \"text\" in note) {\r\n        jsonCell.comment = String((note as any).text);\r\n      }\r\n    }\r\n\r\n    return jsonCell;\r\n  }\r\n\r\n  /**\r\n   * Convert workbook to detailed format (with position information)\r\n   */\r\n  private convertToDetailedFormat(\r\n    workbook: ExcelJS.Workbook,\r\n    options: IExcelReaderOptions,\r\n  ): IDetailedFormat {\r\n    const {\r\n      includeEmptyRows = false,\r\n      includeFormatting = false,\r\n      includeFormulas = false,\r\n      datesAsISO = true,\r\n      sheetName,\r\n      startRow = 1,\r\n      endRow,\r\n      startColumn = 1,\r\n      endColumn,\r\n    } = options;\r\n\r\n    const cells: IDetailedCell[] = [];\r\n\r\n    // Get metadata\r\n    const metadata = {\r\n      title: workbook.title,\r\n      author: workbook.creator,\r\n      company: workbook.company,\r\n      created: workbook.created,\r\n      modified: workbook.modified,\r\n      description: workbook.description,\r\n    };\r\n\r\n    // Filter sheets\r\n    let sheetsToProcess: ExcelJS.Worksheet[] = [];\r\n\r\n    if (sheetName !== undefined) {\r\n      if (typeof sheetName === \"number\") {\r\n        const sheet = workbook.worksheets[sheetName];\r\n        if (sheet) sheetsToProcess.push(sheet);\r\n      } else {\r\n        const sheet = workbook.getWorksheet(sheetName);\r\n        if (sheet) sheetsToProcess.push(sheet);\r\n      }\r\n    } else {\r\n      sheetsToProcess = workbook.worksheets;\r\n    }\r\n\r\n    // Process each sheet\r\n    for (const worksheet of sheetsToProcess) {\r\n      const actualStartRow = Math.max(startRow, 1);\r\n      const actualEndRow =\r\n        endRow || worksheet.rowCount || worksheet.lastRow?.number || 1;\r\n      const actualStartCol = Math.max(startColumn, 1);\r\n      const actualEndCol =\r\n        endColumn || worksheet.columnCount || worksheet.lastColumn?.number || 1;\r\n\r\n      for (let rowNum = actualStartRow; rowNum <= actualEndRow; rowNum++) {\r\n        const excelRow = worksheet.getRow(rowNum);\r\n\r\n        for (let colNum = actualStartCol; colNum <= actualEndCol; colNum++) {\r\n          const cell = excelRow.getCell(colNum);\r\n\r\n          // Skip empty cells if configured\r\n          if (!cell.value && !includeEmptyRows) {\r\n            continue;\r\n          }\r\n\r\n          // Convert column number to letter (1 = A, 2 = B, etc.)\r\n          const columnLetter = this.numberToColumnLetter(colNum);\r\n          const cellValue = this.getCellValue(cell, {\r\n            includeFormatting,\r\n            includeFormulas,\r\n            datesAsISO,\r\n          });\r\n\r\n          // Get the formatted text from ExcelJS (this is the actual displayed text)\r\n          const cellText = cell.text || String(cellValue.value ?? \"\");\r\n\r\n          const detailedCell: IDetailedCell = {\r\n            value: cellValue.value as string | number | boolean | Date | null,\r\n            text: cellText,\r\n            column: colNum,\r\n            columnLetter,\r\n            row: rowNum,\r\n            reference: cell.address || `${columnLetter}${rowNum}`,\r\n            sheet: worksheet.name,\r\n          };\r\n\r\n          // Always include type if available\r\n          if (cellValue.type !== undefined) {\r\n            detailedCell.type = cellValue.type;\r\n          }\r\n          // Include formattedValue if includeFormatting is true or if it exists\r\n          if (includeFormatting && cellValue.formattedValue !== undefined) {\r\n            detailedCell.formattedValue = cellValue.formattedValue;\r\n          } else if (\r\n            includeFormatting &&\r\n            cellText !== String(cellValue.value ?? \"\")\r\n          ) {\r\n            // If formatting is requested and text differs from value, use text as formattedValue\r\n            detailedCell.formattedValue = cellText;\r\n          }\r\n          // Include formula if includeFormulas is true and formula exists\r\n          if (includeFormulas && cellValue.formula !== undefined) {\r\n            detailedCell.formula = cellValue.formula;\r\n          }\r\n\r\n          // Add comment if exists\r\n          if (cell.note) {\r\n            const note = cell.note;\r\n            if (typeof note === \"string\") {\r\n              detailedCell.comment = note;\r\n            } else if (note && typeof note === \"object\" && \"texts\" in note) {\r\n              // Note object with texts array\r\n              const texts = (note as any).texts;\r\n              if (Array.isArray(texts) && texts.length > 0) {\r\n                detailedCell.comment = texts\r\n                  .map((t: any) => t.text || \"\")\r\n                  .join(\"\");\r\n              }\r\n            } else if (note && typeof note === \"object\" && \"text\" in note) {\r\n              detailedCell.comment = String((note as any).text);\r\n            }\r\n          }\r\n\r\n          cells.push(detailedCell);\r\n        }\r\n      }\r\n    }\r\n\r\n    const result: IDetailedFormat = {\r\n      cells,\r\n      totalCells: cells.length,\r\n    };\r\n\r\n    const hasMetadata = Object.values(metadata).some(\r\n      (val) => val !== undefined && val !== null,\r\n    );\r\n    if (hasMetadata) {\r\n      result.metadata = metadata;\r\n    }\r\n\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Convert workbook to flat format (just data)\r\n   */\r\n  private convertToFlatFormat(\r\n    workbook: ExcelJS.Workbook,\r\n    options: IExcelReaderOptions,\r\n  ): IFlatFormat | IFlatFormatMultiSheet {\r\n    const {\r\n      useFirstRowAsHeaders = false,\r\n      includeEmptyRows = false,\r\n      sheetName,\r\n      startRow = 1,\r\n      endRow,\r\n      startColumn = 1,\r\n      endColumn,\r\n    } = options;\r\n\r\n    // Get metadata\r\n    const metadata = {\r\n      title: workbook.title,\r\n      author: workbook.creator,\r\n      company: workbook.company,\r\n      created: workbook.created,\r\n      modified: workbook.modified,\r\n      description: workbook.description,\r\n    };\r\n\r\n    // Filter sheets\r\n    let sheetsToProcess: ExcelJS.Worksheet[] = [];\r\n\r\n    if (sheetName !== undefined) {\r\n      if (typeof sheetName === \"number\") {\r\n        const sheet = workbook.worksheets[sheetName];\r\n        if (sheet) sheetsToProcess.push(sheet);\r\n      } else {\r\n        const sheet = workbook.getWorksheet(sheetName);\r\n        if (sheet) sheetsToProcess.push(sheet);\r\n      }\r\n    } else {\r\n      sheetsToProcess = workbook.worksheets;\r\n    }\r\n\r\n    // If single sheet, return single format\r\n    if (sheetsToProcess.length === 1) {\r\n      const worksheet = sheetsToProcess[0]!;\r\n      const flatOptions: {\r\n        useFirstRowAsHeaders: boolean;\r\n        includeEmptyRows: boolean;\r\n        startRow: number;\r\n        endRow?: number;\r\n        startColumn?: number;\r\n        endColumn?: number;\r\n      } = {\r\n        useFirstRowAsHeaders,\r\n        includeEmptyRows,\r\n        startRow,\r\n      };\r\n\r\n      if (endRow !== undefined) {\r\n        flatOptions.endRow = endRow;\r\n      }\r\n      if (startColumn !== undefined) {\r\n        flatOptions.startColumn = startColumn;\r\n      }\r\n      if (endColumn !== undefined) {\r\n        flatOptions.endColumn = endColumn;\r\n      }\r\n\r\n      const flatData = this.convertSheetToFlat(worksheet, flatOptions);\r\n      return flatData;\r\n    }\r\n\r\n    // Multiple sheets - return multi-sheet format\r\n    const sheets: Record<string, IFlatFormat> = {};\r\n\r\n    for (const worksheet of sheetsToProcess) {\r\n      const flatOptions: {\r\n        useFirstRowAsHeaders: boolean;\r\n        includeEmptyRows: boolean;\r\n        startRow: number;\r\n        endRow?: number;\r\n        startColumn?: number;\r\n        endColumn?: number;\r\n      } = {\r\n        useFirstRowAsHeaders,\r\n        includeEmptyRows,\r\n        startRow,\r\n      };\r\n\r\n      if (endRow !== undefined) {\r\n        flatOptions.endRow = endRow;\r\n      }\r\n      if (startColumn !== undefined) {\r\n        flatOptions.startColumn = startColumn;\r\n      }\r\n      if (endColumn !== undefined) {\r\n        flatOptions.endColumn = endColumn;\r\n      }\r\n\r\n      const flatData = this.convertSheetToFlat(worksheet, flatOptions);\r\n      sheets[worksheet.name] = flatData;\r\n    }\r\n\r\n    const result: IFlatFormatMultiSheet = {\r\n      sheets,\r\n      totalSheets: Object.keys(sheets).length,\r\n    };\r\n\r\n    const hasMetadata = Object.values(metadata).some(\r\n      (val) => val !== undefined && val !== null,\r\n    );\r\n    if (hasMetadata) {\r\n      result.metadata = metadata;\r\n    }\r\n\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Convert a single sheet to flat format\r\n   */\r\n  private convertSheetToFlat(\r\n    worksheet: ExcelJS.Worksheet,\r\n    options: {\r\n      useFirstRowAsHeaders: boolean;\r\n      includeEmptyRows: boolean;\r\n      startRow: number;\r\n      endRow?: number;\r\n      startColumn?: number;\r\n      endColumn?: number;\r\n    },\r\n  ): IFlatFormat {\r\n    const {\r\n      useFirstRowAsHeaders,\r\n      includeEmptyRows,\r\n      startRow,\r\n      endRow,\r\n      startColumn,\r\n      endColumn,\r\n    } = options;\r\n\r\n    const actualStartRow = Math.max(startRow, 1);\r\n    const actualEndRow =\r\n      endRow || worksheet.rowCount || worksheet.lastRow?.number || 1;\r\n    const actualStartCol = Math.max(startColumn || 1, 1);\r\n    const actualEndCol =\r\n      endColumn || worksheet.columnCount || worksheet.lastColumn?.number || 1;\r\n\r\n    const data: Array<Record<string, unknown> | unknown[]> = [];\r\n    let headers: string[] | undefined;\r\n\r\n    // Get headers if needed\r\n    if (useFirstRowAsHeaders) {\r\n      const headerRow = worksheet.getRow(actualStartRow);\r\n      headers = [];\r\n      for (let colNum = actualStartCol; colNum <= actualEndCol; colNum++) {\r\n        const cell = headerRow.getCell(colNum);\r\n        headers.push(String(cell.value || `Column${colNum}`));\r\n      }\r\n    }\r\n\r\n    // Process data rows\r\n    const dataStartRow = useFirstRowAsHeaders\r\n      ? actualStartRow + 1\r\n      : actualStartRow;\r\n\r\n    for (let rowNum = dataStartRow; rowNum <= actualEndRow; rowNum++) {\r\n      const excelRow = worksheet.getRow(rowNum);\r\n      const rowValues: unknown[] = [];\r\n      let hasData = false;\r\n\r\n      for (let colNum = actualStartCol; colNum <= actualEndCol; colNum++) {\r\n        const cell = excelRow.getCell(colNum);\r\n        const cellValue = this.getCellValue(cell, {\r\n          includeFormatting: false,\r\n          includeFormulas: false,\r\n          datesAsISO: true,\r\n        });\r\n        rowValues.push(cellValue.value);\r\n        if (\r\n          cellValue.value !== null &&\r\n          cellValue.value !== undefined &&\r\n          cellValue.value !== \"\"\r\n        ) {\r\n          hasData = true;\r\n        }\r\n      }\r\n\r\n      if (!hasData && !includeEmptyRows) {\r\n        continue;\r\n      }\r\n\r\n      if (useFirstRowAsHeaders && headers) {\r\n        // Convert to object\r\n        const rowObject: Record<string, unknown> = {};\r\n        headers.forEach((header, index) => {\r\n          rowObject[header] = rowValues[index];\r\n        });\r\n        data.push(rowObject);\r\n      } else {\r\n        // Keep as array\r\n        data.push(rowValues);\r\n      }\r\n    }\r\n\r\n    const result: IFlatFormat = {\r\n      data,\r\n      totalRows: data.length,\r\n      sheet: worksheet.name,\r\n    };\r\n\r\n    if (headers) {\r\n      result.headers = headers;\r\n    }\r\n\r\n    return result;\r\n  }\r\n\r\n  /**\r\n   * Get cell value with type information\r\n   */\r\n  private getCellValue(\r\n    cell: ExcelJS.Cell,\r\n    options: {\r\n      includeFormatting: boolean;\r\n      includeFormulas: boolean;\r\n      datesAsISO: boolean;\r\n    },\r\n  ): {\r\n    value: unknown;\r\n    type?: string;\r\n    formattedValue?: string;\r\n    formula?: string;\r\n  } {\r\n    const { includeFormatting, includeFormulas, datesAsISO } = options;\r\n\r\n    let value: unknown = cell.value;\r\n    let type: string | undefined;\r\n    let formattedValue: string | undefined;\r\n    let formula: string | undefined;\r\n\r\n    if (\r\n      cell.type === ExcelJS.ValueType.Null ||\r\n      cell.value === null ||\r\n      cell.value === undefined\r\n    ) {\r\n      value = null;\r\n      type = \"null\";\r\n    } else if (cell.type === ExcelJS.ValueType.Number) {\r\n      value = cell.value as number;\r\n      type = \"number\";\r\n    } else if (cell.type === ExcelJS.ValueType.String) {\r\n      value = cell.value as string;\r\n      type = \"string\";\r\n    } else if (cell.type === ExcelJS.ValueType.Date) {\r\n      const dateValue = cell.value as Date;\r\n      value = datesAsISO ? dateValue.toISOString() : dateValue;\r\n      type = \"date\";\r\n    } else if (cell.type === ExcelJS.ValueType.Boolean) {\r\n      value = cell.value as boolean;\r\n      type = \"boolean\";\r\n    } else if (cell.type === ExcelJS.ValueType.Formula) {\r\n      // Always try to get formula if includeFormulas is true\r\n      if (includeFormulas) {\r\n        formula = cell.formula || undefined;\r\n        value = cell.result || cell.value;\r\n        type = \"formula\";\r\n      } else {\r\n        value = cell.result || cell.value;\r\n        type =\r\n          typeof cell.result === \"number\"\r\n            ? \"number\"\r\n            : typeof cell.result === \"string\"\r\n              ? \"string\"\r\n              : \"unknown\";\r\n      }\r\n    } else if (includeFormulas && cell.formula) {\r\n      // Some cells might have formulas even if type is not Formula\r\n      formula = cell.formula;\r\n    } else if (cell.type === ExcelJS.ValueType.Hyperlink) {\r\n      const hyperlinkValue = cell.value as\r\n        | { text?: string; hyperlink?: string }\r\n        | string;\r\n      if (typeof hyperlinkValue === \"object\" && hyperlinkValue !== null) {\r\n        value = hyperlinkValue.text || hyperlinkValue.hyperlink || cell.value;\r\n      } else {\r\n        value = hyperlinkValue;\r\n      }\r\n      type = \"hyperlink\";\r\n    } else {\r\n      value = cell.value;\r\n      type = \"unknown\";\r\n    }\r\n\r\n    // Get formatted value - use cell.text which is the actual displayed text in Excel\r\n    if (includeFormatting) {\r\n      // cell.text is the formatted text as it appears in Excel\r\n      formattedValue = cell.text || String(value);\r\n    }\r\n\r\n    return {\r\n      value,\r\n      type,\r\n      ...(formattedValue !== undefined && { formattedValue }),\r\n      ...(formula !== undefined && { formula }),\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Convert column number to letter (1 = A, 2 = B, 27 = AA, etc.)\r\n   */\r\n  private numberToColumnLetter(columnNumber: number): string {\r\n    let result = \"\";\r\n    while (columnNumber > 0) {\r\n      columnNumber--;\r\n      result = String.fromCharCode(65 + (columnNumber % 26)) + result;\r\n      columnNumber = Math.floor(columnNumber / 26);\r\n    }\r\n    return result;\r\n  }\r\n}\r\n","/**\r\n * StyleBuilder - Fluent API for creating Excel styles\r\n */\r\n\r\nimport {\r\n  IStyle,\r\n  IBorder,\r\n  IConditionalFormat,\r\n  IStyleBuilder as IStyleBuilderInterface\r\n} from '../types/style.types';\r\nimport { \r\n  Color, \r\n  HorizontalAlignment,\r\n  VerticalAlignment,\r\n  BorderStyle, \r\n  FontStyle \r\n} from '../types/core.types';\r\n\r\n/**\r\n * StyleBuilder class providing a fluent API for creating Excel styles\r\n */\r\nexport class StyleBuilder implements IStyleBuilderInterface {\r\n  private style: Partial<IStyle> = {};\r\n\r\n  constructor() {\r\n    this.style.alignment = {\r\n      horizontal: HorizontalAlignment.CENTER,\r\n      vertical: VerticalAlignment.MIDDLE,\r\n      wrapText: true,\r\n      shrinkToFit: true\r\n    };\r\n  }\r\n\r\n  static create(): StyleBuilder {\r\n    return new StyleBuilder();\r\n  }\r\n\r\n  fontName(name: string): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.name = name;\r\n    return this;\r\n  }\r\n\r\n  fontSize(size: number): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.size = size;\r\n    return this;\r\n  }\r\n\r\n  fontStyle(style: FontStyle): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.style = style;\r\n    return this;\r\n  }\r\n\r\n  fontColor(color: Color): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.color = color;\r\n    return this;\r\n  }\r\n\r\n  fontBold(): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.bold = true;\r\n    return this;\r\n  }\r\n\r\n  fontItalic(): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.italic = true;\r\n    return this;\r\n  }\r\n\r\n  fontUnderline(): StyleBuilder {\r\n    if (!this.style.font) {\r\n      this.style.font = {};\r\n    }\r\n    this.style.font.underline = true;\r\n    return this;\r\n  }\r\n\r\n  border(style: BorderStyle, color?: Color): StyleBuilder {\r\n    if (!this.style.border) {\r\n      this.style.border = {};\r\n    }\r\n    const border: IBorder = { style };\r\n    if (color) border.color = color;\r\n    this.style.border.top = border;\r\n    this.style.border.bottom = border;\r\n    this.style.border.left = border;\r\n    this.style.border.right = border;\r\n    return this;\r\n  }\r\n\r\n  borderTop(style: BorderStyle, color?: Color): StyleBuilder {\r\n    if (!this.style.border) {\r\n      this.style.border = {};\r\n    }\r\n    this.style.border.top = { style, color };\r\n    return this;\r\n  }\r\n\r\n  borderLeft(style: BorderStyle, color?: Color): StyleBuilder {\r\n    if (!this.style.border) {\r\n      this.style.border = {};\r\n    }\r\n    this.style.border.left = { style, color };\r\n    return this;\r\n  }\r\n\r\n  borderBottom(style: BorderStyle, color?: Color): StyleBuilder {\r\n    if (!this.style.border) {\r\n      this.style.border = {};\r\n    }\r\n    this.style.border.bottom = { style, color };\r\n    return this;\r\n  }\r\n\r\n  borderRight(style: BorderStyle, color?: Color): StyleBuilder {\r\n    if (!this.style.border) {\r\n      this.style.border = {};\r\n    }\r\n    this.style.border.right = { style, color };\r\n    return this;\r\n  }\r\n\r\n  backgroundColor(color: Color): StyleBuilder {\r\n    if (!this.style.fill) {\r\n      this.style.fill = { type: 'pattern' };\r\n    }\r\n    this.style.fill.backgroundColor = color;\r\n    this.style.fill.pattern = 'solid';\r\n    return this;\r\n  }\r\n\r\n  horizontalAlign(alignment: HorizontalAlignment): StyleBuilder {\r\n    if (!this.style.alignment) {\r\n      this.style.alignment = {};\r\n    }\r\n    this.style.alignment.horizontal = alignment;\r\n    return this;\r\n  }\r\n\r\n  verticalAlign(alignment: VerticalAlignment): StyleBuilder {\r\n    if (!this.style.alignment) {\r\n      this.style.alignment = {};\r\n    }\r\n    this.style.alignment.vertical = alignment;\r\n    return this;\r\n  }\r\n\r\n  centerAlign(): StyleBuilder {\r\n    return this.horizontalAlign(HorizontalAlignment.CENTER);\r\n  }\r\n\r\n  leftAlign(): StyleBuilder {\r\n    return this.horizontalAlign(HorizontalAlignment.LEFT);\r\n  }\r\n\r\n  rightAlign(): StyleBuilder {\r\n    return this.horizontalAlign(HorizontalAlignment.RIGHT);\r\n  }\r\n\r\n  wrapText(): StyleBuilder {\r\n    if (!this.style.alignment) {\r\n      this.style.alignment = {};\r\n    }\r\n    this.style.alignment.wrapText = true;\r\n    return this;\r\n  }\r\n\r\n  /** Enable or disable shrink-to-fit */\r\n  shrinkToFit(enabled: boolean = true): StyleBuilder {\r\n    if (!this.style.alignment) {\r\n      this.style.alignment = {};\r\n    }\r\n    this.style.alignment.shrinkToFit = Boolean(enabled);\r\n    return this;\r\n  }\r\n\r\n  numberFormat(format: string): StyleBuilder {\r\n    this.style.numberFormat = format;\r\n    return this;\r\n  }\r\n\r\n  striped(): StyleBuilder {\r\n    this.style.striped = true;\r\n    return this;\r\n  }\r\n\r\n  conditionalFormat(format: IConditionalFormat): StyleBuilder {\r\n    if (!this.style.conditionalFormats) {\r\n      this.style.conditionalFormats = [];\r\n    }\r\n    this.style.conditionalFormats.push(format);\r\n    return this;\r\n  }\r\n\r\n  build(): IStyle {\r\n    return this.style as IStyle;\r\n  }\r\n}\r\n\r\n","/**\r\n * Cell-specific type definitions\r\n */\r\n\r\nimport { IBaseCell } from './core.types';\r\nimport type { CellValue } from 'exceljs';\r\n\r\n/**\r\n * Header cell interface\r\n */\r\nexport interface IHeaderCell extends IBaseCell {\r\n  /** Reference to parent header key */\r\n  mainHeaderKey?: string;\r\n  /** Child headers */\r\n  children?: IHeaderCell[];\r\n  /** Whether this is a main header */\r\n  isMainHeader?: boolean;\r\n  /** Header level (1 = main, 2 = sub, etc.) */\r\n  level?: number;\r\n}\r\n\r\n/**\r\n * Data cell interface\r\n */\r\nexport interface IDataCell extends IBaseCell {\r\n  /** Reference to header key */\r\n  header: string;\r\n  /** Reference to main header key */\r\n  mainHeaderKey?: string;\r\n  /** Child data cells */\r\n  children?: IDataCell[];\r\n  /** Whether this cell has alternating row color */\r\n  striped?: boolean;\r\n  /** Row index */\r\n  rowIndex?: number;\r\n  /** Column index */\r\n  colIndex?: number;\r\n}\r\n\r\n/**\r\n * Footer cell interface\r\n */\r\nexport interface IFooterCell extends IBaseCell {\r\n  /** Reference to header key */\r\n  header: string;\r\n  /** Child footer cells */\r\n  children?: IDataCell[];\r\n  /** Whether this is a total row */\r\n  isTotal?: boolean;\r\n  /** Footer type */\r\n  footerType?: 'total' | 'subtotal' | 'average' | 'count' | 'custom';\r\n}\r\n\r\n/**\r\n * Cell position interface\r\n */\r\nexport interface ICellPosition {\r\n  /** Row index (1-based) */\r\n  row: number;\r\n  /** Column index (1-based) */\r\n  col: number;\r\n  /** Cell reference (e.g., A1) */\r\n  reference: string;\r\n}\r\n\r\n/**\r\n * Cell range interface\r\n */\r\nexport interface ICellRange {\r\n  /** Start position */\r\n  start: ICellPosition;\r\n  /** End position */\r\n  end: ICellPosition;\r\n  /** Range reference (e.g., A1:B10) */\r\n  reference: string;\r\n}\r\n\r\n/**\r\n * Cell data for different types\r\n */\r\nexport interface ICellData {\r\n  /** String cell data */\r\n  string?: {\r\n    value: string;\r\n    maxLength?: number;\r\n    trim?: boolean;\r\n  };\r\n  /** Number cell data */\r\n  number?: {\r\n    value: number;\r\n    min?: number;\r\n    max?: number;\r\n    precision?: number;\r\n    allowNegative?: boolean;\r\n  };\r\n  /** Date cell data */\r\n  date?: {\r\n    value: Date;\r\n    min?: Date;\r\n    max?: Date;\r\n    format?: string;\r\n  };\r\n  /** Boolean cell data */\r\n  boolean?: {\r\n    value: boolean;\r\n    trueText?: string;\r\n    falseText?: string;\r\n  };\r\n  /** Percentage cell data */\r\n  percentage?: {\r\n    value: number;\r\n    min?: number;\r\n    max?: number;\r\n    precision?: number;\r\n    showSymbol?: boolean;\r\n  };\r\n  /** Currency cell data */\r\n  currency?: {\r\n    value: number;\r\n    currency?: string;\r\n    precision?: number;\r\n    showSymbol?: boolean;\r\n  };\r\n  /** Link cell data */\r\n  link?: {\r\n    value: string;\r\n    text?: string;\r\n    tooltip?: string;\r\n  };\r\n  /** Formula cell data */\r\n  formula?: {\r\n    value: string;\r\n    result?: CellValue;\r\n  };\r\n}\r\n\r\n/**\r\n * Cell validation result\r\n */\r\nexport interface ICellValidationResult {\r\n  /** Whether the cell is valid */\r\n  isValid: boolean;\r\n  /** Validation errors */\r\n  errors: string[];\r\n  /** Validation warnings */\r\n  warnings: string[];\r\n}\r\n\r\n/**\r\n * Cell event types\r\n */\r\nexport enum CellEventType {\r\n  CREATED = 'created',\r\n  UPDATED = 'updated',\r\n  DELETED = 'deleted',\r\n  STYLED = 'styled',\r\n  VALIDATED = 'validated'\r\n}\r\n\r\n/**\r\n * Cell event interface\r\n */\r\nexport interface ICellEvent {\r\n  type: CellEventType;\r\n  cell: IDataCell | IHeaderCell | IFooterCell;\r\n  position: ICellPosition;\r\n  timestamp: Date;\r\n  data?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Rich text run interface (for formatted text within a cell)\r\n */\r\nexport interface IRichTextRun {\r\n  /** Text content */\r\n  text: string;\r\n  /** Font name */\r\n  font?: string;\r\n  /** Font size */\r\n  size?: number;\r\n  /** Font color */\r\n  color?: string | { r: number; g: number; b: number } | { theme: number };\r\n  /** Bold */\r\n  bold?: boolean;\r\n  /** Italic */\r\n  italic?: boolean;\r\n  /** Underline */\r\n  underline?: boolean;\r\n  /** Strikethrough */\r\n  strikethrough?: boolean;\r\n}\r\n\r\n","/**\r\n * Worksheet-specific type definitions\r\n */\r\n\r\nimport { IHeaderCell, IDataCell, IFooterCell, ICellPosition, ICellRange } from './cell.types';\r\nimport { Color, Result } from './core.types';\r\n\r\n/**\r\n * Worksheet configuration interface\r\n */\r\nexport interface IWorksheetConfig {\r\n  /** Worksheet name */\r\n  name: string;\r\n  /** Tab color */\r\n  tabColor?: Color;\r\n  /** Default row height */\r\n  defaultRowHeight?: number;\r\n  /** Default column width */\r\n  defaultColWidth?: number;\r\n  /** Whether the worksheet is hidden */\r\n  hidden?: boolean;\r\n  /** Whether the worksheet is protected */\r\n  protected?: boolean;\r\n  /** Protection password */\r\n  protectionPassword?: string;\r\n  /** Whether to show grid lines */\r\n  showGridLines?: boolean;\r\n  /** Whether to show row and column headers */\r\n  showRowColHeaders?: boolean;\r\n  /** Zoom level (1-400) */\r\n  zoom?: number;\r\n  /** Freeze panes position */\r\n  freezePanes?: ICellPosition;\r\n  /** Print area */\r\n  printArea?: ICellRange;\r\n  /** Fit to page settings */\r\n  fitToPage?: {\r\n    fitToWidth?: number;\r\n    fitToHeight?: number;\r\n  };\r\n  /** Page setup */\r\n  pageSetup?: {\r\n    orientation?: 'portrait' | 'landscape';\r\n    paperSize?: number;\r\n    fitToPage?: boolean;\r\n    fitToWidth?: number;\r\n    fitToHeight?: number;\r\n    scale?: number;\r\n    horizontalCentered?: boolean;\r\n    verticalCentered?: boolean;\r\n    margins?: {\r\n      top?: number;\r\n      left?: number;\r\n      bottom?: number;\r\n      right?: number;\r\n      header?: number;\r\n      footer?: number;\r\n    };\r\n  };\r\n  /** Auto filter configuration */\r\n  autoFilter?: {\r\n    /** Enable auto filter for the worksheet */\r\n    enabled?: boolean;\r\n    /** Auto filter range (if not specified, applies to all data) */\r\n    range?: ICellRange;\r\n    /** Start row for auto filter (1-based, default: first data row) */\r\n    startRow?: number;\r\n    /** End row for auto filter (1-based, default: last data row) */\r\n    endRow?: number;\r\n    /** Start column for auto filter (1-based, default: 1) */\r\n    startColumn?: number;\r\n    /** End column for auto filter (1-based, default: last column) */\r\n    endColumn?: number;\r\n  };\r\n  /** Print headers/footers configuration */\r\n  printHeadersFooters?: {\r\n    /** Header text (left, center, right) */\r\n    header?: {\r\n      left?: string;\r\n      center?: string;\r\n      right?: string;\r\n    };\r\n    /** Footer text (left, center, right) */\r\n    footer?: {\r\n      left?: string;\r\n      center?: string;\r\n      right?: string;\r\n    };\r\n  };\r\n  /** Repeat rows/columns on each printed page */\r\n  printRepeat?: {\r\n    /** Rows to repeat (e.g., \"1:2\" or [1, 2]) */\r\n    rows?: string | number[];\r\n    /** Columns to repeat (e.g., \"A:B\" or [1, 2]) */\r\n    columns?: string | number[];\r\n  };\r\n  /** Split panes configuration (divides window into panes) */\r\n  splitPanes?: {\r\n    /** Horizontal split position (column number, 0 = no split) */\r\n    xSplit?: number;\r\n    /** Vertical split position (row number, 0 = no split) */\r\n    ySplit?: number;\r\n    /** Top-left cell in bottom-right pane */\r\n    topLeftCell?: string;\r\n    /** Active pane (topLeft, topRight, bottomLeft, bottomRight) */\r\n    activePane?: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight';\r\n  };\r\n  /** Sheet views configuration */\r\n  views?: {\r\n    /** View state (normal, pageBreakPreview, pageLayout) */\r\n    state?: 'normal' | 'pageBreakPreview' | 'pageLayout';\r\n    /** Zoom level (10-400) */\r\n    zoomScale?: number;\r\n    /** Normal zoom level */\r\n    zoomScaleNormal?: number;\r\n    /** Show grid lines */\r\n    showGridLines?: boolean;\r\n    /** Show row and column headers */\r\n    showRowColHeaders?: boolean;\r\n    /** Show ruler (page layout view) */\r\n    showRuler?: boolean;\r\n    /** Right-to-left */\r\n    rightToLeft?: boolean;\r\n  };\r\n}\r\n\r\n/**\r\n * Table structure interface\r\n */\r\nexport interface ITable {\r\n  /** Table name */\r\n  name?: string;\r\n  /** Table headers */\r\n  headers?: IHeaderCell[];\r\n  /** Table sub-headers */\r\n  subHeaders?: IHeaderCell[];\r\n  /** Table data rows */\r\n  body?: IDataCell[];\r\n  /** Table footers */\r\n  footers?: IFooterCell[];\r\n  /** Table range */\r\n  range?: ICellRange;\r\n  /** Whether to show table borders */\r\n  showBorders?: boolean;\r\n  /** Whether to show alternating row colors */\r\n  showStripes?: boolean;\r\n  /** Table style */\r\n  style?: 'TableStyleLight1' | 'TableStyleLight2' | 'TableStyleMedium1' | 'TableStyleMedium2' | 'TableStyleDark1' | 'TableStyleDark2';\r\n  /** Auto filter for this table */\r\n  autoFilter?: boolean;\r\n}\r\n\r\n/**\r\n * Worksheet interface\r\n */\r\nexport interface IWorksheet {\r\n  /** Worksheet configuration */\r\n  config: IWorksheetConfig;\r\n  /** Tables in the worksheet */\r\n  tables: ITable[];\r\n  /** Current row pointer */\r\n  currentRow: number;\r\n  /** Current column pointer */\r\n  currentCol: number;\r\n  /** Header pointers for navigation */\r\n  headerPointers: Map<string, ICellPosition>;\r\n  /** Whether the worksheet has been built */\r\n  isBuilt: boolean;\r\n\r\n  /** Add a header */\r\n  addHeader(header: IHeaderCell): this;\r\n  /** Add subheaders */\r\n  addSubHeaders(subHeaders: IHeaderCell[]): this;\r\n  /** Add a row or rows */\r\n  addRow(row: IDataCell[] | IDataCell): this;\r\n  /** Add a footer or footers */\r\n  addFooter(footer: IFooterCell[] | IFooterCell): this;\r\n  /** Add a new table to the worksheet */\r\n  addTable(tableConfig?: Partial<ITable>): this;\r\n  /** Finalize the current table with temporary data */\r\n  finalizeTable(): this;\r\n  /** Get a table by name */\r\n  getTable(name: string): ITable | undefined;\r\n  /** Add an image to the worksheet */\r\n  addImage(image: IWorksheetImage): this;\r\n  /** Group rows (create collapsible outline) */\r\n  groupRows(startRow: number, endRow: number, collapsed?: boolean): this;\r\n  /** Group columns (create collapsible outline) */\r\n  groupColumns(startCol: number, endCol: number, collapsed?: boolean): this;\r\n  /** Add a named range */\r\n  addNamedRange(name: string, range: string | ICellRange, scope?: string): this;\r\n  /** Add an Excel structured table */\r\n  addExcelTable(table: IExcelTable): this;\r\n  /** Hide rows */\r\n  hideRows(rows: number | number[]): this;\r\n  /** Show rows */\r\n  showRows(rows: number | number[]): this;\r\n  /** Hide columns */\r\n  hideColumns(columns: number | string | (number | string)[]): this;\r\n  /** Show columns */\r\n  showColumns(columns: number | string | (number | string)[]): this;\r\n  /** Add a pivot table */\r\n  addPivotTable(pivotTable: IPivotTable): this;\r\n  /** Add a slicer to a table or pivot table */\r\n  addSlicer(slicer: ISlicer): this;\r\n  /** Add a watermark to the worksheet */\r\n  addWatermark(watermark: IWatermark): this;\r\n  /** Add a data connection */\r\n  addDataConnection(connection: IDataConnection): this;\r\n  /** Build the worksheet */\r\n  build(workbook: any, options?: any): Promise<void>;\r\n  /** Validate the worksheet */\r\n  validate(): Result<boolean>;\r\n}\r\n\r\n/**\r\n * Worksheet event types\r\n */\r\nexport enum WorksheetEventType {\r\n  CREATED = 'created',\r\n  UPDATED = 'updated',\r\n  DELETED = 'deleted',\r\n  TABLE_ADDED = 'tableAdded',\r\n  TABLE_REMOVED = 'tableRemoved',\r\n  CELL_ADDED = 'cellAdded',\r\n  CELL_UPDATED = 'cellUpdated',\r\n  CELL_DELETED = 'cellDeleted'\r\n}\r\n\r\n/**\r\n * Worksheet event interface\r\n */\r\nexport interface IWorksheetEvent {\r\n  type: WorksheetEventType;\r\n  worksheet: IWorksheet;\r\n  data?: Record<string, unknown>;\r\n  timestamp: Date;\r\n}\r\n\r\n/**\r\n * Worksheet validation result\r\n */\r\nexport interface IWorksheetValidationResult {\r\n  /** Whether the worksheet is valid */\r\n  isValid: boolean;\r\n  /** Validation errors */\r\n  errors: string[];\r\n  /** Validation warnings */\r\n  warnings: string[];\r\n  /** Cell validation results */\r\n  cellResults: Map<string, boolean>;\r\n}\r\n\r\n/**\r\n * Worksheet statistics\r\n */\r\nexport interface IWorksheetStats {\r\n  /** Total number of cells */\r\n  totalCells: number;\r\n  /** Number of header cells */\r\n  headerCells: number;\r\n  /** Number of data cells */\r\n  dataCells: number;\r\n  /** Number of footer cells */\r\n  footerCells: number;\r\n  /** Number of tables */\r\n  tables: number;\r\n  /** Used range */\r\n  usedRange: ICellRange;\r\n  /** Memory usage in bytes */\r\n  memoryUsage: number;\r\n}\r\n\r\n/**\r\n * Image configuration for worksheet\r\n */\r\nexport interface IWorksheetImage {\r\n  /** Image buffer (ArrayBuffer, Uint8Array, or base64 string) */\r\n  buffer: ArrayBuffer | Uint8Array | string;\r\n  /** Image name/ID */\r\n  name?: string;\r\n  /** Image extension (png, jpeg, gif, etc.) */\r\n  extension: 'png' | 'jpeg' | 'jpg' | 'gif' | 'bmp' | 'webp';\r\n  /** Position - can be cell reference or absolute position */\r\n  position: {\r\n    /** Cell reference (e.g., 'A1') or row number (1-based) */\r\n    row: string | number;\r\n    /** Column letter (e.g., 'A') or column number (1-based) */\r\n    col: string | number;\r\n  };\r\n  /** Image size */\r\n  size?: {\r\n    /** Width in pixels or Excel units */\r\n    width?: number;\r\n    /** Height in pixels or Excel units */\r\n    height?: number;\r\n    /** Scale factor (0-1) */\r\n    scaleX?: number;\r\n    /** Scale factor (0-1) */\r\n    scaleY?: number;\r\n  };\r\n  /** Hyperlink for image (optional) */\r\n  hyperlink?: string;\r\n  /** Image description/alt text */\r\n  description?: string;\r\n}\r\n\r\n/**\r\n * Pivot table configuration\r\n */\r\nexport interface IPivotTable {\r\n  /** Pivot table name */\r\n  name: string;\r\n  /** Reference cell where pivot table starts (e.g., 'A1') */\r\n  ref: string;\r\n  /** Source data range (e.g., 'A1:D100') */\r\n  sourceRange: string;\r\n  /** Source worksheet name (if different from current) */\r\n  sourceSheet?: string;\r\n  /** Pivot table fields configuration */\r\n  fields: {\r\n    /** Rows fields */\r\n    rows?: string[];\r\n    /** Columns fields */\r\n    columns?: string[];\r\n    /** Values fields with aggregation function */\r\n    values?: Array<{\r\n      name: string;\r\n      stat: 'sum' | 'count' | 'average' | 'min' | 'max' | 'stdDev' | 'var';\r\n    }>;\r\n    /** Filters fields */\r\n    filters?: string[];\r\n  };\r\n  /** Pivot table options */\r\n  options?: {\r\n    /** Show grand totals for rows */\r\n    showRowGrandTotals?: boolean;\r\n    /** Show grand totals for columns */\r\n    showColGrandTotals?: boolean;\r\n    /** Show headers */\r\n    showHeaders?: boolean;\r\n  };\r\n}\r\n\r\n/**\r\n * Slicer configuration for tables and pivot tables\r\n */\r\nexport interface ISlicer {\r\n  /** Slicer name */\r\n  name: string;\r\n  /** Target table or pivot table name */\r\n  targetTable: string;\r\n  /** Column/field to create slicer for */\r\n  column: string;\r\n  /** Position where slicer should be placed */\r\n  position: {\r\n    /** Row number (1-based) */\r\n    row: number;\r\n    /** Column number or letter (1-based or 'A', 'B', etc.) */\r\n    col: number | string;\r\n  };\r\n  /** Slicer size */\r\n  size?: {\r\n    /** Width in pixels */\r\n    width?: number;\r\n    /** Height in pixels */\r\n    height?: number;\r\n  };\r\n  /** Slicer style */\r\n  style?: {\r\n    /** Caption style */\r\n    caption?: string;\r\n    /** Item style */\r\n    itemStyle?: string;\r\n  };\r\n}\r\n\r\n/**\r\n * Watermark configuration\r\n */\r\nexport interface IWatermark {\r\n  /** Watermark text */\r\n  text?: string;\r\n  /** Watermark image (alternative to text) */\r\n  image?: IWorksheetImage;\r\n  /** Position */\r\n  position?: {\r\n    /** Horizontal position: 'left' | 'center' | 'right' */\r\n    horizontal?: 'left' | 'center' | 'right';\r\n    /** Vertical position: 'top' | 'middle' | 'bottom' */\r\n    vertical?: 'top' | 'middle' | 'bottom';\r\n  };\r\n  /** Opacity (0-1) */\r\n  opacity?: number;\r\n  /** Rotation in degrees */\r\n  rotation?: number;\r\n  /** Font size (if using text) */\r\n  fontSize?: number;\r\n  /** Font color (if using text) */\r\n  fontColor?: string;\r\n}\r\n\r\n/**\r\n * Data connection configuration\r\n */\r\nexport interface IDataConnection {\r\n  /** Connection name */\r\n  name: string;\r\n  /** Connection type */\r\n  type: 'odbc' | 'oledb' | 'web' | 'text' | 'xml';\r\n  /** Connection string or URL */\r\n  connectionString: string;\r\n  /** Command text (SQL query, etc.) */\r\n  commandText?: string;\r\n  /** Refresh settings */\r\n  refresh?: {\r\n    /** Auto refresh on open */\r\n    refreshOnOpen?: boolean;\r\n    /** Refresh interval in minutes */\r\n    refreshInterval?: number;\r\n  };\r\n  /** Credentials */\r\n  credentials?: {\r\n    /** Username */\r\n    username?: string;\r\n    /** Password */\r\n    password?: string;\r\n    /** Integrated security */\r\n    integratedSecurity?: boolean;\r\n  };\r\n}\r\n\r\n/**\r\n * Excel structured table configuration\r\n */\r\nexport interface IExcelTable {\r\n  /** Table name */\r\n  name: string;\r\n  /** Table range (start and end cells) */\r\n  range: {\r\n    /** Start cell reference (e.g., 'A1') */\r\n    start: string;\r\n    /** End cell reference (e.g., 'D10') */\r\n    end: string;\r\n  };\r\n  /** Table style */\r\n  style?: 'TableStyleLight1' | 'TableStyleLight2' | 'TableStyleLight3' | 'TableStyleLight4' | 'TableStyleLight5' | 'TableStyleLight6' | 'TableStyleLight7' | 'TableStyleLight8' | 'TableStyleLight9' | 'TableStyleLight10' | 'TableStyleLight11' | 'TableStyleLight12' | 'TableStyleLight13' | 'TableStyleLight14' | 'TableStyleLight15' | 'TableStyleLight16' | 'TableStyleLight17' | 'TableStyleLight18' | 'TableStyleLight19' | 'TableStyleLight20' | 'TableStyleLight21' | 'TableStyleMedium1' | 'TableStyleMedium2' | 'TableStyleMedium3' | 'TableStyleMedium4' | 'TableStyleMedium5' | 'TableStyleMedium6' | 'TableStyleMedium7' | 'TableStyleMedium8' | 'TableStyleMedium9' | 'TableStyleMedium10' | 'TableStyleMedium11' | 'TableStyleMedium12' | 'TableStyleMedium13' | 'TableStyleMedium14' | 'TableStyleMedium15' | 'TableStyleMedium16' | 'TableStyleMedium17' | 'TableStyleMedium18' | 'TableStyleMedium19' | 'TableStyleMedium20' | 'TableStyleMedium21' | 'TableStyleMedium22' | 'TableStyleMedium23' | 'TableStyleMedium24' | 'TableStyleMedium25' | 'TableStyleMedium26' | 'TableStyleMedium27' | 'TableStyleMedium28' | 'TableStyleDark1' | 'TableStyleDark2' | 'TableStyleDark3' | 'TableStyleDark4' | 'TableStyleDark5' | 'TableStyleDark6' | 'TableStyleDark7' | 'TableStyleDark8' | 'TableStyleDark9' | 'TableStyleDark10' | 'TableStyleDark11';\r\n  /** Whether to show header row */\r\n  headerRow?: boolean;\r\n  /** Whether to show total row */\r\n  totalRow?: boolean;\r\n  /** Column definitions */\r\n  columns?: Array<{\r\n    /** Column name */\r\n    name: string;\r\n    /** Column filter button */\r\n    filterButton?: boolean;\r\n    /** Totals row function */\r\n    totalsRowFunction?: 'none' | 'sum' | 'min' | 'max' | 'average' | 'count' | 'countNums' | 'stdDev' | 'var' | 'custom';\r\n    /** Totals row formula */\r\n    totalsRowFormula?: string;\r\n  }>;\r\n}\r\n\r\n","/**\r\n * Style-specific type definitions\r\n */\r\n\r\nimport { \r\n  Color, \r\n  HorizontalAlignment, \r\n  VerticalAlignment, \r\n  BorderStyle, \r\n  FontStyle \r\n} from './core.types';\r\n\r\n/**\r\n * Font configuration interface\r\n */\r\nexport interface IFont {\r\n  /** Font name */\r\n  name?: string;\r\n  /** Font size */\r\n  size?: number;\r\n  /** Font style */\r\n  style?: FontStyle;\r\n  /** Font color */\r\n  color?: Color;\r\n  /** Whether the font is bold */\r\n  bold?: boolean;\r\n  /** Whether the font is italic */\r\n  italic?: boolean;\r\n  /** Whether the font is underlined */\r\n  underline?: boolean;\r\n  /** Whether the font is strikethrough */\r\n  strikethrough?: boolean;\r\n  /** Font family */\r\n  family?: string;\r\n  /** Font scheme */\r\n  scheme?: 'major' | 'minor' | 'none';\r\n}\r\n\r\n/**\r\n * Border configuration interface\r\n */\r\nexport interface IBorder {\r\n  /** Border style */\r\n  style?: BorderStyle;\r\n  /** Border color */\r\n  color?: Color;\r\n  /** Border width */\r\n  width?: number;\r\n}\r\n\r\n/**\r\n * Border sides interface\r\n */\r\nexport interface IBorderSides {\r\n  /** Top border */\r\n  top?: IBorder;\r\n  /** Left border */\r\n  left?: IBorder;\r\n  /** Bottom border */\r\n  bottom?: IBorder;\r\n  /** Right border */\r\n  right?: IBorder;\r\n  /** Diagonal border */\r\n  diagonal?: IBorder;\r\n  /** Diagonal direction */\r\n  diagonalDirection?: 'up' | 'down' | 'both';\r\n}\r\n\r\n/**\r\n * Fill pattern interface\r\n */\r\nexport interface IFill {\r\n  /** Fill type */\r\n  type: 'pattern' | 'gradient';\r\n  /** Pattern type (for pattern fills) */\r\n  pattern?: 'none' | 'solid' | 'darkGray' | 'mediumGray' | 'lightGray' | 'gray125' | 'gray0625' | 'darkHorizontal' | 'darkVertical' | 'darkDown' | 'darkUp' | 'darkGrid' | 'darkTrellis' | 'lightHorizontal' | 'lightVertical' | 'lightDown' | 'lightUp' | 'lightGrid' | 'lightTrellis';\r\n  /** Background color */\r\n  backgroundColor?: Color;\r\n  /** Foreground color */\r\n  foregroundColor?: Color;\r\n  /** Gradient type (for gradient fills) */\r\n  gradient?: 'linear' | 'path';\r\n  /** Gradient stops */\r\n  stops?: Array<{\r\n    position: number;\r\n    color: Color;\r\n  }>;\r\n  /** Gradient angle (for linear gradients) */\r\n  angle?: number;\r\n}\r\n\r\n/**\r\n * Alignment configuration interface\r\n */\r\nexport interface IAlignment {\r\n  /** Horizontal alignment */\r\n  horizontal?: HorizontalAlignment;\r\n  /** Vertical alignment */\r\n  vertical?: VerticalAlignment;\r\n  /** Text rotation (0-180 degrees) */\r\n  textRotation?: number;\r\n  /** Whether to wrap text */\r\n  wrapText?: boolean;\r\n  /** Whether to shrink text to fit */\r\n  shrinkToFit?: boolean;\r\n  /** Indent level */\r\n  indent?: number;\r\n  /** Whether to merge cells */\r\n  mergeCell?: boolean;\r\n  /** Reading order */\r\n  readingOrder?: 'left-to-right' | 'right-to-left';\r\n}\r\n\r\n/**\r\n * Protection configuration interface\r\n */\r\nexport interface IProtection {\r\n  /** Whether the cell is locked */\r\n  locked?: boolean;\r\n  /** Whether the cell is hidden */\r\n  hidden?: boolean;\r\n}\r\n\r\n/**\r\n * Conditional formatting interface\r\n */\r\nexport interface IConditionalFormat {\r\n  /** Condition type */\r\n  type: 'cellIs' | 'containsText' | 'beginsWith' | 'endsWith' | 'containsBlanks' | 'notContainsBlanks' | 'containsErrors' | 'notContainsErrors' | 'timePeriod' | 'top' | 'bottom' | 'aboveAverage' | 'belowAverage' | 'duplicateValues' | 'uniqueValues' | 'expression' | 'colorScale' | 'dataBar' | 'iconSet';\r\n  /** Condition operator */\r\n  operator?: 'between' | 'notBetween' | 'equal' | 'notEqual' | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual';\r\n  /** Condition values */\r\n  values?: Array<string | number | Date>;\r\n  /** Condition formula */\r\n  formula?: string;\r\n  /** Style to apply when condition is met */\r\n  style?: IStyle;\r\n  /** Priority of the condition */\r\n  priority?: number;\r\n  /** Whether to stop if true */\r\n  stopIfTrue?: boolean;\r\n}\r\n\r\n/**\r\n * Main style interface\r\n */\r\nexport interface IStyle {\r\n  /** Font configuration */\r\n  font?: IFont;\r\n  /** Border configuration */\r\n  border?: IBorderSides;\r\n  /** Fill configuration */\r\n  fill?: IFill;\r\n  /** Alignment configuration */\r\n  alignment?: IAlignment;\r\n  /** Protection configuration */\r\n  protection?: IProtection;\r\n  /** Conditional formatting */\r\n  conditionalFormats?: IConditionalFormat[];\r\n  /** Number format */\r\n  numberFormat?: string;\r\n  /** Whether to apply alternating row colors */\r\n  striped?: boolean;\r\n  /** Custom CSS-like properties */\r\n  custom?: Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Style preset types\r\n */\r\nexport enum StylePreset {\r\n  HEADER = 'header',\r\n  SUBHEADER = 'subheader',\r\n  DATA = 'data',\r\n  FOOTER = 'footer',\r\n  TOTAL = 'total',\r\n  HIGHLIGHT = 'highlight',\r\n  WARNING = 'warning',\r\n  ERROR = 'error',\r\n  SUCCESS = 'success',\r\n  INFO = 'info'\r\n}\r\n\r\n/**\r\n * Style theme interface\r\n */\r\nexport interface IStyleTheme {\r\n  /** Theme name */\r\n  name: string;\r\n  /** Theme description */\r\n  description?: string;\r\n  /** Color palette */\r\n  colors: {\r\n    primary: Color;\r\n    secondary: Color;\r\n    accent: Color;\r\n    background: Color;\r\n    text: Color;\r\n    border: Color;\r\n    success: Color;\r\n    warning: Color;\r\n    error: Color;\r\n    info: Color;\r\n  };\r\n  /** Font family */\r\n  fontFamily: string;\r\n  /** Base font size */\r\n  fontSize: number;\r\n  /** Style presets */\r\n  presets: Record<StylePreset, IStyle>;\r\n}\r\n\r\n/**\r\n * Style builder interface\r\n */\r\nexport interface IStyleBuilder {\r\n  /** Set font name */\r\n  fontName(name: string): IStyleBuilder;\r\n  /** Set font size */\r\n  fontSize(size: number): IStyleBuilder;\r\n  /** Set font style */\r\n  fontStyle(style: FontStyle): IStyleBuilder;\r\n  /** Set font color */\r\n  fontColor(color: Color): IStyleBuilder;\r\n  /** Make font bold */\r\n  fontBold(): IStyleBuilder;\r\n  /** Make font italic */\r\n  fontItalic(): IStyleBuilder;\r\n  /** Make font underlined */\r\n  fontUnderline(): IStyleBuilder;\r\n  /** Set border */\r\n  border(style: BorderStyle, color?: Color): IStyleBuilder;\r\n  /** Set specific border */\r\n  borderTop(style: BorderStyle, color?: Color): IStyleBuilder;\r\n  borderLeft(style: BorderStyle, color?: Color): IStyleBuilder;\r\n  borderBottom(style: BorderStyle, color?: Color): IStyleBuilder;\r\n  borderRight(style: BorderStyle, color?: Color): IStyleBuilder;\r\n  /** Set background color */\r\n  backgroundColor(color: Color): IStyleBuilder;\r\n  /** Set horizontal alignment */\r\n  horizontalAlign(alignment: HorizontalAlignment): IStyleBuilder;\r\n  /** Set vertical alignment */\r\n  verticalAlign(alignment: VerticalAlignment): IStyleBuilder;\r\n  /** Center align text */\r\n  centerAlign(): IStyleBuilder;\r\n  /** Left align text */\r\n  leftAlign(): IStyleBuilder;\r\n  /** Right align text */\r\n  rightAlign(): IStyleBuilder;\r\n  /** Wrap text */\r\n  wrapText(): IStyleBuilder;\r\n  /** Enable/disable shrink-to-fit */\r\n  shrinkToFit(enabled?: boolean): IStyleBuilder;\r\n  /** Set number format */\r\n  numberFormat(format: string): IStyleBuilder;\r\n  /** Set striped rows */\r\n  striped(): IStyleBuilder;\r\n  /** Add conditional formatting */\r\n  conditionalFormat(format: IConditionalFormat): IStyleBuilder;\r\n  /** Build the final style */\r\n  build(): IStyle;\r\n}\r\n\r\n"],"names":["EventEmitter","listeners","Map","on","type","listener","options","this","has","set","registration","once","async","priority","stopPropagation","id","generateId","active","timestamp","Date","get","push","sort","a","b","off","listenerId","index","findIndex","reg","splice","offAll","count","length","delete","emit","event","activeListeners","filter","error","console","cleanupInactiveListeners","emitSync","clear","getListeners","getListenerCount","getEventTypes","Array","from","keys","Math","random","toString","substr","ErrorType","CellType","NumberFormat","HorizontalAlignment","VerticalAlignment","BorderStyle","FontStyle","Worksheet","config","tables","currentRow","currentCol","headerPointers","isBuilt","headers","subHeaders","body","footers","images","rowGroups","columnGroups","namedRanges","excelTables","hiddenRows","Set","hiddenColumns","pivotTables","slicers","watermarks","dataConnections","customStyles","theme","constructor","addHeader","header","addSubHeaders","addRow","row","isArray","addFooter","footer","addTable","tableConfig","table","name","showBorders","showStripes","style","finalizeTable","currentTable","Error","getTable","find","addImage","image","groupRows","startRow","endRow","collapsed","start","end","groupColumns","startCol","endCol","addNamedRange","range","scope","rangeString","reference","numberToColumnLetter","col","namedRange","addExcelTable","hideRows","rows","forEach","add","showRows","hideColumns","columns","colNum","columnLetterToNumber","showColumns","addPivotTable","pivotTable","addSlicer","slicer","addWatermark","watermark","addDataConnection","connection","build","workbook","_options","ws","addWorksheet","properties","defaultRowHeight","tabColor","pageSetup","__customStyles","__theme","rowPointer","tableStartRow","i","buildTable","autoFilter","applyAutoFilter","buildLegacyContent","enabled","applyWorksheetAutoFilter","applyViews","protected","protect","protectionPassword","selectLockedCells","selectUnlockedCells","formatCells","formatColumns","formatRows","insertColumns","insertRows","insertHyperlinks","deleteColumns","deleteRows","applyImage","group","applyRowGrouping","applyColumnGrouping","definedNames","excelTable","applyExcelTable","applyAdvancedPrintSettings","applyHiddenRowsColumns","applyPivotTable","applySlicer","applyWatermark","applyDataConnection","addSpacing","cell","getRow","getCell","richText","value","map","run","text","font","size","color","convertColorToExcelJS","bold","italic","underline","strike","strikethrough","processCellValue","mergeCell","maxCols","calculateTableMaxColumns","mergeCells","styles","eachCell","convertStyle","cellProtection","protection","locked","hidden","applyCellDimensions","comment","applyCellComment","validation","applyDataValidation","conditionalFormats","applyConditionalFormatting","buildNestedHeaders","addDataRowRecursive","addFooterRow","applyTableStyle","getMaxColumns","calculateHeaderColSpan","border","top","argb","left","bottom","right","fill","pattern","fgColor","maxDepth","getMaxHeaderDepth","depth","colIndex","headerInfo","getHeaderAtDepth","colSpan","children","child","applyAllMerges","mergeRange","String","childColSpan","applySmartMerges","applySmartMergesForHeader","headerColSpan","childColIndex","reduce","total","childDepth","max","validate","CoreErrorType","VALIDATION_ERROR","success","calculateDataColumnPositions","positions","collectLeafPositions","headerList","firstCol","key","contextSubHeaders","columnPositions","footerColPosition","excelRow","footerCell","styleName","getPredefinedStyle","themeStyle","getThemeStyle","numberFormat","numFmt","mergeTo","colPosition","childCell","jump","rowHeight","height","colWidth","getColumn","width","trim","note","dataValidation","allowBlank","formulae","operator","values","escaped","v","replace","join","formula1","toISOString","formula2","showErrorMessage","errorMessage","showInputMessage","inputMessage","prompt","cellAddress","address","format","rule","stopIfTrue","formula","addConditionalFormatting","ref","rules","headerRow","dataEndRow","column","to","lastRow","autoFilterConfig","columnCount","startColumn","endColumn","link","LINK","linkUrl","displayText","mask","hyperlink","contextRows","contextIndex","mainColPosition","mainCell","rowsNeeded","calculateRowSpan","mergeAs","fromKey","explicitRows","Number","spanRows","isFinite","nextRow","safeSpan","safeMerge","headerStr","noMerge","startsWith","childRowPointer","startColLetter","_merges","e","convertColor","r","padStart","g","toUpperCase","hex","split","c","span","current","childSpan","findCellInRow","found","converted","family","backgroundColor","foregroundColor","bgColor","alignment","horizontal","includes","vertical","wrapText","Boolean","shrinkToFit","indent","textRotation","readingOrder","Object","columnNumber","result","fromCharCode","floor","columnLetter","charCodeAt","imageBuffer","position","match","parseInt","buffer","base64Data","binaryString","atob","bytes","Uint8Array","ArrayBuffer","imagePosition","tl","ext","scaleX","scaleY","extension","description","warn","outlineLevel","excelCol","totalsRow","totalRow","showFirstColumn","showLastColumn","showRowStripes","showColumnStripes","filterButton","totalsRowFunction","totalsRowFormula","printHeadersFooters","headerFooter","center","oddHeader","oddFooter","printRepeat","rowsStr","printTitlesRow","colsStr","printTitlesColumn","rowNum","sourceSheet","getWorksheet","pivotConfig","sourceRange","fields","stat","filters","substring","x","views","freezePanes","freezeView","state","xSplit","ySplit","topLeftCell","activeCell","splitPanes","splitConfig","splitView","activePane","paneMap","topLeft","topRight","bottomLeft","bottomRight","viewConfig","view","zoomScale","zoomScaleNormal","showGridLines","showRowColHeaders","showRuler","rightToLeft","zoom","section","rowIndex","autoApplySectionStyles","targetTable","imageConfig","opacity","centerRow","rowCount","centerCol","fontSize","fontColor","model","connectionString","commandText","refresh","credentials","username","integratedSecurity","BuilderEventType","ExcelBuilder","worksheets","currentWorksheet","isBuilding","stats","eventEmitter","cellStyles","enableValidation","enableEvents","enablePerformanceMonitoring","maxWorksheets","maxRowsPerWorksheet","maxColumnsPerWorksheet","memoryLimit","initializeStats","worksheetConfig","defaultColWidth","defaultWorksheetConfig","worksheet","emitEvent","WORKSHEET_ADDED","worksheetName","removeWorksheet","WORKSHEET_REMOVED","setCurrentWorksheet","setMetadata","metadata","BUILD_ERROR","startTime","now","BUILD_STARTED","ExcelJS","Workbook","creator","author","lastModifiedBy","created","modified","title","subject","keywords","category","company","hyperlinkBase","applyTheme","entries","addStyleToWorkbook","xlsx","writeBuffer","compression","compressionLevel","endTime","buildTime","fileSize","byteLength","BUILD_COMPLETED","err","errorResult","message","originalError","generateAndDownload","fileName","buildResult","DOWNLOAD_STARTED","blob","Blob","data","mimeType","saveAs","DOWNLOAD_COMPLETED","FILE_ERROR","DOWNLOAD_ERROR","saveToFile","filePath","window","nodeModules","fsReq","require","pathReq","bufferReq","fsMod","Promise","resolve","then","pathMod","bufferMod","fs","default","path","Buffer","createDir","dir","dirname","mkdir","recursive","code","writeFile","encoding","saveToStream","writeStream","write","toBuffer","toBlob","errors","worksheetValidation","getStats","addCellStyle","getCellStyle","setTheme","getTheme","eventType","removeAllListeners","totalWorksheets","totalCells","memoryUsage","stylesUsed","formulasUsed","conditionalFormatsUsed","performance","headersTime","dataTime","stylesTime","writeTime","excelTheme","colors","dark1","convertColorToTheme","light1","dark2","light2","accent1","accent2","accent3","accent4","accent5","accent6","followedHyperlink","fonts","major","latin","eastAsian","complexScript","minor","OutputFormat","ExcelReader","defaultOptions","createErrorResult","errorType","details","processingTime","fromBuffer","mergedOptions","arrayBuffer","slice","byteOffset","load","outputFormat","WORKSHEET","DETAILED","convertToDetailedFormat","FLAT","convertToFlatFormat","convertWorkbookToJson","mapper","mapperError","unified","detailed","flat","fromBlob","fromFile","file","fromNodeBuffer","fromBlobUnified","fromPath","readFile","isBrowserError","fromBufferUnified","fromFileUnified","fromNodeBufferUnified","fromPathUnified","includeEmptyRows","useFirstRowAsHeaders","sheetName","includeFormatting","includeFormulas","datesAsISO","sheetsToProcess","sheet","sheets","sheetOptions","convertSheetToJson","workbookResult","totalSheets","some","val","maxColumns","actualStartRow","actualEndRow","number","actualStartCol","actualEndCol","lastColumn","cells","rowData","hasData","jsonCell","convertCellToJson","indexOf","jsonRow","rowNumber","totalRows","totalColumns","ValueType","Null","dateValue","Formula","Hyperlink","hyperlinkValue","formattedValue","texts","t","cellValue","getCellValue","cellText","detailedCell","flatOptions","convertSheetToFlat","flatData","rowValues","rowObject","StyleBuilder","CENTER","MIDDLE","create","fontName","fontStyle","fontBold","fontItalic","fontUnderline","borderTop","borderLeft","borderBottom","borderRight","horizontalAlign","verticalAlign","centerAlign","leftAlign","LEFT","rightAlign","RIGHT","striped","conditionalFormat","CellEventType","WorksheetEventType","StylePreset"],"mappings":"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"}