Tehnički članak

Izvoz opsega ćelija Excel-a kao jedne slike uz HotXLS

Ponekad isporučivo nije dokument, to je slika tabele. Blok sažetka u e-poruci o statusu, prikazani KPI panel na nadzornoj tabli, sličica pored rezultata pretrage: svi žele ćelije i nijedan ne želi papir. TXLSCellImageExporter u HotXLS-u uzima klasični ili XLSX pravougaonik ćelija i proizvodi jedan kompaktni PNG ili JPEG bez veličine stranice, bez margina, bez zaglavlja ili podnožja, bez naslova štampe i bez preloma stranica. Rezolucija, razmera, format i JPEG kvalitet su konfigurabilni, objekti, grid linije i ivice ćelija imaju nezavisne prekidače, pozadina može biti boja ili providna, i upis datoteke ide kroz atomsku zamenu u istoj fascikli koja ostavlja postojeću metu netaknutom ako bilo šta otkazuje

Razlog što ovo traži sopstveni eksporter umesto zastavice na putu štampe je što paginacija nije opcion sloj koji možete isključiti. To je stvar zbog koje postoji pipeline stranica

Zašto ne prikazati opseg kroz pipeline štampe?

Zato pipeline štampe umeće stranicu između vas i ćelija. Veličina papira odlučuje koliko staje, margine guraju sadržaj unutra, zaglavlja i podnožja zauzimaju trake koje niste tražili, naslovi štampe ponavljaju redove koje već imate, i preloma stranica rascepuju opseg. Blok sažetka koji slučajno premošćuje prelom izlazi kao dve slike sa zanimljivim redom presečenim na pola. Možete to nadoknaditi postavljanjem prilagođene veličine stranice koja tačno odgovara opsegu, i ljudi to rade, ali to znači ponovno računanje geometrije papira svaki put kad se opseg promeni, i i dalje ostavlja traku zaglavlja i logiku naslova štampe na putu

Eksporter ćelija meri pravougaonik, alocira bitmapu tačno te veličine, crta ćelije u nju, i koduje. Nema stranice, pa nema šta konfigurisati van. Za slučajeve gde ipak želite papir, put PDF izvoza pravi je alat i pokriven je u članku o PDF izvozu radnog lista

TXLSCellImageExporter meri, crta i koduje jednu sliku po opsegu ćelija dok pipeline štampe rascepuje opseg na prelomima stranica
Pipeline stranica umeće geometriju papira između vas i ćelija; eksporter ćelija nema stranicu nigde na putu

Izmerite pre nego što prikažete

Measure vraća piksel dimenzije koje bi trenutne postavke proizvele bez kodovanja bilo čega. To važi iz dva razloga. HTML ili e-poštni šablon obično traži dimenzije slike pre nego što slika postoji, pa da rezerviše kutiju i izbegne pomeranje rasporeda. I servis koji prikazuje opsege izabrane od korisnika traži način da odbije apsurdan zahtev pre nego što alocira 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štrim
      Exporter.DPI := 96;
      Exporter.Scale := 2.0;             // izlaz retina gustine
      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; rezervišite kutiju rasporeda pre kodovanja
      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;

Budžeti, jer se razmera množi

MaxPixels i MaxBytes nisu odbrambena dekoracija. Broj piksela raste sa kvadratom faktora razmere i sa kvadratom odnosa rezolucije, pa opseg koji je razuman 1200 sa 800 pri 96 DPI postaje otprilike 47 megapiksela pri 600 DPI, i korisnik koji izabere ceo korišćeni opseg umesto bloka sažetka dodaje još jedan red veličine preko toga. Bez granice režim otkazivanja je alociranje koje proces ne može zadovoljiti, što obara šta god je taj proces drugo radio

Sa granicom zahtev otkazuje i pozivalac bira: odbiti, smanjiti razmeru, ili suziti opseg. To je mnogo bolji položaj za serverski izveštaj, i isto je rasuđivanje iza eksplicitnih budžeta u dekoderu metafajla opisanom u članku o ograničenom EMF i WMF dekoderu

