Esse artigo faz parte da revista Clube Delphi Edição 102. Clique aqui para ler todos os artigos desta edição

imagem

PHP

Relatórios no PHP com arquivos PDF

Aprenda a gerar arquivos PDF no PHP para emissão de relatórios

 

Neste artigo veremos

·         Como utilizar a classe FPDF para criar arquivos PDF;

·         Como gerar relatórios em PDF para Web Sites PHP.

Qual a finalidade?

·         Implementar uma solução para relatórios, em formato profissional, no PHP.

Quais situações utilizam esses recursos?

·         Desenvolvimento de sistemas e sites com PHP onde se necessita de relatórios para obter-se informações.

 

Resumo do DevMan

Todos nós sabemos que grande parte dos sistemas de como um todo acabam não tenho tanta utilidade quando não há relatórios. É assim com aplicações Win32, mais cedo ou mais tarde o cliente pede para desenvolver algum tipo de relatório, tais como: comissão de vendas, vendas no mês, controle de estoque, gráfico de vendas, fluxo de caixa etc.

É possível desenvolver relatórios em Delphi for Win32 numa facilidade incrível, já que temos diversos editores de relatórios para todo gosto e bolso.

Na web não é diferente, os relatórios serão solicitados e teremos que estar preparados para desenvolver a solução para o cliente. A diferença maior entre aplicações Win32 e Web é que em Web a gama de opções para o desenvolvimento é bastante pequena. Por isso, nesse artigo quero mostrar uma boa solução para desenvolver relatórios na Web utilizando a biblioteca FPDF que é específica para programação PHP.

 

Quem tem uma aplicação WEB sabe que haverá solicitação de relatórios que deverão ter uma aparência profissional, que não percam a formatação de uma impressora para outra e, o mais importante, possam ser salvos para arquivo ou enviados via e-mail.

O formato ideal para relatórios na Web atualmente é o PDF, pois além de imprimir nas mais variadas impressoras sem perder formatação, podemos guardar os arquivos e enviá-los por e-mail ou qualquer outra mídia.

Portanto, nesse artigo criaremos arquivos PDF utilizando a biblioteca PDFLib do PHP. Vamos aprender na prática!

 

Preparando a utilização

Como o FPDF é uma classe, basta fazer o download do mesmo e colocar em um diretório dentro da sua aplicação. Para baixar acesse o site www.fpdf.org e o link Downloads. Escolha a versão mais atual até o fechamento dessa edição. Depois de fazer o download descompacte o arquivo. Como resultado, tem-se o arquivo da classe (fpdf.php) que deverá ser copiada para o diretório da sua aplicação, bem como a pasta font que contém as fontes TrueType que poderão ser utilizadas.

Os demais arquivos são a documentação, um tutorial e informações. No site também existe um tutorial traduzido para o português do Brasil que pode ser baixado.

FPDF é liberado sob uma licença permissiva: não há qualquer restrição de utilização. Você pode inserí-lo livremente na sua aplicação (comercial ou não), com ou sem modificações.

 

Conhecendo alguns recursos disponíveis

Para geração de arquivos PDF, a FPDF oferece suporte para inserir imagens nos formatos JPEG, PNG e GIF. Para a edição do texto, qualquer fonte TrueType pode ser utilizada, desde que seja distribuída juntamente com a aplicação, podendo-se também definir a cor das fontes. Quanto à formatação do texto, é possível criar cabeçalhos e rodapés, criar links hipertexto, sendo também possível a quebra automática de linhas e páginas. Além de também definir as medidas das margens.

 

Nota: Para inserir no relatórios imagens do tipo Gif, será necessário ter carregada no PHP a biblioteca GD. Em instalações do Delphi for PHP essa biblioteca já vem carregada. Se não seu caso, verifique o arquivo PHP.ini.

 

E o melhor de tudo é que o arquivo PDF resultante estará devidamente compactado, o que torna sua exibição mais rápida, em um tempo aceitável para aplicações Web.

 

Construindo os primeiros relatórios

Vamos iniciar nosso primeiro teste criando uma aplicação bastante conhecida de todos, a famosa e tradicional mensagem: Ola Mundo! Abra seu editor preferido e digite o código da Listagem 1. Minha preferência é pelo Delphi For PHP, para agilizar a execução dos testes e ter a possibilidade de debug do código PHP, mas sinta-se a vontade para utilizar seu software de preferência, como o Bloco de Notas do Windows, por exemplo.

 

Listagem 1. Relatório Olá Mundo!

