O HotXLS armazena células de planilha em blocos compactos de 256 linhas, resolve formatação de linha, coluna e retângulo por meio de sobreposições preguiçosas de intervalo em vez de criar objetos de célula, e faz streaming de cada linha direto no stream deflate do pacote ao salvar. Juntas essas três mudanças decidem o perfil de memória de uma pasta de trabalho grande: o pico de uso segue a maior linha única em vez do tamanho do XML completo da planilha
O motivo pelo qual isso importa é uma forma que todo desenvolvedor de planilha encontra mais cedo ou mais tarde. Um usuário formata uma coluna inteira — um clique, um milhão de células — e um modelo de objetos ingênuo responde alocando um milhão de objetos de célula para segurar um índice de formato numérico. O arquivo no disco continua minúsculo porque o formato XLSX expressa isso como uma única entrada <col>. O processo de forma nenhuma continua minúsculo
Por que formatar uma coluna custa mais memória do que preenchê-la?
Porque formatação não tem dados para justificar o objeto. Uma célula com um valor precisa existir em algum lugar. Uma célula que está vazia mas estilizada existe apenas para carregar um índice de estilo, e materializar milhões dessas é o jeito clássico de uma aplicação de planilha em Delphi ficar sem espaço de endereçamento em um arquivo que o Excel abre instantaneamente
Sobreposições de estilo por intervalo removem a necessidade. Uma instrução de formatação de linha, coluna ou retângulo é armazenada uma vez como um intervalo mais as partes de estilo que ela contribui, e resolve preguiçosamente quando uma célula naquele intervalo é de fato acessada. Sobreposições sobrevivem a edições estruturais — inserir uma linha dentro de um bloco formatado move o intervalo em vez de reconstruí-lo — e fazem ida e volta como entradas compactas de coluna, linha e célula somente estilo, que é exatamente como o Excel as escreve
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 é o conjunto que decide o que uma sobreposição contribui: xfpFont, xfpFill, xfpBorder, xfpNumberFormat, xfpAlignment e xfpProtection. Nomear apenas as partes que você quer dizer é o que permite que sobreposições se acumulem de forma sensata — uma sobreposição de coluna que fornece um formato numérico não briga com uma sobreposição de linha que fornece um preenchimento, porque nenhuma reivindica a parte da outra
O que o bloco de 256 linhas dá a você
Localidade. Células são mantidas em blocos de 256 linhas com handles públicos estáveis, serializadas em ordem de linha, então escrever uma planilha percorre memória na ordem em que vai emitir bytes em vez de perseguir ponteiros pelo heap. Handles estáveis importam para a superfície da API: um handle que um chamador segura segue válido através da reorganização interna que o layout de bloco realiza, que é o que torna a representação compacta um detalhe de implementação em vez de uma mudança quebradora
A compactação do pool de estilos roda junto. Antes de cada salvamento, fontes, preenchimentos, bordas, formatos numéricos, alinhamentos e proteções que nenhuma célula referencia são descartados. Pastas de trabalho de longa vida acumulam registros de estilo sem referência do mesmo jeito que documentos de longa vida acumulam estilos sem uso, e uma pasta de trabalho editada por um usuário durante uma hora pode carregar centenas deles para um arquivo de onde ninguém nunca vai lê-los
Salvamento com streaming de linhas, e quando ele não se aplica
Com StreamingWrite habilitado — o padrão — cada linha da planilha é escrita diretamente no stream deflate do pacote. A alternativa, que é o que o flag desliga, constrói o XML completo da planilha primeiro e o comprime depois, então a memória de pico escala com a planilha inteira. Streaming faz escalar com uma linha
Strings compartilhadas e partes auxiliares seguem a mesma disciplina por meio de um serializador UTF-8 reutilizável que emite entradas uma de cada vez, limitando a memória de pico pela maior entrada única em vez da parte inteira. Isso cobre a tabela de strings compartilhadas e registros de tabela dinâmica, que numa pasta de trabalho analítica ampla costumam ser maiores do que qualquer planilha individual
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;
Deixe ligado a menos que você tenha um motivo concreto para não. O caminho sem streaming existe para os casos em que outra coisa no pipeline precisa do XML montado, e pagar por isso por padrão é pagar por um caso que a maioria das aplicações nunca atinge
Como dizer se sobreposições estão de fato em uso
Observe a contagem de células, não o gráfico de memória. Se uma planilha relata um número plausível de células físicas depois que você aplicou formatação ampla, as sobreposições estão fazendo seu trabalho. Se a contagem pula pelo tamanho do intervalo formatado, algo no caminho de código materializou as células — geralmente um loop que lê cada célula do intervalo para conferir seu estilo, o que força resolução uma célula por vez e derrota todo o arranjo
Resolva um estilo quando você precisa do formato efetivo de uma célula. Não resolva um estilo para um milhão de células para descobrir que a coluna tem um formato numérico; pergunte à sobreposição. A mesma regra se aplica a escrita: atribua valores às células que têm valores, e deixe formatação seguir como intervalo
Para onde vai a memória restante
Depois que células e estilos estão compactos, os maiores consumidores seguintes numa pasta de trabalho grande são a tabela de strings compartilhadas e qualquer parte satélite que o arquivo carregue — caches dinâmicos, drawings, XML preservado de partes que o modelo de objetos não modela. Esses têm suas próprias estratégias, e a resposta honesta é que nenhuma configuração única resolve todos de uma vez
Se o seu gargalo é abrir em vez de salvar, o carregamento seletivo é a alavanca: o guia sobre carregamento de planilha somente metadados e seletivo cobre ler uma pasta de trabalho sem pagar pelas planilhas que você não vai tocar. Para throughput de leitura em arquivos muito grandes, veja as notas sobre análise paralela de XLSX e o alocador de memória, e para cargas somente de saída que nunca precisam de um modelo de objetos de forma nenhuma, escrita em streaming para jobs em lote no servidor costuma ser um encaixe melhor do que qualquer ajuste aqui
O HotXLS lê e escreve XLS e XLSX a partir de código nativo em Delphi e C++Builder sem instalação do Excel e sem automação OLE, que é o que torna essas características de memória observáveis e controláveis em primeiro lugar — a página do componente de planilha HotXLS lista os formatos e versões do RAD Studio suportados