Revista The Club Megazine - 09/2003 - O maior clube de ... · - “Triggers” - excelente para...
Transcript of Revista The Club Megazine - 09/2003 - O maior clube de ... · - “Triggers” - excelente para...
Revista The Club Megazine - 09/2003A utilização, reprodução, apropriação, armazenamento em banco de dados,sob qualquer forma ou meio, de textos, fotos e outras criações intelectuaisem cada publicação da revista “The Club” são terminantemente proibidos
sem autorização escrita dos titulares dos direitos autorais.Copyright© The Club® 2003
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 33333
EDITORIALEDITORIALEDITORIALEDITORIALEDITORIAL
Editorial
Celso Jefferson PaganelliPresidente - The Club
Editorial ............................................................................ 03News ............................................................................... 04Dicas & Truques ................................................................. 05Pesquisa em Banco de Dados ............................................. 08DBExpress - Criando um relacionamentoMASTER/DETALHE - Parte II ............................................... 14IntraWeb - Desenvolvendo aplicações web page ................ 18Delphi Web HardCore ........................................................ 24Rave Reports - Carregando Imagens Dinâmicamente ......... 28
THE CLUBAv. Celso Ferreira da Silva, 190
Jd. Europa - Avaré - SP - CEP 18.707-150Informações: (0xx14) 3732-3689
Suporte: (0xx14) 3733-1588 - Fax: (0xx14) 3732-0987
Internethttp://www.theclub.com.br
Cadastro: [email protected]: [email protected]ções: [email protected]
DúvidasCorrespondência ou fax com dúvidas devem serenviados ao - THE CLUB, indicando "Suporte".
OpiniãoSe você quer dar a sua opinião sobre o clube em
geral, mande a sua correspondência para a seção"Tire sua dúvida".
ReproduçãoA utilização, reprodução, apropriação,
armazenamento em banco de dados, sob qualquerforma ou meio, de textos, fotos e outras criações
intelectuais em cada publicação da Revista“The Club” são terminantemente proibidos sem
autorização escrita dos titulares dos direitosautorais.
Copyright© The Club® 2003
Impressão e acabamento:Impressos Gril - Gril Gráfica e Repr. Ind. Ltda.
Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259Rua São Paulo, 447 - Cep 18.740-000
Taquarituba - SPTiragem: 5.000 exemplares
ColaboradoresEmerson Facunte
Diretor - Presidente
Celso Jefferson M. Paganelli
Diretor Técnico
Mauro Sant’Anna
Delphi é marca registrada da Borland International, asdemais marcas citadas são registradas pelos seus
respectivos proprietários.
Olá amigos,
Estamos trazendo até você a 108ª edição da nossa The Club Megazine e como decostume com muita coisa legal preparada especialmente para você!
Começamos com a sessão Dicas & Truques, trazendo algumas das dicas solicitadasao nosso setor de suporte, porém, como são muitas, não temos como estar publicandoaqui todas as novas dicas, mas você poderá acessar diretamente em nosso site, http:/www.theclub.com.br na sessão “Suporte On-Line”, bastando para isso baixar umpequeno plug-in de acesso e com isso acessar diretamente nosso banco de dados!
Pesquisa em Banco de Dados! Este ítem sem dúvidas é um dos mais requisitadosaos nossos consultores, visto ser algo imprescindível em qualquer tipo de aplicação eassim sendo, estamos demonstrando uma das abordagens possíveis para este assunto.
Continuando, estamos trazendo a segunda parte do artigo sobre relacionamentosmaster/detalhe utilizando dbExpress, com mais algumas dicas e macetes bastanteinteressantes!
Falando em Internet, estamos trazendo mais um artigo sobre a suite decomponentes Intraweb, desta vez, abordando a versão que acompanha o Delphi 7Professional e mostrando que através desta versão também é possível obter ótimosresultados sem muito esforço. Ainda falando em Internet, Emerson Facunte,especialista neste assunto traz um excelente artigo mesclando as tecnologiasWebBroker, Mobile, Intraweb e WebServices, vale a pena conferir!
E finalizamos com um artigo sobre o gerador de relatórios Rave Reports,demonstrando uma abordagem bastante interessante para apresentação de imagensdinâmicamente.
Aproveitem e até a próxima,
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE44444
NEWSNEWSNEWSNEWSNEWS
Extended Systems lança o Advantage Database Server 7.0A Extended Systems XTND anunciou que a empresa está
reforçando sua solução de gerenciamento de banco de dados como lançamento da versão 7.0 do Advantage Database Server.
Novas funcionalidades significativas foram incorporadas aoAdvantage Database Server, incluindo “triggers”, compressão dedados na comunicação, “full text search” (procura completa detextos), “.NET data provider” e “driver type-4 JDBC”. Com estasmelhorias, a Extended Systems continua fornecendo aosdesenvolvedores de aplicações comerciais sua robusta soluçãogerenciamento de banco de dados cliente/servidor, que pode serutilizada facilmente e sem custos extras, em diversasplataformas.
Os desenvolvedores Java e .Net estarão particularmenteinteressados no Advantage Database Server 7.0, pois o driverAdvantage JDBC permite acesso nativo ao Advantage DatabaseServer enquanto .NET Data Provider permite às aplicaçõesADO.NET acesso nativo. Estas inovações permitem que aExtended Systems persiga agressivamente os mercados Java e.NET, fornecendo aos seus desenvolvedores, alternativa degerenciamento de banco de dados de alto nível, que é escalonável,robusta e de fácil distribuição.
”O Advantage é desenhado especificamente para desenvolvedoresde aplicações que necessitem de uma solução de gerenciamentode dados na filosofia cliente/servidor e que forneça funcionalidadepara todo o tipo de processamento crítico, sem criar problemasadministrativos.”, disse Chuck Vertrees, gerente de produtosAdvantage, da Extended Systems. “Estamos com o compromissode, continuadamente, atualizar e melhorar o ADS e fornecertecnologias adicionais para a nossa leal base de clientes atual etambém para futuros clientes.”
Funcionalidades adicionais incorporadas ao AdvantageDatabase Server 7.0:
- “Triggers” - excelente para melhorar autorizações desegurança mais complexas e para fornecer eventos de log eauditoria, de forma transparente e independente.
- Compressão de dados na comunicação - consegue tráfego derede reduzido entre clientes Advantage e o servidor Advantage.
- Capacidade para “Full Text Search” (procura completa de
textos) - usado para encontrar registros que contenham dadosque confiram com condições de procura, construídas através depalavras e frases, combinadas com operadores lógicos AND, OR eNOT e o operador de proximidade NEAR
Disponibilidade do Advantage 7.0O Advantage Database Server estará disponível em 22/09/03.
O .NET Data Provider estará disponível logo depois. Versõesanteriores do Advantage poderão ser atualizadas por umaporcentagem do preço do produto final. No Brasil, contate aReNet Tecnologia (www.renet.com.br), telefone 11 3872-0423.
Sobre o Advantage Database ServerAdvantage Database Server é a culminação sobre de 13 anos
da experiência do desenvolvimento no mercado de banco dedados. Advantage é suportada por completo departamento detécnicos treinados que ajudam usuários a extrair o máximo desuas soluções cliente/servidor através de excepcional suporte,treinamento e consultoria. Hoje, o Advantage Database Server éum produto premiado (*) que suporta mais de 2,5 milhões deinstalações mundialmente. É solução confiável para empresasclassificadas de pequenas a integrantes do Fortune 500, queconfiam ao Advantage Database Server a missão de processaraplicações críticas que permitem a conduzir com sucesso seusnegócios através do país e do mundo. Para mais informações,visite o Web site do distribuidor no Brasil: www.renet.com.br/database.
Sobre a Extended Systems
A Extended Systems fornece perícia, estratégia e soluções paraajudar as corporações afinarem seus processos corporativos.Fundada em 1984, a Extended Systems têm escritórios esubsidiárias nos Estados Unidos e no resto do mundo. Para maisinformações, visite o Web Site da companhia emwww.extendedsystems.com. No Brasil, visite www.renet.com.br.
(*) Delphi Informant Magazine 2003, 2002, and 2001Readers Choice Award
Visite www.renet.com.br ou contate-nos para detalhesadicionais e conhecer o programa de avaliação.
ReNet Tecnologia [email protected].: 11 3872-0423
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 55555
Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques
QuickReport – Como criar bandas viaprogramação
Muitas vezes, temos a necessidade de criar bandas ecomponentes QRDBText via programação em um QuickReport enesta dica iremos demonstrar alguns macetes para isso...
{
Esta função tem a finalidade de retornar a banda no
qual componentes como um QRDBText irão ser
apresentados.
}
function AchaParent(Nome: String; QRep: TQuickRep):
TWinControl;
var
i: Integer;
begin
Result := Nil;
for i := 0 to QRep.ControlCount-1 do
if QRep.Controls[i].Name = Nome then
begin
Result := QRep.Controls[i] as TWinControl;
Break;
end;
end;
{
Cria os objetos e chama o Preview.
}
procedure TForm1.btnPreviewClick(Sender: TObject);
var
i: Integer;
begin
// Criando uma banda do tipo QRGroup
with TQRGroup.Create(Self) do
begin
Parent := QuickRep1;
Master := Parent;
Expression := ‘Continent’;
Color := clAqua;
Name := ‘QRGroup1’;
end;
// Criando um componente QRDBText
with TQRDBText.Create(Self) do
begin
Parent := AchaParent(‘QRGroup1’, QuickRep1);
Dataset := QuickRep1.Dataset;
DataField := ‘Continent’;
Color := clAqua;
Font.Style := [fsBold];
end;
QuickRep1.Preview;
end;
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE66666
Auto-CompletarEsta funcionalidade existe em
aplicações como por exemplo, noInternet Explorer, no qual, quandocomeçamos digitar um endereço,automaticamente se esse já foidigitado anteriormente, ele éautomaticamente completado. Aqui,iremos demonstrar uma abordagempara implementar uma pesquisa embanco de dados com estafuncionalidade. Para estaabordagem, adicione umcomponente TDBGrid, um Tedit,uma TTable e um TdataSource econfigure como mostra a figura ao lado:
Para esta funcionalidade, utilizamos o evento OnKeyUp docomponente TEdit, como poderá verificar abaixo:
procedure TForm1.EdPesqKeyUp
(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
theText: string;
i, p: integer;
begin
with EdPesq do
case key of
8, 13, 46, 37..40: ; // Se for backspace,
enter, delete, ou setas, ignora...
else
begin
p := SelStart;
theText := copy(text, 0, p);
if TabCountry.Locate(‘Name’, theText,
[loCaseInsensitive, loPartialKey]) then begin
text := TabCountry.FieldByName
(‘Name’).AsString;
SelStart := p;
SelLength := length(text) - selStart;
end;
end; // case
end; // with
end;
DBExpressPlus – Turbinando a dbExpress
O DBExpressPlus é uma suíte de componentes gratuítos quefacilitam a execução de tarefas comuns no dia-a-dia doprogramador Delphi.
Você poderá fazer o download do DBExpressPlus no seguinteendereço:
http://sourceforge.net/projects/dbexpressplus
A instalação é bastante simples, basta descompactar oarquivo baixado preferencialmente criando uma pasta em$(Delphi)\Source\dbExpressPlus, onde “$(Delphi)” indica apasta de instalação de seu Delphi.
Após isso, abra o pacote dbExprPlus_r?0.dpk (?=versão doDelphi, 6 ou 7) e clique no botão “Compile”. Continuando, abra opacote dbExprPlus_d?0.dpk, clique em “Compile” e depois em“Install”.
Para concluir, acesso o menu “Tools | Environment Options| Library | Library Path” e adicione o path onde os arquivosforam descompactados, ou seja,$(Delphi)\Source\dbExpressPlus e com isso finalizamos ainstalação do dbExpressPlus.
Se tudo ocorreu sem problemas, você poderá visualizar osnovos componentes na paleta de componentes dbExpress:
Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 77777
Entre vários componentes que o pacote instala, podemosdestacar um que é bastante útil, o SQLScript, que permite aoprogramador rodar scripts SQL para manutenção no banco dedados.
Para conhecer as funcionalidades de todos os componentes,você poderá abrir o projeto de exemplo que acompanha odbExpressPlus, podendo ser encontrado na pasta Demo($(Delphi)\Source\dbExpressPlus\Demo).
Rave Reports – Como acessar valores nos eventos internos
O Rave Reports possui eventos internos visíveis somentedentro de sua própria IDE, eventos estes que trabalham comuma linguagem própria de scripts, a qual até o momento aindanão encontramos documentação a respeito, contudo, em cima detestes estamos conseguindo desvendar o caminho das pedras. Porexemplo, para acessar um determinado valor no eventoOnBeforePrint de uma banda do Rave, bastará acessar
diretamente via campo gerado pelo DataView:
if DataView1VendorName.AsString =
‘Cacor Corporation’ then
Text2.Text := DataView1VendorName.AsString;
end if;
Porta Serial – Como verificar se uma porta está em uso
Existem APIs do Windows que possibilitam fazer acesso emanutenção à portas seriais, veja abaixo:
var
portHandle: Integer;
begin
portHandle := 0;
portHandle := CreateFile(Pchar(ComboCOM.Text),
GENERIC_READ or GENERIC_WRITE, 0, nil,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if portHandle > 0 then
ShowMessage(‘Porta em uso!’)
else
raise Exception.Create
(‘Não consegui abrir a porta!’);
end;
Neste exemplo, estamos utilizando o objeto TGifImage que éinstalado junto com a suite de componentes RxLib. Esta suite égratuíta e possui vários componentes bem legais e, caso hajainteresse, poderá baixar em nosso site, www.theclub.com.br.Abaixo, segue a rotina de conversão:
implementation
uses RxGif;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
GIF: TGIFImage;
BMP: TBitmap;
begin
GIF := TGIFImage.Create;
BMP := TBitmap.Create;
try
GIF.LoadFromFile(‘c:\banner_theclub.gif’);
BMP.Assign(GIF);
BMP.SaveToFile(‘c:\theclub.bmp’);
finally
GIF.Free;
BMP.Free;
end;
end;
GIF – Como converter uma imagem GIF para BMP
Envie-nos suas dicas para que possamos compartilhá-las com todos associados.
Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE88888
DelphiDelphiDelphiDelphiDelphi
IntroduçãoOlá amigos, neste artigo vamos abordar um tema bastante
solicitado à nossa equipe de suporte e que parece ter ser um bichopapão, quando na realidade trata-se de algo bastante simples,como poderá ser acompanhar a seguir.
Iremos aqui, mostrar uma das abordagens possíveis naimplementação de um formulário de pesquisa, formulário esteque poderá ser utilizado praticamente em quase todas assituações onde sua aplicação necessitar de uma pesquisa, seja elauma pesquisa exata ou parcial, e ainda, permitindo ao usuárioselecionar qualquer campo (desde que este seja um tipo válido)para efetuar a pesquisa.
LógicaA idéia é bastante simples... Criaremos um formulário que
irá receber alguns parâmetros, tais como um objeto TDataSet(TQuery, TClientDataSet, TSimpleDataSet, etc) e o nome databela que irá sofrer a pesquisa. Após isso, iremos obter todos oscampos que nos interessarem do referido TDataSet passado comoparâmetro para montar uma lista na qual o próprio usuáriopoderá estar selecionando por qual campo irá pesquisar. Bem,chega de conversa e vamos por a mão-na-massa.
Primeiramente, abra o Delphi e crie um novo projeto esalve-o em seguida. Neste exemplo, iremos fazer acesso a umbanco Interbase/Firebird chamado EMPLOYEE.GDB, que é um,banco de dados exemplo que acompanha a instalação doInterbase/Firebird, via dbExpress utilizando o componenteTSimpleDataSet (disponível a partir do Delphi 7), mas, nadaimpede de aplicar esta abordagem a qualquer outra engine deacesso e banco de dados. Insira um componente TSimpleDataSetno formulário e configure seu nome para sdsCustomer, cliquecom o botão direito do mouse sobre ele e selecione o ítem “EditConnection” e crie uma conexão com seu banco de dados ou com o
banco de exemplo sugerido acima. Após isso, acesse a propriedade“DataSet” e na sub-propriedade “CommandText” adicione ainstrução SQL para acesso a sua tabela ou a tabela sugeridaCUSTOMERS, como exemplo, “Select * From CUSTOMERS”.Bem, agora dê um duplo clique no componente sdsCustomer ecom o botão direito, adicione os TFields (campos) na lista “FieldsEditor”, como mostra a Figura 1:
Pesquisa em Banco de Dados
Configure a propriedade DisplayLabel de todos oscampos para um nome amigável ao usuário. Oconteúdo da propriedade DisplayLabel será utilizadomais tarde quando formos implementar o formulário depesquisa
Sugestão:
Figura 1 – Campos no Fields Editor
Aprenda a implementar um formuláriogenérico para pesquisas
por Alessandro Ferreira, [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 99999
DelphiDelphiDelphiDelphiDelphi
Figura 2 – Formulário “Cadastro”
Adicione ainda, um componente TDBNavigator e umcomponente TSpeedButton, o qual receberá o nome desbtnPesquisa e o caption “Pesquisar”. Basicamente, nossoformulário de cadastro está pronto!
Implementação do Formulário de PesquisaVamos iniciar a implementação de nosso formulário genérico
de pesquisa.O primeiro passo é criar o formulário, para isso, adicione um
novo formulário, configure seu nome como “fmPesquisa” e salve-o com a unit como “unPesquisa” ou outro nome que achar maisconveniente.
Na sessão private deste do “fmPesquisa”, declare as seguintesvariáveis:
private
{ Private declarations }
Campos: TStringList;
Tabela: string;
edTexto (Edit)
cmbTipo (ComboBox)
Como mencionei anteriormente, esteformulário de pesquisa irá receberalguns parâmetros para “saber” emqual tabela irá ser efetuada a pesquisa etambém, quais os campos serãoapresentadas ao usuário. Para isso,iremos usar um artífio simples, porém,pode ser desconhecido à algunsprogramadores... Iremos reintroduzir oevento “Constructor” deste referidoformulário através da diretiva “reintro-duce”. Você pode me perguntar, -paraque isso? Bem, a resposta é bastantesimples: -quando chamamos o métodocreate de um objeto, automaticamente oevento constructor é acionado e comonecessitamos passar alguns parâmetrospara o novo formulário de pesquisaassim que o mesmo form criado,reintroduzimos o constructor definindoneste os parâmetros que desejamosinformar, pois, com isso, criamos eenviamos os parâmetros de uma só vez.A primeira vista pode parecer um poucoconfuso, mas na prática é bastante
simples. Antes de explicarmos o código que será implementado nofmPesquisa, vamos mostrar o layout sugerido para ofmPesquisa, conforme a Figura 3.
O componente CombBox nomeado cmbTipos irá conter os tiposdisponíveis de pesquisa, tendo os seguintes ítens fixos:
* Pelas Iniciais* Em qualquer parte do texto* Exata
Continuando, iremos inicar as implementações necessáriaspara nossa pesquisa funcionar! Agora, na sessão public de nossofmPesquisa, faça a declaração conforme mostra a Listagem 1:
public
{ Public declarations }
constructor Create(AOwner: TComponent; DataSet:
TSimpleDataSet; TableName: string); reintroduce;
end;
Listagem 1 – Constructor.
Onde:AOwner - objeto que está sendo criado (parâmetro
obrigatório)
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 01 01 01 01 0
DelphiDelphiDelphiDelphiDelphi
DataSet - objeto TDataSet (nosso TSimpleDataSet que irásofrer a pesquisa)
TableName - nome da tabela onde efetuaremos a pesquisa
Tecle a combinação de teclas “CTRL+SHIFT+C” com isso,automaticamente a IDE do Delphi irá declarar o “corpo” paranossa procedure, onde faremos as implementações conformeapresentada na Listagem 2:
constructor TfmPesquisa.Create(AOwner: TComponent;
DataSet: TSimpleDataSet; TableName: string);
var
i: integer;
begin
inherited Create(AOwner);
Tabela := TableName;
// liga DataSource
dsPesq.DataSet := DataSet;
// guardar nome dos campos.
Campos := TStringList.Create;
// Preenche campos no combobox
for i := 0 to DataSet.FieldCount-1 do
if DataSet.Fields[i].DataType in [ftString,
ftInteger] then
begin
cmbCampos.Items.Add(DataSet.Fields[i].DisplayLabel);
Campos.Add(DataSet.Fields[i].FieldName);
end;
// Posiciona no primeiro item
if cmbCampos.Items.Count>0 then
cmbCampos.ItemIndex := 0;
end;
Listagem 2 – Evento Constructor do fmPesquisa
Bastante atenção na implementação desta procedure, pois elaé fundamental para o perfeito funcionamento de nossoformulário de pesquisa. Para um melhor entendimento, vamosexplicar cada linha deste procedure a seguir...
Iniciamos com a diretiva inherited a qual deve estar naprimeira linha da procedure e faz a chamada do método Create naclasse base. Após isso, atribuímos o parâmetro TableName à nossavariável Tabela que deve ter sido declarada previamente na sessãoPrivate do fmPesquisa. Continuando, informamos o DataSetpassado como parâmetro à um componente datasource chamadodsPesq existente em nosso fmPesquisa.
Vamos instanciar agora um objeto do tipo TStringList quetambém já deve ter sido declarado na sessão private, o qual irá
Figura 3 – Layout sugerido para o fmPesquisa
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 11 11 11 11 1
DelphiDelphiDelphiDelphiDelphi
receber os campos dentro de um looping, varrendo todos oscampos do DataSet e testando campo a campo se é do tipo stringou integer (você pode adicionar outros tipos, caso acheinteressante) e caso seja, adicionamos o referido campo à lista(Campos) e os Labels à um TComboBox que nomeamos decmbCampos. (Lembra quando sugeri a configuração dapropriedade DisplayLabel dos campos?!, É exatamente isso queiremos apresentar em nosso Combo).
E, finalizando, apenas posicionamos o cmbCampos noprimeiro item de sua lista.
Continuando nossa implementação, iremos fazer algunspequenos ajustes para deixar nosso exemplo mais funcional,conforme demonstra a Listagem 3:
// evento OnCloseUp do cmbCampos
procedure TfmPesquisa.cmbCamposCloseUp(Sender:
TObject);
begin
EdTexto.SetFocus;
end;
// evento OnCreate do fmPesquisa
procedure TfmPesquisa.FormCreate(Sender: TObject);
begin
cmbTipo.ItemIndex := 0;
end;
// evento OnEnter do EdTexto
procedure TfmPesquisa.EdTextoEnter(Sender: TObject);
begin
// limpar o Edit.
EdTexto.Clear;
end;
// evento OnClose do fmPesquisa
procedure TfmPesquisa.FormClose(Sender: TObject; var
Action: TCloseAction);
begin
Campos.Free;
end;
// evento OnKeyDown do fmPesquisa
procedure TfmPesquisa.FormKeyDown(Sender: TObject;
var Key: Word;
Shift: TShiftState);
begin
case Key of
vk_Escape: ModalResult := mrCancel;
vk_F5: if not dsPesq.DataSet.IsEmpty then
ModalResult := mrOK;
end;
end;
// evento OnKeyDown do DBGrid_Pesq
procedure TfmPesquisa.DBGrid_PesqKeyDown(Sender:
TObject; var Key: Word;
Shift: TShiftState);
begin
if (key = vk_Return) and not
(dsPesq.DataSet.IsEmpty) then
ModalResult := mrOK;
end;
Listagem 3 – Alguns eventos do fmPesquisa
O próximo passo, posso dizer que em conjunto com o eventoconstructor do fmPrincipal, é o evento mais importante de nossoformulário de pesquisa, visto ser neste que será implementada apesquisa propriamente dita. Para isso, abra o evento OnKeyDowndo componente EdTexto e nele vamos passo a passo concluirnossa pesquisa. Comece declarando três variáveis do tipo string,sendo aSQL, aWhere e Campo. A Listagem 4, mostra o código completodo evento OnKeyDown...
procedure TfmPesquisa.EdTextoKeyDown(Sender:
TObject; var Key: Word;
Shift: TShiftState);
var
aSql, aWhere, Campo: string;
begin
if (key in [vk_Down, vk_Up]) and not
(dsPesq.DataSet.IsEmpty) then
DBGrid_Pesq.SetFocus;
if (edTexto.Text<>’’) and (Key = vk_Return) then
begin
// descobrir o campo.
Campo := Campos[cmbCampos.ItemIndex];
// inicializar variáveis auxiliares
aSql := ‘’;
aWhere := ‘’;
// montar cláusula where.
case cmbTipo.ItemIndex of
0: {Iniciais}aWhere := Format(‘ Where
Upper(%s) Like %s ‘, [Campo,
QuotedStr(EdTexto.Text+’%’)]);
1: {Qualquer}aWhere := Format(‘ Where
Upper(%s) Like %s ‘, [Campo,
QuotedStr(‘%’+EdTexto.Text+’%’)]);
2: {Exata }aWhere := Format(‘ Where
Upper(%s) = %s ‘ , [Campo,
QuotedStr(EdTexto.Text)]);
end;
aSql := Format(‘Select * From %s %s’, [Tabela,
aWhere]);
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 21 21 21 21 2
DelphiDelphiDelphiDelphiDelphi
with TSimpleDataSet(dsPesq.DataSet) do
begin
Close;
DataSet.CommandText := aSql;
Open;
if not IsEmpty then
DBGrid_Pesq.SetFocus;
end;
end;
end;
Listagem 4 – Evento OnKeyDown do EdTexto
No início do evento OnKeyDown, começamos fazendo umaverificação das teclas vk_Down (seta abaixo) e vk_Up (seta acima) e,caso a tabela apresentada esteja com algum registro visível,mandamos o foco para o DBGrid_Pesq.
Para que a pesquisa seja efetuada, verificamos se o usuárioteclou vk_Return (Enter) e se existe alguma coisa digitada nocomponente EdTexto e caso sim, entramos no bloco para realizar apesquisa.
A variável local Campo recebe o nome do campo selecionado nocmbCampos, porém, obtendo o nome através da lista (Campos),lista esta que alimentamos com o nome dos campos no eventoconstructor, lembra?!
Seguindo, inicializamos as variáveis locais aSQL e aWherecomo vazias, e montamos um “case”, analisando o tipo depesquisa selecionada no cmbTipos e assim, montar a cláusulaWhere para nossa pesquisa. Basicamente, nosso “case” verifica oseguinte:
* Opção 0, pesquisa pelas iniciais- Nesta abordagem, preparamos a cláusula where para
utilizar o operador Like, adicionando a caracter coringa “%”apenas no final do valor pesquisado, como exemplo, “ Select *From Tabela where campo Like ‘TheClub%’ “.
* Opção 1, pesquisa em qualquer parte do campo- Nesta abordagem, preparamos a cláusula where para
também utilizar o operador Like, contudo, adicionando o caractercoringa “%” no início e no final do valor pesquisado, exemplo:“Select * From Tabela where campo Like ‘%TheClub%’”.
* Opção 2, pesquisa exata- Nesta abordagem, preparamos a cláusula where para
trabalhar com o operador “=”, visto a busca ser exata. Exemplo: “Select * From Tabela where campo = ‘TheClub’ “.
Estando pronta nossa claúsula where, partimos para aimplementação de nossa sentença SQL completa, atribuindo a
mesma para a variável local aSQL:
aSql := Format(‘Select * From %s %s’,
[Tabela, aWhere]);
E finalizando, iremos repassar asentença SQL completa para o objetoTDataSet, utilizando o valor configuradona propriedade DataSet do dsPesq, ondefazemos um typecast* paraTSimpleDataSet, abrimos o mesmo e casoalgum registro tenha sido encontrado,mandamos o foco para nossoDBGrid_Pesq.
Como mencionei, esta abordagem pode ser Aplicada à outrosobjetos TdataSets, como por exemplo uma TQuery ou umTClientDataSet, onde a implementação ficaria como demonstradona Listagem 5.
// TClientDataSet *
with TClientDataSet(dsPesq.DataSet) do
begin
Close;
CommandText := aSql;
Open;
if not IsEmpty then
DBGrid_Pesq.SetFocus;
end;
// TQuery
with TQuery(dsPesq.DataSet) do
begin
Close;
SQL.Text := aSql;
Open;
if not IsEmpty then
DBGrid_Pesq.SetFocus;
end;
Listagem 5 – Utilizando ClientDataSet e Query.
Chamando o Formulário de Pesquisa
Antes de finalizamos o artigo, iremos demonstrar comochamar o nosso formulário de pesquisa. O código demonstrado naListagem 6 representa o evento OnClick do botão sbtnPesquisa, na qualpoderá ver que a chamada é bastante simples e funcional.
procedure TForm1.sbtnPesquisaClick(Sender: TObject);
begin
TypeCast - Conversão detipos em object pascal, ouseja, no exemplo citado,convertemos um objetoTDataSet para um objetoTSimpleDataSet, afim depoder acessarpropriedades, métodos eeventos de umTSimpleDataSet.
Dica
TClientDataSet - No casodesta abordagem utilizandoum componenteTClientDataSet, vocêdeverá alterar a propriedadeOptions |AllowCommandText doc o m p o n e n t eTDataSetProvider ao qualseu ClientDataSet estáligado.
Dica
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 31 31 31 31 3
DelphiDelphiDelphiDelphiDelphi
fmPesquisa := tfmPesquisa.Create(Self,
sdsCustomer, ‘CUSTOMER’);
try
fmPesquisa.ShowModal;
finally fmPesquisa.Free; end;end;
Listagem 6 – Chamada da Pesquisa
Veja que não há nada em especial, a não ser, a chamada dométodo create, o qual recebe alguns parâmetros a mais (essa já eranossa intenção no início), sendo o objeto TDataSet (no casosdsCustomer) e o nome da tabela, neste exemplo CUSTOMER.Depois, executamos o método ShowModal como de costume e umFree para liberar o formulário da memória.
ConclusãoNeste simples artigo, procuramos mostrar uma das
abordagens possíveis para implementação de um formulário depesquisa genérica, sendo esta apenas a ponta do iceberg, a qualcom um pouco mais de criatividade pode ser enriquecida deacordo com suas necessidades. Espero ter contribuído parafacilitar seu dia-a-dia, e, caso tenha alguma sugestão ou crítica,bastará nos enviar que faremos o possível para atendê-lo,abraços e até a próxima.
Download
O projeto de exemplo referente este artigo está disponível paradownload em:
http://www.theclub.com.br/revista/download/pesquisagenerica.zip
Sobre o autorAlessandro Ferreira,Consultor Técnico do The [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 41 41 41 41 4
DelphiDelphiDelphiDelphiDelphi
Na matéria anterior focamos a criação de um relacionamentoMaster/Detail com DBExpress.
Nesta segunda parte iremos fazer algumas alterações emnosso projeto inicial, pois da maneira como foi criado ele nãovisualiza o código sequencial criado dentro do banco através dastriggers, com isso dependendo de como você irá utilizá-lo ocorremerros porque os ClientDataSets ainda não estão visualizandoesses códigos.
Portanto somente iremos mudar a criação do códigosequencial das tabelas Master e Detalhe que estão dentro de duastriggers para serem geradas dentro do projeto, para que assimlogo após o CDSMaster incluir um registro o seu código já estarávisível ao usuário.
O mesmo caso será feito para o CDSDetalhe. Vamos iniciaras alterações.
Alteração no banco de dados ( GDB )
Bem a primeira alteração que iremos fazer é em nosso bancode dados, ao qual nós iremos apagar as duas Triggersresponsáveis pela criação do código sequencial. Para apagar essasduas Triggers iremos executar as seguintes instruções:
DROP TRIGGER AI_MASTER_CODMASTERDROP TRIGGER AI_DETALHE_CODDETALHE
Pronto, essa é a única alteração realizada em nosso banco dedados.
Alteração no projeto
Em nosso projeto a alteração também será simples, poissomente iremos criar uma função ao qual irá executar um Selectnos Generators para pegar o próximo valor do Código sequencialdo Master e do Detalhe.
Primeiro passo, abra o DataModule e dê duplo click sobre ocomponente SQLMaster para abrir a lista de tfields. Selecione otfield CODMASTER e na propriedade ProviderFlags altere aopção pfInUpdate para TRUE, ficando como TRUE as opçõespfInUpdate e pfInKey.
Faça os mesmos passos para o SQLDetalhe, isso é, altere oProviderflags do campo CODDETALHE deixando o pfInUpdate eo pfInKey como TRUE.
Não é necessário alterar os Providerflags dos ClientDataSets.Neste momento habilitamos para que os campos
DBEXPRESSDBEXPRESSDBEXPRESSDBEXPRESSDBEXPRESSCriando um relacionamento MASTER/DETALHE – Parte II
por André Colavite – Suporte THE [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 51 51 51 51 5
DelphiDelphiDelphiDelphiDelphi
CODMASTER e CODDETALHE possam receber valores geradosdentro do projeto Delphi, o próximo passo será gerar esse códigoautomaticamente.
Gerando o código sequencial dentro do projeto
Bem, para começar coloque um componente SQLQuery nodatamodule e em sua propriedade NAME coloque SQLGen. Nasua propriedade SQLConnection ligue ao SQLConnection1, jáexistente no datamodule.
Esse SQLGen será utilizado para ler o próximo valor dosGenerators e para isso iremos criar uma function chamadaGeraCodigo.
Esta function terá um parâmetro chamado NomeGeneratorao qual será utilizado para indicar o nome do Generator a serutilizado e dentro dessa function iremos montar, viaprogramação, uma instrução de Select ao qual irá buscar opróximo valor desse Generator passado como parâmetro.
Veja abaixo a function criada na unit do DataModulecontendo a instrução para montar o select e pegar o próximovalor do Generator.
function TDM.GeraCodigo(NomeGenerator: String):
Integer;
begin
SQLGen.SQL.Text := ‘select
Gen_ID(‘+NomeGenerator+’,1) from RDB$DataBase’;
SQLGen.Open;
Result := SQLGen.Fields[0].AsInteger;
SQLGen.Close;
end;
Listagem – Function GeraCodigo
Essa function poderá ser declarada na seção Private da Unit,conforme o exemplo abaixo:
private
function GeraCodigo(NomeGenerator: String):
Integer;
public
{ Public declarations }
end;
Listagem – Declaração da function GeraCodigo
O próximo passo será criar uma chamada para essa functionao qual será no evento BeforePost do CDSMaster e doCDSDetalhe.
Veja nas instruções abaixo que verifico se estou fazendo umainclusão de registros, se tiver, chamo a function passando comoparâmetro o nome do generator e depois o retorno da function euatribuo para o campo que é o código sequencial.
procedure TDM.CDSMasterBeforePost(DataSet:
TDataSet);
begin
if DataSet.State = dsInsert then
CDSMasterCODMASTER.AsInteger :=
GeraCodigo(‘MASTER_CODMASTER_GEN’);
end;
Listagem - Evento BeforePost do CDSMaster
procedure TDM.CDSDetalheBeforePost(DataSet:
TDataSet);
begin
if DataSet.State = dsInsert then
CDSDetalheCODDETALHE.AsInteger :=
GeraCodigo(‘DETALHE_CODDETALHE_GEN’);
end;
Listagem - Evento BeforePost do CDSDetalhe
Pronto, terminamos as alterações em nosso projeto, veja queforam bem simples. Agora ao incluir um registros no CDSMasterou no CDSDetalhe o código sequencial já estará visível logo após oPost.
O projeto de exemplo contendo as alterações está disponívelem nosso site:
http://www.theclub.com.br/revista/download/DBXMasterDetailIB.zip
Sobre o autorAndré ColaviteConsultor Técnico do The [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 61 61 61 61 6
Caro leitor da THE CLUB MeGAZINE,
É com grande satisfação que estamos entrando no nosso décimo ano deexistência. Nestes 10 anos o THE CLUB acessorou inúmeras pessoas,ajudou milhares de programadores e difundiu várias linguagens deprogramação, entre elas o Clipper, Visual Objects, o nosso querido Delphi,e também linguagens da Microsoft como o Visual Basic.NET e o C#, danova plataforma .NET.
Nestes 10 anos acumulamos uma vasta experiência, sendo que járespondemos mais de 100.000 questões que foram reportadas ao suportetécnico! Toda esta base de conhecimento sempre esteve disponível à você,que nos acompanha no dia-a-dia, seja pelo seu contato conosco portelefone, e-mail, carta ou pela web, agora com o novíssimo recurso desuporte on-line, onde você mesmo pode achar tudo o que precisa com anossa ferramenta de pesquisa.
A partir deste mês, você acompanhará uma contagem regressiva, ondevamos lembrar toda a história do THE CLUB nestes 10 anos, e estaremospublicando as revistas que foram lançadas no mês de setembro, ano aano, até chegarmos a edição número 1, onde estaremos republicando elainteira, da mesma maneira que foi publica há 10 anos atrás!
Este é um presente que o THE CLUB oferece à você, que tem nosprestigiado ao longo de todos estes anos. Boa leitura, e boas recordações!
Em setembro de 2002, estávamos publicando uma matéria sobre olançamento do Delphi 7, as suas diversas mudanças, e o suporte ao RaveReports, ModelMaker e muito mais. Também tratamos das aplicaçõesWAP com banco de dados, que estava no auge nesta época. A matériaprincipal tratou do DataSnap, escrita por Anderson Haertel Rodrigues.
RetrospectivaRetrospectivaRetrospectivaRetrospectivaRetrospectiva
The Club MegazineThe Club MegazineThe Club MegazineThe Club MegazineThe Club Megazine
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 81 81 81 81 8
DelphiDelphiDelphiDelphiDelphi
IntraWeb é um modo visual para desenvolver aplicações paraWeb. Neste artigo, mostraremos como usar IntraWeb 5.1.28 emcombinação com Delphi 7 Profissional e aplicações de WebBrokerpara produzir aplicações Web que trabalham com bancos dedados.
Apesar do IntraWeb não ter sido escrito pela Borland, ele éincluído no Delphi 7 Professional e Enterprise. Contudo, existediferença do pacote IntraWeb entre o que acompanha o Delphi 7,sendo no Professional, o IntraWeb “Page Mode” e no Enterprise oIntraWeb “Application Mode”, o qual é bem mais poderoso,contudo, podemos obter um ótimo resultado em “Page Mode”,fazendo uma mesclagem com o aplicações WebBroker comopoderá acompanhar neste artigo.
Um detalhe importante, neste artigo estamos utilizando aversão 5.1.28 do IntraWeb, e assim sendo recomendo vocêatualizar seu IntraWeb, o que poderá ser feito no site dofabricante, Atozed Software (www.atozedsoftware.com).Reforçando, a atualização mais recente e gratuíta (paraprogramadores Delphi 7) do IntraWeb é a versão 5.1.28. Existetambém a versão 6, porém, esta versão não é gratuíta. Nesteartigo, utilizaremos a versão gratuíta.
WebBroker + IntraWeb Page Mode
Bem, para começar, crie uma aplicação WebBroker simples...Para isso, acesse o menu File | New | Other, e selecione “WebServer Application”. Isso lhe apresentará uma caixa de diálogosemelhante a mostrada na Figura 1, onde você deverá selecionar“CGI Stand-alone executable”.
IntraWebIntraWebIntraWebIntraWebIntraWebDesenvolvendo aplicações web Page Mode
com IntraWeb e WebBroker
Adptação: Alessandro Ferreira, [email protected]
Figura 1 – Nova aplicação WebBroker
Assim, será gerada uma nova aplicação WebBroker, na qualpoderá verificar a existência de um WebModule vazio. Salve aaplicação como IWB.dpr e o WebModule para WebMod.pas.
Agora, adicione dois componentes sendo umTIWModuleController e um TIWPageProducer. O componenteTIWModuleController é responsável em fazer os controles detodas as páginas IntraWeb adicionadas ao projeto, e assim sendo,você irá necessitar de apenas um componente deste em seuWebModule. Já, o componente TIWPageProducer, é responsávelem “produzir” páginas IntraWeb, sendo necessário umcomponente para cada página que necessitarmos apresentar.Nosso WebModule ficará semelhante ao apresentado na Figura 2.
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 91 91 91 91 9
DelphiDelphiDelphiDelphiDelphi
Antes de continuarmos, adicione uma WebAction (ação) em nossoWebModule. Para isso, dê um duplo clique no WebModule e adicione anova ação, e configure a propriedade “PathInfo” da mesma com ovalor “/IntraWeb”, pois será esta ação a responsável em chamarnosso IWForm. Confira a Figura 3.
Por enquanto, nosso IWPageProducer não está fazendo nada,porém, porque ainda não está conectado a nenhuma páginaIntraWeb. Para gerar uma página IntraWeb, acesse o menu File| New | Other | IntraWeb, conforme apresentado na Figura 4.
Figura 4
Figura 3 – WebActions
Figura 2 – WebModule
Agora, selecione a opção “New Form” o qual lhe apresentaráum Wizard para criação de forms IntraWeb, no qual você deveráselecionar a opção “Page Forms”, conforme apresentado na Figura5.
Figura 5 – Wizard para seleção de Forms
Obviamente, quando trabalhamos com IntraWeb em “PageMode”, devemos ignorar as opções referentes “Application Form”.Outro detalhe, você poderá observar que existem opções “3.2”, aqual é restringindo a HTML 3.2 e oferece suporte a dispositivosPDA, como exemplo celulares. Agora, salve este novo “PageForm” com o nome de IWformMain.pas e retorne ao WebModule.
IntraWeb 5.1 – 1º bug encontrado emnossa abordagem
Observe que depois que você adicionou onovo “Page Form” o qual salvamos comoIWformMain.pas, se abrir o arquivo de projetoIWB.dpr, ele ainda está fazendo referência a“Unit1”, mesmo após termos alterado e gravadonosso “Page Form” como IWfrmMain.pas. Emresumo, para resolver, altere “Unit1”manualmente para “IWformMain.pas”, comoexemplo:
IWformMain in ‘IWformMain.pas’
{IWForm1: TIWPageForm};
Bem, voltando ao nosso WebModule, declare aunit IwformMain na lista de units abaixo da
sessão implementation de nossa unit WebMod (referente ao
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 02 02 02 02 0
DelphiDelphiDelphiDelphiDelphi
WebModule). Após isso, declare as units IWApplication eIWPageForm à cláusula “uses” abaixo da sessão interface. Agora,iremos conectar o componente IWPageProducer ao nosso “PageForm”, utilizando para isso o evento OnGetForm do próprioIWPageProducer, conforme poderá acompanhar na Listagem 1.
procedure TIntraWeb.IWPageProducer1GetForm(
ASender: TIWPageProducer;
AWebApplication: TIWApplication;
var VForm: TIWPageForm);
begin
VForm := TIWfrmMain.Create(AWebApplication)
end;
Listagem 1
Implementando nosso IntraWeb Page Form
Você poderá acrescentar todos os tipos de componentesdisponibilizados nas palhetas “IntraWeb” à este novo “PageForm”, o qual posteriormente estará sendo chamado por nossaaplicação WebBroker, de forma bastante simples!
Como exemplo, iremos construir uma aplicação bastantesimples que tem a finalidade de converter graus Celsios paraFahrenheit e vice-versa. Para isso, adicione dois componentesTIWEdit, e ajuste a propriedade “name” para IWEditCelsius eITEditFahrenheit, depois, apenas limpe o conteúdo dapropriedade “text” dos mesmos. Continuando, adicione doiscomponentes TIWButton e ajuste sua propriedade “name” paraIWButtonCelsiusToFahrenheit e IWButtonFahrenheitToCelsiuse sua propriedade “caption” para “Celsius to Fahrenheit” e“Fahrenheit to Celsius”, respectivamente. Nosso IwfrmMaindeverá ficar semelhante a Figura 6.
Figura 6 – IWFrmMain
Note que este form se parece com um form convencional doDelphi, o qual você já está acostumado a trabalhar, há não serpelo fundo branco... Além das aparências, o código à serimplementado para os botões IWButtonCelsiusToFahrenheit eIWButtonFahrenheitToCelsius não trás nenhuma novidade,
como poderá acompanhar na Listagem 2.
// evento OnClick do IWButtonCelsiusToFahrenheit
procedure
TIWfrmMain.IWButtonCelsiusToFahrenheitClick(Sender:
TObject);
begin
IWEditFahrenheit.Text := Format(‘%.2f’,
[StrToFloatDef(IWEditCelsius.Text,0) * 9/5 + 32])
end;
// evento OnClick do IWButtonFahrenheitToCelsius procedure
TIWfrmMain.IWButtonFahrenheitToCelsiusClick(Sender:
TObject);
begin
IWEditCelsius.Text := Format(‘%.2f’,
[(StrToFloatDef(IWEditFahrenheit.Text,0)-32) * 5/
9])
end;
Listagem 2 – Eventos do botão.
Bem, tudo parece estar OK! Assim sendo, o próximo passo écompilar e executar nossa aplicação em browser de internet,então, compile a aplicação e copie o arquivo “IWB.EXE” gerandopela compilação para uma pasta com permissão para execução deCGIs e Scripts de seu servidor WEB, IIS ou PWS, e execute aaplicação via seu browser.
IntraWeb 5.1 – 2º bug encontrado em nossa abordagem
Para quem já está acostumado a trabalhar com aplicaçãoCGI WebBroker, para acessar uma determinada URL bastachamá-la, como exemplo a URL deste exemplo, que poderia serhttp://localhost/scripts/IWB.exe/IntraWeb. Contudo, quandoadicionamos “Page Forms” à nossa aplicação CGI WebBroker, eesta irá necessitar executar alguma ação, mesmo algo simplescomo este projeto, ao invés desta chamar a URL correta, comoexemplo http://localhost/scripts/IWB.exe/IntraWeb, ela apenasposta http://localhost/IntraWeb, o que irá resultar em erro!
Aparentemente o IntraWeb não consegue recuperar o nomecorreto do módulo de executável (aplicações) CGI. Para resolver(mais uma vez manualmente) podemos especificar o caminhocompleto de nosso CGI na propriedade FormAction de nosso “PageForm” e ainda, ajustar a propriedade PostToSelf para False.
Após configurar a propriedade FormAction para http://localhost/scripts/IWB.exe/IntraWeb e a propriedade PostToSelfpara False, recompile sua aplicação e faça o teste da mesma
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 12 12 12 12 1
DelphiDelphiDelphiDelphiDelphi
novamente via browser e verá que agora irá funcionar semproblemas, confira a Figura 7.
Figura 7 – Aplicação rodando no browser.
Acessando banco de dados via Page Mode
A seguir, iremos desenvolver mais uma aplicação exemplotrabalhando com “Page Forms” fazendo acesso à um banco dedados Interbase/Firebird. Para isso, certifique-se de ter oInterbase/Firebird instalado em sua máquina para podemosprosseguir.
Bem, crie um novo projeto, seguindo passo-a-passo tudo quejá foi sugerido anteriormente, e neste novo “Page Form” adicioneos seguintes componentes apresentados no Quadro 1.
Componente
sqlConnection
Faça as devidas configurações, acessando obanco de dados EMPLOYEE.GDB que é umbanco de dados exemplo que você deve terem sua máquina.Dica: Utilize a configuração do path do bancode dados da seguinte forma:localhost:c:\pasta\employee.gdb
sqlDataSet
Ajuste sua propriedade sqlConnection para ocomponente sqlConnection adicionadoanteriormente... e sua propriedadeCommandText para:Select * From Customer
DataSetProvider Ligue sua propriedade DataSet ao sqlDataSetanteriormente adicionando.
ClientDataSet Ligue sua propriedade ProviderName aoDataSetProvider anteriormente adicionado.
DataSource Ligado ao ClientDataSet.
Quadro 1 – Componentes para acesso a dados.
Continuando, como estamos trabalhando com o componenteClientDataSet para manutenção nos dados, temos que
programar os eventos AfterDelete e AfterPost domesmo, para que os dados sejam postados aoservidor de banco de dados, veja a Listagem 3.
// evento AfterPost
procedure
TIWfrmMain.ClientDataSet1AfterPost
(DataSet: TDataSet);
begin
ClientDataSet1.ApplyUpdates(0)
end;
// evento AfterDeleteprocedure
TIWfrmMain.ClientDataSet1AfterDelete
(DataSet: TDataSet);
begin
ClientDataSet1.ApplyUpdates(0)
end;
Listagem 3 – Eventos do ClientDataSet
Outro detalhe importante quando trabalhamos com ocomponente ClientDataSet, é em relação ao tratamento de errosque possam ocorrem no momento que os dados forem postados aoservidor de banco de dados. O ClientDataSet oferece um eventochamado OnReconcileError o qual tem exatamente a finalidade dereceber erros gerados durante a atualização, conformeapresentado na Listagem 4.
procedure TIWfrmMain.ClientDataSet1ReconcileError(
DataSet: TCustomClientDataSet; E: EReconcileError;
UpdateKind: TUpdateKind; var Action:
TReconcileAction);
begin
WebApplication.ShowMessage(E.Message)
end;
Listagem 4 – Evento OnReconcileError do ClientDataSet
Bem, agora adicione os controles visuais ao “Page Form”,sendo basicamente alguns TIWDBEdit e TIWLabels, umTIWDBNavigator e um TIWDBGrid. Poderá ver na Figura 8 o“Page Form” já configurado.
Bem, agora adicione os controles visuais ao “Page Form”,sendo basicamente alguns TIWDBEdit e TIWLabels, umTIWDBNavigator e um TIWDBGrid. Poderá ver na Figura 8 o“Page Form” já configurado.
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 22 22 22 22 2
DelphiDelphiDelphiDelphiDelphi
Figura 8 – Page Form contendo os componentes
Ajuste a propriedade bgIndicator dentro da propriedade Optionsdo componente IWDBGrid, a qual irá mostrar um pequenoindicador de registros ao lado do registro quando a aplicação forexecutada.
Outro detalhe importante, certifique-se de que oscomponentes ClientDataSet e sqlDataSet estejam com a propriedade“Active” setada para False em tempo de desenvolvimento, pois, oClientDataSet deverá ser ativado via programação no momento queo “Page Form” for executado.
Estando tudo OK, salve e compile a aplicação e novamentecopie o arquivo “IWB.EXE” gerado para seu servidor web ouservidor pessoal para podermos executar um teste com nossanova aplicação, se tudo correu bem, você verá uma telasemelhante a apresentada na Figura 9.
IntraWeb 5.1 – 3º bug encontrado em nossaabordagem
Quando utilizamos esta abordagem de trabalhar com“IntraWeb Page Forms” em conjunto com aplicações WebBroker,ao navegar entre os registros é gerada uma exceção com amensagem “Key Violation” ou simplesmente “HTTP 500 Internalserver error”, dependendo das configurações de seu browser. Este
problema ocorre tanto utilizando executáveis CGI, quanto emDLLs ISAPI, porém, iremos demonstrar uma forma alternativapara solucionar este problema a seguir.
Fixando problemas na navegação de registros em “PageMode”
Na realidade, o problema durante a navegação ocorre porquenão existe uma sessão ou algo semelhante mantendo um estadoda página atual e com isso, o ponteiro do registro se perdedurante a navegação. O “segredo” aqui, será armazenar oponteiro do registro e informá-lo manualmente (mais uma vez?!)ao ClientDataSet e com isso podemos navegar para o próximoregistro e registros anteriores sem problemas, para isso, iremosutilizar o evento OnRender de nosso “Page Form”, conformeapresentado na Listagem 5.
// evento OnCreate
procedure TIWfrmMain.IWPageFormCreate(Sender:
TObject);
var
CustNo: String;
begin
ClientDataSet1.Active := True;
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 32 32 32 32 3
DelphiDelphiDelphiDelphiDelphi
CustNo := WebApplication.Request.
ContentFields.Values[‘CUST_NO’];
if CustNo <> ‘’ then
ClientDataSet1.Locate(‘CUST_NO’, CustNo, [])
end;
// evento OnRender
procedure TIWfrmMain.IWPageFormRender(Sender:
TObject);
begin
HiddenFields.Add(‘CUST_NO=’ +
ClientDataSet1CUST_NO.AsString);
end;
Listagem 6 – eventos de nosso “Page Form”
Para que esta solução funcione corretamente, o campo/valorinformado deverá corresponder a um ID único de sua tabela,sugiro utilizar o campo referente sua chave primária para isso,que com certeza não terá problemas.
Conclusão
Você (que possui o Delphi 7Enterprise) pode estar seperguntando qual a vantagem deutilizar o IntraWeb como “PageMode”, sendo que a abordagem“Application Mode” é bem maispoderosa?!
A princípio, aplicaçõesdesenvolvidas como “ApplicationMode” permitem gerar apenas DLLsISAPI, o que é um inconvenientequando não temos um servidor webpróprio, principalmente quando aaplicação já está em produção enecessitamos fazer atualização dareferida DLL, o que já não acontececom aplicações executáveis CGI.
Além de tudo, com um pouquinhomais de trabalho, conseguimos obterquase os mesmos resultados de uma
aplicação “Application Mode”, mesclandouma aplicação WebBroker com IntraWeb.
Outro detalhe importante, é que programadores que possuemo Delphi 7 “Professional”, não tem acesso a desenvolvimento“Application Mode”, restando apenas o “Page Mode”, mas, comopuderam ver neste simples artigo, é possível implementarpoderosas aplicações, com acesso a banco de dados e tudo maisque for necessário, mesmo em “Page Mode”, espero ter ajudado ecaso tenham sugestões, críticas ou dúvidas, sintam-se a vontadepara entrar em contato, abraços e até a próxima!
Download
O projeto de exemplo referente este artigo está disponível paradownload em:
http://www.theclub.com.br/revista/downloads/IntraWebBroker.zip
Figura 9 – Aplicação acessando banco de dados rodando no browser.
Sobre o autor
Alessandro Ferreira,Consultor Técnico do The [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 42 42 42 42 4
DelphiDelphiDelphiDelphiDelphi
Salve, salve Delphianos!
Vocês já imaginaram a união das melhores tecnologias Webnuma aplicação? A intenção deste artigo é demonstrar a uniãodas tecnologias WebBroker, Mobile, Intraweb e WebServices, demaneira simples e objetiva.
Este artigo foi demonstrado na Borcon 2003, e deu paraperceber a satisfação do público, e o famoso caso do WAP – ame-oou deixe-o.
Visão geral da aplicaçãoAplicação para gerenciamento de veículos na Matrix,
utilizando as seguintes tecnologias:
. WebBroker (base para aplicação)
. WebServices (webservice para consulta de veículos)
. WAP (aplicação para multas)
. Intraweb (cadastro de veículos)
. dbExpress (tecnologia de acesso a dados)
Ferramentas para testar a aplicação:
. Apache 2.036 Servidor Web (www.apache.org)
. Deck – It (emulador wap-browser) www.pyweb.com
Configurações iniciais
. Crie a seguinte estrutura de diretório
Delphi Web HardCoreDelphi Web HardCoreDelphi Web HardCoreDelphi Web HardCoreDelphi Web HardCore
Servidor Web
. Após a instalação do Apache, configure o arquivo httpd.conf(normalmente localizado no diretório “C:\Arquivos deprogramas\Apache Group\Apache2\conf”), como segue:
. localize a seção DocumentRoot e altere para:
DocumentRoot “C:/borcon_matrix/html”
Neste ponto definimos a raiz do nosso servidor principal.. localize a seção ScriptAlias, e insira a linha que segue:
ScriptAlias /scripts/ “c:/borcon_matrix/scripts/”
<Directory “C:/borcon/scripts”>
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
Neste ponto estamos configurando o subdiretório virtual (/scripts) para execução de scripts CGI.
No final do arquivo, insira a configuração para o nosso
<VirtualHost localhost>
ServerAdmin [email protected]
DocumentRoot “c:/borcon_matrix/html”
ServerName nome_do_seu_computador
</VirtualHost>
Salve o arquivo e reinicie o Apache.
Script do Banco
No exemplo estamos utilizando o SGDB Interbase 6.02. Figura 1 – Estrutura de Diretórios
por Emerson Facunte
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 52 52 52 52 5
DelphiDelphiDelphiDelphiDelphi
SET SQL DIALECT 3;
/* CREATE DATABASE ‘c:\borcon\matrixdb.gdb’
PAGE_SIZE 4096
DEFAULT CHARACTER SET */
/* Table: MULTAS, Owner: SYSDBA */
CREATE TABLE “MULTAS”
(
“MLT_CODIGO” INTEGER,
“MLT_PLACA” VARCHAR(7),
“MLT_DATA” DATE
);
/* Table: VEICULOS, Owner: SYSDBA */
CREATE TABLE “VEICULOS”
(
“VEI_PLACA” VARCHAR(7) NOT NULL,
“VEI_MODELO” VARCHAR(30),
“VEI_PROPRIETARIO” VARCHAR(30),
“VEI_ANO” INTEGER,
“VEI_COR” VARCHAR(20),
PRIMARY KEY (“VEI_PLACA”)
);
Criando a aplicação1ª. Fase – criação da base e aplicação wapWebBroker
. Iniciar aplicação Other.../WebServices.
. Selecione o modelo Soap Server Application.
. Em seguida, selecione a opção do modelo CGI para facilitar oaprendizado.
. Grave a unit como um_wmMatrix.pas e o projeto comoMatrixDriver.DPR
. Altere o nome do container para wmMatrixV.
Repare que utilizamos o assistente do WebServices para criaro nosso WebBroker com os objetos-base para criação doWebServices.
Objetos de Dados
. Insira um objeto SQLConnection [dbExpress], e altere asseguintes propriedades:
. Através do duplo-clique, entre no assistente.
. Crie uma nova conexão Interbase clicando no botão [ + ]. . Database = localhost:c:\borcon_matrix\matrixdb.gdb. SQLDialect = 3. Login Prompt = False. Name = conexao. Connected = True. Insira um objeto SQLDataSet [dbExpress], e altere as
propriedades que seguem:. SQLConnection = conexão. CommandText = INSERT INTO MULTAS VALUES (:CODIGO, :PLACA,
:DATA). Agora vamos criar o documento WML para interagir com o
celular. Através das opções File.../New.../Other.../Web Documents,
selecione a opção WML Document. Insira o código que segue.
<wml>
<card id=”inclusao”>
<p align=”center”>
Matrix Multas
<br/>
<br/>
</p>
<p>
placa <input type=”text” name=”placa”/>
<select name=”multa” title=”codigo multa”>
<optgroup title=”multa”>
<option value=”1">rodizio </option>
<option value=”2">velocidade</option>
<option value=”3">vermelho</option>
</optgroup>
</select>
<do type=”accept” label=”CONFIRMA”>
<go href=”wapconfirma” method=”post”>
<postfield name=”placa” value=”$placa”/>
<postfield name=”multa” value=”$multa”/>
</go>
</do>
</p>
</card>
</wml>
. Grave o documento no subdiretório
C:\Borcon_Matrix\HTML com o nome:MULTA.WML
Neste ponto vamos inserir o objeto responsável pela produção
Figura 2 – Testando o módulo WAP
Figura 3 – Tipo da Multa
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 72 72 72 72 7
DelphiDelphiDelphiDelphiDelphi
de mensagens para clientes WAP.
. Insira um objeto do PageProducer [Internet] e configure asseguintes propriedades:
HTMLFile = C:\borcon_matrix\html\multa.wmlName = PPWAP.
Com isso concluímos as definições iniciais da nossa aplicação.
Ações para o cliente WAP
Neste ponto iremos criar as ações necessárias para o móduloWAP.
.Através do duplo-clique no wmMatrixV adicione uma Action(primeiro speed button, ou tecla INS), alterando as seguintespropriedades:
Name = actWAPPathInfo = /wap. Insira o código a seguir no evento OnAction deste objeto:
Response.ContentType:=’text/vnd.wap.wml’;
Response.Content:=ppWap.Content;
Neste ponto criamos a ação que dispara a tela para aplicaçãode multas no através do celular, embutida no arquivo WML,criado anteriormente.
Agora iremos criar a ação para gravar a operação do usuário:
.Através do duplo-clique no wmMatrixV adicione uma Action(primeiro speed button, ou tecla INS), alterando as seguintespropriedades:
Name = actWAPConfirmaPathInfo = /wapconfirma. Insira o código a seguir no evento OnAction deste objeto:
Response.ContentType:=’text/vnd.wap.wml’;
try
with sqlWapInsere do
begin
ParamByName(‘codigo’).Value:=StrtoInt
(Request.ContentFields.Values[‘multa’]);
ParamByName(‘placa’).Value:=
Request.ContentFields.Values[‘placa’];
ParamByName(‘data’).Value:=Now;
ExecSQL();
end;
Response.Content:=’<wml><card
id=”mensagem”><p>multa aplicada</p></card></wml>’;
except
On E:Exception do
begin
Response.Content:=’<wml><card
id=mensagem><p>falhou [‘+E.Message+’]</p></card></
wml>’;
end;
end;
Testando a primeira fase da aplicação
Através das opções Project/Options...Directories/Conditionals,configure o parâmetro Output Directory apontando paraC:\Borcon_Matrix\Scripts.
Salve e compile a aplicação.
Através do utilitário Deck-It, teste a aplicação, digitando aseguinte URL:
http://localhost/scripts/MatrixDriver.exe/WAP
A figura 2 ilustra nossa aplicação.
Utilize os controles do celular para informar a placa e o tipode multa (figura 3)
Selecionando o tipo da multa... (ver figura 3)
Confirme a operação e veja o resultado.
Com isso concluímos a primeira parte do artigo.
No próximo mês teremos o cadastro de veículos utilizando atecnologia Intraweb.
Forte abraço à todos.
Sobre o autorEMERSON FACUNTE ([email protected])é
Consultor de Tecnologia com diversos livros publicados,especialista em desenvolvimento de aplicações e-Busi-ness utilizando a ferramenta Delphi, baseado emWebSnap, DataSnap, BizSnap e ISAPI/Apache Modules.
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 82 82 82 82 8
DelphiDelphiDelphiDelphiDelphi
Introdução
Entre várias novidades, o Delphi 7 trouxe um gerador derelatórios chamado Rave Reports, o qual é bastante poderoso,porém, o modo de trabalhar é bastante diferente em relação aoQuickReport, pois ele possui um projeto próprio de relatório o qualgera um arquivo externo ao projeto, apesar de ser possívelembutir junto ao executável, porém, nosso foco neste pequenoartigo será em relação a carga dinâmica de imagens em nossorelatório Rave.
Criando um novo relatório
Neste exemplo, vamos utilizar como fonte de dados, umaruqivo XML chamado Country, o qual está disponível na pasta...\Borland Shared\Data.
Então, crie um novo projeto no Delphi e salve-o como“RvJpg” e sua unit para “unRvJpg” e adicione os seguintes
Rave ReportsRave ReportsRave ReportsRave ReportsRave ReportsCarregando Imagens DinâmicanteCarregando Imagens DinâmicanteCarregando Imagens DinâmicanteCarregando Imagens DinâmicanteCarregando Imagens Dinâmicante
componentes à este novo form, como mostra a Figura 1.
Agora, partiremos para ajustar as propriedades destescomponentes, onde iremos abordar apenas os mais significativos,visto algumas configurações serem triviais...
RvProject* Engine ->RvSystem* Name -> RvProject* ProjectFile ->RvJPEG.ravClientDataSet* Name -> cdsCountry* FileName -> country.xml* Active -> true
TRvDataSetConnection* Name -> rvdsCountry* DataSet -> cdsCountry
Figura 1 – Nosso formulário
Alessandro Ferreira, [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 92 92 92 92 9
Estando feitas estas configurações, partiremos para o designde nosso relatório. Para isso, dê um duplo-clique no componenteRvProject para acessar o Rave Designer.
Estando no Rave Designer, vá ao menu File | New paraadicionar um novo relatório e após isso, salve o mesmo com onome de RvJPEG.rav. Agora, novamente no menu File, cliquena opção New Data Object e selecione a opção “Direct Data View”e “Next” e se você seguiu os passos anteriores, verá nossocomponente rvdsCountry, bastando clicar em Finish paraconcluir.
Para aceleramos a confecção de nosso relatório, vá ao menuTools | Report Wizard, opção esta que irá abrir um form deconfiguração semelhante a Figura 2.
Clique em “Next” e o próximo passo será selecionar os camposque irão aparecer no relatório, conforme apresenta a Figura 3.
Vá clicando “Next” até chegar em “Report Layout Options”,conforme mostra a Figura 4.
Clicando mais um vez em “Next”, chegaremos ao últimopasso sugerido pelo Wizard, onde você poderá configurar a fonte deletra dos “texts” disponibilizados sobre as bandas, onde parafinalizar, bastará clicar em “Generate” e com isso nosso relatórioestará criado. Em nosso exemplo, mostraremos apenas o campo“Name” e ao lado do mesmo iremos adicionar um componentechamado Bitmap disponível na aba Standard do Rave Designer.
A Figura 5 apresenta o layout sugerido para nosso relatório.
Figura 2 – Primeiro passo do Wizard
Figura 4 – Report Layout Options
Figura 3 – Selecionando campos no Wizard
Figura 5 – Layout sugerido
DelphiDelphiDelphiDelphiDelphi
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE3 03 03 03 03 0
Salve tudo e aqui finalizamos nosso trabalho dentro do Rave Designer,podendo fechá-lo por enquanto.
Mostrando a Imagem DinâmicamenteEstando agora na IDE do Delphi, iremos implementar o código responsável
em mostrar a imagem no componente Bitmap existente em nosso relatório. Paraesta abordagem, iremos utilizar o evento OnGetRow do componentervdsCountry, conforme poderá acompanhar na Listagem 1.
procedure TForm1.rvdsCountryGetRow(Connection: TRvCustomConnection);
var B: TRaveBitmap; P: TRavePage; Jpg: TJpegImage;begin{Cria Objeto JPEGImage para carregar o arquivo Jpeg.} Jpg := TJpegImage.Create; try {Pesquisa componentes dentro do projeto rave.} P := RvProject.ProjMan.FindRaveComponent
(‘Report2.MainPage’, nil) as TRavePage; B := RvProject.ProjMan.FindRaveComponent
(‘rvImage’, P) as TRaveBitmap;{verifica se existe um JPG referente ao país atual.} if FileExists(cdsCountry.FieldByName
(‘Name’).AsString+’.jpg’) then begin {Carrega o arquivo do disco.} Jpg.LoadFromFile(cdsCountry.FieldByName
(‘Name’).AsString+’.jpg’); {Atribui ao Rave Bitmap component.} B.Image.Assign(Jpg); end else {senão encontrar a imagem, insere umagenérica} begin Jpg.LoadFromFile(‘pirata.jpg’); B.Image.Assign(Jpg); end; { Recall the event.} Connection.DoGetRow; finally Jpg.Free; end;end;
Listagem 1 – Código do evento OnGetRow.
Para melhor explicarmos, iremos analisar os pontos mais significativosapresentados na Listagem 1. Observe que declaramos três variáveis, sendo:
B: TRaveBitmap -> variável que irá conter a referência do componenteBitmap existente em nosso relatório;
P: TRavePage; -> variável que irá conter a referência da página onde ocomponente Bitmap foi disponibilizado no relatório;
Jpg: TJpegImage ->Responsável em carregar a imagem JPG existente emdisco;
Continuando, instânciamos o objeto TJPegImage na variável Jpg. Após isso,vem um ponto muito importante em nossa abordagem onde através do métodoFindRaveComponent do componente RvProject, iremos “pegar” a referência dapágina existente em nosso relatório e logo em seguida, tendo a referência dapágina atribuída à variável “P”, iremos dentro desta página “pegar” a referênciaao componente Bitmap disponibilizado sobre a mesma. As próximas instruçõesbasicamente irão apenas buscar a imagem (JPG) em disco e atribuir aocomponente Bitmap. Observe que ao término desta abordagem, chamamos ométodo DoGetRow do parâmetro Connection existente neste evento, o qualtem a finalidade de forçar o processamento deste evento.
Importante: Declare as seguintes units abaixo da sessão implementation:uses RVClass, RVProj, RVCsStd, Jpeg;
Dica: O evento OnGetRow será executado a cadaregistro processado em nosso relatório.
Finalizando, apresentamos na Listagem 2 o código utilizado na chamada denosso relatório.
procedure TForm1.Button1Click(Sender: TObject);
begin
with RvProject do
begin
// Carrega o projeto de relatório Rave.
ProjectFile := ‘RvJPEG.rav’;
// Executa o relatório.
Execute;
end;
end;
Listagem 2 – Chamada do relatório
ConclusãoApresentamos neste pequeno artigo, um macete que podemos empregar afim
de aproveitar melhor os recursos do Rave Reports, que é uma excelenteferramenta, porém, pecando ainda no quesito documentação, o que obriga-nos aefetuar testes e em cima de tentativas e erros ir desvendando o caminho daspedras... Espero que esta dica possa ser últil à você, lembrando que além deimagens, você poderá efetuar outras abordagens através deste evento e, qualquerdúvida ou sugestão, sinta-se a vontade em nos enviar. Até a próxima!
DownloadO projeto de exemplo referente este artigo está disponível para download no
seguinte endereço: http://www.theclub.com.br/revista/downloads/RaveJPeg.zip.
Sobre o autorAlessandro Ferreira, Consultor Técnico do TheClub - [email protected]
DelphiDelphiDelphiDelphiDelphi