<?php

  define('FPDF_FONTPATH','C:/CD/PDF/fpdf16/font/');

  require('fpdf16/fpdf.php');

  $pdf=new FPDF();

  $pdf->AddPage();

  $pdf->SetFont('Arial','B',50);

  $pdf->Cell(40,10,'Olá Mundo!');

  $pdf->Output();

?>

 

A primeira linha de comando no código da Listagem 1 serve para definir o valor de uma constante, utilizada pela classe para saber o diretório onde estão as fontes Perceba que no meu caso apontei para C:/CD/PDF/fpdf16/font/ , ou seja, local. Obviamente quando distribuir essa aplicação terei que modificar o caminho para que se adapte as urls de meu sistema on-line. Mais abaixo vemos uma chamada ao método SetFont, que serve para escolher a fonte, sua formatação e tamanho. O comando require do PHP inclui o arquivo passado como parâmetro no script atual, exigindo sua existência. Essa inclusão é necessária para adicionar o código da classe FPDF ao nosso script PHP.

Para iniciar a criação de um relatório declara-se uma variável que irá receber um objeto da classe FPDF. Esse objeto representa o arquivo PDF que vamos criar. E ele adicionamos uma página através do método AddPage e, para escrever utiliza-se o método Cell que tem como parâmetro os tamanhos width, heigth e o texto a ser impresso.

O Cell na verdade define uma célula com largura (width) e altura (heigth) onde pode-se, inclusive, centralizar ou alinhar o texto na direita e na esquerda. Para exibir o relatório criado, utiliza-se o método Output que faz uma saída redirecionando a página para um arquivo PDF que deverá ser carregado no browser.

Agora vamos evoluir um pouco o relatório codificando conforme a Listagem 2, onde acrescentamos alguns parâmetros nos métodos.

 

Listagem 2. Relatório com várias linhas seguidas

<?php

  define('FPDF_FONTPATH','C:/CD/PDF/fpdf16/font/');

  require('fpdf16/fpdf.php');

  $pdf=new FPDF('P','mm','A4');

  $pdf->AddPage();

  $pdf->SetFont('Arial','',10);

  $pdf->Cell(190,4,'Olá Mundo!',1,1);

  $pdf->Cell(190,4,'Proxima Linha 1',1,1);

  $pdf->Cell(190,4,'Proxima Linha 2',1,1,'C');

  $pdf->Cell(190,4,'Proxima Linha 3 - Texto que será alinhado à direita',1,1,'R');

  $pdf->Output();

?>

 

Na Listagem 2 criamos o relatório e já configuramos a orientação e formato da folha. Isso é feito na linha

 

$pdf=new FPDF('P','mm','A4');

 

O primeiro parâmetro (P) está definindo a orientação Portrait (retrato). Se você deseja fazer um relatório no formato horizontal, defina o parâmetro como (L) que significa Landscape (paisagem). Também pode-se definir a unidade de medida do relatório, esse é o segundo parâmetro. No caso, foi definido em milímetros (mm), mas pode-se utilizar: (cm) centímetros, (pt) pontos e (in) polegadas. Essa definição de unidade de medida será aplicada no documento todo e será utilizada para qualquer posicionamento dentro do mesmo. Por isso é muito importante definir a unidade padrão antes de organizar os relatórios, pois mudar depois poderá desorganizar completamente a formatação. Finalizando os parâmetros do relatório pode-se definir o formato da folha e os valores que podem ser utilizados são: A3, A4, A5, Letter e Legal. Lembrando que no Brasil o formato padrão é o A4.

O método AddPage também possui o parâmetro de orientação e formato da página, o que possibilita que você tenha páginas diferenciadas dentro do mesmo relatório.

Para definir a fonte, utilizou-se o método SetFont com o parâmetro de fonte como Arial. O parâmetro seguinte está em branco, ou seja, sem nenhuma formatação original, lembrando que é possível formatar como negrito (B), itálico (I) e sublinhado (U). Inclusive pode-se formatar a fonte com todas as opções passando no segundo parâmetro BIU. No final do SetFont tem-se o tamanho da fonte, em pontos, que, se não for informado será 12 (doze). Ao definir um SetFont, essa definição valerá para todo o relatório até que exista outra definição, ou seja, outro SetFont.

