32
- Notícias - Artigos - Curso - Dicas - FAQ - Links - Livros Relatório A impressão de relatórios é uma necessidade na maioria dos sistemas. Quem tem Delphi tem tudo para imprimir relatórios. O Delphi vem com dois mecanismos básicos para gerar relatórios: (1) Quick Report e (2) TPrinter. Além disso existem muitos geradores de relatórios de terceiros que podem ser adquiridos à parte, tais como Report Builder e ReportSmith. O TPrinter permite manipular diretamente a impressora. Cada texto impresso é posicionado na página através de um sistema de coordenadas calculadas em pixels. Isso é tão difícil quanto parece. É melhor pular esse método. No Quick Report o relatório é desenhado em um ambiente visual como se fosse um Form. Esse método é bem mais fácil. Vamos a ele. Quick Report Desenhar um relatório com o Quick Report é assim: Você cria um novo Form e nesse Form em branco você desenha o relatório usando os componentes próprios do Quick Report (esses componentes estão na aba QReport da palheta de componetes). Para fazer o programa imprimir o relatório ou mostrar uma prévia do relatório em vídeo, você deve incluir uma opção de impressão – no menu ou botão - em um Form que seja visível ao usuário (pode ser o Form principal do sistema). O Form do relatório em Quick Report não fica visível ao usuário. Imagine um projeto Project1 que tem um Form chamado Form1. Para fazer um relatório, crie um outro Form chamado Form2. Desenhe seu relatório no Form2. Coloque um botão ou coisa parecida no Form1. Defina uma procedure para responder ao evento do botão. Nessa procedure mande imprimir o relatório do Form2. Não esqueça de declarar o Form2 na cláusula uses do Form1. A unit do Form1 vai ficar assim: . . . unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2;

Quick Report

  • Upload
    alexvrd

  • View
    315

  • Download
    8

Embed Size (px)

Citation preview

Page 1: Quick Report

- Notícias - Artigos - Curso - Dicas - FAQ - Links - Livros

RelatórioA impressão de relatórios é uma necessidade na maioria dos sistemas. Quem tem Delphi tem tudo para imprimir relatórios.

O Delphi vem com dois mecanismos básicos para gerar relatórios: (1) Quick Report e (2) TPrinter. Além disso existem muitos geradores de relatórios de terceiros que podem ser adquiridos à parte, tais como Report Builder e ReportSmith.

O TPrinter permite manipular diretamente a impressora. Cada texto impresso é posicionado na página através de um sistema de coordenadas calculadas em pixels. Isso é tão difícil quanto parece. É melhor pular esse método.

No Quick Report o relatório é desenhado em um ambiente visual como se fosse um Form. Esse método é bem mais fácil. Vamos a ele.

Quick ReportDesenhar um relatório com o Quick Report é assim: Você cria um novo Form e nesse Form em branco você desenha o relatório usando os componentes próprios do Quick Report (esses componentes estão na aba QReport da palheta de componetes).

Para fazer o programa imprimir o relatório ou mostrar uma prévia do relatório em vídeo, você deve incluir uma opção de impressão – no menu ou botão - em um Form que seja visível ao usuário (pode ser o Form principal do sistema). O Form do relatório em Quick Report não fica visível ao usuário.

Imagine um projeto Project1 que tem um Form chamado Form1. Para fazer um relatório, crie um outro Form chamado Form2. Desenhe seu relatório no Form2. Coloque um botão ou coisa parecida no Form1. Defina uma procedure para responder ao evento do botão. Nessa procedure mande imprimir o relatório do Form2. Não esqueça de declarar o Form2 na cláusula uses do Form1.

A unit do Form1 vai ficar assim:

. . .unit Unit1;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2;. . .procedure TForm1.Button1Click(Sender: TObject);begin Form2.QuickRep1.Preview;end;. . .

Note a declaração da Unit2 (a unit do Form2) na cláusula uses do Form1.

Note também a procedure Button1Click, que responde ao evento OnClick do botão Button1. QuickRep1 é o nome do relatório que está no Form2. O método preview do QuickRep1 mostra uma prévia do relatório em vídeo. Para fazer o programa mandar o relatório diretamente para a impressora é só substituir o método preview pelo método print.

Desenhando o relatório

Page 2: Quick Report

Vamos retomar o projeto Pcliente e fazer um relatório de clientes. O relatório vai conter nome, contato, telefone e limite de crédito.

Componente QuickRepO componente QuickRep é a base para a construção do relatório. É dentro do QuickRep que o relatório vai ser desenhado.

Abra o projeto Pcliente.dpr Crie um Form novo: clique na opção do menu do Delphi "File --> New Form" ou clique no botão New Form da barra de ferramentas. Mude a propriedade Name do Form para frmRelatorio. Salve o Form com o nome Urelat.pas Coloque um componente QuickRep no Form novo. O QuickRep está na aba QReport da palheta de componentes. BandsAs bands do QuickRep dividem o relatório em faixas de acordo com a função. Existe uma faixa para o cabeçalho, outra para o rodapé, outra para a linha de detalhe, etc.

Dê um duplo clique na propriedade Bands do QuickRep Vão aparecer as opções HasColumnHeader, HasDetail, HasPageFooter, HasPageHeader, HasSummary e HasTitle.

Opções da propriedade Bands Função HasTitle Põe uma faixa (band) para edição do título do relatório. Título é aquela parte do relatório que só aparece no topo da primeira página, depois do cabeçalho.Coloque False. HasPageHeader Põe uma faixa para edição do cabeçalho. O cabeçalho aparece no topo de cada página do relatório.Coloque True. HasDetail Põe uma faixa para edição de linha de detalhe. A linha de detalhe aparece uma vez para cada registro da tabela.Coloque True. HasColumnHeader Põe uma faixa para edição do cabeçalho de coluna. Essa faixa aparece entre o cabeçalho e a linha de detalhe.Coloque True. HasPageFooter Põe uma faixa para edição do rodapé. Essa faixa aparece no fim de cada página.Coloque True. HasSummary Põe uma faixa para edição do sumário. Essa faixa aparece no fim da última página do relatório, antes do rodapé.Coloque True.

Tabela 29: QuickRep - Bands - Opções

Veja como ficou:

Figura 34: Componente QuickRep

DataSet

Page 3: Quick Report

A próxima propriedade do QuickRep é a DataSet. Essa propriedade aponta para a fonte dos dados que serão impressos. A fonte dos dados, neste caso, vai ser a tabela Cliente.

Coloque um componente Table no Form Mude as propriedades do Table para acessar a tabela Cliente Propriedade do Table Valor Active True DatabaseName MEUALIAS IndexName idxNOME Name tblCliente TableName Cliente.db

