Import another debris module from another using Libreoffice macros

Asked

Viewed 229 times

2

This question refers to the use of macros in python in Libreoffice. I’ve been doing some studies on the subject and found that one of the ways to add a Python-written macro to Libreoffice would be to put it in the directory: ~/.config/libreoffice/4/user/Scripts/python. So far so good, but I’d like to take a step forward. When developing larger programs, it is often necessary to divide it into several modules. Consequently we would have, in the case of mod_A.py and mod_B.py modules in the same project:

import mod_B # Estando em mod_A

However, when I try to run the mod_A macro through [Tools > Organize Macros > Python] > mod_A > uma_das_functions I get a big error message informed that mod_B was not found.

com.sun.star.uno.Runtimeexceptionerror During invoking Function main in module file://usr/lib/libreoffice/share/Scripts/python/Balanco.py (name 'getMovimentGeral' is not defined /usr/lib/libreoffice/share/Scripts/python/Balanco.py:41 in Function main() [movement = getMovimentGeral(model, Sheets)] /usr/lib/libreoffice/program/pythonscript.py:869 in Function invoke() [Ret = self.func( *args )] )

complementing. I inform you that Balanco.py and Movimento.py are in the same folder as above.

In summary: I would like to know if anyone has knowledge about how to import a project module into a python macro developed for Libreoffice / Openoffice.

Actually, by my mistake, I did not realize that the error message I transcribed above was not an import error. However, I assure you that in subsequent tests I received messages stating that Movement was not found. Anyway, I realized by the link you sent me, that I could add the path to the macro folder to sys.path. So I inserted the following command at the beginning of the program:

sys.path.append('/home/jorge/.config/libreoffice/4/user/Scripts/python/')

which is the location of macros in Libreoffice / Openoffice. Then I inserted the import of the module desired.

Perhaps you’d better enter the code from the main module.

`Arquivo: Balanco.py
@author: Jorge Luiz
Aquivo principal da aplicação (teste) para totalização do balanço geral de        uma planliha
voltada para controle de despesas de um condoínio.
Há uma aba para cada mês do ano, sendo que o balanço final do mês é   transferido para o mês seguinte.
@note: A coluna dos valores é "C"
@attention: foi encontrada uma dificuldade na execução de import de   módulos locais, no caso Movimento.py
o que foi resolvido adicionando-se o caminho do local do script a sys.path
Este é o arquivo pricipal da aplicação / macro para rodar numa planilha   específica do Calc.
Depende do módulo Movimento
'''
import sys
from datetime import date

lSheets = ('JAN', 'FEV', 'MAR', 'ABR', 'MAI', 'JUN', 'JUL', 'AGO', 'SET',
       'OUT', 'NOV', 'DEZ')

__debug = False     #Mudar __debug para False quando for distribuir.

def init():
    '''
    Obter model no contexto de uma instância do LibreOffice  já executando.
    @todo: Tendo em vista que esta é uma macro para um arquivo específico:
    1: Tentar inserir a macro no próprio arquivo OU
    2. Fazer a verificação do nome do arquivo.
    '''

    desktop = XSCRIPTCONTEXT.getDesktop()
    model = desktop.getCurrentComponent()

    #Graças ao comando abaixo é possível reconhecer os imports (import Movimento)
    #Obs: não aceita caminho: ~/
    sys.path.append('/home/jorge/.config/libreoffice/4/user/Scripts/python/')

    return model


def main():
    # access the active sheet
    if not __debug:
         model = init()

    else:
        #Quando em modo de depuração.
        import initOO
        model = initOO.initOO()

    import Movimento    #Esse import deve ficar após as inicializções.

    if not model:
        print('Falha ao obter model')
        sys.exit(1)

    anoSimpl = str(date.today().year)[-2:]
    nomesSheets = []
    for sheet in lSheets:
        nomesSheets.append(sheet + ' ' + anoSimpl)

    print('Lendo Planilhas...')   
    lMov = Movimento.getMovimentoGeral(model, nomesSheets)

    print('Escevendo movimento financeiro')

    sheetResumo = model.Sheets.getByName('RESUMO')
    Movimento.escreveMovimento(sheetResumo, lMov)

    print('Planilha%12s' % 'VALOR')
    valorTotal = 0.0
    for mov in lMov:
        print(mov['sheet'])
        valorMensal = 0.0
        for valor in mov['movimento']:
            valorMensal += valor
            valorTotal += valor
            print ('%21.2f' % valor)


        print('Saldo no mês:%8.2f\n' % valorMensal)

    print('Saldo final %9.2f' % valorTotal)

    receita,despesa = Movimento.getReceitasDespesas(lMov)

    print('RESUMO ---------------------------------')
    print('Receita:%13.2f\ndespesa:%13.2f\nsaldo:  %13.2f' %(receita, despesa, receita + despesa))

if __name__ == '__main__':    #Essa parte é só para debug.
    main() 
    print ('FIM')

g_exportedScripts = main,

`

