Tekninen artikkeli

Rivilohkosolujen tallennus ja suoratoistettu XLSX-tallennus HotXLS:llä

HotXLS tallentaa laskentataulukon solut tiiviissä 256-rivisissä lohkoissa, ratkaisee rivi-, sarake- ja suorakulmiomuotoilun laiskan välikerroksen läpi sen sijaan että se loisi olioita, ja suoratoistaa kunkin rivin suoraan paketin deflate-virtaan tallentaessa. Yhdessä nuo kolme muutosta päättävät suuren työkirjan muistiprofiilin: huippukäyttö seuraa suurinta yksittäistä riviä eikä koko laskentataulukon XML:n kokoa

Syy miksi tämä merkitsee on muoto jonka jokainen taulukkolaskentakehittäjä kohtaa lopulta. Käyttäjä muotoilee kokonaisen sarakkeen — yksi klikkaus, miljoona solua — ja naiivi oliomalli vastaa varaamalla miljoona soluoliota pitämään yhtä lukumuotoiluindeksiä. Tiedosto levyllä pysyy pienenä koska XLSX-muoto ilmaisee tuon yhtenä <col>-merkintänä. Prosessi ei pysy pienenä lainkaan

Miksi sarakkeen muotoilu maksaa enemmän muistia kuin sen täyttäminen?

Koska muotoilulla ei ole dataa joka oikeuttaisi olion. Solulla jolla on arvo pitää olla olemassa jossain. Solu joka on tyhjä mutta tyylitelty on olemassa vain kantamaan yhtä tyyli-indeksiä, ja miljoitten tuollaisten materialisoiminen on klassinen tapa jolla Delphi-taulukkolaskentasovellus loppuu osoitetila kesken tiedostossa jonka Excel avaa välittömästi

Välistyylikerrokset poistavat tarpeen. Rivi-, sarake- tai suorakulmiomuotoiluohje tallennetaan kerran alueena plus tyyli-osina joita se tuo, ja se ratkeaa laiskasti kun alueen soluun oikeasti päästään käsiksi. Kerrokset selviävät rakenteellisista muokkauksista — rivin lisääminen muotoillun lohkon sisällä siirtää väliä sen sijaan että se rakentaisi sen uudelleen — ja ne kiertävät edestakaisin tiiviinä sarake-, rivi- ja vain-tyyli-solumerkintöinä, mikä on juuri niin kuin Excel kirjoittaa ne

Välityylipinokaavio HotXLS:lle, joka näyttää sarakkeen muotoilualueen tallennettuna yhtenä tietueena vaadituilla muotoiluosilla miljoonan tyhjän solun objektin sijaan Delphissä
Sarakkeen, rivin tai suorakulmion muotoilu elää kerran välikerrostietueena, joka vaatii vain omistamansa osat. Tehokas tyyli kootaan laiskasti ensimmäisellä kerralla, kun alueen sisällä olevaan soluun oikeasti kosketaan
var
  Sheet: TXLSXWorksheet;
  State: TXLSXCellStyleState;
begin
  Sheet := Workbook.Sheets[1];
  // Tyyli-indeksit tulevat työkirjan tyylivarastoista, esim. solusta
  // jonka olet jo muotoillut haluamallasi tavalla kohteelle
  State := BuildStateFromTemplateCell(Sheet.Cells.Item[1, 1]);
  // Muotoile sarakkeet B..D luomatta yhtäkään tyhjää soluoliota
  Sheet.StyleOverlays.Add(1, 2, MaxRowIndex, 4,
    [xfpNumberFormat, xfpAlignment], State);
end;

TXLSXFormatParts on joukko joka päättää mitä kerros tuo: xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment ja xfpProtection. Vain niiden osien nimeäminen joita tarkoitat on se mikä antaa kerrosten asettua järkevästi — sarakekerros joka tuo lukumuodon ei taistele rivikerrosta vastaan joka tuo täytön, koska kumpikaan ei vaadi toistensa osaa

Mitä 256-rivinen lohko antaa sinulle

Lokaaliutta. Soluja pidetään 256-rivisissä lohkoissa vakailla julkisilla kahvoilla, sarjoituksena riveittäin, joten laskentataulukon kirjoittaminen kävelee muistissa siinä järjestyksessä jossa se emitoi tavuja sen sijaan että se jahtaisi osoittimia keon yli. Vakaat kahvat merkitsevät API-pinnan kannalta: kahva jota kutsuja pitää pysyy voimassa lohkoasettelun suorittaman sisäisen uudelleenjärjestelyn yli, mikä on se mikä tekee tiiviistä esityksestä toteutusyksityiskohdan eikä rikkovan muutoksen

Rivilohkotallennuksen kaavio, joka näyttää HotXLS-laskentataulukon solut kiinteissä 256 rivin lohkoissa vakailla Delphi-kahvoilla ja rivipääjärjestyksessä sarjallistettuina XLSX deflate -virtaan
Solut istuvat kiinteissä 256 rivin lohkoissa, jotka varaavat vain varatut rivit ja sarjoittuvat samassa järjestyksessä kuin tavut poistuvat prosessista. Julkiset handlet selviävät sisäisestä uudelleenjärjestelystä, joten lohkoasettelu pysyy näkymättömänä kutsujille

