Atualmente, entre as ferramentas de desenvolvimento de software, o Delphi se tornou uma ferramenta de desenvolvimento rápido reconhecida mundialmente devido aos seus diversos controles, fortes funções de programação orientada a objetos, rápida velocidade de execução de código e simplicidade e facilidade de uso, combinadas com um ambiente de desenvolvimento visual e o compilador mais rápido. As ferramentas de desenvolvimento de aplicativos estão sendo usadas por cada vez mais programadores. Você pode usar Delphi para escrever vários aplicativos Windows, especialmente o desenvolvimento de sistemas de gerenciamento de informações de banco de dados, que tem suas vantagens exclusivas. No processo de desenvolvimento do sistema de gerenciamento de informações de banco de dados, muitas vezes precisamos imprimir muitos relatórios. Usar Delphi para projetar relatórios complexos não é tão simples quanto o Visual FoxPRo. No entanto, como os controles também são usados para projetar relatórios no Delphi, podemos criar diretamente os controles de relatório necessários durante a execução do programa para gerar relatórios em tempo real, e a amostra do relatório gerado pode ser determinada pelo controle do programa. Por exemplo, quando consultamos informações do banco de dados, a estrutura das informações dos resultados geralmente não é fixa. Se quisermos imprimir os resultados da consulta, não é suficiente criar apenas um formato de relatório. Devemos projetar um para todas as informações de resultados possíveis. A formatação do relatório também não é uma boa solução. Para resolver tal problema, podemos usar tecnologia de geração de relatórios em tempo real. O objetivo deste artigo é apresentar detalhadamente como gerar relatórios em tempo real através de um exemplo.
Este exemplo criará uma caixa de diálogo de impressão, que inclui o controle TQickRep e alguns controles de estilo de relatório. A aparência de outros formulários é mostrada abaixo:
1. Descrição da função de controle
QuickRep:TQuickRep Inclui bandas de cabeçalho de coluna (HB:TQRBand), detalhes (DB:TQRBand), rodapé (FB:TQRBand), resumo (SB:TQRBand) e não inclui um TQRLabel nos detalhes, rodapé ou resumo, Controle TQRExpr ou TDBText, que são criados principalmente quando o programa é executado. A zona do cabeçalho da coluna inclui Título (TQRLabel) para o título do relatório; TQRLabel é usado para condições de consulta. As propriedades Caption desses dois controles podem ser alteradas arbitrariamente durante a execução do programa. Para evitar que o QuickRep seja exibido, coloque-o atrás do Panel1 (Tpanel) e expanda Panel1 para todo o formulário;
Consulta: controle de instrução SQL TQuery, o programa irá gerar relatórios com base nos resultados retornados pela Consulta. Portanto, ao criar este formulário, você deve especificar uma instrução SQL para a propriedade Query.SQL;
No formulário acima, os controles incluídos nas colunas "Papel" e "Configuração da página" controlam as propriedades QuickRep.Page. Alterá-los quando o programa for executado alterará diretamente os valores das propriedades correspondentes do controle QuickRep. pode ser feito através do evento OnChange ou OnExit concluído;
O título na coluna "Configurações de conteúdo de impressão" é o título do relatório especificado (TT:TEdit). Seu valor é consistente com QuickRep.ReportTitle e Title.Caption e pode ser alterado arbitrariamente na caixa de seleção "Condições de consulta de impressão". se deve imprimir as condições de consulta. Se esta caixa de seleção estiver marcada controla diretamente se QRSQL.Caption está vazio; "Alinhamento de colunas da tabela" consiste em um conjunto de botões de opção É usado principalmente para o alinhamento de conteúdo detalhado ao gerar relatórios. alterar variável de controle RD1 (Byte) valor (0 alinhamento automático, 1 alinhamento central, 2 alinhamento à esquerda); "Largura de impressão da coluna da tabela" consiste em um conjunto de botões de opção, usados principalmente para a largura dos valores das colunas na geração de formatos de relatório e sua alteração. variáveis de controle O valor de RD2 (Byte) (0 largura automática, 1 Mesma Largura, 2 Limite de Largura Máxima), ao selecionar 1 Mesma Largura, 2 Limite de Largura Máxima, é necessário informar a largura em pixels. "Método Estatístico" indica se o relatório inclui rodapé (FB: TQRBAND) e soma (SB); : Zona TQRBAND).
2. Descrição do programa
O programa define os seguintes tipos:
TQRLabelName=matriz de TQRLabel;
TQRDBTextName=matriz de TQRDBText;
TQRShapeName=matriz de TQRShape;
TQRExpName=matriz de TQRExpr;
O tipo acima é um tipo de array dinâmico e cada elemento dos dados é uma classe. Ao criar controles de relatório em tempo real, o número de controles a serem criados é incerto e os nomes dos controles não podem ser determinados. Usar matrizes dinâmicas é uma solução melhor, ou seja, você pode especificar arbitrariamente as dimensões dos dados sem precisar gerenciar a memória. alocação por conta própria. Esse problema também facilita a liberação e o processamento dos controles contidos nos relatórios. O programa também declara variáveis dos tipos acima da seguinte forma:
CHBName:TQRLabelName;
NomeBD:TQRDBTextName;
CHBShape,DBShape,FBShape,SumShape:TQRShapeName;
FBNome,SomaNome:TQRExpNome;
Essas variáveis de array alocarão memória com base nos resultados dos campos retornados pela Consulta quando o formulário for criado.
Processo de execução do programa: Ao criar e exibir o formulário, é estabelecida a operação de inicialização deste formulário. Exiba o valor correspondente da propriedade QuickRep.Page no evento OnCreate, execute a operação Query.Open no evento OnShow e aloque o espaço variável da matriz de controle de acordo com o resultado do retorno. Após a criação do formulário, clique no botão “Gerar” para gerar o relatório (ignorando o campo de memorando e o campo de foto) e a seguir clique em “Imprimir” e “Visualizar” para imprimir ou visualizar o relatório. Quando as configurações forem alteradas após a geração do relatório, o relatório deverá ser gerado novamente. Se o conjunto de resultados retornado pela Consulta tiver muitos campos, o tamanho do papel pode não ser suficiente para gerar todos os relatórios ao gerar o relatório. Você pode ajustar o tamanho do papel do relatório e depois gerar o relatório. Quando o formulário é fechado, os controles criados são liberados.
3. Lista e comentários do programa fonte
unidade PrintDlg;
interface
usa
Windows, Mensagens, SysUtils, Classes, Gráficos, Controles, Formulários, Diálogos,
StdCtrls, Botões, ExtCtrls, Spin, QuickRpt, QRPrntr, impressoras, Qrctrls,
Db,DBTables,ComCtrls,SysIni;
tipo
TQRLabelName=array de TQRLabel;//matriz dinâmica de classes de controle de título de coluna na faixa de cabeçalho de coluna
TQRDBTextName=array de TQRDBText; //Matriz dinâmica de controles de título de coluna na faixa de detalhes
TQRShapeName=array de TQRShape; //Array dinâmico de peças de controle de linha
TQRExpName=matriz de TQRExpr; //matriz dinâmica da classe de controle estatístico
TPrintForm = classe(TForm)
GroupBox1: TGroupBox;
Rótulo5: TLabel;
BtnSet: TbitBtn;//controle do botão "Configurações"
BtnCancel: TBitBtn; // controle do botão "Fechar"
Painel1: TPanel;
BtnPrint: TBitBtn; // controle do botão "Imprimir"
BtnPrview: TBitBtn; // botão "Visualizar"
QuickRep: TQuickRep; // Controle rápido de relatório
HB: TQRBand; // controle de banda "cabeçalho da coluna"
Título: TQRLabel;//Controle de título do relatório
QRE1: TQRExpr;//controle "Número da página" na faixa do cabeçalho da coluna
QRE2: TQRExpr;//controle "Data" na faixa do cabeçalho da coluna
Painel2: TPanel;
Rótulo1: TLabel;
R1: TRadioButton;//controle "Impressão Retrato"
R2: TRadioButton;//controle de "impressão horizontal"
GroupBox4: TGroupBox;
TT: TEdit; //Controle da caixa de entrada de título
Etiqueta2: TLabel;
SR: TCheckBox; // controle "Imprimir condições de consulta"
Rótulo3: TLabel;
Image1: TImage;//Exibir imagem de impressão vertical
Image2: TImage; //Exibe imagem de impressão horizontal
QRSQL: TQRLabel; // Utilizado para exibir o controle "Condição de Consulta" na faixa do cabeçalho da coluna
GroupBox2: TGroupBox;
Rótulo7: TLabel;
Rótulo8: TLabel;
Rótulo9: TLabel;
Rótulo10: TLabel;
Rótulo11: TLabel;
Rótulo12: TLabel;
Rótulo13: TLabel;
PageSpace: TEdit; // controle da caixa de entrada de espaçamento de colunas
PageTop: TEdit; // Controle da caixa de entrada na margem da página
PageBottom: TEdit; //Controle da caixa de entrada na margem da página
PageLeft: TEdit; // controle da caixa de entrada esquerda da página
PageRight: TEdit; // controle da caixa de entrada direita da margem da página
PageDlux: TCheckBox; // controle "Impressão frente e verso"
PageCol: TEdit; // controle da caixa de entrada da coluna
Páginas: TEdit; // Imprime o controle da caixa de entrada do número
PaperH: TEdit; // Controle da caixa de entrada do comprimento do papel
PaperW: TEdit; //Controle da caixa de entrada da largura do papel
Etiqueta4: TLabel;
Rótulo6: TLabel;
Ps: TComboBox; //Controle da caixa de listagem de modelos de papel
Consulta: TQuery; //controle de consulta SQL
DB: TQRBand; // controle de banda "Detalhes"
CrtRep: TBitBtn; // controle do botão "Gerar"
Rótulo14: TLabel;
Rótulo15: TLabel;
Painel3: TPanel;
Wdauto: TRadioButton; // controle "Largura automática"
Wdall: TRadioButton; // controle "Mesma largura"
Wdmax: TRadioButton; // controle "Limite à largura"
Rótulo16: TLabel;
ColWd: TEdit; // controle da caixa de entrada da largura da coluna
Painel4: TPanel;
DJAUTO: TRadioButton; // controle de "alinhamento automático"
DJCENTER: TRadioButton; // controle "Centro"
DJLEFT: TRadioButton; // controle "Alinhar à esquerda"
FB: TQRBand; // Controle de banda de rodapé;
Rótulo17: TLabel;
Painel5: TPanel;
TJ1: TCheckBox; // controle "Estatísticas por página"
TJ2: TCheckBox; // controle "Soma estatística"
SB: TQRBand // Soma controle de banda;
procedimento FormCreate(Remetente: TObject);
procedimento RadioButtonClick(Remetente: TObject);
procedimento PageDluxClick(Remetente: TObject);
procedimento PageColChange(Remetente: TObject);
procedimento PageSpaceExit(Remetente: TObject);
procedimento PagesChange(Remetente: TObject);
procedimento PageTopExit(Remetente: TObject);
procedimento PageBottomExit(Remetente: TObject);
procedimento PageLeftExit(Remetente: TObject);
procedimento PageRightExit(Remetente: TObject);
procedimento TTExit(Remetente: TObject);
procedimento DTClick(Remetente: TObject);
procedimento BtnPrviewClick(Remetente: TObject);
procedimento BtnSetClick(Remetente: TObject);
procedimento PsChange(Remetente: TObject);
procedimento PaperChange(Remetente: TObject);
procedimento FormClose(Sender: TObject; var Action: TCloseAction);
procedimento FormDestroy(Remetente: TObject);
procedimento CreateReport(Remetente: TObject);
procedimento SRClick(Remetente: TObject);
procedimento ClearRep();
procedimento FormShow(Remetente: TObject);
procedimento PaperSizeChg(Remetente: TObject);
procedimento DJChage(Remetente: TObject);
procedimento WdChage(Remetente: TObject);
procedimento QuickRepStartPage(Remetente: TCustomQuickRep);
procedimento BtnPrintClick(Remetente: TObject);
privado
{Declarações privadas}
CHBName:TQRLabelName;//Define o nome do controle da faixa do cabeçalho da coluna nome do array dinâmico
DBName:TQRDBTextName; //Define o nome da matriz dinâmica do nome do controle da banda detalhada
CHBShape,DBShape,FBShape,SumShape:TQRShapeName; //Define o nome do array dinâmico do controle de linha
FBName,SumName:TQRExpName; //Define o nome do array dinâmico dos nomes de controle do rodapé (FBNAME) e da banda de soma (SUMNAME).
DJ:TAlignment;//Alinhamento da coluna (taLeftJustify, taRightJustify, taCenter)
Rd1, Rd2:Byte; //Usado para salvar o alinhamento das colunas da tabela (RD1) e a largura de impressão (RD2) dos nomes das variáveis de status
público
{Declarações públicas}
CXTJ,BT:String;//CXTJ armazena condições de consulta, BT armazena títulos de relatórios
//Especificado pelo formulário de nível superior
fim;
const
PaperSize:array[0..26] de TQRPaperSize=(A3, A4, A4Small, A5, B4, B5, Letter,
LetterSmall, Tabloid, Ledger, Legal, Statement, Executive, Folio,
Quarto, qr10X14, qr11X17, Nota, Env9, Env10, Env11, Env12,
Env14, CSheet, DSheet, ESheet, Personalizado);
//Tipos de papel listados pelo QuickRep
var
ImprimirForm: TPrintForm;
implementação
{$R *.DFM}
procedimento TPrintForm.FormCreate(Sender: TObject);
//Exibe a propriedade QuickRep.Page e outros valores de propriedade
var
Eu: Byte;
começar
PageCol.Text:=IntToStr(QuickRep.Page.Columns);
PageSpace.Text:=FormatFloat('0.00',QuickRep.Page.ColumnSpace);
PageTop.Text:=FormatFloat('0.00',QuickRep.Page.TopMargin);
PageBottom.Text:=FormatFloat('0.00',QuickRep.Page.BottomMargin);
PageLeft.Text:=FormatFloat('0.00',QuickRep.Page.LeftMargin);
PageRight.Text:=FormatFloat('0.00',QuickRep.Page.RightMargin);
PageSpace.Text:=FormatFloat('0.00',QuickRep.page.ColumnSpace);
R1.Checked:=QuickRep.Page.Orientation=poPortrait;
Imagem1.Visível:=R1.Verificado;
R2.Checked:=QuickRep.Page.Orientation=poLandscape;
Imagem2.Visível:=R2.Verificado;
PageDlux.Checked:=QuickRep.PrinterSettings.Duplex;
Pages.Text:=IntToStr(QuickRep.PrinterSettings.Copies);
PaperH.Text:=FormatFloat('0.00',QuickRep.Page.Length);
PaperW.Text:=FormatFloat('0.00',QuickRep.Page.Width);
Para I:=0 a 26 do //PS a caixa de listagem exibe o tipo de papel
se QuickRep.Page.PaperSize=PaperSize[I] então comece
PS.ItemIndex:=I;
Quebrar;
fim;
//Determina se a largura do papel pode ser alterada. Só pode ser alterado se o tipo de papel for personalizado (Ps.ItemIndex=26)
PapelH.Enabled:=Ps.ItemIndex=26;
PaperW.Enabled:=Ps.ItemIndex=26;
fim;
procedimento TPrintForm.RadioButtonClick(Sender: TObject);
//Manipulação de eventos de mudança de orientação do papel
var
S:Corda;
começar
Imagem1.Visível:=R1.Verificado;
Imagem2.Visível:=R2.Verificado;
se R1.Checked então
QuickRep.Page.Orientation:=poPortrait
outro
QuickRep.Page.Orientation:=poLandscape;
//Troca os valores de largura e comprimento do papel
S:=PapelH.Texto;
PapelH.Text:=PapelW.Text;
PapelW.Text:=S;
se (Ps.ItemIndex=26) ou (Ps.ItemIndex=0) então comece
QuickRep.Page.Width:=StrToFloat(PaperW.Text);
QuickRep.Page.Length:=StrToFloat(PaperH.Text);
fim;
fim;
procedimento TPrintForm.PageDluxClick(Remetente: TObject);
começar
QuickRep.PrinterSettings.Duplex:=PageDlux.Checked;
fim;
procedimento TPrintForm.PageColChange(Remetente: TObject);
começar
se StrToInt(PageCol.Text)<1 então PageCol.Text:='1';
QuickRep.Page.Columns:=StrToInt(PageCol.Text);
fim;
procedimento TPrintForm.PageSpaceExit(Remetente: TObject);
começar
QuickRep.Page.ColumnSpace:=StrToFloat(PageSpace.Text);
fim;
procedimento TPrintForm.PagesChange(Remetente: TObject);
começar
se StrToInt(Pages.Text)<1 then Pages.Text:='1';
QuickRep.PrinterSettings.Copies:=StrToInt(Pages.Text);
fim;
procedimento TPrintForm.PageTopExit(Remetente: TObject);
começar
QuickRep.Page.TopMargin:=StrToFloat(PageTop.Text);
fim;
procedimento TPrintForm.PageBottomExit(Remetente: TObject);
começar
QuickRep.Page.BottomMargin:=StrToFloat(PageBottom.Text);
fim;
procedimento TPrintForm.PageLeftExit(Remetente: TObject);
começar
QuickRep.Page.LeftMargin:=StrToFloat(PageLeft.Text);
fim;
procedimento TPrintForm.PageRightExit(Remetente: TObject);
começar
QuickRep.Page.RightMargin:=StrToFloat(PageRight.Text);
fim;
procedimento TPrintForm.TTExit(Sender: TObject); // Tratamento de eventos de mudança de título
começar
QuickRep.ReportTitle:=TT.Text;
Título.Caption:=TT.Texto;
Bt:=TT.Texto;
fim;
procedimento TPrintForm.DTClick(Sender: TObject); //Imprime evento de caixa de seleção de condição de consulta
começar
QRSQL.Enabled:=SR.Verificado;
fim;
procedimento TPrintForm.BtnPrviewClick(Sender: TObject); //Visualizar evento de clique do botão
começar
QuickRep.Preview;
fim;
procedimento TPrintForm.BtnSetClick(Sender: TObject); //Definir evento de clique do botão
começar
QuickRep.PrinterSetup;
fim;
procedimento TPrintForm.PsChange(Sender: TObject);//Evento de mudança de tipo de papel
começar
QuickREp.Page.PaperSize:=PaperSize[Ps.ItemIndex];
PaperH.Text:=FormatFloat('0.00',QuickRep.Page.Length);
PaperW.Text:=FormatFloat('0.00',QuickRep.Page.Width);
PapelH.Enabled:=Ps.ItemIndex=26;
PaperW.Enabled:=Ps.ItemIndex=26;
CrtRep.Enabled:=Verdadeiro;
BtnPrint.Enabled:=não CrtRep.Enabled;
BtnPrview.Enabled:=BtnPrint.Enabled;
fim;
procedimento TPrintForm.PaperChange(Sender: TObject);//Eventos de alteração de largura e comprimento do papel
começar
QuickRep.Page.Width:=StrToFloat(PaperW.Text);
QuickRep.Page.Length:=StrToFloat(PaperH.Text);
fim;
procedimento TPrintForm.FormClose(Sender: TObject; var Action: TCloseAction);
começar
Ação:=caFree;
fim;
procedimento TPrintForm.FormDestroy(Sender: TObject);
começar
ClearRep;
ImprimirFormulário:=nil;
fim;
procedimento TPrintForm.CreateReport(Sender: TObject); //Gera evento de clique de botão
Var
Eu,L:Byte;
CHBtp,CHBlf,Cd,ObWidth:Palavra;
começar
Screen.Cursor:=crHourGlass;
Title.Caption:=Bt;//Defina o título
ClearRep(); //Limpa o objeto criado;
if Sr.Checked then QrSQL.Caption:=CXTJ else QRSQL.Caption:=';//Se deseja imprimir as condições da consulta?
CHBtp:=HB.Height-17;//A posição superior do controle criado na banda
CHBlf:=0; //O controle criado está na posição esquerda da banda
ObWidth:=0; //A largura do controle criado
for I := 0 to Query.FieldCount-1 do //Cria um controle baseado no número de campos retornados pela Query
começar
se (Query.Fields[I].DataType<>ftBlob) E (Query.Fields[I].DataType<>ftMemo) então
começar //Ignora o campo de nota e o campo de foto
L:=Query.Fields[I].DataSize-1;//L=largura do campo (bytes)-1
case Rd1 of //Define o alinhamento do controle de acordo com o alinhamento selecionado
0: se L<=10 então Dj:=taCenter else DJ:=taLeftJustify;
//Alinhamento automático: Campos menores ou iguais a 10 são alinhados no centro, caso contrário alinhados à esquerda
1: Dj:=taCenter;//alinhamento central
2: DJ:=taLeftJustify;//Alinhamento à esquerda
fim;
case Rd2 of //Define a largura da coluna do relatório de acordo com a largura da lista selecionada
0: começar
//Largura automática: se L>14 então largura ObWidth=14+(L-14)/2;
//A largura não pode exibir os títulos das colunas, então ObWidth=largura do título da coluna se o tipo de campo;
//Para tipo de data, tipo de moeda e tipo de número de ponto flutuante, ObWidth=65
se L>14 então L:=14+(L-14) div 2;
ObLargura:=L*6;
L:=Comprimento(Query.Fields[I].DisplayName);
se ObWidth<L*6 então ObWidth:=L*6;
ObLargura:=LarguraOb+2;
if (Query.Fields[I].DataType=ftDateTime) ou
(Query.Fields[I].DataType=ftFloat) ou
(Query.Fields[I].DataType=ftCurrency) então ObWidth:=65;
fim;
1: se ColWd.Text<>' então ObWidth:=StrToInt(ColWd.Text)
else ObWidth:=100;//Mesma largura:ObWidth=valor da largura de entrada
2: começar //Limite a largura máxima: primeiro calcule a largura automática e depois determine se a largura excede o valor máximo.
//Se exceder ObWidth=valor de entrada de largura máxima
se ColWd.Text<>' então Cd:=StrToInt(ColWd.Text)
senão Cd:=200;
ObLargura:=L*6;
se ObWidth>Cd então ObWidth:=Cd;
ObLargura:=LarguraOb+2;
if (Query.Fields[I].DataType=ftDateTime) ou
(Query.Fields[I].DataType=ftFloat) ou
(Query.Fields[I].DataType=ftCurrency) então ObWidth:=65;
fim;
fim;
se CHBlf+ObWidth>=HB.Width então comece //Criar controle>largura do papel?
DlgMes:='A largura do papel não é suficiente, altere o tamanho do papel. ';
MessageBox(Handle,DlgMes,Cap_Inf,Ico_Inf);
quebrar;
fim
senão começar
CHBShape[I]:=TQRShape.Create(HB);//Cria controle de linha de faixa de cabeçalho de coluna
CHBSforma[I].Parent:=HB;
CHBSForma[I].Topo:=CHBtp;
CHBSforma[I].Esquerda:=CHBlf;
CHBSForma[I].Largura:=ObLargura+1;
CHBSForma[I].Altura:=17;
CHBNAME[I]:=TQRLabel.Create(HB); //Criar controle de título da coluna
CHBNAME[I].Parent:=HB;
CHBNAME[I].Topo:=CHBtp+2;
CHBNAME[I].Esquerda:=CHBlf+1;
CHBNAME[I].AutoSize:=Falso;
CHBNAME[I].Largura:=ObLargura-1;
CHBNAME[I].Alinhamento:=taCenter;
CHBNAME[I].Caption:=Query.Fields[I].DisplayName;//Obtém o campo como o nome da coluna
CHBNAME[I].BringToFront;
DBShape[I]:=TQRShape.Create(DB); //Criar controle de linha de faixa de detalhes
DBShape[I].Parent:=DB;
DBShape[I].Topo:=-1;
DBShape[I].Esquerda:=CHBlf;
DBShape[I].Largura:=ObLargura+1;
DBShape[I].Altura:=17;
DBNAME[I]:=TQRDBText.Create(DB); //Cria controle de banda detalhada
DBNAME[I].Parent:=DB;
DBNAME[I].ParentReport:=QuickRep;
DBNAME[I].Topo:=2;
DBNAME[I].Esquerda:=CHBlf+2;
DBNAME[I].AutoSize:=Falso;
DBNAME[I].Largura:=ObLargura-3;
DBNAME[I].Altura:=13;
DBNAME[I].Alinhamento:=Dj;
DBNAME[I].DataSet:=Consulta;
DBNAME[I].DataField:=Query.Fields[I].FieldName;
DBNAME[I].BringToFront;
if Tj1.Checked then begin //Deseja criar uma faixa de rodapé?
FBShape[I]:=TQRShape.Create(FB); //Cria controle de linha de banda de rodapé
FBShape[I].Parent:=FB;
FBShape[I].Topo:=0;
FBShape[I].Esquerda:=CHBlf;
FBShape[I].Largura:=ObLargura+1;
FBShape[I].Altura:=17;
if (Query.Fields[I].DataType=ftFloat) ou
(Query.Fields[I].DataType=ftCurrency) ou (I<2) então
Begin //Se o tipo de campo for numérico, crie-o
FBNAME[I]:=TQRExpr.Create(FB); //Cria controle de banda de rodapé
FBNAME[I].Parent:=FB;
FBNAME[I].ParentReport:=QuickRep;
FBNAME[I].Topo:=3;
FBNAME[I].Esquerda:=CHBlf+2;
FBNAME[I].AutoSize:=Falso;
FBNAME[I].Largura:=ObLargura-3;
FBNAME[I].Altura:=13;
FBNAME[I].Alinhamento:=taCenter;
FBNAME[I].Expression:='SUM(QUERY.'+Query.Fields[I].FieldName+')';
FBNAME[I].BringToFront;
fim;
fim;
if Tj2.Checked then begin //Devemos estabelecer a banda de soma?
SumShape[I]:=TQRShape.Create(SB); //Cria um controle de linha de soma
SomaForma[I].Parent:=SB;
SomaForma[I].Topo:=0;
SomaForma[I].Esquerda:=CHBlf;
SomaForma[I].Largura:=ObLargura+1;
SomaForma[I].Altura:=17;
if (Query.Fields[I].DataType=ftFloat) ou
(Query.Fields[I].DataType=ftCurrency) ou (I<2) então
Begin //Se o tipo de campo for numérico, crie-o
SumNAME[I]:=TQRExpr.Create(SB); //Cria controle de banda de soma
SomaNOME[I].Parent:=SB;
SomaNOME[I].ParentReport:=QuickRep;
SomaNOME[I].Topo:=3;
SomaNOME[I].Esquerda:=CHBlf+2;
SomaNOME[I].AutoSize:=Falso;
SomaNOME[I].Largura:=ObLargura-3;
SomaNOME[I].Altura:=13;
SomaNOME[I].Alignment:=taCenter;
SomaNOME[I].Expressão:='SUM(QUERY.'+Query.Fields[I].NomeCampo+')';
SomaNOME[I].BringToFront;
fim;
fim;
CHBlf:=CHBlf+ObWidth;//O processamento do campo atual é concluído, uma largura de campo à direita
fim;
fim;
fim;
CrtRep.Enabled:=False;//Desativa o botão de geração
BtnPrint.Enabled:=not CrtRep.Enabled;Permitir impressão de botões de amônio
BtnPrview.Enabled:=BtnPrint.Enabled;Permitir botão de visualização
if Tj1.Checked then begin //Se uma faixa de rodapé for criada, altere as duas primeiras colunas da faixa de rodapé
FBNAME[0].Expressão:=''Total de páginas'';
FBNAME[1].Expressão:='COUNT+'linha'';
fim;
if Tj1.Checked then begin //Se a banda de soma for estabelecida, altere as duas primeiras colunas da banda de soma
SomaNOME[0].Expressão:=''Total'';
SomaNOME[1].Expressão:='COUNT+'linha'';
fim;
//Ajusta a posição de impressão da data e do número da página na zona do cabeçalho da coluna
QRE2.Esquerda:=HB.Largura-Qre2.Largura;
QRSQL.Esquerda:=QRE1.Largura+10;
QRSQL.Largura:= QRE2.Left-10-QRSQL.Left;
QuickRep.DataSet:=Query; //Especifique o conjunto de dados para QuickRep, esta frase não deve faltar
Screen.Cursor:=crDefault;
fim;
procedure TPrintForm.ClearRep();//Limpa o controle criado ao gerar o formato do relatório
Var
Eu: Byte;
começar
Para I:=0 para Query.FieldCount-1 comece
se Atribuído(CHBShape[I]) então comece CHBShape[I].Free;CHBShape[I]:=nil;end;
se atribuído(CHBNAME[I]) então comece CHBNAME[I].Free;CHBNAME[I]:=nil;end;
se Assigned(DBShape[I]) então comece DBShape[I].Free;DBShape[I]:=nil;end;
se atribuído(DBNAME[I]) então comece DBNAME[I].Free;DBNAME[I]:=nil;end;
se Atribuído(FBShape[I]) então comece FBShape[I].Free;FBShape[I]:=nil;end;
se atribuído(FBNAME[I]) então comece FBNAME[I].Free;FBNAME[I]:=nil;end;
if Assigned(SumShape[I]) então comece SumShape[I].Free;SumShape[I]:=nil;end;
if Assigned(SumNAME[I]) então comece SumNAME[I].Free;SumNAME[I]:=nil;end;
fim;
fim;
procedimento TPrintForm.SRClick(Remetente: TObject);
começar
se Sr.Checked então QrSQL.Caption:=CXTJ senão QRSQL.Caption:=';
fim;
procedimento TPrintForm.FormShow(Sender: TObject); //Evento de exibição do formulário
começar
Query.Active:=True;//Imprime SQL
TT.Texto:=Bt;
QuickRep.ReportTitle:=Bt;//Definir o título
//Array de nome de controle aloca espaço
SetLength(CHBNAME,Query.FieldCount);
SetLength(CHBShape,Query.FieldCount);
SetLength(DBNAME,Query.FieldCount);
SetLength(DBShape,Query.FieldCount);
SetLength(FBNAME,Query.FieldCount);
SetLength(FBShape,Query.FieldCount);
SetLength(SumNAME,Query.FieldCount);
SetLength(SumShape,Query.FieldCount);
fim;
procedimento TPrintForm.PaperSizeChg(Remetente: TObject);
começar
CrtRep.Enabled:=Verdadeiro;
BtnPrint.Enabled:=não CrtRep.Enabled;
BtnPrview.Enabled:=BtnPrint.Enabled;
fim;
procedimento TPrintForm.DJChage(Sender: TObject);//Manipulação de evento de mudança de alinhamento
var
Alterar:Byte;
começar
se Djauto.Checked então Chg:=0
senão se DjCenter.Checked então Chg:=1
senão Alterar:=2;
se Chg<>Rd1 então comece PaperSizeChg(nil);Rd1:=Chg;end;
fim;
procedimento TPrintForm.WdChage(Sender: TObject); // Manipulação de eventos de mudança de largura
var
Alterar:Byte;
começar
se Wdauto.Checked então Chg:=0
senão se Wdall.Checked então comece
Variável:=1;
se ColWd.Text=' então ColWd.Text:='100';
fim
senão começar
Alterar:=2;
se ColWd.Text=' então ColWd.Text:='200';
fim;
se Chg<>Rd2 então comece PaperSizeChg(nil);Rd2:=Chg;end;
ColWd.Enabled:=Alterar<>0;
fim;
procedimento TPrintForm.QuickRepStartPage(Remetente: TCustomQuickRep);
//A impressão do relatório inicia o processamento de eventos de nova página e os valores estatísticos na faixa do rodapé são apagados.
Var
Eu: Byte;
começar
se Tj1.Checked então
Para I:=0 para Query.FieldCount-1 faça
se atribuído (FBNAME[I]) então FBNAME[I].Reset;
fim;
procedimento TPrintForm.BtnPrintClick(Remetente: TObject);
começar
Impressão Rápida;
fim;
fim.
4. Exemplo de caixa de diálogo de chamada:
Primeiro, inclua a unidade PrintDlg na instrução USES no formato a ser chamado e, em seguida, chame-a com o seguinte código:
se não for atribuído (PrintForm), então PrintForm:=TPrintForm.Create(application);
PrintForm.Query.SQL.Assign(Query.SQL);
//Se o formulário de chamada não contém um controle Query, você pode definir diretamente o valor da instrução SQL
PrintForm.Bt:=Título do relatório;
PrintForm.Caption:=Título do formulário;
PrintForm.CXTJ:=condições de consulta;
PrintForm.ShowModal;
5. Conclusão
A chave deste programa é o processo de evento CreateReport e o processamento de nomes de controle dinâmico. Devido ao espaço limitado, alguns conteúdos não são explicados e espero que os leitores possam entendê-los por si próprios. Para geração de relatórios gerais, este programa pode atender aos requisitos.
Tenho a versão mais recente, que tem funções mais fortes. Amigos que precisarem podem me enviar um e-mail e com certeza enviarei.