Python libreoffice set margin values, optimal height and print document with uno - python

I trying to interact with libreoffice with Python, which integrated in Libreoffice installation. And I didn't found anywhere how can I set margins in PageStyle, to set optimal height of row and prind few copies of document. Or, maybe, I can write macro in Libreoffice and run it from python. Code below is not working.
pageStyle = document.getStyleFamilies().getByName("PageStyles")
page = pageStyle.getByName("Default")
page.LeftMargin = 500
P.S. Sorry for my english.

In most versions of LibreOffice, the name of the default style is "Default Style". In Apache OpenOffice, it is named "Default" instead.
Here is the complete code. For example, name the file change_settings.py.
import uno
def set_page_style_margins():
document = XSCRIPTCONTEXT.getDocument()
pageStyle = document.getStyleFamilies().getByName("PageStyles")
page = pageStyle.getByName("Default Style")
page.LeftMargin = 500
g_exportedScripts = set_page_style_margins,
On my Windows 10 system, this script is located under the directory C:\Users\<your username>\AppData\Roaming\LibreOffice\4\user\Scripts\python. You will need to create the last two directories, and case must match.
Now, in LibreOffice Writer, go to Tools -> Macros -> Run Macro. Expand to My Macros -> change_settings and select the macro name set_page_style_margins.
For a full introduction to Python with LibreOffice:
https://wiki.openoffice.org/wiki/Python/Transfer_from_Basic_to_Python
http://christopher5106.github.io/office/2015/12/06/openoffice-libreoffice-automate-your-office-tasks-with-python-macros.html

Related

How to get LibreOffice headless Calc calculate to save new values from uno?

I am trying to open an excel file from python, get it to recalculate and then save it with the newly calculated values.
The spreadsheet is large and opens fine in LibreOffice with GUI, and initially shows old values. If I then do a Data->Calculate->Recalculate Hard I see the correct values, and I can of course saveas and all seems fine.
But, there are multiple large spreadsheets I want to do it from so I don't want to use a GUI instead I want to use Python. The following all seems to work to create a new spreadsheet but it doesn't have the new values (unless I again manually do a recalculate hard)
I'm running on Linux. First I do this:
soffice --headless --nologo --nofirststartwizard --accept="socket,host=0.0.0.0,port=8100,tcpNoDelay=1;urp"
Then, here is sample python code:
import uno
local = uno.getComponentContext()
resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
context = resolver.resolve("uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager")
remoteContext = context.getPropertyValue("DefaultContext")
desktop = context.createInstanceWithContext("com.sun.star.frame.Desktop", remoteContext)
document = desktop.getCurrentComponent()
file_url="file://foo.xlsx"
document = desktop.loadComponentFromURL(file_url, "_blank", 0, ())
controller=document.getCurrentController()
sheet=document.getSheets().getByIndex(0)
controller.setActiveSheet(sheet)
document.calculateAll()
file__out_url="file://foo_out.xlsx"
from com.sun.star.beans import PropertyValue
pv_filtername = PropertyValue()
pv_filtername.Name = "FilterName"
pv_filtername.Value = "Calc MS Excel 2007 XML"
document.storeAsURL(file__out_url, (pv_filtername,))
document.dispose()
After running the above code, and opening foo_out.xlsx it shows the "old" values, not the recalculated values. I know that the calculateAll() is taking a little while, as I would expect for it to do the recalculation. But, the new values don't seem to actually get saved.
If I open it in Excel it does an auto-recalculate and shows the correct values and if I open in LibreOffice and do Recalculate Hard it shows the correct values. But, what I need is to save it, from python like above, so that it already contains the recalculated values.
Is there any way to do that?
Essentially, what I want to do from python is:
open, recalculate hard, saveas
It seems that this was a problem with an older version of LibreOffice. I was using 5.0.6.2, on Linux, and even though I was recalculating, the new values were not even showing up when I extracted the cell values directly.
However, I upgraded to 6.2 and the problem has gone away, using the same code and the same input files.
I decided to just answer my own question, instead of deleting it, as this was leading to a frustration until I solved it.

