+2

Gerando Documentos OpenOffice Dinamicamente

criado por Giovanni Floridia em 25/01/2006 6:58am
Abra o OpenOffice e crie um documento com a tabela, como a seguir, salvando-o com o nome tab1.odt.



(Uma imagem alternativa pode ser encontrada em http://www.floridia.net/OpenDocumentFormat/Artigo/html/fig3.gif)

Como pode ser percebido, já estamos preparando o arquivo para o uso de templates, marcados pelas chaves {}. Crie uma pasta OpenDocumentFormat em algum lugar do seu htdocs e descompacte o arquivo, criando uma nova pasta tab1 (costumo fazer uma cópia do arquivo, mudando a extensão de odt para zip).

Há algumas rotinas para zipar um arquivo, a minha eleita foi a ziplib.php do phpwiki versão 1.3.11.p1. São necessárias 3 mudanças muito simples no arquivo. Uma versão modificada pode ser encontrara <a href="http://floridia.net/OpenDocumentFormat/FacaVoceMesmo_OpenDocumentFormat.zip">aqui</a>.

O SmartTemplate é uma ferramenta leve e rápida. Incialmente devemos colocar os arquivos class.smarttemplate.php, class.smarttemplateparser.php e class.smarttemplatedebugger.php no include_path ou no diretório atual para pode utilizar a biblioteca.

Criamos uma cópia de content.xml chamada content2.xml, dentro da pasta tab1. Incluímos as duas linhas, conforme a seguir.

 (...)
</table:table-row>
  </table:table-header-rows>
<!-- BEGIN users -->
    <table:table-row>
      <table:table-cell table:style-name="Tabela1.A2" office:value-type="string">
        <text:p text:style-name="P3">{NAME}</text:p>
      </table:table-cell>
      <table:table-cell table:style-name="Tabela1.B2" office:value-type="string">
        <text:p text:style-name="P3">{GROUP}</text:p>
      </table:table-cell>
    </table:table-row>
<!-- END users -->
  <table:table-row>
(...)


Note a presença dos marcadores de bloco BEGIN / END users e as tags {NAME} e {GROUP}.

Substituímos a primeira linha

<?xml version="1.0" encoding="UTF-8"?>

pelo marcador {XMLHEADER}.

Salvemos o arquivo content2.xml. O motivo da mudança é que na primeira linha existem caracteres especiais que geram um erro quando o OpenOffice tenta abrir o arquivo gerado.

O programa que deve processá-lo é o que segue.

<?php

require_once ("ziplib.php");
require_once "class.smarttemplate.php";

$base="tab1";

    $x['users'][0]['NAME']='Giovanni';
    $x['users'][0]['GROUP']='Admin';

    $x['users'][1]['NAME']='Leonardo';
    $x['users'][1]['GROUP']=utf8_encode('Operações');

    $x['users'][2]['NAME']='Orfeu';
    $x['users'][2]['GROUP']='Desenvolvimento';

    $x['users'][3]['NAME']='Isa';
    $x['users'][3]['GROUP']='Vendas';

    $content = new SmartTemplate("$base/content2.xml");
    $content->assign($x);
    $content->assign('XMLHEADER', '<?xml version="1.0" encoding="UTF-8"?>');
    
// $content->output();
// exit;


$zipfile = new ZipWriter("Comentario", $base."_generated.odt", "application/vnd.oasis.opendocument.text");
$ooofiles = array(
                   "mimetype",
//                 "content.xml",  // Note que está comentada!
                   "styles.xml",
                   "meta.xml",
                   "settings.xml",
//                 "Configurations2/",
                   "META-INF/manifest.xml",
//                 "Pictures/",
//                 "Thumbnails/thumnail.png"                   
             );

foreach ($ooofiles as $file) {
  $handle = fopen("$base/$file","rb");
  $filedata = fread($handle , filesize("$base/$file"));
  $zipfile -> AddRegularFile($file, $filedata);
}

$zipfile->addRegularFile('content.xml', $content->result() );

echo $zipfile -> finish();

?> 

Vale notar o que é possível atribuir a uma variável uma tabela inteira, evitando a execução do loop: a matriz $x['users'] é substituída em uma linha! Veja, também, que não necessário incluir muitos marcadores no template, o que será importante para a facilidade de criação e manutenção dos documentos-modelo.

Apesar de lermos o arquivo content2.xml, o compactamos com o nome content.xml. Assim, podemos utilizar diversos esqueletos de arquivo, caso estilos e outros detalhes inscritos nos outros arquivos não mudem. Não esqueça de comentar o arquivo content.xml do vetor $ooofiles.

Ainda deve ser notado que as linhas que possuem caracteres especiais devem passar por uma codificação UTF8, senão aparecerão erros no arquivo. É claro que o procedimento correto é codificar todos os campos, este é apenas um exemplo didático.

Caso haja algum problema, descomente as linhas a seguir para enviar o resultado para a tela.

// $content->output();
// exit;



Comentários:

Mostrando 1 - 4 de 4 comentários
Alguém tem algum exemplo de planilha com mais de uma pasta?

Valeu!

Adriano
07/03/2006 10:17am (~18 anos atrás)

Pessoal,

Como é minha primeira publicação, acabei deixando html demais. O código estava ilegível...

Dei uma limpada nos códigos, que tinham html demais, que acabou não sendo interpretado. Acho que agora a terceira parte está mais clara.


[]'s

Giovanni
26/01/2006 8:54am (~18 anos atrás)

Obrigado, Paulo.

A documentação do PDF é importante para aplicações mais complexas, inclusie para contribuir com o próprio phpdocwiter, que eu não conhecia.

Valem duas ressalvas. Primeiro, a abordagem do projeto é de gerar o documento codificando - similar ao uso de libs para criar pdf e outros formatos. Aqui utiliza-se o próprio OpenOffice para montar, de um jeito quase-WYSIWYG, o documento. É mais simples, mas pode-se deixar xml-lixo no documento.

Segundo, esta abordagem não é só para Writer, mas para planilhas eletrônicas Calc ou qualquer outro documento da suíte OpenOffice. Na realidade, é mais geral ainda - pode-se criar figura ou animações sgv, em pricípio. No site http://www.floridia.net/OpenDocumentFormat tenho um exemplo de planilha.

Abraços,

Giovanni
26/01/2006 8:52am (~18 anos atrás)

Paulo disse:
Existe um projeto chamado PHP DocWriter (http://phpdocwriter.sf.net) que utiliza classes do PHP para gerar todo o arquivo OpenOffice. Ele já faz o trabalho de geração de tabelas, propriedades da página, formatação de caracteres, imagens etc. Há muitos recursos ainda não implementados, mas, para projetos que demandem poucos recursos esta é uma excelente classe para geração de relatórios.

Gostei muito do artigo por ter abordado a coisa prática ao invés da teórica. De qualquer forma, para a utilização de recursos avançados, é fundamental a leitura do PDF sobre OpenDocument.

Parabéns!
26/01/2006 6:11am (~18 anos atrás)

Novo Comentário:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)