Como Imprimir utilizando TPrinter - para quem tem problemas!
23/11/2005
0
Vamos a um exemplo completo com explicações de cada passo e o porquê de cada ato.
O programa baseia-se em um form contendo um botão para a impressão de dados, os quais poderão ser tirados de uma tabela, uma tabela com filtro ou através de SQL, o que não faz a menor diferença, se quiser colocar um DBGrid para a visualização dos dados, nada impede.
Vamos supor a impressão de um relatório parcial de vendas durante um determinado período, a parte da seleção do período não será mostrada.
Coloque Printers no uses do Form
Procedure TForm1.Button1Click(Sender : TObject);
Var
Linha, Coluna, Quantidade : Integer;
IndiceHorizontal, IndiceVertical, Total, TotalGeral : Real;
Código : String;
Begin
Button1.Enabled := False; // isto é para evitar que o usuário ache que a impressão está demorando e acione o botão diversas vezes provocando diversas impressões
Cursor := crHourGlass // coloca a ampulheta para informar ao usuário que o computador está efetuando um trabalho
IndiceHorizontal := Printer.PageWidth / 960;
IndiceVertical := Printer.PageHeight / 1584;
Estes dois índices horizontal e vertical são utilizados para ajustar a impressão em qualquer impressora, quer seja matricial ou jato de tinta em qualquer resolução, os números 960 e 1584 foram tirados da minha matricial com uma resolução de 120 x 144 pixels e usando papel A4. Pegue a sua impressora, escolha um tamanho de papel e uma resolução qualquer e dê um showmessage(inttostr(printer.pagewidth) + ‘ ‘ + inttostr(printer.pageheight)) para achar estes números. Na sua configuração inicial as duas divisões terão como resultado o número um, porém se modificar a resolução da impressora, ou o tamanho do papel verá que estes números mudarão, estes números serão utilizados logo abaixo.
Printer.Font.Name := ‘Arial’; // utilizo a fonte arial por ser uma fonte que normalmente está em todos os computadores
Printer.Orientation := poPortrait; // aqui certifica-se que o papel será impresso na forma retrato, pois poderia estar configurado para Printer.Orientation := poLandScape que é o modo paisagem, caso mude para o modo paisagem o printer.pagewidth e printer.pageheight devem ter os seus valores invertidos
Printer.BeginDoc; // inicia o serviço de impressão
Linha := 0;
Quantidade := 0;
TotalGeral := 0; // zera as variáveis;
With Table1 do // pega os dados de uma tabela, mas poderia ser uma Query
Begin
First; // é para confirmar que a tabela está no primeiro registro desejado, esta tabela poderá estar filtrada, caso exista uma DBGrid o usuário poderá ter selecionado algo e não estar no primeiro registro
While not eof do // para imprimir toda a tabela
Begin
With Printer.Canvas do // para evitar a digitação de printer.canvas em cada comando de impressão, o canvas é o responsável pelo processo de “desenho” no windows
Begin
If Linha = 0 then // verifica se é início de página para colocar um cabeçalho
Begin;
Font.Size := 10; // tamanho da fonte para o cabeçalho
Coluna := Round(150 * IndiceHorizontal); // aqui, é efetuada a correção para a resolução horizontal da impressora onde 150 é a posição na coluna onde estou querendo imprimir, nos arredondamentos efetuados o erro máximo será de um pixel, o que não será notado pelo usuário
TextOut(Coluna, Linha, ‘NOME DA EMPRESA’); // a coluna e a linha TEM que ser número inteiro, o texto entre aspas poderá ser uma variável tipo string
Coluna := Round(720 * IndiceHorizontal);
TextOut(Coluna, Linha, DateToStr(Now)); // impressão da data
Linha := Linha + Round(23 * IndiceVertical); aqui pega o valor da linha, faz o acréscimo e a correção da resolução vertical da impressora
Coluna := Round(250 * IndiceHorizontal);
TextOut(Coluna, Linha, ‘Venda entre: ‘ + MaskEdit1.Text + ‘ e ‘ + MaskEdit2.Text)); // imprime a informação do período
Linha := Linha + Round(28 * IndiceVertical);
Font.Size := 9;
Coluna := 0;
TextOut(Coluna, Linha, ‘CÓDIGO’); // este e os seguintes são os nomes das colunas a serem impressas
Coluna := Round(90 * IndiceHorizontal);
TextOut := Round(Coluna, Linha, ‘QUANT’);
Coluna := Round(170 * IndiceHorizontal);
TextOut(Coluna, Linha, ‘VALOR’); // acrescente quantas colunas a mais precisar utilizando o mesmo princípio
Linha := Linha + (Round(25 * IndiceVertical);
End;
Coluna := 0;
Código := IntToStr(FieldByName(‘CODIGOPRODUTO’).AsInteger); // transforma o código de inteiro para string para a impressão, para mostrar a utilização de variável e utilizando o tipo de campo;
TextOut(Coluna, Linha, Código); // imprime o código do produto
Coluna := Round(90 * IndiceHorizontal);
TextOut(Coluna, Linha, IntToStr(FieldByName(´QUANTIDADEVENDIDA’).Value)); // imprime sem utilização de variável e utilizando VALUE em vez do tipo do campo
Total := FieldByName(‘TOTAL’).AsFloat; // joga o valor do total em uma variável;
TotalGeral := TotalGeral + Total; // soma o total geral para impressão no final
Quantidade := Quantidade + 1; // soma a quantidade de produtos vendidos para a impressão no final
Coluna := Round(170 * IndiceHorizontal);
TextOut(Coluna, Linha, FloatToStrF(Total, ffFixed, 10, 2)); // pega o valor e formata o mesmo para um valor fixo com duas casas decimais. O ffFixed também pode ser ffGeneral, ffExponent, ffNumber ou ffCurrency, veja o help do Delphi
Linha := Linha + Round(20 * IndiceVertical);
If Linha >= 1440 then // verifica se já chegou no local onde quero terminar a impressão da página
Begin
Linha := 0; // zera o valor da linha para a impressão do cabeçalho na outra página, se quiser fazer controle de impressão de número de página também pode colocar aqui para que o mesmo seja impresso no final da página
Printer.NewPage; // ejeta a página
Se quiser pode acrescentar um contador de páginas aqui e imprimir o número da página
End;
End;
End;
Next; // vai para o próximo registro da tabela
End;
Printer.Canvas.Font.Size := 10; // troca o tamanho da fonte
Linha := Linha + Round(25 * IndiceVertical);
If Linha > 1400 then // verifica a posição no papel para ter certeza que a impressão ficará inteira na mesma página
Printer.NewPage;
Coluna := 0;
Printer.Canvas.TextOut(Coluna, Linha, ‘QUANTIDADE TOTAL DE ÍTENS: ’ + IntToStr(Quantidade)); // aqui também poderia ser a quantidade total de produtos vendidos, é só uma questão de escolha do que vai ser impresso
Linha := Linha + Round(25 * IndiceVertical);
Printer.Canvas.TextOut(Coluna, Linha, ‘VALOR TOTAL: ‘ + FloatToStrF(TotalGeral, ffCurrency, 10, 2); // aqui em vez de ffFixed utilizei ffCurrency para que na impressão apareça o R$
Printer.EndDoc; // com este comando acaba a impressão ejetando a página, caso não seja colocado a ejeção acontecerá porém o documento demorará mais tempo para ser impresso
Cursor := crDefault; // volta o cursor ao estado original
Apesar de aparentemente muito trabalhosa, esta impressão, depois que a pessoa se acostuma, é bem rápida, desde que sempre se utilize uma mesma resolução de desenvolvimento, pois o desenvolvedor acostuma-se com a noção de espaço horizontal e vertical e já não precisa mais efetuar diversas impressões do documento para efetuar ajustes.
Edilcimar Reis Félix – Vitória - ES
Edilcimar
Posts
03/01/2006
Edilcimar
13/01/2006
Fabiano_aprendiz
13/01/2006
Edilcimar
13/01/2006
Fabiano_aprendiz
14/01/2006
Edilcimar
2)O fato de estar em folha solta ou papel contínuo não muda nada desde que o layout seja o mesmo
3)Você pode ter um botão para imprimir com o QR e outro para o TCanvas
4)Você pode colocar um pagesetupdialog para o usuário escolher o papel antes da impressão
5)Se está saindo direito no primeiro e não no restante, provavelmente é porque o papel não está configurado com o comprimento exato, veja que mesmo 1 mm vai dar diferença
23/01/2006
Fabiano_aprendiz
E usando o WriteLn, como eu faço p/definir a posição dos campos, na vertical e horizontal?
23/01/2006
Edilcimar
25/01/2006
Fabiano_aprendiz
Resolvi fazer um teste com o TPrinter, mas não estou tendo sucesso. Tenho um formulário que também foge aos padrões, o seu comprimento tem + ou - a metade de uma folha A4 portanto o comprimento é menor do que a largura mesmo. To fazendo um teste rápido, aqui segue o código:
IndiceHorizontal := Printer.PageWidth / 1010;
IndiceVertical := Printer.PageHeight / 792;
Printer.Canvas.Font.Name := ´Arial´;
Printer.Orientation := poPortrait;
Printer.BeginDoc;
Printer.Canvas.Font.Size := 10;
Linha := 20;
Table1.Open;
Table1.First;
While not Table1.Eof do
Begin
If Linha = 20 Then
begin
Coluna := Round(150 * IndiceHorizontal);
Printer.Canvas.TextOut(Coluna, Linha, Table1.FieldByName(´Nome´).AsString);
Linha := Linha + Round(20 * IndiceVertical);
Printer.Canvas.TextOut(Coluna, Linha, Table1.FieldByName(´Natureza´).AsString);
Linha := Linha + Round(20 * IndiceVertical);
Printer.Canvas.TextOut(Coluna, Linha, Table1.FieldByName(´Autor´).AsString);
Linha := Linha + Round(20 * IndiceVertical);
Printer.Canvas.TextOut(Coluna, Linha, Table1.FieldByName(´Comarca´).AsString);
Linha := Linha + Round(20 * IndiceVertical);
Printer.Canvas.TextOut(Coluna, Linha, Table1.FieldByName(´Juizo´).AsString);
Linha := Linha + Round(60 * IndiceVertical);
end;
If Linha >= 160 Then
begin
Printer.NewPage;
Linha := 20;
end;
Table1.Next;
End;
Printer.EndDoc;
Table1.Close;
Mas qdo ele da o salto para a proxima página, ele naum para na posição q eu quero, parece q continua saltando como se fosse A4. O que pode ser?
Desde já agradeço.
25/01/2006
Edilcimar
25/01/2006
Fabiano_aprendiz
Desculpe a ignorância, mas como faço p/criar esse pagesetupdialog? Poderia passar algum exemplo?
25/01/2006
Edilcimar
o comando é pagesetupdialog.execute
11/02/2006
Pro-luck
Perdoe-me pela minha ignorância, mas ainda não consegui entender como, através do ÍndiceVertical e do ÍndiceHorizontal, poderei saber a posiçào onde os dados serao impressos... O que siginifica mesmo essas medidas: 960 e 1584...
IndiceHorizontal := Printer.PageWidth / 960;
IndiceVertical := Printer.PageHeight / 1584;
Espero poder contar com a tua colaboração, assim sendo, antecipadamente agradeço...
12/02/2006
Edilcimar
IndiceVertical := Printer.PageHeight / 1584;
estes números eu peguei da ´minha´ impressora, para o tamanho do papel que ´eu´ estou usando, estes valores vão variar de acordo com o tamanho do papel utilizado e de acordo com a resolução, assim sendo, se eu dobrar a resolução da impressora, utilizando o mesmo papel eu teria
IndiceHorizontal := Printer.PageWidth / 1920;
IndiceVertical := Printer.PageHeight / 3168;
se eu modificar o tamanho do papel então deverei modificar estes valores, portanto quando for iniciar o programa pela primeira vez, pegue estes números da sua própria impressora, dê
showmessage(´indice vertical: ´ + inttostr(printer.pageheight) + #13 + 10 + ´indice horizontal: ´ + inttostr(printer.pagewidth), assim vc ficará sabendo quais os valores no seu caso
Estes índices não são para saber ´onde´ o texto será impresso e sim para fazer a compensação de posição quando a resolução for impressa, se vc imprime em uma resolução de 300 x 300 e o seu cliente usa uma impressora com resolução de 1200 x 600, e vc não fizer isto, a impressão na impressora dele vai ficar toda ´encavalada´, ou seja as letras vão ficar amontoadas e ninguém vai conseguir ler nada, se a situação for o inverso, então as linhas vão ficar muito separadas e além de desperdiçar muito papel ainda vai ficar feio
Clique aqui para fazer login e interagir na Comunidade :)