Mudanças entre as edições de "Bibliotecas Gráficas"
(→Abrindo o formulário pelo menu do unilab) |
(→Incluindo ícones na tela e salva tela) |
||
(20 revisões intermediárias pelo mesmo usuário não estão sendo mostradas) | |||
Linha 1 161: | Linha 1 161: | ||
[[Arquivo:Uses.png]] | [[Arquivo:Uses.png]] | ||
− | Agora podemos programar a parte de abrir o formulário, volte no componente de menu da ufmain, e de dois cliques na nova opção de menu adicionada, neste caso a nova opção será 'Exemplo'. Após dar duplo click, irá criar uma função e será direcionada pra ela, nessa função basta colocar a seguinte chamada | + | Agora podemos programar a parte de abrir o formulário, volte no componente de menu da ufmain, e de dois cliques na nova opção de menu adicionada, neste caso a nova opção será 'Exemplo'. Após dar duplo click, irá criar uma função e será direcionada pra ela, nessa função basta colocar a seguinte chamada: |
+ | - ChamaForm(TFExemploRel); | ||
− | - | + | Com isso, a chamada do form já deverá funcionar. |
+ | |||
+ | ===Incluindo ícones na tela e salva tela=== | ||
+ | |||
+ | - procedure TFExemploRel.FormCreate(Sender: TObject); | ||
+ | - begin | ||
+ | - SalvaTela.Load; | ||
+ | - colocarImagemNoBotao(bImprimir, 'bt_imprime'); | ||
+ | - colocarImagemNoBotao(bFechar, 'bt_fecha'); | ||
+ | - colocarImagemNoBotao(btnPlanilha, 'bt_planilha_relatorios'); | ||
+ | - end; | ||
+ | |||
+ | Este é o resultado: | ||
+ | |||
+ | [[Arquivo:Resufinal.png]] | ||
+ | |||
+ | Para usar o salva tela é preciso definir a propriedade UDatabase: FMain.UDB e Useg:FMain.USeg. | ||
+ | - procedure TFExemploRel.FormDestroy(Sender: TObject); | ||
+ | - begin | ||
+ | - SalvaTela1.Save; | ||
+ | - end; | ||
+ | |||
+ | ===Montando a query=== | ||
+ | Neste ponto iniciaremos os primeiros passos para buscar as informações que apresentaremos no relatório. Será preciso criar uma procedure que ficará responsável por rodar o select. Exemplo: | ||
+ | - procedure TFExemploRel.MontaQuery; | ||
+ | - begin | ||
+ | - Q.SQL.Clear; | ||
+ | - Q.SQL.Text:= 'SELECT XA.CCODIXANDE, '+ | ||
+ | - ' CDESCXANDE, '+ | ||
+ | - ' ESEXO, '+ | ||
+ | - ' DDATANASC, '+ | ||
+ | - ' ULIBUINC, '+ | ||
+ | - ' CCODIQLD, '+ | ||
+ | - ' CDESCQLD, '+ | ||
+ | - ' NPTS '+ | ||
+ | - ' FROM LB_XANDE2 XA '+ | ||
+ | - 'LEFT JOIN LB_QLDXANDE QLD ON XA.CCODIXANDE = QLD.CCODIXANDE '+ | ||
+ | - ' WHERE TRUE '+ | ||
+ | - slcCadastros.getSQLText + | ||
+ | - IfStr((SEXO.ItemIndex > 0),'AND ESEXO = :ESEXO','') + | ||
+ | - ' AND DDATANASC BETWEEN :DATAINI AND :DATAFIM '+ | ||
+ | - ' ORDER BY '; | ||
+ | - if(ESEXO.ItemIndex > 0) then begin | ||
+ | - Q.GraveParametro('ESEXO', copy(ESEXO.Items[ESEXO.ItemIndex],1,1),ftString); | ||
+ | - end; | ||
+ | - Q.GraveParametro('DATAINI',DDATANASCIni.Text,ftDateTime); | ||
+ | - Q.GraveParametro('DATAFIM',DDATANASCFim.Text,ftDateTime); | ||
+ | - | ||
+ | - if (cbxOrdem.Combo.ItemIndex = 1) then begin | ||
+ | - Q.SQL.Text := Q.SQL.Text + 'CDESCXANDE '; | ||
+ | - end else begin | ||
+ | - Q.SQL.Text := Q.SQL.Text + 'CCODIXANDE'; | ||
+ | - end; | ||
+ | - | ||
+ | - Q.SQL.Text := Q.SQL.Text + ifStr(cbxOrdem.Descendente, ' DESC', ''); | ||
+ | - end; | ||
+ | |||
+ | *Explicando a função | ||
+ | ** Q.SQL.Clear; - Limpa a propriedade SQL e evita a execução da query com lixo. | ||
+ | ** slcCadastros.getSQLText - é o nosso TSelectBoxCaller, essa propriedade getSQLText trata as opções selecionados para serem usadas em um select, então ela vem com um AND e depois as opções, por isso colocamos este WHERE TRUE para que na execução fique WHERE TRUE AND opções e não WHERE AND opções. | ||
+ | ** IfStr() - essa função ela compara se o primeiro parâmetro é verdadeiro, caso seja retorna o segundo parâmetro, do contrário retorna o terceiro. Ou seja, no exemplo se o index selecionado no combobox for maior que 0, ele adiciona a condição AND SEXO = alguma coisa no where. '''Para utilizar o IfStr deve ser incluído UStringUtil na uses.''' | ||
+ | ** GraveParametro() - No select temos :SEXO, :DATAINI e :DATAFIM, o GraveParametro serve para substituir esses textos pelo valor do segundo parametro da função. Então em um exemplo de data, o Graveparamentro vai buscar o texto DATAINI(no select) e substituir pelo nosso dataedit(segundo parametro da função GraveParametro) o terceiro parametro é o tipo de dado. '''Para utilizar o ftString ou ftDatetime, deve ser dado uses na Data.DB''' | ||
+ | |||
+ | ===Gerando PDF=== | ||
+ | Os relatórios do unilab são separados em colunas, por isso antes de iniciar a montagem do relatório precisamos criar as colunas que serão utilizadas. As colunas são do tipo TSuRColumn, então para criá-las precisa dar uses na clase UTSuRPage. Precisamos também de uma variável para controlar o número da página, armazenar a data de hoje e o nome do laboratório, para orelatório de exemplo a declaração ficou assim: | ||
+ | |||
+ | [[Arquivo:Declaracao.png]] | ||
+ | |||
+ | Toda pagina ela tem um valor fixo 100000 de uma margem a outra. Então, por padrão, o unilab define uma margem de 5 mil em cada um dos lados; por isso, pode ser criado duas constantes uma para definir a margem em 5 mil e outra para definir o fim da página em 95 mil, pois assim chegando em 95 mil é gerado uma nova pagina. | ||
+ | |||
+ | Para gerar o relatório precisamos de 4 eventos do TSuReportData: RDStartReport, RDPage, RDNewPage, RDEndPage. | ||
+ | * RDStartReport | ||
+ | - procedure TFRelXande.RDStartReport(Sender: TObject); | ||
+ | - var | ||
+ | - vPos: integer; | ||
+ | - begin | ||
+ | - FPagina:= 1; | ||
+ | - FDataImpressao:= Now; | ||
+ | - FNomeLaboratorio:= ConfigSis('CADLABORATORIO'); | ||
+ | - | ||
+ | - RD.EndPosition := INICIO_RODAPE; | ||
+ | - vPos:= MARGEM; | ||
+ | - colXANDE:= RD.NewColumn(vPos,10000,rpLeft); Inc(vPos,10500); | ||
+ | - colDesc:= RD.NewColumn(vPos,43000,rpLeft); Inc(vPos,43500); | ||
+ | - colSexo:= RD.NewColumn(vPos,5000,rpLeft); Inc(vPos,5500); | ||
+ | - colDataNas:= RD.NewColumn(vPos,20000,rpLeft); Inc(vPos,20500); | ||
+ | - colUsuario:= RD.NewColumn(vPos,10000,rpLeft); | ||
+ | - end; | ||
+ | |||
+ | Este é o primeiro evento a ser disparado, por isso deixamos as coisas iniciais nesta função. | ||
+ | |||
+ | 1º FPagina recebe 1 para identificarmos que é a primeira pagina do relatório. | ||
+ | |||
+ | 2º FDataImpressao recebe a data atual, para utilizarmos no rodapé do relatório no texto "Impresso em...." | ||
+ | |||
+ | 3º FNomeLaboratorio recebe o nome direto defino em Cadastros > Configurações > Sistema. '''Para utilizar a função ConfigSis() deve incluir UConfigSis na uses''' | ||
+ | |||
+ | 4º RD.EndPosition recebe os 95 mil, sinalizando ao componente que quando chegar nessa marca deve ser gerado uma nova pagina. | ||
+ | |||
+ | 5º vPos recebe os 5 mil da Margem, para definirmos as posições das colunas. | ||
+ | |||
+ | A primeira coluna é a colXande ela vai ser criado iniciando na posição 5 mil, com 10000 de espaçamento e seu texto ficará alinhado a esquerda. Após ser criada essa coluna, executamos um Inc adicionando 10500 na vPos que vale 5 mil. Ou seja a próxima coluna vai iniciar com um espaçamento de 500 da coluna anterior. Visualizando: | ||
+ | |||
+ | [[Arquivo:exemploRelatorio.png]] | ||
+ | |||
+ | * RDPage | ||
+ | - procedure TFExemploXande.RDPage(Sender: TObject); | ||
+ | - var | ||
+ | - vPosicao: Integer; | ||
+ | - vCodigoAtual: string; | ||
+ | - begin | ||
+ | - RD.StartGroup(0,RD.NextGroup,False); | ||
+ | - vCodigoAtual := Q.AsString('CCODIXANDE'); | ||
+ | - while (not Q.Eof) and (not RD.Aborted) do begin | ||
+ | - RD.TextColumn(colXANDE,RD.NextLine, Q.AsString('CCODIXANDE')); | ||
+ | - RD.TextColumn(colDesc,RD.CurrentLine, Q.AsString('CDESCXANDE')); | ||
+ | - RD.TextColumn(colSEXO,RD.CurrentLine, Q.AsString('ESEXO')); | ||
+ | - RD.TextColumn(colDataNas,RD.CurrentLine, Q.AsString('DDATANASC')); | ||
+ | - RD.TextColumn(colUsuario,RD.CurrentLine, Q.AsString('ULIBUINC')); | ||
+ | - if(Q.AsString('CCODIQLD') <> '')then begin | ||
+ | - RD.FontStyle([fsBold]); | ||
+ | - RD.TextColumn(colDesc,RD.NextLine, 'Qualidades:'); | ||
+ | - RD.FontStyle([]); | ||
+ | - RD.TextColumn(colDesc,RD.NextLine, 'Descrição'); | ||
+ | - RD.TextColumn(colSexo,RD.CurrentLine, 'Pontos'); | ||
+ | - while (vCodigoAtual = Q.AsString('CCODIXANDE')) and (not Q.Eof) do begin | ||
+ | - RD.TextColumn(colDesc,RD.NextLine, Q.AsString('CDESCXANDE')); | ||
+ | - RD.TextColumn(colSexo,RD.CurrentLine, Q.AsString('NPTS')); | ||
+ | - Q.Next; | ||
+ | - end; | ||
+ | - end else begin | ||
+ | - Q.Next; | ||
+ | - end; | ||
+ | - vCodigoAtual := Q.AsString('CCODIXANDE'); | ||
+ | - end; | ||
+ | - RD.EndGroup; | ||
+ | - end; | ||
+ | |||
+ | 1º Executamos um RD.StartGroup(posição x onde iniciara o texto(deixar 0), RD.NextGroup para iniciar onde terminou o group anterior, keeptogether define se será impresso junto). | ||
+ | |||
+ | 2º while (not Q.Eof) and (not RD.Aborted) do begin - Executa enquanto o retorno da query estiver sendo lido e a geração do relatório não tiver sido abortada. | ||
+ | |||
+ | 3º RD.TextColumn(colXANDE,RD.NextLine, Q.AsString('CCODIXANDE')); - Define que na coluna colXande, na próxima linha será escrito o valor de Q.AsString('CCODIXANDE'). | ||
+ | |||
+ | 4º RD.TextColumn(colDesc,RD.CurrentLine, Q.AsString('CDESCXANDE')); - Define que na coluna colDesc, na mesma linha anterior será escrito o valor de Q.AsString('CDESCXANDE'). | ||
+ | |||
+ | E assim por diante, preenchendo as demais colunas. Nesse relatório temos o exemplo de um mestre/detalhe, onde o if 'if(Q.AsString('CCODIQLD') <> '')then begin' verifica se tem algo preenchido como detalhe e se estiver imprime antes de ir para o proximo registro mestre. | ||
+ | |||
+ | * RDNewPage | ||
+ | - function TFExemploRel.RDNewPage(o: TObject): Integer; | ||
+ | - var | ||
+ | - vPosicao: Integer; | ||
+ | - begin | ||
+ | - if RD.Aborted then begin | ||
+ | - Result :=0; | ||
+ | - end else begin | ||
+ | - | ||
+ | - if(FPagina = 1)then begin | ||
+ | - ReportPrimeiraPagina(RD, MARGEM, RD.Title); | ||
+ | - RD.FontSize(10); | ||
+ | - RD.ImprimeFiltro(MARGEM, RD.NextLine+500, slcCadastros.Text, 'Cadastros', 8, -500); | ||
+ | - | ||
+ | - end else begin | ||
+ | - RD.StartGroup(0,RD.NextGroup,True); | ||
+ | - ReportDemaisPaginas(RD,MARGEM,RD.Title,FNomeLaboratorio); | ||
+ | - end; | ||
+ | - RD.Line(MARGEM,RD.NextLine+100,95000,RD.NextLine+100); | ||
+ | - vPosicao:= RD.NextLine; | ||
+ | - RD.FontSize(8); | ||
+ | - RD.TextColumn(colXANDE,vPosicao,'Código'); | ||
+ | - RD.TextColumn(colDesc,vPosicao,'Descrição'); | ||
+ | - RD.TextColumn(colSEXO,vPosicao,'Sexo'); | ||
+ | - RD.TextColumn(colDataNas,vPosicao,'Data de Nascimento',1); | ||
+ | - RD.TextColumn(colUsuario,vPosicao,'Incluído por'); | ||
+ | - | ||
+ | - RD.Line(MARGEM,RD.NextLine+200,95000,RD.NextLine+200); | ||
+ | - inc(FPagina); | ||
+ | - Result:= RD.EndGroup; | ||
+ | - end; | ||
+ | - | ||
+ | - end; | ||
+ | |||
+ | Essa função serve para criação das colunas iniciais e seus respectivos textos. Ela é chamada sempre que atinge os 95 mil do rodapé, cria uma nova pagina, monta os cabeçalhos das colunas e chama a RDPage. | ||
+ | |||
+ | *RDEndPage | ||
+ | - procedure TFExemploRel.RDEndPage(Sender: TObject); | ||
+ | - begin | ||
+ | - ReportRodapePadrao(RD, 2500, 96000, FDataImpressao); | ||
+ | - end; | ||
− | + | Acionado ao chegar no fim da página, imprime o rodapé de impressão. | |
+ | |||
+ | |||
+ | ===Gerando Planilha=== | ||
+ | Primeiramente precisa ser incluído no uses as seguintes classes: UAuxReport,Uplanilha,UFOpenDialog, UFSaveDialog, UBDTime, UAuxGlobal e UFMain. | ||
+ | |||
+ | '''Código Base''' | ||
+ | - procedure TFExemploRel.GeraPlanilha; | ||
+ | - const | ||
+ | - CODIGO = 1; | ||
+ | - DESCRICAO = 2; | ||
+ | - SEXO = 3; | ||
+ | - DATANASCE = 4; | ||
+ | - USUARIO = 5; | ||
+ | - | ||
+ | - var | ||
+ | - vPlan : TWorkBookPool; | ||
+ | - vSaveDlg : TFSaveDialog; | ||
+ | - | ||
+ | - vStFil, | ||
+ | - vStCol, | ||
+ | - vFileName, | ||
+ | - vStCab : String; | ||
+ | - i, vMescla, | ||
+ | - vFile : integer; | ||
+ | - vCodigoAtual: string; | ||
+ | - | ||
+ | - begin | ||
+ | - vSaveDlg := TFSaveDialog.Create(GlobalDataCenter); | ||
+ | - FNomeLaboratorio:= ConfigSis('CADLABORATORIO'); | ||
+ | - try | ||
+ | - | ||
+ | - vSaveDlg.Filter := 'Planilha XLS|*.xls|Planilha XML|*.xml'; | ||
+ | - if SalvarPlanilha(vSaveDlg) then begin | ||
+ | - vFileName := vSaveDlg.FileName; | ||
+ | - vPlan := TWorkBookPool.Create(False); | ||
+ | - vFile := vPlan.NewFile(vFileName); | ||
+ | - BDTime.DesativarGuardiaoDoTempo; | ||
+ | - Screen.Cursor:= crHourGlass; | ||
+ | - Try | ||
+ | - vStCab := vPlan.WorkBook[vFile].Styles.AddStyle; | ||
+ | - vPlan.WorkBook[vFile].Styles[vStCab].Font.Name := 'Arial'; | ||
+ | - vPlan.WorkBook[vFile].Styles[vStCab].Font.Size := 11; | ||
+ | - vPlan.WorkBook[vFile].Styles[vStCab].Font.Style := [fsBold]; | ||
+ | - vPlan.WorkBook[vFile].Styles[vStCab].VAlign := vaCenter; | ||
+ | - | ||
+ | - i := 2; | ||
+ | - vPlan.Cell(vFile,1,i,CODIGO).setProp('Mesclar',4).setProp('Style',vStCab).value := FNomeLaboratorio; | ||
+ | - inc(i); | ||
+ | - | ||
+ | - vPlan.Cells[vFile,1,i,CODIGO] := 'Código'; | ||
+ | - vPlan.Cells[vFile,1,i,DESCRICAO] := 'Descrição'; | ||
+ | - vPlan.Cells[vFile,1,i,SEXO] := 'Sexo'; | ||
+ | - vPlan.Cells[vFile,1,i,DATANASCE] := 'Data de nascimento'; | ||
+ | - vPlan.Cells[vFile,1,i,USUARIO] := 'Incluído por'; | ||
+ | - | ||
+ | - vCodigoAtual := Q.AsString('CCODIXANDE'); | ||
+ | - while (not Q.Eof) and (not RD.Aborted) do begin | ||
+ | - vPlan.Cells[vFile,1,i,CODIGO] := Q.AsString('CCODIXANDE'); | ||
+ | - vPlan.Cells[vFile,1,i,DESCRICAO] := Q.AsString('CDESCXANDE'); | ||
+ | - vPlan.Cells[vFile,1,i,SEXO] := Q.AsString('ESEXO'); | ||
+ | - vPlan.Cells[vFile,1,i,DATANASCE] := Q.AsString('DDATANASC'); | ||
+ | - vPlan.Cells[vFile,1,i,USUARIO] := Q.AsString('ULIBUINC'); | ||
+ | - inc(i); | ||
+ | - if(Q.AsString('CCODIQLD') <> '')then begin | ||
+ | - vPlan.Cells[vFile,1,i,DESCRICAO] := 'Qualidades:'; | ||
+ | - inc(i); | ||
+ | - vPlan.Cells[vFile,1,i,DESCRICAO] := 'Descrição'; | ||
+ | - vPlan.Cells[vFile,1,i,SEXO] := 'Pontos'; | ||
+ | - inc(i); | ||
+ | - while (vCodigoAtual = Q.AsString('CCODIXANDE')) do begin | ||
+ | - vPlan.Cells[vFile,1,i,DESCRICAO] := Q.AsString('CDESCXANDE'); | ||
+ | - vPlan.Cells[vFile,1,i,SEXO] := Q.AsString('NPTS'); | ||
+ | - inc(i); | ||
+ | - Q.Next; | ||
+ | - end; | ||
+ | - end else begin | ||
+ | - Q.Next; | ||
+ | - end; | ||
+ | - vCodigoAtual := Q.AsString('CCODIXANDE'); | ||
+ | - end; | ||
+ | - FinalizaPlanilha(vPlan,vFile,vFileName); | ||
+ | - finally | ||
+ | - vPlan.Free; | ||
+ | - BDTime.ReAtivarGuardiaoDoTempo; | ||
+ | - Screen.Cursor := crDefault; | ||
+ | - end; | ||
+ | - end; | ||
+ | - finally | ||
+ | - vSaveDlg.Free; | ||
+ | - end; | ||
+ | - end; | ||
+ | |||
+ | Os pontos mais importantes desse é estilização da celula: | ||
+ | vStCab := vPlan.WorkBook[vFile].Styles.AddStyle; | ||
+ | vPlan.WorkBook[vFile].Styles[vStCab].Font.Name := 'Arial'; | ||
+ | vPlan.WorkBook[vFile].Styles[vStCab].Font.Size := 11; | ||
+ | vPlan.WorkBook[vFile].Styles[vStCab].Font.Style := [fsBold]; | ||
+ | vPlan.WorkBook[vFile].Styles[vStCab].VAlign := vaCenter; | ||
+ | |||
+ | Essa parte mesma 4 colunas na linha 2(valor de i) e adiciona nessa linha o nome do laboratório. | ||
+ | vPlan.Cell(vFile,1,i,CODIGO).setProp('Mesclar',4).setProp('Style',vStCab).value := FNomeLaboratorio; | ||
+ | |||
+ | Monta os titulos da coluna, onde i representa a linha e o ultimo parametro representa o numero da coluna: | ||
+ | |||
+ | vPlan.Cells[vFile,1,i,CODIGO] := 'Código'; | ||
+ | vPlan.Cells[vFile,1,i,DESCRICAO] := 'Descrição'; | ||
+ | vPlan.Cells[vFile,1,i,SEXO] := 'Sexo'; | ||
+ | vPlan.Cells[vFile,1,i,DATANASCE] := 'Data de nascimento'; | ||
+ | vPlan.Cells[vFile,1,i,USUARIO] := 'Incluído por'; | ||
+ | |||
+ | Sempre que for ir pra próxima linha incremente no i. |
Edição atual tal como às 18h04min de 12 de março de 2024
Índice
- 1 Desenvolvendo interfaces com a Biblioteca Uniware
- 2 Dicionário de Termos
- 3 Incluindo telas da biblioteca
- 4 Criação de Tabelas
- 5 Componentes
- 6 Outros componentes importantes
- 6.1 UFBase
- 6.2 USys
- 6.3 UUser
- 6.4 UErros
- 6.5 UCS
- 6.6 UPS
- 6.7 UPSCad, UPSSel, UPSRel
- 6.8 USeg
- 6.9 UDatabase
- 6.10 UMaskEdit
- 6.11 UDateEdit
- 6.12 UNumericEdit
- 6.13 UComboBox
- 6.14 UCheckBox
- 6.15 DataSeeker
- 6.16 UPars
- 6.17 TURel
- 6.18 TURelCol
- 6.19 TURelColumn
- 6.20 UCodBarMatr
- 6.21 RBuilder: Preview Maximizada
- 6.22 Metodos e propriedades do RD
- 7 Configurando permissões
- 8 Problemas Conhecidos
- 9 HOTKEYS Para abrir telas
- 10 Lista de exercicios
Desenvolvendo interfaces com a Biblioteca Uniware
Esse guia tem por funcionalidade auxiliar o desenvolvedor na programação de interfaces utilizando a biblioteca da Uniware.
É importante observar que esse artigo não aborda a instalação dos componentes gráficos. Para isso, visite Instalação Delphi
Dicionário de Termos
- Interface
- Referência a um form, uma tela no unilab
- RD
- Reporte Data, componente referente a relatórios
Incluindo telas da biblioteca
- Para incluir telas da biblioteca é necessário incluir os seguintes componentes na UFMain que estão localizados na aba R04(como na imagem acima):
UCS, UPSCad, UPSSel e UPSRel(se necessário).
- Primeiramente é necessário nomear os componentes adicionados nos padrões:
Ex no CRUD de Municipio USC - muni UPSSel - muniSel UPSCad - muniCad UPSRel - muniRel
- Ligar o UPSCad, o UPSSel e o UPSRel ao UCS, indo na propriedade CS de cada um destes componentes e colocando o nome do UCS.
Incluindo tela FBaseSel
- Após incluir os componentes na UFMain, ir em File > New, clicar na aba UNILAB_BETA, selecionar FBaseSelR03 e clicar em Ok.
- Incluir as novas units no proj do unilab e unilaudos e dar ADD pelo svn para incluir na postagem
- A Unit, ao ser criada, possui uma parte do código assim:
- var
- Form1: TForm1;
- No projeto essa parte é desnecessária, visto que o FMain realiza a instanciação das interfaces de outra forma.
- Ao apagar o código acima de uma unit, remover do projeto UNILAB_BETA a criação automática da interface, como na linha:
- Application.CreateForm(TForm1, Form1);
- Salvar a a Unit criada com o nome UF+NomeDaFuncionalidade+Sel'.
- Colocar no Form o mesmo nome apenas trocando o U por F, ficando como F+NomeDaFuncionalidade+Sel.
- Alterar a propriedade BorderIcons no form, e deixar o biHelp como false, e alterar Formstyle para fsMDIChild
- Na UNIT da SEL, dar USES no implementation da UFMain para poder se conectar ao banco de dados.
- No componente UQuery preencher na propriedade UDataBase com FMain.UDB.
- Na propriedade SQL passar o SELECT da tabela que foi criada no banco de dados para a tela deste cadastro.
- Ao dar um duplo clique no componente UQuery abrirá a lista com todos os campos do dataset da tabela.
- Ao selecionar um FIELD de um campo do dataset irá listar as seguintes propriedades:
- Nome Default: Q concatenado do mesmo nome da coluna do banco;
- Campo: Qual campo do banco ele representará;
- ChavePrimaria: Identifica a PK da tabela. Obrigatoriamente a PK da tabela deve estar marcada na tela Sel;
- Edicao: Indica o componente visual que edita esse valor (Usado só na tela CAD);
- Filtra: Habilita o campo a ser uma chave no botão Filtra;
- NaNavegacao: Define se o campo estará disponível, requerido para mostrá-lo em uma coluna na Grid ;
- Ordena: Permite o usuário Ordenar os resultados utilizando a coluna como parâmetro, por padrão colocamos true em todos os campos que aparecem na grid ( a biblioteca exige que apenas 1 campo esteja com true)
- PreencheChave: Em uma situação mestre-detalhe, esse parâmetro permite que seja inserido no campo a chave primária do mestre (Usado na tela CAD);
- Procura: Habilita a procura de valores na coluna pelo localizar, por padrão colocamos true em todos os campos que aparecem na grid;
- Sequencial:Quando for um número sequencial (auto-incremento) informar o nome da tabela a qual o campo pertence; (Usado só na tela CAD)
- Tabela: Indica a qual tabela o campo pertence;
- TabelaAlias: Preenchido caso a tabela possua alias;
- Titulo: Valor a ser apresentado no cabeçalho da coluna da DBGrid e no filtro;
- OBS: O ideal seria ajustar os títulos das colunas para ficarem corretas quando forem adicionadas;
- Para adicionar todas as colunas na Grid, clicar com o botão direito no componente CAD e escolher a opção Colunas da Grid de Procura.
- Para incluir apenas uma coluna, selecionar a DBGrid, dar um duplo clique na propriedade Columns e depois clicar no botão Add New (Ins).
- Existe um componente que não aparece no form principal, chamado OC, este componente e responsável por definir qual coluna a grid ira ordenar ao abrir o form. Selecione-o pela combo do object inspector, setar qual coluna sera ordenada inicialmente na propriedade "AliasInicial", e se ira ser ascendente ou descendente
- DBGrid > Columns > selecionar a coluna que sera ordenada inicialmente (definida no componente OC) > Title > Font > Color, definir a cor clRed (Vermelho) quando a ordem inicial é decrescente ou clBlue quando for crescente.
- Após esse processo deve-se ligar a nova tela ao menu, da seguinte maneira:
- Criar o menu para o novo cadastro (FMain.MM);
- Dar um duplo clique no menu criado e utilizar a chamada para a tela SEL da seguinte maneira:
- UMenuCall('NomeDoUCS','NomeDoUPSSel');
- No evento OnFormType do componente UPSSel(na UFMain) colocar o result da função recebendo o form da Sel.
- Ex: Result := TFPediSel;
Incluindo tela FBaseCad
- Ir em File > New, clicar na aba UNILAB_BETA, selecionar FBaseCadR03 e depois clicar em OK.
- A Unit, ao ser criada, possui uma parte do código assim:
- var
- FBaseCadR1: TFBaseCadR1;;
- Apague essa parte, pois no projeto essa parte é desnecessária, visto que o FMain realiza a instanciação das interfaces de outra forma.
- Ao apagar o código acima de uma unit, apagar do projeto UNILAB_BETA a linha de criação automática da interface:
- Application.CreateForm(TFBaseCadR1, FBaseCadR1);
- Na Unit criada, salvar como UF+ NomeDaFuncionalidade +Cad.
- Colocar no Form o mesmo nome retirando apenas o U do inicio, ficando como F+ NomeDaFuncionalidade +Cad.
- Na UNIT da CAD, dar USES na UFMain para poder se conectar banco de dados.
- Para incluir campos nesta tela, preferencialmente utilizar os componentes da biblioteca(aba R03).
- Por padrão na propriedade Name do campo adicionado, o mesmo deverá conter o mesmo nome das colunas criadas no banco de dados.
- Ex: Campo "Nome":TUEdit na tela MuniCad, irá ficar como CNOMEMUNI.
- No form da SEL criado terá um componente SelData, na propriedade CallCS e CallPS preencher com o mesmo nome do UCS e UPSCad criado na #UFMain.
- No componente UQuery preencher na propriedade UDataBase com FMain.UDB.
- Na propriedade SQL passar o SELECT para a tabela que foi criada no banco de dados para a tela deste cadastro. Diferente da Sel, a tela Cad não pode ter o SELECT na view, e sim diretamente na tabela
- Ao dar um duplo clique no componente UQuery abrirá a lista com todos os campos da tabela.
- Na propriedade Edicão do campo U SQL, colocar a propriedade que representa a coluna da tabela para true.
- Nessa mesma tela, definir quais campos serão chave primária na propriedade "ChavePrimaria". Não esquecer de definir o MaxLength do edit que recebe a chave primária com o mesmo tamanho do Varchar da coluna na tabela
- A propriedade AjCod dos edits, servem para preencher os espaços que faltam no varchar com zeros. Marcar nos edits necessários
- Ex: CCODIPOST:TUEdit, representa a coluna CCODIPOST no banco;
- Na UFMain, no evento OnFormType do componente UPSCad, colocar o result da função recebendo o form da Cad, lembre que é nome da TForm, e não da UF, Cada UF dentro dela tem uma instancia da TForm, e dar uses na CAD dentro da UFmain.
- Ex: Result := TFPediCad;
- Ajustar em object Inspector da Form da CAD o FormStyle para deixar a janela da CAD criada como filha (fsMDIChild) no projeto.
Mestre Detalhe
- Mestre vai ser o cadastro que fizemos posteriormente, vamos adicionar agora o detalhe.
- Na aba R03, adicionar os seguintes componentes: TUDataEntry, TUDataSource, TUQuery e TUBotaoCadastro coloque o name nos ocmponetes expecificando que são detalhe coloque DETA ex: TUDataEntry = DEDETA, TUDataSource=DSDETA, TUQuery = QDETA
- TUBotaoCadastro para excluir o detalhe
- Na propriedade: coloca o name como btnExcluir e transparent true.
- OBS: Verifique de estar fazendo esses processos nos componentes do DETALHE.
- TUDataEntry
- Na propriedade:
- Limite - colocar a quantidade máxima que é possível cadastrar, não possui infinito;
- LinhasVisiveis - colocar a quantidade de linhas que irão ficar visíveis na tela;
- UBotaoExclusao - ligar com o TUBotaoCadastro adicionado anteriormente;
- UDataEntry - colocar o DataEntry(DE) do mestre;
- UDataSource - colocar o TUDataSource do detalhe;
- UsaScrollBar - Quando estiver TRUE irá aparecer o scrollBar.
- TUDataSource
- Na propriedade:
- UQuery - colocar a TUQuery do detalhe adicionada anteriormente.
- TUQuery
- Na propriedade:
- SQL - Passar o SELECT da tabela que foi criada no banco de dados para a tela deste cadastro.
- UDataBase - Caso já estiver com o USES na UFMain selecionar o FMain.UDB, se não, dar primeiramente o USES na UFMain e depois selecionar FMain.UDB.
- Dar um duplo clique na Query para abrir a tela dos Fields;
- No field que for a FK deve-se deixar marcado como TRUE as propriedades ChavePrimaria e PreencheChave, ex: CCODI da Mestre que vai fazer Referencia na detalhe, além de ter o mesmo nome também tem que estar marcado o ChavePrimaria e PreencheChave no U SQL do DETALHE.
- No field que for a PK deve-se deixar marcado como TRUE a propriedade ChavePrimaria.
- No Campo que você esta fazendo a validação, ou sejá adicionando a informação de detalhe ir no evento OnValidar e acrescentar código para preencher a chave no detalhe.
- Onde DEDETA é o referente as tabelas do Detalhe e DE referente ao campos da Tabela Mestre, tendo em vista que essa comparação os mesmos nomes que tem na MESTRE tem que ter na DETALHE, Chaves primarias.
- Exemplo
Result := True; DEDETA['CCODIDETALHE'] := RecSeq('LB_QQDETALHES',FMain.UDB,6,,True); DEDETA['CCODIQQ'] := DE['CCODIQQ']; DEDETA['CCODIPOST'] := DE['CCODIPOST'];
- Excluindo Detalhe do mestre
- No campo onde você vai digitar e quando der tab ele vai para o campo de baixo para adicionar um novo detalhe, nele vá em events Duplo clique em OnNewControl
- Esse evento vai fazer você poder excluir os detalhes em qualquer ordem, nesse evento coloque apenas TUedit(NewControl).OnKeyDown := Nome da procedure criada do OnKeyDown;
- No campo onde você vai digitar e quando der tab ele vai para o campo de baixo para adicionar um novo detalhe, nele vá em events Duplo clique em OnNewControl
ex:
TUEdit(NewControl).OnKeyDown := TUEdit(AControl).OnKeyDown;
- No evento OnKeyDown dos campos do detalhe, fazer a verificação para quando a tecla F7 for pressionada, chamar a função criada anteriormente.
if Key = VK_F7 then begin if not Vazio(DEDETA['CCODIDETALHE']) then begin ExcluiViaKeyDown(btnExcluir); end; end;
QueryManager
Para fazer buscas no banco por registros usar o exemplo da QueryManager.
- Exemplo de Query Manager
var vQ:TUQuery; begin vQ := FMain.QM.GetQuery; try vQ.SQL.Text := 'SELECT CPOSTOTRAN '+ ' FROM LB_LTTRANS '+ ' WHERE CCODIPOST = :CCODIPOST '+ ' AND CCODILTTRANS = :CCODILTTRANS '; vQ.GraveParametro('CCODIPOST', CAD['CCODIPOST'], ftString); vQ.GraveParametro('CCODILTTRANS', CAD['CCODILTTRANS'], ftString); //grava oque vem da Query, pega o valor da CAD, e joga nas variaveis CCODIPOST, CCODILTTRANS, e usa elas nas query = :CCODIPOST e = :CCODILTTRANS vQ.Open; if (vQ.AsString('CPOSTOTRAN') <> 'E') then begin msgerro('Este lote não pode ser excluído ou alterado pois já foi transmitido.'); end; vQ.Close; finally globalQM.ReleaseQuery(vQ); end; end;
Criação de Campo Calculado
- Os campos calculados são campos que não carregam nada do banco e tem que ser populados na mão.
- Exemplo:Ao Selecionar um código do município o seu nome e UF ser carregados automaticamente.
- Para criar um campo calculado:
- Na TUQuery dar dois cliques e na janela que abrir apertar com o botão direito e colocar em criar campo calculado.
- Colocar nome com o padrão inicial de CALC para diferenciar.
- No evento OnValidar, inicializar o Result como false, para quando o for setado Result true no final, ele guardar o dado no campo, e não ficar sumindo.
- Para atribuir valores do banco a esse campos, usar a QueryManager e atribuir como mostra o exemplo.
- Ex:
DE['CCALCNOMEMUNI'] := q1.AsString('CNOMEMUNI'); DE['CCALCUFMUNI'] := q1.AsString('CUFMUNI');
- Campos calculados são bastante usado para concatenar campos compostos, na tabela tem codigo do paciente e codigo do posto, fazendo um campo calculodo como acima, você consegue mostrar esses dois dados concatenados
- EX:
DE['CALCODIGPOSTOPACIENTE'] := IfNull(vQ.AsString('CCODIPOST'),) + IfNull(vQ.AsString('CCODIPACI'),);
- Obs: O IfNulL é um metodo que verifica se esta nulo, ou não IfNull(vQ.AsString('Verifica se vazia'),) e estiver vazia seta , caso contrario pega o valor da variável.
- vQ é a variavel que anteriormente foi usado e esta trazendo o SQL, o AsString pega dentro do vQ a Variável CCODIPOST e converte para jogar dentro da variável CALCODIGOPOSTOPACIENTE.
Incluindo tela FBaseRel (Depreciado - Atualmente somente em manutenção)
- Ir em File > New, clicar na aba UNILAB_BETA, selecionar FBaseRelM02R04 e depois clicar em OK.
- A Unit, ao ser criada, possui uma parte do código assim:
- var
- Form1: TForm1;
- No projeto essa parte é desnecessária, visto que o FMain realiza a instanciação das interfaces de outra forma.
- Ao apagar o código acima de uma unit, remover do projeto UNILAB_BETA a criação automática da interface, como na linha:
- Application.CreateForm(TForm1, Form1);
- Na Unit criada, no campo Name ajustar para UF+NomeDaFuncionalidade+Rel.
- Colocar no Form o mesmo nome retirando apenas o U do inicio, ficando como F+NomeDaFuncionalidade+Rel.
- Na UNIT da REL, no implementation, dar USES na UFMain para poder se conectar ao banco de dados.
- No componente UQuery preencher na propriedade UDataBase com FMain.UDB.
- Na propriedade SQL passar o SELECT da tabela que foi criada no banco de dados para a tela deste cadastro.
- Ao dar um duplo clique no componente UQuery abrirá a lista com todos os campos da tabela.
- Na aba R03, acrescentar o componente SuReportData.
- No evento OnClick do botão BImprimir realizar os tratamentos dos filtros aplicados na tela.
- Exemplo.
- OBS: Se não for utilizar o combo ordem na tela, comentar a linha inherited desta procedure pois esta função realiza tratamentos do combo.
- No Form da UPSREL, no OnCreate, onde foi setado a ordem no case da imagem a cima temos ordem 1, 2, 3. Para setar uma inicial coloque OC.Combo.ItemIndex := 1; no FormeCreate
- OBs: Na propriedade do combo setar para false SemOrdem, a ordem vai ser dada com a propriedade Item, colocando o nome respectivo que esta na ordem 1, 2, 3 ...
- Na UFMain, no evento OnFormType do componente UPSRel, colocar o result da função recebendo o form.
- Result := TFPediRel;
- Criar o menu para o novo relatório na UFMain
- Dar um duplo clique no menu criado e utilizar a chamada para a tela REL da seguinte maneira:
- UMenuCall('NomeDoUCS','NomeDoUPSSel');
- Inserir o componente SUReportData da aba R04 e ajustar na propriedade Name o nome do componente;
- Dar um duplo clique no evento OnStartReport, nesse evento é onde é criado as configurações de cabeçalho e as colunas do relatório.
- No evento OnNewPage é feita a impressão do cabeçalho.
- No evento OnPage é onde é feito o loop da impressão.
- Cada página será impressa até que seu conteúdo atinja a posição marcada na propriedade EndPosition.
- Antes de imprimir o comando que extrapolou o EndPosition, é chamado o OnEndPage, pois assim é criado uma nova página chamando o OnNewPage.
- No evento OnEndPage é chamado no final do relatório, antes de gerar um nova página.
- Seu propósito é fazer a impressão do rodapé da página.
- O evento OnEndReport é chamado uma vez depois do último OnEndPage do relatório.
- Para o relatorio funcionar o combo, vá na U SQL, de um duplo click, nos campo que você quer que apareça no combo, clique neles e marque as propriedades NaNavegação, Ordena e Filtra, todas para true.
- Altere também o Título onde o mesmo vai aparecer com esse nome no combo.
- Lembrando que na :
case OC.Combo.ItemIndex of 0: vOrdem := ' LB_PACI.CCODIPACI ' + vDesc ; 1: vOrdem := ' LB_PACI.CNOMEPACI ' + vDesc; else
- Nessa linha acima os valores 0: e 1: recebem campos das tabelas, caso o relatório for ter mais opções deve ser colocado aqui, além de setar o paço da U SQL.
- Criar o evento FormCreate e colocar:
FCfgCLab := TUCfg.Create(nil);
- Criar o evento FormDestroy e colocar :
FCfgCLab.Free
- No RDStartReport: roda uma vez, definindo as variaveis globais, e larguras das colunas
- No RDStartReport : colCodigo := RD.NewColumn(5000,8000, rpLeft); // colCodigo é a variavel representa a primeira coluna, começa no 5mil e termina no 8mil = 13mil, esse 13mil a proxima linha tem que começar dele ex: (13000,8000)
- No RDStartReport: roda uma vez, definindo as variaveis globais, e larguras das colunas
- No RDNewPage: roda uma vez por pagina e imprime o cabeçalho
- No RDNewPage: setar espaçamento das colunas, colocar um ou mais de um nome no cabeçalho, tamanho da fonte, quais colunas vão estar na pagina
- No RDNewPage: roda uma vez por pagina e imprime o cabeçalho
- No RDPage: gera as paginas
- No RDPage: seta onde começa o a escrever o relatorio no X, onde começa no Y, onde termina no X, onde termina no Y. geralmente é : RD.Line(5000,RD.NextLine+150,95000,RD.NextLine+250);
- No RDPage: gera as paginas
- No RDEndPage: imprime o rodapé
- No RDEndPage: a linha RD.Line(FMargin,RD.CurrentLine,FLarguraLinha+FMargin,RD.CurrentLine,6); as variaveis FLarguraLinha, FMargin devem ser criadas como private do tipo integer
Incluindo tela FBaseRel (Atual)
- Ir em File > New, clicar na aba NEW, selecionar Form e depois clicar em OK.
- Remover do projeto UNILAB_BETA a criação automática da interface, como na linha:
- Application.CreateForm(TForm1, Form1);
- Na Unit criada, no campo Name ajustar para UF+NomeDaFuncionalidade+Rel.
- Colocar no Form o mesmo nome retirando apenas o U do inicio, ficando como F+NomeDaFuncionalidade+Rel.
- Na UNIT da REL, no implementation, dar USES na UFMain.
- Desenhar a tela do relatório como desejar (Seguindo os padrões de desenvolvimento).
- Acrescentar componente UQuery e preencher na propriedade Name com Q.
- Na aba R03, acrescentar o componente SuReportData.
- No evento OnClick do botão BImprimir realizar os tratamentos dos filtros aplicados na tela.
- Exemplo.
- Criar o menu para o novo relatório na UFMain
- Dar um duplo clique no evento OnStartReport, nesse evento é onde é criado as configurações de cabeçalho e as colunas do relatório.
- No evento OnNewPage é feita a impressão do cabeçalho.
- No evento OnPage é onde é feito o loop da impressão.
- Cada página será impressa até que seu conteúdo atinja a posição marcada na propriedade EndPosition.
- Antes de imprimir o comando que extrapolou o EndPosition, é chamado o OnEndPage, pois assim é criado uma nova página chamando o OnNewPage.
- No evento OnEndPage é chamado no final do relatório, antes de gerar um nova página.
- Seu propósito é fazer a impressão do rodapé da página.
- O evento OnEndReport é chamado uma vez depois do último OnEndPage do relatório.
- Criar o evento FormCreate e colocar:
FCfgCLab := TUCfg.Create(nil);
- Criar o evento FormDestroy e colocar :
FCfgCLab.Free
- No RDStartReport: roda uma vez, definindo as variaveis globais, e larguras das colunas
- No RDStartReport : colCodigo := RD.NewColumn(5000,8000, rpLeft); // colCodigo é a variavel representa a primeira coluna, começa no 5mil e termina no 8mil = 13mil, esse 13mil a proxima linha tem que começar dele ex: (13000,8000)
- No RDStartReport: roda uma vez, definindo as variaveis globais, e larguras das colunas
- No RDNewPage: roda uma vez por pagina e imprime o cabeçalho
- No RDNewPage: setar espaçamento das colunas, colocar um ou mais de um nome no cabeçalho, tamanho da fonte, quais colunas vão estar na pagina
- No RDNewPage: roda uma vez por pagina e imprime o cabeçalho
- No RDPage: gera as paginas
- No RDPage: seta onde começa o a escrever o relatorio no X, onde começa no Y, onde termina no X, onde termina no Y. geralmente é : RD.Line(5000,RD.NextLine+150,95000,RD.NextLine+250);
- No RDPage: gera as paginas
- No RDEndPage: imprime o rodapé
- No RDEndPage: a linha RD.Line(FMargin,RD.CurrentLine,FLarguraLinha+FMargin,RD.CurrentLine,6); as variaveis FLarguraLinha, FMargin devem ser criadas como private do tipo integer
UAuxReport
- Helper de impressão de relatórios.
- Simplificando impressão do relatório.
Q.Open; if Q.Eof then begin msgerro('Nenhum registro para o pedido informado.') end else begin if (PrinterManager <> Nil) then begin if (Not PrinterManager.SetReportPrinter(RD.Report,,RD.ShowPreview)) then begin ShowMessage('Impressora nao especificada.'); Q.Close; Exit; end; end else begin Printer.PrinterIndex:=-1; Printer.Refresh; end; RD.Execute(Printer); RD.FileName := ; RD.Quiet := False; end; Q.Close;
Por
ReportImprime;
- Simplificando footer de relatórios
procedure SuaUnit.RDEndPage(Sender: TObject); begin If Not Rd.Aborted Then Begin RD.StartGroup(0,INICIO_RODAPE,True); RD.Line(5000,RD.NextLine,95000,RD.NextLine); RD.FontName('Arial'); RD.FontSize(8); RD.FontStyle([fsBold]); RD.TextColumn(colRoda1, RD.NextLine, RodaImpressoEm); RD.PageNumber(colRoda2, RD.CurrentLine+100,3,'Página '); RD.EndGroup; End; end;
Por
procedure SuaUnit.RDEndPage(Sender: TObject); ReportRodapePadrao(RD, MARGEM_ESQUERDA, INICIO_RODAPE); end;
Seeker
- Este componente possui uma Query própria e tem como função de buscar conforme a digitação do usuário.
- Na aba UNIWARE, adicionar o componente TDataSeeker.
- Configurando as propriedades
- BorderWidth - Colocar 3;
- Flutuante - Server para quando o seeker for maior do que a tela, para não cortar deixar como True.
- GridColumns - Define as colunas que irão aparecer no seeker, deve-se incluir manualmente.
- Color - Colocar $00AEE8BB.
- FieldName - Nome do campo retornado pelo SQL que a coluna representa.
- Title.Caption - Título da coluna.
- Alguns ajustes nas colunas.
- Ajustar o Negrito,
- Colocar font color clNavy para coluna de ordenação inicial
- intercalar cores nas colunas $00C6FFC6/$00AEE8BB
- Alguns ajustes nas colunas.
- HideOnExit - Quando false, a tela não fecha nunca.
- Hint - Escrever a mensagem para aparecer no hint.
- HotKeys - Define até 6 hotkeys, para quando o usuário estiver com foco no seeker.
- OBS - A tecla F2 é usada no HotKey6
- Name - Ajustar para ds + Nome da funcionalidade.
- NextCtrl - Define qual componente irá receber o foco, quando o usuário o seeker perder o foco.
- OrdemInicial- Nome do campo que o SQL traz ordenado por padrão.
- Query
- SQL - Determina o SQL que vai ser executado para buscar os dados utilizados na busca.
- UDatabase - conexão com o banco de dados.
- OnGetSQL - Colocar o SQL no evento OnGetSQL, como o seguinte exemplo:
SQL.Text:= 'SELECT CCODIMUNI, '+ ' CNOMEMUNI, '+ ' CUFMUNI '+ ' FROM LB_MUNI '+ 'IfStr(SearchString = '','',' WHERE '+IndexFieldName+' LIKE ' + QuotedStr(SearchString)) '+ ' ORDER BY '+ IndexFieldName;
- SortFields escrever em cada linha o nome de um campo que pode ser ordenado e buscado.
Exemplo de uso do Seeker no Município
- No FormCreate, Sincronizar os campos
- Exemplo ->
dsExame.EditCodigo := TEdit(CCODIMUNI); dsExame.EditNome := TEdit(CNOMEMUNI); dsExame.LstSincronize.Text := 'CODIGO|CCODIMUNI|ALL' + #13#10 + 'NOME|CNOMEMUNI|ALL'; dsExame.CampoCodigo := 'CCODIMUNI'; dsExame.CampoNome := 'CNOMEMUNI';
- No FormDestroy dar um Close no seeker
- Exemplo -> dsMuni.Close;
- Será preciso criar uma função para setar, no evento do onSeeker clicando no seeker:
- No exemplo abaixo, CCODIPACI é seu campo na CAD, o DataSet.FieldByName('CCODIPACI') é o nome do campo dentro da gridviewer da seeker está setado dentro da seeker no FieldName
procedure TFRuanCad.dsMuniSeek(Sender: TObject; DataSet: TDataSet);
begin
inherited; DE['CCODIPACI'] := DataSet.FieldByName('CCODIPACI').AsString;
Direitos
Usar componente useg na UFMain.
- No campo de Direitos do componente acrescentar o direito desejado.
Ex:
TFTESTESEL|Fechar|Pode fechar a janela SEL|NOME|COMENTARIO
- E para validar seu direito utilizar a seguinte function:
USegLeiaDireito('TFTesteSel','Fechar')
Passando o nome da SEL e o nome do direito.
Criação de Tabelas
- Na criação de tabelas no banco de dados para as telas da biblioteca deverão conter os seguintes atributos:
- ULIBDINC –> DATETIME data da inclusão do registro.
- ULIBUINC –> VARCHAR(20) usuário da inclusão do registro.
- ULIBDALT –> DATETIME data da alteração do registro.
- ULIBUALT –> VARCHAR(20) usuário da alteração do registro.
- ULIBRELA –> NUMERIC(9,0) sequencial de controle de alteração simultânea. Quando um usuário carrega um registro para alteração, carrega esse ULIBRELA junto, quando for salvar a alteração, consulta novamente no banco se o ULIBRELA ainda é o mesmo numero, se não for, resulta em erro de registro alterado por outra estação, senão incrementa o numero do ULIBRELA e salva.
- Em tabelas que realizarão transmissões deverão ter os atributos seguintes atributos:
- CTRANSTRAN –> VARCHAR(1) Utilizado em registros que são alterados apenas na central e transmitidos para o posto. O registro é incluído com N nesse campo e quando o registro é transmitido ele muda para S, ao tentar excluir o registro, se este estiver com S não permite.
- CCENTRALTRAN –> VARCHAR(9) Controle de transmissão da central. Deve ser atualizado sempre que um registro é alterado para que ele entre no próximo pacote de transmissão para o posto.
- CPOSTOTRAN –> VARCHAR(9) Controle de transmissão do posto. Deve ser setado como E na inclusão ou M na alteração para marcar os registros para ser transmitido
Componentes
TUQuery
- Nome Default: Q;
- Generico: Essa propriedade define a consulta a ser utilizada;
- SQL, SQLIB, SQLMS, SQLMySQL e SQLORACLE: consulta destinada à um tipo de banco. SQL deve ser configurada caso seja determinado Generico = true;
- TabelaPrincipal: Deve conter o nome da tabela utilizada no SQL, em interfaces SEL, é comum o uso de Views para essa consulta;
- TabelaPrincipalAlias: Caso a tabela possua um alias na SQL, ele deve ser informado aqui;
- UDataBase: referencia FMain.UDB que é a database do sistema.
TDataSource
- Nome Default: DS;
- UQuery: Esse campo deve estar referenciado para o componente anteriormente descrito, Q.
TUDataEntry
- Nome Default: DE;
- Limite: Determina a quantidade máxima de cadastros de detalhes;
- LinhasVisiveis: Define quantos campos aparecem abaixo do edit de detalhe (inclusive);
- UCadastro:Precisa referenciar o TUCadastro associado à grid;
- UDataSource: Esse campo deve estar referenciado para o componente anteriormente descrito, DS;
- UDataEntry: Quando for utilizar relações mestre-detalhe na interface, o Data Entry responsável pelo detalhe referencia o Data Entry do mestre.
- UsaScrollBar: Necessário quando o numero de 'Limite' ultrapassa 'LinhasVisiveis'.
TUDataEntry
- Nome Default: CAD;
- UDataEntry: Esse campo deve estar referenciado para o componente anteriormente descrito, DE.
Para poder trabalhar as configurações visuais da grid, como largura da coluna, propriedades de leitura, etc.
Use o RightClick nesse componente e selecione colunas da grid de procura.
(Você acessa a coluna individualmente buscando a propriedade Columns da DBGridP)
TUField
Para acessar os Campos do dataset, DoubleClick o componente de Query.- Nome Default: Q concatenado do mesmo nome da coluna do banco;
- Campo: Qual campo do banco ele representará;
- ChavePrimaria: Identificar a PK da tabela;
- Edicao: Indica o componente visual que edita esse valor;
- Filtra: Habilita o campo a ser uma chave no botão Filtra;
- NaNavegacao: Define se a coluna aparecerá na Grid;
- Ordena: Permite o usuário Ordenar os resultados utilizando a coluna como parâmetro, é obrigatório no mínimo 1 dos campos ser True;
- PreencheChave: Em uma situação mestre-detalhe, esse parâmetro permite que seja inserido no campo a chave primária do mestre;
- Procura: Habilita a procura de valores na coluna pelo botão Procura;
- Sequencial:Quando for um número seqüencial (auto-incremento) informar o nome da tabela a qual o campo pertence;
- Tabela: Indica a qual tabela o campo pertence;
- TabelaAlias: Preenchido caso a tabela possua alias;
- Titulo: valor a ser apresentado no cabeçalho da coluna;
TUFBase???R03Data
??? pode-se interpretar como 'Cad' ou 'Sel'.- Nome Default: ???Data;
- No SelData:
- CallCadModal: Não permite que seja aberta mais de uma tela de Cad;
- CallCs: Nome do CS que gerenciará essa interface (UFMain);
- CallPs: Identificar o processo da interface (UFMain);
- No SelData:
TUOrdemCombo
(Esse é um componente Invisível)- Nome Default: OC;
- AliasInicial: Coluna definida para que o edit possa fazer uma busca;
TDataSeeker
- É a popup de auto-complete do projeto:
- Flutuante: Não prende o seeker nas delimitações do form;
- GridColumns: Colunas exibidas na popup;
- Hotkeys: configurar o botão de retorno;
- NextCtrl: Componente a receber o foco quando a popup for encerrada;
- OrdemInicial: Define a coluna em que a pesquisa se ordena;
- Query:
- SingleFields: Define o nome das colunas;
- SingleQuery: Se a consulta utiliza apenas uma tabela;
- SingleTable: Nome da tabela;
TUEdit ou outras formas de input
Caso o componente esteja referenciando um CODI, Alterar:
- AJCod - Preenche o campo com zeros;
- MaxLength - Define o tamanho máximo do campo.
Outros componentes importantes
Talvez você não os use, mas é importante registrar aqui outros componentes da biblioteca para futuras consultas:
UFBase
Esse formulário é a base dos forms utilizados no sistema unilab. A partir desse modelo são criados os três tipos de interface do sistema: Rel, Sel e Cad, Que por sua vez são herdadas nas interfaces da biblioteca R03.
Nome | Funcionalidade |
---|---|
constructor TFBase.Create(AOwner: TComponent); | Todo formulário possui um componente com os eventos e dados referentes ao formulário. formulários mais especializados podem ter FormData especializados.
A checagem do FormData é feita na constructor dos Forms. Além disso, este construtor cria o helptimer. O helptimer serve para evitar que o usuário abra várias vezes o help pressionando F1 várias vezes. |
procedure FormClose(Sender: TObject; var Action: TCloseAction); | Evento para fechar o form e destruí-lo. Não entendi como funcionam as mensagens que ele procura e manda antes de fechar o form. |
function FormHelp(Command: Word; Data: Integer; var CallHelp: Boolean): Boolean; | Chama a ajuda relacionada à tela quando usuário pressiona F1. O arquivo de help deve estar no <path do executável>\<LibParam.ProgHelp>\<nome do form>.p. Se o arquivo não existir copia para ele o arquivo “<path onde esta o executável>\manunilab..p”. Por fim, executa o help.
|
function SearchMsg(s:string): TUMsg; | Procura pela mensagem - nil se nao encontrar. Chama o SearchMsg do PS do Form. |
function SearchMsgStarting(s:string): TUMsg; | Procura pela mensagem começando por s - nil se não encontrar. Chama o SearchMsgStarting do PS do Form. |
function CreateMsg(pnome, pcs, pps: string;pforcenew:boolean=True): TUMsg; | Criação de mensagem de comunicação com outro processo. Chama o CreateMsg do PS do form. |
procedure CreateCall(pname,pcs,pps,pretorno:string;pmodal:boolean=False); overload; | Cria uma chamada a uma tela de seleção - CreateCall('nome','cs','ps','ret'). Chama uma tela de seleção. Se a tela já existir, dá foco nela. |
procedure CallCad(pmode: TModoCadastro;pname,pcs,pps:string;key:TUPars=nil; pmodal:boolean=False); overload; | Cria uma chamada a uma tela de CAD. Idêntico ao CreateCall, mas adicionado à possibilidade de definir o modo (inserção, alteração, exclusão) e os valores da chave. |
procedure Answer(pmsg: TUMsg); virtual; | tratamento das mensagens |
procedure DoAfterCreateForm; | apos a criar e mostrar o form |
procedure DoAfterLoaded(pcalled:boolean); | apos a carregar o form, independente se direto ou por chamada msg (f2...) |
procedure DoAfterCreateMsg(pmsg:TUMsg); | apos criar uma mensagem de ligacao com outro processo |
procedure DoBeforeDestroy; | antes de destruir o PS |
procedure DoOnDoneUpdated(pdone:Extended); | o processo avancou |
property PS:TUPS read FPS write FPS default nil; | qual instancia de processo e dono do form |
procedure Confirm(pclose:boolean=False); | Confirma a execucao do processo. Metodo chamado pelo programador para confirmar o form e chamar o processo que o form executa - no evento OnProcess do FormData. |
procedure Cancel(pclose:boolean=True); | cancela a execucao do processo |
property Done:extended read GetDone write SetDone; | Informa o quanto o processo esta pronto (%) |
procedure PSDestroy(pmsg: TUMsg); virtual; | o PS que comunicava pela mensagem enviada foi destruido |
property Msg[s:string]: TUMsg read GetMsg; | ? |
property Processing : boolean read FProcessing; | ? |
USys
- Gerente do sistema, centraliza os processamentos do sistema:
- executa processos (dos CSs);
- trabalha direitos (verificar, delegar);
- troca de informacoes entre processos;
- controle e troca de informacoes com BD (a implementar no futuro 'proximo');
- Primeiro a ser instanciado, inicializa a aplicacao;
- As configuracoes gerais do sistema ficam em um .ini junto com o .exe na secao [Geral];
- As configuracoes por maquina ficam no registro do windows;
- As configuracoes por usuario ficam no cadastro do usuário.
Classe | Nome | Funcionalidade |
---|---|---|
protected | procedure Notification(AComponent: TComponent; Operation: TOperation); override; | Recebe uma notificação para remover um CS da ListCS onde AComponent é o cs que será destruído e Operation = opRemove. |
public | function Initialize: boolean; | Inicializa o Sys. Verifica a existência dos componentes UError, UCPU e UUser e cria em ListCS uma lista com todos os UCS do form e chama o Initialize de cada cs. Se faltar algum componente ou o initialize de algum cs falhar (retornar false) então interrompe o processo e retorna false. |
procedure IniWriteKey(pchave:string;pvalor:string); | Escreve no arquivo ini com o mesmo nome do executável e no objeto USys.INI o valor pvalor na chave pchave. | |
procedure VersionCheck; | Compara o número da versão que está gravado no arquivo ini com a versão do executável. Se o executável possui uma versão superior chama o evento BeforeNewVersion, atualiza a versão no Ini e chama o AfterNewVersion. | |
function CSCount : integer; | Retorna quantidade de CS do form. | |
function SearchCS(s:string): TUCS; | Recebe o nome de um cs e retorna a instância. Se não existe retorna nil. | |
function SearchPSExe(pcs,pps:string;pincludedependent:boolean=False):TComponent; | Recebe o nome de um ps e retorna a instância. Se não existe retorna nil. | |
function FormClassOf(pcs,pps:string):TFormClass; | Retorna o tipo de form do processo informado | |
function NewPS(pcs,pps:string;pdependent:TComponent=nil):TComponent; | Cria e retorna uma nova instância PS do pcs. Onde o seu CS será o pcs e sua propriedade Dependent será o pdependent. É isso mesmo? Quando devo usa esta função? | |
function AnyPS(pcs,pps:string;pincludedependent:boolean=False):TComponent; | Retorna o PS pps. Se a instancia não existe, cria. | |
procedure BroadCast(o:TObject); | Repassa o objeto para o sistema inteiro (para todos os PS do sistema). Para que serve exatamente? | |
procedure AtualizeBarraTarefas; | Atualiza os botões da barra de tarefas, de forma que exista um botão para cada OS instanciado. | |
property ExePars : TUPars read FExePars write FExePars; | Lista de parâmetros passados na chamada do executável. | |
property Ini : TUpars read FIni write FIni; | Parâmetros do sistema, lidos do arquivo de inicialização. | |
property PSs : TUPars read FPSs write FPSs; | Lista dos PS instanciados. | |
property PSn : integer read FPSn write FPSn; | Número de PSs instanciados. | |
property PSb : TList read FPSb write FPSb; | Lista com o nome dos botões da barra da tarefas. | |
published | ||
property Description : TStringList read GetDescription write SetDescription; | Breve descrição do objetivo desta instância. | |
property Documentation: TStringList read GetDocumentation write SetDocumentation stored false; | Documentação para esta instância. | |
property Development : TStringList read GetDevelopment write SetDevelopment stored false; | Observações sobre o desenvolvimento. | |
property ID : string read FID write SetID; | para registro do windows. | |
property Version : string read FVersion write FVersion; | Versão do sistema. | |
property TaskBar : TWinControl read FTaskBar write SetTaskBar; | Barra de tarefas do form principal. | |
property BeforeNewVersion : TBeforeNewVersionEvent read FBeforeNewVersion write FBeforeNewVersion; | Este evento é disparado pelo VersionCheck quando o executável for uma nova versão. | |
property AfterNewVersion : TAfterNewVersionEvent read FAfterNewVersion write FAfterNewVersion; | Este evento é disparado pelo VersionCheck depois do BeforeNewVersion e depois de atualizar a versão. |
UUser
- Detém as informações do usuário que está logado.
- Property UserControl: boolean read FUserControl write FUserControl default True;
- para que serve?
- property UserID: string read FUserID write SetUserID;
- ID do usuário (Login);
- property UserName: string read FUserName write FUserName;
- Nome do usuário (para exibição)
- property UserPassword: string read FUserPassword write FUserPassword;
- Senha do usuário que está logado.
UErros
- A idéia deste componente é ele receber e tratar todas as mensagens de erro do sistema. Entretanto, este componente ainda não teve nenhuma funcionalidade implementada (até hoje 11/12/2006).
UCS
Componente de Sistema.
- Gerencia a troca de mensagens entre um determinado grupo de processos de sistema.
UPS
- Processos de Sistema.
UPSCad, UPSSel, UPSRel
- São componentes idênticos ao UPS (até hoje 11/12/2006).
- Para um processo que representa um form de cadastro deve ser utilizado o UPSCad.Para um form de seleção o UPSSel, para um form de relatório um UPSRel e para outros forms ou processos o UPS.
USeg
Controle de segurança do sistema.
- Determina quando um usuário pode ter acesso a uma determinada função.
- Grava quando que cada registro foi incluído ou alterado pela última vez. Possui a função de gravar um log dos registros excluídos.
UDatabase
- Contém a informação do tipo de banco de dados.
- Deve ser utilizado e têm a relação de quais componentes de conexão utilizar para cada banco de dados.
UMaskEdit
- Igual ao UEdit com opção de máscara para digitação.
UDateEdit
Igual ao UEdit com máscara para digitação de datas.
- Valor : Variant, Valor de edição.
UNumericEdit
- Igual ao UEdit com alinhamento à esquerda e com propriedades para digitação de números:
DecimalPlaces, PermiteNegativo
UComboBox
- Em Uitens colocar os valores como Sim|S então aparece Sim no combo mas o valor dele é S
UCheckBox
Checkbox que permite determinar o valor e imagem para marcado e desmarcado.
- Domínio, Valores possíveis, na mesma seqüência das imagens do IL.
- IL, ImageList com as imagens para o checkbox.
- FirstImage, LastImage, número da primeira e última imagem do IL para utilizar.
- Valor, contém o valor atual do campo.
- Valor.Type, contém o tipo dos valores do campo.
- No componente Q selecionando o campo do checkbox preencher o Edicao com o nome do campo no banco, e também preencher o INICIALIZA com o valor inicial do checkbox, caso contrario não funciona.
DataSeeker
(Atualizar e transferir para o capítulo 2)
Serve para procurar um valor no banco de dados, normalmente utilizado para procurar um valor que é chave estrangeira para preencher um formulário. Este componente possui um Query próprio e a função de buscar conforme a digitação do usuário.
- HideOnExit - se a propriedade Visible é por padrão false e ele deve sumir depois de utilizado, esta propriedade deve ser true.
- HotKeys - defina até 6 Hotkeys para quando o usuário estiver com foco no dataseeker. Cada uma delas dispara o seu evento correspondente (OnHotkey1-6).
- NextCtrl - defina qual o controle que deve receber foco quando o usuário tirar o foco do DataSeeker.
- OrdemInicial - nome do campo que o SQL traz ordenado por padrão.
- Query - componente query para conexão com o banco
- Active - ativa a conexão.
- SingleFields - quando SingleQuery é true, então escrever aqui separado por vírgulas o nome dos campos que devem ser retornados.
- SingleQuery - quando true não é necessário informar um SQL, apenas o nome da tabela e os SIngleFIelds. Mas se o SQL precisa de algum JOIN, informe false nessa propriedade e escreva o SQL.
- SQL - quando SingleQuery é false determina o SQL que vai ser executado para buscar os dados utilizados na busca.
- UDatabase - conexão com o banco de dados.
- GridColumns - define as colunas do Dataseeker, incluir manualmente.
- FieldName - nome do campo retornado pelo SQL que a coluna representa.
- Title.Caption - Rótulo da coluna.
- Width - Tamanho da coluna
- SortFields - escrever em cada linha o nome de um campo que pode ser ordenado e buscado.
UPars
- Lista de parâmetros. Não entendi como funciona.
TURel
Componente para montar relatórios em modo texto, possui vários recursos para facilitar o desenho do layout do relatório. É organizado em impressão de uma parte fixa do relatório e impressão do corpo do relatório.
- BodyLines - Quantidade de registros do corpo (detalhe) que cabe em uma página.
- BodyStart - Número da linha onde inicia o corpo do relatório.
- LeftOffSet - Número de colunas em 20cpi que o relatório deve ser deslocado em relação à margem esquerda.
- ModeFileRep - mdAssignedFile = Saída em AssignFile(...,Port). mdCreateFile = Saída em CreateFile(Port...
- PageLength - Número de linhas equivalente à altura da página. Uma página Carta, com 6LPI contém 64 linhas. Esta propriedade serve apenas para configurar a impressora depois de quantas linhas deve ser dado o saldo de página.
- *Port - porta de impressão ou caminho e nome de arquivo de saída.
- PrinterType - define o conjunto de comandos de impressão a utilizar (ptEpson, ptHP).
- Spacing - número de linhas por polegada (sp6LPI ou sp8LPI)
- TopOffSet - Número de linhas que o relatório deve ser deslocado em relação ao topo da página.
- OnPrintBody - Incluir aqui a rotina que imprime um registro do corpo (detalhe) do relatório. Quando for o último registro, o parâmetro pLast deve ser setado para true. Se pLast nunca for true o programa entrará em loop e ficará chamando este evento indefinidamente. Para o relatório ter alguma saída é obrigatório que este evento esteja implementado e gere algum texto para imprimir, ou seja em b seja atribuída alguma propriedade.
- OnPrintFixed - incluir aqui as rotinas que imprimem a parte fixa do relatório (cabeçalhos e rodapés). Se a OnPrintBody não estiver definida ou não gerar nada para imprimir então esta rotina nem é chamada.
- Colunas - Para imprimir mais de uma página por folha na horizontal, adicione colunas a esta propriedade. É necessário que exista pelo menos uma coluna.
TURelCol
É um item da propriedade Colunas, pode ser adicionado em tempo de projeto pelo ObjectInspector ou em tempo de execução;
- BufferOut - Envia todo o conteúdo do Buffer do TURel para a impressora. Este método é chamado internamente ao final de cada página. Quando estiver definido mais do que uma coluna e passar false para o parâmetro
- EndReport - ele apenas coleciona o conteúdo do Buffer no buffer da coluna ‘ProximaColuna’ e incrementa o contador ProximaColuna. Se esta for a última coluna ele manda o conteúdo para a impressora, e zera o contador ProximaColuna.
- Os campos do relatório devem ser determinados dentro dos eventos OnPrintBody e OnPrintFixed nos objetos b e f : TURelGrupo, respectivamente.
TURelColumn
Campo do relatório. Para criar uma coluna basta atribuir uma propriedade qualquer a um f[‘nomecampo’].
- Top - número da linha para imprimir o campo, em relação ao topo da página no OnPrintFixed ou em relação ao BodyStart no OnPrintBody. * A primeira linha é 0.
- Left - número da coluna para imprimir o campo e relação à margem esquerda da página em caracteres 20cpi, não importando o tamanho da fonte deste campo. A primeira coluna é 0.
- Width - número máximo de caracteres do campo.
- TextFont - tamanho da fonte: 5, 10, 12, 15 e 20cpi, que em uma impressora 80 colunas equivalem respectivamente a 40, 80, 96, 137 e 160 caracteres por linha.
- TextBold - Negrito. Se vc estiver utilizando fonte 12, 15 ou 20 cpi o texto em negrito será impresso em um caracter maior. (booleano).
- Alignment - Alinhamento. Alinha o texto à esquerda, centro ou direita dentro do campo. Para funcionar a propriedade width deve estar definida (<> 0).
- DecimalPlaces - Número de casas decimais. Uma vez atribuído, se a propriedade text contiver um número no formato ####.## o número será formatado truncando no número de casas decimais especificado e o separador decimal será a vírgula.
- ThousandSeparator - Utilizar separador de milhar. Uma vez atribuído, se a propriedade text contiver um número no formato ####.## o número será formatado com separadores de milhar. Se Decimal places não for atribuído ou for = 0, então o número será formatado como um número inteiro com separador de milhar.
- Text - Texto a ser impresso. Deve ser uma string.
UCodBarMatr
Unit com funções para impressão de código de barras em matricial. Basta incluir esta unit no uses e chamar a função codbar.
- TCodBar = (cbClean13, cbClean8, cbCLUPC, cbCL25, cbCL39);
- Tlpi = (sp6LPI,sp8LPI)
- Function clean8(codigo: string): string;
recebe o número a codificar e devolve a string q contém os comandos para imprimir uma linha com código de barras
- Codbar(código): string; tipo: TCodBar; ultlin: boolean; lpi: Tlpi; left : integer) - função criada para impressão de código de barras no mapa e protocolo do unilabw
- retorna uma string contendo os comandos que devem ser enviados para uma impressora padrão Epson com uma linha do código de barras selecionado. Se ultlin for false, imprime uma linha, salta meia linha, imprime outra linha e deixa o salto configurado para meia linha. Para isso deve ser passado o número de linhas por polegada e a posição horizontal (left) da barra em número de caracteres 20cpi em relação à margem esquerda. Na prática este recurso é útil para utilizar esta unit em conjunto com o componente URel, onde a coluna que contém este código de barras deve ser a última coluna da linha. Este recurso evita um espaço em branco entre a primeira e segunda linha do código de barras imprimindo uma linha com o mesmo código entre as duas linhas. Quando ultlin for false na linha seguinte deve ter uma chamada à mesma função com ultlin true, que reconfigura o saldo de linha para o tamanho normal.
RBuilder: Preview Maximizada
Para gerar um report com a tela de preview maximizada e com um determinado nível de zoom. Incluir no uses:
- ppViewr
Incluir o seguinte código no evento OnPreviewFormCreate do TppReport
- R.PreviewForm.WindowState := wsMaximized;
- TppViewer(R.PreviewForm.Viewer).ZoomSetting := zsPageWidth;
Metodos e propriedades do RD
StartGroup – Inicia um grupo para inserção de conteúdo.
EndGroup – Finaliza o grupo para inserção de conteudo.
AddPage – Adiciona uma quebra de Página. *Não pode ser chamado de dentro de um grupo.
NextGroup – Retorna a posição vertical para impressão do próximo grupo de conteúdo com base na posição onde o último conteúdo foi impresso.
CurrentLine – Retorna a posição vertical onde o último conteúdo foi impresso.
NextLine – Retorna a posição vertical seguinte ao último impresso.
Métodos para formatação de texto:
Estes métodos só podem ser chamados de dentro de um grupo e sempre que um grupo é iniciado, ele reseta estas formatações.
FontName – Seta a fonte a ser utilizada no conteúdo.
FontSize – Determina o tamanho da fonte a ser utilizada.
FontStyle – Determina o Estilo da fonte (Negrito, Itálico, Sublinhado).
Métodos para impressão de conteúdo:
Estes métodos só podem ser chamados de dentro de um grupo
TextOut – Imprime um texto na posição especificada.
TextColumn – Imprime um texto na posição especificada dentro do objeto de coluna passado por parâmetro. Permite definir o alinhamento do texto dentro da coluna.
TextAlignment – Imprime um texto na posição e alinhamento especificados por parâmetro..
Line – imprime uma linha entre as coordenadas passadas por parâmetro.
Configurando permissões
Ao criar uma nova interface, por padrão nenhuma permissão é atribuída aos usuários do sistema, com exceção do administrador que possui todos os direitos do programa.
Dependendo de sua regra ou aplicação, as permissões da interface podem exigir uma configuração avançada. A seguir estão as informações mais importantes desse processo:
Compreendendo o USeg
TUSeg é a classe responsável pela gerência de permissões no sistema Unilab. Esse componente faz parte da biblioteca R03.
Instanciada no FMain, habilita/desabilita componentes da propriedade MainMenu. A configuração do conteúdo é feito na interface UFUserCad.
Há duas propriedades que não tenho certeza da funcionalidade: Tabelas e Views.
Gerenciando permissões
Ao incluir uma interface no menu, automaticamente é criado as permissões 'Inclusão', 'Alteração', 'Exclusão' e 'Consulta' para a interface criada.
É possível visualizar tais permissões pelo menu Cadastros > Usuários, consultando o usuário de preferência e selecionando a aba Direitos.
Na interface estão as opções do menu, antecipadas pelo botão que altera a permissão para o usuário em questão.
Para realizar a leitura/escrita das permissões via código, a TUSeg possui o método USegLeiaDireito('NOME_FORM','TIPO_Operação')
Adicionando uma função específica
Algumas interfaces aplicam uma regra específica ao software, portanto, precisam de uma permissão diferenciada para realizar uma função unica.
O componente USeg possui uma propriedade Direitos utilizada para armazenar permissões especiais. Nessa propriedade, é necessário adicionar uma nova linha seguindo os parametros:
NOME_FORM | NOME_PERMISSÃO | DESCRIÇÃO_PERMISSÃO
Problemas Conhecidos
Abaixo estão listadas algumas peculiaridades da biblioteca (problemas ou bug's) que podem impedir o bom funcionamento tanto do software em si quanto o ambiente de programação.
O campo CODI
A biblioteca, hoje, trabalha a chave primária como string, e somente com esse tipo de dados;
Além disso, ela suporta um limite de nove caracteres, e para uma melhor visualização, a Uniware preenche os valores com zeros à esqueda.
Recarregando o DataSource
Quando for alterado alguma estrutura do banco de dados, será necessário recarregar o datasource da interface caso ela esteja aberta.
Para isso, alterar algum campo da interface e fechar/abrir novamente a unit. (Há casos que não é necessário a alteração da propriedade)
Remover um campo calculado
Ao remover um campo calculado da lista de TUFields, nenhum outro registro é selecionado.
Se o programador selecionar alguma interface sem antes selecionar um campo da lista,
o Delphi encerrará acusando um erro.
AJCOD, recursos necessários
Há alguns recursos necessários para funcionar o AjCod, são eles: MaxLength & SoNumeros
nota: só completa os números ao sair do campo, ok?
Aribuir "vazio" para um campo do DE
Quando for atribuir um "nada" para um campo do DE q representa uma data, atribuir null ao invés de ' '; O banco de dados prevê null ou data para campos date e datetime, mas não prevê ' ' ' (string vazia).
Chave primaria
Ao rodar a tela de seleção ou a tela de cadastro nova e o seguinte erro for apresentado: TUPars.GetValue não é variant; verificar se os TUFields referente a chave primaria no banco de dados no objeto TUQuery foram colocados como 'TRUE' no atributo 'CHAVE PRIMARIA'.
Procura label
Apesar de que no desenvolvimento estarmos sempre utilizando os componentes da biblioteca gráfica R03 e R04, o componente de label 'UProcuraLabel' não deve ser utilizado pois gera erros, por isto utilizar o label da aba 'Standard'.
HOTKEYS Para abrir telas
O F2 é usado para com o campo selcionado abrir o seeker e pegar o dado de dentro do seeker. O F5 é usado para adicionar algum item O F6 é usado para alterar um item
Para adicionar :
- Com o seeker já adicionado, va nas propriedas e HotKeys coloque:
HotKey1 = F5 HotKey2 = F6 HotKey6 = F2
Nos eventos do Seeker va em OnHotKey1 coloque:
Key := VK_F5; //campo onde chama o seeker CALCODIGPOSTOPACIENTE onde você clica para chamar CALCODIGPOSTOPACIENTEKeyDown(CALCODIGPOSTOPACIENTE,Key,[]);
Nos eventos do Seeker va em OnHotKey2 coloque:
Key := VK_F6; //campo onde chama o seeker CALCODIGPOSTOPACIENTE CALCODIGPOSTOPACIENTEKeyDown(CALCODIGPOSTOPACIENTE,Key,[]);
Nos eventos do Seeker va em OnHotKey6 coloque:
dtskrPACISeek( dtskrPACI, dtskrPACI.DataSet); // Evento on Seeker (nome seeker, nome seeker.DataSet) CALCODIGPOSTOPACIENTE.SetFocus; // focos de onde vai ficar a seta depois de fechar oseeker dtskrPACI.Visible := False; // desabilita o seeker
- Com os eventos OnHotsKey criados, vamos adicionar o local onde ele vai ser aberto, no evento KeyDown do campo que você quer que ele apareça faça:
Ok ifs vão verificar qual tecla apertou para fazer algo:
if Key = VK_F2 then begin //1 = left do campo onde vai ser chamado o seeker em baixo. //2 = heigth + top do campo para o seeker aparecer em baixo. //3 = width do seeker - o width do campo //4 = heigth do seeker //5 = é sempre true. // dtskrPACI.ShowAt([1],[2],[3],[4],[5]); dtskrPACI.ShowAt(0,243,705,201,True); dtskrPACI.Visible := True; //if do F5 verifica se o usuario tem permissão de acessar a TFPACISEL, no metodo inclusão end else if (key=VK_F5) and USegLeiaDireito('TFPACISEL','Inclusão') then begin //passa a cad, cs, forme(procurar saber se é o forme mesmo) CallCad(umodoINCLUSAO,'pediPaciCad','paci','paciCad'); //if do F6 verifica se o usuario tem permissão de acessar a TFPACISEL, no metodo Alteração end else if (key=VK_F6) and USegLeiaDireito('TFPACISEL','Alteração') then begin // k é um objeto que guarda o valor do DE[] para quando atualizar, salvar no objeto referente. k:=TUPars.Create; try if not Vazio(DE['CCODIPACI']) then begin k['CCODIPACI']:=IfNull(DE['CCODIPACI'],); k['CCODIPOST']:=IfNull(DE['CCODIPOST'],); k['CNOMEQQ']:=IfNull(DE['CNOMEQQ'],); //ex: CallCad(modo referente),("nome para chamada que vai ser usado no eventoOnDataAnswer) ,(pedi, cs qual eu quero abrir), (paci de quem eu quero abrir),(K referente objeto) CallCad(umodoALTERACAO,'pediPaciCad','paci','paciCAD',k); end else begin MsgErro('Selecione o Paciente a ser alterado.'); end; finally k.Free; end; end;
- Agora vamos jogar os campos do seeker na nossa cad, no evento do OnSeek coloque :
//os meus campos De[] vão receber os campos que eu trouxer do seeker, repare que o meu no evento do seeker OnGetSQL tem um SQL que são os que eu quero trazer na seeker para minha cad //ex DE['nome do meu campo na tabela'] := DataSet.FieldByName('nome do meu campo que eu estou querendo no select do evento OnGetSQL').AsString DE['CALCODIGPOSTOPACIENTE'] := DataSet.FieldByName('CCODIPOST').AsString + DataSet.FieldByName('CCODIPACI').AsString ; DE['CNOMEQQ'] := DataSet.FieldByName('CNOMEPACI').AsString; DE['CCODIPACI'] := DataSet.FieldByName('CCODIPACI').AsString;
- Pronto, isso já deve fazer as telas serem abertas, para atualizar os dados vá na cadData, no evento OnDataAnswer coloque o codigo abaixo para atualizar os dados.
//if $pediPaciCad é o identificador que foi colocado no nome la no F6 if pmsg.CheckName('$pediPaciCad') then begin if pmsg.CheckMsg('MirrorClose') then begin if pmsg['MirrorCloseSuccess'] then begin DE['CCODIPOSTPACI']:=pmsg['CCODIPOST']; // nome na minha DE['Campo da Minha tabela'] := pmsg["que vem da seeker"]; DE['CCODIPACI']:=pmsg['CCODIPACI']; DE['CNOMEQQ']:=pmsg['CNOMEQQ']; dtskrPACI.Close; dtskrPACI.Open; end; end end;
Lista de exercicios
Tarefas
- Para a tarefa, será necessário adicionar uma tabela no seu banco Unilabw de Teste, faça uma tabela com lb_'seunome'
- Sua tabela deve ter os campo
- Referente a um nome
- Referente a uma chave primaria
- Referente as 2 FK da lb_paci e lb_post
- Referente a um numero inteiro
- Referente a um numero Deimal
- Referente a uma Data
- Referente a um enumerado com 3 opções, para usar o combobox
- Referente a um enumerado com 2 opções, S, N para usar o checkbox
- Essa tabela deve ter um relacionamento com a tabela lb_paci e lb_post, onde você vai puxar o ccodipaci da lb_paci e ccodiposto da lb_post para formar sua chave composta
- Criar SEL
- Quando a Sel carregar ela deve mostrar todos dados da sua tabela.
- Criar CAD
- Com sua CAD contendo todos campos da sua tabela, incluiu um campo calculado, um combobox, um checkbox
- Faça um campo calculado que quando você recebe os 8 digitos, 2 referente ao posto e 6 referente ao codigo do paciente faça um select na lb_paci e coloque o nome da busca, no campo da sua Cad referente ao nome, para ser salva na lb_'seunome'
- Com a busca do campo calculado pegue os 8 digitos salve os 2 primeiros referente ao posto na sua tabela no campo referente ao nome e faça o mesmo para o codigo do paciente, a chave primaria da sua tabela deve ser autocomplementar automatico, os campos do codigo do posto e codigo do paci são usados para formar sua chave composta.
- Deixar os combos e cheks funcionando gravando no banco
- Mestre detalhe criar uma tabela lb_'seunome'Detalhe
- Deve ter os campos:
- Referente a chave primaria
- Referente a chave estrangeria da lb_'seunome', onde recebe a ccodipaci, nome tem que ser o mesmo ex: se na fk você usou ccodipaci e ccodipost na mestre, na detalhe tem que ter ccodipaci e ccodipost
- Referente a chave estrangeria da lb_'seunome', onde recebe a ccodipost, nome tem que ser o mesmo também.
- Deve ter os campos:
- Seeker
- Colocar no botão calcular quando apertar F2 abrir o seeker
- F2 para selecionar o paciente em questão e o codigo ir para o campo calculado e o nome no campo de nome
- F5 para incluir um novo, onde o codigo do cliente já esta no campo calculado, apertar F5 para incluir
- F6 seguindo a mesma logica do F5 porem para o F6 para alterar.
- Incluir e alterar deve ser atualizado o seeker e o campo de nome com o novo que foi incluso ou alterado
- Criar relatorio
- Criar relatorio usando as ordens desc e asc com mais de uma opção ex: nome do paciente, codigo do posto, data
Padrões
Utilizar os padrões de escrita de código e edentação da empresa.
Criando relatórios
Existem dois tipos de relatórios no unilab, os que são gerados em PDF e em planilha, neste ponto da wiki será mostrado o passo a passo para gerar os dois modelos.
Criando a tela
1. O primeiro passo é criar uma nova tela para que o cliente consiga gerar este relatório, para isso você pode clicar em FILE > NEW > VCL Form - DELPHI
Após criar o novo formulário, será preciso fazer 4 coisas iniciais:
- Mudar o nome do form para o padrão F+funcionalidade+Rel. - Salvar o arquivo .pas para a pasta padrão de relatórios, conforme a função do relatório. Ou seja, se o relatório for referente a um cadastro, salvar ele em Source > Relatórios > cadastros e assim por diante. Lembrando que o padrão para arquivos .pas é UF+funcionalidade+Rel.pas. - Apagar a linha Application.CreateForm(nomedoseuform, nomedoseuform) da view source. Para fazer isso, basta ir em Project > View Source e dar um Ctrl + Y na linha que estiver com o novo form. - Mudar a propriedade FormStyle do form para fsMDChild.
Feito os passos iniciais, podemos preparar nossa tela para colocar os componentes de filtro, todos os componentes devem ficar em um TPanel, a cor do TPanel deve ser a padrão do sistema($00E6E6E6), os botões para impressão devem ficar em um groupbox(para agilizar, recomendo procurar um relatório que ja possua estes botões e copie e cole no seu form(relatório de exemplo: UFPrecoExamApoRel)), buscando um resultado como este:
Concluído a parte acima, podemos colocar os componentes de filtro, geração do pdf, execução da query e caso faça sentido para o relatório pode ser adicionado também o componente SalvaTela. No relatório de exemplo irei colocar os seguintes componentes:
Visuais:
TSelectBoxCaller - para filtrar em cadastros específicos podendo selecionar de 1 até n.
TUComboBox - para filtrar os dados em "grupos", exemplo(todos os cadastros que possuem sexo Feminino).
TUDateEdit - para filtrar em períodos específicos.
TUOrdemCombo - para definir qual coluna eu quero ordenar e ascendente ou decrescente.
Não visuais:
TSuReportData - Gerar os pdfs.
TUQuery - Executar o select para montagem da query.
TSalvaTela - Para salvar os filtros do usuário quando a tela do relatório for fechada.
Após incluir os labels e renomear os componentes, este é o resultado da tela:
Para chamar o formulário pelo unilab é bem simples, basta dar um Ctrl + F12 e procurar a UFmain e abrir a do projeto unilab. Com ela aberta, clique neste componente:
Irá abrir essa tela:
Feito isso, identifique a qual grupo esse relatório faz parte e adicione a opção dele no menu correspondente(se for um relatório de cadastros adicione em Relatórios> Cadastros> Seumenu), agora já ira aparecer a opção para você selecionar e chamar seu formulário, porém ainda não estará funcionando. Abra o código da UFMain(clicando em code ao lado de Design ou pressione F12), antes de programar a parte de chamar o formulário é preciso que ele seja incluído no bloco Uses da ufmain, nela tem 2 blocos de uses inclua no segundo. Deverá ficar assim:
Agora podemos programar a parte de abrir o formulário, volte no componente de menu da ufmain, e de dois cliques na nova opção de menu adicionada, neste caso a nova opção será 'Exemplo'. Após dar duplo click, irá criar uma função e será direcionada pra ela, nessa função basta colocar a seguinte chamada:
- ChamaForm(TFExemploRel);
Com isso, a chamada do form já deverá funcionar.
Incluindo ícones na tela e salva tela
- procedure TFExemploRel.FormCreate(Sender: TObject); - begin - SalvaTela.Load; - colocarImagemNoBotao(bImprimir, 'bt_imprime'); - colocarImagemNoBotao(bFechar, 'bt_fecha'); - colocarImagemNoBotao(btnPlanilha, 'bt_planilha_relatorios'); - end;
Este é o resultado:
Para usar o salva tela é preciso definir a propriedade UDatabase: FMain.UDB e Useg:FMain.USeg.
- procedure TFExemploRel.FormDestroy(Sender: TObject); - begin - SalvaTela1.Save; - end;
Montando a query
Neste ponto iniciaremos os primeiros passos para buscar as informações que apresentaremos no relatório. Será preciso criar uma procedure que ficará responsável por rodar o select. Exemplo:
- procedure TFExemploRel.MontaQuery; - begin - Q.SQL.Clear; - Q.SQL.Text:= 'SELECT XA.CCODIXANDE, '+ - ' CDESCXANDE, '+ - ' ESEXO, '+ - ' DDATANASC, '+ - ' ULIBUINC, '+ - ' CCODIQLD, '+ - ' CDESCQLD, '+ - ' NPTS '+ - ' FROM LB_XANDE2 XA '+ - 'LEFT JOIN LB_QLDXANDE QLD ON XA.CCODIXANDE = QLD.CCODIXANDE '+ - ' WHERE TRUE '+ - slcCadastros.getSQLText + - IfStr((SEXO.ItemIndex > 0),'AND ESEXO = :ESEXO',) + - ' AND DDATANASC BETWEEN :DATAINI AND :DATAFIM '+ - ' ORDER BY '; - if(ESEXO.ItemIndex > 0) then begin - Q.GraveParametro('ESEXO', copy(ESEXO.Items[ESEXO.ItemIndex],1,1),ftString); - end; - Q.GraveParametro('DATAINI',DDATANASCIni.Text,ftDateTime); - Q.GraveParametro('DATAFIM',DDATANASCFim.Text,ftDateTime); - - if (cbxOrdem.Combo.ItemIndex = 1) then begin - Q.SQL.Text := Q.SQL.Text + 'CDESCXANDE '; - end else begin - Q.SQL.Text := Q.SQL.Text + 'CCODIXANDE'; - end; - - Q.SQL.Text := Q.SQL.Text + ifStr(cbxOrdem.Descendente, ' DESC', ); - end;
- Explicando a função
- Q.SQL.Clear; - Limpa a propriedade SQL e evita a execução da query com lixo.
- slcCadastros.getSQLText - é o nosso TSelectBoxCaller, essa propriedade getSQLText trata as opções selecionados para serem usadas em um select, então ela vem com um AND e depois as opções, por isso colocamos este WHERE TRUE para que na execução fique WHERE TRUE AND opções e não WHERE AND opções.
- IfStr() - essa função ela compara se o primeiro parâmetro é verdadeiro, caso seja retorna o segundo parâmetro, do contrário retorna o terceiro. Ou seja, no exemplo se o index selecionado no combobox for maior que 0, ele adiciona a condição AND SEXO = alguma coisa no where. Para utilizar o IfStr deve ser incluído UStringUtil na uses.
- GraveParametro() - No select temos :SEXO, :DATAINI e :DATAFIM, o GraveParametro serve para substituir esses textos pelo valor do segundo parametro da função. Então em um exemplo de data, o Graveparamentro vai buscar o texto DATAINI(no select) e substituir pelo nosso dataedit(segundo parametro da função GraveParametro) o terceiro parametro é o tipo de dado. Para utilizar o ftString ou ftDatetime, deve ser dado uses na Data.DB
Gerando PDF
Os relatórios do unilab são separados em colunas, por isso antes de iniciar a montagem do relatório precisamos criar as colunas que serão utilizadas. As colunas são do tipo TSuRColumn, então para criá-las precisa dar uses na clase UTSuRPage. Precisamos também de uma variável para controlar o número da página, armazenar a data de hoje e o nome do laboratório, para orelatório de exemplo a declaração ficou assim:
Toda pagina ela tem um valor fixo 100000 de uma margem a outra. Então, por padrão, o unilab define uma margem de 5 mil em cada um dos lados; por isso, pode ser criado duas constantes uma para definir a margem em 5 mil e outra para definir o fim da página em 95 mil, pois assim chegando em 95 mil é gerado uma nova pagina.
Para gerar o relatório precisamos de 4 eventos do TSuReportData: RDStartReport, RDPage, RDNewPage, RDEndPage.
- RDStartReport
- procedure TFRelXande.RDStartReport(Sender: TObject); - var - vPos: integer; - begin - FPagina:= 1; - FDataImpressao:= Now; - FNomeLaboratorio:= ConfigSis('CADLABORATORIO'); - - RD.EndPosition := INICIO_RODAPE; - vPos:= MARGEM; - colXANDE:= RD.NewColumn(vPos,10000,rpLeft); Inc(vPos,10500); - colDesc:= RD.NewColumn(vPos,43000,rpLeft); Inc(vPos,43500); - colSexo:= RD.NewColumn(vPos,5000,rpLeft); Inc(vPos,5500); - colDataNas:= RD.NewColumn(vPos,20000,rpLeft); Inc(vPos,20500); - colUsuario:= RD.NewColumn(vPos,10000,rpLeft); - end;
Este é o primeiro evento a ser disparado, por isso deixamos as coisas iniciais nesta função.
1º FPagina recebe 1 para identificarmos que é a primeira pagina do relatório.
2º FDataImpressao recebe a data atual, para utilizarmos no rodapé do relatório no texto "Impresso em...."
3º FNomeLaboratorio recebe o nome direto defino em Cadastros > Configurações > Sistema. Para utilizar a função ConfigSis() deve incluir UConfigSis na uses
4º RD.EndPosition recebe os 95 mil, sinalizando ao componente que quando chegar nessa marca deve ser gerado uma nova pagina.
5º vPos recebe os 5 mil da Margem, para definirmos as posições das colunas.
A primeira coluna é a colXande ela vai ser criado iniciando na posição 5 mil, com 10000 de espaçamento e seu texto ficará alinhado a esquerda. Após ser criada essa coluna, executamos um Inc adicionando 10500 na vPos que vale 5 mil. Ou seja a próxima coluna vai iniciar com um espaçamento de 500 da coluna anterior. Visualizando:
- RDPage
- procedure TFExemploXande.RDPage(Sender: TObject); - var - vPosicao: Integer; - vCodigoAtual: string; - begin - RD.StartGroup(0,RD.NextGroup,False); - vCodigoAtual := Q.AsString('CCODIXANDE'); - while (not Q.Eof) and (not RD.Aborted) do begin - RD.TextColumn(colXANDE,RD.NextLine, Q.AsString('CCODIXANDE')); - RD.TextColumn(colDesc,RD.CurrentLine, Q.AsString('CDESCXANDE')); - RD.TextColumn(colSEXO,RD.CurrentLine, Q.AsString('ESEXO')); - RD.TextColumn(colDataNas,RD.CurrentLine, Q.AsString('DDATANASC')); - RD.TextColumn(colUsuario,RD.CurrentLine, Q.AsString('ULIBUINC')); - if(Q.AsString('CCODIQLD') <> )then begin - RD.FontStyle([fsBold]); - RD.TextColumn(colDesc,RD.NextLine, 'Qualidades:'); - RD.FontStyle([]); - RD.TextColumn(colDesc,RD.NextLine, 'Descrição'); - RD.TextColumn(colSexo,RD.CurrentLine, 'Pontos'); - while (vCodigoAtual = Q.AsString('CCODIXANDE')) and (not Q.Eof) do begin - RD.TextColumn(colDesc,RD.NextLine, Q.AsString('CDESCXANDE')); - RD.TextColumn(colSexo,RD.CurrentLine, Q.AsString('NPTS')); - Q.Next; - end; - end else begin - Q.Next; - end; - vCodigoAtual := Q.AsString('CCODIXANDE'); - end; - RD.EndGroup; - end;
1º Executamos um RD.StartGroup(posição x onde iniciara o texto(deixar 0), RD.NextGroup para iniciar onde terminou o group anterior, keeptogether define se será impresso junto).
2º while (not Q.Eof) and (not RD.Aborted) do begin - Executa enquanto o retorno da query estiver sendo lido e a geração do relatório não tiver sido abortada.
3º RD.TextColumn(colXANDE,RD.NextLine, Q.AsString('CCODIXANDE')); - Define que na coluna colXande, na próxima linha será escrito o valor de Q.AsString('CCODIXANDE').
4º RD.TextColumn(colDesc,RD.CurrentLine, Q.AsString('CDESCXANDE')); - Define que na coluna colDesc, na mesma linha anterior será escrito o valor de Q.AsString('CDESCXANDE').
E assim por diante, preenchendo as demais colunas. Nesse relatório temos o exemplo de um mestre/detalhe, onde o if 'if(Q.AsString('CCODIQLD') <> )then begin' verifica se tem algo preenchido como detalhe e se estiver imprime antes de ir para o proximo registro mestre.
- RDNewPage
- function TFExemploRel.RDNewPage(o: TObject): Integer; - var - vPosicao: Integer; - begin - if RD.Aborted then begin - Result :=0; - end else begin - - if(FPagina = 1)then begin - ReportPrimeiraPagina(RD, MARGEM, RD.Title); - RD.FontSize(10); - RD.ImprimeFiltro(MARGEM, RD.NextLine+500, slcCadastros.Text, 'Cadastros', 8, -500); - - end else begin - RD.StartGroup(0,RD.NextGroup,True); - ReportDemaisPaginas(RD,MARGEM,RD.Title,FNomeLaboratorio); - end; - RD.Line(MARGEM,RD.NextLine+100,95000,RD.NextLine+100); - vPosicao:= RD.NextLine; - RD.FontSize(8); - RD.TextColumn(colXANDE,vPosicao,'Código'); - RD.TextColumn(colDesc,vPosicao,'Descrição'); - RD.TextColumn(colSEXO,vPosicao,'Sexo'); - RD.TextColumn(colDataNas,vPosicao,'Data de Nascimento',1); - RD.TextColumn(colUsuario,vPosicao,'Incluído por'); - - RD.Line(MARGEM,RD.NextLine+200,95000,RD.NextLine+200); - inc(FPagina); - Result:= RD.EndGroup; - end; - - end;
Essa função serve para criação das colunas iniciais e seus respectivos textos. Ela é chamada sempre que atinge os 95 mil do rodapé, cria uma nova pagina, monta os cabeçalhos das colunas e chama a RDPage.
- RDEndPage
- procedure TFExemploRel.RDEndPage(Sender: TObject); - begin - ReportRodapePadrao(RD, 2500, 96000, FDataImpressao); - end;
Acionado ao chegar no fim da página, imprime o rodapé de impressão.
Gerando Planilha
Primeiramente precisa ser incluído no uses as seguintes classes: UAuxReport,Uplanilha,UFOpenDialog, UFSaveDialog, UBDTime, UAuxGlobal e UFMain.
Código Base
- procedure TFExemploRel.GeraPlanilha; - const - CODIGO = 1; - DESCRICAO = 2; - SEXO = 3; - DATANASCE = 4; - USUARIO = 5; - - var - vPlan : TWorkBookPool; - vSaveDlg : TFSaveDialog; - - vStFil, - vStCol, - vFileName, - vStCab : String; - i, vMescla, - vFile : integer; - vCodigoAtual: string; - - begin - vSaveDlg := TFSaveDialog.Create(GlobalDataCenter); - FNomeLaboratorio:= ConfigSis('CADLABORATORIO'); - try - - vSaveDlg.Filter := 'Planilha XLS|*.xls|Planilha XML|*.xml'; - if SalvarPlanilha(vSaveDlg) then begin - vFileName := vSaveDlg.FileName; - vPlan := TWorkBookPool.Create(False); - vFile := vPlan.NewFile(vFileName); - BDTime.DesativarGuardiaoDoTempo; - Screen.Cursor:= crHourGlass; - Try - vStCab := vPlan.WorkBook[vFile].Styles.AddStyle; - vPlan.WorkBook[vFile].Styles[vStCab].Font.Name := 'Arial'; - vPlan.WorkBook[vFile].Styles[vStCab].Font.Size := 11; - vPlan.WorkBook[vFile].Styles[vStCab].Font.Style := [fsBold]; - vPlan.WorkBook[vFile].Styles[vStCab].VAlign := vaCenter; - - i := 2; - vPlan.Cell(vFile,1,i,CODIGO).setProp('Mesclar',4).setProp('Style',vStCab).value := FNomeLaboratorio; - inc(i); - - vPlan.Cells[vFile,1,i,CODIGO] := 'Código'; - vPlan.Cells[vFile,1,i,DESCRICAO] := 'Descrição'; - vPlan.Cells[vFile,1,i,SEXO] := 'Sexo'; - vPlan.Cells[vFile,1,i,DATANASCE] := 'Data de nascimento'; - vPlan.Cells[vFile,1,i,USUARIO] := 'Incluído por'; - - vCodigoAtual := Q.AsString('CCODIXANDE'); - while (not Q.Eof) and (not RD.Aborted) do begin - vPlan.Cells[vFile,1,i,CODIGO] := Q.AsString('CCODIXANDE'); - vPlan.Cells[vFile,1,i,DESCRICAO] := Q.AsString('CDESCXANDE'); - vPlan.Cells[vFile,1,i,SEXO] := Q.AsString('ESEXO'); - vPlan.Cells[vFile,1,i,DATANASCE] := Q.AsString('DDATANASC'); - vPlan.Cells[vFile,1,i,USUARIO] := Q.AsString('ULIBUINC'); - inc(i); - if(Q.AsString('CCODIQLD') <> )then begin - vPlan.Cells[vFile,1,i,DESCRICAO] := 'Qualidades:'; - inc(i); - vPlan.Cells[vFile,1,i,DESCRICAO] := 'Descrição'; - vPlan.Cells[vFile,1,i,SEXO] := 'Pontos'; - inc(i); - while (vCodigoAtual = Q.AsString('CCODIXANDE')) do begin - vPlan.Cells[vFile,1,i,DESCRICAO] := Q.AsString('CDESCXANDE'); - vPlan.Cells[vFile,1,i,SEXO] := Q.AsString('NPTS'); - inc(i); - Q.Next; - end; - end else begin - Q.Next; - end; - vCodigoAtual := Q.AsString('CCODIXANDE'); - end; - FinalizaPlanilha(vPlan,vFile,vFileName); - finally - vPlan.Free; - BDTime.ReAtivarGuardiaoDoTempo; - Screen.Cursor := crDefault; - end; - end; - finally - vSaveDlg.Free; - end; - end;
Os pontos mais importantes desse é estilização da celula: vStCab := vPlan.WorkBook[vFile].Styles.AddStyle; vPlan.WorkBook[vFile].Styles[vStCab].Font.Name := 'Arial'; vPlan.WorkBook[vFile].Styles[vStCab].Font.Size := 11; vPlan.WorkBook[vFile].Styles[vStCab].Font.Style := [fsBold]; vPlan.WorkBook[vFile].Styles[vStCab].VAlign := vaCenter;
Essa parte mesma 4 colunas na linha 2(valor de i) e adiciona nessa linha o nome do laboratório. vPlan.Cell(vFile,1,i,CODIGO).setProp('Mesclar',4).setProp('Style',vStCab).value := FNomeLaboratorio;
Monta os titulos da coluna, onde i representa a linha e o ultimo parametro representa o numero da coluna:
vPlan.Cells[vFile,1,i,CODIGO] := 'Código'; vPlan.Cells[vFile,1,i,DESCRICAO] := 'Descrição'; vPlan.Cells[vFile,1,i,SEXO] := 'Sexo'; vPlan.Cells[vFile,1,i,DATANASCE] := 'Data de nascimento'; vPlan.Cells[vFile,1,i,USUARIO] := 'Incluído por';
Sempre que for ir pra próxima linha incremente no i.