Page 1 of 1

Reporting Writer Annotation contents

Posted: Tue Jun 30, 2020 9:14 pm
by RoryOF
I am trying to enumerate all Annotations (formerly Comments) in a Writer document. I am able to do this using the macro code listed below.

I have only one problem. No matter where in the document I invoke the macro, it returns the first Annotation of the document, then the last, second-last, third-last etc. Is there any way to make it return the Annotations either in ascending or descending order? This would obviate having to write some code to handle the "out of place" first Annotation.

For the present I display the Annotation contents using a messagebox. When (if) I have their retrieval in sequential order, either ascending or descending, I will do further processing with the contents.

Code: Select all

Sub ListAnnotes

Rem Report the content of  all Annotations in a Writer document

Dim oDoc as Object
Dim oEnum as Object
Dim oField as Object
Dim oText as String ' do not Dim as Object or Variant

oDoc = ThisComponent
oEnum = oDoc.getTextFields().createEnumeration()

If Not IsNull(oEnum) Then
    Do While oEnum.hasMoreElements()
        oField = oEnum.nextElement()
        If oField.supportsService("com.sun.star.text.TextField.Annotation") Then
            oText = oField.Content
            Msgbox "Annotation content is : " + oText
        End If
    Loop
End If

End Sub 'ListAnnotes


Re: Reporting Writer Annotation contents

Posted: Wed Jul 01, 2020 2:54 pm
by hubert lambert
Hi RoryOF,

Strange behavior indeed, that still exists within LibreOffice.
One way to workaround it would be to sort the field anchors before displaying their content, as in the following example.
Caveat: this only work if all annotations are in the same text object, i.e. not in frames or tables...

Code: Select all

Sub ListAnnotes

Rem Report the content of  all Annotations in a Writer document

Dim oDoc as Object
Dim oEnum as Object
Dim oField as Object
Dim oText as String ' do not Dim as Object or Variant

    oDoc = ThisComponent
    textfields = oDoc.getTextFields()
    oEnum = textfields.createEnumeration()
    
    dim anchors()

    If Not IsNull(oEnum) Then
        Do While oEnum.hasMoreElements()
            oField = oEnum.nextElement()
            If oField.supportsService("com.sun.star.text.TextField.Annotation") Then
                addanchor(anchors, oField.anchor)
            End If
        Loop
        sortanchors(anchors)
        dim notes(ubound(anchors))
        for n = 0 to ubound(anchors)
            msgbox anchors(n).TextField.Content
        next n
    End If
End Sub 'ListAnnotes

sub addanchor(anchors, anchor)
    u = ubound(anchors)+1
    redim preserve anchors(u)
    anchors(u) = anchor
end sub

sub sortanchors(sortlist())
    ' adapted from AOO Tools macro BubbleSortList
    txt = sortlist(0).Text
    i = ubound(sortlist(),1)
    for s = 1 to i - 1
        for t = 0 to i-s
            if txt.compareRegionStarts(sortlist(t+1), sortlist(t)) = 1 then                             
                displaydummy = sortlist(t)
                sortlist(t) = sortlist(t+1)
                sortlist(t+1) = displaydummy    
            end if
        next t
    next s
end sub
Regards.

Re: Reporting Writer Annotation contents

Posted: Wed Jul 01, 2020 3:23 pm
by RoryOF
I will try your code later today, Hubert.

For various reasons, it would be most convenient if the Annotations were returned in document order. That would greatly simplify some of the processing I would like to do with them and avoid having to pass through the document to count the number of Annotations, before once again having to pass through to retrieve, modify, and rewrite any modified Annotations.

An Annotation does not appear to have an index or any location in the document other than its anchor. Early today I found some code by Andrew Pitonyak processing other enumerations in a Writer document which, if it is applicable to Annotations (not yet tested) might change their return order to ascending.

Re: Reporting Writer Annotation contents

Posted: Wed Jul 01, 2020 5:23 pm
by RoryOF
That works nicely, Hubert. Thank you. I will now have to consider how I can integrate your method with my project, but will have to pause on that for a few days because of other commitments.

If anyone else has suggestions on a direct method of retrieving the enumeration of Annotations in proper ascending or descending order, their suggestions would be welcome.

Re: Reporting Writer Annotation contents

Posted: Tue Jul 07, 2020 1:50 am
by JeJe
Enumerate the paragraphs and text portions of each paragraph (as Pitonyak)

Look for TextPortionType = "Annotation" then the TextField of that Portion is the Comment.

Re: Reporting Writer Annotation contents

Posted: Tue Jul 07, 2020 9:27 am
by RoryOF
Thanks, JeJe. I've had to pause my project for a few days (medical tests), but I will return to it shortly.

Re: Reporting Writer Annotation contents

Posted: Tue Jul 07, 2020 11:19 am
by JeJe
Writer must have a list of Comments ordered as they appear in the document internally - as it displays them this way in the Navigator. Its the same with other Navigator items like Sections - we're given access to the list of items - but not in the way we want, in the order they appear in the document.

Re: Reporting Writer Annotation contents

Posted: Tue Jul 07, 2020 11:47 am
by JeJe
The exception is bookmarks. They're listed in the navigator in alphabetical order, but usefully (unless you need that) they're listed in the order they appear in the document in ThisComponent.bookmarks. That means if you want access to a list of objects as they appear in the document you can bookmark them as a workaround.

