Seite 1 von 1

externes python-script XSCRIPTCONTEXT

Verfasst: Mo 23. Feb 2026, 22:31
von gerderich
Moin zusammen,
zunächst:
@mikele: Vielen Dank für Deinen Denkanstoss im Thread viewtopic.php?f=12&t=41974#p115800
Um missverständnisse zu vermeiden, habe ich mal meinen kompletten Test Code hier eingebracht. Das Script wird in einem Terminal gestartet. Es soll ein definiertes Calc Workbook öffnen und nach 5 sekunden wieder schließen. Speichern, bearbeiten und was sonst noch ist im Augenblick nicht relevant.
Der Code macht was er soll, nur die Zeile

Code: Alles auswählen

    desktop = XSCRIPTCONTEXT.getDesktop()
will partout nicht funktionieren. Ebenso kann ich die Extension MRI nicht benutzen.

Code: Alles auswählen

import sys
import subprocess
import uno
import time
from com.sun.star.beans import PropertyValue

DEBUG=True # False if no debugging needed

# Start LibreOffice in headless mode
def start_libreoffice():
    try:
        process = subprocess.Popen([
            r"soffice",
            #"--headless",
            "--accept=socket,host=localhost,port=2002;urp;StarOffice.Servicemanager",
            "--minimized"
        ])
        # An dieser Stelle wird der LO Dialog "Dokumentwiederherstellung" angezeigt.
        if DEBUG:
            print("LibreOffice process started")
        return process
    except Exception as e:
        print(f"Failed to start LibreOffice: {e}")
        return None

# Connect to LibreOffice
def connect_to_libreoffice():
    local_context = uno.getComponentContext()
    resolver = local_context.ServiceManager.createInstanceWithContext(
        "com.sun.star.bridge.UnoUrlResolver", local_context)
    # context in other codes = ctx
    context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext")
    return context

# Load  python_test.ods document
def getWorkbook(context):
    try:
        args = (PropertyValue(Name='Hidden', Value=False),PropertyValue(Name="MacroExecutionMode",Value=1),)
        if DEBUG:
            print ("props sind eingerichtet")
        path="/home/gerd/Dokumente/python_test.ods"
        docurl = uno.systemPathToFileUrl(path)
        if DEBUG:        
            print ("path ist gesetzt  ..")
        #desktop = XSCRIPTCONTEXT.getDesktop()
        # funktioniert nicht. Fehler ist:
        # name 'XSCRIPTCONTEXT' is not defined
        desktop = context.ServiceManager.createInstanceWithContext(
			 "com.sun.star.frame.Desktop", context)
        if DEBUG:
            print ("desktop definiert .... ")
        document = desktop.loadComponentFromURL(docurl,"_default",0,args)
        if DEBUG:
            print ("calc dokument ist geladen!")
        return document
    except Exception as e:
        print(f"Calc File nicht gefunden: {e}")
        return None
        
def mri(target):
    ctx = uno.getComponentContext()
    mri = ctx.ServiceManager.createInstanceWithContext("mytools.Mri",ctx)
    #mri = create_instance("mytools.Mri", True)
    mri.inspect(target)
	
# Main execution
if __name__ == "__main__":
    try:
        # Start LibreOffice
        libreoffice_process = start_libreoffice()

        #API server take time to fire up
        # therefor: start 10 seconds
        time.sleep(10)
        
        # Connect to LibreOffice
        context = connect_to_libreoffice()        

        # load an exiting spreadsheet document
        doc = getWorkbook(context)
        ### ----- extension not loadable ----- 
        # if DEBUG:
        #     print("mri wird aufgerufen")
        # mri(doc)
        # if DEBUG:
        #  print("mri wurde aufgerufen")
        ###
        if doc == None : # Es wurde kein CALC File geladen
            sys.exit()
        else:			# CALC File wurde geladen, könnte jetzt bearbeitet werden
            time.sleep(5)
        # 5 sekunden bis zum Schließen
        # hier kommt der Code zum Bearbeiten des workbook hin      
        # Close the document
        doc.close(True)
        
    except Exception as e:
        print(f"An error occurred: {e}")
    finally:
        # Close document and
        # Stop LibreOffice
        if libreoffice_process:
            doc.close(True)
            libreoffice_process.terminate()
            print("LibreOffice process terminated.")

Ich habe versucht, den Code so kurz wie möglich zu halten. Ich möchte einfach nur, das XSCRIPTCONTEX funktioniert und: das ich das geladene Dokument mittels MRI inspizieren kann. Ich muss leider zugeben: In diesem externen Script bekomme ich es nicht hin. Geht das mit einem externem Script überhaupt?
Gruß
Gerd Erich

Re: externes python-script XSCRIPTCONTEXT

Verfasst: Di 24. Feb 2026, 00:12
von karolus
Hallo

Falls ich nichts übersehen habe in deinen etwas unübersichtlichen setup!
Du »verbindest« dich von extern mit einer soffice-instanz, da fällt die interne globale Variable »XSCRIPTCONTEXT« nicht einfach so vom Himmel herab.
was du noch brauchst ist noch ein import (vorzugsweise ganz am Anfang ):

Code: Alles auswählen

from pythonscript import ScriptContext
und später an der passenden Stelle innerhalb der »getWorkbook« funktion:

Code: Alles auswählen

    XSCRIPTCONTEXT = ScriptContext(context, None, None)
das was du unterhalb von »if __name__ == "__main__":« global machst, würde ich dann kapseln in einer »main« funktion, in der du einfach »return« statt »sys.exit()« nimmst.
Dann bleibt zuletzt nur noch:

Code: Alles auswählen

if __name__ == "__main__":
    main()

Re: externes python-script XSCRIPTCONTEXT

Verfasst: Di 24. Feb 2026, 16:29
von gerderich
Moin Karolus,
da habe ich wohl falsch gesucht. die Anweisung
karolus hat geschrieben:
Di 24. Feb 2026, 00:12

Code: Alles auswählen

from pythonscript import ScriptContext
und später an der passenden Stelle innerhalb der »getWorkbook« funktion:

Code: Alles auswählen

    XSCRIPTCONTEXT = ScriptContext(context, None, None)
habe ich jedenfalls bei meinen Recherchen nicht gefunden. Vielleicht habe ich auch falsch gesucht. Wie dem auch sei, der Tipp hat geholfen. Jetzt funktioniert auch der Zugriff auf MRI und ich kann weitermachen. Danke für Deine Zeit.
Gruß
Gerd Erich

Re: externes python-script XSCRIPTCONTEXT

Verfasst: Di 24. Feb 2026, 18:25
von karolus
habe ich jedenfalls bei meinen Recherchen nicht gefunden.
ist auch nicht ganz trivial…

LO-intern findet der ganze Zauber in …/libreoffice/program/pythonscript.py statt.
Wenn du dort nachschaust wird zunächst mal »XSCRIPTCONTEXT« an das Symbol: GLOBAL_SCRIPTCONTEXT_NAME gebunden. … und später dann sowas:

Code: Alles auswählen

……
    def actionPerformed( self, event ):
        try:
            if event.ActionCommand == "Run":
                code = self.editor.getControl("EditorTextField").getText()
                code = ensureSourceState( code )
                mod = types.ModuleType("ooo_script_framework")
                mod.__dict__[GLOBAL_SCRIPTCONTEXT_NAME] = self.provCtx.scriptContext
                exec(code, mod.__dict__)
                …