Nas linhas que chamam o método Cell na Listagem 2, definiu-se a largura (width) em 190, sendo que uma folha do tipo A4 tem 210 mm, deixando 20 mm de margem, ou seja, 2 centímetros. Como altura utilizou-se a medida de 4 mm o que é suficiente para um texto com fonte Arial tamanho 10. Ainda no método Cell, após o texto que deverá ser escrito colocou-se no próximo parâmetro o número ‘1’ que significa que uma borda será aplicada em toda a célula, o que é bem interessante em relatórios que precisam de linhas a cada registro. Depois da borda, tem-se mais um parâmetro com ‘1’ para definir uma quebra de linha após o texto. Com isso a próxima chamada ao método Cell estará posicionado na linha seguinte.

Na chamada escreve o texto Próxima Linha 2 tem-se, como último parâmetro a letra C que define que o texto deve ser centralizado dentro da célula, levando em conta seu tamanho (largura). Pode-se ainda definir a posição do texto com R (direita) e L (esquerda), como demonstra-se na última chamada ao método Cell que alinha o texto na margem direita. Colocando esse script para executar tem-se como resultado o exibido na Figura 1.

 

imagem

Figura 1. Relatório criado através do script da Listagem 2

 

Adicionando cabeçalho e rodapé ao relatório

A classe FPDF possui dois métodos que não foram implementados, deixando essa possibilidade de extensão dos mesmos. Esses métodos são o Header (cabeçalho) e o Footer (rodapé). Portanto, para criar um cabeçalho e rodapé faze-se uma extensão da classe definindo esses dois métodos. É importante salientar a necessidade de utilizar o $this para chamar os métodos da própria classe. Veja na Listagem 3 um relatório com cabeçalho e rodapé, bem como recursos de imagem e contador de páginas.

 

Listagem 3. Relatório com cabeçalho e rodapé

<?php

  define('FPDF_FONTPATH','C:/CD/PDF/fpdf16/font/');

  require('fpdf16/fpdf.php');

 

class RELATORIO extends FPDF{

  function Header(){

    $this->Image('logo_CD.gif',10,8);

    $this->SetFont('Arial','B',15);

    $this->Cell(80);

    $this->Cell(100,10,'Relatório de Demonstração do FPDF',0,0,'C');

    $this->Ln(20);

  }

  function Footer(){

    $this->SetY(-15);

    $this->SetFont('Arial','I',8);

    $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');

  }

}

$pdf=new RELATORIO();

$pdf->AliasNbPages();

$pdf->AddPage();

$pdf->SetFont('Times','',12);

for($i=1;$i<=40;$i++)

  $pdf->Cell(0,10,'Texto da linha número '.$i,0,1);

$pdf->Output();

?>

 

No código da Listagem 3 estende-se (herança) a classe FPDF criando a classe Relatorio. Com essa extensão podemos definir os métodos Header e Footer.

No Header, invocamos o método Image para adicionar uma imagem contida no mesmo diretório do script PHP, que será iniciada na posição horizontal 10 e vertical 8. Tem-se a opção ainda de passar mais um parâmetro, o tamanho que a imagem deve ter de largura, assim ela será redimensionada proporcionalmente. No caso da Listagem 3 não declarou-se o tamanho da imagem e a mesma será exibida no tamanho original. Na seqüência tem-se uma chamada ao Cell passando como parâmetro 80 (oitenta), com o objetivo de criar uma célula de espaço entre a figura e o título do relatório que é impresso através da próxima chamada. No final do Header tem-se uma chamada ao método Ln que cria uma linha em branco com uma quebra, onde seu parâmetro é a altura que se não for informada será a mesma altura da última chamada ao Cell.

No Footer vemos uma chamada a SetY que serve para posicionar a escrita em relação vertical. O valor negativo refere-se à base do relatório, ou seja, tem-se 15 mm de baixo para cima. Depois imprime-se o número da página atual, através do método PageNo, bem como a quantidade de páginas através do alias {nb} que é resultado da função AliasNbPages. Assim fecha-se a extensão da classe FPDF.

Continuando, tem-se a criação do relatório que agora é uma variável do tipo Relatorio que é a classe estendida e que contém o cabeçalho e rodapé. Faz-se necessário chamar o método AliasNbPages para definir o alias que conterá o número final de páginas do relatório. Define-se uma fonte do tipo Times e tem-se um looping para imprimir o mesmo texto várias vezes, ocasionando quebras de páginas. Na Figura 2 apresenta-se o resultado do relatório da Listagem 3.

 

imagem

Figura 2. Relatório com cabeçalho e rodapé

 

Colorindo o relatório

