torsdag den 10. november 2016

Undersøge markeret tekst i Writer (med makro)


Vi kan med en makro aflæse hvad der er markeret i et tekstdokument.

Problemet er at vi ikke på forhånd kan vide om der overhovedet er markeret noget, og om markeringen dækker et enkelt eller flere områder. Flere markerede områder er hvis du holder CTRL-tasten nede mens du markerer flere områder.

Vi kommer til at anvende to centrale begreber: Selection og Cursor
Selection er en liste med alle markerede områder:

oSelections = ThisComponent.getCurrentSelection()

Resultatet kan f.eks. vises sådan:

Print oSelections.getCount

For at udlede noget af det markerede, må vi håndtere hver enkelt markeret område et ad gangen. Her aflæser vi helt konkret hvad der står i hver enkelt markering:

Sub Main
oSelections = ThisComponent.getCurrentSelection()
For i = 0 To oSelections.getCount() - 1
oSel = oSelections.getByIndex(i)
Print oSel.String
Next
End Sub

Der findes to typer cursor i LibreOffice makroer:
  • ViewCursor ved, hvordan dataene vises, men ikke noget om data. 
  • TextCursor (non-view cursor), ved en masse om data, men meget lidt om, hvordan de vises. 
For eksempel kender ViewCursor ikke hvilke ord der er markeret, og TextCursor kender intet til linjer, skærme, eller sider.

Vi skal bruge en TextCursor ud fra hver enkelt af vores markeringer:

oCursor = oDoc.Text.CreateTextCursorByRange(oSel)

Nu kan vi kontrollere om noget er markeret, hvilket lyder enkelt, men tro om igen. Hvis antallet er markeringer er 0, så er intet markeret. Men der er altid en markør i dokumentet, så antallet af markeringer er aldrig 0. Principielt kan vi komme ud for at der ingen markering er, hvis LibreOffice afvikles på en server, uden brugergrænsefladen vises.

Hvis længden af markeringen er 0, er intet markeret. Længden skal måles på hver enkelt markering, hvilket er lidt farligt. Det er fordi en tekststreng ikke kan/må være længere end 64k, så brug ikke den metode. Du risikerer at LibreOffice crasher.

Den bedste måde er at skabe en tekstcursor fra den aktuelle markering, og så undersøge om start og slutpunktet er det samme. Kontrol af om der er noget markeret er altså relativt kompliceret men dog muligt. Vi kan lave denne funktion til formålet:

Function IsAnythingSelected(oDoc As Object) As Boolean
Dim oSelections 'Contains all of the selections
Dim oSel 'Contains one specific selection
Dim oCursor 'Text cursor to check for a collapsed range
REM Assume nothing is selected
IsAnythingSelected = False
If IsNull(oDoc) Then Exit Function
' The current selection in the current controller.
'If there is no current controller, it returns NULL.
oSelections = oDoc.getCurrentSelection()
If IsNull(oSelections) Then Exit Function
If oSelections.getCount() = 0 Then Exit Function
If oSelections.getCount() > 1 Then
REM There is more than one selection so return True
IsAnythingSelected = True
Else
REM There is only one selection so obtain the first selection
oSel = oSelections.getByIndex(0)
REM Create a text cursor that covers the range and then see if it is
REM collapsed.
oCursor = oDoc.Text.CreateTextCursorByRange(oSel)
If Not oCursor.IsCollapsed() Then IsAnythingSelected = True

REM You can also compare these to see if the selection starts and ends at
REM the same location.
REM If oDoc.Text.compareRegionStarts(oSel.getStart(),_
REM oSel.getEnd()) <> 0 Then
REM IsAnythingSelected = True
REM End If
End If
End Function

Funktionen IsAnythingSelected er fra bogen OpenOffice.org Macros Explained af Andrew D. Pitonyak.