Tabela 30: Propriedades do componente Table para o relatório

Selecione o componente QuickRep Mude a propriedade DataSet para tblCliente Outras Propriedades do QuickRepPropriedade Função Name Nome do componente.Mude para relCliente ReportTitle É o nome que vai aparecer na fila de impressão do Windows ou da rede.Mude para Relatório de Clientes Options Estas opções permitem impedir que o cabeçalho apareça na primeira página ou que o rodapé apareça na última. Isso é útil se você quiser que o título ou a faixa de fim de relatório apareçam isolados, sem cabeçalho ou rodapé.No projeto atual deixe como está. Page Define o formato da página. Altura, largura, margens, orientação (retrato ou paisagem), etc.

Tabela 31: Propriedades do componente QuickRep

CabeçalhoVamos desenhar o cabeçalho na faixa PageHeader.

Selecione a faixa PageHeader Clique e arraste a âncora inferior da faixa para aumentar o tamanho. Âncoras são aqueles pontos pretos que aparecem em volta do componente selecionado. Coloque um componente QRLabel na faixa PageHeader. Note que os componentes não podem ser movidos de uma faixa para outra. Centralize o componente QRLabel mudando a propriedade Alignment para taCenter e a propriedade AlignToBand para True. Mude a propriedade Caption para "Relatório de Clientes" (sem as aspas). Mude a opção Size da propriedade Font para 20 Se você quiser pode incluir uma imagem (um logotipo, por exemplo).

Coloque um componente QRImage na faixa PageHeader. Clique na propriedade Picture Clique no botão das reticências Escolha uma imagem com o Picture Editor

Figura 35: Cabeçalho

Cabeçalho de Coluna

Page 4: Quick Report

Vamos desenhar o cabeçalho de coluna na faixa ColumnHeader.

Coloque 4 componentes QRLabel na faixa ColumnHeader (um para cada coluna do relatório). Altere as propriedades Caption para Nome, Contato, Telefone e Limite de Crédito. Altere o Style das propriedades Font para Underline e Italic. Só para enfeitar um pouco vamos colocar uma linha separando o cabeçalho das linhas de detalhe.

Coloque um componente QRShape na faixa ColumnHeader Mude a opção Width da propriedade Pen para 4. Isso vai engrossar a linha. Mude a propriedade Shape para qrsHorLine. O componente QRShape tem várias formas pré-definidas. qrsHorLine é a linha horizontal. Estique a linha por toda extensão do relatório usando as âncoras.

Figura 36: Cabeçalho de Coluna

Linha de DetalheVamos desenhar a linha de detalhe na faixa Detail.

Coloque 4 componentes QRDBText na faixa Detail (um para cada coluna do relatório). Faça com que eles fiquem grudados na parte superior da faixa. Reduza a altura da faixa até não sobrar espaço entre os componentes e o fim da faixa. Se sobrar algum espaço, as linhas de detalhe vão aparecer afastadas. Mude a propriedade DataSet de cada componente QRDBText para tblCliente. Isso vai indicar a fonte dos dados. Mude as propriedades DataField para os respectivos campos de cada coluna do relatório. Na última coluna (Limite de Crédito) mude a propriedade Alignment para taRightJustify. Tradicionalmente os números são alinhados à direita. Na última coluna mude a propriedade AutoSize para False. Quando AutoSize é igual a True o campo é esticado ou encolhido para caber o texto valor a ser impresso. O problema é que o AutoSize estica o campo fixando a posição da borda esquerda, o que acaba desalinhando os campos alinhados à direita. Coloque a máscara de edição ###,##0.00 na propriedade Mask.

Figura 37: Linha de Detalhe

SumárioVamos desenhar o sumário do relatório na faixa Summary. Vamos colocar nessa faixa um totalizador para imprimir o somatório dos limites de crédito.

Coloque na faixa Summary um componente QRExpression. Esse componente é um curinga que pode imprimir um valor constante, um campo da tabela ou um valor calculado. Mude as propriedades Alignment para taRightJustify e AutoSize para False. Clique na propriedade Expression. Essa é a propriedade que contém a fórmula a ser calculada. Digite a fórmula SUM(tblCliente.VALOR_CREDITO).

Para ver outras fórmulas clique no botão das reticências ao lado da propriedade Expression. Isso vai abrir o Expression Wizard que vai ajudar a criar outras fórmulas.

Mude o Style da propriedade Font para Bold. Coloque a máscara de edição ###,##0.00 na propriedade Mask. Mude a propriedade Master para relCliente.

Page 5: Quick Report

Toda fórmula que contém funções agregadoras (somatório, média, mínima, máxima, etc.) precisa de um Master. Esse Master indica quando calcular (o que entra ou não no cálculo). O relCliente em Master indica que toda vez que uma linha de detalhe for impressa, essa linha vai ser totalizada.

Coloque um QRLabel ao lado do QRExpr Mude o Caption para Total: Mude o Style da propriedade Font para Bold

Figura 38: Sumário

RodapéVamos desenhar o rodapé do relatório na faixa PageFooter.

Coloque um componente QRSysData na faixa PageFooter à esquerda. Esse componente é usado para imprimir informações do sistema, tais como data, hora e número da página. Mude a propriedade Data para qrsDate (data corrente). Coloque outro componente QRSysData na faixa PageFooter à direita.. Mude a propriedade Data para qrsPageNumber (número da página). Coloque um componente QRLabel próximo ao número da página. Mude a propriedade Caption para Página: Mude o Size da propriedade Font de todos os componentes do rodapé para 8 Para dar um toque final coloque mais uma linha separando o rodapé das linhas de detalhe, do mesmo jeito que foi feito no cabeçalho das colunas.

Figura 39: Rodapé

Imprimindo com Quick ReportAgora que o relatório está desenhado, vamos colocar a opção de impressão no Form principal.

Abra o Form frmCliente

Inclua a Unit do relatório – Urelat – na cláusula uses Inclua um botão na barra de ferramentas do Form. Se você esqueceu como fazer, veja o tópico Barra de Ferramentas em Componentes visuais. Coloque uma figura de impressora no botão. Veja o tópico Lista de Imagens no Componentes visuais. Inclua uma opção Imprimir no menu. Veja o tópico Menu em Componentes visuais. Inclua uma procedure para tratar o evento OnClick da opção Imprimir do menu. Associe o evento OnClick do botão Imprimir à mesma procedure. A procedure deve ficar assim:

