Solução de código aberto para automação de relatórios

Os desenvolvedores de sites e aplicativos móveis geralmente precisam controlar a preparação de páginas PDF para impressão ou enviá-las aos clientes por correio.

Os arquivos PDF têm controle total sobre a exibição de texto e gráficos na página. Infelizmente, as bibliotecas para gerar arquivos PDF preenchidos dinamicamente não estão incluídas nas ferramentas padrão de PHP, JS (Web), Java ou Swift (Android e iOS, respectivamente). Neste artigo, quero falar sobre a solução de código aberto para gerar arquivos PDF.



JasperReports é uma biblioteca Java de código aberto para gerar arquivos preenchidos dinamicamente. Possui muitas ferramentas para criar formulários de relatórios complexos, inclusive em formato PDF, mas também estão disponíveis outros formatos: RTF, DOCX, HTML, XLS, XLS, CSV e XML. Em outras palavras, basta desenvolver um formulário, criar um layout - e será possível exportá-lo para qualquer um dos formatos acima.

Também existem boas bibliotecas, como PDFLib (versão comercial) para PHP e sua versão de código aberto do PDFLib-Lite. É verdade que a biblioteca é bastante cara e a versão lite é distribuída apenas no código-fonte e, quando é instalada no ambiente de desenvolvimento, essa limitação pode se tornar um problema.

PDFbox é outra biblioteca Java de código aberto para trabalhar com documentos PDF. Permite criar novos documentos PDF, gerenciar documentos existentes com a capacidade de extrair conteúdo deles. Mas ele não possui uma interface do usuário (Interface do usuário), diferente do JasperReports.

Eu acho que o JasperReports é especialmente útil em grandes projetos relacionados a relatórios e não apenas em formato PDF. Ele tem tudo o que você precisa para implementá-lo em seu projeto: criação simples de formulários de relatórios complexos, interface do usuário para layout conveniente, aplicativo de servidor e integração simples com a frente.

No artigo, abordarei os seguintes tópicos:

  • Instale o ambiente de desenvolvimento e o aplicativo do servidor.
  • Crie um arquivo PDF preenchido automaticamente do banco de dados.
  • Integração do aplicativo de servidor ao front-end para obter o PDF criado.

Para começar a usar o JasperReports em seu projeto, você precisa fazer o download de dois aplicativos: JaspersoftStudio - a seguir, chamaremos de ambiente de trabalho - e JasperServer - chamaremos o aplicativo de servidor .

O JaspersoftStudio é um ambiente de desenvolvimento baseado em Eclipse com a biblioteca Java JasperReports integrada, na qual são desenvolvidos arquivos PDF dinâmicos ou estáticos: por exemplo, tickets, recibos, contratos, gráficos analíticos e outros.

JasperServer é um aplicativo de servidor no qual os arquivos são implantados e armazenados no JaspersoftStudio. Eles podem ser acessados ​​a partir de um aplicativo móvel ou da web. O JasperServer possui uma interface do usuário, com ela você pode visualizar relatórios, criar contas para diferentes usuários e dar-lhes acesso apropriado. Você também pode configurar a lista de endereçamento para e-mail (Agendador).

Configurar o ambiente de trabalho e o aplicativo do servidor


Você pode baixar e instalar aplicativos usando os links acima. Após a configuração de dois aplicativos, é necessário estabelecer uma conexão do ambiente de trabalho com o aplicativo do servidor.

Servidores → Criar conexão do servidor JasperReports → Especifique o nome, URL , nome de usuário e senha preferidos do servidor. Clique em Testar conexão para verificar se a conexão com o servidor está estabelecida. Se vir Bem - sucedido - vá mais longe.



Crie um PDF preenchido dinamicamente e publique-o


Instalamos o ambiente de desenvolvimento, o servidor e estabelecemos uma conexão entre eles. Agora, vamos criar um arquivo PDF primitivo que preenche dinamicamente, que quando é lançado (gerado) pega os dados do PostgreSQL e os instala em um aplicativo de servidor.

Primeiro, você deve prender a fonte de dados (no nosso caso, PostgreSQL) ao ambiente de trabalho, de onde o PDF coletará os dados. Então, vamos começar a desenvolver nosso primeiro arquivo PDF.

Adaptadores de Dados → Criar Adaptador de Dados → Conexão JDBS do Banco de Dados e especifique os dados da conexão:

  1. Driver JDBC - PostgreSQL (org.postgresql.Driver). Se não houver driver para o seu DBMS, você poderá instalar o driver necessário na guia Caminho da classe do driver.
  2. URL JDBC - consiste no nome do host, porta e banco de dados.
  3. Nome de usuário e senha - passe de log da sua conta DBMS.



Clicamos no botão Teste já familiar para nós e após uma conexão bem-sucedida (Bem-sucedida) com o banco de dados - Concluir .

