HotXLS stocke les cellules de feuille de calcul dans des blocs compacts de 256 lignes, résout la mise en forme de ligne, colonne et rectangle via des surcouches d'intervalle paresseuses au lieu de créer des objets cellule, et streame chaque ligne directement dans le flux deflate du paquet à la sauvegarde. Ensemble ces trois changements décident du profil mémoire d'un gros classeur : l'usage de pointe suit la plus grosse ligne unique plutôt que la taille du XML complet de feuille de calcul
La raison pour laquelle cela compte est une forme que tout développeur tableur finit par rencontrer. Un utilisateur met en forme une colonne entière — un clic, un million de cellules — et un modèle objet naïf répond en allouant un million d'objets cellule pour porter un seul index de format de nombre. Le fichier sur disque reste minuscule car le format XLSX exprime cela comme une seule entrée <col>. Le processus ne reste pas minuscule du tout
Pourquoi mettre en forme une colonne coûte-t-elle plus de mémoire que la remplir ?
Parce que la mise en forme n'a pas de données pour justifier l'objet. Une cellule avec une valeur doit exister quelque part. Une cellule qui est vide mais stylée n'existe que pour porter un index de style, et matérialiser des millions de celles-ci est la façon classique dont une application tableur Delphi tombe à court d'espace d'adressage sur un fichier qu'Excel ouvre instantanément
Les surcouches de style par intervalle suppriment ce besoin. Une instruction de mise en forme de ligne, colonne ou rectangle est stockée une fois comme une plage plus les parties de style qu'elle contribue, et se résout paresseusement quand une cellule dans cette plage est effectivement accédée. Les surcouches survivent aux éditions structurelles — insérer une ligne à l'intérieur d'un bloc mis en forme déplace l'intervalle plutôt que de le reconstruire — et font l'aller-retour comme entrées compactes de colonne, ligne et cellule à style uniquement, ce qui est exactement comment Excel les écrit
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 est l'ensemble qui décide ce qu'une surcouche contribue : xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment et xfpProtection. Ne nommer que les parties que vous voulez est ce qui permet aux surcouches de s'empiler sensément — une surcouche de colonne qui fournit un format de nombre ne combat pas une surcouche de ligne qui fournit un remplissage, car aucune ne réclame la partie de l'autre
Ce que le bloc de 256 lignes vous donne
La localité. Les cellules sont détenues dans des blocs de 256 lignes avec des handles publics stables, sérialisées en ligne majeure, donc écrire une feuille de calcul parcourt la mémoire dans l'ordre où elle émettra des octets plutôt que de chasser des pointeurs à travers le tas. Les handles stables comptent pour la surface API : un handle qu'un appelant détient reste valide à travers la réorganisation interne que la disposition en blocs effectue, ce qui fait de la représentation compacte un détail d'implémentation plutôt qu'un changement cassant
Le compactage du pool de styles tourne à côté. Avant chaque sauvegarde, les polices, remplissages, bordures, formats de nombre, alignements et protections qu'aucune cellule ne référence sont abandonnés. Les classeurs de longue vie accumulent des enregistrements de style non référencés comme les documents de longue vie accumulent des styles inutilisés, et un classeur qui a été édité par un utilisateur pendant une heure peut en porter des centaines dans un fichier que personne ne lira jamais
Sauvegarde en streaming ligne à ligne, et quand elle ne s'applique pas
Avec StreamingWrite activé — par défaut — chaque ligne de feuille de calcul est écrite directement dans le flux deflate du paquet. L alternative, ce que l'indicateur désactive, construit le XML complet de feuille de calcul d'abord et le compresse ensuite, donc la mémoire de pointe évolue avec la feuille entière. Le streaming la fait évoluer avec une ligne
Les chaînes partagées et les parties auxiliaires suivent la même discipline à travers un sérialiseur UTF-8 réutilisable qui émet les entrées une à la fois, bornant la mémoire de pointe par la plus grosse entrée unique plutôt que par la partie entière. Cela couvre la table de chaînes partagées et les enregistrements de tableau croisé dynamique, qui sur un classeur analytique large sont fréquemment plus grands que toute feuille de calcul individuelle
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;
Laissez-le activé à moins que vous n'ayez une raison concrète de ne pas le faire. Le chemin non streaming existe pour les cas où quelque chose d'autre dans le pipeline a besoin du XML assemblé, et le payer par défaut c'est payer pour un cas que la plupart des applications ne rencontrent jamais
Comment dire si les surcouches sont effectivement utilisées
Surveillez le compte de cellules, pas le graphe mémoire. Si une feuille de calcul signale un nombre plausible de cellules physiques après que vous avez appliqué une mise en forme étendue, les surcouches font leur travail. Si le compte saute de la taille de la plage mise en forme, quelque chose dans le chemin de code a matérialisé les cellules — habituellement une boucle qui lit chaque cellule dans la plage pour vérifier son style, ce qui force la résolution une cellule à la fois et défait tout l'arrangement
Résolvez un style quand vous avez besoin du format effectif d'une cellule. Ne résolvez pas un style pour un million de cellules pour découvrir que la colonne a un format de nombre ; demandez à la surcouche. La même règle s'applique à l'écriture : assignez des valeurs aux cellules qui ont des valeurs, et laissez la mise en forme rester un intervalle
Où va la mémoire restante
Une fois les cellules et les styles compacts, les plus gros consommateurs suivants sur un gros classeur sont la table de chaînes partagées et les parties satellites que le fichier porte — caches de tableau croisé dynamique, dessins, XML préservé de parties que le modèle objet ne modélise pas. Ceux-ci ont leurs propres stratégies, et la réponse honnête est qu'aucun paramètre unique ne les résout tous à la fois
Si votre goulot est à l'ouverture plutôt qu'à la sauvegarde, le chargement sélectif est le levier : la visite guidée du chargement métadonnées seules et sélectif de feuilles de calcul couvre la lecture d'un classeur sans payer pour les feuilles que vous ne toucherez pas. Pour le débit en lecture sur de très gros fichiers, voir les notes sur l'analyse XLSX parallèle et l'allocateur de mémoire, et pour les charges à écriture seule qui n'ont jamais besoin d'un modèle objet du tout, les écritures en streaming pour les travaux par lots serveur est habituellement un meilleur ajustement que n'importe quelle quantité de réglage ici
HotXLS lit et écrit XLS et XLSX depuis du code Delphi et C++Builder natif sans installation Excel ni automation OLE, ce qui est ce qui rend ces caractéristiques mémoire observables et contrôlables en premier lieu — la page composant tableur HotXLS liste les formats et versions RAD Studio pris en charge