unit Ucliente;interfaceuses Windows, . . ., DBTables, Urelat;. . .procedure TfrmCliente.Imprimir1Click(Sender: TObject);begin frmRelatorio.relCliente.Preview;end;. . .

Page 6: Quick Report

Observações:

A unit do relatório (Urelat) é declarada na cláusula Uses. frmRelatorio é o nome do Form do relatório. relCliente é o nome do componente QuickRep no Form frmRelatorio. Preview é o comando que mostra o relatório no vídeo. Se quiser imprimir diretamente na impressora é só substituir o comando Preview pelo Print. Quando executar o programa você vai ver o relatório no vídeo assim:

Figura 40: Preview do Relatório

Próximo passo: Arquivos seqüenciais

Faça de www.marcosferreira.eti.br a sua home page! Copyright © 2001 Marcos dos Santos Ferreira Outorga-se a permissão de copiar, distribuir e/ou modificar este documento sob os termos da Licença de Documentação Livre GNU Versão 1.1 ou qualquer outra versão posterior publicada pela Free Software Foundation; sem Seções Invariantes; sem textos da Página de Rosto e sem textos da Contracapa. Uma cópia da licença é incluída na seção intitulada "GNU Free Documentation License".

- Notícias - Artigos - Curso - Dicas - FAQ - Links - Livros

Arquivos sequenciaisEstá certo. Com Delphi você tem todos os principais bancos de dados do mundo à sua disposição. Então porque você iria querer manipular arquivos sequenciais ? Arquivos são como BomBril: Têm mil e uma utilidades.

Por exemplo: Os arquivos podem ser acessados por virtualmente todas as linguagens de programação. Por esse motivo os arquivos costumam ser usados como interface entre aplicativos diferentes. De que outra forma, um aplicativo de Contabilidade escrito em Cobol poderia importar dados de um aplicativo de Contas a Receber escrito em Delphi ?

Neste capítulo você vai aprender a manipular arquivos: ler, gravar, renomear, excluir, etc.

Funções BásicasO Delphi vem com um conjunto de funções de manipulação de arquivos.

Renomeando um ArquivoA função RenameFile renomeia um arquivo, retornando True se o arquivo foi renomeado.

. . .

Page 7: Quick Report

if RenameFile(‘ARQUIVO.OLD’, ‘ARQUIVO.NEW’) then ShowMessage(‘Arquivo renomeado.’)else ShowMessage(‘Erro ao renomear arquivo’);. . .

No exemplo, o arquivo "Arquivo.old" vai mudar de nome para "Arquivo.new".

Quando o PATH não é informado, o arquivo deve estar no diretório corrente.

Atenção: Quando é informado o PATH do nome antigo mas não é informado o PATH do nome novo, a função RenameFile MOVE o arquivo para o diretório corrente.

. . .RenameFile(‘C:\Windows\ARQUIVO.OLD’, ‘ARQUIVO.NEW’);. . .

No exemplo, o arquivo chamado "C:\Windows\Arquivo.old" vai mudar de nome para "Arquivo.new" e vai mudar para o diretório corrente (que pode até ser ou não o próprio C:\Windows)

Excluindo um ArquivoA função DeleteFile exclui um arquivo, retornando True se o arquivo foi excluído.

. . .if DeleteFile(‘ARQUIVO.OLD’) then ShowMessage(‘Arquivo excluído.’)else ShowMessage(‘Erro ao excluir arquivo’);. . .

No exemplo, o arquivo "Arquivo.old" vai ser excluído.

Quando o PATH não é informado, a função procura o arquivo no diretório corrente.

Copiando um ArquivoO Delphi não tem nenhuma função para copiar arquivos mas você pode usar a função do próprio Windows.

. . .if CopyFile(‘ARQUIVO.OLD’, ‘ARQUIVO.NEW’, True) then ShowMessage(‘Arquivo copiado.’)else ShowMessage(‘Erro ao copiar arquivo’);. . .

No exemplo, o arquivo "Arquivo.old" vai ser copiado para "Arquivo.new".

Quando o PATH do arquivo original não é informado, a função procura o arquivo no diretório corrente.

Quando o PATH do arquivo de destino não é informado, a função grava o arquivo no diretório corrente.

O terceiro parâmetro é do tipo booleano (True ou False) e indica o que fazer caso o arquivo de destino já exista. Quando True e o arquivo de destino já existe, a função aborta a cópia. Quando False e o arquivo de destino já existe, a função grava por cima.

Atenção: A função CopyFile não aceita variáveis do tipo string como parâmetros dos nomes dos arquivos. Aceita somente variáveis do tipo Pchar. Quando necessário, faça o typecast.

Page 8: Quick Report

. . .var strTmpArqOrig, strTmpArqDest: string;. . .if CopyFile(Pchar(strTmpArqOrig), Pchar(strTmpArqDest), True)then ShowMessage(‘Arquivo copiado.’)else ShowMessage(‘Erro ao copiar arquivo’);. . .

Observe que as variáveis strTmpArqOrig e strTmpArqDest são do tipo string. Se não fosse feito o typecast Pchar(strVariavelString) o compilador acusaria erro de incompatibilidade entre tipo de dado string e Pchar.

Testando se um Arquivo ExisteA função FileExists testa se um arquivo existe e retorna True se encontrou.

. . .if FileExists(‘C:\ARQUIVO.TXT’) then ShowMessage(‘Arquivo existe.’)else ShowMessage(‘Arquivo não existe.’);. . .

Lendo e Gravando ArquivosLer e gravar arquivos em Delphi é uma tarefa fácil. Para quem já conhece alguma versão anterior do Pascal é mais fácil ainda porque não mudou praticamente nada.

Gravando um Arquivo NovoObserve o exemplo abaixo. Neste exemplo estamos criando um arquivo novo (chamado ARQUIVO.NEW) e gravando quatro registros com a mensagem "Hello World !".

. . .var tfArquivo: TextFile; strRegistro: string; x: integer;begin strRegistro := ‘Hello World !’; AssignFile(tfArquivo, ‘c:\Windows\Temp\Arquivo.new’); Rewrite(tfArquivo); for x := 0 to 3 do Writeln(tfArquivo, strTmpRegistro + ‘(‘ + IntToStr(x) + ‘)’); CloseFile(tfArquivo);end;. . .

Primeiro, é preciso declarar uma variável do tipo arquivo. No exemplo, a variável tfArquivo é do tipo TextFile (um arquivo texto).

Depois usa-se o comando AssignFile para associar um arquivo (no exemplo, "c:\Windows\Temp\Arquivo.new") à variável declarada. A partir deste ponto, a variável tfArquivo representará o arquivo associado a ela. Usar uma variável não associada a algum arquivo gera erro de I/O em tempo de execução.

