Get anchor "object" of images

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Get anchor "object" of images

Post by musikai »

Hi,

in Writer: Is there a way to find out where an image is anchored to? If it's anchored in the text, a header, textframe, table.

The reason is: I can modify all images that are within a text selection as long as the images are anchored in the text but when there are images in header, textframes or tables in the document, then the anchor position can't be compared anymore with the selection range:

Code: Select all

sub changeimageswithinselection
oDoc = ThisComponent
oText = oDoc.Text
oRange = oDoc.currentSelection(0)
  
    go = oDoc.getGraphicObjects
    For i = 0 to go.Count-1
    g = go.getByIndex(i)

 if  oRange.text.compareRegionStarts(oRange.getStart, oRange.getEnd)=0 then    'if no selection then process all images
g.AdjustRed=100 
 elseif  oRange.text.compareRegionStarts(g.anchor, oRange)=1 OR  oRange.text.compareRegionEnds(g.anchor, oRange)=-1 then     'out of selection
  else      'images within selection range
g.AdjustRed=100 
 end if

 next
end sub
Last edited by musikai on Fri Dec 11, 2015 7:36 pm, edited 2 times in total.
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
B Marcelly
Volunteer
Posts: 1160
Joined: Mon Oct 08, 2007 1:26 am
Location: France, Paris area

Re: Get anchor "object" of images

Post by B Marcelly »

Hi,
At first, a simple test : is the graphic object anchored to the main text ?

Code: Select all

oDoc = ThisComponent
oText = oDoc.Text
oRange = oDoc.currentSelection(0)

selText = oRange.Anchor.Text
if EqualUnoObjects(oText, selText)  then
  MsgBox("Graphic anchored directly to the Main text")
else
  MsgBox("Graphic anchored elsewhere")
end if
But if you want to find where exactly it is anchored at, you need a much more complex and recursive code.
Because you can store an image in the main text, in a frame, in a cell of a text table; the frame or text table may be inside another text table or frame, etc. An image may be stored in the main text, a header, a footer, a footnote. Etc, etc...
Bernard

OpenOffice.org 1.1.5 / Apache OpenOffice 4.1.1 / LibreOffice 5.0.5
MS-Windows 7 Home SP1
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

Thank you for the idea to use EqualUnoObjects() to find out the images that are anchored elsewhere. Your code works well on (selected) images (that is g in my code).
My problem is: As I test all images in the document if they are anchored inside or outside of the selected text range, I get a crash when they are anchored not in the main text. So I would have to either exlude these before compareRegionStarts() (not so great) or find eg. the anchor of the image frame and test this anchor position.


But thank you! I will have a further look into EqualUnoObjects() and related things.
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

images in textframes are now also tested if they are in selection range:

Code: Select all

sub changeimageswithinselection2
oDoc = ThisComponent
oText = oDoc.Text
go = oDoc.getGraphicObjects
oFrames = oDoc.getTextFrames()
oRange = oDoc.currentSelection(0)


For i = 0 to go.Count-1
 g = go.getByIndex(i)
    
 if oRange.text.compareRegionStarts(oRange.getStart, oRange.getEnd)=0  then    'if no selection then process all images
    gosub processimage
 elseif EqualUnoObjects(oText, g.anchor.Text)=false then   'if image anchor not in main text compare it with textframes
    For l = 0 to oFrames.Count-1
    oFrame = oFrames.getByIndex(l)
  
      if oText.compareRegionStarts(oFrame.anchor, oRange)=1 OR  oText.compareRegionEnds(oFrame.anchor, oRange)=-1 then       'out of selection
      elseif  EqualUnoObjects(oFrame.text, g.anchor.Text)=true then
      gosub processimage
      
      end if 
    next
   
 elseif oText.compareRegionStarts(g.anchor, oRange)=1 OR  oText.compareRegionEnds(g.anchor, oRange)=-1 then       'out of selection
 else      'images within selection range
 gosub processimage

 end if

next
exit sub

processimage:
g.AdjustRed=50
RETURN
end sub
This is done by comparing the anchor of the textframes with the selection range. But how can I find out if an image is in Header/Footer. And how can I test if a texttable is in selection range?
Last edited by musikai on Fri Dec 11, 2015 7:38 pm, edited 1 time in total.
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

ok,
just to answer my own question about how to test if images are in header oder footer:
This code processes all images of the document but exclude images in header and footer.

Code: Select all

sub excludeheaderfooterimages
oDoc = thiscomponent
go = oDoc.getGraphicObjects
StyleFamilies = oDoc.StyleFamilies
PageStyles = StyleFamilies.getByName("PageStyles")

