[Solved] TextFrames in Writer

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
Cogito ergo sum
Posts: 13
Joined: Sun May 13, 2018 8:40 am

[Solved] TextFrames in Writer

Post by Cogito ergo sum »

Would I be right in assuming no methods are available for programming textframe properties in Writer? To test I set the macro recorder in action and made a text frame with custom size, frame thickness and colour. When I played it back it produced the text frame but without the custom frame style and colour. If Basic can do these Things would someone show me how? Thanks.
Last edited by Cogito ergo sum on Sun Aug 12, 2018 12:03 pm, edited 2 times in total.
OpenOffice 5.3.6.1 on Windows 7
FJCC
Moderator
Posts: 9248
Joined: Sat Nov 08, 2008 8:08 pm
Location: Colorado, USA

Re: TextFrames in Writer

Post by FJCC »

It is wrong to equate the capabilities of the macro recorder and the capabilities of macros in general. If you want to do serious macro programming, you have to learn the API (Application Programming Interface) . Andrew Pitonyak's macro book and macro document (http://www.pitonyak.org/oo.php) are good places to start.
Here is how to manipulate some properties of a text frame.

Code: Select all

  oTextFrames = ThisComponent.getTextFrames()
  oFrame = oTextFrames.getByName("Frame1")
  
  aBorder = oFrame.BottomBorder 
  aBorder.OuterLineWidth = 4
  aBorder.Color = RGB(255,0,0) 'red
  
  oFrame.BottomBorder = aBorder
  oFrame.LeftBorder = aBorder
  oFrame.RightBorder = aBorder
  oFrame.TopBorder = aBorder
  
  
  Size = oFrame.Size
  Size.Width = 3000
  Size.Height = 1500
  
  oFrame.Size = Size
OpenOffice 4.1 on Windows 10 and Linux Mint
If your question is answered, please go to your first post, select the Edit button, and add [Solved] to the beginning of the title.
Cogito ergo sum
Posts: 13
Joined: Sun May 13, 2018 8:40 am

Re: TextFrames in Writer

Post by Cogito ergo sum »

Many thanks for this help. You're right of course about the need to learn the API and indeed I am in the process. I have tried Pitonyak and got a lot of help there, but it's pretty turgid stuff at times, and assumes some familiarity with more advanced programming routine which I don't have. Otherwise the help available online seems pretty scanty and demands a lot of time and perseverance to find and adapt.
I found that "OuterLineWidth" had no effect whereas just "LineWidth" works fine. I don't know if this is because I have the Libre Office version. I'm particularly interested in stand alone macros so I can just click an icon instead of first having to open the Writer program and then fish around in the Tools|Macros menu after the right script I once wrote but probably lost after I re-installed. As far as I can tell that more or less means VBScript if I'm restricted to Windows native scripting possibilities. So let's make a dreadful coloured address label in VBS:

