Strange behavior when using LibreOffice quick start

There are two ways to start LibreOffice:

  1. Start LibreOffice when an application is launched

  2. Start LibreOffice when Windows starts (quick start)

I have a spreadsheet application with several Python scripts that runs fine with method 1. I can open, close, and reopen the application without any problems. However, when I use method 2, it works fine the first time, but error messages appear when I start the application again. According to the first message, I inadvertently closed the application, and then I get an error message about activating a sheet. Is this a bug, or does method 2 require clearing data (garbage collect) to enable a fresh start?

Please paste here the information on Menu/Help/About LibreOffice (There is an icon to copy)

No one can answer without seeing your code (and data). What does your code do? What does it assume? Is it incorrect Python code, or is it a bug in LibreOffice, that shown in some specific situation? People that can answer this without seeing your code are rare species; sometimes even their crystal balls malfunction…

1 Like

This strange behavior only occurs in Windows; other operating systems, such as Linux, don’t have quickstart.

The comment that the code is incorrect seems unfounded to me. When the sheet is started and LibreOffice is then launched, it works without any problems, and the first launch after a quickstart also works fine.
Only each subsequent launch after a quickstart produces errors. It seems that information isn’t being reloaded or that old information isn’t being cleared out, causing errors.

These ase the error messages:

and

Looking at the error messages again, I get the impression that the APSO extension is no longer present when the Calc application is next started after using Quickstart. This would mean that when using Python scripts in Windows, LibreOffice Quickstart cannot be used.

There is no comment “that the code is incorrect”; such a claim would indeed be unfounded - exactly for the reason that was stated in the comment: we had no idea what the code was. What was written there was “we don’t know if it’s a problem in your code, or in LibreOffice”.

And we still have no idea - you haven’t provided the needed info.
But it’s completely unclear, where is APSO there - the error message mentions ScriptForge, but I see no APSO there. (And I would very much suspect ScriptForge. @JPLED could have more insight.)

please show the content of …/Scripts/python/MijnBib/Mod1.py

This is the code of Mod1.py:

# coding: utf-8
from __future__ import unicode_literals
from scriptforge import CreateScriptService
#import subprocess
import webbrowser
import uno
from datetime import datetime
doc = CreateScriptService('Calc')
bas = CreateScriptService('Basic')

#-----Magic strings and numbers------
antw_ja = 6
doen = 1
fout1 = 'BNK.G7'
fout2 = 'BNK.G9'
BNK_sheet = 'BNK'
BNK_kolB = 'BNK.B'
BNK_kolC = 'BNK.C'
BNK_printrange = 'BNK.A1:F'
BNK_afresregels = 'BNK.F7'
BNK_regels = 'BNK.F6'
BNK_alles = 'BNK.B10:F100'
BNK_start = 'B10:F'
BNK_datum = 'BNK.D2'
VPM_sheet = 'VPM'
VPM_kolG = 'G'
VPM_kolR = ':R'
VPM_kolV = 'VPM.V'
VPM_start = 'VPM.B3'
VPM_omschr = 'VPM.C3'
VPM_copykol = 'VPM.F3'
VPM_mndnr = 'VPM.T2'
VPM_mndnaam = 'VPM.U2'
VPM_mndkol = 'VPM.V2'
VPM_regels = 'VPM.V1'
VPM_weken = 'VPM.Y4'
VPM_cprange = 'VPM.C3:E'
VPM_mndrange = 'VPM.F3:F94'
VPM_alles = 'VPM.B3:R94'
INS_sheet = 'INS'
INS_pdfmap = 'INS.M3'
INS_werkjaar = 'INS.P2'
#---------------------------------

def today(n):
    uno_date = bas.CDateToUnoDateTime(datetime.now())
    mnd = str(uno_date.Month)
    mnd = mnd.rjust(2,'0')
    dag = str(uno_date.Day)
    dag = dag.rjust(2,'0')
    jaar = str(uno_date.Year)
    if (n == 0):
        today = jaar + mnd + dag
    else:
        today = dag + '-' + mnd + '-' +jaar
    return today

def show_msb(args=None):
    doc.activate(BNK_sheet)
    result = bas.MsgBox('Datum op vandaag zetten?',bas.MB_YESNO + bas.MB_ICONINFORMATION,'BankBeheer')
    if result == antw_ja :
        doc.SetValue(BNK_datum,today(1))