For i = 0 to go.Count-1
        g = go.getByIndex(i)
        isinHeaderOrFooter = 0
        
        For n = 0 to PageStyles.Count-1
    
        DefPage = PageStyles.getByIndex(n)
        
        HContent = DefPage.HeaderText
        HContentL = DefPage.HeaderTextLeft
        HContentR = DefPage.HeaderTextRight       
        FContent = DefPage.FooterText
        FContentL = DefPage.FooterTextLeft
        FContentR = DefPage.FooterTextRight
        
        if EqualUnoObjects(g.anchor.text, HContent)=true OR EqualUnoObjects(g.anchor.text, HContentL)=true Or EqualUnoObjects(g.anchor.text, HContentR)=true OR EqualUnoObjects(g.anchor.text, FContent)=true OR EqualUnoObjects(g.anchor.text, FContentL)=true Or EqualUnoObjects(g.anchor.text, FContentR)=true then isinHeaderOrFooter=1
       
        next 
        
if isinHeaderOrFooter=0 then g.AdjustRed=100

next
end sub
But what I really would like to know is a way to find out if a texttable is within a selection range. ???
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

The anchor of TextTables can't be compared with a text range (as opposed to anchors of TextGraphicObjects and TextFrames.) So instead I get all texttables that are in the current selection.
This code processes a selected image, or if nothing is selected all images of the document, or if a textrange is selected then all images within the selection. Images can be in TextFrames and TextTables. Doesn't work with more interleaved situations.

Code: Select all

sub changeimageswithinselection5   'with textframes and texttables
oDoc = ThisComponent
oText = oDoc.Text
go = oDoc.getGraphicObjects
oFrames = oDoc.getTextFrames()
oTables = oDoc.getTextTables()
oRange = oDoc.currentSelection(0)

g = ThisComponent.CurrentSelection(0)
if g.supportsService("com.sun.star.text.TextGraphicObject")=true then  'single image selected
    gosub processimage
else 'no single image selected
    For i = 0 to go.Count-1
        g = go.getByIndex(i)
    
      if oRange.text.compareRegionStarts(oRange.getStart, oRange.getEnd)=0  then    'if no selection then process all images
         gosub processimage
      elseif EqualUnoObjects(oText, g.anchor.Text)=false then   'if image anchor not in main text compare it with texttables
rem--------textframes
        For l = 0 to oFrames.Count-1
        oFrame = oFrames.getByIndex(l)
  
          if oText.compareRegionStarts(oFrame.anchor, oRange)=1 OR  oText.compareRegionEnds(oFrame.anchor, oRange)=-1 then       'out of selection
          elseif  EqualUnoObjects(oFrame.text, g.anchor.Text)=true then
            gosub processimage
          end if 
        next l

rem--------texttables
        oTextElementEnum = thisComponent.getCurrentSelection().getByIndex(0).createEnumeration()

        while oTextElementEnum.hasMoreElements()
        oTextElement = oTextElementEnum.nextElement

           if oTextElement.supportsService("com.sun.star.text.TextTable") then
             oTable =  oTextElement
             cellnames = oTable.getCellNames() 
             For c = LBound(cellnames) To UBound(cellnames)
             cellname = cellnames(c)
 
               if EqualUnoObjects(g.anchor.text, oTable.getCellByName(cellname))=true then  'if image is in any cell of table
               gosub processimage
               end if
        
             next c
           end if  
       wend
   
      elseif oText.compareRegionStarts(g.anchor, oRange)=1 OR  oText.compareRegionEnds(g.anchor, oRange)=-1 then       'out of selection
      else      'images within selection range
         gosub processimage
 
      end if

    next i
end if 'no single image selected
exit sub

processimage:
g.AdjustRed=100
RETURN
end sub
Last edited by musikai on Fri Dec 11, 2015 7:39 pm, edited 2 times in total.
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

Hi,
images anchored to page can't be compared with selection range. So let's filter them out for selection range (at the moment).

Images anchored to a frame must be treated differently than if anchored to paragraph, to/as character of the frame text. While for the latter EqualUnoObjects(oFrame.text, image.anchor.Text)=true, it is not when the anchored to the frame. But then you can directly get the frame of the anchor with image.AnchorFrame.name . That is nice!

Code: Select all

sub changeimageswithinselection6   'with textframes and texttables, Anchor at frames/page supported
oDoc = ThisComponent
oText = oDoc.Text
go = oDoc.getGraphicObjects
oFrames = oDoc.getTextFrames()
oTables = oDoc.getTextTables()
oRange = oDoc.currentSelection(0)

