HotXLS memorizza le celle dei fogli di lavoro in blocchi compatti da 256 righe, risolve la formattazione di riga, colonna e rettangolo attraverso sovrapposizioni di intervallo lazy invece di creare oggetti cella, e riversa ogni riga dritta nello stream deflate del package quando salva. Insieme quei tre cambiamenti decidono il profilo di memoria di una cartella di lavoro grande: il picco di utilizzo segue la singola riga più grande anziché la dimensione del XML completo del foglio
Il motivo per cui questo conta è una forma che ogni sviluppatore di fogli di calcolo incontra prima o poi. Un utente formatta un'intera colonna — un clic, un milione di celle — e un modello a oggetti naive risponde allocando un milione di oggetti cella per tenere un indice di formato numerico. Il file su disco resta minuscolo perché il formato XLSX esprime quello come una singola voce <col>. Il processo non resta minuscolo affatto
Perché formattare una colonna costa più memoria che riempirla?
Perché la formattazione non ha dati per giustificare l'oggetto. Una cella con un valore deve esistere da qualche parte. Una cella che è vuota ma stilizzata esiste solo per portare un indice di stile, e materializzare milioni di quelle è il modo classico in cui un'applicazione Delphi per fogli di calcolo esaurisce lo spazio di indirizzamento su un file che Excel apre istantaneamente
Le sovrapposizioni di stile a intervallo rimuovono la necessità. Un'istruzione di formattazione di riga, colonna o rettangolo viene memorizzata una sola volta come intervallo più le parti di stile che contribuisce, e si risolve in modo lazy quando una cella in quell'intervallo è effettivamenteata. Le sovrapposizioni sopravvivono alle modifiche strutturali — inserire una riga dentro un blocco formattato sposta l'intervallo anziché ricostruirlo — e tornano indietro come voci compatte di colonna, riga e cella solo-stile, che è esattamente come Excel le scrive
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 è l'insieme che decide cosa contribuisce una sovrapposizione: xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment e xfpProtection. Nominare solo le parti che intendi è ciò che permette alle sovrapposizioni di stratificarsi in modo sensato — una sovrapposizione di colonna che fornisce un formato numerico non combatte una sovrapposizione di riga che fornisce un riempimento, perché nessuna delle due rivendica la parte dell'altra
Cosa ti dà il blocco da 256 righe
Località. Le celle sono tenute in blocchi di 256 righe con handle pubblici stabili, serializzati row-major, così scrivere un foglio di lavoro percorre la memoria nell'ordine in cui emetterà byte anziché rincorrere puntatori attraverso l'heap. Gli handle stabili contano per la superficie dell'API: un handle che un chiamante conserva resta valido attraverso la riorganizzazione interna che il layout a blocchi esegue, il che è ciò che rende la rappresentazione compatta un dettaglio di implementazione anziché un cambiamento che rompe la compatibilità
La compattazione dello style pool gira alongside. Prima di ogni salvataggio, font, riempimenti, bordi, formati numerici, allineamenti e protezioni che nessuna cella referenzia vengono droppati. Le cartelle di lavoro longeve accumulano record di stile non referenziati come i documenti longevi accumulano stili non usati, e una cartella di lavoro che è stata modificata da un utente per un'ora può portarne centinaia in un file che nessuno leggerà mai
Salvataggio row-streamed, e quando non si applica
Con StreamingWrite attivo — il predefinito — ogni riga del foglio di lavoro viene scritta direttamente nello stream deflate del package. L'alternativa, che è ciò che il flag disattiva, costruisce prima il XML completo del foglio di lavoro e lo comprime dopo, così il picco di memoria scala con l'intero foglio. Lo streaming lo fa scalare con una sola riga
Le stringhe condivise e le part ausiliarie seguono la stessa disciplina attraverso un serializzatore UTF-8 riusabile che emette le voci una alla volta, limitando il picco di memoria alla singola voce più grande anziché all'intera part. Questo copre la tabella delle stringhe condivise e i record pivot, che su un foglio di lavoro analitico largo sono frequentemente più grandi di qualsiasi singolo foglio
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;
Lascialo attivo a meno che tu non abbia un motivo concreto per non farlo. Il percorso non in streaming esiste per i casi in cui qualcos'altro nella pipeline ha bisogno del XML assemblato, e pagarlo per default è pagare per un caso che la maggior parte delle applicazioni non incontra mai
Come capire se le sovrapposizioni sono davvero usate
Osserva il conteggio delle celle, non il grafico della memoria. Se un foglio di lavoro riporta un numero plausibile di celle fisiche dopo che hai applicato formattazione estesa, le sovrapposizioni fanno il loro lavoro. Se il conteggio salta della dimensione dell'intervallo formattato, qualcosa nel percorso di codice ha materializzato le celle — di solito un ciclo che legge ogni cella nell'intervallo per controllarne lo stile, che forza la risoluzione una cella alla volta e sconfigge l'intero arrangiamento
Risolvi uno stile quando ti serve il formato effettivo di una sola cella. Non risolvere uno stile per un milione di celle per scoprire che la colonna ha un formato numerico; chiedilo all'overlay. La stessa regola si applica alla scrittura: assegna valori alle celle che hanno valori, e lascia che la formattazione resti un intervallo
Dove va il resto della memoria
Una volta che celle e stili sono compatti, i consumer successivi più grandi su una cartella di lavoro grossa sono la tabella delle stringhe condivise e qualsiasi part satellite il file porti — pivot cache, disegni, XML preservato da part che il modello a oggetti non modella. Quelle hanno le proprie strategie, e la risposta onesta è che nessuna singola impostazione le risolve tutte insieme
Se il tuo collo di bottiglia è aprire anziché salvare, il caricamento selettivo è la leva: la guida sul caricamento metadata-only e selettivo dei fogli di lavoro copre la lettura di una cartella di lavoro senza pagare i fogli che non toccherai. Per il throughput sul percorso di lettura su file molto grandi, vedi le note sul parsing XLSX parallelo e il memory allocator, e per carichi di lavoro di solo output che non hanno bisogno affatto di un modello a oggetti, le scritture in streaming per job batch server sono di solito una scelta migliore di qualsiasi quantità di tuning qui
HotXLS legge e scrive XLS e XLSX da codice Delphi e C++Builder nativo senza installazione di Excel e senza automazione OLE, il che è ciò che rende queste caratteristiche di memoria osservabili e controllabili in primo luogo — la pagina del componente spreadsheet HotXLS elenca i formati supportati e le versioni di RAD Studio