Code: Select all



      Dim args()

      Set objServiceManager= CreateObject ("com.sun.star.ServiceManager")
      Set oDsk= objServiceManager.createInstance("com.sun.star.frame.Desktop")
      Set oDoc = oDsk.loadComponentFromURL _
             ("private:factory/swriter", "_blank", 0, args)
      Set oViewCursor = oDoc.CurrentController.getViewCursor()

      Set objText= oDoc.getText
      Set objCursor= objText.createTextCursor

      Set oFrame1 = oDoc.createInstance("com.sun.star.text.TextFrame")


      objText.insertTextContent objCursor, oFrame1, false

      Set oTextFrames = oDoc.getTextFrames()
      Set oFrame = oTextFrames.getByName("Frame1")

      oFrame.IsFollowingTextFlow = False
      oFrame.FrameIsAutomaticHeight = 0
      oFrame.AnchorType = 1

      Set aborder = oFrame.BottomBorder
      aBorder.Color = RGB(0,0,255)
      aBorder.LineWidth = 80

      Set bborder = oFrame.TopBorder
      bBorder.Color = RGB(0,255,0)
      bBorder.LineWidth = 40

      Set cborder = oFrame.LeftBorder
      cBorder.Color = RGB(255,0,0)
      cBorder.LineWidth = 120

      Set dborder = oFrame.RightBorder
      dBorder.Color = RGB(60,200,240)
      dBorder.LineWidth = 100

      oFrame.BottomBorder = aBorder
      oFrame.TopBorder = bBorder
      oFrame.LeftBorder = cBorder
      oFrame.RightBorder = dBorder

      Set Size = oFrame.Size
      Size.Width = 10000
      Size.Height = 4000
      oFrame.Size = Size


      Set oTxFrameCursor = oFrame.createTextCursor()
      oTxFrameCursor.CharFontName="Segoe Print"
      oTxFrameCursor.CharColor = RGB(100,0,0)
      oTxFrameCursor.CharHeight="15"
      oTxFrameCursor.CharWeight=150.0
      oTxFrameCursor.String = "This would be recipients name" & VbCr
      oTxFrameCursor.gotoEnd(False) 
      oTxFrameCursor.CharHeight="13"
      oTxFrameCursor.CharFontName="Verdana"
      oTxFrameCursor.CharColor = RGB(100,0,0)
      oTxFrameCursor.CharWeight=100.0
      oTxFrameCursor.String = "This line contains his/her street address" & VbCr
      oTxFrameCursor.gotoEnd(False) 
      oTxFrameCursor.String = "Town/City and Post number" & VbCr
      oTxFrameCursor.gotoEnd(False) 
      oTxFrameCursor.String = "County/State" & VbCr
      oTxFrameCursor.gotoEnd(False) 
      oTxFrameCursor.String = "Country"

      objText.insertString objCursor, VbCr & VbCr, false
This works great except that it doesn't quite work for me because the result is a 'No such element exception' error message but this is only because in my language Open Office automatically calls its first frame not "Frame1" but "Ramme1" so if I change that then there's no problem. But it seems curious to me that you have to be able to predict what the name of the element is going to be - or perhaps it's possible in some way to determine that yourself?
The other curious thing that strikes me is that you must define parameters for each border individually and apparently can't just have a general borders.color=red borders.thickness = 50 or whatever. Or you can do as you have and define parameters for one of the borders and then just adapt the same to the other borders. Not that it matters that much of course it just seems it would be more economical to envelope the Whole in one line.
Again thanks for the help.
OpenOffice 5.3.6.1 on Windows 7
User avatar
Lupp
Volunteer
Posts: 3542
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: [Solved] TextFrames in Writer

Post by Lupp »

To hell with counterproductive "localisation"!

However, you don't need the automatically applied name to get access to a newly inserted TextFrame. If you don't create and insert the frame in one go with the help of the DispatchHelper, but explicitly create it first and then insert it using a myText.InsertTextContent method, you have a grip on the object anyway, can edit its properties, and also can ask it for its name.

See attached demo.

(To be clear: I never used such a macro "in production". I'm not fond of much "document automation".
AND: The frames already inserted into the attached document partly got different properties -anchoring e.g!- due to changes I made in-betwen to hard coded attributes in the Sub. Generally the passing of parameters is a problem aggravating a reasonable use of macros.
AND: No "recorded" content there!
AND: The demo is 2 days old, and I forgot the details since, of course.
AND (BTW): Line 11 of the code is obsolete. You can, however, use any valid TextCursor created in any way in place of insPos in Line 26. Regarding this, insPos is named misleading in Line 6.)
Attachments
aoo94645insertTextFrame.odt
(27.46 KiB) Downloaded 222 times
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
Cogito ergo sum
Posts: 13
Joined: Sun May 13, 2018 8:40 am

Re: [Solved] TextFrames in Writer

Post by Cogito ergo sum »

Lupp - thanks for your contribution, I couldn't get your macro to produce anything in Libre Office unfortunately, but a minor adjustment in the line

  • newFrame.FrameStyleName = "fsMyFrame"
    to simply
    newFrame.Name = "fsMyFrame"

