Você está na página 1de 24

- Notcias - Artigos - Curso - Dicas - FAQ - Links - Livros Relatrio A impresso de relatrios uma necessidade na maioria dos sistemas.

. Quem tem Delphi tem tudo para imprimir relatrios. O Delphi vem com dois mecanismos bsicos para gerar relatrios: (1) Quick Report e (2) TPrinter. Alm disso existem muitos geradores de relatrios 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 pgina atravs de um sistema de coordenadas calculadas em pixels. Isso to difcil quanto parece. melhor pular esse mtodo. No Quick Report o relatrio desenhado em um ambiente visual como se fosse um Form. Esse mtodo bem mais fcil. Vamos a ele. Quick Report Desenhar um relatrio com o Quick Report assim: Voc cria um novo Form e nesse Form em branco voc desenha o relatrio usando os componentes prprios do Quick Report (esses componentes esto na aba QReport da palheta de componetes). Para fazer o programa imprimir o relatrio ou mostrar uma prvia do relatrio em vdeo, voc deve incluir uma opo de impresso no menu ou boto - em um Form que seja visvel ao usurio (pode ser o Form principal do sistema). O Form do relatrio em Quick Report no fica visvel ao usurio. Imagine um projeto Project1 que tem um Form chamado Form1. Para fazer um relatrio, crie um outro Form chamado Form2. Desenhe seu relatrio no Form2. Coloque um boto ou coisa parecida no Form1. Defina uma procedure para responder ao evento do boto. Nessa procedure mande imprimir o relatrio do Form2. No esquea de declarar o Form2 na clusula uses do Form1. A unit do Form1 vai ficar assim: ... unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Unit2; ... procedure TForm1.Button1Click(Sender: TObject); begin Form2.QuickRep1.Preview; end; ... Note a declarao da Unit2 (a unit do Form2) na clusula uses do Form1. Note tambm a procedure Button1Click, que responde ao evento OnClick do boto Button1. QuickRep1 o nome do relatrio que est no Form2. O mtodo preview do QuickRep1 mostra uma prvia do relatrio em vdeo. Para fazer o programa mandar o relatrio diretamente para a impressora s substituir o mtodo preview pelo mtodo print. Desenhando o relatrio

Vamos retomar o projeto Pcliente e fazer um relatrio de clientes. O relatrio vai conter nome, contato, telefone e limite de crdito. Componente QuickRep O componente QuickRep a base para a construo do relatrio. dentro do QuickRep que o relatrio vai ser desenhado. Abra o projeto Pcliente.dpr Crie um Form novo: clique na opo do menu do Delphi "File --> New Form" ou clique no boto 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. Bands As bands do QuickRep dividem o relatrio em faixas de acordo com a funo. Existe uma faixa para o cabealho, outra para o rodap, outra para a linha de detalhe, etc. D um duplo clique na propriedade Bands do QuickRep Vo aparecer as opes HasColumnHeader, HasDetail, HasPageFooter, HasPageHeader, HasSummary e HasTitle. Opes da propriedade Bands Funo HasTitle Pe uma faixa (band) para edio do ttulo do relatrio. Ttulo aquela parte do relatrio que s aparece no topo da primeira pgina, depois do cabealho. Coloque False. HasPageHeader Pe uma faixa para edio do cabealho. O cabealho aparece no topo de cada pgina do relatrio. Coloque True. HasDetail Pe uma faixa para edio de linha de detalhe. A linha de detalhe aparece uma vez para cada registro da tabela. Coloque True. HasColumnHeader Pe uma faixa para edio do cabealho de coluna. Essa faixa aparece entre o cabealho e a linha de detalhe. Coloque True. HasPageFooter Pe uma faixa para edio do rodap. Essa faixa aparece no fim de cada pgina. Coloque True. HasSummary Pe uma faixa para edio do sumrio. Essa faixa aparece no fim da ltima pgina do relatrio, antes do rodap. Coloque True. Tabela 29: QuickRep - Bands - Opes Veja como ficou:

Figura 34: Componente QuickRep DataSet