Para se ter uma idéia do quão interessante é a classe FPDF, temos um recurso interessante. Mesmo o relatório sendo PDF é interessante utilizar cores para destacar informações importantes e que devem ser rapidamente identificadas. A classe possui isso e veremos que é bem fácil colorir um relatório. Indo direto ao ponto tem-se na Listagem 4 a criação de um relatório com cores.

 

Listagem 4. Relatório com cores

<?php

define('FPDF_FONTPATH','C:/CD/PDF/fpdf16/font/');

require('fpdf16/fpdf.php');

$pdf=new FPDF();

$texto='Teste com Cores';

$pdf->SetFont('Arial','',14);

$pdf->AddPage();

$w=$pdf->GetStringWidth($texto)+6;

$pdf->SetX((210-$w)/2);

$pdf->SetDrawColor(0,80,180);

$pdf->SetFillColor(230,230,0);

$pdf->SetTextColor(220,50,50);

$pdf->SetLineWidth(1);

$pdf->Cell($w,9,$texto,1,1,'C',true);

$pdf->Ln(10);

$pdf->Output();

?>

 

Na Listagem 4, criamos uma caixa personalizada e nela escrevemos um texto. Utilizamos o método GetStringWidth para descobrir o tamanho que o texto contido na variável terá no relatório, levando em conta a unidade de media do mesmo. A esse resultado soma-se mais 6 (seis) para ter um tamanho ideal da caixa que será criada. Utilizou-se o método SetX para posicionar o texto em relação horizontal, fazendo uma conta para posicionar o resultado bem ao centro. Essa conta é simples, pegou-se o tamanho do relatório (210), diminuiu-se o tamanho do texto ($w) e dividiu-se por dois (2).

O SetDrawColor é utilizado para defini a cor das linhas (bordas) que compõem a célula, utilizando como parâmetro o padrão de cores RGB (Red, Green, Blue), onde define-se a quantidade de vermelho (0 a 255), a quantidade de verde (0 a 255) e a quantidade de azul (0 a 255). Para mudar a cor interna da célula utiliza-se o SetFillColor que também utiliza o padrão RGB, bem como o método SetTextColor que define a cor do texto propriamente. Ainda pode-se definir o tamanho da linha da célula através do método SetLineWidth.

 

Nota do DevMan

No padrão RGB todas as cores são formadas por misturas de vermelho, verde e azul, sendo assim cada cor possui uma representação numérica que informa a quantidade de cada mistura. Por exemplo, a cor branca é representada como RGB(1,1,1). Para obter esses valores você pode utilizar programas de edição gráfica, como o Photoshop.

 

Listando dados no formato de tabelas

Até agora, vimos como fazer a impressão de relatórios simples, sem acesso a dados. Agora vamos à parte que mais interessa: uma listagem de dados. Com tudo que já foi escrito nesse artigo fica fácil pensar e fazer uma listagem que coloca, no formato de tabela, o resultado de uma consulta ao banco de dados. Mas, para facilitar vamos ver um exemplo na Listagem 5, que busca dados de uma tabela de Clientes em um banco MySQL.

 

Listagem 5. Listagem de dados em formato de tabela

<?php

  define('FPDF_FONTPATH','C:/CD/PDF/fpdf16/font/');

  require('fpdf16/fpdf.php');

  $MYSQL = mysql_pconnect("localhost","root","root");

  mysql_select_db('direto',$MYSQL);

  $SQL = "select * from clientes order by nome";

  $MResultado = mysql_query($SQL, $MYSQL);

  class RELATORIO extends FPDF{

    function Header(){

      $this->Image('logo_CD.gif',10,8);

      $this->SetFont('Arial','B',15);

      $this->Cell(80);

      $this->Cell(100,10,'Listagem de Clientes',0,0,'C');

      $this->Ln(20);

    }

    function Footer(){

      $this->SetY(-15);

      $this->SetFont('Arial','I',8);

      $this->Cell(0,10,'Página '.$this->PageNo().'/{nb}',0,0,'C');

    }

  }

$pdf=new RELATORIO();

$pdf->AliasNbPages();

$pdf->AddPage();

$pdf->SetFont('Times','B',12);

//Colunas

$pdf->Cell(20,4,'Código',1,0,'C');

$pdf->Cell(60,4,'Nome',1,0,'C');

$pdf->Cell(30,4,'D.Nasc',1,0,'C');

$pdf->Cell(30,4,'Fone',1,0,'C');

$pdf->Cell(50,4,'E-mail',1,1,'C');

$pdf->SetFont('Times','',12);

//Registros

