Technisch artikel

Excel Camera Objects vanuit Delphi: live momentopnamen

HotXLS maakt Excel Camera Objects aan op XLSX-werkbladen vanuit Delphi via AddCamera. Een camera object is een afbeelding die permanent gekoppeld is aan een celbereik: Excel rendert deze telkens opnieuw vanuit het bronbereik wanneer de werkmap wordt geopend of de bron verandert, zodat een dashboard een live weergave kan tonen van een tabel die op een ander blad staat, op elke gewenste grootte, en desgewenst gedraaid

De functie bestaat in Excel als het Camera-hulpmiddel, een knop die de meeste gebruikers nooit hebben gezien omdat hij standaard niet op het lint staat. Het lost een echt dashboardprobleem beter op dan de alternatieven: een gekopieerd bereik veroudert, een grafiek kan geen willekeurige celinhoud tonen, en een gekoppelde afbeelding die handmatig is geplakt, kan niet door code worden gegenereerd. Een camera object is de enige constructie die zowel live als willekeurig is

HotXLS camera object aangemaakt vanuit Delphi: een live afbeelding van Data!$B$2:$D$4 geplaatst op een dashboardblad, die Excel bij het openen en bij elke bronwijziging opnieuw rendert
Een camera object blijft permanent gekoppeld aan zijn bronbereik, zodat Excel de afbeelding bij het openen en bij elke bewerking opnieuw rendert, op elke grootte en vanuit een bereik op een ander blad

Waar is dit gedocumenteerd, en waarom maakt dat uit?

De hoofdspecificatie voor spreadsheets beschrijft camera objects niet; ze worden behandeld als een implementatiedetail. De gezaghebbende beschrijving staat in de documentatie over drawing-markup, onder de kop Camera Tool, en dat weten bespaart u een middag zoeken in het verkeerde document

Structureel is een camera object een gewoon afbeeldingselement waarvan de niet-visuele afbeeldingseigenschappen een extensielijst dragen. De extensie wordt geïdentificeerd door een vaste GUID, en daarbinnen legt een element uit de 2010-drawing-namespace twee dingen vast: het bronbereik als een absolute verwijzing in A1-stijl, optioneel met bladkwalificatie, en een vormidentificatie. Al het andere aan de afbeelding is normaal

XLSX-anatomie van een camera object geschreven door HotXLS vanuit Delphi: een gewoon afbeeldingselement waarvan de extensielijst een element uit de 2010-drawing-namespace draagt dat het absolute bronbereik en een vormidentificatie vastlegt
Structureel is een camera een gewone afbeelding plus één extensie-element uit de 2010-drawing-namespace, dat het absolute bronbereik in A1-stijl en een vormidentificatie vastlegt

Er één aanmaken

Er bestaan twee overloads omdat twee manieren om een bereik te benoemen handig zijn. De tekstvorm neemt de verwijzing precies zoals die wordt opgeslagen, wat wenselijk is voor een bron op een ander blad. De coördinatenvorm neemt vier celcoördinaten op hetzelfde blad en bouwt de absolute verwijzing voor u op:

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

    // Live weergave van Data!$B$2:$D$4, geplaatst over B10:F20 op het dashboard
    Cam := Dashboard.AddCamera('Data!$B$2:$D$4', 10, 2, 20, 6);

    // Het plaatsingsvak valt standaard terug op Excels eigen kolommen van 64 px en
    // rijen van 20 px; pas de getekende grootte achteraf zo nodig aan in EMU
    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;

Het geretourneerde object is een normaal afbeeldingsobject met één extra eigenschap, CameraRange, die precies niet-leeg is wanneer de afbeelding een camera is. Zo detecteert u ook camera's in een werkmap die u niet zelf hebt gemaakt: doorloop de afbeeldingen en controleer de eigenschap

Waarom hoeft de placeholder-afbeelding niet echt te zijn?

Elke afbeelding in een XLSX-pakket heeft een image part nodig, en een camera object vormt daarop geen uitzondering. Maar Excel negeert die afbeelding: bij het laden rendert het het gekoppelde bereik opnieuw en tekent het resultaat. De ingesloten bytes bestaan puur als weergavecache voor tools die het cameragedrag niet implementeren

