Ler e Escrever arquivos Office 2003 e 2007 com Apache POI

Olá povo!

Tenho que construir uma aplicação em Java SE para ler e escrever em documentos do MS Office no padão OOXML (docx, xlsx, pptx,…).

Vi pela web que uma boa forma de se fazer isto é com a API Apache POI.

Dei uma olhada em alguns tutoriais pela web, mas a maioria se destina a ensinar a leitura e escrita do formato antigo do Office (doc, xls, ppt,…).

Alguém já trabalhou com esta ferramenta anteriormente? ou alguém tem um bom artigo (mesmo que em ingles) sobre o assunto?

Dei uma olhada no Javadoc da API para ao menos ver como se realiza a leitura de um arquivo. Mas achei um pouco complexa a forma de como ele trabalha o XML do conteiner zip do OOXML principalmente pelo fato de que eu tenho que manter o template padrão dos arquivos que já existem aqui e vim até aqui pedir auxilio.

bom, aguardo vocês para a ajuda! té mais!

bom tive uns progressos.

tentei converter o arquivo que eu tinha pro formato doc pra ser mais facil de trabalhar (na verdade é pq tem mais exemplos por ai).

então acabei achando um código aqui pelo guj mesmo que trabalha com o Range e um mapa de strings pra localização e substituição do conteudo o arquivo:

vamos ao códEgo:

[code] public static void replaceWord(InputStream fistream, Map<String, String> mapReplacement) {
try{
HWPFDocument word = new HWPFDocument(new POIFSFileSystem(fistream));

        Range range = word.getRange();  

        for(String keySet : mapReplacement.keySet())  
            range.replaceText(keySet, mapReplacement.get(keySet));  

        OutputStream output = new FileOutputStream("DocTeste.doc");  

        word.write(output);  
    }catch(Exception e){  
        e.printStackTrace();  
    }  
}[/code]

esse provavelmente é o mais efetivo dos códigos pra se trabalhar com um modelo doc.

