[Python] Generating Writer document with more complex format

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

[Python] Generating Writer document with more complex format

Post by _savage »

Hi,

Hopefully I find what I am looking for here... :? The information I found online so far seems rather sparse, and the forums over at LibreOffice hold no responses. If anyone is interested, here or here or here are questions I've asked previously, some of which I've figured out by now.

Through lots of trial-and-error on a Python prompt and poking around the API documentation here or here I've made some progress and I'm able to produce a document with some formatting. However, there are still questions left that I can't answer:
  1. How can I create a new paragraph style? I can use existing paragraph styles for heading and such, but I'd need to attach a few more custom styles to select paragraphs throughout the document.
  2. How do I insert an image?
  3. How do I insert a footnote?
Am I correct that page breaks and chapter starts on right pages are all properties of, say, the "Heading 1" paragraph style, and I can modify them directly there?

Thanks heaps!
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
FJCC
Moderator
Posts: 9248
Joined: Sat Nov 08, 2008 8:08 pm
Location: Colorado, USA

Re: [Python] Generating Writer document with more complex fo

Post by FJCC »

Here are bare bones answers to the first two questions.

Code: Select all

import uno
oDoc = XSCRIPTCONTEXT.getDocument()
def AddStyleFunc():
  Style = oDoc.createInstance("com.sun.star.style.ParagraphStyle")
  ParaStyles = oDoc.StyleFamilies.getByName("ParagraphStyles")
  ParaStyles.insertByName("NewStyle", Style)

def AddGraphic():
  GraphObj = oDoc.createInstance("com.sun.star.text.GraphicObject")
  GraphObj.GraphicURL = "file:///C:/MyPicture.JPG"
  oText = oDoc.Text
  VC = oDoc.CurrentController.ViewCursor
  oText.insertTextContent(VC.Start, GraphObj, False)
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.
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

Thank you FJCC :) I'll give this a try later today. Another quesion regarding your code...
FJCC wrote:

Code: Select all

import uno
oDoc = XSCRIPTCONTEXT.getDocument()
    ...
I've seen this XSCRIPTCONTEXT quite a bit in forums, how does that differ to getting a Document as described in this blog?
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
FJCC
Moderator
Posts: 9248
Joined: Sat Nov 08, 2008 8:08 pm
Location: Colorado, USA

Re: [Python] Generating Writer document with more complex fo

Post by FJCC »

Either way you end up with the same object as far as I know. I use XSCRIPTCONTEXT.getDocument() because I can remember it.
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.
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

FJCC: Thank you so much: the functions you suggested above work flawlessly :super: Now I'll have to figure out ordered/unordered lists and the footnotes.

Can you suggest reading material and documentation? I found it difficult to read the UNO API (for Java or C++) and map that to the Python implementation...

As for the XSCRIPTCONTEXT, that didn't work for me:

Code: Select all

Python 3.3.0 (default, Mar 26 2013, 10:55:35) 
[GCC 4.0.1 (Apple Inc. build 5494)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import uno
>>> document = XSCRIPTCONTEXT.getDocument()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'XSCRIPTCONTEXT' is not defined
This is for LibreOffice4, however, there might be differences with the OpenOffice branch? I went back to the way I used before

Code: Select all

>>> local = uno.getComponentContext()
>>> resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
>>> context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
>>> desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context)
>>> document = desktop.loadComponentFromURL("private:factory/swriter", "_blank", 0, ())
>>> cursor = document.Text.createTextCursor()
and that works just fine.
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: [Python] Generating Writer document with more complex fo

Post by hanya »

Can you suggest reading material and documentation? I found it difficult to read the UNO API (for Java or C++) and map that to the Python implementation...
No Python specific one is there. The PyUNO binding maps between these API and calling methods by Python callable.
As for the XSCRIPTCONTEXT, that didn't work for me:
XSCRIPTCONTEXT is provided only for the module executed as Python macro, see: http://wiki.openoffice.org/wiki/Documen ... rom_macros
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

Thanks hanya and FJCC for the answers so far :super:

For safekeeping and maybe because others may benefit from this, I'm just going to post a few more answers here, but I will also keep asking question if I'm stuck. Perhaps the discussion will be helpful in the future.

So here is the code that inserts numbered footnotes into the text. Assume the document's cursor sits right after some text which requires a footnote:

Code: Select all

document.Text.insertString(cursor, "This text gets the footnote.", 0)
footnote = document.createInstance("com.sun.star.text.Footnote")
document.Text.insertTextContent(cursor, footnote, 0)
footnotecursor = footnote.Text.createTextCursor()
footnote.insertString(footnotecursor, "This is the actual footnote.", 0)
document.Text.insertString(cursor, " And here is more text following the footnote", 0)
This assumes that "document" and "cursor" are set up according the the code snipped from the reply above.

Next things to tackle are:
* Numbered and unnumbered lists.
* Figuring out when and when not to use a PARAGRAPH_BREAK.
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: [Python] Generating Writer document with more complex fo

Post by hanya »

Code: Select all

document.Text.insertString(cursor, "This text gets the footnote.", 0)
PyUNO object is not simple Python object but it is the wrapper object that references instance of the office. When you access to Text with "." operator, new instance is created for each call. If it is temporally object, the new instance is created and then died. In most case, this is not wrong for performance but I suggest to keep it into a variable.
This is happen on each method callings, I sometimes keep method instance into a variable if I need to call it many times.
* Numbered and unnumbered lists.
Apply the paragraph style to the paragraph that bound to numbering style with NumberingStyleName property. Numbering styles are little bit complicated. Please learn how to use object inspector.
* Figuring out when and when not to use a PARAGRAPH_BREAK
Depends on the structure of your document. Use template document if you have some static parts in your document.
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

