HotXLS เก็บเซลล์เวิร์กชีตในบล็อก 256 แถวกระชับ คลี่คลายการจัดรูปแบบแถว คอลัมน์ และสี่เหลี่ยมผ่าน interval overlay แบบ lazy แทนที่จะสร้างออบเจกต์เซลล์ และสตรีมแต่ละแถวตรงเข้าสู่ deflate stream ของแพ็กเกจขณะบันทึก สามการเปลี่ยนแปลงนี้ร่วมกันตัดสินโปรไฟล์หน่วยความจำของเวิร์กบุ๊กขนาดใหญ่ การใช้งานสูงสุดตามแถวเดียวที่ใหญ่ที่สุด ไม่ใช่ตามขนาดของ worksheet XML ทั้งหมด
เหตุผลที่เรื่องนี้สำคัญคือรูปร่างที่นักพัฒนาสเปรดชีตทุกคนพบในที่สุด ผู้ใช้จัดรูปแบบคอลัมน์ทั้งคอลัมน์ — คลิกเดียว หนึ่งล้านเซลล์ — และ object model ที่ไร้เดียงสาตอบโดยจัดสรรออบเจกต์เซลล์หนึ่งล้านเพื่อถือ index number-format เดียว ไฟล์บนดิสก์ยังคงเล็กเพราะรูปแบบ XLSX แทนมันเป็น entry <col> เดียว โพรเซสไม่เล็กเลย
ทำไมการจัดรูปแบบคอลัมน์จึงกินหน่วยความจำมากกว่าการเติม
เพราะการจัดรูปแบบไม่มีข้อมูลที่จะให้เหตุผลกับออบเจกต์ เซลล์ที่มีค่าต้องมีอยู่ที่ไหนสักแห่ง เซลล์ที่ว่างแต่มีสไตล์อยู่เพื่อถือ style index เท่านั้น และการสร้างออบเจกต์เซลล์เป็นล้าน ๆ เป็นวิธีคลาสสิกที่แอปพลิเคชันสเปรดชีต Delphi หมดพื้นที่อยู่บนไฟล์ที่ Excel เปิดทันที
interval style overlay เอาความจำเป็นนั้นออกไป คำสั่งจัดรูปแบบแถว คอลัมน์ หรือสี่เหลี่ยมถูกเก็บครั้งเดียวเป็นช่วงบวกส่วนสไตล์ที่มันสนับสนุน แล้วคลี่คลายแบบ lazy เมื่อเซลล์ในช่วงนั้นถูกเข้าถึงจริง overlay รอดจากการแก้ไขเชิงโครงสร้าง — การแทรกแถวในบล็อกที่จัดรูปแบบแล้วย้ายช่วงแทนที่จะสร้างใหม่ — และเดินทางไปกลับเป็น entry คอลัมน์ แถว และเซลล์เฉพาะสไตล์แบบกระชับ ซึ่งเป็นวิธีที่ 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 เป็นเซ็ตที่ตัดสินว่า overlay สนับสนุนอะไรบ้าง xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment และ xfpProtection การระบุเฉพาะส่วนที่คุณตั้งใจคือสิ่งที่ทำให้ overlay ซ้อนกันได้อย่างสมเหตุสมผล — column overlay ที่ส่ง number format ไม่ขัด row overlay ที่ส่ง fill เพราะไม่มีฝั่งใดอ้างส่วนของอีกฝั่ง
บล็อก 256 แถวให้อะไรคุณ
locality เซลล์ถูกถือในบล็อก 256 แถวพร้อมแฮนเดิลสาธารณะที่คงที่ ทำให้เป็นอนุกรมแบบ row-major ดังนั้นการเขียนเวิร์กชีตเดินผ่านหน่วยความจำตามลำดับที่มันจะปล่อยไบต์ แทนที่จะไล่ตามพอยน์เตอร์ข้าม heap แฮนเดิลที่คงที่สำคัญต่อพื้นผิว API แฮนเดิลที่ผู้เรียกถือยังคงใช้ได้ข้ามการรีออร์แกไนซ์ภายในที่เลย์เอาต์บล็อกกระทำ ซึ่งเป็นสิ่งที่ทำให้การแทนกระชับเป็นรายละเอียดการทำงานไม่ใช่การเปลี่ยนแปลงที่ทำลาย
การทำ style pool ให้กระชับรันควบคู่กับมัน ก่อนทุกการบันทึก font fill border number format alignment และ protection ที่ไม่มีเซลล์อ้างถึงจะถูกทิ้ง เวิร์กบุ๊กที่อายุยืนสะสมเรคคอร์ดสไตล์ที่ไม่ถูกอ้างถึงเหมือนที่เอกสารที่อายุยืนสะสมสไตล์ที่ไม่ใช้ เวิร์กบุ๊กที่ผู้ใช้แก้มาหนึ่งชั่วโมงสามารถพกมันเข้าไปในไฟล์เป็นร้อย ๆ ที่ไม่มีใครจะอ่านจาก
การบันทึกแบบ row-streamed และเมื่อใดที่มันไม่นำไปใช้
เมื่อเปิดใช้ StreamingWrite — ค่าเริ่มต้น — แต่ละแถวเวิร์กชีตจะถูกเขียนตรงเข้า deflate stream ของแพ็กเกจ ทางเลือกอื่น ซึ่งคือสิ่งที่สถานะปิด คือสร้าง worksheet XML ทั้งหมดก่อนแล้วบีบอัดภายหลัง ทำให้หน่วยความจำสูงสุดขึ้นกับชีตทั้งหมด การสตรีมทำให้ขึ้นกับหนึ่งแถว
shared string และ part สนับสนุนทำตามวินัยเดียวกันผ่านตัวทำให้เป็นอนุกรม UTF-8 หนึ่งตัวที่ใช้ซ้ำได้ที่ปล่อย entry ทีละตัว จำกัดหน่วยความจำสูงสุดด้วย entry เดียวที่ใหญ่ที่สุดแทนทั้ง part นั่นครอบคลุม shared string table และเรคคอร์ด 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;
ปล่อยมันเปิดไว้ เว้นแต่คุณมีเหตุผลที่แน่ชัดที่จะไม่ทำ เส้นทางที่ไม่ใช่สตรีมมีไว้สำหรับกรณีที่สิ่งอื่นในไปป์ไลน์ต้องการ XML ที่ประกอบแล้ว และการจ่ายให้มันโดยค่าเริ่มต้นคือการจ่ายสำหรับกรณีที่แอปพลิเคชันส่วนใหญ่ไม่เคยพบ
จะบอกได้อย่างไรว่า overlay ถูกใช้จริง
ดูจำนวนเซลล์ ไม่ใช่กราฟหน่วยความจำ หากเวิร์กชีตรายงานจำนวนเซลล์ทางกายภาพที่เป็นไปได้หลังคุณใช้การจัดรูปแบบกว้าง ๆ overlay ก็กำลังทำงาน หากจำนวนกระโดดเท่ากับขนาดของช่วงที่จัดรูปแบบ สิ่งใดสิ่งหนึ่งในเส้นทางโค้ดสร้างเซลล์เป็นรูปธรรม — มักเป็นลูปที่อ่านทุกเซลล์ในช่วงเพื่อตรวจสไตล์ ซึ่งบังคับให้คลี่คลายทีละเซลล์และทำลายการจัดเรียงทั้งหมด
คลี่คลายสไตล์เมื่อคุณต้องการรูปแบบที่มีผลของเซลล์หนึ่ง อย่าคลี่คลายสไตล์สำหรับเซลล์ล้านเซลล์เพื่อค้นหาว่าคอลัมน์มี number format ถาม overlay กฎเดียวกันนำไปใช้กับการเขียน กำหนดค่าให้เซลล์ที่มีค่า แล้วปล่อยการจัดรูปแบบให้เป็นช่วงต่อไป
หน่วยความจำที่เหลือไปอยู่ที่ใด
เมื่อเซลล์และสไตล์กระชับแล้ว ผู้บริโภคที่ใหญ่ที่สุดถัดไปบนเวิร์กบุ๊กขนาดใหญ่คือ shared string table และ part ดาวเทียมใด ๆ ที่ไฟล์พก — pivot cache งานวาด XML ที่รักษาไว้จาก part ที่ object model ไม่ได้ model สิ่งเหล่านั้นมีกลยุทธ์ของตัวเอง และคำตอบที่ซื่อคือไม่มีการตั้งค่าเดียวที่แก้ทั้งหมดพร้อมกัน
หากคอขวดของคุณคือการเปิดไม่ใช่การบันทึก การโหลดแบบเลือกคือ lever คู่มือของ การโหลดเฉพาะเมตาดาต้าและเลือกเฉพาะเวิร์กชีต ครอบคลุมการอ่านเวิร์กบุ๊กโดยไม่จ่ายสำหรับชีตที่คุณจะไม่แตะ สำหรับ throughput เส้นทางอ่านบนไฟล์ขนาดใหญ่มาก ดูบันทึกของ การ parse XLSX แบบขนานและตัวจัดสรรหน่วยความจำ และสำหรับเวิร์กโหลดเฉพาะเอาต์พุตที่ไม่เคยต้องการ object model เลย การเขียนแบบสตรีมสำหรับชุดงานเซิร์ฟเวอร์ มักเหมาะสมกว่าการปรับแต่งใด ๆ ที่นี่
HotXLS อ่านและเขียน XLS และ XLSX จากโค้ด Delphi และ C++Builder พื้นเมืองโดยไม่ติดตั้ง Excel และไม่มี OLE automation ซึ่งเป็นสิ่งที่ทำให้คุณลักษณะหน่วยความจำเหล่านี้สังเกตและควบคุมได้ตั้งแต่แรก — หน้าคอมโพเนนต์สเปรดชีต HotXLS จัดประเภทรูปแบบและเวอร์ชัน RAD Studio ที่รองรับ