Techninis straipsnis

Eilučių blokų langelių saugykla ir srautinis XLSX išsaugojimas HotXLS

HotXLS saugo darbalapio langelius kompaktiškuose 256 eilučių blokuose, išsprendžia eilučių, stulpelių ir stačiakampių formatavimą per tingias intervalų perdangas vietoj langelių objektų kūrimo ir srautina kiekvieną eilutę tiesiai į paketo glaudinimo srautą išsaugojant. Kartu tie trys pakeitimai sprendžia didelės knygos atminties profilį: pikinis naudojimasis seka didžiausia viena eilute, o ne baigto darbalapio XML dydžiu

Priežastis, kodėl tai svarbu, yra pavidalas, su kuriuo anksčiau ar vėliau susiduria kiekvienas skaičiuoklės kūrėjas. Naudotojas formatuoja visą stulpelį — vienas spustelėjimas, vienas milijonas langelių — ir naivus objektų modelis atsako paskirdamas milijoną langelių objektų, laikančių vieną skaičių formato indeksą. Failas diske lieka mažas, nes XLSX formatas tai išreiškia kaip vieną <col> įrašą. Procesas visai nelieka mažas

Kodėl stulpelio formatavimas kainuoja daugiau atminties nei jo užpildymas?

Nes formatavimas neturi duomenų, kurie pateisintų objektą. Langelis su reikšme turi egzistuoti kažkur. Langelis, kuris tuščias, bet stilizuotas, egzistuoja tik tam, kad neštų stiliaus indeksą, o milijonų jų materializavimas yra klasikinis būdas, kuriuo Delphi skaičiuoklės programai baigiasi adresų erdvė faile, kurį Excel atveria akimirksniu

Intervalų stilių perdangos pašalina tą poreikį. Eilutės, stulpelio ar stačiakampio formatavimo nurodymas saugomas vieną kartą kaip intervalas ir stiliaus dalys, kurias jis prideda, ir tingiai išsprendžiamas, kai langelis tame intervale iš tikrųjų pasiekiamas. Perdangos išgyvena struktūrinius redagavimus — eilutės įterpimas į formatuotą bloką perkelia intervalą, užuot jį atstatęs — ir jos keliauja ten ir atgal kaip kompaktiški stulpelių, eilučių ir tik stiliaus langelių įrašai, kaip tik taip Excel juos rašo

var
  Sheet: TXLSXWorksheet;
  State: TXLSXCellStyleState;
begin
  Sheet := Workbook.Sheets[1];
  // Style indexes come from the workbook style pools, e.g. from a cell
  // you have already formatted the way you want the range to look
  State := BuildStateFromTemplateCell(Sheet.Cells.Item[1, 1]);
  // Format columns B..D without creating a single empty cell object
  Sheet.StyleOverlays.Add(1, 2, MaxRowIndex, 4,
    [xfpNumberFormat, xfpAlignment], State);
end;

TXLSXFormatParts yra rinkinys, sprendžiantis, ką perdanga prideda: xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment ir xfpProtection. Tik tų dalių, kurias turite omenyje, įvardijimas leidžia perdangoms sluoksniuotis protingai — stulpelio perdanga, tiekianti skaičių formatą, nekovoja su eilutės perdanga, tiekiančia užpildą, nes nė viena nesiskelbia kitos dalimi

Ką duoda 256 eilučių blokas

Vietiškumą. Langeliai laikomi 256 eilučių blokuose su stabiliais viešaisiais deskriptoriais, serijuoti pagal eilutę, todėl rašant darbalapį atmintis einama tvarka, kuria bus išspausdinti baitai, o ne gaudant rodykles krūvoje. Stabilūs deskriptoriai svarbūs API paviršiui: deskriptorius, kurį laiko kviesiantysis, lieka galiojęs per vidinę reorganizaciją, kurią atlieka blokų išdėstymas, kas ir padaro kompaktišką atvaizdavimą diegimo detale, o ne laužomuoju pakeitimu

Stilių telkinio kompaktiškumas vyksta kartu. Prieš kiekvieną išsaugojimą šriftai, užpildai, rėmeliai, skaičių formatai, lygiuotės ir apsaugos, į kuriuos nenurodo joks langelis, yra išmetami. Ilgai gyvuojančios knygos kaupia nenaudojamus stiliaus įrašus taip, kaip ilgai gyvuojantys dokumentai kaupia nenaudojamus stilius, ir knyga, kurią naudotojas redagavo valandą, gali nešti šimtus jų į failą, iš kurio niekas niekada nenuskaitys

