Artículo técnico

Fórmulas entre libros de Excel en vivo, en Delphi con HotXLS

HotXLS puede evaluar una fórmula como =[Rates.xlsx]FX!B4*C10 contra otro libro que esté abierto en memoria, y no contra un valor obsoleto de una caché. Registras el segundo libro por nombre con RegisterExternalWorkbook, y cada recálculo lee las celdas referenciadas directamente de ese objeto. Si lo desregistras, la evaluación recurre a la caché de enlaces externos que el archivo ya lleva incorporada

Esto cierra una brecha concreta y frustrante. Los libros de Excel se referencian entre sí constantemente: una tabla de tipos de cambio, un plan de cuentas, una lista de precios mantenida por otro equipo. Cuando un archivo así lo abre una biblioteca en lugar de Excel, esas referencias normalmente se resuelven con los valores que quedaron en caché la última vez que Excel recalculó, que pueden tener meses de antigüedad, y ninguna cantidad de recálculos lo arregla porque los datos sencillamente no están ahí

Rutas de resolución de una fórmula entre libros de HotXLS en Delphi: un libro registrado mediante RegisterExternalWorkbook suministra celdas actualizadas al recalcular, un libro no registrado recurre a la caché de enlaces externos, y sin caché la celda conserva su último valor calculado
El registro lee las celdas del objeto vivo, el respaldo de caché hace seguro desregistrar, y una referencia irresoluble deja intacto el último valor válido

¿Qué aspecto tiene una referencia entre libros dentro del archivo?

Una referencia externa no se almacena como el texto que ves en la barra de fórmulas. El libro mantiene una tabla de libros de apoyo, cada token de fórmula apunta a un índice dentro de esa tabla, y una parte separada de valores en caché guarda el último resultado conocido de cada celda referenciada. Por eso un archivo abierto sin sus acompañantes sigue mostrando números

Analizar la forma textual tiene sus propios matices. El analizador léxico trata un nombre de libro entre corchetes como parte de un único identificador, de modo que [Book.xlsx]Sheet!A1 se convierte en un solo token en lugar de un corchete sin cerrar seguido de una referencia de hoja. Los nombres se normalizan luego para la búsqueda: las comillas, los prefijos de ruta, la extensión del archivo y la forma de índice numérico se reducen todos a un nombre base en mayúsculas, de modo que 'C:\Rates\[Rates.xlsx]FX'!B4 y [rates.xlsx]FX!B4 resuelven al mismo libro registrado

Registrar un libro y recalcular

El registro se hace por nombre, y el nombre es el que aparece en las fórmulas del libro que hace la referencia:

uses
  lxHandleX;

var
  Main, Rates: TXLSXWorkbook;
begin
  Main := TXLSXWorkbook.Create;
  Rates := TXLSXWorkbook.Create;
  try
    if (Main.Open('valuation.xlsx') <> 1) or
       (Rates.Open('rates.xlsx') <> 1) then
      Exit;

    // Las fórmulas de valuation.xlsx que dicen [Rates.xlsx]... ahora leen
    // del objeto vivo en lugar de los valores externos en caché
    Main.RegisterExternalWorkbook('Rates.xlsx', Rates);
    Main.Recalculate;

    Writeln(VarToStr(Main.Sheets[0].Cells[10, 3].Value));

    // Cambia el origen y recalcula de nuevo: el nuevo valor se propaga
    Rates.Sheets[0].Cells[4, 2].Value := 1.0842;
    Main.Recalculate;
    Writeln(VarToStr(Main.Sheets[0].Cells[10, 3].Value));
  finally
    Main.UnregisterExternalWorkbook('Rates.xlsx');
    Rates.Free;
    Main.Free;
  end;
end;

El registro mantiene una referencia débil. HotXLS no toma posesión del libro registrado y no lo liberará, lo que significa que el ciclo de vida es responsabilidad tuya y el orden importa: desregístralo antes de liberar el libro de origen, o como mínimo no recalcules después de liberarlo

¿Qué ocurre cuando un libro no está registrado?

La evaluación recurre a la caché de enlaces externos almacenada en el archivo, que es exactamente el comportamiento de un libro abierto sin sus acompañantes. Ese respaldo es la razón por la que desregistrar es seguro y no destructivo

El comportamiento tras la desregistración merece precisarse, porque sorprende a la gente. Cuando una referencia no puede resolverse ni desde un libro registrado ni desde la caché, la evaluación produce un error y ese error no se escribe de vuelta en la celda. La celda conserva su último valor calculado. Vuelve a registrar el origen y recalcula, y el valor se actualiza de nuevo

