O HotXLS mantém o ChartML original de um gráfico de Excel importado e reprodu-lo byte a byte quando nada no modelo com tipo mudou, pelo que abrir e regravar um livro não remove silenciosamente as partes de um gráfico que o modelo de objetos não representa. Edite um título, uma série ou um eixo e o HotXLS funde estruturalmente os novos nós com tipo na árvore original em vez de regenerar o gráfico de raiz
Essa distinção — reproduzir quando intacto, fundir quando editado — é o que torna uma aplicação Delphi segura para apontar a gráficos que um analista construiu no Excel. Regenerar um gráfico a partir de um modelo com tipo perde sempre o que o modelo não conhece, e os gráficos do Excel estão cheios de coisas que uma biblioteca não conhece: estilos personalizados, listas de extensão, ramos de conteúdo alternativo, formatação qualificada por espaço de nomes de add-ins
Porque razão é que regravar um livro apanha os seus gráficos?
Porque a implementação habitual lê o que percebe e escreve o que percebe. Tudo o que está pelo meio — um extLst de uma versão mais recente do Excel, um ramo mc:AlternateContent, um efeito de forma para o qual o modelo não tem propriedade — existe no ficheiro, não tem casa no modelo de objetos, e desaparece na gravação. O utilizador vê um gráfico que perdeu o seu gradiente, as suas etiquetas de dados personalizadas ou o seu efeito 3D, e o livro não consegue explicar porquê
Com PreserveUnsupportedParts ativado no livro, o HotXLS armazena os bytes UTF-8 originais do gráfico na importação juntamente com um comprimento e uma impressão digital de 64 bits do conteúdo modelado. Se o modelo com tipo não tiver mudado pela hora de gravação, escreve os bytes originais de volta. Sem reordenação de XML, sem desvio de espaços em branco, sem cópia UTF-16 residente do gráfico pendurada na memória para um gráfico que ninguém editou
var
Workbook: TXLSXWorkbook;
Chart: TXLSXChart;
begin
Workbook := TXLSXWorkbook.Create(nil);
try
Workbook.PreserveUnsupportedParts := True; // set before Open
Workbook.Open('quarterly-review.xlsx');
Chart := Workbook.Sheets[1].Charts[0]; // Sheets[] is 1-based
if Chart.HasPreservedXml then
Log('original ChartML retained; untouched charts replay exactly');
Chart.Title := 'Revenue by region, Q3 2026'; // now the merge path runs
Workbook.SaveAs('quarterly-review-out.xlsx');
finally
Workbook.Free;
end;
end;
O que a fusão mantém e o que o modelo é dono
A regra é propriedade. Os nós públicos do modelo — título, séries, caches, grupos de plotagem, eixos — são decididos pela árvore recém-gerada. As subárvores não modeladas são transportadas a partir da original. Essa assimetria é deliberada, e é a parte que demora um momento a interiorizar: apagar uma série não pode ressuscitar a série antiga do XML preservado, pelo que tudo o que o modelo é dono é tirado do modelo mesmo quando o modelo diz "fora"
O conteúdo sem dono é reinserido ao lado dos nós correspondentes junto aos quais estava, e extLst mantém-se último dentro do seu pai porque é aí que o esquema o exige. Limpar uma propriedade conhecida — remover um sinalizador de negrito, dropar uma cor — é tratado como uma limpeza, não como uma lacuna a preencher a partir da árvore original. Atributos desconhecidos na mesma vizinhança mantêm o seu lugar
O conteúdo de compatibilidade de marcação recebe tratamento específico. Na análise, o HotXLS salta mc:Choice e lê mc:Fallback; se esse ramo de recurso envolver um grupo de plotagem que o modelo conhece, a fusão escreve o novo conteúdo com tipo de volta na subárvore de recurso. Sem esse passo, uma gravação emitiria o novo grupo de plotagem e deixaria o antigo dentro do recurso, e o gráfico transportaria dois
Excluir um gráfico
ClearPreservedXml descarta o XML original e a impressão digital de um gráfico, pelo que a próxima gravação reconstrói esse gráfico puramente a partir do modelo com tipo. É uma decisão por gráfico; o PreserveUnsupportedParts ao nível do livro continua a reger se o estado de preservação é construído na importação
Recorra a isso quando quer um gráfico limpo em vez de um fiel — por exemplo quando um gráfico de modelo transporta formatação de um tema corporativo antigo e o ponto da operação é descartá-la. Não recorra a isso como um reflexo de depuração: um gráfico que renderiza errado depois de uma edição é mais frequentemente uma questão de modelação do que uma questão de preservação, e limpar o XML preservado destrói a evidência
Gráficos de combinação e o segundo eixo
AddPlotGroup constrói gráficos de combinação ordenados, em que cada grupo de plotagem mantém a sua própria família de gráfico e a sua própria atribuição de eixo primário ou secundário. É o que o gráfico de negócio onipresente precisa: receita como colunas no eixo esquerdo, margem percentual como linha no direito
Os gráficos expõem eixos de categoria e de valor primários e secundários mais um eixo de séries, com definições de categoria, valor, data e eixo de séries com tipo a cobrir posições, identificadores, cruzamentos, unidades de data, intervalos de etiqueta e visibilidade. A API plana antiga — ChartType, AddSeries, a coleção plana Series — continua a endereçar o grupo de plotagem primário, pelo que código existente continua a funcionar enquanto o modelo por baixo detém todos os grupos ordenados
var
Chart: TXLSXChart;
Line: TXLSXChartPlotGroup;
begin
// Column chart anchored over rows 1..15, columns 5..12
Chart := Sheet.Charts.Add(xlsxChartColumn, 'Revenue and margin',
1, 5, 15, 12);
Chart.AddSeries('Revenue', 'Data!$A$2:$A$13', 'Data!$B$2:$B$13');
// Second plot group: a line, read against the secondary value axis
Line := Chart.AddPlotGroup(xlsxChartLine, xlsxAxisSecondary);
Line.AddSeries('Margin %', 'Data!$A$2:$A$13', 'Data!$C$2:$C$13');
end;
Antes deste modelo existir, abrir e regravar um gráfico de combinação colapsava-o numa única família de gráfico e perdia os eixos secundário, de data e de séries. As referências de fórmulas de gráfico e os valores de séries em cache agora sobrevivem a cópias de livro e ciclos de abrir/gravar também, e as âncoras de gráfico são correspondidas às suas partes de gráfico por identificador de relação — pelo que uma aplicação que reordene entradas de relação já não troca conteúdos de gráfico entre posições de folha de cálculo
A armadilha da disposição manual
Se posicionar uma área de plotagem, título, título de eixo ou legenda à mão, escreva as quatro coordenadas. O Office exige x, y, w e h como um grupo completo sempre que qualquer um deles esteja presente, e ignora o manualLayout inteiro caso contrário. O HotXLS emite sempre o retângulo completo por essa razão, e SetPositionAndSize define-o e ativa-o numa única chamada
Dois detalhes mais seguem o Excel em vez da latitude completa da especificação. A posição é escrita com xMode e yMode definidos como edge enquanto o tamanho usa factor para wMode e hMode, porque é isso que o Excel escreve e no que converte outras combinações. E layoutTarget só é emitido para a área de plotagem, nunca para títulos ou legendas, onde as notas de implementação da Microsoft o proíbem
Encaixar isto numa ida e volta de livro
A preservação de gráficos é uma instância de uma política geral: uma biblioteca que edita documentos criados noutro lado deve mudar o que lhe foi pedido para mudar e nada mais. O mesmo raciocínio conduz o HotXLS em temas, cadeias de cálculo e extensões de folha de cálculo, descrito nas notas sobre idas e voltas sem perdas para tema, extLst e calcChain, e sobre projetos VBA e ligações externas em preservar VBA e ligações externas. Para a superfície de autoria de gráficos em si — criar gráficos, colocar imagens e desenhos a partir de Delphi — veja o guia de gráficos, imagens e desenhos no HotXLS
O HotXLS lê, edita e escreve gráficos XLSX a partir de código nativo Delphi e C++Builder sem qualquer instalação de Excel na máquina, que é o que torna a fidelidade um problema de biblioteca em vez de um problema de automatização — a página do componente de folha de cálculo HotXLS tem a lista de funcionalidades de gráficos e um descarregamento de avaliação