مقاله فنی

ذخیره سلول بلوک ردیفی و ذخیره streaming برای XLSX در HotXLS

HotXLS سلول‌های کاربرگ را در بلوک‌های فشرده 256 ردیفی ذخیره می‌کند، قالب‌بندی ردیف، ستون و مستطیل را از طریق overlayهای بازه‌ای تنبل به‌جای ایجاد اشیاء سلول حل می‌کند، و هر ردیف را هنگام ذخیره مستقیماً در stream deflate بسته streaming می‌کند. با هم آن سه تغییر profile حافظه یک کاربرگ بزرگ را تصمیم می‌گیرند: مصرف اوج از بزرگ‌ترین ردیف واحد پیروی می‌کند نه اندازه XML کامل کاربرگ

دلیل اهمیت این شکل‌ای است که هر توسعه‌دهنده spreadsheet در نهایت ملاقات می‌کند. یک کاربر یک ستون کامل را قالب‌بندی می‌کند — یک کلیک، یک میلیون سلول — و یک مدل شیء ساده‌لوحانه با اختصاص یک میلیون شیء سلول برای نگه‌داری یک اندیس قالب عدد پاسخ می‌دهد. فایل روی دیسک کوچک می‌ماند چون فرمت XLSX آن را به‌عنوان یک entry <col> واحد بیان می‌کند. پردازش اصلاً کوچک نمی‌ماند

چرا قالب‌بندی یک ستون حافظه بیشتری از پر کردنش مصرف می‌کند؟

چون قالب‌بندی هیچ داده‌ای برای توجیه شیء ندارد. یک سلول با مقدار باید جایی وجود داشته باشد. یک سلول که خالی اما سبک‌دار است فقط برای حمل یک اندیس سبک وجود دارد، و مادی کردن میلیون‌ها از آن‌ها روش کلاسیک آن است که یک کاربرد spreadsheet دلفی روی فایلی که Excel فوراً باز می‌کند فضای آدرس را از دست می‌دهد

overlayهای سبک بازه‌ای نیاز را حذف می‌کنند. یک دستور قالب‌بندی ردیف، ستون یا مستطیل یک‌بار به‌عنوان یک بازه به‌اضافه بخش‌های سبکی که عرضه می‌کند ذخیره می‌شود، و وقتی یک سلول در آن بازه واقعاً دسترسی پیدا کرد تنبل حل می‌شود. 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ها اجازه می‌دهد عاقلانه لایه شوند — یک overlay ستون که قالب عدد عرضه می‌کند با یک overlay ردیف که fill عرضه می‌کند نمی‌جنگد، چون هیچ‌کدام دیگری را ادعا نمی‌کند

بلوک 256 ردیفی به شما چه می‌دهد

محلی‌بودن. سلول‌ها در بلوک‌های 256 ردیفی با handle عمومی پایدار نگه‌داری می‌شوند، ردیف-محور سریال می‌شوند، تا نوشتن یک کاربرگ حافظه را به ترتیبی که بایت emit می‌کند پیمایش کند به‌جای تعقیب اشارهگر در سراسر heap. handleهای پایدار برای سطح API مهم‌اند: handleی که یک فراخواننده نگه می‌دارد در سراسر بازسازی درونی که چیدمان بلوک انجام می‌دهد معتبر می‌ماند، که همان چیزی است نمایش فشرده را به یک جزئیات پیاده‌سازی به‌جای یک تغییر شکست‌آور تبدیل می‌کند

فشرده‌سازی pool سبک در کنار آن اجرا می‌شود. قبل از هر ذخیره، فونت‌ها، fillها، حاشیه‌ها، قالب‌های عدد، ترازها و محافظت‌هایی که هیچ سلولی ارجاع نمی‌دهند رها می‌شوند. کاربرگ‌های طولانی‌عمر رکوردهای سبک ارجاع‌نشده همان‌طور انباشته می‌کنند که اسناد طولانی‌عمر سبک‌های استفاده‌نشده انباشته می‌کنند، و کاربردی که یک ساعت توسط یک کاربر ویرایش شده می‌تواند صدها از آن‌ها را به فایلی ببرد که هیچ‌کس هرگز از آن نمی‌خواند

