DEV Community

Yusuke arakawa
Yusuke arakawa

Posted on • Edited on

Make LibreOffice Draw Document to use odfpy

Odfpy is famous Python library to make OpenDocument Format.
But,How to use odfpy?

odfpy official manual is only api-for-odfpy.odt and example program in github.

OpenDocument Text and OpenDocument Spreadsheet's odfpy tutorial is a few found.
OpenDocument Graphic's odfpy tutorial is not found!

I want to have Getting started at Draw Document's odfpy.

Enviroment

  • Windows10 Pro/Home x64
  • Windows System for Linux(WSL)
  • Ubuntu16.04
  • Python3
  • Python3-pip (pip)
  • odfpy
  • iPython
  • LibreOffice Draw for Windows

I use WSL.
I don't explain to install WSL.
if don't install WSL, check it under url.

Install the Windows Subsystem for Linux

Setup Python

$ sudo apt update $ sudo apt upgrade # Python $ sudo apt install Python3 # pip $ sudo apt Python3-pip $ pip3 install -U pip -user # odfpy iPython $ pip3 install odfpy,iPython -user $ pip3 list --format columns # folder $ mkdir odfpy $ cd odfpy 
Enter fullscreen mode Exit fullscreen mode

Make Document and Page

At first,I start iPython.
iPython is very useful.

 $ ipython Python 3.6.3 (default, Nov 6 2017, 23:30:23) Type 'copyright', 'credits' or 'license' for more information IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help. In [1]: 
Enter fullscreen mode Exit fullscreen mode

Check your current directory.
odfpy make Draw Document in this directory.
Put picture and python script to run.

 # check your current directory In [1]: %pwd Out [1]:'/home/username/odfpy' 
Enter fullscreen mode Exit fullscreen mode

Make docucment

In:[2] from odf.opendocument import OpenDocumentDrawing In:[3] doc=Open # press your tab key  open() OpenDocumentDrawing() 
Enter fullscreen mode Exit fullscreen mode

Type OpenDocu... press tab key.
Amazing! Type-Ahead.

OK?
Umm,drawing in addText method.
try,it.

In[3]:doc=OpenDocmentDrawing() In[3]:doc.drawing.addText('aaaa') ....(Abbreviation)... IllegalText: The <office:drawing> element does not allow text In[4]: 
Enter fullscreen mode Exit fullscreen mode

can't add Text.
Draw Document can't put direct text and Shape.
make Page.
Text and Shape in Page.

Open Another Terminal and make createpage.py file in odfpy folder.

from odf.opendocument import OpenDocumentDrawing from odf.draw import Page from odf.style import Style,MasterPage,PageLayout ## Create the drawing page style dpstyle = Style(family="drawing-page",name="DP1") doc.automaticstyles.addElement(dpstyle) ## Create page layout specifying dimensions plstyle = PageLayout(name="PM1") doc.automaticstyles.addElement(plstyle) ## Create a master page masterpage = MasterPage(stylename=dpstyle, name="Default", pagelayoutname=plstyle) doc.masterstyles.addElement(masterpage) ## Create a page to contain the drawing drawpage = Page(masterpagename=masterpage, name="page1", stylename=dpstyle) doc.drawing.addElement(drawpage) 
Enter fullscreen mode Exit fullscreen mode

To make Page

  1. make PageStyle and PageLayout.
  2. make Masterpage
  3. make Page form MasterPage
  4. add Page to Draw Document

It's too much bother to make Page.
That’s how it is.

That run in iPython.

# check File In[4]: %ls createpage.py In[5]: %run createpage.py 
Enter fullscreen mode Exit fullscreen mode

If it is not error,Success to add Page.

PageProperties

How to change PageProperties?
I try a little.

# load PageLayoutProperties In[6]:from odf.style import PageLayoutPropretis In[7]:plsytle.addElement(PageProperties(margin="0cm",pageheight="210mm",pagewidth="297mm", printorientation="portrait")) In[8]:doc.automaticstyles.addElement(plsytle) 
Enter fullscreen mode Exit fullscreen mode

Nothing PaperSize,so we change pageheight and pagewidth.
and save it.

In[9]: doc.save('draw01',True) 
Enter fullscreen mode Exit fullscreen mode

it copy to Windows Desktop.

$ cp draw01.odg /mnt/c/Users/username/Desktop 
Enter fullscreen mode Exit fullscreen mode