g = ThisComponent.CurrentSelection(0)
if g.supportsService("com.sun.star.text.TextGraphicObject")=true then  'single image selected
    gosub processimage
else 'no single image selected
    For i = 0 to go.Count-1
        g = go.getByIndex(i)
    
      if oRange.text.compareRegionStarts(oRange.getStart, oRange.getEnd)=0  then    'if no selection then process all images
         gosub processimage
      elseif g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_PAGE then 'don't process images anchored to page
      elseif EqualUnoObjects(oText, g.anchor.Text)=false  or g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_FRAME then   'if image anchor not in main text or is anchored to frame compare it with texttables
rem--------textframes
        For l = 0 to oFrames.Count-1
        oFrame = oFrames.getByIndex(l)
  
          if oText.compareRegionStarts(oFrame.anchor, oRange)=1 OR  oText.compareRegionEnds(oFrame.anchor, oRange)=-1 then       'out of selection
          elseif  EqualUnoObjects(oFrame.text, g.anchor.Text)=true then   
            gosub processimage
          elseif g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_FRAME then
              if g.AnchorFrame.name = oFrame.name then gosub processimage
          end if 
        next l

rem--------texttables
        oTextElementEnum = thisComponent.getCurrentSelection().getByIndex(0).createEnumeration()

        while oTextElementEnum.hasMoreElements()
        oTextElement = oTextElementEnum.nextElement

           if oTextElement.supportsService("com.sun.star.text.TextTable") then
             oTable =  oTextElement
             cellnames = oTable.getCellNames() 
             For c = LBound(cellnames) To UBound(cellnames)
             cellname = cellnames(c)
 
               if EqualUnoObjects(g.anchor.text, oTable.getCellByName(cellname))=true then  'if image is in any cell of table
               gosub processimage
               end if
        
             next c
           end if  
       wend
   
      elseif oText.compareRegionStarts(g.anchor, oRange)=1 OR  oText.compareRegionEnds(g.anchor, oRange)=-1 then       'out of selection
      else      'images within selection range
         gosub processimage
 
      end if

    next i
end if 'no single image selected
exit sub

processimage:
g.AdjustRed=100
RETURN
end sub
Last edited by musikai on Fri Dec 11, 2015 7:40 pm, edited 1 time in total.
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

ok, here is the opus:
for changing multiple images depending on selection range. Images can be in frames or in texttables (but not more complex situations like images in frames in a table).
If cursor is a point (no selection) then all images will be changed (also in header, footer, foot- and end-notes, or anchored to page or images in frames in frames etc.).
If a selection range in document is made all images within the selection are changed. if there are frames or tables within the selection range then all contained images will be changed.
Selection range can also be in a table, frame or header, footer etc.
You can select an image to be changed. If you select a frame, all images in the frame will be changed. You can make table range selections.
Perhaps all this could be solved more elegant and better and I will have a look at it someday.
If you ask yourself what is it all about - only to adjust the Red?, then have a look at the PicTool of the free Project in my Signature. If I managed to make an extension of that tool alone, I will post it in the extension thread.

Code: Select all

sub changeimageswithinselection7   'with textframes and texttables, Anchor at frames or pages, Textframe selection, selection range also in not main text
oDoc = ThisComponent
oText = oDoc.Text
go = oDoc.getGraphicObjects
oFrames = oDoc.getTextFrames()
oTables = oDoc.getTextTables()
oRange = oDoc.currentSelection(0)

g = ThisComponent.CurrentSelection(0)
if g.supportsService("com.sun.star.text.TextGraphicObject")=true then  'single image selected
    gosub processimage
elseif g.supportsService("com.sun.star.text.TextFrame") then  'Textframe selected
oFrame = g
    For i = 0 to go.Count-1
        g = go.getByIndex(i)

        if  EqualUnoObjects(oFrame.text, g.anchor.Text)=true then
            gosub processimage
        elseif g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_FRAME then
            if g.AnchorFrame.name = oFrame.name then gosub processimage
        end if
    next i
    
else 'no single image selected
    For i = 0 to go.Count-1
        g = go.getByIndex(i)
rem------TextTable cellrange selection
      if oRange.supportsService("com.sun.star.text.TextTableCursor") Then
       oTextTable = ThisComponent.CurrentController.ViewCursor.TextTable

        if instr(oRange.RangeName, ":")>0 then 
        selrange = oTextTable.getCellRangeByName(oRange.RangeName)
