När du genererar en arbetsbok från Delphi och kommenterar en cell med det klassiska comment-API:et, arkiverar Excel 365 din text under Anteckningar (Notes): en gul ruta av gammal modell utan svarsfält, författarbild eller stängningsknapp. HotXLS skriver äkta Excel 365-trådade kommentarer via AddThreadedComment och AddThreadedReply i XLSX-motorn, vilket genererar den dedikerade xl/threadedComments/threadedCommentN.xml-delen per kalkylblad och registrerar varje författare i person-delen på arbetsboks-nivå. På så sätt blir konversationen din kod skriver samma objekt som en granskare svarar på i Excel
Distinktionen är viktig eftersom de två funktionerna bara liknar varandra till utseendet. En anteckning är en flytande textruta, medan en trådad kommentar är en konversationspost med stabila identifierare, ett svarsträd, ett författarregister och en markering för om den är stängd — de saker som ett granskningsarbetsflöde faktiskt bygger på. Den här artikeln går först igenom OOXML-strukturen, för när du väl ser de två lagringsmodellerna sida vid sida upphör alla skillnader i Excels beteende att vara mystiska
Varför visas mina kommentarer som anteckningar i Excel 365?
Det korta svaret: två generationer kommentarer delar samma rutnät, och de lever i helt olika delar av paketet. Den äldre modellen — den som AddComment rikta in sig på — lagrar text i xl/comments1.xml (innehållstyp application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml) och placerar bubblan via en tillhörande VML-ritningsdel, xl/drawings/vmlDrawing1.vml. Det paret skapades före menyfliksområdet; Excel 365 läser det fortfarande troget, men renderar resultatet som en "anteckning" och erbjuder inget trådningsgränssnitt på det, eftersom det inte finns något i lagringen att tråda. Författaren är en visningssträng, positionen är en VML-form, och det är hela modellen
Trådade kommentarer, som introducerades i Excel 365, ignorerar VML-skiktet helt. Varje kalkylblad med en konversation bär på sin egen xl/threadedComments/threadedCommentN.xml-del under innehållstypen application/vnd.openxmlformats-officedocument.spreadsheetml.threadedComments+xml, och arbetsboken innehåller en enskild xl/person/person.xml-del (innehållstyp ...spreadsheetml.people+xml) som listar varje deltagare en gång. HotXLS exponerar båda modellerna på samma kalkylblad: AddComment fortsätter att skriva det äldre paret, AddThreadedComment skriver de nya delarna. Om dina utdata visas som anteckningar, anropade du det första API:et när du ville ha det andra. Den äldre modellen är stilla rätt verktyg för vissa jobb — den tidigare artikeln om cellkommentarer och hyperlänkar i granskningsarbetsflöden täcker den på djupet, inklusive XLS-sidan — men inget i den uppgraderas till en tråd
Vad HotXLS skriver till paketet
HotXLS modellerar varje svar som ett TXLSXThreadedComment-objekt som bär på ett cellankare (Ref), en identifierare i GUID-stil (Id), en valfri ParentId, en AuthorId som löses upp via personlistan, en kopia av DisplayName, textkroppen, en Done-flagga samt en ISO-8601 DateTime. När det sparas blir varje post ett <threadedComment>-element vars t-attribut innehåller identifieraren, vars dT-attribut innehåller tidsstämpeln och vars parentT-attribut — som endast finns på underordnade svar — namnger den överordnade identifieraren. Excel återskar konversationsträdet genom att matcha parentT mot t; det finns ingen nästling i XML-koden, bara en platt lista plus referenser
Person-delen är den bit som de flesta hembyggda implementeringar glömmer bort. Varje authorId i en trådad kommentar måste lösas upp till en <person>-post i xl/person/person.xml, kopplad till arbetsbokens relationer, med sin egen innehållstypsöverskridning — annars har Excel inget visningsnamn att visa. HotXLS hanterar registreringen automatiskt: AddThreadedComment söker upp författaren i arbetsbokens Persons-lista via visningsnamn och skapar en post med en ny GUID när ingen sådan finns, så att efterföljande kommentarer av samma författare delar en identitet. Kalkylbladsrelationerna får relationen threadedComments, arbetsboksrelationerna får personrelationen och innehållstypsmanifestet får båda överskridningarna, utan att något av detta behöver synas i din kod
Bygga en svarstråd med AddThreadedComment och AddThreadedReply
AddThreadedComment skapar konversationens rot: dess ParentId förblir tom, vilket är det som markerar den som toppen av tråden. AddThreadedReply tar en ParentRef-parameter — cellreferensen där roten lever — hittar roten vid det ankaret och stämplar det nya svarets ParentId med rotens Id. Båda returnerar den nya TXLSXThreadedComment-instansen, så att du kan ställa in tidsstämpel eller stängningsstatus på objektet du just skapade:
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;
Två detaljer i den listningen är värda uppmärksamhet. För det första skickas Root.Ref istället för en manuellt ihopsatt sträng: referensen som biblioteket genererade matchar garanterat det som AddThreadedReply kommer att slå upp, vilket tar bort en hel klass av off-by-one-förskjutningsbuggar gällande ankare. För det andra skickades båda författarna som vanliga visningsnamn — personregistret, GUID-identiteterna och authorId-kopplingarna hanterades alla bakom kulisserna. Öppna den sparade filen i Excel 365, så är cellförankringen, svarsordningen och de två olika deltagarna alla aktiva: klicka på Svara och Excel lägger till i samma tråd som din kod startade
Läsa tillbaka en konversation: round-trip-beteende
HotXLS stöder round-trips för trådade kommentarer från och med version 2.122.0: att återöppna ett sparat paket bygger upp varje blads konversationslista och arbetsbokens deltagarlista från delarna, så att identifierare, svarslänkar och visningsnamn överlever en hel läs→skriv-cykel. Läsaren tolkar person.xml före kalkylbladets innehåll, vilket gör att varje authorId kan lösas upp till ett visningsnamn vid laddningstillfället; tolkade personidentifierare bevaras som de är snarare än att genereras om, vilket gör att eine arbetsbok som flyttas mellan din kod och Excel behåller stabila författaridentiteter över hur många round-trips som helst
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;
Lagringen med en platt lista plus referenser lyser igenom här medvetet: ThreadedComments räknar upp svar i den ordning de ligger i filen, och en tom ParentId identifierar varje rot. Om du behöver trädformen — till exempel för att exportera en granskningslogg — grupperar du först efter Ref och kedjar sedan ParentId till Id inom varje cells grupp. Detta bevara-det-du-tolkade-beteende är ett exempel på en mer generell policy i biblioteket; artikeln om förlustfri round-trip för teman, tilläggslistor och beräkningskedjan beskriver hur samma princip tillämpas på resten av paketet
Stängningsstatus, tidsstämplar och författaridentitet
Tre attribut bär på granskningssemantiken, och alla tre är skrivbara på de returnerade objekten. Done mappar mot attributet done — Excel visar en stängd tråd minimerad med en "Öppna igen"-länk. DateTime is skapandestämpeln i ISO-8601 UTC (dT); HotXLS ersätter den med en fast platshållare när du lämnar den tom så att filen alltid validerar, men en riktig tidsstämpel är det som gör trådhistoriken läsbar, så ställ in den. På identitetssidan exponerar varje TXLSXPerson en ProviderId — vanligtvis None för lokalt skapade poster — samt en UserId som du kan fylla i med en UPN eller e-postadress när din applikation känner till den:
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;
En begränsning som bör framhållas: HotXLS skriver elementet <mentions> tomt. @-omnämnande-poster — den mekanism som lyser upp en kollegas namn inuti kommentarstexten och utlöser en avisering i Microsoft 365 — modelleras inte, så text som innehåller ett @-tecken lagras som vanlig text. För en genererad granskningsarbetsbok är det sällan en förlust, men om ditt arbetsflöde är beroende av omnämnande-aviseringar bör du planera för att en människa lägger till dessa i Excel. Författaridentiteten i person-delen parar naturligt ihop sig med de ursprungsfält på arbetsboks-nivå som beskrivs i arbetsbaksmetadata och dokumentegenskaper, vilket är där resten av den genererade filens granskningsspår finns
Vad gör äldre Excel-versioner med trådade kommentarer?
Excel 2016 och tidigare skapades före den trådade modellen, och de ignorerar helt enkelt delar de inte förstår. När Excel 365 självt sparar en trådad konversation skriver den också en äldre kommentars-skugga — en anteckningsplatshållare med texten "[Threaded comment]…" — just för att äldre versioner ska visa något vid den förankrade cellen. HotXLS genererar endast de trådade delarna, utan någon äldre skugga, så en fil som skrivs av din kod visar ingen kommentarindikator alls när den öppnas i Excel 2016. Om dina mottagare inkluderar installationer före 365 och kommentaren måste vara synlig där, förblir det äldre AddComment-API:et den kompatibla kanalen. Undvik dock att stapla båda modellerna på samma cell utan att testa varje Excel-version du skickar till, eftersom hur en läsare försonar en anteckning och en tråd på samma cell är läsarens beslut, inte ditt
Den andra skarpa gränsen är själva filformatet. Trådade kommentarer är en OOXML-struktur utan någon motsvarighet i BIFF8, så .xls-sidan av HotXLS har inget trådat API — en arbetsbok som måste stanna i det äldre binära formatet är begränsad till klassiska anteckningar. I praktiken är beslutstabellen kort: om du skriver .xlsx för Excel 365 eller webb-/mobil-Excel-läsare, använd AddThreadedComment för att få riktiga konversationer; om du riktar in dig på Excel 2016 eller .xls, använd AddComment och acceptera anteckningsmodellen; om du granskar en fil du tagit emot, kontrollera både ThreadedComments och Comments, eftersom en arbetsbok som har levt i båda världarna legitimt kan bära båda. Hela API-ytan för båda generationerna finns dokumenterad på produktsidan för HotXLS Delphi Excel Component