hanya wrote:PyUNO object is not simple Python object but it is the wrapper object that references instance of the office. When you access to Text with "." operator, new instance is created for each call. If it is temporally object, the new instance is created and then died. In most case, this is not wrong for performance but I suggest to keep it into a variable. This is happen on each method callings, I sometimes keep method instance into a variable if I need to call it many times.
You mean a

Code: Select all

# document.Text.insertString(...)
text = document.Text
text.insertString(...)
text.insertString(...)
...
is a cleaner way of doing this? I assume then this goes for every object created by a "." operator here? Thanks for the tip!
hanya wrote:Apply the paragraph style to the paragraph that bound to numbering style with NumberingStyleName property. Numbering styles are little bit complicated. Please learn how to use object inspector.
Can I just modify the "Default style" for that paragraph or should I generate a new one for the lists?

Do you have a link to the object inspector and how to use it? I've looked around for useful documentation and just can't find much!
hanya wrote:Depends on the structure of your document. Use template document if you have some static parts in your document.
That's what I worried about: that I have to provide an empty and pre-formatted document. I noticed, for example, that the generated paragraphs with a custom style (see above for code from JFCC) don't accept changes to their font weight or slant (LibreOffice 4). Don't know if this is a problem in my document or a bug. It seemed to work in OpenOffice.

EDIT: Correction, it doesn't work in OO either. So basically, I've created a new paragraph style as per above instructions, but changing font properties on that style (slant, weight) doesn't have any effect. Changing the font itself, however, or indentation etc, works.
Last edited by _savage on Tue Apr 23, 2013 12:08 pm, edited 1 time in total.
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
hanya
Volunteer
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: [Python] Generating Writer document with more complex fo

Post by hanya »

Can I just modify the "Default style" for that paragraph or should I generate a new one for the lists?
Depends on your purpose and your style. The default style is linked to other styles, other styles are influenced if you change it. Nothing special than you edit styles through UI.
Do you have a link to the object inspector and how to use it? I've looked around for useful documentation and just can't find much!
http://wiki.openoffice.org/wiki/Documen ... ging_tools
And read the documents that you have chosen.
Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

Thank you again, hanya.

Another question in this contex: what is the difference between

Code: Select all

text.insertControlCharacter(cursor, uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK"), 0)
and a

Code: Select all

text.insertString(cursor, "\n", 0)
Is it paragraph break versus line break, i.e. a line break is a simple new line within the same paragraph?
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
User avatar
karolus
Volunteer
Posts: 1158
Joined: Sat Jul 02, 2011 9:47 am

Re: [Python] Generating Writer document with more complex fo

Post by karolus »

Hallo

Code: Select all

uno.getConstantByName("com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK") == '\r'

Code: Select all

....LINE_BREAK") == '\n'
But maybe there are different Mappings on Linux versus Windows.

Karolus
AOO4, Libreoffice 6.1 on Rasbian OS (on ARM)
Libreoffice 7.4 on Debian 12 (Bookworm) (on RaspberryPI4)
Libreoffice 7.6 flatpak on Debian 12 (Bookworm) (on RaspberryPI4)
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

Thanks karolus, makes sense. I guess I was more interested in the implications of one over the other. For example, inserting "\n" will not begin a new paragraph (and therefore it will not switch paragraph formatting), it simply moves the cursor to the next line within the same paragraph. In contrast, inserting a "\r" introduces a whole new paragraph (and therefore it will allow me to change to a new paragraph style).

Also, to continue the collection of little Python snippets in this thread, it seems that this following one creates a new character style, and switches the styling for characters to this new style and back:

Code: Select all

style = document.createInstance("com.sun.star.style.CharacterStyle")
families = document.StyleFamilies.getByName("CharacterStyles")
families.insertByName("My New Style", style)

...

text.insertString(cursor, "Here is some text", 0)
cursor.setPropertyValue("CharStyleName", "My New Style")
text.insertString(cursor, " followed by some styled text ", 0)
cursor.setPropertyValue("CharStyleName", "Default Style")
text.insertString(cursor, "and then some more text with default styling", 0)
I still haven't figured out if I should link a newly created style (both, paragraph and character styles) to another style, and what category I ought to set it to. Or if it matters. As hanya points out in a previous reply, it's just like going through the UI. Still, not sure it makes sense or a difference.
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

Given a paragraph style

Code: Select all

style = document.createInstance("com.sun.star.style.ParagraphStyle")
which property specifies the space to the next paragraph? I can't seem to find it here?
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
User avatar
RoryOF
Moderator
Posts: 34586
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: [Python] Generating Writer document with more complex fo

Post by RoryOF »

I think ParaTopMargin and/or ParaBottomMargin are what you need.
Apache OpenOffice 4.1.15 on Xubuntu 22.04.4 LTS
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

Thanks RoryOF.

Another question: similar to writing text into a document, can I traverse the paragraphs and read the text from them? Not sure why, but moving the cursor (see examples above) didn't quite seem to work. Am I missing something?
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
_savage
Posts: 187
Joined: Sun Apr 21, 2013 12:55 am

Re: [Python] Generating Writer document with more complex fo

Post by _savage »

As an answer to the above question regarding reading from a document, refer to this thread: http://forum.openoffice.org/en/forum/vi ... 44&t=63441
Mac 10.14 using LO 7.2.0.2, Gentoo Linux using LO 7.2.3.2 headless.
Post Reply