Dat gegeven verwijdert een heel subsysteem uit de implementatie. Er is geen noodzaak om het bronbereik te rasteriseren, geen renderengine nodig om de momentopname te produceren, en geen risico dat de gecachete afbeelding afwijkt van de live afbeelding in Excel. HotXLS schrijft een minimale placeholder-metafile — één headerrecord en één end-of-file-record, in totaal 108 bytes — die het pakket structureel compleet houdt en niets kost

Eén gevolg om rekening mee te houden: een viewer die XLSX rendert zonder camera objects te implementeren toont de placeholder, die leeg is. Als uw werkmappen door zo'n tool worden verwerkt, is een camera object de verkeerde constructie en is een gerenderde afbeelding van het bereik de juiste

Placeholder image part van een HotXLS camera object: Excel rendert het gekoppelde bereik bij het laden opnieuw en negeert de 108-byte metafile, terwijl viewers zonder camera-ondersteuning een lege afbeelding tonen
Excel negeert de ingesloten bytes en rendert het gekoppelde bereik bij het laden opnieuw, dus schrijft HotXLS alleen een 108-byte placeholder-metafile, terwijl een viewer zonder camera-ondersteuning de lege placeholder toont

De eenhedenconversie die gemakkelijk fout gaat

Tekengeometrie in Open XML wordt gemeten in English Metric Units, waarbij één inch 914.400 EMU is en één centimeter 360.000. Metafile-headers leggen hun frame echter vast in eenheden van 0,01 millimeter. De conversie daartussen is een deling door 360

Het is de moeite waard dit te benoemen omdat de fout stilzwijgend optreedt. In plaats daarvan converteren via pixels op 96 DPI — vermenigvuldigen met 2540 en delen door 9525 — levert een waarde op die 96 keer te groot is, en niets wijst dit af: het pakket is geldig, de afbeelding wordt correct geplaatst door het anker, en alleen het gedeclareerde frame van de metafile is onzin. Het EMU-model en zijn afrondingsgedrag worden behandeld in beeldgeometrie, EMU-eenheden en schalen

Een werkmap die al camera's bevat openen en opnieuw opslaan

Het openen en opslaan van een werkmap behoudt camera objects, inclusief het extensie-element en de bereikverwijzing. Dit is belangrijker dan ze aanmaken: de meeste werkmappen met camera objects zijn in Excel gemaakt door een analist, en een library die ze bij het opslaan stilzwijgend omzet in gewone afbeeldingen, heeft het live gedrag vernietigd waarop de analist vertrouwde

// Audit welke afbeeldingen camera's zijn en waar ze naar wijzen
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]));

Wanneer u dashboards programmatisch genereert, is de audit ook de regressietest: na een opslaan-en-heropenen-cyclus moeten evenveel camera's naar dezelfde bereiken wijzen. Algemene afhandeling van afbeeldingen en tekeningen, inclusief het ankermodel dat ze positioneert, wordt behandeld in grafieken, afbeeldingen en tekeningen

Wanneer een camera de alternatieven verslaat

Gebruik een camera object wanneer dezelfde live tabel op meerdere bladen in verschillende groottes moet verschijnen, wanneer een afdruklay-out een regio van één blad naast regio's van andere bladen moet samenstellen, of wanneer een samenvattingsblok wijzigingen elders moet volgen zonder dat elke cel afzonderlijk door een formule wordt gekoppeld

Geef de voorkeur aan gewone formules wanneer het doel een handvol cellen is, want een formule tussen bladen is eenvoudiger en elke tool begrijpt hem. Geef de voorkeur aan een grafiek wanneer de data werkelijk een reeks is in plaats van een opgemaakt blok. En geef de voorkeur aan een gerenderde afbeelding wanneer de werkmap door andere tools dan Excel wordt verwerkt, of wanneer de momentopname na levering niet mag veranderen — een gearchiveerd rapport hoort niet live te zijn

Eén lay-outopmerking uit de praktijk: een camera toont het bronbereik exact zoals opgemaakt, inclusief samengevoegde cellen, voorwaardelijke opmaak en kolombreedtes. Een verzorgd uitziend dashboardblok krijgen begint dus met het bronbereik opmaken alsof het de uiteindelijke output is, wat dezelfde discipline is die wordt beschreven in samengevoegde cellen en lay-out van rapportsjablonen

Camera objects, tekeningen en de XLSX-pakketwriter erachter worden geleverd in één library voor Delphi en C++Builder; de volledige functielijst staat op de HotXLS Delphi spreadsheetcomponent-pagina