Nesse banco de dados, o PDF será preenchido no ambiente de produção. Como planejamos implantar nosso primeiro arquivo PDF no servidor, vamos estragar a mesma fonte de dados no aplicativo do servidor:

Fontes de dados → Adicionar recurso → Fonte de dados e repita tudo do ponto acima.

Agora você está pronto para criar o PDF. As fontes no JasperReports são armazenadas no formato JRXML - este é XML com tags e atributos com fio com os quais a API JasperReports trabalha.

Clique em Arquivo → Novo → Relatório Jasper → Em branco A4 → Especifique o nome do arquivo JRXML → Concluir .



Depois de criar um novo projeto, você verá a seguinte imagem:



Sete blocos diferentes - cada bloco tem seu próprio comportamento diferente dos outros. Você pode ler mais sobre isso na documentação . Ao clicar em Fonte, você pode ver a estrutura desses blocos:

<?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="79" splitType="Stretch"/> </title> <pageHeader> <band height="35" splitType="Stretch"/> </pageHeader> <columnHeader> <band height="61" splitType="Stretch"/> </columnHeader> <detail> <band height="125" splitType="Stretch"/> </detail> <columnFooter> <band height="45" splitType="Stretch"/> </columnFooter> <pageFooter> <band height="54" splitType="Stretch"/> </pageFooter> <summary> <band height="42" splitType="Stretch"/> </summary> </jasperReport> 

Então, vamos remover cinco blocos extras e deixar apenas dois: Título e Detalhe. O botão Excluir (Windows) ou Backspace (OS X) nos ajudará com isso.

Agora adicione dois elementos. Você pode adicionar um novo elemento de duas maneiras: registre o contêiner na estrutura XML (botão Origem ) ou arraste o elemento desejado da janela superior da paleta direita - Texto estático, onde haverá nomes de campos e Campo de texto, dentro dos quais preencheremos os campos variáveis ​​extraídos do banco de dados:

 <?xml version="1.0" encoding="UTF-8"?> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Example" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="ae9517f6-ff0b-41bb-a8dc-82196190e940"> <queryString> <![CDATA[]]> </queryString> <background> <band splitType="Stretch"/> </background> <title> <band height="30" splitType="Stretch"> <staticText> <reportElement x="0" y="0" width="100" height="30" uuid="7b697ed9-f52a-483c-965e-f0b2dc6130c1"/> <text> <![CDATA[Static Text]]> </text> </staticText> </band> </title> <detail> <band height="169" splitType="Stretch"> <textField> <reportElement x="0" y="0" width="100" height="20" uuid="41002e0b-ddb2-4e4b-a049-10810ab51208"/> <textFieldExpression> <![CDATA["Text Field"]]> </textFieldExpression> </textField> </band> </detail> </jasperReport> 

A consulta no banco de dados pode ser gravada na tag queryString ou clique no botão de diálogo DataSet and Query editor . Depois disso, uma nova janela será aberta onde você precisará selecionar uma fonte de dados (1), escrever uma consulta (2) e declarar variáveis ​​de campo. O botão Ler campos (3) lerá todos os campos automaticamente, mediante solicitação válida . Para visualizar os dados, clique em Visualização de dados (4).



Ótimo! Temos quatro campos do tipo String, agora podemos realizar quase qualquer manipulação com eles. Por exemplo, simplesmente as listamos e escrevemos um pouco de lógica.

Imprimimos os nomes dos campos obrigatórios nos elementos de texto estático e os colocamos no contêiner de título. Indicaremos campos variáveis ​​nos elementos Campo de texto no contêiner Detalhe, pois eles se multiplicarão. Nosso PDF exibirá o nome, cidade e endereço de email. Para não ficar completamente entediado, vamos escrever uma lógica simples no elemento Campo de Texto, usando o quarto campo - o sexo do cliente, Sexo.

Fazemos o seguinte: se o cliente é uma mulher, a Sra. Será adicionada na frente do nome, se o homem for o Sr. Para fazer isso, use o operador ternário Java:

 <textFieldExpression> <![CDATA[$F{sex}.equals( "male" )?"Mr. "+$F{name}:"Mrs. "+$F{name}]]> </textFieldExpression> 

Ao clicar em Visualizar ao lado do botão Origem , você pode ver o resultado:



Como você pode ver na captura de tela, o PDF foi montado com êxito: pegou todos os valores e aplicou a lógica, colocando corretamente a Sra. e o Sr.

Também obteremos o parâmetro de entrada Cidade para que seja possível filtrar os dados por cidade. Isso pode ser feito clicando em Parâmetros → Criar parâmetro na janela Estrutura de tópicos ou adicionando uma nova marca de parâmetro com os atributos nome e classe :

 <parameter name="City" class="java.lang.String"/> 

