Sve što pluta iznad mreže radnog lista (grafikon, logotip, pečat, oblačić) je objekat za crtanje, a objekat za crtanje definisan je dvema stvarima: šta je i gde je usidren. Sidro (anchor) je deo u kojem ljudi greše. Grafikon ne živi u ćeliji; on se nalazi u pravougaoniku prikovanom za raspon redova i kolona, a podaci koje prikazuje zaseban su skup A1 referenci o kojima sidro ne zna ništa. Pomaknite okvir i prikaz grafikona ostaje na istom mestu. Umetnite redove ispod njega i okvir klizi prema dole zajedno sa njima. Održavanje ta dva koordinatna sistema usklađenim je većina onoga što kod za crtanje čini funkcionalnim
HotXLS je izvorna biblioteka za Object Pascal koja čita i zapisuje XLS i XLSX bez Excel automatizacije, i nosi dva zasebna modela crtanja jer ta dva formata datoteka čuvaju crteže različito. Format BIFF8 .xls drži grafikone na sopstvenim namenskim listovima, a plutajuće oblike u OfficeArt toku pridruženom radnom listu. Format OOXML .xlsx može da ugradi grafikon direktno u mrežu, usidren za pravougaonik ćelije, zajedno sa istom vrstom plutajućih slika i oblika. Model objekta odražava tu podelu, a greške o kojima vredi pisati proizlaze iz primene pravila jednog formata na drugi
Koji kontejner može šta da sadrži
Odabir kontejnera (container) mora da prethodi bilo kom kodu grafikona, jer se dostupni tipovi objekata razlikuju između njih:
- XLS (BIFF8): grafikoni žive na namenskim listovima grafikona stvorenim putem
AddChartSheetna kolekcijiSheets. Slike, tekstualni okviri, pravougaonici, ovali i linije su OfficeArt oblici kojima se upravlja putem kolekcijeShapesradnog lista. Ne postoji API za ugradnju grafikona unutar normalne mreže radnog lista - XLSX (OOXML): grafikoni se mogu ugraditi direktno u radni list pomoću
TXLSXWorksheet.AddChart, usidreni za pravougaonik ćelije, ili postaviti na namenski list grafikona pomoćuTXLSXWorkbook.AddChartSheet. Slike se unose saAddImageiliAddImageFromFile, a plutajuće oznake saAddTextBox
Dakle, zahtev sročen kao 'kontrolna tabla sa grafikonom pored brojeva' zapravo je zahtev za .xlsx format. U .xls formatu to možete samo približno oponašati guranjem grafikona na sopstveni list, što menja način na koji korisnik navigira datotekom i kako se vaš kod mora ponašati. List koji vraća AddChartSheet na XLS strani je podtok grafikona, a ne mreža: pisanje na njega pomoću Cells.Item proizvodi nekonzistentan tok crtanja koji se generiše bez greške, a koji Excel zatim odbacuje pri otvaranju. Grafikon jednostavno nestane, a ništa u zapisniku izgradnje ne govori zašto. Tretirajte vraćeni list kao list isključivo za grafikon i cela klasa prijava o 'nestalim grafikonima' će nestati
Ugradnja grafikona u XLSX radni list
XLSX staza je ona koja daje prostor za manevrisanje, i tu dva koordinatna sistema iz uvoda postaju konkretna. Pravougaonik sidra prosleđen u AddChart izražen je u redovima i kolonama radnog lista i fiksira mesto gde sedi okvir grafikona. Podaci serije izraženi su kao apsolutne A1 reference koje uključuju naziv lista. Oni su nezavisni: možete pomeriti okvir na drugi kraj lista, a grafikon će i dalje prikazivati iste ćelije
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Chart: TXLSXChart;
begin
Book := TXLSXWorkbook.Create;
try
Sheet := Book.Sheets.Add('Sales');
Sheet.Cells[1, 1].Value := 'Region';
Sheet.Cells[1, 2].Value := 'Revenue';
Sheet.Cells[2, 1].Value := 'East';
Sheet.Cells[2, 2].Value := 1184350;
Sheet.Cells[3, 1].Value := 'Central';
Sheet.Cells[3, 2].Value := 902210;
Sheet.Cells[4, 1].Value := 'West';
Sheet.Cells[4, 2].Value := 1010675;
// Frame anchored to rows 6..22, columns 1..8
Chart := Sheet.AddChart(xlsxChartColumn, 'Revenue by Region', 6, 1, 22, 8);
Chart.AddSeries('Revenue', 'Sales!$A$2:$A$4', 'Sales!$B$2:$B$4');
Chart.ValueAxisTitle := 'USD';
Sheet.AddImageFromFile(1, 5, 'logo.png');
Book.SaveAs('dashboard.xlsx');
finally
Book.Free;
end;
end;
Argument koji stvara probleme je niz raspona prosleđen u AddSeries. To je doslovna vrednost (literal), snimljena u trenutku poziva, i ona nema pojma da biste nakon toga mogli dodati još dvadeset redova podataka. Izgradite ga na osnovu broja redova koji ste izračunali nakon što su podaci zapisani, nikada pre. Raspršeni (scatter) i mehuričasti (bubble) grafikoni preopterećuju ista dva argumenta sa različitim značenjima: raspon kategorija sada daje X vrednosti, a raspon vrednosti daje Y, dok poluprečnik mehurića dolazi iz trećeg referentnog skupa postavljenog putem BubbleSizeRange na vraćenom objektu TXLSXChartSeries. Čitajte poziv kao 'X, Y, veličina' umesto 'kategorije, vrednosti' čim napustite familiju stubičastih i trakastih grafikona
TXLSXChartType obuhvata stubičaste, trakaste, linijske, tortne, površinske, prstenaste, raspršene, mehuričaste i radarske grafikone, što pokriva svakodnevni repertoar izveštavanja. Za grafikon preko cele stranice bez okružujuće mreže, Book.AddChartSheet vraća list čije je svojstvo IsChartSheet postavljeno na true. To je XLSX pandan nasleđenom listu grafikona i nosi isto očekivanje: nemojte pisati sadržaj ćelija na njega
Slike se unose kao bajtovi i dimenzionišu se u EMU jedinicama
Postoje dva preopterećenja (overloads) za umetanje slike, a njihovo mešanje je bug sa slikama koji se najčešće pojavljuje u recenziji koda. Funkcija AddImage(ARow, ACol, AData, AFormat) zahteva već kodirane bajtove slike u parametru AData: sirovi sadržaj PNG, JPEG, GIF ili BMP datoteke. Prosledite joj putanju datoteke i sačuvaćete niz od četrdeset bajtova koji nijedan pregledač ne može da dekodira, što je tačno ona prijava o slomljenoj ikoni slike koju ne želite da ispravljate nakon implementacije. Kada je izvor datoteka na disku, radije pozovite AddImageFromFile i pustite biblioteku da pročita bajtove i sama klasifikuje format
Zatim dolazi dimenzonisanje. DrawingML ne meri u pikselima; meri u engleskim metričkim jedinicama (English Metric Units), gde 914400 EMU čini jedan inč, a pri 96 DPI, 9525 EMU čini jedan piksel. Objekat TXLSXImage izlaže WidthEMU and HeightEMU, pa logotip koji bi trebao da se prikaže u veličini 180 sa 60 piksela treba 1714500 sa 571500 EMU. Stavite tu pretvorbu u imenovanu konstantu i računajte prema njoj. Magični brojevi poput 1714500 razbacani po kodu su nečitljivi i tiho pogrešni čim neko promeni ciljani DPI. Sidreni red i kolona su, usput, na bazi 1, što odgovara ostatku API-ja za ćelije, a ne EMU matematici koja je na bazi 0
Listovi grafikona i oblici u nasleđenim XLS datotekama
Na strani BIFF8, bogatije preopterećenje AddChartSheet prima tip grafikona, naslove osa i otvoreni niz zapisa TXLSChartSeriesInfo, gde svaki zapis sadrži naziv te raspon kategorija i vrednosti kao nizove karaktera. Plutajući oblici su zasebna stvar: oni idu na sam radni list sa podacima, kroz njegovu kolekciju Shapes, a ne na list grafikona
var
Book: IXLSWorkbook;
Data, Trend: IXLSWorksheet;
Series: array[0..0] of TXLSChartSeriesInfo;
begin
Book := TXLSWorkbook.Create; // interface-counted: do not Free
Data := Book.Sheets.Add;
Data.Name := 'Data';
Data.Cells.Item[1, 1].Value := 'Month';
Data.Cells.Item[1, 2].Value := 'Units';
Data.Cells.Item[2, 1].Value := 'Apr';
Data.Cells.Item[2, 2].Value := 1530;
Data.Cells.Item[3, 1].Value := 'May';
Data.Cells.Item[3, 2].Value := 1721;
Series[0].Name := 'Units';
Series[0].Categories := 'Data!$A$2:$A$3';
Series[0].Values := 'Data!$B$2:$B$3';
Trend := Book.Sheets.AddChartSheet('Trend', xlsChartTypeLine,
'Units sold', 'Month', 'Units', Series);
// Trend is a chart substream: never call cell methods on it
Data.Shapes.AddTextBox('Source: ERP nightly export', 6, 1, 8, 4);
Data.Shapes.AddPicture('approved-stamp.bmp');
Book.SaveAs('trend.xls');
end;
Ovde su važna dva detalja o životnom veku, i oni vuku u suprotnim smerovima. TXLSWorkbook se drži putem interfejsa IXLSWorkbook i ima brojanje referenci, pa ručno pozivanje Free na njemu pokreće dvostruko oslobađanje. TXLSXWorkbook iz prethodnih odeljaka običan je objekat i mora se osloboditi unutar bloka try..finally. Isti recenzent koda koji označi nedostatak poziva Free na XLSX strani, mora da označi njegovu prisutnost na XLS strani, što je stvarna opasnost od spoticanja kada radite u oba formata unutar iste jedinice. Sami pomagači za oblike su ujednačeni: AddRectangle, AddOval i AddLine, sa DeleteInRange za čišćenje regije crteža, a svi se sidre preko parova redova i kolona, tako da šablon koji umeće redove iznad njih pomiče te oblike zajedno sa mrežom
Još jedno svojstvo opravdava svoje postojanje na nasleđenim datotekama. TXLSPicture.TransparentColor maskira odabranu pozadinsku boju iz bitmape, što je način na koji postavljate nepravougaoni pečat (npr. pečat 'Odobreno' ili vodeni žig) preko mreže u formatu čije BIFF renderovanje nikada nije naučilo PNG alfu. Postavite boju prema kojoj je pečat kreiran i okolni pravougaonik nestaje
Boje tema ne preživljavaju BIFF8 povratno putovanje
OOXML ispune crteža mogu pokazivati na slot boje teme (theme color slot), zbog čega je ponovno bojenje cele .xlsx datoteke zamenom njene teme jeftino. BIFF8 zapisi crteža nemaju takav slot. Kada HotXLS primeni boju teme na XLS crtež, on razrešava boju u doslovnu RGB vrednost i to čuva; indeks teme iz kojeg je proizašla nestaje čim se datoteka zapiše, a ponovno otvaranje ga ne može vratiti. To posebno pogađa 'white-label' alate za izveštavanje, one koji rebrendiraju isti generisani dokument za mnoge klijente. Držite preslikavanje tema-u-RGB u sopstvenoj konfiguraciji i ponovo ga primenite svaki put kada generišete dokument, umest da očekujete da ćete ga pročitati nazad iz sačuvane .xls datoteke
Povezana odluka pojavljuje se na strani performansi. XLS fasadi se može reći da u potpunosti preskoči parsiranje sloja crteža kada iz velike nasleđene datoteke želite samo podatke o ćelijama, postavljanjem _DisableGraphics na true, a to skraćuje stvarno vreme kod skupnog čitanja. Kvaka je trajna: knjiga otvorena na taj način nema OfficeArt tok u memoriji, pa njeno čuvanje briše crteže. Zadržite tu zastavicu samo za čitanje analitičkih zadataka. Šira slika o performansama nalazi se u našim zabeleškama o performansama velikih tabela u HotXLS-u
Održavanje sidara stabilnim dok se mreža menja
Izveštaji retko ostaju veličine u kojoj su generisani, i tu se model sidra iz uvoda isplati. Strukturne operacije XLSX fasade (InsertRows, DeleteRows i ekvivalenti za kolone) pomiču zavisne slojeve zajedno sa ćelijama. Spojene regije, hiperveze, komentari, zamrznuta okna, rasponi filtera, uslovni formati, validacije, tabele, definisani nazivi i, za ovu temu, sidra slika i grafikona, svi putuju zajedno. Logotip usidren u 1. redu ostaje na vrhu kada se ispod njega umetne deset redova. Okvir grafikona usidren ispod bloka podataka klizi prema dole kako blok raste. Jedna stvar koja se ne prepisuje je bilo koji niz raspona koji ste snimili kao doslovnu vrednost (literal) pre nego što se umetanje dogodilo, budući da je to samo tekst koji biblioteka nema razloga ponovo da pregleda. To definiše siguran redosled za popunjavanje šablona: najpre zapišite i preoblikujte podatke, a grafikone izradite i slike postavite u zadnjem prolazu, pri čemu je svaki niz raspona izveden iz broja redova koje imate nakon umetanja, a ne pre
Dva manja alata dovršavaju komplet za postavljanje. Metoda TXLSTextBox.SetArea na XLS strani ponovo sidri postojeći tekstualni okvir ili automatski oblik (auto shape) na novi pravougaonik ćelije, što je gore od brisanja i ponovnog stvaranja kada se blok podnožja pomakne. A preopterećenje bitmape za AddPicture prima živu instancu TBitmap sa neobaveznom zastavicom prozirnosti, pa sve što vaš sopstveni VCL kod može da nacrta (merač, mini grafikon ili tip grafikona koji izvorna lista ne nudi) može se utisnuti direktno u list bez prethodnog zapisivanja privremene datoteke
Grafikoni i slike gotovo su uvek završni sloj na već strukturiranom izveštaju, zbog čega pripremni radovi odlučuju hoće li sjesti čisto. Popunjavanje podataka na koje će se grafikon referisati pokriveno je u članku generisanje izveštaja vođeno šablonima, a održavanje mreže stabilnom ispod vaših sidara tema je članka spojene ćelije i kontrola izgleda. Potpuna dokumentacija klasa i metoda nalazi se na stranici proizvoda HotXLS Component