Kun käyt vastikään avatun raporttipohjan soluja läpi, yhdistetty otsikko käyttäytyy kuin vuoto. Luet solun A1 ja saat arvon "Quarterly Statement"; luet solut B1–F1, jotka näkyvät saman otsakepalkin alla, etkä saa mitään. Kirjoitat arvon soluun C1 korjataksesi otsikon, eikä se koskaan näy näytöllä. Ruudukko ei kadottanut tietojasi. Se tekee täsmälleen sen, mitä yhdistäminen tarkoittaa: sekä XLS- että XLSX-muodossa yhdistetty suorakulmio näyttää yhden solun, vasemman yläkulman ankkurin, sisällön koko alueella ja käsittelee muita soluja peitettynä tilana, joka voi sisältää arvoja mutta ei koskaan näytä niitä. Excelin käyttäjät omaksuvat tämän kokeilemalla ja erehtymällä. Raporttigeneraattorin on ilmaistava se sääntönä, sillä tuotetussa koodissa oire on tyhjä alue ilman poikkeusta, joka johtaisi sen alkuperään. HotXLS, Delphistä ja C++Builderista molempia Excel-muotoja lukeva ja kirjoittava natiivi Object Pascal -kirjasto, tuo yhdistämistaulukon näkyviin riittävän selvästi, jotta voit ohjelmoida säännön mukaan etkä joudu löytämään sitä uudelleen tukipyynnössä
Yksi arvo, yksi ankkuri
Yhdistäminen on ruudukon päälle asetettava näyttöohje, joka ei muuta ruudukon muotoa. Jokainen peitetty solu on edelleen tiedostossa omana paikkanaan; yhdistämistietue vain käskee kuluttajaa piirtämään ankkurin sisällön suorakulmion alueelle. Tämä ero ohjaa kolmea toimintaa, jotka kannattaa sisäistää ennen asettelukoodin kirjoittamista. Peitetyn solun lukeminen palauttaa sen oman tallennetun arvon, joka luomassasi otsakepalkissa on tavallisesti tyhjä, joten yhdistettyä otsikkoa tarkastelevan koodin on selvitettävä ja luettava ankkuri. Peitettyyn soluun kirjoittaminen onnistuu tiedostotasolla mutta ei näy missään, mikä on johdannon näkymätön otsikko -ansa. Yhdistämisen purkaminen taas paljastaa sen alla koko ajan olleet arvot, joten peitettyyn tilaan kirjoitettu harha-arvo muuttuu näkyväksi virheeksi sinä päivänä, kun joku purkaa yhdistämisen
XLSX-puolella taulukko on ensiluokkainen objekti. Sheet.MergedCells sisältää metodit Add('A1:C1'), FindAt(Row, Col), DeleteAt ja Items, ja useimmin tarvitsemasi kutsu on FindAt: anna sille mikä tahansa koordinaatti, niin se palauttaa solun peittävän yhdistetyn alueen tai nil-arvon, jos solu on yksin. Tämä yksi haku on oikean yhdistettyjen solujen käsittelyn molempien puolien, turvallisen luvun ja kirjoitussuojan, perusta, ja molemmat tulevat myöhemmin vastaan
Kaksi julkisivua, kaksi yhdistämistapaa
HotXLS pitää klassisen BIFF8-.xls-moottorin ja OOXML-.xlsx-moottorin erillisinä objektimalleina, ja ne ilmaisevat yhdistämisen eri tavoin, koska niiden taustalla ovat eri käytännöt. XLS-julkisivu noudattaa Excel COM -idiomia: haet alueen kaksiperusteisesta indeksoidusta ominaisuudesta ja kutsut Merge-metodia OleVariant-arvolla, jonka sisältö määrää syntyvän geometrian
var
Book: IXLSWorkbook; // interface-counted: no manual Free
Sh: IXLSWorksheet;
begin
Book := TXLSWorkbook.Create;
Sh := Book.Sheets[1]; // XLS-taulukkojen kokoelma on 1-pohjainen
Sh.Range['A1', 'F1'].Merge(False); // False = yksi yhdistetty lohko
Sh.Cells.Item[1, 1].Value := 'Quarterly Statement';
Sh.Range['A3', 'F4'].Merge(True); // True = yhdistä poikki: yksi yhdistys riviä kohden
Book.SaveAs('layout.xls');
end;
Merge-metodin argumentti on kohta, jonka ihmiset ymmärtävät usein väärin. Kaksirivisellä alueella Merge(True) tuottaa kaksi itsenäistä yksirivistä yhdistämistä, mikä on Excelin "Merge Across" ja juuri sitä, mitä tarvitset pinotulle otsakepalkille, jonka rivit haluat pitää erillisinä. Merge(False) sulauttaa koko suorakulmion yhdeksi lohkoksi. Alue raportoi myös tilalipun MergeCells, palauttaa sisältävän alueen MergeArea-ominaisuuden kautta ja purkaa yhdistämisen Unmerge-metodilla. XLSX-julkisivu tarjoaa samat toiminnot eri nimillä: Sheet.MergeCells(Row1, Col1, Row2, Col2) ottaa kokonaislukurajat, TXLSXRange.Merge hyväksyy vastaavan Across-variantin ja MergedCells-kokoelma sisältää tuloksen
Datansa mukana kasvava pohja
Todellinen raporttipohja ei ole kiinteä ruudukko. Otsikko ja loppusummat ovat kiinteitä, mutta niiden välinen tietojaosto venyy kyselyn palauttaman määrän mukaan. Kestävä toimintamalli pitää pohjassa yhden täysin muotoillun tietorivin, kloonaa sen kerran kutakin tietuetta kohden ja avaa sitten välin loppusummalohkon eteen, jotta kaikki sen alapuolelle ankkuroidut osat siirtyvät alaspäin menettämättä muotoilujaan
Sheet.Range['A1:F1'].Merge;
Sheet.Cells[1, 1].Value := 'INVOICE #2026-0611'; // arvo siirtyy ankkuriin, A1
Sheet.RowHeight[1] := 28;
TitleFont := Book.Fonts.Add('Calibri', 16, True, False);
Sheet.Cells[1, 1].FontIndex := TitleFont + 1; // pool index 0-based, cell side 1-based
// rivi 5 on tyylitelty tietorivin mallirivi
for I := 0 to ItemCount - 1 do
Sheet.CopyRange(5, 1, 5, 6, 6 + I, 1); // tyylit ja kaavat kulkevat mukana
// avaa aukko loppusummalohkon yläpuolelle; sisältö alapuolella siirtyy alas
Sheet.InsertRows(6 + ItemCount, 1);
Sheet.Range['A1:F1'].SetBorders(xlsxEdgeOutline, xlsxBorderMedium);
Kaksi riviä ansaitsee toisen tarkastelun. Fontin määrityksessä on hiljaa pureva yhden indeksin virhe: Fonts.Add palauttaa 0-pohjaisen paikan fonttivarannossa, kun taas solu tallentaa 1-pohjaisen fonttiviittauksen, jossa 0 tarkoittaa oletusfonttia. Jos + 1 jää pois, mitään poikkeusta ei synny, vaan otsikkosi saa väärän kirjasinlajin. Toinen rivi on CopyRange, joka siirtää muotoilun ja kaavat arvojen mukana. Juuri siksi käsin rakennetun pohjarivin kloonaaminen on parempi kuin sen ulkoasun luominen uudelleen koodissa. Suunnittelija omistaa ulkoasun kerran, pohjassa; generaattori vain kaataa tietoja sen kopioihin
Tämä jako skaalautuu pidemmälle, kun uudelleenkäytettävä asettelu sijaitsee omassa työkirjassaan, esimerkiksi raporttien yhteisiä otsake- ja alatunnistepalkkeja sisältävällä laskentataulukolla. CopyRangeTo tekee saman kloonauksen laskentataulukoiden välillä ja ottaa kohdelaskentataulukon sekä kohdekoordinaatit, joten generaattori voi säilyttää yhden koskemattoman pohjalaskentataulukon ja leimata sen alueet niin moneen tuloslaskentataulukkoon kuin työ tarvitsee. Vaihtoehto, pohjan muuttaminen paikallaan ja sen palauttamisen yrittäminen myöhemmin, toimii vain siihen päivään asti, kun ajo keskeytyy puolivälissä
Mitä InsertRows siirtää ja mitä se ei siirrä
Pohjan kasvattamisen malli toimii vain siksi, että XLSX:n InsertRows on rakenteellinen muokkaus eikä solujen sekoitus. Kun se avaa välin, se siirtää lisäyskohdan alapuolella olevat yhdistetyt alueet, rivikorkeudet, hyperlinkit, kommentit, jäädytetyt ruudut, automaattisuodatusalueet, ehdolliset muotoilut, tietojen kelpoisuustarkistukset, taulukot, määritetyt nimet, kuva-ankkurit ja kaavioankkurit, ei vain soluarvoja. Siksi loppusummalohko saapuu uudelle rivilleen yhdistämisineen ja lukumuotoiluineen ehjänä eikä riisuttuna
Sen kaksi dokumentoitua rajoitusta ovat ne, joiden ympärille kannattaa suunnitella. Kaavojen säätö rajoittuu muokattavaan laskentataulukkoon: kyseisen taulukon sisäiset viittaukset kirjoitetaan uudelleen, ja myös toisella laskentataulukolla oleva, siirtyvälle alueelle viittaava kaava kirjoitetaan uudelleen, mutta säätö seuraa vain muokattavaan laskentataulukkoon kohdistuvia viittauksia. Siksi kaikki työkirjojen väliset viittausmallit ansaitsevat oman tarkastuksensa sokon luottamuksen sijaan. Toinen rajoitus on jyrkempi ja koskee XLS-puolta. Pivot-taulukot säilyvät avaa-tallenna-kierroksilla raakoina säilytettyinä tietueina, eivät HotXLS:n siirrettävinä mallinnettuina objekteina, joten rivien lisääminen ei siirrä pivotin aluetta. Kaikissa .xls-muotoon rakennetuissa pohjissa pivot-alueet on pidettävä kaukana kasvavista palkeista
Kieltäydy kirjoittamasta tietoja asettelutilaan
Tuotantoon asti päätyvä yhdistetyn solun virhe ei ole kosmeettinen. Se on rakenteellinen: tietorivi ajautuu yhdistetylle asettelupalkille, sen arvot päätyvät peitettyihin soluihin ja muuttuvat näkymättömiksi, ja sarakesummat lakkaavat hiljaisesti vastaamasta sitä, mitä laskentataulukon lukija näkee. Koska FindAt vastaa minkä tahansa koordinaatin peittävää aluetta koskevaan kysymykseen, generaattori voi kieltäytyä kirjoituksesta heti sen tapahtuessa sen sijaan, että se toimittaisi raportin, joka laskee hiljaa väärin
// kieltäydy kirjoittamasta tietoja yhdistetyn asettelualueen sisään
if Sheet.MergedCells.FindAt(Row, 1) <> nil then
raise Exception.CreateFmt('row %d overlaps a merged layout region', [Row]);
Sheet.Cells[Row, 1].Value := Detail.Description;
Sama rajatarkistus kuuluu kaikkialle, missä käyttäjä lajittelee tai suodattaa tulostetta myöhemmin. Aluetta, jonka sisällä on yhdistämisiä, ei voi lajitella luotettavasti, koska lajittelu siirtää rivejä itsenäisesti eikä usean rivin yli ulottuvalla yhdistämisellä ole yhtä riviä, jonka mukana se voisi siirtyä; Excel vastaa virheellä tai sekoittuneella asettelulla. Raportit pysyvät oikeina maantieteellisellä kurilla. Rajaa yhdistämiset otsakepalkkeihin, osioerottimiin ja allekirjoituslohkoihin ja pidä laskentataulukon taulukkomuotoinen keskiosa tasaisena. Raporttipohjien luontia käsittelevä artikkeli kehittää tämän asettelu–data-jaon kokonaiseksi paikkamerkkipohjaiseksi työnkuluksi, ja ehdollista muotoilua ja rich textiä käsittelevä artikkeli käsittelee tämän tasaisen tietopalkin muotoilua
Miten yhdistämiset heikkenevät vietäessä
Yhdistäminen on työkirjakäsite, ja jokainen tekstisuuntautunut vientimuoto noudattaa sitä eri määrin. Kun tunnet kolme toimintatapaa etukäteen, säästät yhden laadunvarmistuskierroksen. HTML-vienti toistaa yhdistämiset uskollisesti ja tuottaa colspan- ja rowspan-attribuutit yhteen taulukkoon, joten selaimelle tarkoitettu raportti säilyttää palkkiasettelunsa. RTF-vienti ei venytä sarakkeita lainkaan: ankkuriteksti sijoittuu omaan soluunsa ja yhdistämisen jäljelle jäävä leveys tulee tyhjinä soluina, jolloin leveä otsikko näyttää tekstinkäsittelyohjelmassa työnnetyltä vasemmalle. CSV:ssä ei ole yhdistämisen käsitettä, joten ankkuriarvo täyttää yhden kentän ja jokainen peitetty solu viedään tyhjänä kenttänä. Jos työkirja tuottaa myös erotinmerkkimuotoisia vientejä, johtopäätös on pitää kaikki kantava sisältö poissa yhdistetystä geometriasta; CSV-, TSV- ja HTML-vientiä käsittelevä artikkeli käy jokaisen muodon yksityiskohtaisesti läpi
Yksi rauhoittava tieto tiedostokokoa pohtivalle: yhdistämiset maksavat raporttitasolla lähes olemattomasti. Yhdistämistaulukko on solutietoihin verrattuna pieni, ja peitetyn solun lukeminen käyttää edelleen FindAt-hakua skannauksen sijaan. Suurten työkirjojen suorituskykypaine tulee muualta, pääasiassa tyylivarannon kasvusta ja tallennuspolun käyttämästä muistista, joita suurten työkirjojen suorituskykyä käsittelevä artikkeli käsittelee suoraan. Molemmat yhdistämisrajapinnat, rakenteelliset muokkaustoiminnot ja pohjaesittelyt toimitetaan HotXLS Delphi Componentin mukana