How to execute macro on alpine linux?

LibreOffice 7.2.2.2 afc8349a712d40a424b5a12dcfa54f843620fa62

OS: alpine linux docker image

basic macro .

REM  *****  BASIC  *****

function OpenSilent(FilePath as String) as Object
  Dim FileProperties(1) As New com.sun.star.beans.PropertyValue
  FileProperties(0).Name = "Hidden"
  FileProperties(0).Value = True
  Dim Dummy()
  OpenSilent = StarDesktop.loadComponentFromURL(ConvertToURL(FilePath), "_blank", 0, Dummy())
end function

sub Headless(FilePath as String,Out as String)
  Document = OpenSilent(FilePath)
  call ChangeScale()	
  ToPDF(Out)
  call Document.close(True)
end sub


sub ChangeScale
	oStyleFamilies = ThisComponent.StyleFamilies
	oPageStyles = oStyleFamilies.getByName("PageStyles")
	numStyle = oPageStyles.Count 

	For iCount = 0 To numStyle-1
		oDefaultStyle = oPageStyles(iCount)
		oDefaultStyle.PageScale = 50
	Next iCount
	document   = ThisComponent.CurrentController.Frame
	dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
end sub

function ToPDF(File as String)
	dim args(0) As New "com.sun.star.beans.PropertyValue"
	args(0).Name = "FilterName"
    args(0).Value = "calc_pdf_Export"
	ThisComponent.storeToURL(ConvertToURL(File),args())
end function

execute command line

soffice --invisible --nofirststartwizard --headless --norestore ‘macro:///Standard.Module1.Headless("/xxx.xlsx","/test.pdf")’

then nothing happened.

When execute command soffice 'macro:///Standard.Module1.Headless("/xxx.xlsx","/test.pdf")'

got a error msg: Failed to open display .

Except output a pdf after execute the macro

your issue is two-folded:
converting to …pdf should done by comandline:

soffice --convert-to pdf:calc_pdf_export  /path/to/somefile.ods
#but no way to invoke makro

to invoke Makrocode you need:

#
soffice /path/to/file_with_embedded_code.ods macro:///Library.Module.MacroName
# but no option to pass argument[s] to 'MakroName'??

the following pythonscript, should do the job from ‘outside’

import sys
from subprocess import Popen
from random import sample
from string import ascii_letters as abc
from time import sleep
from pathlib import Path
import uno
from pythonscript import ScriptContext
from com.sun.star.beans import PropertyValue as propval

PIPENAME = ''.join(sample(abc,8))

officepath = 'soffice'
calc = '--calc'
pipe = f"--accept=pipe,name={PIPENAME};urp;StarOffice.ComponentContext"

def main():
    filename = sys.argv[1]
    Popen([officepath,
       filename,
       #'--headless', 
       pipe]);
    print(f'LibreOffice has started and is available via PIPE: {PIPENAME}')
    sleep(5)
    doc, desktop  = get_doc(PIPENAME)
    set_page_scale(doc)
    pv = propval()
    pv.Name = "FilterName"
    pv.Value = "calc_pdf_Export"
    pdf_uri = Path(filename).with_suffix('.pdf').as_uri()
    doc.storeToURL(pdf_uri, (pv,) )
    print(doc.Title)
    doc.dispose()
    desktop.terminate()
    
def set_page_scale(document, scale=50):
    pagestyles = document.StyleFamilies['PageStyles']
    for style in pagestyles:
        setattr(style, 'PageScale', scale)
    
def get_doc(pipename):    

    local = uno.getComponentContext()
    resolver = local.ServiceManager.createInstance("com.sun.star."
                                                   "bridge.UnoUrlResolver")
    client = resolver.resolve( "uno:pipe,"
                               f"name={pipename};"
                               "urp;"
                               "StarOffice.ComponentContext")    

    XSCRIPTCONTEXT = ScriptContext(client, None, None)
    return XSCRIPTCONTEXT.getDocument(), XSCRIPTCONTEXT.getDesktop()

    
if __name__ == '__main__':
    main()
    

call it from terminal:

 python -m scriptname_without_suffix  /path/to/calcfile.ods

how to include the uno module for python3 ?

you need to append the …libreoffice/program/ folder to sys.path probably it is:

…
sys.path.append("/usr/lib/libreoffice/program/")
import uno
…
1 Like

Here is a much more simple solution than the previous by me:

import sys
from subprocess import run
from lxml import etree
BASE_NS = '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}'

def scale50(file):
    style_xml =etree.parse(file)
    for elem in style_xml.findall(f'**{ BASE_NS }page-layout-properties'):
        elem.attrib[f'{ BASE_NS }scale-to'] = "50%"
    style_xml.write(file, encoding='utf8',doctype='<?xml version="1.0" encoding="UTF-8"?>')
    
if __name__ == '__main__':
    ods_file = sys.argv[1]
    run(['unzip', ods_file, 'styles.xml'])
    scale50('styles.xml')
    run(['zip', ods_file, 'styles.xml'])
    run(['soffice', '--convert-to', 'pdf:calc_pdf_Export', ods_file ] )

as you can see, it needs soffice … only for the final convert-to-pdf.
usage:

python -m yourscriptname some_ods_file.ods
1 Like

oooooooh! :star_struck: you are so great ! that’s wonderful .