Δημιουργήστε ένα βιβλίο εργασίας από το Delphi, σχολιάστε ένα κελί με το κλασικό API σχολίων, και το Excel 365 αρχειοθετεί το κείμενό σας κάτω από τις Σημειώσεις (Notes): ένα κίτρινο πλαίσιο παλαιού τύπου χωρίς πεδίο Απάντησης (Reply), χωρίς άβαταρ συγγραφέα, χωρίς κουμπί επίλυσης. Το HotXLS γράφει γνήσια threaded comments του Excel 365 μέσω των AddThreadedComment και AddThreadedReply στη μηχανή XLSX, εκπέμποντας το ειδικό μέρος xl/threadedComments/threadedCommentN.xml ανά φύλλο και καταχωρώντας κάθε συγγραφέα στο μέρος ατόμων (person part) σε επίπεδο βιβλίου εργασίας, έτσι ώστε η συνομιλία που γράφει ο κώδικάς σας να είναι το ίδιο αντικείμενο στο οποίο απαντά ένας αναθεωρητής στο Excel
Η διάκριση έχει σημασία επειδή οι δύο δυνατότητες μοιάζουν μόνο εξωτερικά. Μια σημείωση (note) είναι ένα αιωρούμενο πλαίσιο κειμένου· ένα threaded comment είναι μια καταγραφή συνομιλίας με σταθερά αναγνωριστικά, ένα δέντρο απαντήσεων, ένα μητρώο συγγραφέων και μια σημαία επίλυσης — τα πράγματα στα οποία βασίζεται πραγματικά μια ροή εργασίας αναθεώρησης. Αυτό το άρθρο εξετάζει πρώτα τη δομή OOXML, επειδή μόλις δείτε τα δύο μοντέλα αποθήκευσης δίπλα-δίπλα, κάθε διαφορά συμπεριφοράς στο Excel παύει να είναι μυστηριώδης
Γιατί τα σχόλιά μου εμφανίζονται ως σημειώσεις στο Excel 365;
Η σύντομη απάντηση: δύο γενιές σχολίων μοιράζονται το ίδιο πλέγμα, και ζουν σε εντελώς διαφορετικά μέρη του πακέτου. Το παλαιού τύπου μοντέλο — αυτό που στοχεύει η AddComment — αποθηκεύει κείμενο στο xl/comments1.xml (τύπος περιεχομένου application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml) και τοποθετεί το πλαίσιο μέσω ενός συνοδευτικού μέρους σχεδίασης VML, του xl/drawings/vmlDrawing1.vml. Αυτό το ζεύγος προηγείται της κορδέλας (ribbon)· το Excel 365 εξακολουθεί να το διαβάζει πιστά, αλλά αποδίδει το αποτέλεσμα ως "σημείωση" (note) και δεν προσφέρει διεπαφή χρήστη για threaded comments σε αυτό, επειδή δεν υπάρχει τίποτα στην αποθήκευση για να οργανωθεί σε νήμα συνομιλίας. Ο συγγραφέας είναι μια συμβολοσειρά εμφάνισης, η θέση είναι ένα σχήμα VML, και αυτό είναι όλο το μοντέλο
Τα threaded comments, που εισήχθησαν με το Excel 365, αγνοούν εντελώς το επίπεδο VML. Κάθε φύλλο με μια συνομιλία φέρει το δικό του μέρος xl/threadedComments/threadedCommentN.xml υπό τον τύπο περιεχομένου application/vnd.openxmlformats-officedocument.spreadsheetml.threadedComments+xml, και το βιβλίο εργασίας φέρει ένα ενιαίο μέρος xl/person/person.xml (τύπος περιεχομένου ...spreadsheetml.people+xml) που καταγράφει κάθε συμμετέχοντα μία φορά. Το HotXLS εκθέτει και τα δύο μοντέλα στο ίδιο φύλλο εργασίας: η AddComment συνεχίζει να γράφει το παλαιού τύπου ζεύγος, η AddThreadedComment γράφει τα νέα μέρη. Εάν το αποτέλεσμά σας εμφανίζεται ως σημειώσεις, καλέσατε το πρώτο API ενώ θέλατε το δεύτερο. Το παλαιού τύπου μοντέλο εξακολουθεί να είναι το σωστό εργαλείο για ορισμένες εργασίες — το προηγούμενο άρθρο για τα σχόλια κελιών και τους υπερσυνδέσμους σε ροές εργασίας αναθεώρησης το καλύπτει σε βάθος, συμπεριλαμβανομένης της πλευράς XLS — αλλά τίποτα σε αυτό δεν αναβαθμίζεται σε νήμα
Τι εγγράφει το HotXLS στο πακέτο
Το HotXLS μοντελοποιεί κάθε απάντηση ως αντικείμενο TXLSXThreadedComment που φέρει μια άγκυρα κελιού (Ref), ένα αναγνωριστικό τύπου GUID (Id), ένα προαιρετικό ParentId, ένα AuthorId που επιλύεται μέσω της λίστας ατόμων, έναν καθρέφτη DisplayName, το σώμα κειμένου, μια σημαία Done και ένα DateTime κατά ISO-8601. Κατά την αποθήκευση, κάθε καταχώρηση γίνεται στοιχείο <threadedComment> του οποίου το χαρακτηριστικό t κρατά το αναγνωριστικό, το χαρακτηριστικό dT κρατά τη χρονική σήμανση και το χαρακτηριστικό parentT — παρόν μόνο στις θυγατρικές απαντήσεις — ονομάζει το αναγνωριστικό γονέα. Το Excel ανακατασκευάζει το δέντρο συνομιλίας αντιστοιχίζοντας το parentT στο t· δεν υπάρχει φωλιάσμα (nesting) στο XML, παρά μόνο μια επίπεδη λίστα συν αναφορές
Το μέρος του ατόμου (person part) είναι το κομμάτι που ξεχνούν οι περισσότερες χειροποίητες υλοποιήσεις. Κάθε authorId σε ένα threaded comment πρέπει να επιλύεται σε μια καταχώρηση <person> στο xl/person/person.xml, συνδεδεμένη με τις σχέσεις του βιβλίου εργασίας, με τη δική της παράκαμψη τύπου περιεχομένου — διαφορετικά το Excel δεν έχει όνομα εμφάνισης να δείξει. Το HotXLS χειρίζεται την καταχώρηση αυτόματα: η AddThreadedComment αναζητά τον συγγραφέα στη λίστα Persons του βιβλίου εργασίας με βάση το όνομα εμφάνισης και δημιουργεί μια καταχώρηση με ένα νέο GUID όταν δεν υπάρχει καμία, έτσι ώστε τα διαδοχικά σχόλια από τον ίδιο συγγραφέα να μοιράζονται την ίδια ταυτότητα. Οι σχέσεις του φύλλου εργασίας λαμβάνουν τη σχέση threadedComments, οι σχέσεις του βιβλίου εργασίας λαμβάνουν τη σχέση ατόμου, και η λίστα τύπων περιεχομένου (content-types manifest) λαμβάνει και τις δύο παρακάμψεις, χωρίς τίποτα από αυτά να εμφανίζεται στον κώδικά σας
Δημιουργία αλυσίδας απαντήσεων με τα AddThreadedComment και AddThreadedReply
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;
Δύο λεπτομέρειες σε αυτήν την καταχώρηση απαιτούν προσοχή. Πρώτον, μεταβιβάζεται το Root.Ref αντί για μια χειροποίητη συμβολοσειρά: η αναφορά που παρήγαγε η βιβλιοθήκη είναι εγγυημένο ότι ταιριάζει με αυτό που θα αναζητήσει η AddThreadedReply, γεγονός που αφαιρεί μια ολόκληρη κατηγορία σφαλμάτων άγκυρας κατά ένα στοιχείο (off-by-one). Δεύτερον, και οι δύο συγγραφείς μεταβιβάστηκαν ως απλά ονόματα εμφάνισης — το μητρώο ατόμων, οι ταυτότητες GUID και η καλωδίωση authorId συνέβησαν όλα πίσω από τις κλήσεις. Ανοίξτε το αποθηκευμένο αρχείο στο Excel 365 και η αγκύρωση των κελιών, η σειρά των απαντήσεων και οι δύο ξεχωριστοί συμμετέχοντες είναι όλοι ζωντανοί: κάντε κλικ στο Απάντηση (Reply) και το Excel προσαρτά στο ίδιο νήμα συνομιλίας που ξεκίνησε ο κώδικάς σας
Ανάγνωση μιας συνομιλίας πίσω: συμπεριφορά round-trip
Το HotXLS υποστηρίζει τον πλήρη κύκλο round-trip των threaded comments από την έκδοση 2.122.0: το εκ νέου άνοιγμα ενός αποθηκευμένου πακέτου ανακατασκευάζει τη λίστα συνομιλιών κάθε φύλλου και τη λίστα συμμετεχόντων του βιβλίου εργασίας από τα μέρη, οπότε τα αναγνωριστικά, οι σύνδεσμοι απαντήσεων και τα ονόματα εμφάνισης επιβιώνουν από έναν πλήρη κύκλο ανάγνωσης→εγγραφής. Ο αναγνώστης αναλύει το person.xml πριν από οποιοδήποτε περιεχόμενο φύλλου, κάτι που επιτρέπει σε κάθε authorId να επιλύεται σε όνομα εμφάνισης κατά τον χρόνο φόρτωσης· τα αναλυμένα αναγνωριστικά ατόμων διατηρούνται ως έχουν αντί να αναγεννώνται, έτσι ώστε ένα βιβλίο εργασίας που μετακινείται μεταξύ του κώδικά σας και του Excel να διατηρεί σταθερές ταυτότητες συγγραφέων σε όσους κύκλους round-trip κι αν εκτελεστούν
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;
Η αποθήκευση τύπου επίπεδης λίστας συν αναφορών φαίνεται εδώ σκόπιμα: η συλλογή ThreadedComments απαριθμεί τις απαντήσεις με τη σειρά του μέρους, και ένα κενό ParentId προσδιορίζει κάθε ρίζα. Εάν χρειάζεστε το σχήμα δέντρου — για παράδειγμα, για να εξαγάγετε ένα αρχείο καταγραφής αναθεώρησης — ομαδοποιήστε πρώτα κατά Ref και στη συνέχεια συνδέστε το ParentId στο Id μέσα στην ομάδα κάθε κελιού. Αυτή η συμπεριφορά διατήρησης-αυτού-που-αναλύθηκε είναι ένα παράδειγμα μιας ευρύτερης πολιτικής στη βιβλιοθήκη· το άρθρο για το lossless round-trip θεμάτων, λιστών επεκτάσεων και της αλυσίδας υπολογισμού καλύπτει πώς η ίδια αρχή εφαρμόζεται στο υπόλοιπο πακέτο
Κατάσταση επίλυσης, χρονικές σημάνσεις και ταυτότητα συγγραφέα
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;
Μια λεπτομέρεια: το HotXLS εγγράφει το στοιχείο <mentions> κενό. Οι καταγραφές @-mention — ο μηχανισμός που φωτίζει το όνομα ενός συναδέλφου μέσα στο κείμενο του σχολίου και προκαλεί μια ειδοποίηση στο Microsoft 365 — δεν μοντελοποιούνται, οπότε το κείμενο που περιέχει το σύμβολο @ αποθηκεύεται ως απλό κείμενο. Για ένα παραγόμενο βιβλίο εργασίας αναθεώρησης αυτό σπάνια αποτελεί απώλεια, αλλά εάν η ροή εργασίας σας εξαρτάται από ειδοποιήσεις αναφορών, προγραμματίστε ώστε ένας άνθρωπος να τις προσθέσει μέσα στο Excel. Η ταυτότητα του συγγραφέα στο μέρος του ατόμου συνδυάζεται φυσικά με τα πεδία προέλευσης σε επίπεδο βιβλίου εργασίας που καλύπτονται στο άρθρο για τα μεταδεδομένα βιβλίου εργασίας και ιδιότητες εγγράδου, όπου ζει και το υπόλοιπο ίχνος ελέγχου (audit trail) ενός παραγόμενου αρχείου
Τι κάνουν οι παλαιότερες εκδόσεις του Excel με τα threaded comments;
Το Excel 2016 και οι παλαιότερες εκδόσεις προηγούνται του μοντέλου με νήματα συνομιλίας, και απλά αγνοούν τα μέρη που δεν κατανοούν. Όταν το ίδιο το Excel 365 αποθηκεύει μια συνομιλία με νήματα, γράφει επίσης μια σκιά παλαιού τύπου σχολίου — μια σημείωση δείκτη θέσης που διαβάζει "[Threaded comment]..." — ακριβώς ώστε οι παλαιότερες εκδόσεις να δείχνουν κάτι στο αγκυροβολημένο κελί. Το HotXLS εκπέμπει μόνο τα μέρη με νήματα, χωρίς σκιά παλαιού τύπου, οπότε ένα αρχείο που έχει γραφτεί από τον κώδικά σας δεν δείχνει καθόλου δείκτη σχολίου όταν ανοίγει στο Excel 2016. Εάν το κοινό σας περιλαμβάνει εγκαταστάσεις πριν από το 365 και ο σχολιασμός πρέπει να είναι ορατός εκεί, το παλαιού τύπου API AddComment παραμένει το συμβατό κανάλι· απλά αποφύγετε τη συσσώρευση και των δύο μοντέλων στο ίδιο κελί χωρίς να δοκιμάσετε κάθε έκδοση Excel στην οποία παραδίδετε, επειδή ο τρόπος με τον οποίο ένας αναγνώστης συμφιλιώνει μια σημείωση και ένα νήμα συνομιλίας σε ένα κελί είναι απόφαση του αναγνώστη, όχι δική σας
Το άλλο σκληρό όριο είναι η ίδια η μορφή του αρχείου. Τα threaded comments είναι μια δομή OOXML χωρίς αντίστοιχο BIFF8, οπότε η πλευρά .xls του HotXLS δεν έχει API για νήματα συνομιλίας — ένα βιβλίο εργασίας που πρέπει να παραμείνει στην παλαιού τύπου δυαδική μορφή περιορίζεται σε κλασικές σημειώσεις. Στην πράξη, ο πίνακας αποφάσεων είναι σύντομος: γράφοντας .xlsx για το Excel 365 ή για αναγνώστες Excel ιστού/κινητών, χρησιμοποιήστε το AddThreadedComment και λάβετε πραγματικές συνομιλίες. Στοχεύοντας στο Excel 2016 ή στο .xls, χρησιμοποιήστε το AddComment και αποδεχτείτε το μοντέλο σημειώσεων. Ελέγχοντας ένα αρχείο που λάβατε, ελέγξτε τόσο τα ThreadedComments όσο και τα Comments, επειδή ένα βιβλίο εργασίας που έχει ζήσει και στους δύο κόσμους μπορεί νόμιμα να μεταφέρει και τα δύο. Η πλήρης επιφάνεια API και για τις δύο γενιές τεκμηριώνεται στη σελίδα προϊόντος του HotXLS Delphi Excel Component