Artykuł techniczny

Obiekty Camera Excela z Delphi: żywe migawki

HotXLS tworzy obiekty Camera na arkuszach XLSX z Delphi za pomocą AddCamera. Obiekt Camera to obraz na stałe połączony z zakresem komórek: Excel renderuje go ponownie na podstawie zakresu źródłowego za każdym razem, gdy skoroszyt się otwiera albo źródło się zmienia, dzięki czemu pulpit nawigacyjny może pokazywać żywy widok tabeli znajdującej się na innym arkuszu, w dowolnym rozmiarze, a nawet obróconej, jeśli chcesz

Ta funkcja istnieje w Excelu jako narzędzie Camera — przycisk, którego większość użytkowników nigdy nie widziała, ponieważ domyślnie nie ma go na wstążce. Rozwiązuje prawdziwy problem pulpitów nawigacyjnych lepiej niż alternatywy: skopiowany zakres się dezaktualizuje, wykres nie może pokazać dowolnej treści komórek, a połączony obraz wklejony ręcznie nie może zostać wygenerowany przez kod. Obiekt Camera to jedyna konstrukcja, która jest jednocześnie żywa i dowolna

Obiekt Camera HotXLS utworzony z Delphi: żywy obraz Data!$B$2:$D$4 umieszczony na arkuszu pulpitu nawigacyjnego, który Excel renderuje ponownie przy otwarciu i przy każdej edycji źródła
Obiekt Camera pozostaje na stałe połączony ze swoim zakresem źródłowym, więc Excel renderuje obraz ponownie przy otwarciu i przy każdej edycji, w dowolnym rozmiarze i z zakresu na innym arkuszu

Gdzie to jest udokumentowane i dlaczego ma to znaczenie?

Główna specyfikacja arkusza kalkulacyjnego nie opisuje obiektów Camera; są one traktowane jako szczegół implementacyjny. Autorytatywny opis znajduje się w dokumentacji znaczników rysunków, pod nagłówkiem Camera Tool, a znajomość tego faktu oszczędza popołudnie spędzone na przeszukiwaniu niewłaściwego dokumentu

Strukturalnie obiekt Camera to zwykły element obrazu, którego niewizualne właściwości obrazu niosą listę rozszerzeń. Rozszerzenie jest identyfikowane przez stały GUID, a wewnątrz niego element z przestrzeni nazw rysunków 2010 rejestruje dwie rzeczy: zakres źródłowy jako bezwzględne odwołanie w stylu A1, opcjonalnie kwalifikowane nazwą arkusza, oraz identyfikator kształtu. Wszystko inne w obrazie jest zwykłe

Anatomia XLSX obiektu Camera zapisanego przez HotXLS z Delphi: zwykły element obrazu, którego lista rozszerzeń niesie element z przestrzeni nazw rysunków 2010, rejestrujący bezwzględny zakres źródłowy i identyfikator kształtu
Strukturalnie obiekt Camera to zwykły obraz plus jeden element rozszerzenia z przestrzeni nazw rysunków 2010, rejestrujący bezwzględny zakres źródłowy w stylu A1 i identyfikator kształtu

Tworzenie obiektu Camera

Istnieją dwa przeciążenia, ponieważ wygodne są dwa sposoby nazywania zakresu. Forma tekstowa przyjmuje odwołanie dokładnie takie, jakie zostanie zapisane, co jest tym, czego potrzebujesz dla źródła z innego arkusza. Forma współrzędnych przyjmuje cztery współrzędne komórek na tym samym arkuszu i buduje za ciebie bezwzględne odwołanie:

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

    // Żywy widok Data!$B$2:$D$4, umieszczony nad B10:F20 na pulpicie nawigacyjnym
    Cam := Dashboard.AddCamera('Data!$B$2:$D$4', 10, 2, 20, 6);

    // Ramka umieszczenia domyślnie przyjmuje własne 64-pikselowe kolumny Excela i
    // 20-pikselowe wiersze; w razie potrzeby dostosuj potem narysowany rozmiar w 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;

Zwrócony obiekt to zwykły obiekt obrazu z jedną dodatkową właściwością, CameraRange, która jest niepusta dokładnie wtedy, gdy obraz jest obiektem Camera. W ten sam sposób wykrywasz obiekty Camera w skoroszycie, którego nie stworzyłeś: wylicz obrazy i sprawdź tę właściwość

Dlaczego obraz zastępczy nie musi być prawdziwy?

Każdy obraz w pakiecie XLSX potrzebuje części obrazu i obiekt Camera nie jest wyjątkiem. Ale Excel ignoruje ten obraz: przy wczytaniu renderuje ponownie połączony zakres i rysuje wynik. Osadzone bajty istnieją wyłącznie jako pamięć podręczna wyświetlania dla narzędzi, które nie implementują zachowania Camera

