Το HotXLS αποθηκεύει κελιά φύλλων εργασίας σε συμπαγή μπλοκ 256 γραμμών, επιλύει τη μορφοποίηση γραμμής, στήλης και ορθογωνίου μέσω τεμπέλικων επικαλύψεων διαστήματος αντί να δημιουργεί αντικείμενα κελιού, και προωθεί κάθε γραμμή κατευθείαν στο πακέτο deflate stream κατά την αποθήκευση. Μαζί αυτές οι τρεις αλλαγές αποφασίζουν το προφίλ μνήμης ενός μεγάλου βιβλίου εργασίας: η μέγιστη χρήση ακολουθεί τη μεγαλύτερη μεμονωμένη γραμμή παρά το μέγεθος του πλήρους XML φύλλου εργασίας
Ο λόγος που αυτό έχει σημασία είναι ένα σχήμα που κάθε προγραμματιστής υπολογιστικών φύλλων συναντά τελικά. Ένας χρήστης μορφοποιεί μια ολόκληρη στήλη — ένα κλικ, ένα εκατομμύριο κελιά — και ένα αφελές μοντέλο αντικειμένου απαντά δεσμεύοντας ένα εκατομμύριο αντικείμενα κελιού για να κρατήσει ένα ευρετήριο μορφής αριθμών. Το αρχείο στον δίσκο παραμένει μικρό επειδή η μορφή XLSX το εκφράζει ως μία καταχώριση <col>. Η διεργασία δεν παραμένει μικρή καθόλου
Γιατί η μορφοποίηση μιας στήλης κοστίζει περισσότερη μνήμη από το γέμισμά της;
Επειδή η μορφοποίηση δεν έχει δεδομένα να δικαιολογήσουν το αντικείμενο. Ένα κελί με τιμή πρέπει να υπάρχει κάπου. Ένα κελί που είναι κενό αλλά μορφοποιημένο υπάρχει μόνο για να φέρει ένα ευρετήριο στυλ, και η υλοποίηση εκατομμυρίων τέτοιων είναι ο κλασικός τρόπος με τον οποίο μια εφαρμογή Delphi υπολογιστικών φύλλων ξεμένει από χώρο διευθύνσεων σε ένα αρχείο που το Excel ανοίγει ακαριαία
Οι επικαλύψεις στυλ διαστήματος αφαιρούν την ανάγκη. Μια οδηγία μορφοποίησης γραμμής, στήλης ή ορθογωνίου αποθηκεύεται μία φορά ως εύρος συν τα μέρη στυλ που συνεισφέρει, και επιλύεται τεμπέλικα όταν ένα κελί σε αυτό το εύρος προσπελαστεί πραγματικά. Οι επικαλύψεις επιζούν δομικών επεξεργασιών — η εισαγωγή μιας γραμμής μέσα σε ένα μορφοποιημένο μπλοκ μετακινεί το διάστημα αντί να το ξαναχτίσει — και κάνουν round trip ως συμπαγείς καταχωρήσεις στήλης, γραμμής και κελιού μόνο στυλ, που είναι ακριβώς έτσι όπως τις γράφει το Excel
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 είναι το σύνολο που αποφασίζει τι συνεισφέρει μια επικάλυψη: xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment και xfpProtection. Η ονομασία μόνο των μερών που εννοείτε είναι αυτό που επιτρέπει στις επικαλύψεις να στοιβάζονται λογικά — μια επικάλυψη στήλης που παρέχει μια μορφή αριθμών δεν συγκρούεται με μια επικάλυψη γραμμής που παρέχει ένα γέμισμα, επειδή καμία δεν διεκδικεί το μέρος της άλλης
Τι σας δίνει το μπλοκ 256 γραμμών
Τοπικότητα. Τα κελιά κρατιούνται σε μπλοκ 256 γραμμών με σταθερούς δημόσιους χειριστές, σειριοποιημένα row-major, ώστε η εγγραφή ενός φύλλου εργασίας να διασχίζει τη μνήμη με τη σειρά που θα εκπέμψει bytes αντί να κυνηγάει δείκτες μέσα στον σωρό. Οι σταθεροί χειριστές έχουν σημασία για την επιφάνεια API: ένας χειριστής που κρατά ένας καλών παραμένει έγκυρος κατά την εσωτερική αναδιοργάνωση που εκτελεί η διάταξη μπλοκ, που είναι αυτό που κάνει τη συμπαγή αναπαράσταση μια λεπτομέρεια υλοποίησης παρά μια αλλαγή που σπάει συμβατότητα
Η συμπύκνωση της δεξαμενής στυλ τρέχει παράλληλα. Πριν από κάθε αποθήκευση, γραμματοσειρές, γεμίσματα, περιγράμματα, μορφές αριθμών, στοίχιση και προστασία που δεν αναφέρεται κανένα κελί απορρίπτονται. Τα μακρόβια βιβλία εργασίας συσσωρεύουν αναφορές στυλ χωρίς αναφορά όπως τα μακρόβια έγγραφα συσσωρεύουν αχρησιμοποίητα στυλ, και ένα βιβλίο εργασίας που έχει επεξεργαστεί από έναν χρήστη για μία ώρα μπορεί να φέρει εκατοντάδες από αυτά σε ένα αρχείο από το οποίο κανείς δεν θα τα διαβάσει ποτέ
Ροητή αποθήκευση γραμμής, και πότε δεν ισχύει
Με την StreamingWrite ενεργοποιημένη — η προεπιλογή — κάθε γραμμή φύλλου εργασίας γράφεται απευθείας στο πακέτο deflate stream. Η εναλλακτική, που είναι αυτό που κλείνει η σημαία, κατασκευάζει πρώτα το πλήρες XML του φύλλου εργασίας και το συμπιέζει μετά, οπότε η μέγιστη μνήμη κλιμακώνεται με ολόκληρο το φύλλο. Η ροή την κάνει να κλιμακώνεται με μία γραμμή
Οι κοινόχρηστες συμβολοσειρές και τα βοηθητικά μέρη ακολουθούν την ίδια πειθαρχία μέσω ενός επαναχρησιμοποιήσιμου σειριοποιητή UTF-8 που εκπέμπει καταχωρήσεις μία τη φορά, ορίζοντας μέγιστη μνήμη από τη μεγαλύτερη μεμονωμένη καταχώριση παρά από ολόκληρο το μέρος. Αυτό καλύπτει τον πίνακα κοινόχρηστων συμβολοσειρών και τις εγγραφές pivot, που σε ένα ευρύ αναλυτικό βιβλίο εργασίας είναι συχνά μεγαλύτερες από οποιοδήποτε μεμονωμένο φύλλο εργασίας
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;
Αφήστε την ανοιχτή εκτός αν έχετε συγκεκριμένο λόγο να μην την αφήσετε. Η μη ροητή διαδρομή υπάρχει για τις περιπτώσεις όπου κάτι άλλο στη γραμμή παραγωγής χρειάζεται το assembled XML, και η πληρωμή για αυτή από προεπιλογή είναι πληρωμή για μια περίπτωση που οι περισσότερες εφαρμογές δεν συναντούν ποτέ
Πώς να πείτε αν οι επικαλύψεις χρησιμοποιούνται πραγματικά
Παρακολουθήστε τον αριθμό κελιών, όχι το γράφημα μνήμης. Αν ένα φύλλο εργασίας αναφέρει έναν εύλογο αριθμό φυσικών κελιών αφού έχετε εφαρμόσει ευρεία μορφοποίηση, οι επικαλύψεις κάνουν τη δουλειά τους. Αν ο αριθμός πηδά κατά το μέγεθος του μορφοποιημένου εύρους, κάτι στη διαδρομή κώδικα υλοποίησε υλικά τα κελιά — συνήθως ένας βρόχος που διαβάζει κάθε κελί στο εύρος για να ελέγξει το στυλ του, που αναγκάζει επίλυση ένα κελί τη φορά και νικώνει ολόκληρη τη διευθέτηση
Επιλύστε ένα στυλ όταν χρειάζεστε την ενεργή μορφή ενός κελιού. Μην επιλύετε ένα στυλ για ένα εκατομμύριο κελιά για να μάθετε ότι η στήλη έχει μορφή αριθμών· ρωτήστε την επικάλυψη. Ο ίδιος κανόνας ισχύει για τη γραφή: αναθέστε τιμές στα κελιά που έχουν τιμές, και αφήστε τη μορφοποίηση να παραμείνει ένα διάστημα
Πού πάει η υπόλοιπη μνήμη
Μόλις τα κελιά και τα στυλ γίνουν συμπαγή, οι επόμενοι μεγαλύτεροι καταναλωτές σε ένα μεγάλο βιβλίο εργασίας είναι ο πίνακας κοινόχρηστων συμβολοσειρών και όποια δορυφορικά μέρη φέρει το αρχείο — κρυφές μνήμες pivot, σχέδια, διατηρημένο XML από μέρη που το μοντέλο αντικειμένου δεν μοντελοποιεί. Αυτά έχουν τις δικές τους στρατηγικές, και η ειλικρινής απάντηση είναι ότι καμία μεμονωμένη ρύθμιση δεν τα λύνει όλα με τη μία
Αν το bottleneck σας είναι το άνοιγμα παρά την αποθήκευση, η επιλεκτική φόρτωση είναι ο μοχλός: η ανάλυση της φόρτωσης φύλλων εργασίας μόνο μεταδεδομένων και επιλεκτικής καλύπτει την ανάγνωση ενός βιβλίου εργασίας χωρίς να πληρώσετε για τα φύλλα που δεν θα αγγίξετε. Για απόδοση διαδρομής ανάγνωσης σε πολύ μεγάλα αρχεία, δείτε τις σημειώσεις για το παράλληλο parsing XLSX και τον allocator μνήμης, και για φόρτους εργασίας μόνο εξόδου που δεν χρειάζεται ποτέ μοντέλο αντικειμένου, η ροητή εγγραφή για παρτίδες διακομιστή είναι συνήθως καλύτερη προσαρμογή από οποιαδήποτε ποσότητα ρύθμισης εδώ
Το HotXLS διαβάζει και γράφει XLS και XLSX από native κώδικα Delphi και C++Builder χωρίς εγκατάσταση Excel και χωρίς αυτοματισμό OLE, που είναι αυτό που κάνει αυτά τα χαρακτηριστικά μνήμης παρατηρήσιμα και ελέγξιμα εξ αρχής — η σελίδα του HotXLS spreadsheet συστατικού παραθέτει τις υποστηριζόμενες μορφές και τις εκδόσεις RAD Studio