Tehnički članak

Izvoz raspona ćelija Excela kao jedne slike s HotXLS-om

Ponekad isporučljivo nije dokument, nego slika tablice. Blok sažetka u e-poruci o stanju, prikazani KPI panel na nadzornoj ploči, sličica uz rezultat pretraživanja: svi žele ćelije i nijedan ne želi papir. TXLSCellImageExporter u HotXLS-u uzima klasični ili XLSX pravokutnik ćelija i proizvodi jedan kompaktan PNG ili JPEG bez veličine stranice, bez margina, bez zaglavlja ili podnožja, bez naslova ispisa i bez prijeloma stranica. Razlučivost, mjerilo, format i JPEG kvaliteta konfigurabilni su, objekti, mrežne linije i obrubi ćelija imaju neovisne prekidače, pozadina može biti boja ili prozirna, i zapisivanje datoteke prolazi kroz atomsku zamjenu u istoj mapi koja ostavlja postojeću metu netaknutom ako bilo što padne

Razlog da ovo treba vlastiti izvoznik umjesto zastavice na putu ispisa jest to što podjela na stranice nije neobavezni sloj koji možete isključiti. To je stvar radi koje cjevovod stranica postoji

Zašto ne prikazati raspon kroz cjevovod ispisa?

Zato što cjevovod ispisa umeće stranicu između vas i ćelija. Veličina papira odlučuje koliko stane, margine guraju sadržaj prema unutra, zaglavlja i podnožja zauzimaju pojaseve koje niste tražili, naslovi ispisa ponavljaju retke koje već imate, a prijelomi stranica rastavljaju raspon. Blok sažetka koji slučajno zapne preko prijeloma izlazi kao dvije slike s važnim retkom presječenim na pola. Možete to sve nadoknaditi postavljanjem prilagođene veličine papira koja točno odgovara rasponu, i ljudi to čine, ali to znači ponovno računanje geometrije papira svaki put kad se raspon promijeni, i i dalje ostavlja logiku pojasa zaglavlja i naslova ispisa na putu

Izvoznik ćelija izmjeri pravokutnik, dodijeli bitmapu točno te veličine, nacrta ćelije u nju i kodira. Nema stranice, pa nema ničega za konfigurirati van. Za slučajeve u kojima ipak želite papir, put izvoza PDF-a ispravan je alat i pokriven je u članku o PDF izvozu radnog lista

TXLSCellImageExporter mjeri, crta i kodira jednu sliku po rasponu ćelija dok cjevovod ispisa rastavlja raspon na prijelomima stranica
Cjevovod stranica umeće geometriju papira između vas i ćelija; izvoznik ćelija nema stranicu nigdje na putu

Izmjerite prije prikazivanja

Measure vraća dimenzije u pikselima koje bi trenutne postavke proizvele bez kodiranja bilo čega. To je važno iz dva razloga. HTML ili predložak e-pošte obično treba dimenzije slike prije nego slika postoji, tako da može rezervirati okvir i izbjeći pomak rasporeda. I servis koji prikazuje raspone odabrane od korisnika treba način odbiti apsurdan zahtjev prije dodjele za njega

uses
  lxHandleX, lxPagination;

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
  Exporter: TXLSCellImageExporter;
  Summary: TXLSXRange;
  W, H, Bytes: Integer;
begin
  Book := TXLSXWorkbook.Create;
  try
    Book.Open('quarter.xlsx');
    Sheet := Book.Sheets.ByPos[0];
    Summary := Sheet.Range['A1:F20'];

    Exporter := TXLSCellImageExporter.Create;
    try
      Exporter.ImageFormat := xpifPng;   // PNG čuva tanke poteze oštrima
      Exporter.DPI := 96;
      Exporter.Scale := 2.0;             // izlaz gustine retine zaslona
      Exporter.IncludeGridlines := False;
      Exporter.IncludeCellBorders := True;
      Exporter.TransparentBackground := True;
      Exporter.MaxPixels := 40 * 1000 * 1000;
      Exporter.MaxBytes := 8 * 1024 * 1024;

      if not Exporter.Measure(Summary, W, H) then
        raise Exception.Create('range exceeds the configured budget');
      // W i H su sada poznati; rezervirajte kutiju rasporeda prije kodiranja
      Bytes := Exporter.Save(Summary, 'summary.png');
      if Bytes <= 0 then
        raise Exception.Create('image export failed, previous file kept');
    finally
      Exporter.Free;
    end;
  finally
    Book.Free;
  end;
end;

Proračuni, jer se mjerilo množi

MaxPixels i MaxBytes nisu obrambeni ukras. Broj piksela raste s kvadratom faktora mjerila i s kvadratom omjera razlučivosti, pa raspon koji je razuman 1200 puta 800 pri 96 DPI postaje otprilike 47 megapiksela pri 600 DPI, a korisnik koji odabere cijeli korišteni raspon umjesto bloka sažetka doda još jedan red veličine na to. Bez granice način kvara jest dodjela koju proces ne može zadovoljiti, koja obara sve ostalo što je taj proces radio

