Hi, I’m a novice. I want to write a Writer macro which shrinks all images in a selection (there may be one image selected as well). But I can’t even find a manual on Writer data structures. Can you help me with any of these two topics?
How were these images created? It seems that selecting more than one inserted image (Insert → Image) is not possible, but selecting more than one drawing object (View → Toolbars → Drawing) is possible. We need to know what kind of objects you selected in order to enumerate them.
To figure this out, get the selection in a macro and then pass it to an introspection tool such as MRI.
The structure of a Text Document is discussed in the “Text Documents” section of the Apache OpenOffice BASIC Programming Guide. See Text Documents - Apache OpenOffice Wiki.
For all modules (Writer, Calc, Impress, Draw), the graphic objects are iterated using draw pages.
As you are talking about Writer: there is only one global draw page per Writer document, which is accessed using com.sun.star.drawing.XDrawPageSupplier
interface. oDoc.DrawPage
returns the draw page.
To iterate through objects, you get their count (using oDrawPage.Count
), and then get individual objects using oDrawPage(i)
.
To find out if a graphical object is in selection, you need to know what selection you have. It might be no selection, or a range, or a single object, or multiple objects. You may use this code:
Function IsSelectionEmpty(ByRef oSel)
IsSelectionEmpty = False
If (IsNull(oSel)) Then
IsSelectionEmpty = True
ElseIf (HasUnoInterfaces(oSel, "com.sun.star.drawing.XShape")) Then
' Selected single object - selection is not empty; do nothing '
ElseIf (HasUnoInterfaces(oSel, "com.sun.star.sheet.XSheetCellRange")) Then
' Something is selected anyway '
ElseIf (oSel.Count = 0) Then
IsSelectionEmpty = True
ElseIf ((oSel.Count = 1) And oSel.supportsService("com.sun.star.text.TextRanges")) Then
With oSel(0)
If (.text.compareRegionStarts(.getStart, .getEnd)=0) Then
IsSelectionEmpty = True
End If
End With
End If
End Function
Function IsTextRangeInsideRange(ByRef oRange1, ByRef oRange2)
IsTextRangeInsideRange = (oRange2.text.compareRegionStarts(oRange1, oRange2)<=0)_
And (oRange2.text.compareRegionEnds(oRange1, oRange2)>=0)
End Function
Function IsInSelection(ByRef oObj, ByRef oSel)
Dim i As Long
If (IsSelectionEmpty(oSel)) Then
IsInSelection = True
ElseIf (HasUnoInterfaces(oSel, "com.sun.star.drawing.XShape")) Then
IsInSelection = EqualUnoObjects(oObj, oSel)
ElseIf (HasUnoInterfaces(oSel, "com.sun.star.drawing.XShapes")) Then
IsInSelection = False
For i = 0 To oSel.Count - 1
If (EqualUnoObjects(oObj, oSel(i))) Then
IsInSelection = True
Exit For
End If
Next i
Else
IsInSelection = False
For i = 0 To oSel.Count - 1
If (IsTextRangeInsideRange(oObj.Anchor, oSel(i))) Then
IsInSelection = True
Exit For
End If
Next i
End If
End Function
After you identified that object is inside selection, then you need to check that it has proper type (e.g., it is an image), and perform required actions.
HTH.
Hello @shystar, and welcome to the Ask.LibreOffice forum!
To shrink ( or enlarge ) the selected images in the current Writer document, you could use the following Basic macro:
Sub Writer_Resize_Selected_Images( dPercentage As Double )
REM Resizes selected Images in the current Writer document.
REM <dPercentage> : Factor by which to scale each image ( 1.0 = 100% ).
Dim oDoc As Object : oDoc = ThisComponent
Dim oSelection As Object : oSelection = oDoc.CurrentSelection
Dim oSel As Object
Dim oEnum As Object
Dim oEnum2 As Object
Dim oEnum3 As Object
Dim oParagraph As Object
Dim oContent As Object
Dim oPortion As Object
Dim aNewSize As New com.sun.star.awt.Size
Dim i As Integer
If oSelection.supportsService( "com.sun.star.text.TextGraphicObject" ) Then
aNewSize.Width = oSelection.Size.Width * dPercentage
aNewSize.Height = oSelection.Size.Height * dPercentage
oSelection.setSize( aNewSize )
ElseIf oSelection.supportsService( "com.sun.star.text.TextRanges" ) Then
For i = 0 To oSelection.getCount() - 1 REM Traverse Selections.
oSel = oSelection.getByIndex( i )
oEnum = oSel.createEnumeration()
Do While oEnum.hasMoreElements() REM Traverse Paragraphs.
oParagraph = oEnum.nextElement()
oEnum2 = oParagraph.createEnumeration()
Do While oEnum2.hasMoreElements() REM Traverse TextPortions.
oPortion = oEnum2.nextElement()
oEnum3 = oPortion.createContentEnumeration( "com.sun.star.text.TextContent" )
Do While oEnum3.hasMoreElements() REM Traverse TextContents.
oContent = oEnum3.nextElement()
If oContent.supportsService( "com.sun.star.text.TextGraphicObject" ) Then
aNewSize.Width = oContent.Size.Width * dPercentage
aNewSize.Height = oContent.Size.Height * dPercentage
oContent.setSize( aNewSize )
End If
Loop
Loop
Loop
Next i
End If
End Sub
With Regards,
lib