A prxima propriedade do QuickRep a DataSet. Essa propriedade aponta para a fonte dos dados que sero 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 relatrio Selecione o componente QuickRep Mude a propriedade DataSet para tblCliente Outras Propriedades do QuickRep Propriedade Funo Name Nome do componente. Mude para relCliente ReportTitle o nome que vai aparecer na fila de impresso do Windows ou da rede. Mude para Relatrio de Clientes Options Estas opes permitem impedir que o cabealho aparea na primeira pgina ou que o rodap aparea na ltima. Isso til se voc quiser que o ttulo ou a faixa de fim de relatrio apaream isolados, sem cabealho ou rodap. No projeto atual deixe como est. Page Define o formato da pgina. Altura, largura, margens, orientao (retrato ou paisagem), etc. Tabela 31: Propriedades do componente QuickRep Cabealho Vamos desenhar o cabealho na faixa PageHeader. Selecione a faixa PageHeader Clique e arraste a ncora inferior da faixa para aumentar o tamanho. ncoras so aqueles pontos pretos que aparecem em volta do componente selecionado. Coloque um componente QRLabel na faixa PageHeader. Note que os componentes no 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 "Relatrio de Clientes" (sem as aspas). Mude a opo 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 boto das reticncias Escolha uma imagem com o Picture Editor Figura 35: Cabealho Cabealho de Coluna

Vamos desenhar o cabealho de coluna na faixa ColumnHeader. Coloque 4 componentes QRLabel na faixa ColumnHeader (um para cada coluna do relatrio). Altere as propriedades Caption para Nome, Contato, Telefone e Limite de Crdito. Altere o Style das propriedades Font para Underline e Italic. S para enfeitar um pouco vamos colocar uma linha separando o cabealho das linhas de detalhe. Coloque um componente QRShape na faixa ColumnHeader Mude a opo Width da propriedade Pen para 4. Isso vai engrossar a linha. Mude a propriedade Shape para qrsHorLine. O componente QRShape tem vrias formas pr-definidas. qrsHorLine a linha horizontal. Estique a linha por toda extenso do relatrio usando as ncoras. Figura 36: Cabealho de Coluna Linha de Detalhe Vamos desenhar a linha de detalhe na faixa Detail. Coloque 4 componentes QRDBText na faixa Detail (um para cada coluna do relatrio). Faa com que eles fiquem grudados na parte superior da faixa. Reduza a altura da faixa at no sobrar espao entre os componentes e o fim da faixa. Se sobrar algum espao, as linhas de detalhe vo 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 relatrio. Na ltima coluna (Limite de Crdito) mude a propriedade Alignment para taRightJustify. Tradicionalmente os nmeros so 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 posio da borda esquerda, o que acaba desalinhando os campos alinhados direita. Coloque a mscara de edio ###,##0.00 na propriedade Mask. Figura 37: Linha de Detalhe Sumrio Vamos desenhar o sumrio do relatrio na faixa Summary. Vamos colocar nessa faixa um totalizador para imprimir o somatrio dos limites de crdito. 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 contm a frmula a ser calculada. Digite a frmula SUM(tblCliente.VALOR_CREDITO). Para ver outras frmulas clique no boto das reticncias ao lado da propriedade Expression. Isso vai abrir o Expression Wizard que vai ajudar a criar outras frmulas.

Mude o Style da propriedade Font para Bold. Coloque a mscara de edio ###,##0.00 na propriedade Mask. Mude a propriedade Master para relCliente.

Toda frmula que contm funes agregadoras (somatrio, mdia, mnima, mxima, etc.) precisa de um Master. Esse Master indica quando calcular (o que entra ou no no clculo). 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: Sumrio Rodap Vamos desenhar o rodap do relatrio na faixa PageFooter. Coloque um componente QRSysData na faixa PageFooter esquerda. Esse componente usado para imprimir informaes do sistema, tais como data, hora e nmero da pgina. Mude a propriedade Data para qrsDate (data corrente). Coloque outro componente QRSysData na faixa PageFooter direita.. Mude a propriedade Data para qrsPageNumber (nmero da pgina). Coloque um componente QRLabel prximo ao nmero da pgina. Mude a propriedade Caption para Pgina: 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 cabealho das colunas.

