Article technique

Objets Camera Excel depuis Delphi : instantanés en direct

HotXLS crée des objets Camera Excel sur des feuilles XLSX depuis Delphi via AddCamera. Un objet Camera est une image en permanence liée à une plage de cellules : Excel la réaffiche depuis la plage source à chaque ouverture du classeur ou changement de la source, si bien qu'un tableau de bord peut montrer une vue en direct d'un tableau qui vit sur une autre feuille, à n'importe quelle taille, et pivotée si vous le souhaitez

La fonctionnalité existe dans Excel sous forme de l'outil Appareil photo, un bouton que la plupart des utilisateurs n'ont jamais vu car il ne figure pas dans le ruban par défaut. Elle résout un vrai problème de tableau de bord mieux que les alternatives : une plage copiée devient obsolète, un graphique ne peut pas afficher un contenu de cellule arbitraire, et une image liée collée à la main ne peut pas être générée par du code. Un objet Camera est la seule construction à la fois vivante et arbitraire

Objet Camera HotXLS créé depuis Delphi : une image en direct de Data!$B$2:$D$4 placée sur une feuille de tableau de bord qu'Excel réaffiche à l'ouverture et à chaque édition de la source
Un objet Camera reste en permanence lié à sa plage source, si bien qu'Excel réaffiche l'image à l'ouverture et à chaque édition, à n'importe quelle taille et depuis une plage sur une autre feuille

Où cela est-il documenté, et pourquoi cela compte-t-il ?

La spécification principale des feuilles de calcul ne décrit pas les objets Camera ; ils sont traités comme un détail d'implémentation. La description faisant autorité se trouve dans la documentation du balisage de dessin, sous la rubrique Camera Tool, et le savoir permet d'économiser un après-midi de recherche dans le mauvais document

Structurellement, un objet Camera est un élément image ordinaire dont les propriétés d'image non visuelles portent une liste d'extension. L'extension est identifiée par un GUID fixe, et à l'intérieur, un élément de l'espace de noms de dessin 2010 enregistre deux choses : la plage source sous forme de référence absolue de style A1, éventuellement qualifiée par une feuille, et un identifiant de forme. Tout le reste concernant l'image est normal

Anatomie XLSX d'un objet Camera écrit par HotXLS depuis Delphi : un élément image ordinaire dont la liste d'extension porte un élément de l'espace de noms de dessin 2010 enregistrant la plage source absolue et un identifiant de forme
Structurellement, une Camera est une image ordinaire plus un élément d'extension de l'espace de noms de dessin 2010, enregistrant la plage source absolue de style A1 et un identifiant de forme

En créer un

Deux surcharges existent parce que deux façons de nommer une plage sont pratiques. La forme textuelle prend la référence exactement telle qu'elle sera stockée, ce qui est ce que vous voulez pour une source inter-feuilles. La forme par coordonnées prend quatre coordonnées de cellule sur la même feuille et construit la référence absolue pour vous :

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];

    // Vue en direct de Data!$B$2:$D$4, placée sur B10:F20 du tableau de bord
    Cam := Dashboard.AddCamera('Data!$B$2:$D$4', 10, 2, 20, 6);

    // La boîte de placement utilise par défaut les colonnes de 64 px et les
    // lignes de 20 px propres à Excel ; ajustez ensuite la taille dessinée en EMU si besoin
    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;

L'objet retourné est un objet image normal doté d'une propriété supplémentaire, CameraRange, non vide exactement quand l'image est une Camera. C'est aussi comme cela que vous détectez les Camera dans un classeur que vous n'avez pas créé : énumérez les images et vérifiez la propriété

Pourquoi l'image d'espace réservé n'a-t-elle pas besoin d'être réelle ?

Chaque image dans un package XLSX a besoin d'une partie image, et un objet Camera ne fait pas exception. Mais Excel ignore cette image : au chargement, il réaffiche la plage liée et peint le résultat. Les octets intégrés existent purement comme cache d'affichage pour les outils qui n'implémentent pas le comportement Camera

