Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Editorial
Ol amigos,
THE CLUB
Av. Celso Ferreira da Silva, 190
Jd. Europa - Avar - SP - CEP 18.707-150
Informaes: (0xx14) 3732-3689
Suporte: (0xx14) 3733-1588 - Fax: (0xx14) 3732-0987
Internet
http://www.theclub.com.br
Cadastro: cadastro@theclub.com.br
Suporte: suporte@theclub.com.br
Informaes: info@theclub.com.br
Dvidas
Correspondncia ou fax com dvidas devem ser
enviados ao - THE CLUB, indicando "Suporte".
Opinio
Se voc quer dar a sua opinio sobre o clube em
geral, mande a sua correspondncia para a seo
"Tire sua dvida".
Reproduo
A utilizao, reproduo, apropriao,
armazenamento em banco de dados, sob qualquer
forma ou meio, de textos, fotos e outras criaes
intelectuais em cada publicao da Revista
The Club so terminantemente proibidos sem
autorizao escrita dos titulares dos direitos
autorais.
Aqui estamos com mais uma edio da The Club Megazine trazendo at voc
muita informao para facilitar seu dia-a-dia.
Comeamos com um excelente artigo do nosso amigo Marcelo Nogueira, onde ele
trata sobre a gesto de riscos em projetos de software, no deixe de conferir.
Continuando, nosso consultor Claudinei Rodrigues demonstra em seu artigo
vrias dicas acerca do componente TWebBrowser o qual encapsula o navegador
Microsoft Internet Explorer permitindo ao programador adicionar timos recursos
sua aplicao.
Na seqncia, nosso consultor Andr Colavite apresenta uma soluo para criar
arquivos PDFs via Delphi utilizando um componente gratuito o qual tambm pode ser
utilizado em conjunto com o QuickReport, e dessa forma exportar seus relatrios para
formato PDF.
Ainda falando em QuickReport, nosso consultor Alessandro Ferreira preparou um
artigo especial sobre o QuickReport onde demonstra como criar relatrios no triviais
com este gerador que ainda bastante utilizado meio a comunidade Delphi.
E finalizando esta edio, trazemos nossa sesso Perguntas & Respostas onde
apresentamos algumas das solicitaes feitas aos nossos consultores neste ms.
Abrao e sucesso todos,
Diretor - Presidente
Mauro SantAnna
Colaboradores
Emerson Facunte, Marcelo Nogueira
Editorial ............................................................................
Gesto de riscos em projetos de software ....................
Usando o componente TWebBrowser ..........................
Criando um arquivo PDF a partir do Delphi ..................
Explorando o QuickReport .............................................
Perguntas & Respostas ..................................................
MeGAZINE
03
04
08
12
16
28
Delphi
Gesto
Gesto de
de riscos
riscos em
em projetos
projetos de
de software
software
Por Marcelo Nogueira
MeGAZINE
Delphi
Pelo menos 50% dos grandes projetos de software estouram
seu oramento e seu prazo.
2/3 dos projetos de software muito grandes so cancelados
Esquema de
Classificao de
Riscos
Descrio
Alto
A correo de irregularidades
ou a implementao de
melhorias apresentam risco alto
de impacto negativo no projeto.
Mdio
A correo de irregularidades
ou a implementao de
melhorias apresentam risco
mdio de impacto negativo no
projeto.
Baixo
A correo de irregularidades
ou a implementao de
melhorias apresentam risco
baixo de impacto negativo no
projeto.
Zero
A correo de irregularidades
ou a implementao de
melhorias apresentam risco
desprezvel de impacto negativo
no projeto.
antes do final.
Os usurios no ficam satisfeitos com 25% dos produtos
comerciais para PC, 30% dos produtos comerciais para
mainframe e 40% dos produtos feitos por encomenda.
Tipicamente, 50% do patrimnio de software das empresas
no so usados.
Atritos entre a rea de tecnologia da informao e a alta
gerncia ocorrem em mais de 30% das organizaes.
Atritos com clientes ocorrem, no desenvolvimento de
aplicativos, em 50% dos contratos por administrao e 65% dos
contratos por empreitada.
O risco de projeto pode ser estimado qualitativamente. O
principal objetivo da anlise de riscos desenvolver um conjunto
de estratgias de preveno de riscos.
Gesto de Riscos
Tabela 1
Esquema de classificao de riscos - IEEE [3].
MeGAZINE
Delphi
projetos enfrenta.
monitorados:
Risco
Gravidade
legais;
Tecnolgicos;
devidos ao tamanho e complexidade do produto;
relativos a pessoal;
relativos aceitao pelos usurios;
Tecnologia
Pessoal
Organizacional
Ferramentas
Requisitos
Tabela 2
Exemplo de Estimativa de Riscos
Prioridade
Riscos
Riscos
Riscos
Riscos
Riscos
Probabilidade
de ocorrncia
Impacto Previsto
Contramedidas
Previstas
Falta de Equipamentos
para testes beta.
Alta
Mdia
Impossibilidade de
realizar os testes beta.
Cobrar providncia do
cliente.
Defeitos na Engenharia de
Software
Mdia
Mdia
Falta de Usurios
responsveis por testes.
Alta
Baixa
Impossibilidade de
realizar os testes beta.
Cobrar providncia do
cliente.
Alta
Baixa
Impossibilidade de
realizar os testes beta.
Cobrar providncia do
cliente.
Alta
Baixa
Impossibilidade de
realizar os testes beta.
Cobrar providncia do
cliente.
Mudana de Legislao
Mdia
Baixa
MeGAZINE
Delphi
Estimativa
A estimativa dos riscos compreende as seguintes tarefas:
Identificao dos riscos possveis em relao ao projeto;
Anlise desses riscos, avaliando-lhes a probabilidade e o
provvel impacto;
Previso de contramedidas curativas ou preventivas;
Priorizao dos riscos, organizando-os de acordo com a
probabilidade e o impacto.
Os riscos no permanecem constantes durante a execuo de
um projeto. Alguns desaparecem, outros novos surgem, e outros
sofrem alteraes de probabilidade e impacto, mudando portanto
a prioridade. Um relatrio de acompanhamento do projeto
juntamente com uma tabela atualizada para monitorao dos
riscos. A tabela de estimativa deve ser repetida e atualizada para
refletir as modificaes ocorridas, at que os riscos sejam
concretizados ou completamente eliminados [4]
Concluso
Aqui foi possvel verificar a importncia da gesto de riscos
nos projetos de software. O Fracasso ou o sucesso esto
diretamente ligadas a essas variveis e contudo sero objetos de
estudo e anlise para que possam ser monitoradas e controlados
durante os projetos de software.
MeGAZINE
Referncias Bibliogrficas
[1] PRESSMAN, ROGER S., Engenharia de Software, Rio de
Janeiro, Ed. McGraw-Hill, 2002.
[2] REZENDE, DENIS ALCIDES, Engenharia de Software e
Sistemas de Informaes, Rio de Janeiro, Ed. Brasport, 1999.
[3] SOMMERVILLE, IAN, Engenharia de Software, So
Paulo, Ed. Pearson Education, 2003.
[4] FILHO, WILSON DE PDUA PAULA, Engenharia de
Software, Rio de Janeiro, Ed. LTC, 2003.
[5] PETERS, JAMES F. et al. Engenharia de Software,Rio de
Janeiro, Ed. Campus,2001.
[6]PMI, PMBOK, Project Management Institute, 2000.
Sobre o autor
Marcelo Nogueira Mestre em Engenharia de Produo com
nfase em Gesto da Informao, bacharel em Anlise de
Sistemas, Professor Universitrio, Instrutor e
Desenvolvedor Delphi desde 1995, Membro fundador do
DUG-BR. e-mail: marcelo@noginfo.com.br
Delphi
Usando
Usando o
o componente
componente
TWebBrowser
TWebBrowser
Por Claudinei Rodrigues
Ol amigos.
Nos ltimos dias alguns scios tm entrado em contato com o
nosso suporte tcnico solicitado informaes sobre como utilizar o
componente TWebBrowser que fica localizado na palheta
Internet. Sendo assim eu reuni algumas dicas bem
interessantes, as quais voc pode ver a seguir.
MeGAZINE
Delphi
notar que o texto que for localizado ficar com o fundo amarelo.
Veja abaixo a nossa funo ProcuraTexto e tambm como voc
pode utiliz-la.
// Esta funo ir localizar e destacar o
texto
procedure ProcuraTexto(WB: TWebBrowser;
Texto: string) ;
const
prefix = <span style=color:black;
background-color: yellow;>;
suffix = </span>;
var
tr: IHTMLTxtRange;
begin
if Assigned(WB.Document) then
begin
tr := ((wb.Document AS
IHTMLDocument2).body AS
IHTMLBodyElement).createTextRange;
while tr.findText(Texto, 1, 0) do
begin
tr.pasteHTML(prefix +
tr.htmlText + suffix) ;
tr.scrollIntoView(True) ;
end;
end;
end;
// Aqui o evento OnClick do componente
// Button que mostra como utilizar a funo
// ProcuraTexto
procedure TForm1.Button3Click(Sender:
TObject);
begin
ProcuraTexto(WebBrowser1,Template) ;
end;
MeGAZINE
PersistStream: IPersistStreamInit;
Stream: IStream;
FileStream: TFileStream;
begin
if not Assigned(WB.Document) then
begin
ShowMessage
(Documento no foi encontrado!);
Exit;
end;
PersistStream := WB.Document as
IPersistStreamInit;
FileStream := TFileStream.Create
(Arquivo, fmCreate);
try
Stream := TStreamAdapter.
Create(FileStream, soReference) as
IStream;
if Failed(PersistStream.Save
(Stream, True)) then
ShowMessage(No foi possvel salvar o
arquivo !);
finally
FileStream.Free;
end;
end;
// Aqui o evento OnClick de um boto que
// mostra como voc deve utilizar esta funo
procedure TForm1.Button4Click(Sender:
TObject);
begin
//Primeiro chame a pgina desejada
WebBrowser1.Navigate
(http://www.theclub.com.br);
//Depois basta salv-la
Salva_Em_HTML(WebBrowser1,c:\theclub.html);
end;
Para que este cdigo funcione corretamente voc deve
declarar a unit ActiveX.
Delphi
seguir faz a mesma coisa.
// Esta procedure ir chamar a tela
// de dialogo onde voc ir digitar
// a informao a ser pesquisada.
procedure FindDialog
(WB: TWebbrowser) ;
const
CGID_WebBrowser: TGUID =
{ED016940-BD5B-11cf-BA4E-00C04FD70816};
HTMLID_FIND = 1;
var
CmdTarget : IOleCommandTarget;
vaIn, vaOut: OleVariant;
PtrGUID: PGUID;
begin
New(PtrGUID) ;
PtrGUID^ := CGID_WebBrowser;
if WB.Document <> nil then
try
WB.Document.QueryInterface
(IOleCommandTarget, CmdTarget) ;
if CmdTarget <> nil then
try
CmdTarget.Exec(PtrGUID,
HTMLID_FIND, 0, vaIn, vaOut) ;
finally
CmdTarget._Release;
end;
except
end;
Dispose(PtrGUID) ;
end;
// Aqui o evento OnClick de um boto
// que mostra como voc deve utilizar
// a funo FindDialog
procedure TForm1.Button5Click(Sender:
TObject);
begin
FindDialog(WebBrowser1) ;
end;
10
MeGAZINE
Delphi
WB.ControlInterface.ExecWB(OLECMDID_PRINT,
OLECMDEXECOPT_DONTPROMPTUSER, vIn, vOut) ;
end;
//Imprime depois de chamar a tela de dilogo
procedure Imprime_Com_Janela_Dialogo(WB:
TWebBrowser) ;
var
vIn, vOut: OleVariant;
begin
WB.ControlInterface.ExecWB(OLECMDID_PRINT,
OLECMDEXECOPT_PROMPTUSER, vIn, vOut) ;
end;
// Chama o preview
procedure Mostra_Preview(WB: TWebBrowser) ;
var
vIn, vOut: OleVariant;
begin
WB.ControlInterface.ExecWB(OLECMDID_PRINTPREVIEW,
OLECMDEXECOPT_DONTPROMPTUSER, vIn, vOut) ;
end;
//Chama o Print Setup
procedure Chama_PrintSetup(WB: TWebBrowser) ;
var
vIn, vOut: OleVariant;
begin
WB.ControlInterface.ExecWB(OLECMDID_PAGESETUP,
OLECMDEXECOPT_PROMPTUSER, vIn, vOut) ;
end;
MeGAZINE
GetClassName(PMOUSEHOOKSTRUCT(lParam)^.
HWND, classbuf, SizeOf(classbuf)) ;
if lstrcmp(@classbuf[0],
@ie[1]) = 0 then
Result := HC_SKIP
else
Result := CallNextHookEx
(MouseHook, nCode,
wParam, lParam) ;
end
else
begin
Result := CallNextHookEx
(MouseHook, nCode,
wParam, lParam) ;
end;
end;
end;
end;
// Aqui o evento OnCreate do form onde
// estamos chamando a funo que desabilita
// o Context Menu
procedure TForm1.FormCreate(Sender: TObject);
begin
MouseHook := SetWindowsHookEx(WH_MOUSE,
MouseProc, 0, GetCurrentThreadId()) ;
end;
// Aqui o OnDestroy do form onde
// estamos habilidando novamente
// o Context Menu
procedure TForm1.FormDestroy(Sender:
TObject);
begin
if MouseHook <> 0 then
UnHookWindowsHookEx(MouseHook) ;
end;
Concluso
Estas foram algumas dicas que temos disponveis a respeito
do componente TWebBrowser. Se voc tiver mais alguma dica e
quiser v-la publicada em nossa revista, mande um e-mail para
suporte@theclub.com.br que teremos o maior prazer em publiclas.
Um abrao a todos e at o prximo ms.
Sobre o autor
Claudinei Rodrigues,
Consultor Tcnico do The Club
nei@theclub.com.br
11
Delphi
Criando
Criando arquivo
arquivo PDF
PDF
aa partir
partir do
do Delphi.
Delphi.
Introduo
Nesta matria iremos verificar como criar arquivos PDF a
partir do Delphi, esse tpico bastante abordado pois muito
importante que nosso sistema possa exportar dados de uma
forma segura e de fcil visualizao.
Alguns geradores de relatrios j trazem embutidas essas
particularidades, mas em alguns casos no temos esses gerados a
disposio ou a estrutura que iremos montar no se encaixa num
gerador de relatrio. Sendo assim, temos a possibilidade de
montar o PDF via programao, incluindo assim as informaes
conforme a necessidade.
Componente Externo
Para a criao do arquivo PDF utilizaremos um componente
externo e free chamado TNPDF. Esse componente bastante
simples composto de apenas uma unit onde o PDF gerado.
Junto com esse componente temos um outro componente
tambm free chamando ZLIB, que ser utilizado para fazer a
compactao do arquivo PDF gerado.
12
implementation
uses tnpdf;
Em seguida criaremos uma procedure contendo as instrues
para gerar o arquivo PDF:
procedure TForm1.Relat1(NomeArq: String);
var PDF:TPrintPDF;
begin
MeGAZINE
Delphi
Figura 1:
{ Cria o componente TPrintPDF }
PDF := TPrintPDF.Create(self);
try
{ Configurar o ttulo do documento }
PDF.TITLE := Label1.Caption;
{ Usando o componente para compactao do
arquivo }
PDF.Compress := true;
{ Configurar o tamanho da pgina }
PDF.PageWidth := 612;
PDF.PageHeight := 792;
{ Indica o nome do arquivo a ser gerado }
PDF.FileName := NomeArq;
{ Inicia a impresso }
PDF.BeginDoc;
{ Configura o tamanho da linha }
PDF.LineWidth := 1;
{ Desenha uma linha no PDF }
PDF.DrawLine(12,50,600,50);
{ Configura o tamanho da linha }
MeGAZINE
PDF.LineWidth := 2;
{ Desenha um retngulo no PDF }
PDF.DrawRectangle(12,12,600,780);
{ Configura a fonte a ser impressa. Essa
fonte definida dentro do componente
devido ao nome a ser utilizado na
estrutura do PDF }
PDF.Font.Name := poHelveticaBold;
PDF.Font.Size := 20;
{ Imprime Texto no corpo do PDF }
PDF.TextOut(15,30,Label1.Caption);
PDF.Font.Size := 10;
PDF.TextOut(15,45,THE CLUB, O maior
clube de programadores do Brasil);
{ Configura a Fonte }
PDF.Font.Name := poTimesRoman;
PDF.Font.Size := 12;
{ Imprime o contedo de um memo }
PDF.MemoOut(15,60, Memo1);
{ Adiciona nova pgina }
13
Delphi
QuickReport e com o FastReport, mas nesta verso que estou
disponibilizando no site do THE CLUB o componente estar
trabalhando somente com o quickreport. Caso algum queira
pegar a verso que tambm trabalha com o FastReport
recomendo que acesse o site do fabricante no seguinte link: http://
usuarios.lycos.es/isma
PDF.NewPage;
{ Imprime um retngulo }
PDF.DrawRectangle(12,12,600,780);
{ Imprime uma imagem }
PDF.Draw(15,15,Image1);
{ Finaliza o documento }
PDF.EndDoc;
finally
{ Destroi o componente da memria }
PDF.Free;
end;
end;
No evento onclick do boto coloque a instruo para chamar a
procedure:
procedure TForm1.Button1Click(Sender:
TObject);
begin
if SaveDialog1.Execute then
begin
Relat1( SaveDialog1.FileName );
end;
end;
14
procedure TMainForm.BtnExportQRClick(Sender:
TObject);
begin
{ Liga o componente do QuickReport ao
componente de exportao }
EXQR.Report := Rep;
{ Faz a exportao }
EXQR.ExportQR;
end;
Este componente tambm nos permite exportar relatrios a
partir do componente QRPreview que o componente ao qual
criamos preview personalizado no QuickReport.
Para isso podemos colocar um boto no form de preview e
neste boto colocar a seguinte instruo:
procedure TFPreviewQR.TBSaveClick(Sender:
TObject);
begin
{ Faz a ligao do QRPreview com o
componente }
EXQR.Preview := Preview;
{ Faz a exportao do relatrio }
MeGAZINE
Delphi
Esses cdigos acima podem ser encontrados no projeto de
Exemplo3 que acompanha o componente ExportQR.
EXQR.ExportQRFromPreview;
end;
Esses cdigos acima podem ser encontrados no projeto de
Exemplo1 que acompanha o componente ExportQR.
Outros formatos
A exportao dos relatrios para os demais formatos
bastante simples tambm, veja abaixo as sintaxes utilizadas para
cada tipo:
PDF com Alta Compresso:
EXQR.ExportQRPDF(edFileName.Text, True);
PDF com Baixa Compresso
EXQR.ExportQRPDF(edFileName.Text, False);
JPG
EXQR.ExportQRJPG(edFileName.Text);
BMP
EXQR.ExportQRBMP(edFileName.Text);
WMF
EXQR.ExportQRWMF(edFileName.Text);
EMF
EXQR.ExportQREMF(edFileName.Text);
MeGAZINE
Observao
No entrei em detalhes sobre a criao dos exemplos, para
que o foco principal que conhecer o componente no seja
perdido. Os projetos de exemplo aqui apresentados foram criados
pelos prprios fabricantes dos componentes e somente sofreram
algumas poucas alteraes como, por exemplo, traduo dos
forms para o portugus.
Concluso
Particularmente gostei muito desses componentes e acredito
que eles iro nos ajudar bastante na criao de arquivos PDF
atravs dos projetos em Delphi, sem aquela dependncia dos
geradores de relatrio.
Um grande abrao a todos e at a prxima.
Sobre o autor
Andr Colavite
Consultor Tcnico do The Club
colavite@theclub.com.br
15
Delphi
Explorando
Explorando oo QuickReport
QuickReport
Criando relatrios no triviais
Sobre o autor
Alessandro Ferreira, Consultor Tcnico do The Club
alessandro@theclub.com.br
Introduo
O evento OnNeedData
C:\Arquivos de programas\Borland\Delphi7\Bin
Para adicionar, acesse o menu Component | Install Packages
| Add e adicione o referido pacote. Aps adicionar, recomendo
efetuar atualizao do QuickReport que est disponvel para
download no site do fabricante no endereo:
Delphi 7
http://www.qusoft.com/
getfile.asp?level=0&Filename=QRSTD351D7.EXE
Banco de Dados
Iremos utilizar o Firebird 1.5.2 onde a princpio vamos criar
duas tabelas, sendo uma contendo os dados dos clientes e outra
contendo as compras efetuadas por estes clientes. Sugiro utilizar
o IBExpert (www.ibexpert.com) que uma ferramenta gratuita
Delphi 6
http://www.qusoft.com/
getfile.asp?level=0&Filename=qr351sd6.exe
16
MeGAZINE
Delphi
para manuteno em bancos Interbase/Firebird para criar o
banco de dados e suas tabelas. (Poder encontrar referncia
sobre o IBExpert em nossa revista de Dezembro/2004).
Vamos criar as estrutura da tabela Clientes, veja o cdigo na
listagem 1.
CREATE TABLE
ID
NOME
ENDERECO
BAIRRO
CIDADE
UF
CEP
CNPJ_CPF
RG_IE
TELEFONE
EMAIL
);
CLIENTES (
INTEGER NOT NULL PRIMARY KEY,
VARCHAR(70),
VARCHAR(70),
VARCHAR(30),
VARCHAR(30),
CHAR(2),
CHAR(10),
VARCHAR(18),
VARCHAR(18),
VARCHAR(18),
VARCHAR(80)
Figura 2 Vendas
Figura 1 Clientes
MeGAZINE
17
Delphi
Adicione um componente DataSetProvider, configure Name
para dspCrossTab e DataSet para sdsCrossTab. Aps isso,
adicione um componente ClientDataSet, configure Name para
cdsCrossTab, ProviderName para dspCrossTab e
depois clique com o boto direito no mesmo e
selecione a opo: Fetch Params.
Select
CLI.NOME AS CLIENTE, EXTRACT(MONTH FROM
VEN.DATA) AS MES,SUM(VEN.VALOR_TOTAL) AS TOTAL
From
VENDAS VEN
Left Outer Join CLIENTES CLI
on CLI.ID = VEN.CLIENTE_ID
Where
EXTRACT(YEAR FROM VEN.DATA) = :ANO
Group By
CLI.NOME,
EXTRACT(MONTH FROM VEN.DATA)
Jan
Fev
Mar
Abr
Mai
Jun
Jul
Ago
Set
180,00
420,00
280,00
500,00
420,00
180,00
100,00
320,00
180,00 100,00
650,00
540,00
221,00
311,00
Alessand... 420,00
Total
Out
Nov
Dez
Total
500,00
3.600,00
123,00 1205,00
9.564,00
13.164,00
18
MeGAZINE
Tabela 1
Dados arranjados em
cross-tab
Delphi
Tendo como base de layout a tabela 1 anteriormente
apresentada, vamos adicionar componentes QRLabel os quais
sero responsveis pela apresentao dos dados. Na banda
referente o cabealho, adicione 14 QRLabels ajustando o primeiro
com o Caption Nome do Cliente, os prximos 12 devero conter o
nome de cada ms comeando por Janeiro e o ltimo QRLabel
ter como Caption Total;
private
{ Private declarations }
procedure ZeraTotColunas;
procedure LimpaValores;
procedure PreencheValores;
procedure LimpaSumario;
procedure PreencheSumario;
public
{ Public declarations }
end;
Listagem 4 Declaraes.
Dica: Aps efetuar estas declaraes, tecle a combinao
CTRL+SHIFT+C e automaticamente o editor ir criar o
cabealho dos procedimentos abaixo da sesso implementation.
Observe que declaramos um Array o qual ser responsvel
em armazenar a totalizao de cada coluna (ms) o qual iremos
apresentar no final do relatrio, na banda sumrio e para no ter
que fazer referncia a cada elemento do Array, implementamos
um mtodo para inicializar este Array, acompanhe a listagem 5.
{ Limpa Array que ir armazenar a totalizao
das colunas. }
procedure TForm1.ZeraTotColunas;
var
i: Integer;
begin
for i := Low(TotColunas) to
High(TotColunas) do
TotColunas[i] := 0;
end;
Listagem 5 Iniciar Array
MeGAZINE
19
Delphi
QRLabels existentes na banda sumrio.
{ Limpar os QRLabel da banda detalhe }
procedure TForm1.LimpaValores;
var
i: Integer;
C: TComponent;
begin
for i := 1 to 13 do
begin
C := FindComponent(qr_ +
FormatFloat(00, i));
if (C <> nil) and (C is TQRLabel) then
TQRLabel(C).Caption := 0,00;
end;
TotCliente := 0;
end;
{ Limpar os QRLabel da banda sumrio }
procedure TForm1.LimpaSumario;
var
i: Integer;
C: TComponent;
begin
for i := 1 to 13 do
begin
C := FindComponent(tot_ +
FormatFloat(00, i));
if (C <> nil) and (C is TQRLabel) then
TQRLabel(C).Caption := 0,00;
end;
TotGeral := 0;
end;
Listagem 6 Mtodos para limpar os QRLabels
O mtodo seguinte apresentado na listagem 7 um dos mais
importantes dentro deste contexto, pois, ser o responsvel em
preencher os QRLabels (da banda detalhe) com os valores
advindos do ClientDataSet:
{ Preenche os QRLabel da banda detalhe }
procedure TForm1.PreencheValores;
var
C: TComponent;
Mes: Integer;
begin
ImpTitulo := False;
while (NomeDoCliente =
cdsCrossTabCLIENTE.AsString) and not
(cdsCrossTab.EOF) do
20
begin
Mes := cdsCrossTabMES.AsInteger;
// Totaliza por coluna.
TotColunas[Mes] := TotColunas[Mes] +
cdsCrossTabTOTAL.AsFloat;
// Totaliza por cliente.
TotCliente := TotCliente +
cdsCrossTabTOTAL.AsFloat;
C := FindComponent(qr_ +
FormatFloat(00, cdsCrossTabMES.AsInteger));
if (C <> nil) and (C is TQRLabel) then
TQRLabel(C).Caption :=
FormatFloat(###,##0.00,
cdsCrossTabTOTAL.AsFloat);
qr_Nome.Caption :=
cdsCrossTabCLIENTE.AsString;
cdsCrossTab.Next;
end;
// Mostra total do Cliente.
qr_13.Caption := FormatFloat(###,##0.00,
TotCliente);
// Acumula total geral.
TotGeral := TotGeral + TotCliente;
ImpTitulo := True;
end;
Listagem 7 Mtodo que alimenta os QRLabels
Vamos explicar o mtodo PreencheValores, o qual comea
atribuindo false para a varivel ImpTitulo. Esta varivel ser
responsvel em controlar quando a banda detalhe dever ser
impressa, pois a mesma dever ser impressa apenas quando
todos os meses do referido cliente estiverem preenchidos. Voc
deve estar lembrando que o controle de navegao dos registros
por nossa conta e a fim de obtermos todos os registros referente o
cliente atual, efetuamos um lao enquanto o cliente permanecer o
mesmo e enquanto no atingir o final do arquivo. Dentro deste
lao, vamos acumulando o valor de cada coluna (ms) e o valor
referente ao cliente corrente. Mais uma vez recorremos ao
FindComponent para pesquisar e retornar os QRLabels
existentes na banda detalhe atravs do seu nome e caso seja
encontrado, alimentamos sua propriedade caption.
Ao trmino do while, verificamos que todos os dados cliente
armazenado na varivel NomeDoCliente foram obtidos e nos
resta efetuar a totalizao deste cliente e armazenar seu total na
varivel TotaGeral que ir ser apresentada na banda sumrio, e
atribuir true varivel ImpTitulo a qual ir liberar a impresso
da banda detalhe com todos os dados j carregados para o
respectivo cliente.
MeGAZINE
Delphi
Bem, estamos agora quase concluindo a codificao de nosso
relatrio, contudo, necessitamos alimentar os totais para cada
ms e um total geral em nossa banda sumrio.
Para isso, seguindo a mesma lgica do mtodo anterior,
porm, lendo os dados do Array TotColunas que representa o total
de cada coluna (ms), acompanhe a listagem 8.
{ Preenche os componentes da banda sumrio }
procedure TForm1.PreencheSumario;
var
C: TComponent;
i: Integer;
begin
for i := 1 to 12 do
begin
C := FindComponent(tot_ +
FormatFloat(00, i));
if (C <> nil) and (C is TQRLabel) then
TQRLabel(C).Caption :=
FormatFloat(###,##0.00, TotColunas[i]);
end;
tot_13.Caption := FormatFloat(###,##0.00,
TotGeral);
end;
Listagem 8 Alimentando os componentes da banda
sumrio.
Dando continuidade, d um duplo clique no Bitbtn que
ser responsvel em chamar o relatrio e adicione o cdigo
apresentado na listagem 9.
{ Chamar o relatrio }
procedure TForm1.btnVisualizarClick(Sender:
TObject);
begin
with cdsCrossTab do
begin
Close;
Params.ParamByName(ANO).AsInteger :=
StrToInt(MEdit_Ano.Text);
Open;
end;
QR_Titulo.Caption := QR_Titulo.Caption +
MEdit_Ano.Text;
QR_CrossTab.Preview;
end;
Listagem 9 Boto visualizar
MeGAZINE
21
Delphi
{ Se a banda detalhe foi impressa, limpa os
QRLabel }
if BandPrinted then
LimpaValores;
NomeDoCliente :=
cdsCrossTabCLIENTE.AsString;
end;
Figura 7
Layout sugerido
22
MeGAZINE
Delphi
Visualizar (listagem 12).
Figura 8 QR_Etiquetas
Codificando o Relatrio
Mais uma vez vamos utilizar o evento OnNeedData do
QuickReport para efetuar o controle da quantidade de etiquetas
imprimir. Lembre-se que a propriedade DataSet do QuickReport
deve ficar em branco, pois o controle ser manual.
Na listagem 11 apresentamos o evento OnNeedData do
QuickReport e o evento AfterPrint da banda detalhe.
procedure TForm1.QR_EtiquetaNeedData(Sender:
TObject;
var MoreData: Boolean);
begin
{ Enquanto a propriedade TAG estiver maior
que zero porque tem que imprimir mais uma
etiqueta }
MoreData := (QR_Etiqueta.Tag > 0);
end;
procedure
TForm1.DetailBand1AfterPrint(Sender:
TQRCustomBand;
BandPrinted: Boolean);
begin
{ A cada etiqueta impressa, vai
decrementando o contador }
QR_Etiqueta.Tag := QR_Etiqueta.Tag - 1;
end;
Listagem 11 Eventos
No evento OnNeedData atribumos verdadeiro ao parmetro
MoreData enquanto o valor da propriedade TAG do QuickReport
for maior que zero. No evento AfterPrint da banda detalhe,
vamos decrementando o valor da propriedade TAG aps cada
etiqueta impressa.
procedure TForm1.btnVisualizarClick(Sender:
TObject);
var
Quantidade: Integer;
begin
{ pega a quantidade de etiquetas }
TryStrToInt(MEdit_Quant.Text, Quantidade);
{
A propriedade TAG do QR ser utilizada
para efetuar o controle da quantidade de
etiquetas serem impressas.
}
QR_Etiqueta.Tag := Quantidade;
QR_Etiqueta.Preview;
end;
Listagem 12 Boto visualizar.
Compile e rode o preview e se tudo estiver OK ser
apresentado o nmero de etiquetas informadas para o registro
corrente.
MeGAZINE
Figura 9 QuickReport
23
Delphi
Estando tudo configurado, vamos efetuar a codificao para
chamada e apresentao do Preview com a imagem de fundo. Na
listagem 13 apresentamos o procedimento que ser responsvel em
pintar a imagem no fundo do QuickReport.
procedure ImprimeBitmap(Cnv: TCanvas; Bitmap:
TBitmap; R: TRect);
var
Info: PBitmapInfo;
InfoSize: DWORD;
Image: Pointer;
ImageSize: DWORD;
begin
with Bitmap do
begin
GetDIBSizes(Handle, InfoSize, ImageSize);
GetMem(Info, InfoSize);
try
GetMem(Image, ImageSize);
try
GetDIB(Handle, Palette, Info^,
Image^);
with Info^.bmiHeader do
StretchDIBits(Cnv.Handle, R.Left,
R.Top, R.Right - R.Left,
R.Bottom - R.Top, 0, 0, biWidth,
biHeight, Image, Info^,
DIB_RGB_COLORS, SRCAND);
finally
FreeMem(Image, ImageSize);
end;
finally
FreeMem(Info, InfoSize);
end;
end;
end;
{
AfterPrint do rodap
Chamar a rotina que ir imprimir a imagem no
fundo do QReport.
}
procedure
TForm1.PageFooterBand1AfterPrint(Sender:
TQRCustomBand;
BandPrinted: Boolean);
var
M: TBitmap;
R: TRect;
X, Y: integer;
begin
M := TBitmap.Create;
try
M.LoadFromFile(pato.bmp);
with QuickRep1.QRPrinter do
begin
Y := YPos(PaperLengthValue) div 6;
X := XPos(PaperWidthValue) div 4;
R := Rect(X, 2 * Y, 3 * X, 4 * Y);
ImprimeBitmap(Canvas, M, R);
end;
finally
M.Free;
end;
end;
Listagem 14 Evento AfterPrint
Verifique que carregamos uma imagem em disco, contudo,
esta imagem poderia estar em um componente Image ou arquivo
de recursos. Outro aspecto relevante, que passado o objeto
Canvas a partir do objeto QRPrinter implcito no QuickReport.
Para finalizar, vamos efetuar a chamada do relatrio no
evento OnClick do boto (listagem 15).
24
procedure TForm1.Button1Click(Sender:
TObject);
begin
Button1.Enabled := false;
try
QuickRep1.Preview;
finally
Button1.Enabled := true;
end;
end;
MeGAZINE
Listagem 15 OnClick.
Delphi
Ao chamar o preview do relatrio, o mesmo dever conter
uma imagem de fundo assim como demonstra a figura 10.
MeGAZINE
25
Delphi
ainda dentro deste lao FOR, executamos um Next para mover
para o prximo registro.
E para finalizar a codificao, vamos programar o evento
BeforePrint e OnNeedData do QuickReport e a chamada do
relatrio no evento OnClick do boto, acompanhe a listagem 16.
procedure TForm1.QR_LadoALadoNeedData(Sender:
TObject;
var MoreData: Boolean);
begin
{ Gera mais uma linha enquanto no for
final de arquivo }
MoreData := not (tbCustomer.EOF);
end;
procedure TForm1.btnVisualizarClick(Sender:
TObject);
begin
QR_LadoALado.Preview;
end;
procedure
TForm1.QR_LadoALadoBeforePrint(Sender:
TCustomQuickRep;
var PrintReport: Boolean);
begin
tbCustomer.First;
end;
Listagem 16 Finalizando a codificao
Estando tudo OK, compile e execute a aplicao e o resultado
dever ser parecido com o fragmento apresentado na imagem 12.
Codificando o relatrio
A idia aqui ser carregar o arquivo texto em um objeto do
tipo TStringList e depois ir lendo linha a linha este TStrings e
transferindo o contedo da linha ao QRLabel. Assim sendo,
detalhe uma varivel chamada Texto abaixo da sesso var de
nossa unit, veja a listagem 17.
var
Form1: TForm1;
Texto: TStringList;
implementation
{$R *.DFM}
Listagem 17 declarao do TStringList.
Prosseguindo, vamos efetuar a codificao do sbtnProcurar o
qual ter como finalidade abrir uma caixa de dilogo para que o
usurio possa escolher o arquivo ser impresso e atribuir seu
caminho/nome ao Edit, veja a listagem 18.
procedure TForm1.sbtnProcurarClick
(Sender: TObject);
begin
if dlgTexto.Execute then
EdArquivo.Text :=
dlgTexto.FileName;
end;
Listagem 18 sbtnProcurar.
O prximo passo ser codificar o boto btnPreview
que ir efetuar a carga do arquivo texto e a chamada do
nosso relatrio, acompanhe a listagem 19.
26
MeGAZINE
Delphi
procedure TForm1.btnPreviewClick(Sender:
TObject);
begin
if FileExists(EdArquivo.Text) then
begin
Texto := TStringList.Create;
try
Texto.LoadFromFile(EdArquivo.Text);
QR_ImpTexto.Tag := 0;
QR_ImpTexto.Preview;
finally
Texto.Free;
end;
end
else
raise Exception.Create(Selecione um
arquivo!);
end;
MeGAZINE
Concluso
A partir do Delphi 7 o QuickReport deixou de ser distribudo
como ferramenta oficial de relatrios no Delphi, sendo substitudo
pelo Rave Report. Contudo, como mencionamos no incio deste
artigo, o QuickReport ainda um dos geradores de relatrios
mais utilizados na comunidade Delphi. Procurei demonstrar aqui
algumas tcnicas que possibilitam explorar muitas
funcionalidades do QuickReport permitindo a voc utiliz-lo em
situaes que aparentemente teramos que recorrer outros
artifcios, como exemplo o TPrinter, podendo dessa forma seguir
uma padronizao em seus relatrios.
Vale ressaltar que o fabricante do QuickReport lanou
recentemente a verso 4.0 que d suporte at o Delphi 2005 e,
dessa forma, se voc necessitar converter suas aplicaes para o
Delphi 2005 e no pretendo migrar para outro gerador de
relatrios, poder adquirir o QuickReport juntamente ao
fabricante, lembrando que ele no mais gratuito.
Download
Os exemplos apresentados neste artigo esto disponveis para
download no endereo:
http://www.theclub.com.br/revista/download/QREspecial.zip
27
begin
Inc(Result);
N := N.Parent;
end;
end;
procedure TWinForm.Button1_Click(sender:
System.Object; e: System.EventArgs);
begin
MessageBox.Show(
Level(TreeView1.SelectedNode).ToString );
end;
http://support.microsoft.com/default.aspx?scid=kb;ENUS;q306005
Dvida enviada por Wagner Araujo Mesquita, Franca/SP.
28
MeGAZINE
MeGAZINE
ponteiro. }
for i := 1 to count do
begin
if (pnr.dwDisplayType =
RESOURCEDISPLAYTYPE_DOMAIN or
RESOURCEDISPLAYTYPE_SERVER)
and
(pnr.dwType = RESOURCETYPE_DISK)
then
strings.Add(pnr.lpRemoteName);
{ chamada recursiva da funo. }
if (pnr.dwUsage and
RESOURCEUSAGE_CONTAINER) > 0 then
EnumNetworkDrives(pnr);
inc(longint(pnr),sizeof(TNetResource));
end;
end;
finally
FreeMem(buffer);
WNetCloseEnum(hEnum);
end;
end;
begin
if strings = nil then
exit;
EnumNetworkDrives(nil);
end;
Para utilizar a procedure, adicione um componente Button e
um componente ListBox e faa a chamada assim:
procedure TForm1.Button1Click
(Sender: TObject);
begin
GetNetworkedDrives(ListBox1.Items);
end;
Dvida enviada por Vagner Martins, Rafard/SP.
29
unit MsgBoxTimeOut;
interface
uses Windows;
const
MB_TIMEDOUT = 32000;
case iRet of
IDYES: { Boto sim. }
ShowMessage(Sim);
IDNO: { boto no }
ShowMessage(No);
MB_TIMEDOUT: { TimeOut }
ShowMessage(Voc no selecionou Sim/
No, tempo esgotado!);
end;
end;
end.
Pronto, agora bastar declarar esta unit onde
desejar chamar a funo MessageBoxTimeOut,
veja um exemplo a seguir:
procedure TForm1.Button1Click(Sender:
TObject);
var
iRet: Integer;
iFlags: Integer;
begin
iFlags := MB_OK or MB_SETFOREGROUND or
MB_SYSTEMMODAL or MB_ICONINFORMATION;
30
MeGAZINE