Figura 39: Rodap Imprimindo com Quick Report Agora que o relatrio est desenhado, vamos colocar a opo de impresso no Form principal. Abra o Form frmCliente Inclua a Unit do relatrio Urelat na clusula uses Inclua um boto na barra de ferramentas do Form. Se voc esqueceu como fazer, veja o tpico Barra de Ferramentas em Componentes visuais. Coloque uma figura de impressora no boto. Veja o tpico Lista de Imagens no Componentes visuais. Inclua uma opo Imprimir no menu. Veja o tpico Menu em Componentes visuais. Inclua uma procedure para tratar o evento OnClick da opo Imprimir do menu. Associe o evento OnClick do boto Imprimir mesma procedure. A procedure deve ficar assim: unit Ucliente; interface uses Windows, . . ., DBTables, Urelat; ... procedure TfrmCliente.Imprimir1Click(Sender: TObject); begin frmRelatorio.relCliente.Preview; end; ...

Observaes: A unit do relatrio (Urelat) declarada na clusula Uses. frmRelatorio o nome do Form do relatrio. relCliente o nome do componente QuickRep no Form frmRelatorio. Preview o comando que mostra o relatrio no vdeo. Se quiser imprimir diretamente na impressora s substituir o comando Preview pelo Print. Quando executar o programa voc vai ver o relatrio no vdeo assim:

Figura 40: Preview do Relatrio

Prximo passo: Arquivos seqenciais

Faa de www.marcosferreira.eti.br a sua home page! Copyright 2001 Marcos dos Santos Ferreira Outorga-se a permisso de copiar, distribuir e/ou modificar este documento sob os termos da Licena de Documentao Livre GNU Verso 1.1 ou qualquer outra verso posterior publicada pela Free Software Foundation; sem Sees Invariantes; sem textos da Pgina de Rosto e sem textos da Contracapa. Uma cpia da licena includa na seo intitulada "GNU Free Documentation License".

- Notcias - Artigos - Curso - Dicas - FAQ - Links - Livros Arquivos sequenciais Est certo. Com Delphi voc tem todos os principais bancos de dados do mundo sua disposio. Ento porque voc iria querer manipular arquivos sequenciais ? Arquivos so como BomBril: Tm mil e uma utilidades. Por exemplo: Os arquivos podem ser acessados por virtualmente todas as linguagens de programao. 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 captulo voc vai aprender a manipular arquivos: ler, gravar, renomear, excluir, etc. Funes Bsicas O Delphi vem com um conjunto de funes de manipulao de arquivos. Renomeando um Arquivo A funo RenameFile renomeia um arquivo, retornando True se o arquivo foi renomeado. ...

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 no informado, o arquivo deve estar no diretrio corrente. Ateno: Quando informado o PATH do nome antigo mas no informado o PATH do nome novo, a funo RenameFile MOVE o arquivo para o diretrio 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 diretrio corrente (que pode at ser ou no o prprio C:\Windows) Excluindo um Arquivo A funo DeleteFile exclui um arquivo, retornando True se o arquivo foi excludo. ... if DeleteFile(ARQUIVO.OLD) then ShowMessage(Arquivo excludo.) else ShowMessage(Erro ao excluir arquivo); ... No exemplo, o arquivo "Arquivo.old" vai ser excludo. Quando o PATH no informado, a funo procura o arquivo no diretrio corrente. Copiando um Arquivo O Delphi no tem nenhuma funo para copiar arquivos mas voc pode usar a funo do prprio 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 no informado, a funo procura o arquivo no diretrio corrente. Quando o PATH do arquivo de destino no informado, a funo grava o arquivo no diretrio corrente. O terceiro parmetro 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 funo aborta a cpia. Quando False e o arquivo de destino j existe, a funo grava por cima. Ateno: A funo CopyFile no aceita variveis do tipo string como parmetros dos nomes dos arquivos. Aceita somente variveis do tipo Pchar. Quando necessrio, faa o typecast.