This way I was able to make the macro run in Libreoffice inside the desired file. So I think the problem is solved.

3 answers

1

Wait -

You did not get an error message on your import - maybe you’re just not familiar with Python

The function of the other module will be available as

Mod_B.getMovimentoGeral

after a import Mod_B.

If you do not want to put the prefixes of the modules in the code, you can use one of the other import forms, such as:

from Mod_B import getMovimentoGeral
  • I really made a mistake when copying the message, but I assure you that I had previously received an error message in import. I think the difference in this issue is that it is Python code to be executed as macro in a Libreoffice / Openoffice file. Normally there would be no error in import, but by some peculiarity in the macros environment arises this disconcerting error.

0

Put modules or packages in this directory

~/.config/libreoffice/4/user/Scripts/python/pythonpath

Filing cabinet: user/Scripts/python/test.py.

def test():
    import hello
    hello.do_hello()

g_exportedScripts = test,

Filing cabinet: user/Scripts/python/pythonpath/hello.py.

def do_hello():
    f = open('hello.txt', 'w')
    print("Hello", file=f)

Documentation in English.

  • I Translated your Answer for en :), you could use a translater next time, but no problem now

  • Okay, Thank you.

  • Thanks for the reply. It seems to work. I created the folder pythonpath in ~/.config/libreoffice/4/user/Scripts/python/ and there created a symbolic link to the referenced module.

  • Please, acepte esta Respuesta if it solves the problem.

0

With a view to organising an explanation of what has been done, I would like to inform you: Initially, looking at the link that rray gave me, I realized that I could add the path for the referenced module (in the case of Movement.py) making: sys.path.append('/home/jorge/.config/libreoffice/4/user/Scripts/python/') #Não aceita ~/ in Balanco.py. This solution worked. Later, following the same recommendation of rray, I created the pythonpath folder in '~/. config/libreoffice/4/user/Scripts/python/' and then created a symbolic link to Movimento.py in pythonpath . I also commented on the line that added the path to the macros folder: #sys.path.append('/home/jorge/.config/libreoffice/4/user/Scripts/python/') #Não aceita ~/. That solution worked too. Completion The two solutions worked, but it seems that the second proposal favors the distribution of the macro on other computers and also on Windows, if I’m not mistaken. I’ll track the codes

Balanco.py ´

'''
Arquivo: Balanco.py
@author: Jorge Luiz
Aquivo principal da aplicação (teste) para totalização do balanço geral de     uma planliha
voltada para controle de despesas de um condoínio.
Há uma aba para cada mês do ano, sendo que o balanço final do mês é       transferido para o mês seguinte.
@note: A coluna dos valores é "C"
@attention: foi encontrada uma dificuldade na execução de import de    módulos locais, no caso Movimento.py
o que foi resolvido adicionando-se o caminho do local do script a sys.path
Este é o arquivo pricipal da aplicação / macro para rodar numa planilha          específica do Calc.
Depende do módulo Movimento
'''
import sys
from datetime import date

lSheets = ('JAN', 'FEV', 'MAR', 'ABR', 'MAI', 'JUN', 'JUL', 'AGO', 'SET',
       'OUT', 'NOV', 'DEZ')

__debug = False     #Mudar __debug para False quando for distribuir.

def init():
'''
Obter model no contexto de uma instância do LibreOffice  já executando.
'''

desktop = XSCRIPTCONTEXT.getDesktop()
model = desktop.getCurrentComponent()

#Graças ao comando abaixo é possível reconhecer os imports (import Movimento)
#Obs: não aceita caminho: ~/
#sys.path.append('/home/jorge/.config/libreoffice/4/user/Scripts/python/')

return model


