Generați un registru de calcul din Delphi, adăugați o adnotare la o celulă cu API-ul clasic de comentarii, iar Excel 365 vă va înregistra textul la rubrica Note: o casetă galbenă în stil vechi, fără câmp Reply, fără avatar al autorului, fără buton de rezolvare. HotXLS scrie comentarii threaded autentice Excel 365 prin intermediul AddThreadedComment și AddThreadedReply din motorul XLSX, emițând secțiunea dedicată xl/threadedComments/threadedCommentN.xml pentru fiecare foaie și înregistrând fiecare autor în secțiunea person de la nivelul registrului de calcul, astfel încât conversația pe care o scrie codul dvs. reprezintă același obiect la care răspunde un evaluator în Excel
Distanța dintre cele două concepte contează deoarece cele două caracteristici doar seamănă la aspect. O notă este o casetă de text plutitoare; un comentariu threaded reprezintă o înregistrare de conversație cu identificatori stabili, un arbore de răspunsuri, un registru de autori și un indicator de rezolvare — elementele pe care se bazează efectiv un flux de lucru pentru recenzii. Acest articol analizează mai întâi structura OOXML, deoarece odată ce vedeți cele două modele de stocare alăturate, orice diferență de comportament din Excel încetează să mai fie un mister
De ce apar comentariile mele ca note în Excel 365?
Răspunsul scurt: două generații de comentarii împart aceeași grilă, dar trăiesc în secțiuni complet diferite ale pachetului. Modelul moștenit (legacy) — cel vizat de AddComment — stochează textul în xl/comments1.xml (tip de conținut application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml) și poziționează caseta printr-o componentă de desen însoțitoare VML, xl/drawings/vmlDrawing1.vml. Acea pereche este anterioară ribbonului; Excel 365 o citește în continuare corect, dar randează rezultatul ca o „notă” și nu oferă nicio interfață pentru fire de discuții (threading), deoarece nu există nimic de organizat în stocare. Autorul este un șir de caractere de afișare, poziția este o formă VML și acesta este tot modelul
Comentariile threaded, introduse odată cu Excel 365, ignoră complet stratul VML. Fiecare foaie cu o conversație conține propria secțiune xl/threadedComments/threadedCommentN.xml cu tipul de conținut application/vnd.openxmlformats-officedocument.spreadsheetml.threadedComments+xml, iar registrul de calcul conține o singură secțiune xl/person/person.xml (tip de conținut ...spreadsheetml.people+xml) care listează fiecare participant o singură dată. HotXLS expune ambele modele pe aceeași foaie de calcul: AddComment continuă să scrie perechea moștenită, în timp ce AddThreadedComment scrie noile secțiuni. Dacă rezultatul dvs. apare ca note, înseamnă că ați apelat primul API și îl doreați pe al doilea. Modelul moștenit rămâne instrumentul potrivit pentru anumite sarcini — articolul anterior despre comentariile din celule și hyperlink-urile în fluxurile de lucru pentru recenzii îl acoperă în detaliu, inclusiv pe partea de XLS — însă nimic din el nu se poate actualiza la un fir de discuție
Ce scrie HotXLS în pachet
HotXLS modelează fiecare răspuns ca un obiect TXLSXThreadedComment care conține o ancoră de celulă (Ref), un identificator de tip GUID (Id), un ParentId opțional, un AuthorId care se rezolvă prin lista de persoane, o oglindire DisplayName, corpul textului, un indicator Done și o dată/oră DateTime în format ISO-8601. La salvare, fiecare intrare devine un element <threadedComment> a cărui atribut t deține identificatorul, al cărui atribut dT conține marca temporală, iar al cărui atribut parentT — prezent doar la răspunsurile secundare (replies) — indică identificatorul părinte. Excel reconstruiește arborele conversației prin potrivirea lui parentT cu t; nu există cuibărire (nesting) în XML, ci doar o listă plată cu referințe
Secțiunea person este elementul pe care cele mai multe implementări scrise manual îl uită. Fiecare authorId dintr-un comentariu threaded trebuie să se rezolve la o intrare <person> din xl/person/person.xml, conectată în relațiile registrului de calcul, cu propria sa suprascriere a tipului de conținut — altfel Excel nu are niciun nume de afișat. HotXLS gestionează înregistrarea în mod automat: AddThreadedComment caută autorul în lista Persons a registrului după numele de afișare și creează o intrare cu un GUID nou dacă nu există deja, astfel încât comentariile consecutive scrise de același autor să partajeze o singură identitate. Relațiile foii de calcul primesc relația threadedComments, relațiile registrului primesc relația person, iar manifestul content-types primește ambele suprascrieri, fără ca nimic din acestea să apară în codul dvs.
Construirea unui lanț de răspunsuri cu AddThreadedComment și AddThreadedReply
AddThreadedComment creează rădăcina conversației: valoarea sa ParentId rămâne goală, ceea ce o marchează ca fiind începutul firului de discuție. AddThreadedReply primește un parametru ParentRef — referința celulei în care se află rădăcina —, găsește rădăcina la acea ancoră și marchează noul răspuns în ParentId cu valoarea Id a rădăcinii. Ambele returnează noul TXLSXThreadedComment, astfel încât puteți seta marca temporală sau starea de rezolvare pe obiectul nou creat:
var
Book: TXLSXWorkbook;
Sheet: TXLSXWorksheet;
Root: TXLSXThreadedComment;
begin
Book := TXLSXWorkbook.Create;
try
Book.Open('forecast.xlsx');
Sheet := Book.Sheets[0];
// Rădăcina conversației; ParentId rămâne gol
Root := Sheet.AddThreadedComment(8, 3,
'Q3 figure looks low against the pipeline export', 'Maria Ortiz');
Root.DateTime := '2026-07-06T09:12:00Z';
// Răspunsurile se ancorează la aceeași celulă; ParentRef indică celula rădăcină
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;
Două detalii din acel exemplu merită atenție. În primul rând, se transmite Root.Ref în loc de un șir de caractere construit manual: referința generată de bibliotecă garantează potrivirea cu ceea ce va căuta AddThreadedReply, eliminând o întreagă clasă de erori de tip off-by-one la ancore. În al doilea rând, ambii autori au fost transmiși ca simple nume de afișare — registrul de persoane, identitățile GUID și legăturile de tip authorId s-au realizat în spatele apelurilor. Deschideți fișierul salvat în Excel 365, iar ancorarea la celulă, ordinea răspunsurilor și cei doi participanți diferiți sunt active: faceți clic pe Reply, iar Excel se va adăuga la același fir de discuție pe care l-a început codul dvs.
Citirea unei conversații: comportamentul în fluxuri bidirecționale
HotXLS permite fluxuri bidirecționale pentru comentariile threaded începând cu versiunea 2.122.0: redeschiderea unui pachet salvat reconstruiește lista de conversații a fiecărei foi și lista de participanți a registrului din secțiunile respective, astfel încât identificatorii, legăturile de răspuns și numele de afișare supraviețuiesc unui ciclu complet citire→scriere. Cititorul analizează person.xml înaintea oricărui conținut de foaie, permițând ca fiecare authorId să se rezolve la un nume de afișare la momentul încărcării; identificatorii de persoane analizați sunt păstrați ca atare în loc de a fi regenerați, astfel încât un registru de calcul care circulă între codul dvs. și Excel își menține identitățile de autori stabile pe parcursul oricător cicluri
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('Rădăcină la ', Cmt.Ref, ' scris de ', Cmt.DisplayName, ': ', Cmt.Text)
else
Writeln(' răspuns scris de ', Cmt.DisplayName, ': ', Cmt.Text);
end;
Writeln('Participanți: ', Book.Persons.Count);
end;
Stocarea sub formă de listă plată plus referințe se reflectă în mod deliberat aici: ThreadedComments enumeră răspunsurile în ordinea secțiunilor din fișier, iar o valoare goală ParentId identifică fiecare rădăcină. Dacă aveți nevoie de o structură arborescentă — de exemplu, pentru a exporta un jurnal de recenzii —, grupați mai întâi după Ref, apoi conectați ParentId la Id în grupul fiecărei celule. Acest comportament de conservare a ceea ce s-a analizat este un exemplu dintr-o regulă mai amplă a bibliotecii; articolul despre fluxurile bidirecționale lossless pentru teme, liste de extensii și calc chain descrie modul în care același principiu se aplică restului pachetului
Starea de rezolvare, mărci temporale și identitatea autorilor
Trei atribute susțin semantica recenziilor, toate fiind scriptibile pe obiectele returnate. Done se mapează pe atributul done — Excel afișează un fir de discuție rezolvat în mod restrâns, cu un hyperlink Reopen. DateTime este marca temporală de creare în format ISO-8601 UTC (dT); HotXLS introduce un înlocuitor fix când valoarea este lăsată goală, pentru ca secțiunea să fie validă, însă o marcă temporală reală oferă lizibilitate istoricului firului de discuție, prin urmare este recomandat să o setați. Pe partea de identitate, fiecare TXLSXPerson expune ProviderId — de regulă None pentru intrările generate local — și un UserId pe care îl puteți completa cu un UPN sau o adresă de e-mail atunci când aplicația dvs. o cunoaște:
var
Root: TXLSXThreadedComment;
Person: TXLSXPerson;
begin
Root := Sheet.ThreadedComments.FindAt('D9');
if Root <> nil then
Root.Done := True; // salvat ca done="1"; Excel afișează firul ca fiind rezolvat
Person := Book.Persons.FindByDisplayName('Maria Ortiz');
if Person <> nil then
Person.UserId := 'maria.ortiz@example.com';
end;
O limită de menționat clar: HotXLS scrie elementul <mentions> gol. Înregistrările @-mention — sistemul care luminează numele unui coleg în textul comentariului și declanșează o notificare în Microsoft 365 — nu sunt modelate, astfel încât textul ce conține caracterul @ este stocat ca text simplu. Pentru un registru de calcul generat pentru recenzii acest lucru este rareori o pierdere, dar dacă fluxul dvs. se bazează pe notificări de tip mențiuni, asigurați-vă că un utilizator uman adaugă acele mențiuni în Excel. Identitatea autorului din secțiunea person se potrivește de minune cu câmpurile de proveniență de la nivelul registrului acoperite în metadatele registrului și proprietățile documentului, care reprezintă zona în care se află istoricul auditului pentru fișierul generat
Ce fac versiunile mai vechi de Excel cu comentariile threaded?
Excel 2016 și versiunile anterioare sunt anterioare modelului threaded, omițând pur și simplu secțiunile pe care nu le înțeleg. Când Excel 365 însuși salvează o conversație threaded, el scrie și o umbră a comentariului moștenit — o notă-înlocuitor care citește „[Threaded comment]...” — tocmai pentru ca versiunile mai vechi să afișeze ceva la celula ancorată. HotXLS emite exclusiv secțiunile threaded, fără nicio umbră moștenită, astfel încât un fișier scris de codul dvs. nu afișează niciun indicator de comentariu când este deschis în Excel 2016. Dacă publicul dvs. utilizează și instalații pre-365, iar adnotarea trebuie să fie vizibilă acolo, API-ul moștenit AddComment rămâne canalul compatibil; evitați însă suprapunerea ambelor modele pe aceeași celulă fără a testa fiecare versiune de Excel vizată, deoarece modul în care un cititor reconciliază o notă și un fir pe o singură celulă reprezintă decizia cititorului, nu a dvs.
Cealaltă limită strictă o reprezintă formatul de fișier în sine. Comentariile threaded reprezintă o structură OOXML fără un echivalent BIFF8, astfel încât componenta .xls din HotXLS nu oferă un API threaded — un registru de calcul care trebuie păstrat în formatul binar moștenit se limitează la notele clasice. În practică, tabelul de decizie este scurt: dacă scrieți .xlsx pentru Excel 365 sau cititoare web/mobile de Excel, folosiți AddThreadedComment și obțineți conversații reale; dacă vizați Excel 2016 sau .xls, folosiți AddComment și acceptați modelul de note; dacă auditați un fișier primit, verificați atât ThreadedComments, cât și Comments, deoarece un registru de calcul care a existat în ambele lumi poate conține în mod legitim ambele tipuri. Întreaga structură API pentru ambele generații este documentată pe pagina produsului HotXLS Delphi Excel Component