Page 9: Quick Report

O comando Rewrite regrava o arquivo. Em outras palavras, se o arquivo já existe, o Rewrite apaga e cria um novo arquivo vazio.

Para gravar o conteúdo do arquivo, usa-se o comando Write ou Writeln. Os dois comandos gravam um string no arquivo. A diferença é que o Writeln grava no final do string uma marca de LF/CR (Line Feed/Carriage Return). Esta marca indica o fim do registro ou o fim de uma linha.

Para encerrar a gravação, deve-se fechar o arquivo com o comando CloseFile.

Gravando um Arquivo Já ExistenteEm muitas situações precisamos adicionar novas informações a um arquivo já existente. No exemplo abaixo estamos incluindo mais registros ao arquivo criado anteriormente.

. . .var tfArquivo: TextFile; strRegistro: string; x: integer;begin strRegistro := ‘Olá Mundo !’; AssignFile(tfArquivo, ‘c:\Windows\Temp\Arquivo.new’); Append(tfArquivo); for x := 0 to 3 do Writeln(tfArquivo, strTmpRegistro + ‘(‘ + IntToStr(x) + ‘)’); CloseFile(tfArquivo);end;. . .

A única diferença entre este e o exemplo anterior está na substituição do comando Rewrite pelo comando Append. Enquanto o Rewrite cria um arquivo novo, o Append abre o arquivo e se prepara para gravar novos registros no fim do arquivo. Se o arquivo não existir, ocorre um erro com a mensagem "File not found" em tempo de execução.

Lendo um ArquivoVamos agora ler o arquivo que foi gravado nos passos anteriores.

. . .var tfArquivo: TextFile; strRegistro: string;begin AssignFile(tfArquivo, ‘c:\Windows\Temp\Arquivo.new’); Reset(tfArquivo); Readln(tfArquivo, strTmpRegistro); while not Eof(tfArquivo) do begin ShowMessage(strTmpRegistro); Readln(tfArquivo, strTmpRegistro); end; CloseFile(tfArquivo);end;. . .

Com o comando Reset o arquivo fica aberto para leitura.

O comando Readln lê um registro.

Page 10: Quick Report

A função EOF (sigla de End Of File, fim de arquivo em ingl&ecircs) retorna True quando o arquivo chegou ao fim.

Gerando Um Arquivo HTMLCom essa tecnologia tão simples e antiga, é possível gerar páginas para internet com dados extraídos de qualquer banco de dados. Pode até não ser o método mais fácil, mas está ao alcance de qualquer um com poucos conhecimentos de HTML.

Vamos usar a conhecida tabela CLIENTE.DB para gerar uma página HTML com nome, telefone e contato de cada cliente.

. . .var tfArquivo: TextFile; strRegistro: string; tblCliente: TTable;begin tblCliente := TTable.Create(nil); tblCliente.DatabaseName := 'MEUALIAS'; tblCliente.TableName := 'CLIENTE.DB';

AssignFile(tfArquivo, 'C:\Windows\Temp\CLIENTE.html'); Rewrite(tfArquivo);

strRegistro := '<html><head> <title> Relação de Clientes </title> </head>'; Writeln(tfArquivo, strRegistro);

strRegistro := '<body><p align="center"> <font face="Arial"color="#FF0000">'; Writeln(tfArquivo, strRegistro);

strRegistro := '<big><big><big><big>Relação de Clientes </big></big></big></big>'; Writeln(tfArquivo, strRegistro);

strRegistro := '</font></p>'; Writeln(tfArquivo, strRegistro);

strRegistro := '<table border="1" width="100%">'; Writeln(tfArquivo, strRegistro);

strRegistro := ' <tr>'; Writeln(tfArquivo, strRegistro); strRegistro := ' <td width="33%"><big>Nome</big></td>'; Writeln(tfArquivo, strRegistro);

strRegistro := ' <td width="33%"><big>Telefone</big></td>'; Writeln(tfArquivo, strRegistro);

strRegistro := ' <td width="34%"><big>Contato</big></td>'; Writeln(tfArquivo, strRegistro);

Page 11: Quick Report

strRegistro := ' </tr>'; Writeln(tfArquivo, strRegistro); tblCliente.Open; while not tblCliente.EOF do begin strRegistro := ' <tr>'; Writeln(tfArquivo, strRegistro); strRegistro := ' <td width="33%"><font color="#400040"><small><font face="Arial">' + tblCliente.FieldByName('NOME').Value + '</font></small></font></td>'; Writeln(tfArquivo, strRegistro);

strRegistro := ' <td width="33%"><font color="#400040"><small><font face="Arial">' + tblCliente.FieldByName('TELEFONE').Value + '</font></small></font></td>'; Writeln(tfArquivo, strRegistro); strRegistro := ' <td width="34%"><font color="#400040"><small><font face="Arial">' + tblCliente.FieldByName('CONTATO').Value + '</font></small></font></td>'; Writeln(tfArquivo, strRegistro);

strRegistro := ' </tr>';

Writeln(tfArquivo, strRegistro);

tblCliente.Next; end;

tblCliente.Close;

strRegistro := '</table>'; Writeln(tfArquivo, strRegistro); strRegistro := '<p>Documento gerado em ' + DateToStr(now) + '</body></html>'; Writeln(tfArquivo, strRegistro); CloseFile(tfArquivo);end;. . .

Os comandos de gravação de arquivos são idênticos aos já estudados nos exemplos anteriores. Os comandos de leitura de tabelas do banco de dados também já são conhecidos.

Veja abaixo uma lista como os comandos HTML mais importantes usados neste exemplo. (Uma explicação detalhada dos comandos HTML estão além do escopo deste curso).

Comando Descrição <HTML> Início do arquivo HTML <HEAD> Área de cabeçalho da página <TITLE> Título da página que aparece na barra superior do browser.

Page 12: Quick Report

<BODY> Corpo da página, que aparece na área de visualização do browser. <TABLE> Declaração de tabela, semelhante às tabelas usadas no MS-Word. Não tem nada em comum com tabelas de bancos de dados. <BORDER> Declara o formato da borda da tabela. <WIDTH> Indica a largura da tabela ou da coluna da tabela, de acordo com o escopo. <TR> Declara uma linha da tabela. <TD> Declara uma coluna da tabela.

Tabela 32: Comandos HTML

Este código vai gerar um arquivo CLIENTE.HTML que poderá ser aberto em um browser. Experimente.

Próximo passo: Arquivos INI

