Se generi una cartella di lavoro da Delphi e annoti una cella con la classica API dei commenti, Excel 365 archivia il testo sotto la voce Note: una casella gialla vecchio stile senza campo Rispondi, senza avatar dell'autore e senza pulsante per risolvere. HotXLS scrive veri commenti in thread per Excel 365 tramite i metodi AddThreadedComment e AddThreadedReply sul motore XLSX, esportando la sezione dedicata xl/threadedComments/threadedCommentN.xml per foglio e registrando ogni autore nella sezione person a livello di cartella di lavoro, in modo che la conversazione generata dal tuo codice sia lo stesso oggetto a cui un revisore risponde in Excel
La distinzione è importante perché le due funzionalità sono solo apparentemente simili. Una nota è una casella di testo mobile; un commento in thread è un record di conversazione strutturato con identificatori stabili, un albero di risposte, un registro degli autori e un indicatore di risoluzione — tutti elementi su cui si basa effettivamente un flusso di lavoro di revisione. Questo articolo analizza prima la struttura OOXML, poiché una volta confrontati i due modelli di archiviazione, ogni differenza di comportamento in Excel cessa di essere misteriosa
Perché i miei commenti vengono visualizzati come note in Excel 365?
La risposta breve: due generazioni di commenti condividono la stessa griglia e risiedono in sezioni completamente diverse del pacchetto. Il modello legacy — quello a cui fa riferimento AddComment — memorizza il testo in xl/comments1.xml (tipo di contenuto application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml) e posiziona il fumetto tramite una sezione di disegno VML associata, xl/drawings/vmlDrawing1.vml. Questa coppia è antecedente all'interfaccia a schede (ribbon); Excel 365 continua a leggerla fedelmente, ma visualizza il risultato como una "nota" e non offre alcuna interfaccia per il thread, poiché non vi è alcun elemento nella struttura dati che consenta di collegare le risposte. L'autore è una semplice stringa di testo, la posizione è una forma VML, e questo descrive l'intero modello
I commenti in thread, introdotti con Excel 365, ignorano completamente il livello VML. Ogni foglio contenente una conversazione include la propria sezione xl/threadedComments/threadedCommentN.xml sotto il tipo di contenuto application/vnd.openxmlformats-officedocument.spreadsheetml.threadedComments+xml, e la cartella di lavoro include un'unica sezione xl/person/person.xml (tipo di contenuto ...spreadsheetml.people+xml) che elenca ciascun partecipante una sola volta. HotXLS espone entrambi i modelli sullo stesso foglio di lavoro: AddComment continua a scrivere la coppia legacy, mentre AddThreadedComment genera le nuove sezioni. Se il tuo output viene visualizzato come note, significa che hai utilizzato la prima API anziché la seconda. Il modello legacy rimane lo strumento corretto per determinati scenari — l'articolo precedente su commenti e collegamenti ipertestuali delle celle nei flussi di revisione lo tratta in dettaglio, includendo il lato XLS — ma non supporta l'evoluzione in thread
Cosa scrive HotXLS nel pacchetto
HotXLS modella ciascuna risposta come un oggetto TXLSXThreadedComment contenente un ancoraggio di cella (Ref), un identificatore in stile GUID (Id), un ParentId opzionale, un AuthorId che si risolve tramite l'elenco dei partecipanti, un mirror DisplayName, il corpo del testo, un indicatore Done e un timestamp ISO-8601 DateTime. Al salvataggio, ciascuna voce diventa un elemento <threadedComment> il cui attributo t contiene l'identificatore, l'attributo dT contiene il timestamp e l'attributo parentT attribute — presente solo sulle risposte figlie — indica l'identificatore del genitore. Excel ricostruisce l'albero della conversazione associando parentT a t; non vi è alcun annidamento nell'XML, ma solo un elenco semplice corredato da riferimenti
La sezione person è l'elemento che la maggior parte delle implementazioni manuali trascura. Ogni authorId in un commento in thread deve risolversi in una voce <person> all'interno di xl/person/person.xml, collegata alle relazioni della cartella di lavoro e con il proprio override del tipo di contenuto — altrimenti Excel non avrà alcun nome visualizzato da mostrare. HotXLS gestisce la registrazione automaticamente: AddThreadedComment cerca l'autore nell'elenco Persons della cartella di lavoro tramite il nome visualizzato e crea una voce con un nuovo GUID se non ne esiste alcuna, in modo che commenti consecutivi dello stesso autore condividano un'unica identità. Le relazioni del foglio di lavoro ottengono la relazione threadedComments, quelle della cartella di lavoro ottengono la relazione person, e il manifest dei tipi di contenuto riceve entrambi gli override, senza che sia necessario alcun intervento nel tuo codice
Creare una catena di risposte con AddThreadedComment e AddThreadedReply
AddThreadedComment crea la conversazione root: il suo ParentId rimane vuoto, il che lo definisce come inizio del thread. AddThreadedReply richiede il parametro ParentRef — il riferimento alla cella in cui risiede la radice — in modo da individuare la radice a quell'ancoraggio e contrassegnare il campo ParentId della nuova risposta con l'ID della radice stessa. Entrambe le chiamate restituiscono il nuovo oggetto TXLSXThreadedComment, consentendo di configurare il timestamp o lo stato risolto sulla risposta appena creata:
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;
Due dettagli in questo esempio meritano attenzione. In primo luogo, viene passato Root.Ref anziché una stringa generata manualmente: il riferimento generato dalla libreria corrisponderà sicuramente a quello cercato da AddThreadedReply, il che elimina un'intera classe di bug di ancoraggio sfasati di un'unità. In secondo luogo, entrambi gli autori sono stati passati come semplici nomi visualizzati — la registrazione dei partecipanti, le identità GUID e i collegamenti authorId sono stati tutti gestiti dietro le quinte. Aprendo il file salvato in Excel 365, l'ancoraggio delle celle, l'ordine delle risposte e i due partecipanti distinti sono tutti attivi: facendo clic su Rispondi, Excel aggiunge la risposta allo stesso thread avviato dal tuo codice
Leggere una conversazione a ritroso: comportamento di round-trip
HotXLS esegue il round-trip dei commenti in thread a partire dalla versione 2.122.0: la riapertura di un pacchetto salvato ricostruisce l'elenco delle conversazioni di ciascun foglio e l'elenco dei partecipanti della cartella di lavoro a partire dalle singole sezioni, garantendo la conservazione di identificatori, collegamenti delle risposte e nomi visualizzati durante un intero ciclo di lettura e scrittura. Il lettore analizza person.xml prima di qualsiasi contenuto del foglio, consentendo a ciascun authorId di risolversi in un nome visualizzato all'avvio; gli identificatori dei partecipanti analizzati vengono preservati così come sono invece di essere rigenerati, per cui una cartella di lavoro modificata alternativamente dal codice e in Excel conserva identità stabili per gli autori lungo un numero indefinito di passaggi
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;
La struttura di memorizzazione basata su elenchi semplici e riferimenti emerge qui volutamente: ThreadedComments elenca le risposte nell'ordine della sezione, e un valore ParentId vuoto individua ciascuna radice. Se si necessita della struttura ad albero — ad esempio per esportare un registro delle revisioni — è sufficiente raggruppare prima per Ref e poi collegare ParentId a Id all'interno del gruppo di ciascuna cella. Questa logica di conservazione della struttura analizzata è un esempio di una filosofia più ampia adottata dalla libreria; l'articolo sul round-trip senza perdita di temi, elenchi di estensioni e catena di calcolo illustra come questo stesso principio si applici al resto del pacchetto
Stato risolto, timestamp e identità dell'autore
Tre attributi gestiscono la semantica di revisione, e tutti e tre sono modificabili sugli oggetti restituiti. Done fa riferimento all'attributo done — Excel mostra un thread risolto compresso con un collegamento Riapri. DateTime is the ISO-8601 UTC creation stamp (dT); HotXLS sostituisce un segnaposto fisso se questo viene lasciato vuoto in modo che la sezione sia sempre valida, ma un timestamp reale rende leggibile la cronologia del thread, per cui si consiglia di impostarlo. Lato identità, ogni TXLSXPerson espone ProviderId — solitamente None per le voci create localmente — e un UserId che può essere compilato con un email o UPN quando l'applicazione lo conosce:
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;
Un limite da indicare chiaramente: HotXLS scrive l'elemento <mentions> vuoto. I record delle menzioni con @ — il meccanismo che evidenzia il nome di un collega nel testo del commento e avvia una notifica in Microsoft 365 — non vengono modellati, per cui il testo contenente una chiocciola viene memorizzato come testo normale. Per una cartella di lavoro di revisione generata questo raramente rappresenta un limite, ma se il tuo flusso di lavoro richiede notifiche di menzione, prevedi che un utente le inserisca manualmente in Excel. L'identità dell'autore nella sezione person si abbina naturalmente con i campi di provenienza a livello di cartella di lavoro trattati in metadati della cartella di lavoro e proprietà del documento, dove risiede il resto delle informazioni di controllo di un file generato
Cosa fanno le versioni precedenti di Excel con i commenti in thread?
Excel 2016 e le versioni precedenti sono antecedenti al modello in thread, e ignorano semplicemente le sezioni che non comprendono. Quando lo stesso Excel 365 salva una conversazione in thread, scrive anche una nota legacy fittizia — una nota segnaposto con il testo "[Threaded comment]..." — proprio per consentire alle versioni meno recenti di mostrare qualcosa nella cella ancorata. HotXLS esporta solo le sezioni in thread, senza note legacy fittizie, per cui un file generato dal tuo codice non mostrerà alcun indicatore di commento se aperto in Excel 2016. Se il tuo pubblico include installazioni precedenti a Excel 365 e le annotazioni devono essere visibili, la vecchia API AddComment rimane il canale compatibile; evita di inserire entrambi i modelli sulla stessa cella senza aver prima verificato il comportamento su ogni versione di Excel a cui ti rivolgi, poiché il modo in cui un lettore gestisce contemporaneamente una nota e un thread su una stessa cella dipende dal lettore stesso, non dalle impostazioni di scrittura
L'altro limite invalicabile è il formato di file stesso. I commenti in thread sono una struttura OOXML senza controparte BIFF8, per cui la sezione .xls di HotXLS non dispone di API per i thread — una cartella di lavoro che deve rimanere nel formato binario legacy è limitata alle note classiche. In pratica, la scelta è semplice: se si scrive in formato .xlsx per Excel 365 o per i visualizzatori web/mobile di Excel, si utilizza AddThreadedComment ottenendo conversazioni reali; se il target è Excel 2016 o .xls, si utilizza AddComment accettando il modello delle note; per l'ispezione di un file ricevuto, si consiglia di controllare sia ThreadedComments e Comments, poiché una cartella di lavoro che ha transitato in entrambi i formati può legittimamente contenerli entrambi. L'intera gamma di API per entrambe le generazioni è documentata nella pagina del prodotto del Componente HotXLS Delphi Excel