Tok budžeta za TXLSCellImageExporter u HotXLS-u: Measure prvo vraća piksel veličinu, pa MaxPixels i MaxBytes ograničavaju alociranje i veličinu izlaza
Odbijanje dešava se pre alociranja, i neuspeh budžeta bajtova ostavlja prethodnu sliku netaknutom za pozivaoca

Atomska zamena, i zašto fascikla važi

Save u ime datoteke ne piše u metu. Piše privremenu datoteku u istoj fascikli, koduje u nju, i tek zatim zamenjuje metu. Ako kodovanje otkazuje, ako je budžet prekoračen na pola puta, ili ako je proces ubijen, prethodna slika je i dalje tu i i dalje valjana. Nadzorna tabla koja regeneriše svoje pločice po rasporedu dakle nikad ne prikazuje odsečen PNG, što je uobičajeni simptom naivnog upisa koji otvara odredište i počinje strujati

Detalj iste fascikle nije slučajan. Atomska zamena je atomska samo unutar jednog volumena, jer preko volumena operativni sistem mora kopirati pa obrisati, što ponovo uvodi prozor koji ste pokušavali zatvoriti. Svaka implementacija ovog obrasca koja stavlja svoju privremenu datoteku u sistemski temp direktorijum nije atomska na mašini gde izlaz živi na drugom disku

TXLSCellImageExporter Save koduje u privremenu datoteku u istoj fascikli, pa atomski zamenjuje metu; otkazivanja ostavljaju prethodnu sliku valjanom
Privremena datoteka mora živeti pored mete jer atomska zamena radi samo unutar jednog volumena

Događaji bojenja crtaju na pravom canvas-u

I eksporter opsega i eksporter stranica izlažu vodeće i prateće događaje bojenja, i oni primaju pun kontekst samo-za-čitanje umesto samo handle canvas-a. TXLSPagePaintContext nosi živi canvas, piksel granice, veličinu stranice u tačkama, rezoluciju i razmeru zapravo u upotrebi, broj stranice dokumenta, broj stranice u listu, ukupan broj stranica, ime lista i izvorni radni list u klasičnom i XLSX varijantama. To je dovoljno da se nacrta vodeni žig koji se pravilno razmerava, ili pečat stranice koji zna gde je u nizu

procedure TReportJob.StampDraft(Sender: TObject;
  const AContext: TXLSPagePaintContext);
begin
  // Svesno razmere, pa pečat izgleda isto na 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 vredi se osloniti. Događaji opali tačno jednom po prikazanom kadru, uključujući svaki kadar višestraničnog TIFF-a, pa brojač uvećan u rukovaocu pouzdan je. Ostaju tihi tokom merenja, pa rukovaoc sa sporednim efektom ne radi dvaput za jedan izlaz. I ako vodeći događaj podigne izuzetak, prateći događaj ne opali i nijedan delimičan bajt slike se ne piše, pa izuzetak u vašem sopstvenom crtačkom kodu ne može proizvesti polu-pečatanu datoteku

Izbor formata

PNG za sve bogato tekstom. JPEG primenjuje blok transformaciju koja proizvodi vidljivo zazvonjavanje oko tankih visokokontrastnih poteza, što su tačno ivice ćelija i mali tekst, i artefakti prežive na podešavanjima kvaliteta gde fotografija deluje savršeno. JPEG zaslužuje svoje mesto kada opsegom dominiraju ugrađene fotografije i veličina datoteke važi više od vernosti ivica. Providne pozadine traže PNG, pošto JPEG nema alfa kanal, pa je pločica namenjena sedenju na obojenoj površini napravila izbor za vas

Ako vaš opseg sadrži spojene ćelije, proverite izlaz u odnosu na list: spojene regije međusobno deluju sa širinama kolona na načine koji iznenađuju ljude, i pravila rasporeda pokrivena su u članku o spojenim ćelijama i šablonima izveštaja. HotXLS čita i piše XLS, XLSX, ODS i CSV iz Delphi-ja i C++Builder-a bez Excel zavisnosti, i potpuna površina eksportera dokumentovana je na stranici proizvoda HotXLS Delphi spreadsheet component