Artículo técnico

Objetos cámara de Excel desde Delphi: instantáneas en vivo

HotXLS crea objetos cámara de Excel en hojas XLSX desde Delphi mediante AddCamera. Un objeto cámara es una imagen enlazada de forma permanente a un rango de celdas: Excel la vuelve a renderizar a partir del rango de origen cada vez que se abre el libro o cambia el origen, de modo que un panel de control puede mostrar una vista en vivo de una tabla que vive en otra hoja, a cualquier tamaño, e incluso rotada si lo deseas

La función existe en Excel como la herramienta Cámara, un botón que la mayoría de los usuarios nunca ha visto porque no está en la cinta de opciones por defecto. Resuelve un problema real de paneles de control mejor que las alternativas: un rango copiado se queda obsoleto, un gráfico no puede mostrar contenido de celda arbitrario, y una imagen enlazada pegada a mano no se puede generar por código. Un objeto cámara es la única construcción que es a la vez en vivo y arbitraria

Objeto cámara de HotXLS creado desde Delphi: una imagen en vivo de Data!$B$2:$D$4 colocada en una hoja de panel de control que Excel vuelve a renderizar al abrir y en cada edición del origen
Un objeto cámara permanece enlazado de forma permanente a su rango de origen, de modo que Excel vuelve a renderizar la imagen al abrir y en cada edición, a cualquier tamaño y desde un rango situado en otra hoja

¿Dónde está documentado esto, y por qué importa?

La especificación principal de hoja de cálculo no describe los objetos cámara; se tratan como un detalle de implementación. La descripción autorizada vive en la documentación de marcado de dibujo, bajo el epígrafe de la herramienta Cámara, y saberlo ahorra una tarde entera de buscar en el documento equivocado

Estructuralmente, un objeto cámara es un elemento de imagen ordinario cuyas propiedades no visuales llevan una lista de extensión. La extensión se identifica mediante un GUID fijo, y dentro de ella un elemento del espacio de nombres de dibujo de 2010 registra dos cosas: el rango de origen como una referencia absoluta al estilo A1, opcionalmente calificada por hoja, y un identificador de forma. Todo lo demás sobre la imagen es normal

Anatomía XLSX de un objeto cámara escrito por HotXLS desde Delphi: un elemento de imagen ordinario cuya lista de extensión lleva un elemento del espacio de nombres de dibujo de 2010 que registra el rango de origen absoluto y un identificador de forma
Estructuralmente una cámara es una imagen ordinaria más un elemento de extensión del espacio de nombres de dibujo de 2010, que registra el rango de origen absoluto en estilo A1 y un identificador de forma

Crear uno

Existen dos sobrecargas porque hay dos formas convenientes de nombrar un rango. La forma textual toma la referencia exactamente como se almacenará, que es lo que quieres para un origen entre hojas. La forma de coordenadas toma cuatro coordenadas de celda en la misma hoja y construye la referencia absoluta por ti:

uses
  lxHandleX;

var
  Book: TXLSXWorkbook;
  Dashboard: TXLSXWorksheet;
  Cam: TXLSXImage;
begin
  Book := TXLSXWorkbook.Create;
  try
    if Book.Open('reporting.xlsx') <> 1 then
      Exit;
    Dashboard := Book.Sheets[0];

    // Vista en vivo de Data!$B$2:$D$4, colocada sobre B10:F20 en el panel
    Cam := Dashboard.AddCamera('Data!$B$2:$D$4', 10, 2, 20, 6);

    // El cuadro de colocación usa por defecto las columnas de 64 px y
    // filas de 20 px propias de Excel; ajusta después el tamaño dibujado
    // en EMU si es necesario
    Cam.WidthEMU := Round(12.5 * 914400 / 2.54);   // 12,5 cm
    Cam.HeightEMU := Round(6.0 * 914400 / 2.54);

    Book.SaveAs('reporting-dashboard.xlsx');
  finally
    Book.Free;
  end;
end;

El objeto devuelto es un objeto de imagen normal con una propiedad adicional, CameraRange, que es no vacía exactamente cuando la imagen es una cámara. Así es también como detectas cámaras en un libro que no creaste tú: enumera las imágenes y comprueba la propiedad

¿Por qué no necesita ser real la imagen de reserva?

Cada imagen dentro de un paquete XLSX necesita una parte de imagen, y un objeto cámara no es una excepción. Pero Excel ignora esa imagen: al cargar, vuelve a renderizar el rango enlazado y pinta el resultado. Los bytes incrustados existen únicamente como una caché de visualización para las herramientas que no implementan el comportamiento de cámara