S granicom zahtjev pada i pozivatelj bira: odbiti, smanjiti mjerilo ili suziti raspon. To je mnogo bolji položaj za izvještajni poslužitelj, i to je isto razmišljanje iza izričitih proračuna u dekoderu metafilea opisanom u članku o ograničenom EMF i WMF dekoderu

Tok proračuna za TXLSCellImageExporter u HotXLS-u: Measure prvo vraća piksnu veličinu, zatim MaxPixels i MaxBytes ograničavaju dodjelu i veličinu izlaza
Odbitnica se događa prije dodjele, a pad proračuna bajtova ostavlja prethodnu sliku netaknutom za pozivatelja

Atomsko zamjenjivanje i zašto mapa važi

Save u ime datoteke ne piše u metu. Piše privremenu datoteku u istoj mapi, kodira u nju i tek zatim zamjenjuje metu. Ako kodiranje padne, ako se proračun prekorači usput, ili ako se proces ubije, prethodna slika još je tamo i još je valjana. Nadzorna ploča koja obnavlja svoje pločice po rasporedu dakle nikad ne prikaže skraćeni PNG, što je uobičajeni simptom naivnog pisanja koje otvara odredište i počinje strujati

Pojedinost iste mape nije slučajna. Atomska zamjena atomska je samo unutar jednog sveska, jer preko sveskova operativni sustav mora kopirati pa obrisati, čime se ponovno uvodi prozor koji ste pokušavali zatvoriti. Svaka implementacija ovog obrasca koja smjesti svoju privremenu datoteku u sistemsku privremenu mapu nije atomska na stroju gdje izlaz živi na drugom pogonu

Save od TXLSCellImageExporter kodira u privremenu datoteku u istoj mapi, zatim atomski zamjenjuje metu; padovi ostavljaju prethodnu sliku valjanom
Privremena datoteka mora živjeti uz metu jer atomsko zamjenjivanje radi samo unutar jednog sveska

Događaji bojenja crtaju na stvarnom canvasu

Izvoznik raspona i izvoznik stranica oba izlažu vodeće i završne događaje bojenja, i primaju puni kontekst samo za čitanje umjesto samog handlea canvasa. TXLSPagePaintContext nosi živi canvas, granice u pikselima, veličinu stranice u točkama, razlučivost i mjerilo stvarno u uporabi, broj stranice dokumenta, broj stranice unutar lista, ukupni broj stranica, ime lista i polazni radni list u klasičnom i XLSX obliku. To je dovoljno da se nacrta vodeni žig koji se ispravno mjeri ili pečat stranice koji zna gdje je u nizu

procedure TReportJob.StampDraft(Sender: TObject;
  const AContext: TXLSPagePaintContext);
begin
  // Svjesno mjerila, pa pečat izgleda isto pri 1x i 3x
  AContext.Canvas.Font.Height := Round(-48 * AContext.Scale);
  AContext.Canvas.Font.Color := clSilver;
  AContext.Canvas.Brush.Style := bsClear;
  AContext.Canvas.TextOut(AContext.Bounds.Left + Round(24 * AContext.Scale),
    AContext.Bounds.Top + Round(24 * AContext.Scale), 'DRAFT');
end;

Exporter.AfterPaint := Job.StampDraft;

Tri ponašanja vrijedi se osloniti. Događaji se aktiviraju točno jednom po prikazanom okviru, uključujući svaki okvir višestraničnog TIFF-a, pa je brojač povećan u rukovatelju pouzdan. Tihu su tijekom mjerenja, pa rukovatelj sa sporednim učinkom ne radi dvaput za jedan izlaz. I ako vodeći događaj baci iznimku, završni se događaj ne aktivira i ne zapisuju se djelomični bajtovi slike, pa iznimka u vašem vlastitom crtajućem kôdu ne može proizvesti polupečatnu datoteku

Odabir formata

PNG za sve bogato tekstom. JPEG primjenjuje blokovsku transformaciju koja proizvodi vidljivo zvonce oko tankih kontrastnih poteza, a to su točno obrubi ćelija i mali tekst, i artefakti preživljavaju pri postavkama kvalitete gdje fotografija izgleda savršeno. JPEG zaslužuje svoje mjesto kada rasponom dominiraju ugrađene fotografije i kada veličina datoteke važi više od vjernosti rubova. Prozirne pozadine zahtijevaju PNG, jer JPEG nema alfa kanal, pa je pločica namijenjena obojenoj površini odabrala za vas

Ako vaš raspon sadrži spojene ćelije, provjerite izlaz u odnosu na list: spojene regije međudjeluju sa širinama stupaca na načine koji ljude iznenade, a pravila rasporeda pokrivena su u članku o spojenim ćelijama i predlošcima izvješća. HotXLS čita i piše XLS, XLSX, ODS i CSV iz Delphija i C++Buildera bez Excel ovisnosti, a potpuna površina izvoznika dokumentirana je na stranici proizvoda HotXLS Delphi spreadsheet component