Faça de www.marcosferreira.eti.br a sua home page! Copyright © 2001 Marcos dos Santos Ferreira Outorga-se a permissão de copiar, distribuir e/ou modificar este documento sob os termos da Licença de Documentação Livre GNU Versão 1.1 ou qualquer outra versão posterior publicada pela Free Software Foundation; sem Seções Invariantes; sem textos da Página de Rosto e sem textos da Contracapa. Uma cópia da licença é incluída na seção intitulada "GNU Free Documentation License".

- Notícias - Artigos - Curso - Dicas - FAQ - Links - Livros

Arquivos INIArquivos INI são arquivos de configuração. São chamados assim porque têm a extensão *.ini. Cada programa pode ter um ou mais arquivos INI que por sua vez podem conter uma infinidade de parâmetros.

Esses arquivos foram muito usados no tempo do Windows 3.x. A partir do Windows 95 foi introduzido o Registry, um novo conceito em termos de configuração.

Com o advento do Registry, os arquivos INI deveriam ter sido aposentados, mas não foi isso o que aconteceu. Existem programas que foram escritos no tempo do Windows 3.x e que usam arquivos INI até hoje.

Se você vai criar um programa novo, use o Registry, mas se você precisa fazer manutenção em programas antigos, é bom saber como usar os arquivos INI.

Vamos ver neste capítulo como criar configurações usando arquivos INI.

Estrutura do Arquivo INIOs arquivos INI são divididos em seções. Cada seção é dividida em chaves. Cada chave é um parâmetro que possui um valor.

. . .[windows]load=

Page 13: Quick Report

run=NullPort=Nonedevice=Epson Stylus COLOR 500,EPS500,LPT1:

[Desktop]Wallpaper=(None)TileWallpaper=0WallpaperStyle=0Pattern=(None). . .

O exemplo acima é um trecho do arquivo WIN.INI que está no diretório do Windows.

As seções são declaradas entre colchetes (observe as seções [WINDOWS] e [DESKTOP]).

As chaves ficam dentro de uma seção (na seção Desktop as chaves são Wallpaper, TileWallpaper, WallpaperStyle e Pattern)

Cada chave possui um valor (por exemplo, TileWallpaper=0).

Classe TIniFileO Delphi tem uma classe chamada TiniFile, declarada na unit IniFiles, que faz manipulação de arquivos INI.

Criando um Arquivo INIUm arquivo INI não precisa ser criado. Ao inserir o valor em uma chave, o arquivo será criado automaticamente (se ainda não existir).

Criando uma SeçãoDa mesma forma que o arquivo, uma seção não precisa ser explicitamente criada. Ao inserir o valor em uma chave, a seção da chave será criada automaticamente (se ainda não existir).

Gravando uma ChaveA classe TIniFile tem vários métodos para gravar chaves, um para cada tipo de dado.

O mesmo método pode ser usado para criar uma chave nova ou alterar o valor de uma chave já existente.

. . .var iniMeuArquivo: TIniFile;begin iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI'); iniMeuArquivo.WriteString('MINHA SECAO', 'MINHA CHAVE', Edit1.Text); iniMeuArquivo.Free;end;. . .

O método Create não cria o arquivo MEUINI.INI. Este método é o construtor da classe e apenas instancia a classe. Este método recebe como parâmetro o nome do arquivo INI com o qual se quer trabalhar.

O método WriteString grava Edit1.Text como valor na chave "Minha chave" da seção "Minha seção".

O método WriteString cria tudo o que for necessário para guardar o valor da chave. Se o arquivo não existe, cria o arquivo. Se a seção não existe, cria a seção. Se a chave não existe, cria a chave.

Atenção: Não esqueça de declarar a unit IniFiles na cláusula uses.

Page 14: Quick Report

Métodos para gravar chaves com outros tipos de dados são: WriteBool (booleano), WriteInteger (número inteiro), WriteFloat (ponto flutuante), WriteTime (hora), WriteDate (data), WriteDateTime (data e hora).

A única diferença entre esses métodos é o tipo de dado do terceiro parâmetro (o valor da chave), que muda de acordo com o método.

Lendo uma ChaveTal qual a gravação, a classe TIniFile também tem diversos métodos para ler chaves, um para cada tipo de dado.

. . .var iniMeuArquivo: TIniFile;begin iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI'); Label1.Caption := iniMeuArquivo.ReadString('MINHA SECAO', 'MINHA CHAVE', '{sem valor}'); iniMeuArquivo.Free;end;. . .

O método ReadString lê o valor na chave "Minha chave" da seção "Minha seção".

Caso a chave "Minha chave" ou a seção "Minha seção" não existam, o método ReadString retornará o valor default, declarado como terceiro parâmetro. No exemplo o valor default é "{sem valor}".

Métodos para ler chaves com outros tipos de dados são: ReadBool (booleano), ReadInteger (número inteiro), ReadFloat (ponto flutuante), ReadTime (hora), ReadDate (data), ReadDateTime (data e hora).

A única diferença entre esses métodos é o tipo de dado do terceiro parâmetro (o valor default), que muda de acordo com o método.

Apagando uma ChaveÀs vezes é necessário apagar uma chave. Para isso, use o método DeleteKey.

. . .var iniMeuArquivo: TIniFile;begin iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI'); iniMeuArquivo.DeleteKey('MINHA SECAO', 'MINHA CHAVE'); iniMeuArquivo.Free;end;. . .

Apagando uma SeçãoPara apagar a seção inteira, inclusive as chaves dentro dela, use o método EraseSection.

. . .var iniMeuArquivo: TIniFile;begin iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI'); iniMeuArquivo.EraseSection('MINHA SECAO'); iniMeuArquivo.Free;end;. . .

Page 15: Quick Report

O método EraseSection não apaga o arquivo INI, mesmo que a última seção tenha sido excluída.

Próximo passo: Imprimindo com TPrinter

Faça de www.marcosferreira.eti.br a sua home page! Copyright © 2001 Marcos dos Santos Ferreira Outorga-se a permissão de copiar, distribuir e/ou modificar este documento sob os termos da Licença de Documentação Livre GNU Versão 1.1 ou qualquer outra versão posterior publicada pela Free Software Foundation; sem Seções Invariantes; sem textos da Página de Rosto e sem textos da Contracapa. Uma cópia da licença é incluída na seção intitulada "GNU Free Documentation License".

- Notícias - Artigos - Curso - Dicas - FAQ - Links - Livros

Imprimindo com TPrinterExistem dúzias de geradores de relatórios mais ou menos integrados ao Delphi. O próprio Quick Report, o ReportBuilder, o ReportSmith, etc. Teoricamente você jamais teria que se preocupar com os aspectos de baixo nível da impressão, certo ? Errado.

