Remove Comments
Document.RemoveComment(id) deletes a comment, the range markers and reference
run that anchor it in the body, and its threading metadata. Removing a thread
root takes the whole thread with it, matching Word, which never leaves a reply
pointing at a comment that is gone.
The call returns a bool, not an error. It is false when the document has no
comments part or when no comment carries that ID, and true otherwise.
Removing the first thread
doc, err := document.Open("sample.docx")
if err != nil {
return err
}
defer doc.Close()
for _, c := range doc.Comments() {
if c.IsReply() {
continue
}
if ok := doc.RemoveComment(c.ID()); !ok {
return fmt.Errorf("failed removing comment %d", c.ID())
}
break
}The break is load-bearing. Read on for why a loop that keeps going here would
remove the wrong comments.
IDs are renumbered after every removal
Once a removal completes, the comments that remain are renumbered sequentially
from 1 in comments.xml order, and the range markers and reference runs in the
body are rewritten to match. Any ID you captured before the call is now
meaningless: it either refers to a different comment or to none at all.
So collecting a list of IDs and then removing them one by one does not work.
Re-read Document.Comments() after each removal, or remove in a loop that takes
one ID at a time from a freshly read slice.
Limitations
Removing a reply leaves its root and the other replies in place; only removal of a root cascades.
When the last comment goes, comments.xml, commentsExtended.xml,
commentsIds.xml and commentsExtensible.xml are dropped from the package
along with their relationships and content-type overrides, and HasComments()
starts returning false.
Anchors are cleaned out of every story that can hold one: the body, table cells, headers, footers, footnotes and endnotes. The text the comment covered is left untouched; only the markup wrapping it is removed.
Run the example
The example opens the bundled sample.docx, prints its comments, removes the
first thread root it finds with firstThreadRoot, and prints the list again so
the renumbering is visible in the output. It reports the result to stdout and
does not write the document back; add a doc.SaveToFile call to keep the
change.
git clone https://github.com/unidoc/unioffice-examples.git
cd unioffice-examples/document/comment-remove
go run main.goIf this is your first time using UniOffice, follow the getting started guide to create an API key and set up your development environment.