open it on Windows to use LibreOffice Draw.

createpage.png

OK.

Add Text

It's too much bother to make Page for me.
So, it do.

In [1]:from odf.opendocument import OpenDocumentDrawing,load In [2]:doc=load('draw01.odg') In [3]:doc.getMediaType() Out[3]: 'application/vnd.oasis.opendocument.graphics' 
Enter fullscreen mode Exit fullscreen mode

load draw document.

To add Text,

  1. Make Text
  2. Make TextBox and add Text
  3. Make Frame and add TextBox
  4. Take out Page
  5. Add Frame to Page

Text can't directly add to Page.
To add Text,Text add to Frame or Rect...etc.

This is code underline.

In[4]: from odf.draw import Page,TextBox,Frame # get Page In[5]: page=doc.getElementByType(Page) In[6]: page=page[0] In[7]: from odf.text import P # Create Text In[8]: text=P() In[9]: text.addText('こんにちは') # Text add to TextBox In[10]: tb=TextBox() In[11]: tb.addElement(text) # TextBox add to Frame. # x,y is position. In[12]: frame=Frame(width='100mm',height='20mm',x='2cm',y='2cm') In[13]: frame.addElement(tb) # Page add to Frame. In[14]: page.addElement(frame) # Save In[15]: doc.save('draw02',True) 
Enter fullscreen mode Exit fullscreen mode

LibreOffice Draw open draw02.odg.

addtext.png

good!
I want to change font size and background color.

TextProperties and GraphicProperties

TextProperties change Text's font-size.
GraphicProperties change Frame's background color.

In [1]: from odf.opendocument import load In [2]: from odf.draw import Page,Frame,TextBox In [3]: from odf.style import Style,TextProperties,GraphicProper ...: ties In [4]: from odf.text import P # load draw file In [5]: doc=load('draw02.odg') # Take out Frame and Text In [6]: page=doc.getElementsByType(Page) In [7]: page=page[0] In [8]: frame=page.getElementsByType(Frame) In [9]: frame=frame[0] In [10]: tb=frame.getElementsByType(TextBox) In [11]: tb=tb[0] In [12]: text=tb.getElementsByType(P) In [13]: text=text[0] # make Style In [14]: s=Style(name='P1',family='paragraph') # English is fontsize But, Chinese Japanese Korean font is fontsizeasian. # 「こんにちは」=fontasian In [15]: tp=TextProperties(fontsize='32pt',fontsizeasian='32pt') In [16]: gs=Style(name='GR1',family='graphic') In [17]: gp=GraphicProperties(fill='none',stroke='none') # add Style to Frame and Text In [18]: text.setAttribute('stylename',s) In [19]: frame.setAttribute('stylename',gs) # add Style to Draw Document In [20]: doc.automaticstyles.addElement(s) In [21]: doc.automaticstyles.addElement(gs) # Save In [22]: doc.save('draw03',True) 
Enter fullscreen mode Exit fullscreen mode

changestyle.png

got it!
Next,I want to add image.

add Image

Get Image

  1. Get LibreOffice Draw's icon png from Wikimedia Common.
  2. rename drawicon.png
$ pwd /home/users/odfpy $ curl -O https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/LibreOffice_4.0_Draw_Icon.svg/200px-LibreOffice_4.0_Draw_Icon.svg.png $ mv 200px-LibreOffice_4.0_Draw_Icon.svg.png drawicon.png $ ls drawicon.png drawicon.png 
Enter fullscreen mode Exit fullscreen mode

OK, I get image.

Add Image

# load file. In [1]: from odf.opendocument import load In [2]: doc=load('draw01.odg') # import need's Object In [3]: from odf.draw import Page,Image,Frame # Take out Page In [4]: page=doc.getElementsByType(Page) In [5]: page=page[0] # make PhotoFrame. x,y is position,height width is size. # This image is square,so height and width is same scale. In [6]: photoframe=Frame(x='10mm',y='40mm',height='26mm',width='26mm') # add Image to Draw Document. In [7]: href=doc.addPicture('drawicon.png') # add Image to photoframe In [8]: photoframe.addElement(Image(href=href)) # add photoframe to Page In [9]: page.addElement(photoframe) # Save In [10]: doc.save('draw04',True) 
Enter fullscreen mode Exit fullscreen mode

Do you add Image to Document?
OK, Check Document.