... var strTmpArqOrig, strTmpArqDest: string; ... if CopyFile(Pchar(strTmpArqOrig), Pchar(strTmpArqDest), True) then ShowMessage(Arquivo copiado.) else ShowMessage(Erro ao copiar arquivo); ... Observe que as variveis strTmpArqOrig e strTmpArqDest so do tipo string. Se no fosse feito o typecast Pchar(strVariavelString) o compilador acusaria erro de incompatibilidade entre tipo de dado string e Pchar. Testando se um Arquivo Existe A funo FileExists testa se um arquivo existe e retorna True se encontrou. ... if FileExists(C:\ARQUIVO.TXT) then ShowMessage(Arquivo existe.) else ShowMessage(Arquivo no existe.); ... Lendo e Gravando Arquivos Ler e gravar arquivos em Delphi uma tarefa fcil. Para quem j conhece alguma verso anterior do Pascal mais fcil ainda porque no mudou praticamente nada. Gravando um Arquivo Novo Observe 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 varivel do tipo arquivo. No exemplo, a varivel tfArquivo do tipo TextFile (um arquivo texto). Depois usa-se o comando AssignFile para associar um arquivo (no exemplo, "c:\Windows\Temp\Arquivo.new") varivel declarada. A partir deste ponto, a varivel tfArquivo representar o arquivo associado a ela. Usar uma varivel no associada a algum arquivo gera erro de I/O em tempo de execuo.

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 contedo do arquivo, usa-se o comando Write ou Writeln. Os dois comandos gravam um string no arquivo. A diferena 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 gravao, deve-se fechar o arquivo com o comando CloseFile. Gravando um Arquivo J Existente Em muitas situaes precisamos adicionar novas informaes 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 diferena entre este e o exemplo anterior est na substituio 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 no existir, ocorre um erro com a mensagem "File not found" em tempo de execuo. Lendo um Arquivo Vamos 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.

A funo EOF (sigla de End Of File, fim de arquivo em ingl&ecircs) retorna True quando o arquivo chegou ao fim. Gerando Um Arquivo HTML Com essa tecnologia to simples e antiga, possvel gerar pginas para internet com dados extrados de qualquer banco de dados. Pode at no ser o mtodo mais fcil, mas est ao alcance de qualquer um com poucos conhecimentos de HTML. Vamos usar a conhecida tabela CLIENTE.DB para gerar uma pgina 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> Relao 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>Relao 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);

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 gravao de arquivos so idnticos aos j estudados nos exemplos anteriores. Os comandos de leitura de tabelas do banco de dados tambm j so conhecidos. Veja abaixo uma lista como os comandos HTML mais importantes usados neste exemplo. (Uma explicao detalhada dos comandos HTML esto alm do escopo deste curso). Comando Descrio <HTML> Incio do arquivo HTML <HEAD> rea de cabealho da pgina <TITLE> Ttulo da pgina que aparece na barra superior do browser.

<BODY> Corpo da pgina, que aparece na rea de visualizao do browser. <TABLE> Declarao de tabela, semelhante s tabelas usadas no MS-Word. No 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 cdigo vai gerar um arquivo CLIENTE.HTML que poder ser aberto em um browser. Experimente.

Prximo passo: Arquivos INI

Faa de www.marcosferreira.eti.br a sua home page! Copyright 2001 Marcos dos Santos Ferreira Outorga-se a permisso de copiar, distribuir e/ou modificar este documento sob os termos da Licena de Documentao Livre GNU Verso 1.1 ou qualquer outra verso posterior publicada pela Free Software Foundation; sem Sees Invariantes; sem textos da Pgina de Rosto e sem textos da Contracapa. Uma cpia da licena includa na seo intitulada "GNU Free Documentation License". - Notcias - Artigos - Curso - Dicas - FAQ - Links - Livros Arquivos INI Arquivos INI so arquivos de configurao. So chamados assim porque tm a extenso *.ini. Cada programa pode ter um ou mais arquivos INI que por sua vez podem conter uma infinidade de parmetros. 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 configurao. Com o advento do Registry, os arquivos INI deveriam ter sido aposentados, mas no 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 manuteno em programas antigos, bom saber como usar os arquivos INI. Vamos ver neste captulo como criar configuraes usando arquivos INI. Estrutura do Arquivo INI Os arquivos INI so divididos em sees. Cada seo dividida em chaves. Cada chave um parmetro que possui um valor. ... [windows] load=