O Quick Report é muito bom mas não é mágico; tem as suas limitações. Outros geradores de relatórios são muito caros ou muito lentos e também não são perfeitos.

Quando não dá para usar um gerador de relatórios, o jeito é fazer impressão direta.

Classe TPrinterA classe TPrinter encapsula a interface do Windows com a impressora. Possui propriedades e métodos para impressão.

PropriedadesPropriedade Descrição Canvas Representa a superfície da página. Possui métodos para escrever texto e desenhar figuras geométricas. (Veja o tópico Classe TCanvas abaixo). Fonts Lista com os nomes das fontes suportadas pela impressora selecionada. Tipo de dado: TString. Orientation Determina em que sentido será impressa a página: poLandscape imprime na horizontal e poPortrait imprime na vertical. PageHeight Altura da página em número de pixels. PageNumber Número da página corrente que está sendo impressa. É atualizado automaticamente. PageWidth Largura da página em número de pixels. PrinterIndex Seleciona em qual impressora o relatório será impresso. Este índice refere-se à propriedade Printers (abaixo). Para selecionar a impressora padrão do sistema atribua o valor –1 ao PrinterIndex. Printers Lista com todas as impressoras instaladas no Windows. A impressora selecionada é indicada pela propriedade PrinterIndex. Tipo de dado: TString. Title É o nome do relatório que vai aparecer no gerenciador de impressão. Tipo de dado: String

Tabela 33: Propriedades da classe TPrinter

Page 16: Quick Report

MétodosPropriedade Descrição Abort Cancela a impressão de um relatório. BeginDoc Inicia a impressão de um relatório. Tem que ser executado antes de começar a imprimir qualquer coisa. EndDoc Encerra a impressão de um relatório. Tem que ser executado ao fim da impressão. NewPage Muda de página e incrementa a propriedade PageNumber.

Tabela 34: Métodos da classe TPrinter

Classe TCanvasLembra do famoso "Plano Cartesiano" ? Aquele das coordenadas x e y ? Pois é. Agora você vai ver a utilidade prática dessa coisa.

A classe TCanvas é um Plano Cartesiano. É com a classe TCanvas que o programa vai mandar para a impressora textos, figuras geométricas e imagens.

A posição dos textos e figuras na página do relatório é determinada pelo sistema de pares ordenados (x, y). As coordenadas são medidas em pixels. O topo da página, por exemplo, está nas coordenadas (0, 0).

PropriedadesPropriedade Descrição Brush Configura o "pincel" usado para pintar o fundo das figuras geométricas: Cor e estilo. Tipo de dado: TBrush. Font Configura a fonte usada para imprimir o texto: Nome da fonte, cor, tamanho, estilo, etc. (Não confunda com a propriedade Fonts do TPrinter.) Tipo de dado: TFont. Pen Configura a "caneta" usada para desenhar linhas soltas e as linhas que delimitam a parte externa de figuras: Cor, largura, estilo, etc. Tipo de dado: TPen. PenPos Indica a posição corrente da caneta, onde o próximo texto ou figura será impresso. Tipo de dado: TPoint.

Tabela 35: Propriedades da classe TCanvas

MétodosPropriedade Descrição Rectangle Desenha um retângulo preenchendo-o com o padrão definido na propriedade Brush. LineTo Desenha uma linha entre o ponto determinado por PenPos e o ponto passado como parâmetro. Geralmente é usado em conjunto com MoveTo. MoveTo Muda a posição corrente (PenPos) para o ponto passado como parâmetro. TextOut Imprime um string na posição passada como parâmetro.

Tabela 36: Métodos da classe TCanvas

Praticando a Impressão com TPrinterVamos imprimir um relatório usando a impressão com TPrinter. Vai ser um relatório simples, do tipo que qualquer gerador de relatórios pode fazer.

A impressão direta já é, por si só, uma coisa um pouco complicada. A idéia é simplificar o exemplo para não complicar a explicação, certo ?

Definição do Relatório: Imprimir o cadastro de clientes usando a tabela CLIENTE.DB.

Vamos começar ...

Page 17: Quick Report

Seção Interface

Crie um projeto novo.

Na cláusula uses declare a unit Printers.

Coloque no Form um botão.

Coloque no Form um componente TTable.

Na propriedade DatabaseName coloque o alias MEUALIAS.

Na propriedade TableName coloque a tabela CLIENTE.DB.

Declare todos os fields da tabela (Clique com o botão direito do mouse sobre o TTable; selecione "Fields Editor" no menu pop-up; clique com o botão direito do mouse na janela "Form1.Table1"; clique na opção "Add Fields" do menu pop-up; selecione todos os campos na lista "Available Fields" e clique no botão OK.).

Na parte private do Form, declare a variável intPrivLinhaPixel, os procedimentos AbrirRelatorio, ImprimirCabecalho, ImprimirDetalhe, ImprimirRodape, FecharRelatorio e a função Fator. (A finalidade de cada declaração será vista mais tarde.)

unit Unit1;interfaceuses . . ., Printers;

type TForm1 = class(TForm) Button1: TButton; Table1: TTable; Table1CODIGO: TintegerField; Table1CGC: TStringField; Table1NOME: TStringField; Table1CONTATO: TStringField; Table1TELEFONE: TStringField; Table1VALOR_CREDITO: TFloatField; Table1LOGRADOURO: TstringField; Table1COMPLEMENTO: TstringField; Table1CIDADE: TStringField; Table1ESTADO: TStringField; Table1CEP: TStringField; Table1STATUS: TStringField; Table1LUXO: TBooleanField; Table1PECHINCHA: TbooleanField; Table1UTIL: TBooleanField;var private intPrivLinhaPixel: integer;

Page 18: Quick Report

procedure AbrirRelatorio; procedure ImprimirCabecalho; procedure ImprimirDetalhe; procedure ImprimirRodape; procedure FecharRelatorio; function Fator(intParmOperando: integer): integer;. . .

Evento OnClickCrie um procedimento para responder ao evento OnClick do botão. O procedimento deve conter o seguinte código: . . .procedure TForm1.Button1Click(Sender: TObject);begin AbrirRelatorio; ImprimirCabecalho;

Table1.Open; while not Table1.EOF do begin

if intPrivLinhaPixel > 3400 then begin ImprimirRodape; Printer.NewPage; ImprimirCabecalho; end;

ImprimirDetalhe;

Table1.Next; end;

ImprimirRodape; FecharRelatorio;end;. . .

Este procedimento lê cada linha da tabela e imprime o relatório.