Esta regla de conservar en caso de fallo es deliberada. La alternativa, escribir un valor de error en cada celda dependiente en cuanto un origen deja de estar disponible, convertiría una tabla de tipos temporalmente ausente en un libro lleno de marcadores de error que un recálculo posterior exitoso tendría que reparar. Conservar el último valor válido significa que un pipeline interrumpido deja un documento que aún se lee con sentido

La propagación de «sucio» se detiene en la frontera del libro

Editar una celda en el origen registrado no marca como sucias las celdas dependientes del libro principal. El recálculo incremental rastrea dependencias dentro de un mismo libro; no vigila a través de la frontera. Excel se comporta igual, razón por la cual sus referencias externas se actualizan al abrir o ante una actualización explícita, y no de forma continua

La consecuencia práctica es que cambiar un valor de origen exige un recálculo explícito del libro que hace la referencia, como en el ejemplo anterior. Si tu aplicación edita ambos libros en un bucle, recalcula una vez al final en lugar de hacerlo después de cada edición; el motor incremental descrito en recálculo incremental y el grafo de dependencias hace entonces el mínimo trabajo dentro de cada libro

Tres escenarios en los que encaja esta función

La consolidación es el más obvio. Un libro principal referencia doce archivos mensuales; regístralos los doce, recalcula una vez, y lee las cifras consolidadas sin abrir Excel en ningún momento. El nombre de registro de cada uno debe coincidir con lo que realmente dicen las fórmulas del principal, algo que vale la pena verificar contra el texto de la fórmula en lugar de asumir que coincide con el nombre del archivo

El análisis de escenarios es el segundo. Registra un origen, escribe en él un conjunto de supuestos, recalcula el modelo dependiente, registra las salidas, y repite. Como el origen es un objeto vivo, no se escribe ningún archivo entre iteraciones, y cien escenarios cuestan cien recálculos en lugar de cien ciclos de guardar y volver a cargar

La validación previa a la entrega es el tercero y el menos evidente. Abre un libro, registra sus acompañantes, recalcula, y compara los resultados con los valores que el archivo ya llevaba. Una discrepancia significa que los valores en caché están obsoletos, lo cual es un defecto que vale la pena detectar antes de que un cliente reciba el archivo. Esa comparación es un complemento natural de la comparación de libros descrita en comparar dos libros de Excel

Tres escenarios de evaluación en vivo entre libros con HotXLS en Delphi: consolidación de doce archivos mensuales, análisis de escenarios que nunca escribe un archivo entre ejecuciones, y validación que compara los resultados recalculados con los valores en caché que lleva un archivo
La consolidación registra cada archivo mensual y recalcula una vez, los bucles de escenarios nunca tocan el disco, y la validación compara los resultados nuevos con la caché que un cliente habría recibido

Higiene de referencias antes de confiar en ellas

Ejecuta primero un pase de análisis de fórmulas. Reporta funciones ausentes, referencias externas y componentes de dependencia circular en un solo recorrido, lo que te dice exactamente qué nombres de libro espera un documento antes de que salgas a buscar los archivos:

var
  Issues: TArray<TXLSXFormulaIssue>;
  I: Integer;
begin
  Issues := Main.AnalyzeFormulaIssues;
  for I := 0 to High(Issues) do
    if Issues[I].Kind = xlsxFormulaIssueExternalReference then
      Writeln(Format('sheet %d R%dC%d needs [%s] (%s)',
        [Issues[I].Sheet, Issues[I].Row, Issues[I].Col,
         Issues[I].ExternalWorkbook, Issues[I].SourceFileName]));
end;

Otros dos hábitos ahorran tiempo. Mantén canónico el nombre de registro — regístralo con el nombre de archivo sencillo y deja que la normalización se encargue de las variantes con comillas y con prefijo de ruta que aparezcan en las fórmulas. Y trata un libro que referencia archivos que no puedes suministrar como un artefacto de solo lectura: recalcularlo conservará los valores en caché, pero cualquier edición que cambie una celda dependiente deja el documento en un estado donde algunos valores son actuales y otros históricos, sin nada en el archivo que diga cuáles son cuáles. Copiar fórmulas entre libros es una operación distinta con sus propias reglas de reenlace, tratada en copia entre libros y reenlace de fórmulas, y los nombres definidos añaden otra capa descrita en nombres definidos y fórmulas entre hojas

La evaluación en vivo entre libros, el recálculo incremental y el análisis de fórmulas se ejecutan sobre el mismo motor para Delphi y C++Builder; la lista completa de funciones está en la página del componente de hoja de cálculo HotXLS Delphi