Ten fakt usuwa z implementacji cały podsystem. Nie ma potrzeby rasteryzowania zakresu źródłowego, nie ma potrzeby silnika renderującego do wygenerowania migawki i nie ma ryzyka, że obraz z pamięci podręcznej będzie niezgodny z żywym obrazem w Excelu. HotXLS zapisuje minimalny zastępczy metaplik — rekord nagłówka i rekord końca pliku, łącznie 108 bajtów — co utrzymuje strukturalną kompletność pakietu i nic nie kosztuje

Jedna konsekwencja, z którą trzeba się liczyć: przeglądarka renderująca XLSX bez implementacji obiektów Camera pokazuje zastępczy obraz, który jest pusty. Jeśli twoje skoroszyty są konsumowane przez takie narzędzie, obiekt Camera jest niewłaściwą konstrukcją, a właściwym rozwiązaniem jest wyrenderowany obraz zakresu

Zastępcza część obrazu obiektu Camera HotXLS: Excel renderuje ponownie połączony zakres przy wczytaniu i ignoruje 108-bajtowy metaplik, podczas gdy przeglądarki bez obsługi Camera pokazują pusty obraz
Excel ignoruje osadzone bajty i renderuje ponownie połączony zakres przy wczytaniu, więc HotXLS zapisuje tylko 108-bajtowy zastępczy metaplik, podczas gdy przeglądarka bez obsługi Camera pokazuje pusty obraz zastępczy

Konwersja jednostek, którą łatwo pomylić

Geometria rysunków w Open XML jest mierzona w jednostkach English Metric Units, gdzie jeden cal to 914 400 EMU, a jeden centymetr to 360 000. Nagłówki metaplików rejestrują jednak swoją ramkę w jednostkach 0,01 milimetra. Konwersja między nimi to dzielenie przez 360

Warto to nazwać wprost, ponieważ błąd jest cichy. Konwersja przez piksele przy 96 DPI zamiast tego — mnożenie przez 2540 i dzielenie przez 9525 — daje wartość 96 razy za dużą, a nic tego nie odrzuca: pakiet jest ważny, obraz jest poprawnie umieszczony przez kotwicę, a bezsensowna jest tylko zadeklarowana ramka metapliku. Model EMU i jego zachowanie przy zaokrąglaniu opisano w geometrii obrazów, jednostkach EMU i skalowaniu

Zapis i odczyt skoroszytu, który już ma obiekty Camera

Otwarcie i zapisanie skoroszytu zachowuje obiekty Camera, wraz z elementem rozszerzenia i jego odwołaniem do zakresu. Ma to większe znaczenie niż ich tworzenie: większość skoroszytów z obiektami Camera powstała w Excelu, stworzona przez analityka, a biblioteka, która po cichu zamienia je przy zapisie w zwykłe obrazy, zniszczyła żywe zachowanie, na którym analityk polegał

// Sprawdź, które obrazy są obiektami Camera i na co wskazują
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]));

Gdy generujesz pulpity nawigacyjne programowo, ten audyt jest jednocześnie testem regresji: po cyklu zapisu i ponownego otwarcia ta sama liczba obiektów Camera musi wskazywać na te same zakresy. Ogólną obsługę obrazów i rysunków, wraz z modelem kotwiczenia, który je pozycjonuje, opisano w wykresach, obrazach i rysunkach

Kiedy obiekt Camera przewyższa alternatywy

Użyj obiektu Camera, gdy ta sama żywa tabela musi pojawić się na kilku arkuszach w różnych rozmiarach, gdy układ wydruku wymaga fragmentu jednego arkusza złożonego obok fragmentów innych, albo gdy blok podsumowania ma podążać za edycjami dokonanymi gdzie indziej bez formuły łączącej każdą komórkę z osobna

Preferuj zwykłe formuły, gdy celem jest garstka komórek, ponieważ formuła między arkuszami jest prostsza i rozumie ją każde narzędzie. Preferuj wykres, gdy dane są naprawdę serią, a nie sformatowanym blokiem. A preferuj wyrenderowany obraz, gdy skoroszyt będzie konsumowany przez narzędzia inne niż Excel, albo gdy migawka nie może zmienić się po dostarczeniu — zarchiwizowany raport nie powinien być żywy

Jedna uwaga praktyczna dotycząca układu: obiekt Camera pokazuje zakres źródłowy dokładnie tak, jak jest sformatowany, wraz ze scalonymi komórkami, formatowaniem warunkowym i szerokościami kolumn. Uzyskanie schludnie wyglądającego bloku pulpitu nawigacyjnego zaczyna się więc od sformatowania zakresu źródłowego tak, jakby był gotowym wynikiem, co jest tą samą dyscypliną opisaną w scalonych komórkach i układzie szablonów raportów

Obiekty Camera, rysunki i stojący za nimi zapisujący pakiety XLSX są dostarczane w jednej bibliotece dla Delphi i C++Builder; pełną listę funkcji znajdziesz na stronie komponentu arkusza kalkulacyjnego HotXLS dla Delphi