Ce fait supprime tout un sous-système de l'implémentation. Il n'y a nul besoin de rastériser la plage source, nul besoin d'un moteur de rendu pour produire l'instantané, et nul risque que l'image mise en cache diverge de l'image en direct dans Excel. HotXLS écrit un métafichier d'espace réservé minimal — un enregistrement d'en-tête et un enregistrement de fin de fichier, 108 octets au total — ce qui garde le package structurellement complet et ne coûte rien

Une conséquence à anticiper : un visualiseur qui affiche XLSX sans implémenter les objets Camera montre l'espace réservé, qui est vide. Si vos classeurs sont consommés par un tel outil, un objet Camera est la mauvaise construction, et une image rendue de la plage est la bonne

Partie image d'espace réservé d'un objet Camera HotXLS : Excel réaffiche la plage liée au chargement et ignore le métafichier de 108 octets, tandis que les visualiseurs sans prise en charge des Camera affichent une image vide
Excel ignore les octets intégrés et réaffiche la plage liée au chargement, si bien que HotXLS n'écrit qu'un métafichier d'espace réservé de 108 octets, tandis qu'un visualiseur sans prise en charge des Camera affiche l'espace réservé vide

La conversion d'unités facile à mal faire

La géométrie de dessin en Open XML se mesure en unités métriques anglaises (EMU), où un pouce vaut 914 400 EMU et un centimètre 360 000. Les en-têtes de métafichier, en revanche, enregistrent leur cadre en unités de 0,01 millimètre. La conversion entre les deux est une division par 360

Il vaut la peine de nommer cela car l'erreur est silencieuse. Convertir en passant par les pixels à 96 DPI à la place — multiplier par 2540 et diviser par 9525 — produit une valeur 96 fois trop grande, et rien ne la rejette : le package est valide, l'image est placée correctement par l'ancre, et seul le cadre déclaré du métafichier est absurde. Le modèle EMU et son comportement d'arrondi sont traités dans la géométrie d'image, les unités EMU et la mise à l'échelle

Aller-retour sur un classeur qui contient déjà des Camera

Ouvrir puis enregistrer un classeur préserve les objets Camera, y compris l'élément d'extension et sa référence de plage. Cela compte plus que d'en créer : la plupart des classeurs contenant des objets Camera ont été réalisés dans Excel par un analyste, et une bibliothèque qui les convertit silencieusement en images ordinaires à l'enregistrement a détruit le comportement en direct sur lequel comptait l'analyste

// Audite quelles images sont des Camera et vers quoi elles pointent
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]));

Quand vous générez des tableaux de bord par programmation, l'audit sert aussi de test de non-régression : après un cycle d'enregistrement puis de réouverture, le même nombre de Camera doit pointer vers les mêmes plages. La gestion générale des images et des dessins, y compris le modèle d'ancrage qui les positionne, est traitée dans graphiques, images et dessins

Quand une Camera surpasse les alternatives

Utilisez un objet Camera quand le même tableau en direct doit apparaître sur plusieurs feuilles à des tailles différentes, quand une mise en page d'impression a besoin d'une région d'une feuille composée aux côtés de régions d'autres feuilles, ou quand un bloc de synthèse doit suivre des éditions faites ailleurs sans qu'une formule ne relie individuellement chaque cellule

Préférez des formules ordinaires quand la cible est une poignée de cellules, car une formule inter-feuilles est plus simple et tout outil la comprend. Préférez un graphique quand les données constituent réellement une série plutôt qu'un bloc mis en forme. Et préférez une image rendue quand le classeur sera consommé par des outils autres qu'Excel, ou quand l'instantané ne doit pas changer après livraison — un rapport archivé ne devrait pas être vivant

Une remarque de mise en page tirée de la pratique : une Camera montre la plage source exactement telle qu'elle est mise en forme, y compris cellules fusionnées, formats conditionnels et largeurs de colonnes. Obtenir un bloc de tableau de bord au rendu propre commence donc par mettre en forme la plage source comme s'il s'agissait du résultat final, la même discipline que celle décrite dans les cellules fusionnées et la mise en page des modèles de rapport

Les objets Camera, les dessins et l'écrivain de package XLSX qui les sous-tend sont livrés dans une seule bibliothèque pour Delphi et C++Builder ; la liste complète des fonctionnalités se trouve sur la page du composant tableur HotXLS Delphi