def main():
    nomeSheetResumo = 'RESUMO'

    if not __debug:
        model = init()

    else:
        #Quando em modo de depuração.
        import initOO
        model = initOO.initOO()

    import Movimento    #Esse import deve ficar após as inicializções.

    if not model:
    print('Falha ao obter model')
    sys.exit(1)

    anoSimpl = str(date.today().year)[-2:]

    nomesSheets = []
    for sheet in lSheets:
        nomesSheets.append(sheet + ' ' + anoSimpl)

    movimento = Movimento.Movimento(model.Sheets, nomesSheets)

    movimento.escreveMovimento(nomeSheetResumo)




if __name__ == '__main__':
    main() 
    print ('FIM')

g_exportedScripts = main,´

Next up Movement.py

'''
Created on 19 de nov de 2017

@author: jorge
'''


class Movimento():
    '''
    Para os movimentos financeiros do balanço do condomínio
    '''

    def __init__(self, sheets, lNomesSheets):
        '''
        Construtor.
        @param sheets: as abas da planilha.
        @param lNomesSheets: lista de nomes das planilhas onde procurar os movimentos. Geralmente os mêses.
        '''
        self.sheets = sheets                #As abas da planilha.
        self.lNomesSheets = lNomesSheets    #Lista de nomes das planilhas que devem conter os movimentos.


    def getMovimentoSheet(self, sheet, linIni=0):
        '''
        Obter os valores do movimento de uma aba da planilha passada como parâmetro
        @param sheet: a aba a ser lida.
        @param linIni: linha inicial a ser lida (índice). A primeira linha é zero.
        @return: dicionário {'sheet': 'nome_da_aba', 'valores': (lista_de_valores)}
        '''
        colDesc = 0
        colData = 1
        colVal = 2

        lin = linIni

        movSheet = []

        while 1:
            lin += 1
            #Verificar se ainda há linhas (movimento) para serem lidadas.
            cel = sheet.getCellByPosition(colDesc,lin)
            if cel.String.strip() == 'TOTAL'or (not cel.String):
                break

            descricao = cel.String.strip()
            data = sheet.getCellByPosition(colData, lin).getValue()
            valor = sheet.getCellByPosition(colVal, lin).getValue()

            dictMov = {'descricao': descricao, 'data': data, 'valor': valor}

            movSheet.append(dictMov)

        return movSheet


    def getMovimentoGeral(self):
        '''
        Obter uma lista com todos os itens de receita e despesa do movimento financeiro da planilha.
        @return: lista de dicionários keys('descricao', 'data', 'valor').
        '''
        movimentoGeral = []
        lin = 0
        for nomeSheet in self.lNomesSheets:
            if not self.sheets.hasByName(nomeSheet):
                #Não há todos os meses na planilha.
                continue

            sheet = self.sheets.getByName(nomeSheet)

            movMes = self.getMovimentoSheet(sheet, lin)
            movimentoGeral.extend(movMes)
            lin = 1 #A linha aqui não é zerada por que considera-se que nas abas subsequentes a primeira
                    #linha refe-se ao valor TRANSPORTADO da planilha anterior o qual não deve ser computado.

        return movimentoGeral


    def escreveMovimento(self, nomeSheetResumo):
        '''
        Escrever todos os itens de receita e despesa na aba de resumo, além de totalizar.
        @param nomeSheetResumo: o nome da aba para a escrita do resumo.
        '''
        colDescr = 0 
        colData = 1
        colValor = 2


        if not self.sheets.hasByName(nomeSheetResumo):
            ns = self.sheets.getCount()
            self.sheets.insertNewByName(nomeSheetResumo , ns )

        sheetResumo = self.sheets.getByName(nomeSheetResumo)

        lMov = self.getMovimentoGeral()

        valorTotal = 0.0
        lin = 1
        for mov in lMov:
            cellDescr = sheetResumo.getCellByPosition(colDescr, lin)
            cellData = sheetResumo.getCellByPosition(colData, lin)
            cellValor = sheetResumo.getCellByPosition(colValor, lin)

            cellDescr.setString(mov['descricao'])
            cellData.setValue(mov['data'])
            cellValor.setValue(mov['valor'])

            valorTotal += mov['valor']

            lin += 1

        sheetResumo.getCellByPosition(colValor, lin).setValue(valorTotal)




g_exportedScripts = Movimento,

Browser other questions tagged

You are not signed in. Login or sign up in order to post.