ذخیره row-streaming، و چه زمانی اعمال نمی‌شود

با StreamingWrite روشن — پیش‌فرض — هر ردیف کاربرگ مستقیماً در stream deflate بسته نوشته می‌شود. جایگزین، که همان چیزی است flag خاموش می‌کند، ابتدا XML کامل کاربرگ را می‌سازد و بعد آن را فشرده می‌کند، پس حافظه اوج با کل کاربرگ مقیاس می‌کند. streaming آن را با یک ردیف مقیاس می‌کند

رشته‌های مشترک و partهای کمکی از همان انضباط از طریق یک سریالایزر UTF-8 قابل‌استفاده مجدد پیروی می‌کنند که entryها را یکی‌یکی emit می‌کند، حافظه اوج را با بزرگ‌ترین entry واحد به‌جای کل part محدود می‌کند. این جدول رشته مشترک و recordهای 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;

مگر آن یک دلیل ملموس برای نه داشته باشید روشن بگذاریدش. مسیر غیر streaming برای مواردی وجود دارد که چیز دیگری در pipeline به XML اسمبل‌شده نیاز دارد، و پرداخت برای آن به‌طور پیش‌فرض پرداخت برای موردی است که اکثر کاربردها هرگز با آن مواجه نمی‌شوند

چگونه بفهمید overlayها واقعاً استفاده می‌شوند

شمارش سلول را تماشا کنید، نه نمودار حافظه. اگر یک کاربرگ پس از اعمال قالب‌بندی گسترده شمار قابل‌قبولی از سلول‌های فیزیکی گزارش کند، overlayها کارشان را انجام می‌دهند. اگر شمارش به اندازه بازه قالب‌شده می‌پرد، چیزی در مسیر کد سلول‌ها را مادی کرده — معمولاً یک حلقه که هر سلول در بازه را برای بررسی سبکش می‌خواند، که حل را یک سلول در هر بار واداد می‌کند و کل چیدمان را شکست می‌دهد

یک سبک را وقتی به سبک مؤثر یک سلول نیاز دارید حل کنید. یک سبک را برای یک میلیون سلول حل نکنید تا بفهمید ستون قالب عدد دارد؛ از overlay بپرسید. همان قانون برای نوشتن صدق می‌کند: مقادیر را به سلول‌هایی که مقدار دارند اختصاص دهید، و بگذارید قالب‌بندی یک بازه بماند

بقیه حافظه کجا می‌رود

وقتی سلول‌ها و سبک‌ها فشرده شدند، بزرگ‌ترین مصرف‌کننده‌های بعدی روی یک کاربرگ بزرگ جدول رشته مشترک و هر part ماهواره‌ای است که فایل حمل می‌کند — pivot cacheها، نقاشی‌ها، XML حفظ‌شده از partهایی که مدل شیء مدل نمی‌کند. آن‌ها استراتژی‌های خودشان را دارند، و پاسخ صادقانه این است که هیچ تنظیم واحدی همه آن‌ها را یک‌باره حل نمی‌کند

اگر گلوگاه شما باز کردن است نه ذخیره، بارگذاری انتخابی اهرم است: مرور بارگذاری metadata-only و انتخابی کاربرگ خواندن یک کاربرگ را بدون پرداخت برای برگه‌هایی که لمس نخواهید کرد پوشش می‌دهد. برای throughput مسیر خواندن روی فایل‌های خیلی بزرگ، یادداشت‌های parse موازی XLSX و تخصیص‌دهنده حافظه را ببینید، و برای workloadهای فقط‌خروجی که هرگز به یک مدل شیء نیاز ندارند، نوشتن streaming برای کارهای دسته‌ای سرور معمولاً تناسب بهتری از هر میزان tuning اینجا است

HotXLS فایل‌های XLS و XLSX را از کد بومی Delphi و C++Builder بدون هیچ نصب Excel و بدون اتوماسیون OLE می‌خواند و می‌نویسد، که همان چیزی است این ویژگی‌های حافظه را در درجه اول قابل‌مشاهده و قابل‌کنترل می‌کند — صفحه جزء spreadsheet برای HotXLS فرمت‌های پشتیبانی‌شده و نسخه‌های RAD Studio را فهرست می‌کند