run= NullPort=None device=Epson Stylus COLOR 500,EPS500,LPT1: [Desktop] Wallpaper=(None) TileWallpaper=0 WallpaperStyle=0 Pattern=(None) ... O exemplo acima um trecho do arquivo WIN.INI que est no diretrio do Windows. As sees so declaradas entre colchetes (observe as sees [WINDOWS] e [DESKTOP]). As chaves ficam dentro de uma seo (na seo Desktop as chaves so Wallpaper, TileWallpaper, WallpaperStyle e Pattern) Cada chave possui um valor (por exemplo, TileWallpaper=0). Classe TIniFile O Delphi tem uma classe chamada TiniFile, declarada na unit IniFiles, que faz manipulao de arquivos INI. Criando um Arquivo INI Um arquivo INI no precisa ser criado. Ao inserir o valor em uma chave, o arquivo ser criado automaticamente (se ainda no existir). Criando uma Seo Da mesma forma que o arquivo, uma seo no precisa ser explicitamente criada. Ao inserir o valor em uma chave, a seo da chave ser criada automaticamente (se ainda no existir). Gravando uma Chave A classe TIniFile tem vrios mtodos para gravar chaves, um para cada tipo de dado. O mesmo mtodo 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 mtodo Create no cria o arquivo MEUINI.INI. Este mtodo o construtor da classe e apenas instancia a classe. Este mtodo recebe como parmetro o nome do arquivo INI com o qual se quer trabalhar. O mtodo WriteString grava Edit1.Text como valor na chave "Minha chave" da seo "Minha seo". O mtodo WriteString cria tudo o que for necessrio para guardar o valor da chave. Se o arquivo no existe, cria o arquivo. Se a seo no existe, cria a seo. Se a chave no existe, cria a chave. Ateno: No esquea de declarar a unit IniFiles na clusula uses.

Mtodos para gravar chaves com outros tipos de dados so: WriteBool (booleano), WriteInteger (nmero inteiro), WriteFloat (ponto flutuante), WriteTime (hora), WriteDate (data), WriteDateTime (data e hora). A nica diferena entre esses mtodos o tipo de dado do terceiro parmetro (o valor da chave), que muda de acordo com o mtodo. Lendo uma Chave Tal qual a gravao, a classe TIniFile tambm tem diversos mtodos 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 mtodo ReadString l o valor na chave "Minha chave" da seo "Minha seo". Caso a chave "Minha chave" ou a seo "Minha seo" no existam, o mtodo ReadString retornar o valor default, declarado como terceiro parmetro. No exemplo o valor default "{sem valor}". Mtodos para ler chaves com outros tipos de dados so: ReadBool (booleano), ReadInteger (nmero inteiro), ReadFloat (ponto flutuante), ReadTime (hora), ReadDate (data), ReadDateTime (data e hora). A nica diferena entre esses mtodos o tipo de dado do terceiro parmetro (o valor default), que muda de acordo com o mtodo. Apagando uma Chave s vezes necessrio apagar uma chave. Para isso, use o mtodo DeleteKey. ... var iniMeuArquivo: TIniFile; begin iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI'); iniMeuArquivo.DeleteKey('MINHA SECAO', 'MINHA CHAVE'); iniMeuArquivo.Free; end; ... Apagando uma Seo Para apagar a seo inteira, inclusive as chaves dentro dela, use o mtodo EraseSection. ... var iniMeuArquivo: TIniFile; begin iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI'); iniMeuArquivo.EraseSection('MINHA SECAO'); iniMeuArquivo.Free; end; ...

O mtodo EraseSection no apaga o arquivo INI, mesmo que a ltima seo tenha sido excluda.

Prximo passo: Imprimindo com TPrinter