crie campos no arquivo (como se fossem tags) que possam ser alteradas com um replace (por exempo “#remetente#”). e jogue isso num map e ele devolve um arquivo .doc modificado.

public static void main(String[] args) { HashMap<String, String> mapa = new HashMap<String, String>(); mapa.put("#remetente#", "LOLOLOL"); try { replaceWord(new FileInputStream(new File("MODELO.doc")), mapa); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

o problema é que meu modelo tem um header e um footer que contem imagens. o texto ele conseguiu jogar normalmente, mas as imagens não aparecem mais.

depois tentei algo parecido com um código pra trabalhar com XWPFDocument e XWPFWordExtractor

[code] public static void reclace() throws IOException {
InputStream arquivoCarregado = new FileInputStream(new File(“MODELmine.docx”));
XWPFDocument word = new XWPFDocument(arquivoCarregado);
XWPFWordExtractor extractor = new XWPFWordExtractor(word);
String conteudo = extractor.getText();
conteudo = conteudo.replace("#nate_oper#", “Simpsons”);

    FileOutputStream output = new FileOutputStream("testeteste.docx");  
    word.write(output);  
    output.flush();  
    output.close();  
}

[/code]

provavelmente este também funciona da mesma forma. eu consigo ver a saída do texto no console, mas não sei como escrever esses dados alterados corretamente no docx do meu modelo.

alguém sabe alguma coisa a respeito (sobre um ou ambos os casos)?

bom, consegui resolver.

	public void _replaceWord(InputStream localArquivo, Map<String, String> mapa, String nomeArquivoSaida) throws Exception{  
        HWPFDocument word = new HWPFDocument(new POIFSFileSystem(localArquivo));  
        Range range = word.getRange();  
        for(String keySet : mapa.keySet())  
            range.replaceText(keySet, mapa.get(keySet));
        OutputStream output = new FileOutputStream(nomeArquivoSaida+".doc");  
        word.write(output);
        output.close();
    }

o grande lance estava na orientação da imagem.
o único modo que consegui foi deixar a imagem no template foi com o “Alinhada ao Texto”. Qualquer outro modo deu problema.

Então pra manter um padrão visual legal, coloquei as imagens dentro de uma tabela. ai funcionou de boa. mesmo no footer! ^^

Olá novamente.

Estou usando a versão 3.8 beta 4 do Apache POI para manipular um arquivo modelo que servirá como saída de relatório de alguns dados.

Neste caso o arquivo Office é do formato “doc” e estou usando o HWPFDocument para realizar a tarefa.

No modelo, eu tenho a seguinte estrutura:

Cabeçalho: Que contém uma imagem (a logomarca da empresa), o número de páginas, o cabeçalho propriamente dito e um texto que deverá ser impresso em todas as páginas geradas pelo relatório.

“Corpo”: aonde contém uma tabela com duas colunas e que são preenchidas dinamicamente.

Rodapé: Que é semelhante ao cabeçalho, mas que contém informações a serem preenchidas dinamicamente. E elos para o e-mail e site.

Usando isto:

        HWPFDocument word = new HWPFDocument(new POIFSFileSystem(filePath));
     
        Range range = word.getRange();  //to replace the content in the cols of the tables in the "body".
        range.replaceText("#n_v_left#", map.get("#_n_v_left#"));
        range.replaceText("#n_v_right#", map.get("#n_v_right#"));

        HeaderStories hs = new HeaderStories(word);

        Range hsRange = hs.getRange();//to replace the content in header and footnote
        hsRange.replaceText("#day#", map.get("#day#"));
        hsRange.replaceText("#mon#", map.get("#mon#"));
        hsRange.replaceText("#yea#", map.get("#yea#"));
        hsRange.replaceText("#n_1#", map.get("#n_1#"));
        hsRange.replaceText("#n_2#", map.get("#n_2#"));
        hsRange.replaceText("#serial#", map.get("#serial#"));
        
        OutputStream output = new FileOutputStream(outputFileName+".doc");  
        output.flush();
        word.write(output);
        output.close();

Tudo ocorria bem. A API substitui as marcações corretamente, mas ela passou a apagar os links do rodapé e a colocar automaticamente um objeto de imagem no rodapé.

como na imagem: http://i32.photobucket.com/albums/d23/samirrolemberg/image.png
(a imagem é do modelo original que contém dados sigilosos, por isso os rabiscos).

Retirei as imagens e executei novamente a aplicação, mas ocorreu o mesmo problema.

Depois tentei voltar para uma versão estável da API (a 3.7) (utilizando os mesmos metodos de substituição) mas, quando eu tento salvar um arquivo, o arquivo criado é gerado como um arquivo inválido e corrompido.

E agora não sei mais o que fazer! alguém já teve esse “problema”?

Olá samirrolemberg.

Quando li o seu post fiquei muito animado pois é exatamente o meu problema.
Cabeçalho Rodapé imagem e tudo mais que possa existir dentro de um documento WORD.

Mas enfim a uns 10 dias venho dando marretadas com a POI, show de biblioteca, mas o problema é o WORD, que tem uma formatação própria,resumindo a história vou postar o que eu fiz para solucionar o meu problema.

Peguei o meu documento do WORD e salvei eu ODT (OpenOffice), no meu caso não alterou nada com relação a apresentação da página, então utilizei 2 bibliotécas jodreports-2.4.0.jar e jodreports-cli-2.4.0-jar-with-dependencies.jar, e por incrível que pareça ficou tudo certo, cabeçalho no lugar, imagem no rodapé tabelas, grades e tudo mais, vale apenas conferir o exemplo em http://pedrocavalero.blogspot.com/2011/05/criando-documento-partir-de-templates.html

Vale lembrar que o meu documento do word é de 300k e em openOffice passou para 44k, vou economizar um grande espaço em disco.

Espero ter ajudado.

eu entrei na lista de discussão da API (na pagina em ingles)

há esse bug chato mesmo na poi 3.8 beta.

O mais estranho é que mesmo trocando a api pra uma versão mais estavel tb não funionava.

e trabalhar com odt não é opção pra mim, mas valeu pela dica.