LibreOffice Basic: iterate through all images in a selection?

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