Articolo tecnico

HotXLS Component: large workbook performance in Delphi

Crea, modifica, ispeziona, calcola ed esporta cartelle di lavoro Excel direttamente da Delphi o C++Builder. HotXLS e una libreria nativa Object Pascal per XLS e XLSX, progettata per strumenti desktop, batch, report e generazione documenti senza automazione Microsoft Excel.

Questo articolo è rivolto a teams generating or processing large XLS/XLSX workbooks in desktop utilities, services, or batch jobs. Tratta large workbook performance come ingegneria documentale di produzione, non come una semplice chiamata al componente.

Il rischio pratico è che large-workbook workflows fail when shared strings, styles, formulas, memory buffers, and output streams are not managed as production resources. Per questo il flusso richiede un contratto scritto, diagnostica osservabile e file di regressione realistici.

Decisioni architetturali

Plan memory, styles, and streaming together. maximum row count, column count, sheet count, and output file size / shared-string strategy, style reuse, formula volume, and image policy

  • maximum row count, column count, sheet count, and output file size
  • shared-string strategy, style reuse, formula volume, and image policy
  • streaming write boundaries, temporary storage, progress, and cancellation
  • Excel compatibility limits and downstream import limits

Percorso di implementazione

Measure workbook size during generation. The order below keeps the workflow reviewable for Delphi and C++Builder teams.

  1. create capacity fixtures that represent real customer data distribution
  2. reuse styles and strings instead of generating unique resources per cell
  3. write rows in controlled batches and flush output only at safe boundaries
  4. track memory, elapsed time, file size, and warning counts per stage
  5. open large output with the target application before increasing limits

Evidenze di validazione

Performance evidence for capacity planning. Keep these fields with the output or support record.

  • row count, column count, sheet count, style count, shared-string count, and file size
  • memory peak, elapsed time, batch size, temporary storage, and cancellation result
  • formula count, image count, comment count, and relationship count
  • target Excel or importer open time for representative output

Rows are not the only scale factor

Workbook size grows with cells, styles, shared strings, formulas, images, comments, and relationships. A performance plan should reduce redundant resources and choose streaming only where it fits the output contract.

Note di implementazione per la produzione

Tratta HotXLS Component: large workbook performance in Delphi come un contratto di servizio esplicito attorno alle chiamate HotXLS, separando validazione dell'input, scrittura della cartella, controllo dell'output ed evidenze di supporto

  • Definire origine dati, intervalli di celle e formato di output prima di creare la cartella
  • Registrare righe, fogli, avvisi e percorso di output in una prova verificabile
  • Incapsulare i dettagli applicativi in helper testabili invece che in eventi UI
  • Riaprire o ispezionare il file salvato prima di consegnarlo a un altro sistema o al cliente

Casi di errore da provare

  • Un SaveAs riuscito non prova che il contratto di business sia corretto
  • Font, permessi e impostazioni locali possono variare tra server e macchina di sviluppo
  • I log non devono esporre password, dati cliente o link interni

Esempio Delphi dettagliato

L'esempio Delphi seguente mostra un confine di servizio pratico per questo tema, mantenendo policy, logging e validazione in un livello testabile

procedure WriteLargeLedgerWorkbook(const OutputFile: string; const Source: ILedgerReader);
var
  Wb: TXLSXWorkbook;
  Sh: IXLSWorksheet;
  RowIndex: Integer;
  Batch: TArray<TLedgerRow>;
  Item: TLedgerRow;
  Metrics: TWorkbookMetrics;
begin
  Wb := TXLSXWorkbook.Create;
  try
    Sh := Wb.Sheets[0];
    Sh.Name := 'Ledger';
    WriteHeaderRow(Sh, ['Account', 'Date', 'Description', 'Debit', 'Credit', 'Balance']);
    RowIndex := 2;
    Metrics := StartWorkbookMetrics('large-ledger');

    repeat
      Batch := Source.ReadNextBatch(5000);
      for Item in Batch do
      begin
        WriteLedgerRow(Sh, RowIndex, Item);
        Inc(RowIndex);
      end;
      CheckMemoryAndTempQuota(Metrics, RowIndex - 2);
      FlushProgressMetric(Metrics, RowIndex - 2);
    until Length(Batch) = 0;

    Sh.Range['A1:F1'].ApplyBuiltinStyle(xbsTitle);
    AddSummarySheet(Wb, Metrics, RowIndex - 2);
    AssertWorkbookSizePolicy(OutputFile, RowIndex - 2);

    if Wb.SaveAs(OutputFile) <> 1 then
      RaiseWorkbookSaveError(OutputFile);
  finally
    Wb.Free;
  end;
end;

Checklist di produzione

  • Run the workflow on an empty workbook, a normal customer workbook, and a worst-case workbook
  • Open the output with the target spreadsheet application or downstream importer
  • Log product version, template version, profile, row count, output path, elapsed time, and warning count
  • Keep passwords, temporary files, customer data, and support bundles under explicit retention rules
  • Add regression workbooks when a customer file exposes a new edge case

Product documentation

HotXLS Component

Esempi di codice aggiuntivi

// hoist pool lookups out of the hot loop
HeaderFont := Book.Fonts.Add('Calibri', 11, True, False);   // 0-based pool index
for C := 1 to 24 do
  Sheet.Cells[1, C].FontIndex := HeaderFont + 1;            // cells store 1-based; 0 = default
procedure TLedgerExport.FillRow(Sender: TObject;
  SheetIndex, Row, FirstCol, LastCol: Integer;
  var Values: Variant; var Skip: Boolean; var Cancel: Boolean);
begin
  if Row > FCount then
  begin
    Cancel := True;     // stop the whole write
    Exit;
  end;
  Values := VarArrayOf([FRows[Row - 1].Account,
                        FRows[Row - 1].PostedOn,
                        FRows[Row - 1].Amount]);
end;

// one engine call instead of hundreds of thousands of property hits
Sheet.WriteRows(1, 1, FCount, 3, FillRow);
Names := TStringList.Create;
Book := TXLSXWorkbook.Create;
try
  if Book.GetSheetNames('big-unknown.xlsx', Names) <= 0 then
    raise Exception.Create('cannot enumerate sheets');   // failure clears the list
  // pick the target sheet, then decide whether a full Open is worth it
finally
  Book.Free;
  Names.Free;
end;