Article technique

Écriture en streaming et tâches par lot serveur avec HotXLS

Cet article français présente Écriture en streaming et tâches par lot serveur avec HotXLS pour les équipes qui construisent des solutions avec Delphi, C++Builder, Lazarus/FPC et les composants losLab

L'accent est mis sur les choix pratiques, les pièges et les points de contrôle afin que la solution reste fiable en production

Décisions d'architecture

Traitez chaque classeur comme un job isolé : identifiant du job, destination de sortie, politique de reprise, délai d'attente et d'annulation, emplacement des fichiers temporaires, nettoyage, quota et rétention des classeurs en échec

  • job identifier, output destination, retry policy, timeout, and cancellation behavior
  • temporary file location, cleanup, quota, and retention for failed workbooks
  • batch size, concurrency level, progress reporting, and back-pressure
  • which validation can run before final upload or delivery

Parcours d'implémentation

N'écrivez en streaming qu'une fois les points de contrôle de validation définis. L'ordre ci-dessous garde le flux lisible pour les équipes Delphi et C++Builder

  1. assign a job identifier and output boundary before opening the workbook writer
  2. prepare styles, sheets, and headers before streaming row data
  3. write rows in batches and checkpoint progress for operators
  4. validate size, sheet count, row count, and key formulas before final delivery
  5. clean or retain temporary files according to success, cancellation, or failure

Preuves de validation

Preuves de lot pour les opérateurs. Conservez ces champs avec la sortie ou le dossier de support

  • job identifier, batch item count, row count, output size, elapsed time, and memory peak
  • stage timings for data load, workbook write, validation, save, and upload
  • temporary path, cleanup status, retry count, and cancellation reason
  • operator-facing failure reason and whether retry is safe

Streaming is a resource policy

L'écriture en streaming aide à faire passer la génération de classeurs à l'échelle, mais elle limite aussi les parties du classeur que l'on peut revoir plus tard. La conception du job doit décider ce qu'il faut connaître avant le début du streaming

Notes d'implémentation en production

Traitez l'écriture en streaming et les tâches serveur par lot avec HotXLS comme un contrat de service explicite autour des appels HotXLS, en séparant validation d'entrée, écriture du classeur, contrôle de sortie et preuves de support

  • Définir la source de données, les plages de cellules et le format de sortie avant de créer le classeur
  • Consigner le nombre de lignes, les feuilles, les avertissements et le chemin de sortie dans une trace relisible
  • Encapsuler les détails applicatifs dans des helpers testables plutôt que dans des événements UI
  • Rouvrir ou inspecter le fichier enregistré avant livraison à un autre système ou au client

Défaillances à répéter en test

  • Un SaveAs réussi ne prouve pas que le contrat métier est respecté
  • Polices, droits et paramètres régionaux peuvent différer entre serveur et poste de développement
  • Les journaux ne doivent exposer ni mots de passe, ni données client, ni liens internes

Exemple Delphi détaillé

L'exemple Delphi suivant montre une frontière de service pratique pour ce sujet, avec politiques, journalisation et validation dans une couche testable

procedure RunWorkbookBatch(const Jobs: TArray<TWorkbookJob>);
var
  Job: TWorkbookJob;
  JobResult: TWorkbookJobResult;
begin
  for Job in Jobs do
  begin
    StartJobAudit(Job.Id, Job.OutputFile);
    try
      RequireWritableDestination(Job.OutputFile);
      RequireTempQuota(Job.TempFolder, Job.ExpectedRows);
      JobResult := WriteWorkbookJob(Job);
      ValidateWorkbookForDelivery(JobResult.OutputFile, JobResult.ExpectedRows);
      CompleteJobAudit(Job.Id, JobResult);
    except
      on E: Exception do
      begin
        MarkJobFailed(Job.Id, E.Message, CanRetryWorkbookJob(Job));
        CleanupOrRetainTempFiles(Job, E);
        raise;
      end;
    end;
  end;
end;

function WriteWorkbookJob(const Job: TWorkbookJob): TWorkbookJobResult;
var
  Wb: TXLSXWorkbook;
  Sh: IXLSWorksheet;
begin
  Wb := TXLSXWorkbook.Create;
  try
    Sh := Wb.Sheets[0];
    Sh.Name := 'Batch Output';
    StreamRowsIntoWorksheet(Sh, Job.Reader, Job.Progress);
    WriteBatchMetricsSheet(Wb, Job);
    if Wb.SaveAs(Job.OutputFile) <> 1 then
      RaiseWorkbookSaveError(Job.OutputFile);
    Result := BuildWorkbookJobResult(Job);
  finally
    Wb.Free;
  end;
end;

Liste de mise en production

  • 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

Documentation produit

Composant HotXLS

Exemples de code supplémentaires

procedure TBulkExporter.FillRow(Sender: TObject; SheetIndex, Row, FirstCol,
  LastCol: Integer; var Values: Variant; var Skip: Boolean;
  var Cancel: Boolean);
begin
  if not FReader.Next then
  begin
    Cancel := True;              // data source drained: stop cleanly
    Exit;
  end;
  Values := VarArrayCreate([FirstCol, LastCol], varVariant);
  Values[FirstCol]     := FReader.RecordId;
  Values[FirstCol + 1] := FReader.CustomerName;
  Values[FirstCol + 2] := FReader.Amount;
end;

// fill rows 2..100001, columns A..C, pulling from the reader
Sheet.WriteRows(2, 1, 100001, 3, FillRow);
for FileName in SourceFiles do
begin
  Book := TXLSXWorkbook.Create;        // fresh instance: no state bleed
  try
    Book.StreamingWrite := True;
    if Book.Open(FileName) <> 1 then
      Continue;                        // one bad input must not kill the batch
    Book.SaveAsCSV(ChangeFileExt(FileName, '.csv'), 0, ',');
  finally
    Book.Free;
  end;
end;