Faa de www.marcosferreira.eti.br a sua home page! Copyright 2001 Marcos dos Santos Ferreira Outorga-se a permisso de copiar, distribuir e/ou modificar este documento sob os termos da Licena de Documentao Livre GNU Verso 1.1 ou qualquer outra verso posterior publicada pela Free Software Foundation; sem Sees Invariantes; sem textos da Pgina de Rosto e sem textos da Contracapa. Uma cpia da licena includa na seo intitulada "GNU Free Documentation License". - Notcias - Artigos - Curso - Dicas - FAQ - Links - Livros Imprimindo com TPrinter Existem dzias de geradores de relatrios mais ou menos integrados ao Delphi. O prprio Quick Report, o ReportBuilder, o ReportSmith, etc. Teoricamente voc jamais teria que se preocupar com os aspectos de baixo nvel da impresso, certo ? Errado. O Quick Report muito bom mas no mgico; tem as suas limitaes. Outros geradores de relatrios so muito caros ou muito lentos e tambm no so perfeitos. Quando no d para usar um gerador de relatrios, o jeito fazer impresso direta. Classe TPrinter A classe TPrinter encapsula a interface do Windows com a impressora. Possui propriedades e mtodos para impresso. Propriedades Propriedade Descrio Canvas Representa a superfcie da pgina. Possui mtodos para escrever texto e desenhar figuras geomtricas. (Veja o tpico 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 pgina: poLandscape imprime na horizontal e poPortrait imprime na vertical. PageHeight Altura da pgina em nmero de pixels. PageNumber Nmero da pgina corrente que est sendo impressa. atualizado automaticamente. PageWidth Largura da pgina em nmero de pixels. PrinterIndex Seleciona em qual impressora o relatrio ser impresso. Este ndice refere-se propriedade Printers (abaixo). Para selecionar a impressora padro 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 relatrio que vai aparecer no gerenciador de impresso. Tipo de dado: String Tabela 33: Propriedades da classe TPrinter

Mtodos Propriedade Descrio Abort Cancela a impresso de um relatrio. BeginDoc Inicia a impresso de um relatrio. Tem que ser executado antes de comear a imprimir qualquer coisa. EndDoc Encerra a impresso de um relatrio. Tem que ser executado ao fim da impresso. NewPage Muda de pgina e incrementa a propriedade PageNumber. Tabela 34: Mtodos da classe TPrinter Classe TCanvas Lembra do famoso "Plano Cartesiano" ? Aquele das coordenadas x e y ? Pois . Agora voc vai ver a utilidade prtica dessa coisa. A classe TCanvas um Plano Cartesiano. com a classe TCanvas que o programa vai mandar para a impressora textos, figuras geomtricas e imagens. A posio dos textos e figuras na pgina do relatrio determinada pelo sistema de pares ordenados (x, y). As coordenadas so medidas em pixels. O topo da pgina, por exemplo, est nas coordenadas (0, 0). Propriedades Propriedade Descrio Brush Configura o "pincel" usado para pintar o fundo das figuras geomtricas: Cor e estilo. Tipo de dado: TBrush. Font Configura a fonte usada para imprimir o texto: Nome da fonte, cor, tamanho, estilo, etc. (No 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 posio corrente da caneta, onde o prximo texto ou figura ser impresso. Tipo de dado: TPoint. Tabela 35: Propriedades da classe TCanvas Mtodos Propriedade Descrio Rectangle Desenha um retngulo preenchendo-o com o padro definido na propriedade Brush. LineTo Desenha uma linha entre o ponto determinado por PenPos e o ponto passado como parmetro. Geralmente usado em conjunto com MoveTo. MoveTo Muda a posio corrente (PenPos) para o ponto passado como parmetro. TextOut Imprime um string na posio passada como parmetro. Tabela 36: Mtodos da classe TCanvas Praticando a Impresso com TPrinter Vamos imprimir um relatrio usando a impresso com TPrinter. Vai ser um relatrio simples, do tipo que qualquer gerador de relatrios pode fazer. A impresso direta j , por si s, uma coisa um pouco complicada. A idia simplificar o exemplo para no complicar a explicao, certo ? Definio do Relatrio: Imprimir o cadastro de clientes usando a tabela CLIENTE.DB. Vamos comear ...

Seo Interface Crie um projeto novo. Na clusula uses declare a unit Printers. Coloque no Form um boto. 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 boto direito do mouse sobre o TTable; selecione "Fields Editor" no menu pop-up; clique com o boto direito do mouse na janela "Form1.Table1"; clique na opo "Add Fields" do menu pop-up; selecione todos os campos na lista "Available Fields" e clique no boto OK.). Na parte private do Form, declare a varivel intPrivLinhaPixel, os procedimentos AbrirRelatorio, ImprimirCabecalho, ImprimirDetalhe, ImprimirRodape, FecharRelatorio e a funo Fator. (A finalidade de cada declarao ser vista mais tarde.) unit Unit1; interface uses . . ., 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;

procedure AbrirRelatorio; procedure ImprimirCabecalho; procedure ImprimirDetalhe; procedure ImprimirRodape; procedure FecharRelatorio; function Fator(intParmOperando: integer): integer; ... Evento OnClick Crie um procedimento para responder ao evento OnClick do boto. O procedimento deve conter o seguinte cdigo: ... 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 relatrio. necessrio um procedimento para abrir e outro para fechar o relatrio (que sero explicados abaixo). A varivel intPrivLinhaPixel guarda o nmero em pixels da prxima linha a ser impressa. Quando esse nmero ultrapassa 3400 est na hora de mudar de pgina. Entre o rodap de uma pgina e o cabealho de outra, h o comando "Printer.NewPage". Esse comando faz a impressora mudar de pgina. Pergunta: De onde surgiu esse Printer ? Resposta: Printer uma instncia da classe TPrinter. Voc no precisa declarar e nem instanciar a classe TPrinter. O prprio Delphi faz isso automaticamente quando encontra a unit Printers declarada na clusula uses. Procedimento AbrirRelatorio

O procedimento deve conter o seguinte cdigo: ... procedure TForm1.AbrirRelatorio; begin Printer.Title := 'Relatrio de Clientes'; Printer.PrinterIndex := -1; Printer.Orientation := poPortrait; Printer.BeginDoc; Printer.Canvas.Font.Name Printer.Canvas.Font.Size Printer.Canvas.Font.Style Printer.Canvas.Font.Color intPrivLinhaPixel end; ... := 0; := 'Courier New'; := Fator(8); := []; := clBlack;

Printer.Title o ttulo que vai aparecer no Gerenciador de Impresso. Atribuir 1 ao Printer.PrinterIndex faz com que a impressora default do sistema seja selecionada. Atribuir poPortrait ao Printer.Orientation faz imprimir o relatrio na posio vertical. Para imprimir na horizontal, atribua o valor poLandscape. O comando Printer.BeginDoc inicia a impresso. As caractersticas da fonte a ser usada (nome, estilo, tamanho e cor) so atribudas ao Printer.Canvas.Font O estilo da fonte pode ser qualquer combinao 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 vrias cores pr-declaradas, como por exemplo: clBlue, clRed, clGray, clGreen, etc. Para uma relao completa, consulte o tipo de dado TColor na documentao do Delphi. Procedimento FecharRelatorio O procedimento deve conter o seguinte cdigo: ... procedure TForm1.FecharRelatorio; begin Printer.EndDoc; end; ... O relatrio fica retido na fila da impressora at que seja liberado. O comando que libera o relatrio da fila o Printer.EndDoc. Para abortar o relatrio, use o comando Printer.Abort. Funo Fator Voc j sabe que para localizar um ponto sobre a "superfcie" do papel, precisa-se de um par ordenado (x, y), onde x e y representam a coluna e a linha.

A unidade de medida usada pela classe TCanvas o pixel. O problema que cada modelo de impressora tem uma resoluo diferente do outro. E da ? Da que o ponto (x1, y1) em um modelo de impressora no fica no mesmo lugar que em outro. Em outras palavras, quando o relatrio impresso em uma impressora com resoluo diferente daquela na qual o programa foi desenvolvido, o relatrio sai torto, desproporcional, s vezes pequeno demais, outras vezes to grande que ultrapassa os limites da folha de papel. Para minimizar esse problema, todas as coordenadas, tamanhos, e comprimentos devem ser calculados proporcionalmente em funo da resoluo 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 trs. isso que a funo 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 so, respectivamente, a altura e a largura em pixels da "superfcie" de impresso da impressora selecionada. So 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 funo o operando proporcional ao fator. Esta soluo no cem por cento segura e existem muitas outras formas de resolver o mesmo problema. Voc deve procurar a soluo mais adequada ao seu problema. Procedimento ImprimirCabecalho O procedimento deve conter o seguinte cdigo:

... 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 := 'Relatrio 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 end; ... := 460;

Para imprimir um bitmap: Instancie a classe TBitmap; carregue o arquivo com o bitmap desejado; declare a posio onde o bitmap deve ser impresso numa varivel do tipo TRect e mande imprimir com o comando Printer.Canvas.StrechDraw.

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 mtodo Printer.Canvas.TextWidth para obter o tamanho do string a ser impresso); imprima o string com o mtodo 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 incio da linha com o mtodo Printer.Canvas.MoveTo; desenhe a linha com o mtodo Printer.Canvas.LineTo. Nos mtodos da classe TCanvas que recebem uma coordenada, o primeiro parmetro a coluna e o segundo a linha. Ex.: Printer.Canvas.MoveTo(100, 200) Move a "caneta" para a coluna 100 na linha 200. Procedimento ImprimirDetalhe O procedimento deve conter o seguinte cdigo: ... procedure TForm1.ImprimirDetalhe; var strTmpTexto: string; begin // Imprimir um retngulo 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 retngulo 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 configurao original Printer.Canvas.Brush.Color := clWhite; Printer.Canvas.Font.Color := clBlack; Printer.Canvas.Font.Style := []; Printer.Canvas.Font.Size := Fator(8); // Imprimir detalhes strTmpTexto := 'Endereo: ' + 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);

