Clique aqui para ler todos os artigos desta edição
Criando documentos PDF - intermediário
Diversos recursos são encontrados no mercado para se criar arquivos do tipo PDF, alguns são pagos e outros livres com propaganda. Porém, há uma dúvida de como essas três letrinhas tão famosas funcionam. Elas são famosas pela grande aplicação no mercado, seja relatórios, contratos, manuais, formulários e diversos outros tipos de documentos no formato PDF que transitam pela Internet e até mesmo em disquetes.
Mais do que entender esse formato, esse artigo mostra como criar uma classe para gerar esses arquivos facilmente. A utilidade dessa proposta é inestimável, pois conhecimentos para gerar relatórios em PDF coloridos e com imagens serão adquiridos.
Entendendo o formato PDF
Antes de estudarmos esse formato precisamos entender a diferença entre arquivo e documento. O arquivo PDF é um conjunto de bits. Então, podemos dizer que um arquivo PDF é um arquivo que vemos como qualquer um outro no Windows. Já o Documento é a parte lógica contida no arquivo, é a interpretação dos conjuntos de bits que levarão ao resultado final esperado.
A estrutura de um arquivo PDF pode ser basicamente definida por, Cabeçalho, Corpo, Tabela Cross-Reference e Trailer como mostrado na Figura 1. O cabeçalho (Header) é a primeira linha do arquivo e indica a versão em que estamos trabalhando, por exemplo: %PDF-1.1. O Corpo (Body) consiste em uma seqüência indireta de objetos que são os elementos do Documento, sendo imagens, fontes, textos e outros que definem a forma visual do documento. A Tabela Cross-Reference contém informações que permitirá o acesso randômico dos objetos indiretos do Corpo. Na tabela, cada objeto é especificado linha a linha e é indicado sua posição dentro do arquivo, de acordo com a quantidade de bytes desde o inicio do arquivo. O Trailer ajuda as aplicações encontrarem rapidamente a Tabela Cross-Reference e o objeto Catalog, que é o objeto pai ou root. As aplicações iniciam a leitura do arquivo a partir do final e na última linha do arquivo contém uma marcação indicando o final do arquivo, exemplo: %%EOF
Figura 1. Estrutura básica de um Arquivo PDF
O documento PDF tem uma hierarquia própria, é referenciado de um objeto indireto a outro, ou de um conteúdo de objeto a um outro objeto indireto. Para ficar simples de entender a hierarquia e a formação do documento observe a Figura 2. Apenas os itens com fundo verde serão abordados neste artigo.
Figura 2. Hierarquia do Documento PDF
Os objetos são formados por: um número identificador, propriedades e conteúdo. São delimitados por “obj” e “endobj” As propriedades por “<<” e “>>” e os conteúdos, não muito diferente quanto a forma, são delimitados por “stream” e ”endstream”. Veja um exemplo de um objeto indireto, repare na sua identificação “7 0”:
7 0 obj<< /Length 0 >>
stream
endstream
endobj
Os objetos indiretos ainda podem ser identificados por um nome ou apelido (faremos isso nas imagens e fontes), mas isso não exclui a necessidade de um identificador numérico. Todos os objetos que formam o documento não precisam estar em ordem, mas precisam ser referenciados corretamente, principalmente quando se trata de sua hierarquia.
Criando a Classe
Agora que conhecemos um pouco do formato PDF vamos iniciar nosso trabalho. Crie um novo projeto do tipo Class Library, sugerimos o nome “GeradorPDF”. Adicione os namespaces e crie as variáveis como mostrada na Listagem 1.
Listagem 1. Início da Classe
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
namespace GeradorPDF
{
public class PDF: IDisposable
{
private int iPGX = 595; //Largura da Página do padrão A4
private int iPGY = 841; //Altura da Página do Padrão A4
private string sAutor; // Autor do documento
private string sTitulo;// Título do documento
private string XREF = ""; //Armazena a criação da Tabela Cross-Reference
private List<string> ConteudoPagina = new List<string>();//Armazenará o conteúdo de cada página do documento
private List<byte[]> XObjetos = new List<byte[]>();//Onde serão armazenadas as imagens JPG.
private StringBuilder sbAPDF = new StringBuilder();//Para gerar o documento
public const byte FTimes = 1;
public const byte FHelvetia = 5;
public const byte FCourier = 9;
public const byte FSymbol = 13;
public const byte FZapfDingbats = 14;
public const byte SNormal = 0;
public const byte SNegrito = 1;
public const byte SItalico = 2;
...