Ese hecho elimina todo un subsistema de la implementación. No hace falta rasterizar el rango de origen, no hace falta un motor de renderizado para producir la instantánea, y no hay riesgo de que la imagen en caché no coincida con la imagen en vivo dentro de Excel. HotXLS escribe un metarchivo de reserva mínimo — un registro de cabecera y un registro de fin de archivo, 108 bytes en total —, lo cual mantiene el paquete estructuralmente completo y no cuesta nada

Una consecuencia a tener en cuenta: un visor que renderiza XLSX sin implementar objetos cámara muestra la imagen de reserva, que está en blanco. Si tus libros los consume una herramienta así, un objeto cámara es la construcción equivocada y una imagen renderizada del rango es la correcta

Parte de imagen de reserva de un objeto cámara de HotXLS: Excel vuelve a renderizar el rango enlazado al cargar e ignora el metarchivo de 108 bytes, mientras que los visores sin compatibilidad con cámaras muestran una imagen en blanco
Excel ignora los bytes incrustados y vuelve a renderizar el rango enlazado al cargar, de modo que HotXLS solo escribe un metarchivo de reserva de 108 bytes, mientras que un visor sin compatibilidad con cámaras muestra la imagen de reserva en blanco

La conversión de unidades que es fácil hacer mal

La geometría de dibujo en Open XML se mide en unidades métricas inglesas (EMU), donde una pulgada son 914.400 EMU y un centímetro son 360.000. Las cabeceras de metarchivo, sin embargo, registran su marco en unidades de 0,01 milímetros. La conversión entre ambas es una división entre 360

Vale la pena nombrar esto porque el error es silencioso. Convertir en su lugar a través de píxeles a 96 DPI — multiplicando por 2540 y dividiendo entre 9525 — produce un valor 96 veces demasiado grande, y nada lo rechaza: el paquete es válido, la imagen se coloca correctamente por el ancla, y solo el marco declarado del metarchivo carece de sentido. El modelo EMU y su comportamiento de redondeo se tratan en geometría de imagen, unidades EMU y escalado

Ciclo de apertura y guardado de un libro que ya tiene cámaras

Abrir y guardar un libro preserva los objetos cámara, incluido el elemento de extensión y su referencia de rango. Esto importa más que crearlos: la mayoría de los libros con objetos cámara los hizo un analista en Excel, y una biblioteca que los convierte en silencio en imágenes ordinarias al guardar ha destruido el comportamiento en vivo con el que contaba ese analista

// Audita qué imágenes son cámaras y hacia dónde apuntan
for I := 0 to Sheet.Images.Count - 1 do
  if Sheet.Images[I].CameraRange <> '' then
    Writeln(Format('camera %d -> %s',
      [I, Sheet.Images[I].CameraRange]));

Cuando generas paneles de control mediante código, la auditoría también es la prueba de regresión: tras un ciclo de guardar y volver a abrir, el mismo número de cámaras debe apuntar a los mismos rangos. El manejo general de imágenes y dibujos, incluido el modelo de anclaje que las posiciona, se trata en gráficos, imágenes y dibujos

Cuándo una cámara supera a las alternativas

Usa un objeto cámara cuando la misma tabla en vivo deba aparecer en varias hojas a distintos tamaños, cuando un diseño de impresión necesite una región de una hoja compuesta junto a regiones de otras, o cuando un bloque de resumen deba seguir las ediciones hechas en otro lugar sin una fórmula que enlace cada celda individualmente

Prefiere las fórmulas ordinarias cuando el objetivo sea un puñado de celdas, porque una fórmula entre hojas es más simple y cualquier herramienta la entiende. Prefiere un gráfico cuando los datos son genuinamente una serie y no un bloque formateado. Y prefiere una imagen renderizada cuando el libro lo vayan a consumir herramientas distintas de Excel, o cuando la instantánea no deba cambiar después de la entrega — un informe archivado no debería estar vivo

Una nota de maquetación tomada de la práctica: una cámara muestra el rango de origen exactamente como está formateado, incluidas las celdas combinadas, los formatos condicionales y los anchos de columna. Conseguir un bloque de panel de control con buen aspecto empieza, por tanto, formateando el rango de origen como si ya fuera la salida final, la misma disciplina descrita en celdas combinadas y maquetación de plantillas de informe

Los objetos cámara, los dibujos y el escritor del paquete XLSX que hay detrás se distribuyen en una única biblioteca para Delphi y C++Builder; la lista completa de funciones está en la página del componente de hoja de cálculo HotXLS Delphi