The more you look, the more the documentation is really poor. Using UNO dispatch is often the only way to do things, regardless of language. Currently the solution of using .uno:InsertEnvelope
has the following problems:
- only one envelope can be added
- the dialogue is not shown if you provide some parameters
- the non-supplied parameters take the defaults from last time (both a feature and a bug, arguably)
I’d like to avoid using a second template just for the envelope, so the obvious solution is to create the document manually and allow the styles to control the layout. This way the user can control the styles in their own template. However, it looks like the current Insert Envelope command uses per-frame styles at least. These are easy enough to alter individually. Another problem is that we want different fonts for the Addressee and Sender on the envelope than in letter: font on the cover should be sans serif for automatic postal processing. It’s not clear to me what the best solution is here; perhaps alter the style on the cover, perhaps use different styles for the body and envelope. I think it’s more logical to go with the second method (use SenderBody in the body and fall-back to Sender if no such paragraph style exists). We could use the same trick with the frames to allow, for example, changing the layout if desired or just using the defaults. The start of an article on creating dialogues was referenced earlier, if that becomes necessary.
The default behaviour of Insert Envelope appears to be:
- insert a new page, with style Envelope, following style Default
- modify the style to include user-specified margins, and auto-adjust for print settings
- insert two frames, modify their styles to be in user-specified positions
- put sender and addressee into the frames with appropriate paragraph styles
There is some seemingly strange stuff going on with the print settings. For example, setting the paper to be deliberately larger than the envelope size and then setting a margin. This seems like a trick for certain common printer types/trays, and will probably only be clear with experimentation.
Adding a page
Pages in OpenOffice are unusual. This seems to work:
cursor = model.Text.createTextCursor() cursor.gotoStart(False) cursor.BreakType = PAGE_AFTER model.Text.insertControlCharacter(cursor, PARAGRAPH_BREAK, False)
Styles
The documentation surrounding styles is a little better than average.
def getStyle(family, name, model=XSCRIPTCONTEXT.getDocument()): styleFamily = model.StyleFamilies.getByName(family) style = styleFamily.getByName(name) return style
As usual, we don’t need strange type-casts in Python to use the different interfaces that services provide – we can just treat them as any one of the interfaces. Unfortunately we are soon at a dead-end again:
messageBox(cursor.PageStyleName) # "Standard" (=Default) cursor.PageStyleName = "Envelope" # no such property cursor.setPropertyValue("PageStyleName", "Envelope") # property is read-only
The documentation claims that you change the page style by finding the current one and manually altering its properties. Reading more closely, we see that there is a second property, PageDescName
, that will do the job. Normally, styles are set by selecting the appropriate text unit of the model with a cursor and then using its PropertySet
, which in Python is as simple as:
cursor.ParaStyleName = "Sender"
Doing the same with the page style works, but the documentation claims it will insert a new page if not already at the start. This doesn’t seem to respect the cursor PageBreak
setting (always creates after) so our previous code remains useful.
Frames
Frames are used both in the traditional sense of windowing components and in the text layout sense. They are the same in OpenOffice, but the documentation leans towards the former. After hunting around for a while you can find the right page. There is also an overview and a GUI-oriented piece. So we do:
#!python frame = createUnoService(“com.sun.star.text.TextFrame”) model.Text.insertTextContent(vc, frame, False) frame.Text.String = sender
Naturally, this fails. It seems that the standard factory does not support TextFrame
(not mentioned in the documentation page). Not immediately clear how to get the required factory, but hypothesising that the TextFrame
is not a service and can be created by the document model:
frame = model.createInstance("com.sun.star.text.TextFrame") model.Text.insertTextContent(cursor, frame, False) frame.Text.String = sender
We have a frame!
To be continued…