rem---------------------------------------------------
        iNumCols = UBound(selrange.getColumnDescriptions())
        iNumRows = UBound(selrange.GetRowDescriptions())
         For iCol = 0 To iNumCols
           For iRow = 0 To iNumRows
           oCell = selrange.getCellByPosition(iCol, iRow)
               if EqualUnoObjects(g.anchor.text,oCell)=true then  'if image is in selected cell of table
               gosub processimage
               end if
           Next
         Next
rem----------alternatively---------------------------------
' oData() = selrange.getDataArray()
' For i = LBound(oData()) To UBound(oData())
' oRow() = oData(i)
' For j = LBound(oRow()) To UBound(oRow())
'   oCell = selrange.getCellByPosition(j,i)
'              if EqualUnoObjects(g.anchor.text,oCell)=true then  'if image is in selected cell of table
'              gosub processimages
'              end if
' Next j 
' Next i   
rem---------------------------------------------   
        else    'if cellrange is only 1 single cell (eg. in complex tables) 
               oCell = oTextTable.getCellByName(oRange.RangeName) 
               if EqualUnoObjects(g.anchor.text,oCell)=true then  'if image is in selected cell of table
               gosub processimage
               end if
        end if
rem--------if no selection then process all images    
      elseif oRange.text.compareRegionStarts(oRange.getStart, oRange.getEnd)=0  then    'if no selection then process all images
         gosub processimage
rem--------don't process images anchored to page
      elseif g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_PAGE then 'don't process images anchored to page
rem--------if selection range is not in main text eg.textframe, 1tablecelltext, footer etc.
      elseif EqualUnoObjects(oRange.text, oText)=false then 'if selection range is not in main text eg.textframe, 1tablecelltext, footer etc.
                if EqualUnoObjects(oRange.text, g.anchor.Text)=false or g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_FRAME then  
                elseif oRange.text.compareRegionStarts(g.anchor, oRange)=1 OR  oRange.text.compareRegionEnds(g.anchor, oRange)=-1 then       'out of selection
                else 
                gosub processimage
                end if
rem----if image anchor not in main text or is anchored to frame compare it with textframes and texttables
      elseif EqualUnoObjects(oText, g.anchor.Text)=false  or g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_FRAME then   'if image anchor not in main text or is anchored to frame compare it with texttables
rem--------textframes
        For l = 0 to oFrames.Count-1
        oFrame = oFrames.getByIndex(l)
  
          if oText.compareRegionStarts(oFrame.anchor, oRange)=1 OR  oText.compareRegionEnds(oFrame.anchor, oRange)=-1 then       'out of selection
          elseif  EqualUnoObjects(oFrame.text, g.anchor.Text)=true then   
            gosub processimage
          elseif g.AnchorType = com.sun.star.text.TextContentAnchorType.AT_FRAME then
              if g.AnchorFrame.name = oFrame.name then gosub processimage
          end if 
        next l

rem--------texttables
        oTextElementEnum = thisComponent.getCurrentSelection().getByIndex(0).createEnumeration()

        while oTextElementEnum.hasMoreElements()
        oTextElement = oTextElementEnum.nextElement

           if oTextElement.supportsService("com.sun.star.text.TextTable") then
             oTable =  oTextElement
             cellnames = oTable.getCellNames() 
             For c = LBound(cellnames) To UBound(cellnames)
             cellname = cellnames(c)
 
               if EqualUnoObjects(g.anchor.text, oTable.getCellByName(cellname))=true then  'if image is in any cell of table
               gosub processimage
               end if
        
             next c
           end if  
       wend
rem------regular selection   
      elseif oText.compareRegionStarts(g.anchor, oRange)=1 OR  oText.compareRegionEnds(g.anchor, oRange)=-1 then       'out of selection
      else      'images within selection range
         gosub processimage
 
      end if

    next i
end if 'no single image selected
exit sub

processimage:
g.AdjustRed=100
RETURN
end sub
Last edited by musikai on Fri Dec 11, 2015 7:43 pm, edited 1 time in total.
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
musikai
Volunteer
Posts: 294
Joined: Wed Nov 11, 2015 12:19 am

Re: Get anchor "object" of images

Post by musikai »

This code is now part of the PicTool:
viewtopic.php?f=47&t=80586
or
OpenOffice4 extension:
http://extensions.openoffice.org/de/node/18393
LibreOffice4 extension:
http://extensions.libreoffice.org/exten ... er-pictool
Win7 Pro, Lubuntu 15.10, LO 4.4.7, OO 4.1.3
Free Project: LibreOffice Songbook Architect (LOSA)
http://struckkai.blogspot.de/2015/04/li ... itect.html
Post Reply