Resta apenas adicionar o parâmetro à consulta SQL:

 SELECT Id, name, sex, city, email FROM users WHERE city = $P{City} 

Passamos o valor São Francisco para o parâmetro City (vou dizer no próximo parágrafo como fazer isso) e clique em Visualização de dados para visualizar o resultado.



O PDF foi coletado filtrando com sucesso os dados. Vamos mais longe

Como já temos um arquivo PDF preenchido dinamicamente, podemos carregá-lo no servidor para uma maior integração com nossos aplicativos front-end. Para fazer isso, clique no botão Publicar relatório no servidor JasperReports → clique duas vezes para abrir o servidor → Selecione a pasta do servidor para baixar o PDF (no nosso caso, relatórios ) → Avançar → Fonte de dados do repositório → selecione a fonte de dados criada anteriormente no aplicativo do servidor → Concluir .

Integração de front-end


A API JasperReports inclui sua própria implementação RESTful para interação cliente-servidor - REST v2 . Se não lhe convier, você pode usar um protocolo de acesso a objetos simples - SOAP .

Vamos considerar o REST v2.

Os quatro métodos principais para ações CRUD (Criar, Ler, Atualizar e Excluir) estão disponíveis: GET (get), POST (adicionar, alterar, excluir), PUT (adicionar, substituir), DELETE (excluir). Todas as informações detalhadas estão disponíveis na documentação nos links acima.

Vamos considerar o método GET mais comum e relevante para este artigo.

 http://<host>:<port>/jasperserver[pro]/rest_v2/reports/path/to/report.<format>?<arguments> 

Acima, há uma solicitação síncrona , com a qual você pode obter a saída do arquivo (PDF finalizado) em uma resposta de solicitação (você pode encontrar a chamada assíncrona aqui ).

Eu acho que tudo está claro com o host e a porta, e / reports / path / to / report é o URI do arquivo que está sendo chamado. Como implantamos a origem do arquivo PDF (Example.jrxml) na pasta do servidor de relatórios, a versão completa do URI será: / reports / reports / Example.

formato é um formato (no nosso caso, PDF).
argumentos são parâmetros.

Acima, adicionamos o parâmetro City e o transmitiremos na solicitação com o valor San Francisco para filtrar os dados dessa cidade.

Se a chamada não for de uma zona autorizada, você precisará adicionar mais dois parâmetros / atributos: j_username e j_password (passe de log para autorização). Por padrão, o nome de usuário e a senha no servidor são jasperadmin .

Assim, obtemos o seguinte URL:

 http://localhost:8080/jasperserver/rest_v2/reports/reports/Example.PDF?city=San Francisco&j_username=jasperadmin&j_password=jasperadmin 

Então, temos um PDF já gerado. Por exemplo, quando você chama esse URL pela barra de endereços do navegador, o arquivo deve ser baixado automaticamente.

Pode ser necessário exibir uma imagem em PDF. Por exemplo, se o cliente apenas deseja visualizar o arquivo, você pode mostrar o documento no formato PNG, se desejar fazer o download, e em PDF.

Usando Java como exemplo, usando a biblioteca PDFbox, veremos como você pode gerar e selecionar um arquivo PDF de um aplicativo externo e depois convertê-lo em PNG.

Abaixo está a classe PullPDF com um método que usa uma URL como argumento.

 import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.util.Base64; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.PDFRenderer; import org.apache.pdfbox.tools.imageio.ImageIOUtil; public class PullPDF { public String ConvertPDF2PNG(String valuefromParam) throws IOException { BufferedInputStream input_file = new BufferedInputStream(new URL(valuefromParam).openStream()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { PDDocument document = PDDocument.load(input_file); PDFRenderer pdfRenderer = new PDFRenderer(document); for (int page = 0; page < document.getNumberOfPages(); ++page) { BufferedImage bim = pdfRenderer.renderImageWithDPI(page, 300, ImageType.RGB); ImageIOUtil.writeImage(bim, "png", baos); baos.flush(); byte[] encodedBytes = Base64.getEncoder().encode(baos.toByteArray()); valuefromParam = new String(encodedBytes); } } catch (Exception e) { } return valuefromParam; } } 

Você pode obter o mesmo resultado usando, por exemplo, o Spring Framework. Mas tentei mostrar uma maneira universal que pode ser aplicada no Android e na Web ao trabalhar com Java.

Conclusão


Se você deseja automatizar a geração de uma verificação simples para uma loja online e tem tempo limitado para criá-la, recomendamos o uso das ferramentas nativas do seu projeto ou da estrutura familiar. Como o tempo gasto na instalação do JasperReports, a familiarização com a documentação para o desenvolvimento de formulários de relatório mais complexos pode não ser justificada. Em outros casos, o JasperReports é uma boa solução de código aberto para automação de relatórios.

Source: https://habr.com/ru/post/pt461719/


All Articles