addimage.png

Success!

 Conclusion

  1. PageProperties
  2. Put Text
  3. Put Image and Shape
  4. Save

I believe it to make odfpy's Getting Started.

Reference

API for Odfpy - odt
API Reference.
example program's explain is a little.

odfpy - example
sample program.

Official is only two Reference.

Search and replace text odfpy - StackOverflow
I know it add set Style to Text.P to use SetAttribute.

Top comments (5)

Collapse
 
sammarrques profile image
sammarrques • Edited

Tahnks, Yusuke.

But I still didn't manage to get I want.

I am new to Python and I'm working with odt files, from libreoffice.

I would like to add an specific image to a specific position in my document.

By the way, I'm using the teletype method, from: balasankarc.in/tech/using-python-a....

I tried to paste some command lines in your guide and despite the programm runs ok, the archive doesn't add the image I want.

Collapse
 
arachan profile image
Yusuke arakawa

Thank you reading, sammarrques.

Your blog read a little.

It's a point that I concerned.

Writer and Draw is a little different.

When put picture on Writer Document,we need to think about Wrap text around a picture.

I read your blog a little more.

Collapse
 
arachan profile image
Yusuke arakawa • Edited

I add Picture use LibreOffice Writer.
I read this documents's context.xml.

It's under code.

it add text.p in frame.
it add draw image in frame.

Add image to odt #45
He is mistake.
He should add frame in text.P .

Test code?
Not yet.

<?xml version="1.0" encoding="UTF-8"?> ... Omission ... <office:body> <office:text> <text:sequence-decls> <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> <text:sequence-decl text:display-outline-level="0" text:name="Table"/> <text:sequence-decl text:display-outline-level="0" text:name="Text"/> <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> </text:sequence-decls> <text:p text:style-name="Standard"> <draw:frame draw:style-name="fr1" draw:name="イメージ1" text:anchor-type="paragraph" svg:width="17cm" svg:height="5.736cm" draw:z-index="0"> <draw:image xlink:href="Pictures/1000020100000C8000000438BDD44B89CE152A7F.png" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" loext:mime-type="image/png"/> </draw:frame> </text:p> </office:text> </office:body> </office:document-content> 
Thread Thread
 
arachan profile image
Yusuke arakawa • Edited

Test Code.
Work Fine!
It is Point that add picture frame in paragraph element.

from odf.opendocument import OpenDocumentText from odf.text import P,ParagraphProperties from odf import teletype from odf.style import Style from odf.draw import Frame,Image # Justified style justifystyle = Style(name="justified", family="paragraph") justifystyle.addElement(ParagraphProperties(attributes={"textalign": "justify"})) # Creating different style used in the document doc=OpenDocumentText() s=doc.styles s.addElement(justifystyle) # Adding a paragraph paragraph_element = P(stylename=justifystyle) paragraph_text="hello world" teletype.addTextToElement(paragraph_element, paragraph_text) doc.text.addElement(paragraph_element, paragraph_text) # add picture picframe=Frame() href=doc.addPicture("drawlogo.png") picframe.addElement(Image(href=href)) # Point! # add picture frame in paragraph element paragraph_element.addElement(picframe) # save ODT doc.save("new.odt") 
Thread Thread
 
arachan profile image
Yusuke arakawa

Test Code.
Add element in Frame.
Add element in Image.

 from odf.opendocument import OpenDocumentText from odf.text import P from odf import teletype from odf.style import Style,ParagraphProperties from odf.draw import Frame,Image # Justified style justifystyle = Style(name="justified", family="paragraph") justifystyle.addElement(ParagraphProperties(attributes={"textalign": "justify"})) # Creating different style used in the document doc=OpenDocumentText() s=doc.styles s.addElement(justifystyle) # Adding a paragraph paragraph_element = P(stylename=justifystyle) paragraph_text="hello world" teletype.addTextToElement(paragraph_element, paragraph_text) doc.text.addElement(paragraph_element, paragraph_text) # add picture picframe=Frame(anchortype="paragraph",height='26mm',width='26mm',name='image1') href=doc.addPicture("drawlogo.png") picframe.addElement(Image(href=href,actuate="onLoad",show="embed",type="simple")) paragraph_element.addElement(picframe) # save ODT doc.save("new.odt") 

Some comments may only be visible to logged-in visitors. Sign in to view all comments.