Eilučių srautinis išsaugojimas ir kai jis netaikomas

Su StreamingWrite, įjungtu — numatytuoju — kiekviena darbalapio eilutė užrašoma tiesiai į paketo glaudinimo srautą. Alternatyva, kurią vėliavėlė išjungia, pirmiausia stato baigtą darbalapio XML ir glaudina jį vėliau, todėl pikinė atmintis mastosi su visu lakštu. Srautinimas padaro ją mastinčią su viena eilute

Bendrosios eilutės ir pagalbinės dalys seka tą pačią drausmę per vieną pakartotinai naudojamą UTF-8 serijuotoją, išspausdinantį įrašus po vieną, ribojant pikinę atmintį pagal didžiausią vieną įrašą, o ne visą dalį. Tai padengia bendrųjų eilučių lentelę ir pivoto įrašus, kurie plačioje analitinėje knygoje dažnai yra didesni už bet kurį atskirą darbalapį

var
  Workbook: TXLSXWorkbook;
begin
  Workbook := TXLSXWorkbook.Create(nil);
  try
    Workbook.Open('ledger-2026.xlsx');
    // StreamingWrite defaults to True; turn it off only when a downstream
    // step requires the whole worksheet XML to exist before compression
    Workbook.StreamingWrite := True;
    Workbook.SaveAs('ledger-2026-out.xlsx');
  finally
    Workbook.Free;
  end;
end;

Palikite jį įjungtą, nebent turite konkretų motyvą ne. Nesrautinis kelias egzistuoja atvejams, kai kam nors kitam konvejeryje reikia surinkto XML, o mokėti už jį pagal numatytuosius nustatymus reiškia mokėti už atvejį, į kurį dauguma programų niekada nepatenka

Kaip pasakyti, ar perdangos iš tikrųjų naudojamos

Stebėkite langelių skaičių, o ne atminties grafiką. Jei darbalapis praneša tikėtiną fizinų langelių skaičių po plataus formatavimo pritaikymo, perdangos atlieka savo darbą. Jei skaičius šoka per formatuoto intervalo dydį, kažkas kodo kelyje materializavo langelius — dažniausiai ciklas, skaitantis kiekvieną langelį intervale, kad patikrintų jo stilių, kas priverčia sprendimą po vieną langelį ir nugriauja visą sandarą

Išspręskite stilių, kai reikia vieno langelio veiksmingojo formato. Neišspręskite stiliaus milijonui langelių, kad sužinotumėte, jog stulpelis turi skaičių formatą; klauskite perdangos. Ta pati taisyklė taikoma rašymui: priskirkite reikšmes langeliams, kurie turi reikšmių, ir leiskite formatavimui likti intervalu

Kur eina likusi atmintis

Kai langeliai ir stiliai kompaktiški, kit didžiausi vartotojai didelėje knygoje yra bendrųjų eilučių lentelė ir bet kokios palydovo dalys, kurias neša failas — pivoto podėliai, piešiniai, išsaugotas XML iš dalių, kurių objektų modelis nemodeliuoja. Tos turi savo strategijas, ir sąžiningas atsakymas yra tas, kad joks vienas nustatymas neišsprendžia visų iš karto

Jei jūsų silpnoji vieta yra atvėrimas, o ne išsaugojimas, atrankinis įkėlimas yra svertas: tik metaduomenų ir atrankinio darbalapių įkėlimo aprašymas padengia knygos skaitymą nemokant už darbalapius, kurių neliesite. Dėl skaitymo kelio pralaidumo labai dideliems failams žr. lygiagrečios XLSX analizės ir atminties paskirstytuvo pastabas, o darbo apkrovoms, skirtoms tik išvesčiai, kurioms išvis nereikia objektų modelio, srautiniai užrašymai serverio paketiniams darbams dažniausiai tinka geriau nei bet koks derinimas čia

HotXLS skaito ir rašo XLS bei XLSX iš natyvaus Delphi ir C++Builder kodo be Excel diegimo ir be OLE automatizavimo, kas ir padaro šias atminties charakteristikas pastebimas ir valdomas iš pradžių — HotXLS skaičiuoklės komponento puslapyje išvardyti palaikomi formatai ir RAD Studio versijos