É necessário um procedimento para abrir e outro para fechar o relatório (que serão explicados abaixo).

A variável intPrivLinhaPixel guarda o número em pixels da próxima linha a ser impressa. Quando esse número ultrapassa 3400 está na hora de mudar de página.

Entre o rodapé de uma página e o cabeçalho de outra, há o comando "Printer.NewPage". Esse comando faz a impressora mudar de página.

Pergunta: De onde surgiu esse Printer ?

Resposta: Printer é uma instância da classe TPrinter. Você não precisa declarar e nem instanciar a classe TPrinter. O próprio Delphi faz isso automaticamente quando encontra a unit Printers declarada na cláusula uses.

Procedimento AbrirRelatorio

Page 19: Quick Report

O procedimento deve conter o seguinte código:

. . .procedure TForm1.AbrirRelatorio;begin Printer.Title := 'Relatório de Clientes'; Printer.PrinterIndex := -1; Printer.Orientation := poPortrait;

Printer.BeginDoc;

Printer.Canvas.Font.Name := 'Courier New'; Printer.Canvas.Font.Size := Fator(8); Printer.Canvas.Font.Style := []; Printer.Canvas.Font.Color := clBlack;

intPrivLinhaPixel := 0;end;. . .

Printer.Title é o título que vai aparecer no Gerenciador de Impressão.

Atribuir –1 ao Printer.PrinterIndex faz com que a impressora default do sistema seja selecionada.

Atribuir poPortrait ao Printer.Orientation faz imprimir o relatório na posição vertical. Para imprimir na horizontal, atribua o valor poLandscape.

O comando Printer.BeginDoc inicia a impressão.

As características da fonte a ser usada (nome, estilo, tamanho e cor) são atribuídas ao Printer.Canvas.Font

O estilo da fonte pode ser qualquer combinação entre os valores: fsItalic, fsBold, fsUnderline. Por exemplo, para que a fonte fique em negrito e sublinhada, atribua [fsBold, fsUnderline] ao Printer.Canvas.Font.Style.

Existem várias cores pré-declaradas, como por exemplo: clBlue, clRed, clGray, clGreen, etc. Para uma relação completa, consulte o tipo de dado TColor na documentação do Delphi.

Procedimento FecharRelatorioO procedimento deve conter o seguinte código:

. . .procedure TForm1.FecharRelatorio;begin Printer.EndDoc;end;. . .

O relatório fica retido na fila da impressora até que seja liberado. O comando que libera o relatório da fila é o Printer.EndDoc.

Para abortar o relatório, use o comando Printer.Abort.

Função FatorVocê já sabe que para localizar um ponto sobre a "superfície" do papel, precisa-se de um par ordenado (x, y), onde x e y representam a coluna e a linha.

Page 20: Quick Report

A unidade de medida usada pela classe TCanvas é o pixel. O problema é que cada modelo de impressora tem uma resolução diferente do outro. E daí ? Daí que o ponto (x1, y1) em um modelo de impressora não fica no mesmo lugar que em outro.

Em outras palavras, quando o relatório é impresso em uma impressora com resolução diferente daquela na qual o programa foi desenvolvido, o relatório sai torto, desproporcional, às vezes pequeno demais, outras vezes tão grande que ultrapassa os limites da folha de papel.

Para minimizar esse problema, todas as coordenadas, tamanhos, e comprimentos devem ser calculados proporcionalmente em função da resolução da impressora.

O problema é: "Se um ponto fica na coluna 100 na impressora que tem 2.880 pixels de largura, em que coluna esse ponto deveria ficar numa impressora com 1.660 pixels ?" Para resolver esse problema, é só usar a regra de três.

É isso que a função Fator faz.

. . .function TForm1.Fator(intParmOperando: integer): integer;var intTmpOperando: integer; douTmpFatorHeight: double; douTmpFatorWidth: double;begin douTmpFatorHeight := Printer.PageHeight / 3969; douTmpFatorWidth := Printer.PageWidth / 2880;

if douTmpFatorHeight < douTmpFatorWidth then intTmpOperando := Trunc(intParmOperando * douTmpFatorHeight) else intTmpOperando := Trunc(intParmOperando * douTmpFatorWidth);

if intTmpOperando = 0 then intTmpOperando := 1;

Result := intTmpOperando;end;. . .

Nos testes do programa de exemplo, foi usada uma impressora Epson Stylus Color 500, com 2.880 pixels de largura por 3.969 de altura.

Printer.PageHeight e Printer.PageWidth são, respectivamente, a altura e a largura em pixels da "superfície" de impressão da impressora selecionada.

São calculados dois fatores, um para altura e outro para largura. Vale o menor deles.

O operando (que pode ser uma coluna, linha, comprimento, etc.) é multiplicado pelo fator. O resultado da função é o operando proporcional ao fator.

Esta solução não é cem por cento segura e existem muitas outras formas de resolver o mesmo problema. Você deve procurar a solução mais adequada ao seu problema.

Procedimento ImprimirCabecalhoO procedimento deve conter o seguinte código:

Page 21: Quick Report

. . .procedure TForm1.ImprimirCabecalho;var intTmpPos: integer; strTmpTexto: string; rectTmpBmp: TRect; bmpTmpBitmap: TBitmap;begin

// Imprimir bitmap if FileExists('C:\Windows\Circles.bmp') then begin bmpTmpBitmap := TBitmap.Create; bmpTmpBitmap.LoadFromFile('C:\Windows\Circles.bmp');

rectTmpBmp.Top := Fator(100); rectTmpBmp.Bottom := Fator(350); rectTmpBmp.Left := Fator(100); rectTmpBmp.Right := Fator(300);

Printer.Canvas.StretchDraw(rectTmpBmp, bmpTmpBitmap); bmpTmpBitmap.Free; end;

// Imprimir texto Printer.Canvas.Font.Color := clBlack; Printer.Canvas.Font.Size := Fator(16); Printer.Canvas.Font.Style := [fsBold];

strTmpTexto := 'Relatório de Clientes'; intTmpPos := (2870 – Printer.Canvas.TextWidth(strTmpTexto)) div 2; Printer.Canvas.TextOut(Fator(intTmpPos), Fator(150), strTmpTexto);

strTmpTexto := 'Impresso Diretamente por TPrinter'; intTmpPos := (2870 – Printer.Canvas.TextWidth(strTmpTexto)) div 2; Printer.Canvas.TextOut(Fator(intTmpPos), Fator(250), strTmpTexto);

// Imprimir as linhas Printer.Canvas.Pen.Width := Fator(12); Printer.Canvas.MoveTo(Fator(100), Fator(400)); Printer.Canvas.LineTo(Fator(2800), Fator(400));

