Introdução ao Docx4J
1. Visão geral
Neste artigo, focaremos na criação de um documento .docx usando a biblioteca https://www.docx4java.org [docx4j].
O Docx4j é uma biblioteca Java usada para criar e manipular arquivos Office OpenXML - o que significa que só pode funcionar com o tipo de arquivo .docx, enquanto as versões anteriores do Microsoft Word usam uma extensão .doc (arquivos binários).
*Observe que o formato _OpenXML_ é suportado pelo Microsoft Office, começando com a versão 2007.*
*2. Configuração do Maven *
Para começar a trabalhar com o docx4j, precisamos adicionar a dependência necessária em nosso pom.xml:
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j</artifactId>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
Observe que sempre podemos procurar as versões mais recentes das dependências em https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.docx4j%22%20AND%20a%3A%22docx4j% 22 [Maven Central Repository].
A dependência JAXB é necessária, pois o docx4j usa essa biblioteca sob o capô para organizar/desmarcar partes XML em um arquivo docx.
===* 3. Crie um documento de arquivo Docx *
====* 3.1 Elementos de texto e estilo *
Vamos primeiro ver como criar um arquivo docx simples - com um parágrafo de texto:
WordprocessingMLPackage wordPackage = WordprocessingMLPackage.createPackage();
MainDocumentPart mainDocumentPart = wordPackage.getMainDocumentPart();
mainDocumentPart.addStyledParagraphOfText("Title", "Hello World!");
mainDocumentPart.addParagraphOfText("Welcome To Baeldung");
File exportFile = new File("welcome.docx");
wordPackage.save(exportFile);
Aqui está o arquivo welcome.docx resultante:
link:/wp-content/uploads/2017/10/im1.png [imagem:/wp-content/uploads/2017/10/im1-300x236.png [imagem, largura = 554, altura = 436]]
Para criar um novo documento, precisamos usar o WordprocessingMLPackage, que representa um arquivo docx no formato OpenXML, enquanto a classe MainDocumentPart mantém uma representação da parte principal document.xml.
Para esclarecer as coisas, descompacte o arquivo welcome.docx e abra o arquivo word/document.xml para ver como é a representação XML:
<w:body>
<w:p>
<w:pPr>
<w:pStyle w:val="Title"/>
</w:pPr>
<w:r>
<w:t>Hello World!</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t>Welcome To Baeldung!</w:t>
</w:r>
</w:p>
</w:body>
Como podemos ver,* cada frase é representada por uma sequência (r) de texto (t) dentro de um parágrafo (_p _) *, e é para isso que serve o método _addParagraphOfText () _.
O addStyledParagraphOfText () _ faz um pouco mais do que isso; ele cria propriedades de parágrafo (_pPr) que mantém o estilo a ser aplicado ao parágrafo.
Simplificando, os parágrafos declaram execuções separadas e cada execução contém alguns elementos de texto:
link:/wp-content/uploads/2017/10/p-r-t.png [imagem:/wp-content/uploads/2017/10/p-r-t.png [imagem, largura = 385, altura = 240]]
Para criar um documento bonito, precisamos ter controle total desses elementos _ (parágrafo, execução, _ e texto) .
Então, vamos descobrir como estilizar nosso conteúdo usando o objeto runProperties (RPr):
ObjectFactory factory = Context.getWmlObjectFactory();
P p = factory.createP();
R r = factory.createR();
Text t = factory.createText();
t.setValue("Welcome To Baeldung");
r.getContent().add(t);
p.getContent().add(r);
RPr rpr = factory.createRPr();
BooleanDefaultTrue b = new BooleanDefaultTrue();
rpr.setB(b);
rpr.setI(b);
rpr.setCaps(b);
Color green = factory.createColor();
green.setVal("green");
rpr.setColor(green);
r.setRPr(rpr);
mainDocumentPart.getContent().add(p);
File exportFile = new File("welcome.docx");
wordPackage.save(exportFile);
Aqui está a aparência do resultado:
link:/wp-content/uploads/2017/10/im2a.png [imagem:/wp-content/uploads/2017/10/im2a-300x236.png [imagem, largura = 461, altura = 363]]
Depois de criar um parágrafo, uma execução e um elemento de texto usando createP () _, _createR () _ e _createText () _ respectivamente, declaramos um novo objeto _runProperties (RPr) para adicionar um pouco de estilo ao elemento de texto .
O objeto rpr é usado para definir propriedades de formatação, Negrito (B), Itálico (I) e maiúsculo (Caps); essas propriedades são aplicadas ao texto executado usando o método _setRPr () _.
3.2 Trabalhando com imagens
O Docx4j oferece uma maneira fácil de adicionar imagens ao nosso documento do Word:
File image = new File("image.jpg" );
byte[] fileContent = Files.readAllBytes(image.toPath());
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage
.createImagePart(wordPackage, fileContent);
Inline inline = imagePart.createImageInline(
"Baeldung Image (filename hint)", "Alt Text", 1, 2, false);
P Imageparagraph = addImageToParagraph(inline);
mainDocumentPart.getContent().add(Imageparagraph);
E aqui está a aparência da implementação do método _addImageToParagraph () _:
private static P addImageToParagraph(Inline inline) {
ObjectFactory factory = new ObjectFactory();
P p = factory.createP();
R r = factory.createR();
p.getContent().add(r);
Drawing drawing = factory.createDrawing();
r.getContent().add(drawing);
drawing.getAnchorOrInline().add(inline);
return p;
}
Primeiro, criamos o arquivo que contém a imagem que queremos adicionar à parte principal do documento e, em seguida, vinculamos a matriz de bytes que representa a imagem ao objeto wordMLPackage.
Depois que a parte da imagem é criada, precisamos criar um objeto Inline usando o método createImageInline ().
O método addImageToParagraph () _ incorpora o objeto _Inline em um Drawing para que possa ser adicionado a um run.
Por fim, como um parágrafo de texto, o parágrafo que contém a imagem é adicionado ao mainDocumentPart.
E aqui está o documento resultante:
link:/wp-content/uploads/2017/10/im3a.png [imagem:/wp-content/uploads/2017/10/im3a-298x300.png [imagem, largura = 508, altura = 511]]
3.3 Criando tabelas
O Docx4j também facilita bastante a manipulação de Tabelas (Tbl), linhas (Tr) e colunas (Tc).
Vamos ver como criar uma tabela 3 × 3 e adicionar algum conteúdo a ela:
int writableWidthTwips = wordPackage.getDocumentModel()
.getSections().get(0).getPageDimensions().getWritableWidthTwips();
int columnNumber = 3;
Tbl tbl = TblFactory.createTable(3, 3, writableWidthTwips/columnNumber);
List<Object> rows = tbl.getContent();
for (Object row : rows) {
Tr tr = (Tr) row;
List<Object> cells = tr.getContent();
for(Object cell : cells) {
Tc td = (Tc) cell;
td.getContent().add(p);
}
}
Dadas algumas linhas e colunas, o método createTable () _ cria um novo objeto _Tbl, o terceiro argumento refere-se à largura da coluna em twips (que é uma medida de distância - 1/1440 de polegada).
Uma vez criado, podemos iterar sobre o conteúdo do objeto tbl e adicionar objetos Paragraph em cada célula.
Vamos ver como é o resultado final:
link:/wp-content/uploads/2017/10/im4a.png [imagem:/wp-content/uploads/2017/10/im4a-300x236.png [imagem, largura = 609, altura = 479]]
*4. Lendo um documento de arquivo Docx *
Agora que descobrimos como usar o docx4j para criar documentos, vamos ver como ler um arquivo docx existente e imprimir seu conteúdo:
File doc = new File("helloWorld.docx");
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
.load(doc);
MainDocumentPart mainDocumentPart = wordMLPackage
.getMainDocumentPart();
String textNodesXPath = "//w:t";
List<Object> textNodes= mainDocumentPart
.getJAXBNodesViaXPath(textNodesXPath, true);
for (Object obj : textNodes) {
Text text = (Text) ((JAXBElement) obj).getValue();
String textValue = text.getValue();
System.out.println(textValue);
}
Neste exemplo, criamos um objeto WordprocessingMLPackage com base em um arquivo helloWorld.docx existente, usando o método _load () _.
Depois disso, usamos uma expressão XPath (//w: t) para obter todos os nós de texto da parte principal do documento.
O método getJAXBNodesViaXPath () _ retorna uma lista de objetos _JAXBElement.
Como resultado, todos os elementos de texto dentro do objeto mainDocumentPart são impressos no console.
Observe que sempre podemos descompactar nossos arquivos docx para entender melhor a estrutura XML, o que ajuda na análise de problemas e fornece uma melhor compreensão de como enfrentá-los.
===* 5. Conclusão*
Neste artigo, descobrimos como o docx4j facilita a execução de operações complexas no documento MSWord, como a criação de parágrafos, tabelas, partes de documentos e adição de imagens.
Os trechos de código podem ser encontrados, como sempre, over no GitHub.