Re: Reporting Writer Annotation contents

Posted: Sun Aug 11, 2024 9:57 pm
by _savage
Thank you for the useful hints!

FWIW, the following works for me (pseudo code):

Code: Select all

texts = par.createEnumeration()
while texts.hasMoreElements():
    text = texts.nextElement() 
    if text.TextPortionType == 'Annotation':  # Or 'AnnotationEnd' for the span.
        # text.getString() seems always empty for 'Annotation', it's just a marker/anchor, I guess.
        field = text.TextField  # As per JeJe's comment implements the Annotation service, does not exist for 'AnnotationEnd'.
        comment = field.Content
See also the Annotation service (as per Hubert’s suggestion).

I also assume that there always must be an 'AnnotationEnd' type portion paired with an 'Annotation' type portion? That would make sense to establish the text that’s spanned by a comment (which might span multiple paragraphs, etc.)

Re: Reporting Writer Annotation contents

Posted: Mon Aug 12, 2024 12:02 am
by JeJe
There's no AnnotationEnd if the Annotation is just at one point.

Re: Reporting Writer Annotation contents

Posted: Mon Aug 12, 2024 12:05 am
by JeJe
For the text of the Annotation look at the TextRange property of the Annotation portion.

Re: Reporting Writer Annotation contents

Posted: Mon Aug 12, 2024 12:31 am
by _savage
JeJe wrote: Mon Aug 12, 2024 12:02 amThere's no AnnotationEnd if the Annotation is just at one point.
I see a text portion type 'Annotation' always paired with a text portion type 'AnnotationEnd', and that 'Annotation' text portion itself is an empty string. But that’s probably because in the document, all annotations (comments) span words and phrases?
JeJe wrote: Mon Aug 12, 2024 12:05 amFor the text of the Annotation look at the TextRange property of the Annotation portion.
Hmm, I tried

Code: Select all

if text.portion == "Annotation":
    print(text.TextRange)
and it always gives me a None.

Re: Reporting Writer Annotation contents

Posted: Mon Aug 12, 2024 7:47 am
by JeJe
I should have said .TextField.TextRange of the Annotation portion. Its an interface not a string. Use MRI.

viewtopic.php?t=49294

You can create a single paragraph test document with one annotation at one point to verity that then there isn't an AnnotationEnd portion.

Re: Reporting Writer Annotation contents

Posted: Mon Aug 12, 2024 10:44 am
by Lupp
(I probably didn't study the old thread and its revival thoroughly enough. Sorry if my hints will not be useful.)
There is viewtopic.php?t=111343 where I presented a piece of code related to this thread.
If you want to study it, please note that the

Code: Select all

Sub annotationInfoToSheet(..., ...)
is not eligible for a direct call from >>Macros>Run Macro... . It's just a helper for

Code: Select all

Sub collectWriterAnnotationsInfo(Optional pDoc)

Re: Reporting Writer Annotation contents

Posted: Sat Aug 31, 2024 11:10 pm
by _savage
I think I might have been unclear: for an annotation I’d like to get access to both the annotated text and the annotation itself.

Take, for example, the attached document: it contains a paragraph

Code: Select all

A paragraph with annotated text.
and the annotation itself

Code: Select all

A text annotation.
The above code extracts the annotation via .textfield.textrange, but I can’t quite get access to the annotated text itself — other than having two special text portions Annotation and AnnotationEnd “wrapping” the annotated text itself. Furthermore, annotations can overlap for annotated text, so, hmm… :?

Re: Reporting Writer Annotation contents

Posted: Sun Sep 01, 2024 12:21 am
by _savage
Ah, poking and poking around with MRI… it looks like the Anchor property of a Annotation type text portion is the gateway to the annotated text.

Re: Reporting Writer Annotation contents

Posted: Sun Sep 01, 2024 1:06 pm
by Lupp
Back to the roots:
JeJe wrote: Tue Jul 07, 2020 11:19 am Writer must have a list of Comments ordered as they appear in the document internally - as it displays them this way in the Navigator. ...
Can't confirm this. For my example the Navigator is showing the annotations in an arbitrary order.
@RoryOF: There is no .Annotations (and also no .Comments) property/service, and the .TextFields property/service hasn't even a .Count nor does it support XIndexAccess. We need to use the XEnumerationAccess for which no order is specified in any way.

@All:
If we want to get the annotations in a specific order we wiil need to create that order explicitly. My related suggestion was posted and exemplified in the CodeSnippets thread I linked to already in my previous post to this topic (viewtopic.php?t=111343).
_savage wrote: Sat Aug 31, 2024 11:10 pm I think I might have been unclear: for an annotation I’d like to get access to both the annotated text and the annotation itself.
Supposing "annotated text" is meant to mean the content of the .Anchor TextRange of the annotation:
In the abovementioned post I also commented on the relevant fact that AOO and old versions of LibO don't support non-empty anchors for annotations. Old documents opened with newer version will also show the empty anchors annotations got at creation.
_savage wrote: Sun Sep 01, 2024 12:21 am Ah, poking and poking around with MRI… it looks like the Anchor property of a Annotation type text portion is the gateway to the annotated text.
Actually we are talking of the .Text porperty of the .Anchor of the related TextField .
Once again: Everything exemplified in the mentioned CodeSnippets post.