Printer.Canvas.Pen.Width := Fator(4); Printer.Canvas.MoveTo(Fator(100), Fator(425)); Printer.Canvas.LineTo(Fator(2800), Fator(425));

intPrivLinhaPixel := 460;end;. . .

Para imprimir um bitmap: Instancie a classe TBitmap; carregue o arquivo com o bitmap desejado; declare a posição onde o bitmap deve ser impresso numa variável do tipo TRect e mande imprimir com o comando Printer.Canvas.StrechDraw.

Page 22: Quick Report

Para imprimir um string centralizado: Defina a fonte (nome, tamanho, estilo e cor) usando Printer.Canvas.Font; Calcule a coluna em pixels onde o texto deve ser impresso (use o método Printer.Canvas.TextWidth para obter o tamanho do string a ser impresso); imprima o string com o método Printer.Canvas.TextOut.

Para imprimir uma linha horizontal: Defina a largura da "caneta", para desenhar uma linha mais grossa ou mais fina, usando a propriedade Printer.Canvas.Pen.Width; posicione a "caneta" no início da linha com o método Printer.Canvas.MoveTo; desenhe a linha com o método Printer.Canvas.LineTo.

Nos métodos da classe TCanvas que recebem uma coordenada, o primeiro parâmetro é a coluna e o segundo a linha. Ex.: Printer.Canvas.MoveTo(100, 200) Move a "caneta" para a coluna 100 na linha 200.

Procedimento ImprimirDetalheO procedimento deve conter o seguinte código:

. . .procedure TForm1.ImprimirDetalhe;var strTmpTexto: string;begin

// Imprimir um retângulo Printer.Canvas.Brush.Color := clSilver; Printer.Canvas.Pen.Width := Fator(1);

Printer.Canvas.Rectangle(Fator(100), Fator(intPrivLinhaPixel), Fator(2800), Fator(intPrivLinhaPixel + 100));

// Imprimir um string dentro do retângulo Printer.Canvas.Font.Color := clBlue; Printer.Canvas.Font.Style := [fsBold]; Printer.Canvas.Font.Size := Fator(12);

strTmpTexto := Table1NOME.Value; Printer.Canvas.TextOut(Fator(110), Fator(intPrivLinhaPixel + 10), strTmpTexto);

intPrivLinhaPixel := intPrivLinhaPixel + 130;

// Retornar a configuração original Printer.Canvas.Brush.Color := clWhite; Printer.Canvas.Font.Color := clBlack; Printer.Canvas.Font.Style := []; Printer.Canvas.Font.Size := Fator(8);

// Imprimir detalhes strTmpTexto := 'Endereço: ' + Table1LOGRADOURO.Value; Printer.Canvas.TextOut(Fator(100), Fator(intPrivLinhaPixel), strTmpTexto); strTmpTexto := 'Compl.: ' + Table1COMPLEMENTO.Value; Printer.Canvas.TextOut(Fator(1500), Fator(intPrivLinhaPixel), strTmpTexto);

intPrivLinhaPixel := intPrivLinhaPixel + 60;

strTmpTexto := 'Cidade..: ' + Table1CIDADE.Value; Printer.Canvas.TextOut(Fator(100), Fator(intPrivLinhaPixel), strTmpTexto); strTmpTexto := ' UF: ' + Table1ESTADO.Value; Printer.Canvas.TextOut(Fator(1500), Fator(intPrivLinhaPixel), strTmpTexto);

Page 23: Quick Report

strTmpTexto := 'CEP: ' + Table1CEP.Value; Printer.Canvas.TextOut(Fator(2000), Fator(intPrivLinhaPixel), strTmpTexto);

intPrivLinhaPixel := intPrivLinhaPixel + 70;end;. . .

Para imprimir um retângulo: Defina a cor de fundo do retângulo com a propriedade Printer.Canvas.Brush.Color; defina a largura da "caneta" para desenhar a borda do retângulo com a propriedade Printer.Canvas.Pen.Width; desenhe o retângulo com o método Printer.Canvas.Rectangle. Esse método recebe como parâmetros dois pares ordenados. O primeiro indica o ponto superior esquerdo do retângulo e o segundo, o ponto inferior direito.

Para imprimir um string dentro do retângulo: Defina a cor, o tamanho e o estilo da fonte do string a ser impresso com a propriedade Printer.Canvas.Color; imprima o string usando o método Printer.Canvas.TextOut passando como coordenada um ponto dentro do retângulo.

Retornar a configuração original: Depois de modificar a configuração (fonte, brush, etc.) para imprimir uma figura ou um texto em destaque, a configuração deve ser refeita para retornar aos valores originais.

Procedimento ImprimirRodapeO procedimento deve conter o seguinte código:

. . .procedure TForm1.ImprimirRodape;var strTmpTexto: string;begin // Imprimir as linhas Printer.Canvas.Pen.Width := Fator(4); Printer.Canvas.MoveTo(Fator(100), Fator(3700)); Printer.Canvas.LineTo(Fator(2800), Fator(3700));

Printer.Canvas.Pen.Width := Fator(12); Printer.Canvas.MoveTo(Fator(100), Fator(3725)); Printer.Canvas.LineTo(Fator(2800), Fator(3725));

// Imprimir o texto Printer.Canvas.Font.Color := clGray; Printer.Canvas.Font.Size := Fator(8); Printer.Canvas.Font.Style := [fsBold];

strTmpTexto := 'Página: ' + IntToStr(Printer.PageNumber); Printer.Canvas.TextOut(Fator(100), Fator(3770), strTmpTexto);

strTmpTexto := 'Data: ' + DateToStr(Date);

Printer.Canvas.TextOut(Fator(2400), Fator(3770), strTmpTexto);

intPrivLinhaPixel := 0;end;. . .

O rodapé do relatório consiste de duas linhas paralelas (semelhantes às usadas no cabeçalho), a data da impressão e o número da página.

Page 24: Quick Report

Para obter o número da página, use a propriedade Printer.PageNumber.

Próximo passo: Experts

Faça de www.marcosferreira.eti.br a sua home page! Copyright © 2001 Marcos dos Santos Ferreira Outorga-se a permissão de copiar, distribuir e/ou modificar este documento sob os termos da Licença de Documentação Livre GNU Versão 1.1 ou qualquer outra versão posterior publicada pela Free Software Foundation; sem Seções Invariantes; sem textos da Página de Rosto e sem textos da Contracapa. Uma cópia da licença é incluída na seção intitulada "GNU Free Documentation License".