Can LibreOffice/OpenOffice programmatically add passwords to existing .docx/.xlsx/.pptx files?

TL;DR version - I need to programmatically add a password to .docx/.xlsx/.pptx files using LibreOffice and it doesn't work, and no errors are reported back either, my request to add a password is simply ignored, and a password-less version of the same file is saved.
In-depth:
I'm trying to script the ability to password-protect existing .docx/.xlsx/.pptx files using LibreOffice.
I'm using 64-bit LibreOffice 6.2.5.2 which is the latest version at the time of writing, on Windows 8.1 64-bit Professional.
Whilst I can do this manually via the UI - specifically, I open the "plain" document, do "Save As" and then tick "Save with Password", and enter the password in there, I cannot get this to work via any kind of automation. I'm been trying via Python/Uno, but to no gain. Although the code below correctly opens and saves the document, my attempt to add a password is completely ignored. Curiously, the file size shrinks from 12kb to 9kb when I do this.
Here is my code:
import socket
import uno
import sys
localContext = uno.getComponentContext()
resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext)
ctx = resolver.resolve( "uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext" )
smgr = ctx.ServiceManager
desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)
from com.sun.star.beans import PropertyValue
properties=[]
oDocB = desktop.loadComponentFromURL ("file:///C:/Docs/PlainDoc.docx","_blank",0, tuple(properties) )
sp=[]
sp1=PropertyValue()
sp1.Name='FilterName'
sp1.Value='MS Word 2007 XML'
sp.append(sp1)
sp2=PropertyValue()
sp2.Name='Password'
sp2.Value='secret'
sp.append(sp2)
oDocB.storeToURL("file:///C:/Docs/PasswordDoc.docx",sp)
oDocB.dispose()
I've had great results using Python/Uno to open password-protected files, but I cannot get it to protect a previously unprotected document. I've tried enabling the macro recorder and recording my actions - it recorded the following LibreOffice BASIC code:
sub SaveDoc
rem ----------------------------------------------------------------------
rem define variables
dim document as object
dim dispatcher as object
rem ----------------------------------------------------------------------
rem get access to the document
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
rem ----------------------------------------------------------------------
dim args1(2) as new com.sun.star.beans.PropertyValue
args1(0).Name = "URL"
args1(0).Value = "file:///C:/Docs/PasswordDoc.docx"
args1(1).Name = "FilterName"
args1(1).Value = "MS Word 2007 XML"
args1(2).Name = "EncryptionData"
args1(2).Value = Array(Array("OOXPassword","secret"))
dispatcher.executeDispatch(document, ".uno:SaveAs", "", 0, args1())
end sub
Even when I try to run that, it...saves an unprotected document, with no password encryption. I've even tried converting the macro above into the equivalent Python code, but to no avail either. I don't get any errors, it simply doesn't protect the document.
Finally, out of desperation, I've even tried other approaches that don't include LibreOffice, for example, using the Apache POI library as per the following existing StackOverflow question:
Python or LibreOffice Save xlsx file encrypted with password
...but I just get an error saying "Error: Could not find or load main class org.python.util.jython". I've tried upgrading my JDK, tweaking the paths used in the example, i.e. had an "intelligent" go, but still no joy. I suspect the error above is trivial to fix, but I'm not a Java developer and lack the experience in this area.
Does anyone have any solution? Do you have some LibreOffice code that can do this (password-protect .docx/.xlsx/.pptx files)? Or OpenOffice for that matter, I'm not precious about which package I use. Or something else entirely!
NOTE: I appreciate this is trivial using full-fat Microsoft Office, but thanks to Microsoft's licensing restrictions, is a complete no-go for this project - I have to use an alternative.
The following example is from page 40 (file page 56) of Useful Macro Information
For OpenOffice.org by Andrew Pitonyak (http://www.pitonyak.org/AndrewMacro.odt). The document is directed to OpenOffice.org Basic but is generally applicable to LibreOffice as well. The example differs from the macro recorder version primarily in its use of the documented API rather than dispatch calls.
5.8.3. Save a document with a password
To save a document with a password, you must set the “Password”
attribute.
Listing 5.19: Save a document using a password.
Sub SaveDocumentWithPassword
Dim args(0) As New com.sun.star.beans.PropertyValue
Dim sURL$
args(0).Name ="Password"
args(0).Value = "test"
sURL=ConvertToURL("/andrew0/home/andy/test.odt")
ThisComponent.storeToURL(sURL, args())
End Sub
The argument name is case sensitive, so “password” will not work.

Libre/Open and writer2Latex, call from Python

I came across this wonderful extension for Open/Libre Office, writer2Latex, which can convert my whole document into TeX format.It's working great so I was wondering if it is possible to skip open/libre office application and call writer2Latex directly from Python? I would like that my python application just calls writer2Latex with the word document as input, and get generated latex file.
This should be doable using Python + uno. The method is very similar to exporting to PDF, which is more common for people to do than export to TeX / Latex. LibreOffice / OpenOffice have a set of export filters that can just be changed.
See DocumentHacker.com for some general documentation about using Python + LibreOffice / OpenOffice, such as how to open documents. The recipe in the cookbook that you need to modify is "Converting to PDF". Simply replace the output filter with the latex filter name
#already have the document open
from com.sun.star.beans import PropertyValue
outputfiltername = "writer_pdf_Export" #for PDF
property = (
PropertyValue( "FilterName" , 0, outputfiltername , 0 ),
)
document.storeToURL("file:///home/my_username/output.pdf", property)
I'm not sure what the FilterName should be however, maybe you can work it out from the writer3Latex documentation. I found a PDF that suggests it should be:
outputfiltername = "org.openoffice.da.writer2latex"
but I haven't tested it (search for "FilterName").

Having a hard time with wx.Config

My problem is that I wanna make a config file for an application but things aren't as simple as they seamed. So I've seen a tutorial where a config file contained the width and the height and the values that followed the equal sign could been retrieved and used to establish the size of a frame. Been there, done that, and everything worked okey. Strangely enough this seams to work only for some key words, as if I've used in the config file, also a parameter named freq it didn't retrieved its value as it did with the width, height parameters.
for example if I have a piece of code like this:
self.cfg = wx.Config('myconf')
wid = self.cfg.ReadInt('width')
hei = self.cfg.ReadInt('height')
freq = self.cfg.ReadInt('frequency')
print wid, hei, freq
where in myconf
width=400
height=250
frequency=3000
So it displays the height, the width but not the frequency, as for freq it gives only 0, and this happens for any other word I use in the config file. I'm guessing that only certain key words can be used in the config file, so they could be recognized while using wxPython.
If so where could I get a list of those keys I could use in making a configuration file ?
Personally, I would recommend using ConfigParser which comes with Python or perhaps ConfigObj (which I like better). If you're trying to save widget attributes / settings, then you also might want to look at the PersistenManager
What you could do is reading the lines yourself:
F = open('myconf', 'r')
for line in F.read().split('\n'):
switchres = { 'frequency': print(line.split('=')[1]),
# add the rest
}
switchres[line.split('=')[0]]
wxPython is a wrapper (or binding) for wxWidgets that is a C++ library.
So wx.Config or wx.FileConfig is intended for C++ that has no specific way of treating these type of config file (still wx.Config is meant to be portable between platforms).
In Python you already have ConfigParser module, but have in mind:
that some wxPython classes work with wx.Config like wx.FileHistory,
use wx.Config if you want to use the platform specific way of storing configurations (like registry in Windows).

Calling python script from excel/vba

I have a python code that reads 3 arguments (scalars) and a text files and then returns me a vector of double. I want to write a macro in vba to call this python code and write the results in one of the same excel sheet. I wanted to know what was the easiest way to do it, here are some stuffs that I found:
call the shell() function in vba but it doesn't seem so easy to get the return value.
register the python code as a COM object and call it from vba--> i don't know how to do that so if you have some examples it would be more than welcome
create a custom tool in a custom toolbox, in vba create a geoprocessing object and then addtoolbox and then we can use the custom tool directly via the geoprocessing object but this is something as well that I don't know how to do..
Any tips?
Follow these steps carefully
Go to Activestate and get ActivePython 2.5.7 MSI installer.
I had DLL hell problems with 2.6.x
Install in your Windows machine
once install is complete open Command Prompt and go to
C:\Python25\lib\site-packages\win32comext\axscript\client
execute \> python pyscript.py
you should see message Registered: Python
Go to ms office excel and open worksheet
Go to Tools > Macros > Visual Basic Editor
Add a reference to the Microsoft Script control
Add a new User Form. In the UserForm add a CommandButton
Switch to the code editor and Insert the following code
Dim WithEvents PyScript As
MSScriptControl.ScriptControl
Private Sub CommandButton1_Click()
If PyScript Is Nothing Then
Set PyScript = New MSScriptControl.ScriptControl
PyScript.Language = "python"
PyScript.AddObject "Sheet", Workbooks(1).Sheets(1)
PyScript.AllowUI = True
End If
PyScript.ExecuteStatement "Sheet.cells(1,1).value='Hello'"
End Sub
Execute. Enjoy and expand as necessary
Do you have to call the Python code as a macro? You could use COM hooks within the Python script to direct Excel and avoid having to use another language:
import win32com.client
# Start Excel
xlApp = win32com.client.Dispatch( "Excel.Application" )
workbook = xlApp.Workbooks.Open( <some-file> )
sheet = workbook.Sheets( <some-sheet> )
sheet.Activate( )
# Get values
spam = sheet.Cells( 1, 1 ).Value
# Process values
...
# Write values
sheet.Cells( ..., ... ).Value = <result>
# Goodbye Excel
workbook.Save( )
workbook.Close( )
xlApp.Quit( )
Here is a good link for Excel from/to Python usage:
continuum.io/using-excel
mentions xlwings, DataNitro, ExPy, PyXLL, XLLoop, openpyxl, xlrd, xlsxwriter, xlwt
Also I found that ExcelPython is under active development.
https://github.com/ericremoreynolds/excelpython
2.
What you can do with VBA + Python is following:
Compile your py scripts that take inputs and generate outputs as text files or from console. Then VBA will prepare input for py, call the pre-compiled py script and read back its output.
3.
Consider Google Docs, OpenOffice or LibreOffice which support Python scripts.
This is assuming that available options with COM or MS script interfaces do not satisfy your needs.
This is not free approach, but worth mentioning (featured in Forbes and New York Times):
https://datanitro.com
This is not free for commercial use:
PyXLL - Excel addin that enables functions written in Python to be called in Excel.
Updated 2018
xlwings is a BSD-licensed Python library that makes it easy to call Python from Excel and vice versa.
Scripting: Automate/interact with Excel from Python using a syntax that is close to VBA.
Macros: Replace your messy VBA macros with clean and powerful Python code.
UDFs: Write User Defined Functions (UDFs) in Python (Windows only).
Installation
Quickstart
There's a tutorial on CodeProject on how to do this.
See http://www.codeproject.com/Articles/639887/Calling-Python-code-from-Excel-with-ExcelPython.
Another open source python-excel in process com tool.
This allows executing python scripts from excel in a tightly integrated manner.
https://pypi.python.org/pypi/Python-For-Excel/beta,%201.1

Categories

Resources