set me on the right track. I don't stop to consider whether I'm "fond of" automating documents or not, I'm just interested in cutting out boring repetitive work wherever possible. For a secretary for example such a macro might easily reproduce an identical letter to a hundred recipients from a data base, with individual address labels. Not that I'm not aware that there probably are a hundred other ways of doing something like that, which might also be better, but that is just an example. It's satisfying just to know you can do it yourself if needs be, without any fancy expensive tools. I think with your help I now have full control over TextFrames! And this is much faster than waiting for Open Office to go through it's wakeup routine with splash screen and all, and THEN having to find the blinking code buried in the macro library by first opening a dialog, then selecting the correct library then searching through the modules and finally clicking the Sub you want executed. Don't take my word for it - try it!

Code: Select all

     Dim args(1)

     Set objServiceManager= CreateObject ("com.sun.star.ServiceManager")
     Set oDsk= objServiceManager.createInstance("com.sun.star.frame.Desktop")
     Set oDoc = oDsk.loadComponentFromURL _
         ("private:factory/swriter", "_blank", 0, args)
     Set docFrame = oDoc.CurrentController.Frame
     docFrame.ContainerWindow.ismaximized = true

     Set objText= oDoc.getText
     Set objCursor= objText.createTextCursor

     Set oTxtFrame1 = oDoc.createInstance("com.sun.star.text.TextFrame")
     oTxtFrame1.Name = "fsMyFrame"

     objText.insertTextContent objCursor, oTxtFrame1, false

     Set oTextFrames = oDoc.getTextFrames()
     Set oTxtFrame = oTextFrames.getByName("fsMyFrame")

     oTxtFrame.IsFollowingTextFlow = False
     oTxtFrame.FrameIsAutomaticHeight = 0
     oTxtFrame.AnchorType = 2

     Set aborder = oTxtFrame.BottomBorder
     aBorder.Color = RGB(0,0,255)
     aBorder.LineWidth = 80

     Set bborder = oTxtFrame.TopBorder
     bBorder.Color = RGB(0,255,0)
     bBorder.LineWidth = 40

     Set cborder = oTxtFrame.LeftBorder
     cBorder.Color = RGB(255,0,0)
     cBorder.LineWidth = 120

     Set dborder = oTxtFrame.RightBorder
     dBorder.Color = RGB(60,200,240)
     dBorder.LineWidth = 100

     oTxtFrame.BottomBorder = aBorder
     oTxtFrame.TopBorder = bBorder
     oTxtFrame.LeftBorder = cBorder
     oTxtFrame.RightBorder = dBorder

     Set Size = oTxtFrame.Size
     Size.Width = 10000
     Size.Height = 4000
     oTxtFrame.Size = Size

     oTxtFrame.HoriOrient = 0
     oTxtFrame.VertOrient = 0

     oTxtFrame.setPropertyValue "BackColor", 5111847
     oTxtFrame.setPropertyValue "FillTransparence", 90

     oTxtFrame.VertOrientPosition = 1500
     oTxtFrame.HoriOrientPosition = 1500

     Set oTxFrameCursor = oTxtFrame.createTextCursor()
     oTxFrameCursor.CharFontName="Segoe Print"
     oTxFrameCursor.CharColor = RGB(100,0,0)
     oTxFrameCursor.CharHeight="15"
     oTxFrameCursor.CharWeight=150.0
     oTxFrameCursor.String = "This would be recipients name" & VbCr
     oTxFrameCursor.gotoEnd(False)
     oTxFrameCursor.CharHeight="13"
     oTxFrameCursor.CharFontName="Verdana"
     oTxFrameCursor.CharColor = RGB(100,0,0)
     oTxFrameCursor.CharWeight=100.0
     oTxFrameCursor.String = "This line contains his/her street address" & VbCr
     oTxFrameCursor.gotoEnd(False)
     oTxFrameCursor.String = "Town/City and Post number" & VbCr
     oTxFrameCursor.gotoEnd(False)
     oTxFrameCursor.String = "County/State" & VbCr
     oTxFrameCursor.gotoEnd(False)
     oTxFrameCursor.String = "Country"
OpenOffice 5.3.6.1 on Windows 7
Post Reply