Gere uma pasta de trabalho a partir do Delphi, anote uma célula com a API de comentário clássica, e o Excel 365 arquivará seu texto sob Notas: uma caixa amarela de estilo antigo sem campo de Resposta, sem avatar do autor, sem botão de resolução. O HotXLS grava comentários em thread genuínos do Excel 365 por meio de AddThreadedComment e AddThreadedReply no mecanismo XLSX, emitindo a parte dedicada xl/threadedComments/threadedCommentN.xml por planilha e registrando cada autor na parte person em nível de pasta de trabalho, de modo que a conversa gravada pelo seu código seja o mesmo objeto ao qual um revisor responde no Excel
A distinção importa porque os dois recursos apenas se parecem. Uma nota é uma caixa de texto flutuante; um comentário em thread é um registro de conversa com identificadores estáveis, uma árvore de respostas, um registro de autor e uma sinalização de resolvido — as coisas sobre as quais um fluxo de trabalho de revisão realmente é executado. Este artigo percorre a estrutura do OOXML primeiro, pois uma vez que você veja os dois modelos de armazenamento lado a lado, cada diferença de comportamento no Excel deixa de ser misteriosa
Por que meus comentários aparecem como notas no Excel 365?
A resposta curta: duas gerações de comentários compartilham uma grade, e elas residem em partes inteiramente diferentes do pacote. O modelo herdado — o qual o AddComment visa — armazena o texto em xl/comments1.xml (tipo de conteúdo application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml) e posiciona o balão por meio de uma parte de desenho VML complementar, xl/drawings/vmlDrawing1.vml. Esse par antecede a faixa de opções; o Excel 365 ainda o lê fielmente, mas renderiza o resultado como uma "nota" e não oferece interface de usuário de thread para ele, porque não há nada no armazenamento para encadear. O autor é uma string de exibição, a posição é uma forma VML, e esse é o modelo completo
Os comentários em thread, introduzidos com o Excel 365, ignoram completamente a camada VML. Cada planilha com uma conversa carrega sua própria parte xl/threadedComments/threadedCommentN.xml sob o tipo de conteúdo application/vnd.openxmlformats-officedocument.spreadsheetml.threadedComments+xml, e a pasta de trabalho carrega uma única parte xl/person/person.xml (tipo de conteúdo ...spreadsheetml.people+xml) listando cada participante uma vez. O HotXLS expõe ambos os modelos na mesma planilha: o AddComment continua gravando o par herdado, e o AddThreadedComment grava as novas partes. Se a sua saída aparecer como notas, você chamou a primeira API quando queria a segunda. O modelo herdado ainda é a ferramenta certa para algumas tarefas — o artigo anterior sobre comentários de célula e hiperlinks em fluxos de trabalho de revisão o aborda em detalhes, incluindo o lado do XLS —, mas nada nele é atualizado para uma thread
O que o HotXLS grava no pacote
O HotXLS modela cada resposta como um objeto TXLSXThreadedComment contendo uma âncora de célula (Ref), um identificador de estilo GUID (Id), um ParentId opcional, um AuthorId que se resolve através da lista person, um espelho DisplayName, o corpo do texto, uma sinalização Done e uma data e hora ISO-8601 DateTime. Ao salvar, cada entrada se torna um elemento <threadedComment> cujo atributo t contém o identificador, cujo atributo dT contém o carimbo de data/hora e cujo atributo parentT — presente apenas nas respostas filhas — nomeia o identificador pai. O Excel reconstrói a árvore de conversas combinando parentT com t; não há aninhamento no XML, apenas uma lista simples mais referências
A parte person é a peça que a maioria das implementações manuais esquece. Cada authorId em um comentário em thread deve se resolver para uma entrada <person> em xl/person/person.xml, vinculada aos relacionamentos da pasta de trabalho, com sua própria substituição de tipo de conteúdo — caso contrário, o Excel não terá um nome de exibição para mostrar. O HotXLS lida com o registro automaticamente: o AddThreadedComment procura o autor na lista Persons da pasta de trabalho pelo nome de exibição e cria uma entrada com um GUID novo se nenhuma existir, de modo que comentários consecutivos do mesmo autor compartilhem uma única identidade. Os relacionamentos da planilha recebem o relacionamento threadedComments, los relacionamentos da pasta de trabalho recebem o relacionamento person, e o manifesto de tipos de conteúdo recebe ambas as substituições, sem que nada disso apareça no seu código
Construindo uma cadeia de respostas com AddThreadedComment e AddThreadedReply
Building a reply chain with AddThreadedComment and AddThreadedReply
O AddThreadedComment cria a raiz da conversa: seu ParentId permanece vazio, que é o que o marca como o topo da thread. O AddThreadedReply recebe um parâmetro ParentRef — a referência da célula onde reside a raiz —, localiza a raiz nessa âncora e carimba o ParentId da nova resposta com o Id da raiz. Ambos retornam o novo TXLSXThreadedComment, de modo que você possa definir o carimbo de data/hora ou o estado resolvido no objeto que acabou de criar:
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Root: TXLSXThreadedComment;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('forecast.xlsx');
Sheet := Book.Sheets[0];
// Conversation root; ParentId stays empty
Root := Sheet.AddThreadedComment(8, 3,
'Q3 figure looks low against the pipeline export', 'Maria Ortiz');
Root.DateTime := '2026-07-06T09:12:00Z';
// Replies anchor at the same cell; ParentRef names the root cell
Sheet.AddThreadedReply(8, 3, Root.Ref,
'Pipeline export missed the EMEA renewals, re-running', 'Jan Kowalski');
Sheet.AddThreadedReply(8, 3, Root.Ref,
'Confirmed, refreshed figure lands tomorrow', 'Maria Ortiz');
Book.SaveAs('forecast-reviewed.xlsx');
finally
Book.Free;
end;
end;
Dois detalhes nessa listagem merecem atenção. Primeiro, Root.Ref é passado em vez de uma string construída manualmente: a referência que a biblioteca gerou garante corresponder ao que o AddThreadedReply procurará, o que remove toda uma classe de bugs de âncora com desvio de um (off-by-one). Segundo, ambos os autores foram passados como nomes de exibição simples — o registro de pessoas, as identidades GUID e a fiação do authorId ocorreram nos bastidores das chamadas. Abra o arquivo salvo no Excel 365 e a ancoragem de células, a ordem de resposta e os dois participantes distintos estarão ativos: clique em Responder e o Excel acrescentará na mesma thread iniciada pelo seu código
Lendo uma conversa de volta: comportamento de ida e volta (round-trip)
O HotXLS realiza a ida e volta de comentários em thread a partir da versão 2.122.0: reabrir um pacote salvo reconstrói a lista de conversas de cada planilha e a lista de participantes da pasta de trabalho a partir das partes, portanto, identificadores, links de resposta e nomes de exibição sobrevivem a um ciclo completo de leitura→gravação. O leitor analisa o person.xml antes de qualquer conteúdo da planilha, que é o que permite que cada authorId se resolva para um nome de exibição no momento do carregamento; os identificadores de pessoa analisados são preservados como estão, em vez de serem regenerados, de modo que uma pasta de trabalho que transita entre seu código e o Excel mantém identidades estáveis de autor ao longo de quantas idas e voltas forem necessárias
var
i: Integer;
Cmt: TXLSXThreadedComment;
begin
Book.Open('forecast-reviewed.xlsx');
Sheet := Book.Sheets[0];
for i := 0 to Sheet.ThreadedComments.Count - 1 do
begin
Cmt := Sheet.ThreadedComments[i];
if Cmt.ParentId = '' then
Writeln('Root at ', Cmt.Ref, ' by ', Cmt.DisplayName, ': ', Cmt.Text)
else
Writeln(' reply by ', Cmt.DisplayName, ': ', Cmt.Text);
end;
Writeln('Participants: ', Book.Persons.Count);
end;
O armazenamento em formato de lista simples mais referências transparece aqui deliberadamente: o ThreadedComments enumera as respostas na ordem das partes, e um ParentId vazio identifica cada raiz. Se você precisar do formato de árvore — por exemplo, para exportar um log de revisão —, agrupe por Ref primeiro e, em seguida, encadeie o ParentId ao Id dentro do grupo de cada célula. Esse comportamento de preservar o que foi analisado é um exemplo de uma política mais ampla na biblioteca; o artigo sobre ida e volta sem perdas de temas, listas de extensões e cadeia de cálculo aborda como o mesmo princípio se aplica ao restante do pacote
Estado resolvido, carimbos de data/hora e identidade do autor
Três atributos carregam a semântica de revisão, e todos os três são graváveis nos objetos retornados. Done mapeia para o atributo done — o Excel mostra uma thread resolvida recolhida com um link Reabrir. DateTime é o carimbo de data/hora de criação UTC ISO-8601 (dT); o HotXLS substitui por um marcador de posição fixo quando você o deixa vazio para que a parte sempre seja validada, mas um carimbo de data/hora real é o que torna o histórico da thread legível, portanto, defina-o. No lado da identidade, cada TXLSXPerson expõe ProviderId — normalmente None para entradas criadas localmente — e um UserId que você pode preencher com um UPN ou e-mail quando seu aplicativo o conhecer:
var
Root: TXLSXThreadedComment;
Person: TXLSXPerson;
begin
Root := Sheet.ThreadedComments.FindAt('D9');
if Root <> nil then
Root.Done := True; // saved as done="1"; Excel shows the thread resolved
Person := Book.Persons.FindByDisplayName('Maria Ortiz');
if Person <> nil then
Person.UserId := 'maria.ortiz@example.com';
end;
```
Um limite a ser declarado claramente: o HotXLS grava o elemento <mentions> vazio. Registros de menção @ (arroba) — o mecanismo que ilumina o nome de um colega dentro do texto do comentário e aciona uma notificação no Microsoft 365 — não são modelados, de modo que o texto contendo um sinal @ é armazenado como texto simples. Para uma pasta de trabalho de revisão gerada, isso raramente é uma perda, mas se o seu fluxo de trabalho depende de notificações de menção, planeje para que um humano as adicione dentro do Excel. A identidade do autor na parte person emparelha-se naturalmente com os campos de proveniência no nível de pasta de trabalho abordados em metadados da pasta de trabalho e propriedades do documento, que é onde reside o restante da trilha de auditoria de um arquivo gerado
O que as versões mais antigas do Excel fazem com os comentários em thread?
O Excel 2016 e versões anteriores antecedem o modelo em thread e simplesmente ignoram as partes que não compreendem. Quando o próprio Excel 365 salva uma conversa em thread, ele também grava uma sombra de comentário herdada — uma nota marcadora de posição que diz "[Comentário em thread]..." —, precisamente para que as versões mais antigas mostrem algo na célula ancorada. O HotXLS emite apenas as partes em thread, sem sombra herdada, portanto, um arquivo gravado por seu código não exibe nenhum indicador de comentário ao ser aberto no Excel 2016. Se o seu público inclui instalações anteriores ao 365 e a anotação deve ser visível nelas, la API herdada AddComment continua sendo o canal compatível; apenas evite empilhar ambos os modelos na mesma célula sem testar cada versão do Excel para a qual você envia, porque a forma como um leitor reconcilia uma nota e uma thread em uma única célula é decisão do leitor, não sua
O outro limite rígido é o próprio formato do arquivo. Os comentários em thread são uma estrutura OOXML sem contrapartida BIFF8, portanto o lado .xls do HotXLS não possui uma API de thread — uma pasta de trabalho que deve permanecer no formato binário herdado é limitada a notas clássicas. Na prática, a tabela de decisões é curta: ao gravar .xlsx para o Excel 365 ou leitores do Excel na web/dispositivos móveis, use AddThreadedComment e obtenha conversas reais; ao visar o Excel 2016 ou .xls, use AddComment e aceite o modelo de nota; ao auditar um arquivo recebido, verifique tanto ThreadedComments quanto Comments, pois uma pasta de trabalho que viveu em ambos os mundos pode legitimamente carregar ambos. Toda a superfície da API para ambas as gerações está documentada na página do produto Componente Excel Delphi HotXLS