Tyyli allaskompaktiointi pyörii sen rinnalla. Ennen jokaista tallennusta fontit, täytöt, reunukset, lukumuodot, tasaukset ja suojaukset joita mikään solu ei osoita pudotetaan. Pitkä ikäiset työkirjat keräävät viittaamattomia tyyilitietueita niin kuin pitkä ikäiset asiakirjat keräävät käyttämättömiä tyylejä, ja työkirjaa jota käyttäjä on muokannut tunnin voi kantaa satoja niitä tiedostoon jota kukaan ei koskaan lue

Rivisuoratoistettu tallennus ja milloin se ei päde

StreamingWrite käytössä — oletus — kunkin laskentataulukon rivi kirjoitetaan suoraan paketin deflate-virtaan. Vaihtoehto, jonka lippu ottaa pois päältä, rakentaa ensin täydellisen laskentataulukon XML:n ja pakkaa sen jälkikäteen, jolloin huippumuisti skaalautuu koko taulukon mukaan. Suoratoisto saa sen skaalautumaan yhden rivin mukaan

Jaetut merkkijonot ja apuosat seuraavat samaa kurinalaisuutta yhden uudelleenkäytettävän UTF-8-sarjoittimen kautta joka emitoi merkinnät yksi kerrallaan, rajoittaen huippumuistia suurimman yksittäisen merkinnän mukaan eikä koko osan. Tämä kattaa jaetun merkkijonotaulun ja pivot-tietueet, jotka laajalla analyyttisellä työkirjalla ovat usein suurempia kuin yksittäinen laskentataulukko

var
  Workbook: TXLSXWorkbook;
begin
  Workbook := TXLSXWorkbook.Create;
  try
    Workbook.Open('ledger-2026.xlsx');
    // StreamingWrite on oletuksena True; kytke pois vain, jos jatko-
    // vaihe vaatii koko arkin XML:n olevan olemassa ennen pakkausta
    Workbook.StreamingWrite := True;
    Workbook.SaveAs('ledger-2026-out.xlsx');
  finally
    Workbook.Free;
  end;
end;

Jätä se päälle ellei sinulla ole konkreettista syytä sammuttaa. Ei-suoratoistopolku on olemassa tapauksia varten joissa jokin muu putkessa tarvitsee koottua XML:ää, ja sen maksaminen oletuksena on maksamista tapauksesta jota useimmat sovellukset eivät koskaan kohtaa

Miten kerrosten käytön todellisuuden erottaa

Tarkkaile solujen määrää, ei muistigrafia. Jos laskentataulukko raportoi uskottavan määrän fyysisiä soluja laajan muotoilun jälkeen, kerrokset tekevät työnsä. Jos määrä hyppää muotoillun alueen koolla, jokin koodipolussa materialisoi solut — yleensä silmukka joka lukee joka solun alueelta tarkistaakseen sen tyylin, mikä pakottaa ratkaisun yksi solu kerrallaan ja voittaa koko järjestelyn

StreamingWrite-kaavio, joka vertailee rivikohtaista deflate-striimausta HotXLS:ssä ja koko laskentataulukon XML:n kokoamista muistiin ennen pakkausta Delphissä
StreamingWrite ollessa päällä jokainen rivi virtaa suoraan paketin deflate-streamiin, ja huippumuisti seuraa yhtä riviä. Lipun kytkeminen pois päältä kokoaa ensin koko laskentataulukon XML:n, mikä skaalaa huippumuistin täyden taulukon mukaan

Ratkaise tyyli kun tarvitset yhden solun tehokasta muotoilua. Älä ratkaise tyyliä miljoonalle solulle selvittääksesi että sarakkeella on lukumuoto; kysy kerrokselta. Sama sääntö koskee kirjoittamista: anna arvot soluille joilla on arvot, ja anna muotoilun pysyä välinä

Mihin jäljellä oleva muisti menee

Kun solut ja tyylit ovat tiiviitä, seuraavat suurimmat kuluttajat suuressa työkirjassa ovat jaettu merkkijonotaulu ja mitä satelliittiosia tiedosto kantaa — pivot-välimuistit, piirrokset, säilytetty XML osista joita oliomalli ei mallinna. Niillä on omat strategiansa, ja rehellinen vastaus on ettei yksikään asetus ratkaise kaikkia kerralla

Jos pullonkaulasi on avaaminen eikä tallennus, valikoiva lataus on vipu: artikkeli vain-metatiedot- ja valikoiva laskentataulukoiden lataaminen käsittelee työkirjan lukemista maksamatta taulukoista joita et koske. Hyvin suurten tiedostojen lukupolun läpimenolle katso muistiinpanot rinnakkainen XLSX-jäsennys ja muistivaraaja, ja pelkästään tulostetyökuormille jotka eivät koskaan tarvitse oliomallia lainkaan, suoratoistettu kirjoitus palvelinerätyöihin on yleensä parempi sopivuus kuin minkä tahansa määrän virittely täällä

HotXLS lukee ja kirjoittaa XLS- ja XLSX-tiedostoja natiivista Delphi- ja C++Builder-koodista ilman Excel-asennusta ja ilman OLE-automaatiota, mikä on sitä mikä tekee näistä muisti-ominaisuuksista havaittavissa ja hallittavissa ensimmäisessäkään — HotXLS-Delphi-taulukkolaskentakomponenttisivulta löytyy tuetut muodot ja RAD Studio -versiot