Do import another detrous module from another using LibreOffice macros

2

This question refers to the use of python macros in LibreOffice. I've been doing some research on the subject and found that one of the ways to add a macro written in Python to LibreOffice would be to put it in the directory: ~/.config/libreoffice/4/user/Scripts/python . So far so good, but I would like to go one step further. When developing larger programs, it is often necessary to break it down into multiple modules. Consequently, in the case of mod_A.py and mod_B.py in the same project, we would have:

import mod_B # Estando em mod_A

However, when I try to run the mod_A module macro through [Tools & Organize Macros > Python] > mod_A > one_functions get a big error message 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 'getMovementGeneral' is not defined     /usr/lib/libreoffice/share/Scripts/python/Balanco.py:41 in function main () [movement = getMovementGeral (model, sheets)]     /usr/lib/libreoffice/program/pythonscript.py:869 in function invoke () [ret = self.func (* args)]   )

Complementing. I report that Balanco.py and Movimento.py are in the same folder as indicated above.

In short: 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 a mistake of mine, I did not realize that the error message I transcribed above was not an import error. However, I guarantee that in subsequent tests I received messages stating that Movement was not found. Anyway, I realized by the link they 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/')

This is the location of the macros in LibreOffice / OpenOffice. Then I enter the import of the desired module.

It may be better to insert the master module code.

'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,

'

In this way I was able to make the macro run in LibreOffice within the desired file. So I consider the problem solved.

    
asked by anonymous 22.11.2017 / 12:35

3 answers

1

Please wait -

You did not get an error message in 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 need to place module prefixes in code, you can use one of the other forms of import, such as:

from Mod_B import getMovimentoGeral
    
22.11.2017 / 14:05
0

Place the modules or packages in this directory

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

File: user/Scripts/python/test.py .

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

g_exportedScripts = test,

File: user/Scripts/python/pythonpath/hello.py .

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

Documentation in English .

    
22.11.2017 / 18:55
0

In order to organize explain what was done I inform the following: Initially, looking at the link that rray passed me, I realized that I could add path to the referenced module (in the case of Movimiento.py) by doing: sys.path.append('/home/jorge/.config/libreoffice/4/user/Scripts/python/') #Não aceita ~/ in Balanco.py. This solution worked. Later, following the same rray recommendation, I created the folder'pythonpath 'in' ~ / .config / libreoffice / 4 / user / Scripts / python / 'and then created a symbolic link for' Move.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. Conclusion The two solutions worked, but it seems that the second proposal favors the distribution of the macro in other computers and still in Windows, if I am not mistaken. I'll put the codes below

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,´

Then Move.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,
    
10.12.2017 / 15:42