while ($MColuna = mysql_fetch_assoc($MResultado)){

  $pdf->Cell(20,4,$MColuna["id"],1,0,'C');

  $pdf->Cell(60,4,$MColuna["nome"],1,0);

  $pdf->Cell(30,4,$MColuna["datanasc"],1,0,'C');

  $pdf->Cell(30,4,$MColuna["fone"],1,0,'C');

  $pdf->Cell(50,4,$MColuna["email"],1,1);

}

mysql_free_result($MResultado);

$pdf->Output();

?>

 

Na Listagem 5, tem-se uma consulta ao banco de dados MySQL, em uma tabela de clientes. Montou-se o relatório com cabeçalho e rodapé, como visto anteriormente. Na questão da tabela criaram-se os títulos da coluna de forma centralizada e definindo um tamanho. Na última coluna (E-mail) colocou-se 1 no parâmetro que quebra a linha para que o registro seja iniciado abaixo dos títulos.

Com o while criou-se um loop até o final de registros da consulta imprimindo os campos com as mesmas definições da coluna. Perceba que algumas colunas estão centralizadas e outras não. Na Figura 3 vemos o relatório finalizado.

 

imagem

Figura 3. Relatório com dados no formato de tabela

 

Conhecendo todas as possibilidades da classe FPDF

Bem, até agora viu-se os principais métodos da classe FPDF que, ao meu ver, são suficientes para criar a maioria dos relatórios. Mas ainda existe mais, veja a Tabela 1 todos os métodos e a descrição das suas funcionalidades.

 

Método

Descrição

AcceptPageBreak

Orienta sobre aceitação ou não de quebra de página automática

AddFont

Possibilita a adição de nova fonte ao relatório

AddLink

Cria um link externo (http)

AddPage

Adiciona uma nova página ao relatório

AliasNbPages

Cria um apelido para variável que controla o número de páginas do relatório

Cell

Formata e imprime uma célula

Close

Fecha (termina) o relatório

Error

Cria um exceção do tipo fatal que aborta a execução do código restante

Footer

Método do rodapé que pode ser estendido na classe filha

FPDF

Nome da classe construtora (pai)

GetStringWidth

Retorna o tamanho do texto levando em conta a unidade de medida

GetX

Retorna a posição horizontal atual do cursor (relatório)

GetY

Retorna a posição vertical atual do cursor (relatório)

Header

Método do cabeçalho que pode ser estendido na classe filha

Image

Imprime uma imagem do tipo PNG, GIF e JPG

Line

Cria uma linha

Link

Insere um link criado pelo método AddLink

Ln

Força uma quebra de linha

MultiCell

Formata e imprime uma célula com várias linhas fazendo quebra automática

Output

Salva e/ou retorna o relatório. Em outras palavras apresenta o mesmo no browser

PageNo

Retorna o número da página

Rect

Cria um retângulo (desenho)

SetAuthor

Define o autor do documento

SetAutoPageBreak

Define o modo de quebra automática

SetCompression

Define se existe ou não compressão do relatório

SetCreator

Define o criador do documento

SetDisplayMode

Define o modo de visualização

SetDrawColor

Define a cor das linhas

SetFillColor

Define a cor de fundo (preenchimento)

SetFont

Define a fonte para escrita

SetFontSize

Define o tamanho da fonte

SetKeywords

Associa palavras chaves ao documento (utilizado para buscas)

SetLeftMargin

Define a margem esquerda do relatório

SetLineWidth

Define a largura da linha

SetLink

Define o destino de um link interno

SetMargins

Define as margens do relatório

SetRightMargin

Define a margem direita do relatório

SetSubject

Define o assunto do documento

SetTextColor

Define a cor do texto que será escrito

SetTitle

Define o título do documento

SetTopMargin

Define a margem superior do relatório

SetX

Seta a posição horizontal para a próxima escrita

SetXY

Seta a posição horizontal e vertical para a próxima escrita

SetY

Seta a posição vertical para a próxima escrita

Text

Imprime um texto (escreve)

Write

Imprime o texto na seqüência

Tabela 1. Métodos disponíveis na classe FPDF

 

Conclusão

Nesse artigo apresentou-se a classe FPDF que possibilita, facilmente, criar relatórios no formato PDF para apresentação na WEB. Você pode aprender mais sobre essa classe vendo os tutoriais disponíveis no site do projeto: www.fpdf.org. Agora temos uma boa forma de criar relatórios no PHP sendo com Delphi For PHP ou não. Coloque a mão na massa e crie vários relatórios em seus sistemas.