strTmpTexto := 'CEP: ' + Table1CEP.Value; Printer.Canvas.TextOut(Fator(2000), Fator(intPrivLinhaPixel), strTmpTexto); intPrivLinhaPixel := intPrivLinhaPixel + 70; end; ... Para imprimir um retngulo: Defina a cor de fundo do retngulo com a propriedade Printer.Canvas.Brush.Color; defina a largura da "caneta" para desenhar a borda do retngulo com a propriedade Printer.Canvas.Pen.Width; desenhe o retngulo com o mtodo Printer.Canvas.Rectangle. Esse mtodo recebe como parmetros dois pares ordenados. O primeiro indica o ponto superior esquerdo do retngulo e o segundo, o ponto inferior direito. Para imprimir um string dentro do retngulo: 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 mtodo Printer.Canvas.TextOut passando como coordenada um ponto dentro do retngulo. Retornar a configurao original: Depois de modificar a configurao (fonte, brush, etc.) para imprimir uma figura ou um texto em destaque, a configurao deve ser refeita para retornar aos valores originais. Procedimento ImprimirRodape O procedimento deve conter o seguinte cdigo: ... 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 := 'Pgina: ' + IntToStr(Printer.PageNumber); Printer.Canvas.TextOut(Fator(100), Fator(3770), strTmpTexto); strTmpTexto := 'Data: ' + DateToStr(Date);

Printer.Canvas.TextOut(Fator(2400), Fator(3770), strTmpTexto); intPrivLinhaPixel end; ... := 0;

O rodap do relatrio consiste de duas linhas paralelas (semelhantes s usadas no cabealho), a data da impresso e o nmero da pgina.

Para obter o nmero da pgina, use a propriedade Printer.PageNumber.

Prximo passo: Experts

Faa de www.marcosferreira.eti.br a sua home page! Copyright 2001 Marcos dos Santos Ferreira Outorga-se a permisso de copiar, distribuir e/ou modificar este documento sob os termos da Licena de Documentao Livre GNU Verso 1.1 ou qualquer outra verso posterior publicada pela Free Software Foundation; sem Sees Invariantes; sem textos da Pgina de Rosto e sem textos da Contracapa. Uma cpia da licena includa na seo intitulada "GNU Free Documentation License".

Você também pode gostar