def print_bnk(args=None):
    doc.activate(BNK_sheet)
    bnk_range = BNK_printrange + str(doc.GetValue(BNK_regels) + 9)
    directory = doc.GetValue(INS_pdfmap)
    p_file = directory + 'BNK_'  + today(0) + '.pdf'
    doc.ExportRangeToFile(bnk_range,p_file, 'pdf', overwrite = True)
    webbrowser.open('file://' + p_file)
    
def dialog_sort(args=None):
    dlg = CreateScriptService('SFDialogs.Dialog', 'GlobalScope', 'Standard', 'DlgOvSort')
    if (dlg.execute() == doen):
        try:
            cs = ['ASC', 'DESC']
            ks = [1, 2, 5, 1, 2, 5]
            KzeListbox = dlg.Controls('ListBoxKeuze')
            Kze = KzeListbox.ListIndex
            ad = cs[dlg.Controls('SortBox').value]
            if (Kze <= 2):
                sheet = BNK_sheet
                rg = BNK_alles
                go = doc.GetValue(BNK_regels) != 0
            else:
                sheet = VPM_sheet
                rg = VPM_alles
                go = doc.GetValue(VPM_regels) != 0
            if go:
                sort_data(sheet, rg, ks[Kze], cs[dlg.Controls('SortBox').value])
        finally:
            dlg.Terminate()
            dlg.dispose()

def sort_data(SN,RN,col,AD):
    doc.activate(SN)
    doc.SortRange(RN, col, AD, casesensitive = True)

def afb_BNK(args=None):
    doc.activate(BNK_sheet)
    F = doc.GetValue(BNK_afresregels)
    if (bas.MsgBox('Doorgaan met verwerken van ' +str(F) + ' regel(s)?',
                   bas.MB_YESNO + bas.MB_ICONINFORMATION, 'Verwerken afschrift') == antw_ja):
        sort_data(BNK_sheet,BNK_alles,5,'ASC')
        doc.clearValues(BNK_start + str(F + 9))
        sort_data(BNK_sheet,BNK_alles,1,'ASC')
        
def dialog_month(args=None):
    doc.activate(BNK_sheet)
    dlg = CreateScriptService('SFDialogs.Dialog', 'GlobalScope', 'Standard', 'DlgMaandPosten')
    if (dlg.execute() == doen):
        try:
            MndListBox = dlg.Controls('MaandenListBox')
            Mnd = MndListBox.ListIndex
            Mnd = Mnd+1
            mnd_add(Mnd)
        finally:
            dlg.Terminate()
            dlg.dispose()

def mnd_add(mnd):    
    jr_name = str(doc.GetValue(INS_werkjaar)) 
    doc.SetValue(VPM_mndnr, mnd)
    m = doc.GetValue(VPM_mndnaam) 
    k = doc.GetValue(VPM_mndkol) 
    if (mnd != 12) :
        tv_text = 'Vaste posten van '
    else :
        tv_text = 'LET OP: dit is de laatste maand van het jaar, er moet een nieuw weekschema voor volgend jaar aangemaakt worden.\n\n Vaste posten van '
    if (bas.MsgBox(tv_text + m + '. '+jr_name+' toevoegen?',
                   bas.MB_YESNO + bas.MB_ICONINFORMATION, 'Toevoegen vaste posten') == antw_ja):
        copy_content(k)
   
def copy_content(column):
    doc.clearValues(VPM_mndrange)
    source_range = doc.range(VPM_sheet + '.' + column + '3:' + column + '94')
    doc.copyToCell(source_range, VPM_copykol)
    sort_data(VPM_sheet,VPM_alles,5,'ASC')
    number = doc.GetValue(VPM_regels) #aantal regels uit VPM.V1
    bnk_start = doc.GetValue(BNK_regels)+10 #startpositie in BNK
    arrData = [doc.GetValue(doc.Offset(VPM_start,i)) for i in range(number)]
    source_range = doc.range(VPM_cprange + str(number +2)) 
    doc.copyToCell(source_range, BNK_kolC + str(bnk_start))
    doc.SetArray(BNK_kolB + str(bnk_start),arrData)
    sort_data(BNK_sheet,BNK_alles,1,'ASC')
   
