Programando o OO.o com Python Introdução Python é uma linguagem de programação de propósito geral, interpretada, multiplataforma e de fácil aprendizagem. Ela é orientada a objetos, mas pode ser usada na programação estruturada. Além disso, ela é livre, muito bem documentada e conta com uma comunidade bastante ativa. Desde o OO.o 1.1.0, o núcleo da linguagem de programação Python versão 2.2.2 é instalado, por padrão, juntamente com o OpenOffice.org. Deste modo, programadores Python podem escrever aplicativos para o Openoffice.org. O componente PyUNO é o responsável pela intermediação entre o interpretador Python e o OO.o. Ele coloca à disposição do desenvolvedor todos os objetos da API do OO.o. Aqui, você não encontrará explicações sobre a API do OO.o. Para conhecê-la, consulte a minha apostila _ Introdução ao OpenOffice.org Basic _ ou consulte o item Mais Informações no final deste documento. Usando Python para OO.o ( PyUNO ) Para usar Python, você só precisa instalar o OO.o versão 1.1.x ou superior. É recomendado o uso da versão distribuida e instalada com o OO.o e não as versões oficiais do Python (apesar da substituição ser possível). Python é instalada, por padrão, no diretório <OO.o_Install>\program\python-core-2.2.2. Para iniciar o ambiente Python, alterne para o diretório <OO.o_Install>\program e execute o script python.bat (ambiente Windows). Os programas Python para o OO.o podem ser escritos para serem usados de duas maneiras diferentes: (1) a partir de um processo Python ou (2) de dentro de um processo do OO.o. No primeiro modo, o OO.o precisa ser inicializado para reconhecer conexões remotas. No segundo, o programa Python precisa ser instalado como um componente UNO e ser ativado a partir de um evento definido pelo programador (seleção de uma opção de menu, clique sobre um ícone, chamado a partir de uma macro OOoBasic, etc). Num processo Python Este método de execução é lento, principalmente pela sobrecarga da comunicação entre os processos Python e OO.o. Ele deve ser usado quando você: (1) estiver aprendendo PyUNO ou desejar o menor tempo entre codificação e execução, e (2) for usar o seu programa num processo separado (p.ex: como parte de um script). Digite o exemplo abaixo no seu editor preferido e salve-o (formato UNIX, sem CR) como ex_py_calc.py: ## ##################################################### ## ex_py_calc.py ## Exemplo de programa Python para o OO.o. ## ## ## ## ## ## ## ## ## ## ## ## ## ## - Usa o processo Python para rodar o programa ( modo 1) - Abre um novo documento do calc e preenche algumas células com dados - Salva e fecha o novo documento ATENCAO -> antes de usar este exemplo voce precisa: 1. encerrar todo OOo (inclusive o inicio rápido) 2. iniciar o OOo para aceitar conexão remota, com o comando: <oooInstall>\program\soffice "-accept=socket,host=localhost,port=2002;urp;" Uso: <oooInstall>\program\python ex_py_calc.py ............. OU ............... <oooInstall>\program\python >> import ex_py_calc.py ##################################################### import uno # cria o contexto do componente UNO localContext = uno.getComponentContext() # cria o UnoUrlResolver resolver = localContext.ServiceManager.createInstanceWithContext ("com.sun.star.bridge.UnoUrlResolver",localContext) # conecta ao processo OO.o (você iniciou o OO.o para aceitar conexões remotas) ctx = resolver.resolve ("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext") smgr = ctx.ServiceManager # de agora em diante, o uso da API do OO.o é bastante semelhante ao # da linguagem OOoBasic, portanto você pode consultar a apostila # <Introdução ao OOoBasic> (ou outra documentação) para aprender # como programar com os objetos da API do OO.o. # # cria o objeto Desktop desktop = smgr.createInstanceWithContext ("com.sun.star.frame.Desktop", ctx) # cria um novo documento (planilha) do Calc oDoc = desktop.loadComponentFromURL ("private:factory/scalc","_blank",0,()) # obtem a folha de planilha 1 oPlan = oDoc.getSheets().getByIndex(0) # dados para as celulas lin = [ ['Gênero','Quant','Preço'], ['Banana','1 dz',1.50], ['Arroz','5 kg',7.50], ['Feijão','3 kg',4.50] ] # obtem as células e preenche com dados for i in range(4): for j in range(3): oCel = oPlan.getCellByPosition(j, i) oCel.setFormula(lin[i][j]) # salva o arquivo, altere o caminho para o seu sistema sURL = uno.systemPathToFileUrl ('C:\Documents and Settings\user1\My Documents\ex_py_calc.sxc') oDoc.storeToURL(sURL, ()) # fecha o arquivo oDoc.close(True) # # para evitar problemas com metodos <oneway> # ctx.ServiceManager Vejamos os passos preparatórios para rodar programas neste modo: (1) iniciar o processo OO.o, e (2) iniciar o processo Python. No passo (1) devemos iniciar o OO.o para aceitar conexões remotas. Certifique-se de encerrar todos os processos do OO.o, inclusive o Início Rápido e no “prompt” digite o comando abaixo e tecle <Enter>: <oooInstall>\program\soffice "-accept=socket,host=localhost,port=2002;urp;" No passo (2) iniciamos o processo Python. O OO.o traz o “script” python.bat que se encarrega desta tarefa. No “prompt” digite o comando abaixo e tecle <Enter>: <oooInstall>\program\python ex_py_calc.py ................ OU ................... <oooInstall>\program\python <Enter> >> import ex_py_calc.py Agora, teste o nosso exemplo. Em caso de erros, revise o programa (testado com OO.o 1.1.3 + XPp). Num processo OO.o Este modo deve ser usado quando você desejar: (1) rapidez na execução do seu programa; (2) distribuir seu programa por várias instalações do OO.o, e (3) executar o seu programa pela interface gráfica do OO.o. Neste modo, o programa Python deve ser escrito como um componente UNO e deve ser parte de uma classe Python. Adicionalmente, precisamos de um arquivo para configurar o OO.o de modo que ele saiba qual evento dispara a execução do programa. O exemplo abaixo (ex_comp_py_calc.py) tem a mesma funcionalidade do anterior: ######################################################################## ## ex_comp_py_calc.py ## Exemplo de programa Python para o OO.o. ## - Usa o processo OO.o para rodar o programa ( modo 2) ## - Abre um novo documento do calc e preenche algumas células com dados ## - Salva e fecha o novo documento ######################################################################## import uno import unohelper from com.sun.star.task import XJobExecutor # implementa um componente UNO, derivando da classe padrão # unohelper.Base e das interfaces que você vai implementar. class PyCalcJob( unohelper.Base, XJobExecutor ): def __init__( self, ctx ): # o construtor recebe o contexto (ctx) como argumento. # armazena o contexto para uso posterior. self.ctx = ctx def trigger( self, args ): # nota: args[0] == "DespesaAlimentar", veja config. abaixo # cria o objeto Desktop desktop = self.ctx.ServiceManager.createInstanceWithContext( "com.sun.star.frame.Desktop", self.ctx ) # cria um novo documento (planilha) do Calc oDoc = desktop.loadComponentFromURL ("private:factory/scalc","_blank",0,()) # obtem a folha de planilha 1 oPlan = oDoc.getSheets().getByIndex(0) # dados para as celulas lin = [ ['Gênero','Quant','Preço'], ['Banana','1 dz',1.50], ['Arroz','5 kg',7.50], ['Feijão','3 kg',4.50] ] # obtem as células e preenche com dados for i in range(4): for j in range(3): oCel = oPlan.getCellByPosition(j, i) oCel.setFormula(lin[i][j]) # salva o arquivo, altere o caminho para o seu sistema sURL = uno.systemPathToFileUrl ('C:\Documents and Settings\Anadsec\My Documents\ex_py_calc.sxc') oDoc.storeToURL(sURL, ()) # fecha o arquivo oDoc.close(True) # o loader python busca uma variável estática g_ImplementationHelper g_ImplementationHelper = unohelper.ImplementationHelper() # adiciona a classe ao container de implementação, que é # usado pelo loader para registrar/instanciar o componente g_ImplementationHelper.addImplementation( \ PyCalcJob, # classe de objeto UNO "org.openoffice.comp.pyuno.nad.DespesaAlimentar", # nome da implementação # mude este nome para o seu script ("com.sun.star.task.Job",),) # lista dos serviços implementados # (apenas um serviço) Apesar das semelhanças, algumas diferenças são notórias, por exemplo: toda a etapa de conexão com o OO.o foi removida. Vamos agora preparar o arquivo de configuração abaixo, que cuida da configuração do OO.o para executar o componente python. Digite o código xml no seu editor de texto favorito e salve como addons.xcu: <?xml version="1.0" encoding="UTF-8"?> <oor:node xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office"> <node oor:name="AddonUI"> <node oor:name="AddonMenu"> <node oor:name="org.openoffice.comp.pyuno.nad.DespesaAlimentar" oor:op="replace"> <prop oor:name="URL" oor:type="xs:string"> <value>service:org.openoffice.comp.pyuno.nad.DespesaAlimentar?insert</value> </prop> <prop oor:name="ImageIdentifier" oor:type="xs:string"> <value>private:image/3216</value> </prop> <prop oor:name="Title" oor:type="xs:string"> <value>Food Expense</value> <value xml:lang="pt-BR">Despesa Alimentar</value> </prop> </node> </node> </node> </oor:node> Já temos os arquivos necessários para cirar o pacote UNO (um arquivo zip). Então crie um arquivo ex_comp_py_calc.zip contendo os arquivos ex_comp_py_calc.py e addons.xcu. O próximo passo é a instalação do pacote ex_comp_py_calc.zip. Para isto, mova o pacote para o diretório <OOoUserInstall>\user\uno_packages e em seguida execute o programa pkgchk com o comando (ATENÇÃO: feche todos os processos do OO.o, inclusive o Início Rápido): <OOoInstall>\program\pkgchk Agora, ao iniciar o OO.o uma nova opção de menu estará disponível em (Ferramentas => Suplementos => Despesa Alimentar). Ao selecioná-la o nosso exemplo será executado. Se ocorrer algum erro, revise os arquivos ( testado com OO.o 1.1.3 e XPp ). Podemos, ainda, escrever componentes Python para serem utilizados por outros programas (por exemplo, implementar uma interface UNO e chamar seus métodos de uma macro OOoBasic). Nestes casos, precisamos apenas registrar o componente Python no OO.o. Não é necessário escrever o arquivo de configuração e nem criar um pacote UNO, basta copiar o componente para o diretório uno_packages e executar o programa pkgchk, como explicado. Usando tipos UNO com o Python A API do OO.o define diversos tipos de dados, que são usados como valores para propriedades de objetos ou como argumentos para os métodos, a seguir veremos como usar alguns destes tipos em nossos programas: Os tipos de dados simples são, de modo geral, convertidos para tipos similares do Python. Por exemplo, você pode usar True/False quando um objeto UNO lidar com um tipo boolean. Existem objetos no módulo uno.py (importado nos programas PyUNO) representando vários tipos de dados (uno.Bool – uno.Char, etc): oCursor.gotoEnd ( uno.Bool ( 1 ) ) um_char = uno.Char ( u'A' ) # uno.Char('A') <= errado Constantes ( Constant Groups ) e Enumerações ( Enums ) devem ser importadas como abaixo: from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK from com.sun.star.text.TextContentAnchorType import AS_CHARACTER A seguir a constante PARAGRAPH_BREAK e o valor Enum AS_CHARACTER podem ser usados no código Python: oText.insertControlCharacter( oCursor, PARAGRAPH_BREAK, 0 ) Estruturas ( Structs ) também devem ser importadas: from com.sun.star.awt import Size # .... oRetangulo.setSize ( Size ( 2000, 1000 ) ) Seqüências UNO são mapeadas para o tipo Python tupla (listas não funcionam). Muitos métodos da API recebem como argumento uma seqüência de estruturas. Por exemplo, o último argumento do método loadComponentFromURL é um vetor da estrutura com.sun.star.beans.PropertyValue: # importa a estrutura from com.sun.star.beans import PropertyValue # # para sequencia vazia (não precisa importar) oDoc = oDT.loadComponentFromURL( sUrl , "_blank", 0, () ) # # sequencia com um elemento, note a vírgula final aProp = PropertyValue( "Hidden" , 0 , True, 0 ), oDoc = oDT.loadComponentFromURL( sUrl , "_blank", 0, aProp ) # # sequencia com mais de um elemento aProps = ( PropertyValue( "FilterName" , 0, filtro , 0 ), PropertyValue( "FilterOptions",0, opcoes ,0)) oDoc = oDT.loadComponentFromURL( sUrl , "_blank", 0, aProps ) Você está pronto para prosseguir sozinho, seguem alguns vínculos contendo documentos/código sobre programação para o OO.o. Mais Informações PyUNO Bridge => Documentação oficial com exemplos de programas para os dois modos e vínculos para aplicações desenvolvidas com Python. OOo SDK => Tudo que você precisa, principalmente documentação (The Developer's Guide e IDL Reference) além de exemplos. Apostila de Introdução ao OOoBasic => Apesar de orientada para o OOoBasic, contém inúmeros exemplos de uso da API com uma descrição dos objetos, métodos e propriedades utilizadas. Addons1_1 => Documento detalhando o arquivo de configuração addons.xcu. Contém uma macro para criar automaticamente este arquivo. OOoForum => Fórum de discussão (em inglês) sobre o OOo. Faça uma busca com a palavra-chave Python. Danny's Python modules => Da seção de código do OOoForum, um exemplo de componente UNO. Modeless window with controls in Python => Da seção de código do OOoForum, um exemplo sobre a criação de janelas contendo controles. Autor Tradução resumida do documento PyUNO Bridge, por Noelson Alves Duarte, em 23/02/2005.