def close_sheet(args=None):
    doc.activate(BNK_sheet)
    if ((doc.GetValue(fout1)=='!') or (doc.GetValue(fout2)=='NR')):
        bas.MsgBox('LET OP: er zijn nog fouten in het blad BNK!',
               bas.MB_OK + bas.MB_ICONEXCLAMATION, 'Afsluiten BankBeheer')

def new_monthscheme(args=None):
    if(doc.GetValue(VPM_mndnaam) == 'dec'):
        doc.activate(INS_sheet)
        text = "Reservering hh week 5"
        cell_wk5 = 0
        for i in range(91):
            start_cell = doc.Offset(VPM_omschr,i)
            if(text == doc.GetValue(start_cell)):
                cell_wk5 = i + 3
                break
        doc.clearValues(VPM_kolG + str(cell_wk5) + VPM_kolR + str(cell_wk5))   
        for j in range(12):
            start_wk =doc.Offset(VPM_weken,j)
            nr = doc.GetValue(start_wk)
            if (nr == 5):
                col = doc.GetValue(VPM_kolV + str(j+4))
                doc.SetValue(VPM_sheet+ '.' + col + str(cell_wk5), 'x')
        doc.SetValue(VPM_mndnr,1)        
        bas.MsgBox('Jaarschema is doorgevoerd',bas.MB_OK + bas.MB_ICONINFORMATION,'Jaarschema doorvoeren')
    else:
        bas.MsgBox('Maand december is nog niet toegevoegd.',
                   bas.MB_OK + bas.MB_ICONEXCLAMATION, 'Jaarschema doorvoeren')
 
def tester(args=None):
    bas.MsgBox('Ok')

g_exportedScripts = (show_msb,
                     print_bnk,
                     afb_BNK,
                     sort_data,
                     copy_content,
                     close_sheet,
                     dialog_month,
                     dialog_sort,
                     new_monthscheme,
                     tester,
                     )

Mike,
Sorry, I misunderstood your comment. You’re right that the problem isn’t with APSO; it’s just a tool for editing Python and therefore has nothing to do with how the scripts work. As you mentioned, Scriptforge might be misbehaving.

Thanks, @mikekaganski for pinging me.

The error message is raised on the code line 59
doc.activate(BNK_sheet)
and indicates that the doc object refers to some Calc sheet that disappeared, probably due to a user interaction.

@jmrn
Why does this happen ? To (maybe ?) identify a root cause I need to know a bit more :

  • Where is your script stored (in the document, in a global library, in an extension, …) ?
  • What is the scenario ? How is the script triggered: a button, a dialog event, a toolbar button, … ?
  • Where do you enter the script (g_exportedScripts is a long list …) and where do you exit the script ?

To avoid the “strange behavior”, I see next 2 workarounds:

  1. Use doc.dispose() before exiting the script
    and/or
  2. Use doc.IsAlive() (available in LO >= 25.2) to test if your doc variable still refers to a valid document. If False, assign CreateScriptService('Calc') to doc again before activating it.

Anyway, they can only make your scripts more robust.

Dear Jean Pierre,

The error only occurs on the next start of the sheet when Calc is started in Windows with the quickstart. The sheet is closed properly and afterwards reopend. In other circomstances the error doesn’t appear.

Here are the answer to your questons:
The script is stored in a global library
ScriptsStorage

There is a trigger at the opening of the document and there is a trigger when the document is closed.

Furthermore there are four triggers in a menubar.

@JPLED Do I understand correctly, that an instance of Calc service represents a given document, and becomes “dangling” when the document gets closed; and then, without some special actions, maybe re-attaching to another document, or creating a new instance, that old instance can’t be used?

an instance of Calc service represents a given document

Yes

becomes “dangling” when the document gets closed

when closed manually, yes. It is disposed when the closure is by code

that old instance can’t be used

Indeed, the above error message is displayed and the execution stops. It seems logical that, even when you reopen the document that was just closed before, a new instance should be created and assigned to the same or another variable.

My perception of the issue here is that the statement
doc = CreateScriptService('Calc')
(line 8), which is defined at the global level of the python module is executed only once at module loading. The Quick Starter forces any such module to remain loaded until a real LO stop.
(I don’t see a bug here).

I would insert before line 59 next lines:

global doc
doc = CreateScriptService('Calc')

to reinitialize doc each time the document is reopened.

2 Likes

Jean Pierre,

Your last suggestion works! I just removed line 8 to prevent duplicate code in the script. A test showed this worked without any problems. Thanks for the solution.