Anda di halaman 1dari 31

Revista The Club Megazine - 03/2004

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.

Copyright The Club 2004

EDITORIAL

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.

Vocs esto recebendo mais uma revista The Club Megazine recheada de informaes importantes para manter-lhes sempre atualizados. Estamos trazendo neste ms a terceira e ltima parte sobre o cadastro de clientes utilizando o Intraweb. Nesta matria voc ir aprender a desenvolver o formulrio para manuteno geral, responsvel pelo controle da aplicao. Voc ver tambm a segunda parte da matria Migrando aplicaes BDE para o dbExpress, veja nesta matria os beneficios desta migrao. Estamos trazendo uma matria que serve tanto para programadores iniciantes, quanto para intermedirios. Trabalhando com units. Veja nesta matria algumas dicas interessantes para o seu trabalho do dia a dia. Para aqueles que esto trabalhando ou pretendem trabalhar com Palm, veja as novas informaes sobre o PocketStudio. E como no poderia deixar de ser a seo Perguntas e Respostas com informaes muito interessantes. Boa leitura a todos e at o prximo ms.

Copyright The Club 2004 Impresso e acabamento:


Impressos Gril - Gril Grfica e Repr. Ind. Ltda. Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259 Rua So Paulo, 447 - Cep 18.740-000 Taquarituba - SP Tiragem: 5.000 exemplares

Celso Jefferson Paganelli Presidente - The Club

Diretor - Presidente

Celso Jefferson M. Paganelli


Diretor Tcnico

Mauro SantAnna

Delphi marca registrada da Borland International, as demais marcas citadas so registradas pelos seus respectivos proprietrios.

Editorial .................................................................................... 03 Migrando Aplicaes BDE para dbExpress - Parte 2......................... 04 Trabalhando com Units ................................................................ 12 Retrospectiva ............................................................................. 16 Cadastro de Clientes com Intraweb - Parte III - Final ...................... 18 PocketStudio: poder, mais produtividade e facilidade de uso ........... 22 ClienteDataSet - Controlando pacotes de dados ............................. 26 Perguntas & Respostas ................................................................ 31

MeGAZINE

Delphi

Migrando aplicaes BDE para dbExpress - Parte 2


Recursos & Arquitetura Provider/Resolver
Por: Alessandro Ferreira, alessandro@theclub.com.br

Os componentes Data Access


Como mencionamos anteriormente, os DataSets dbExpress so uni-direcionais e iremos necessitar combin-los com outros componentes para prover navegao de registros. A seguir iremos analisar os componentes DataSetProvider e ClientDataSet.

sero includos na clusula WHERE, a menos que a propriedade pfInWhere do campo (em ProviderFlags) esteja igual a False. Contudo, quando trabalhamos com UpdateMode = upWhereAll, se outro usurio alterar o valor original do registro durante o processo de UPDATE ou DELETE, a operao ir falhar visto no ser possvel localizar o registro. Quando configuramos UpdateMode = upWhereChanged, somente os campos que sofreram alteraes sero includos na clusula WHERE, porm, particularmente no gosto desta configurao, pois pode trazer problemas tambm. E finalmente, temos a opo de configurar UpdateMode = upWhereKeyOnly, onde somente os campos referentes a chave primria sero utilizados na clusula WHERE, lembrando que neste caso deveremos configurar a propriedade ProviderFlags dos campos que fazem parte da chave primria habilitando pfInKey e pfInWhere para True e os demais campos apenas pfInUpdate = True. A propriedade Options do DataSetProvider possui diversos flags que influenciam diretamente o mecnismo Provider/ Resolver. Vamos ver algumas destas... Configurando a propriedade poCascadeDeletes para True, o provider no ir gerar instrues SQL para deletar os registros detalhes pertencentes a um registro master que foi deletado, assumindo assim que o banco de dados ir se encarregar de cuidar da integridade referencial. A propriedade poCascadeUpdates prov o mesmo, porm, para alteraes em registros. Se utilizarmos uma SQLQuery/SQLDataSet com uma

DataSetProvider
O DataSetProvider deve ser ligado a um dataset dbExpress atravs da propriedade DataSet. Este componente responsvel em suprir as requisies feitas pelo ClientDataSet, alm ainda de gerar as instrues SQL DML a fim de atualizar o banco de dados, utilizando-se do log de alteraes provido pelo ClientDataSet. Bem, vamos retornar ao nosso aplicativo de exemplo e fazer o seguinte: 1. Adicione um componente DataSetProvider (aba Data Access); 2. Ajuste a propriedade DataSet para EmployeeQry e Name para EmployeeProv; Atravs da propriedade UpdateMode do DataSetProvider podemos controlar como o provider ir fazer as atualizaes nos registros do banco de dados. Quando o provider gera instrues SQL para atualizar o banco de dados, cada instruo de UPDATE ou DELETE possui um clusula WHERE para identifcar o registro. Se UpdateMode estiver configurado como upWhereAll, o valor original de todos os campos, exceto BLOBs

MeGAZINE

Delphi
clusula ORDER BY e voc no deseje que a visualizao seja alterada atravs do ClientDataSet, poder configurar a propriedade poRetainServerOrder para True, ficando a ordenao controlada atravs do Provider. Se voc necessitar alterar a instruo SQL existentes no SQLQuery/SQLDataSet, no precisa referenciar-se diretamente a estes componentes, podendo faz-lo diretamente via propriedade CommandText do ClientDataSet. Isso permitido desde que a propriedade poAllowCommandText esteja igual a True. Atravs do evento BeforeUpdateRecord do DataSetProvider, temos a possibilidade de manipular os valores que sero postados ao banco de dados e para que estas alteraes sejam visualizadas automaticamente pelo ClientDataSet bastar alterar a propriedade poPropogateChanges para True. Dessa forma, qualquer mudana feita atravs do evento BeforeUpdateRecord sero refletidas no ClientDataSet. Todos os eventos do DataSetProvider so muito importantes e possibilitam muita flexibilidade ao programador. Contudo, gostaria de destacar dois em especial, sendo o OnGetTableName e o BeforeUpdateRecord. Atravs destes eventos podemos fazer ajustes para trabalharmos com junes de tabelas, stored procedure ou ainda views existentes no banco de dados. Basicamente, temos trs ferramentas para controlar estas situaes. Se os registros incluem campos de uma nica tabela, no h problemas. Contudo, se estivermos editando registros retornados por uma stored procedure, o provider no tem como descobrir o nome da tabela ser atualizada, e nesta situao o problema pode ser facilmente solucionando atravs do evento OnGetTableName, informando o nome da tabela ao parmetro TableName. Uma segunda possibilidade quando trabalhamos com vrias tabelas (joins) para visualizao, porm necessitamos alterar os campos apenas de uma destas tabelas, geralmente a principal. Para isso, iremos ter que configurar a propriedade ProviderFlags dos campos, identificando quais os campos devero ser includos na instruo SQL de atualizao. Neste caso, os campos que no queremos atualizar devero estar com todas as opes dentro de ProviderFlags = False, dessa forma, estes campos podero ser visualizados, porm, no faro parte da instruo SQL de atualizao, no esquecendo do evento OnGetTableName para informar qual tabela dever ser atualizada. O evento BeforeUpdateRecord, conforme mencionamos anteriormente um timo local para que voc possa analisar registro a registro, campo a campo antes dos mesmos serem postados ao banco de dados. Neste evento, voc pode at mesmo cancelar completamente a atualizao elevando uma exceo (Exception). Isso faz deste evento um excelente repositrio para regras de negcios.

ClientDataSet
O ClientDataSet conectado ao DataSetProvider atravs de sua propriedade ProviderName. Ele recebe os dados do Provider e os armazena em um cache local. Quando efetuamos qualquer manuteno, um log de alteraes criado pelo ClientDataSet e ao chamarmos o mtodo ApplyUpdates este log enviando ao DataSetProvider que por sua vez manda ao banco de dados. Voltando ao nosso projeto de exemplo... 1. Adicione dois componentes ClientDataSet ao DataModule; 2. Aponte a propriedade ProviderName do primeiro cds para EmployeeProv e Name para EmployeeCds; 3. D um duplo-clique no EmployeeCds para acessar o Fields Editor e adicione os campos ao mesmo; Observe que o ltimo campo o HistoryQry que um nested dataset field o qual ir conter a tabela SALARY_HISTORY relacionados a tabela EMPLOYEE; (Apenas para lembrar, fizemos o relacionamento ligando o componente HistoryQry ao EmployeeQry atravs do DataSource EmpLinkSrc); 4. Agora, clique com o boto direito no componente EmployeeCds e selecione a opo Fetch Params para que o(s) parmetro(s) sejam descarregados neste Cds; 5. Selecione o segundo ClientDataSet (que voc adicionou) e configure seu nome para HistoryCds e aponte a propriedade DataSetField para EmployeeCdsHistoryQry (que o nome do nested dataset gerado. Neste momento, estamos fazendo um relacionamento master/detail); 6. D um duplo-clique no componente HistoryCds e adicione os campos ao Fields Editor; 7. Adicione dois novos DataSources e configure o nome para EmployeeSrc e HistoryCds; 8. Aponte a propriedade DataSet dos novos DataSources para EmployeeCds e HistoryCds, respectivamente; Nosso DataModule ir ficar parecido com a figura 1. Nested Detail DataSets (conjuntos de dados detalhe) aninhados so bastante interessantes e poderosos porque eles evitam confuso no momento da requisio e aplicao das atualizaes junto ao registro master e os registros detalhes. Por exemplo, se um novo registro master e logo em seguida vrios registros detalhes so adicionados, logicamente, o registro master deve ser enviado ao servidor de banco de dados primeiro que seus filhos, caso contrrio o controle de integridade referencial do banco de dados ir levantar uma exceo. J no

MeGAZINE

Delphi
poAllowCommandText no DataSetProvider). Vale lembrar, que voc pode parametrizar seu CommandText passando os parmetros atravs da propriedade Params. Voc pode estar se perguntando, por que utilizar o CommandText do ClientDataSet e no acessar diretamente o SQLQuery ou SQLDataSet? Simples! Em uma possvel migrao para DataSnap (n-tier) o DataSetProvider e o SQLQuery/SQLDataSet ficam fisicamente separados em uma outra camada (aplicao) e na aplicao cliente voc no ter acesso diretamente a estes, tendo que fazer tudo via ClientDataSet mesmo, ento, dessa forma voc j deixa as coisas encaminhadas e vai se habituando com esta forma de trabalhar. A propriedade PacketRecords sem dvidas muito interessante e tem papel fundamental na performance da aplicao. Atravs desta propriedade informamos ao Provider quantos registros queremos que ele traga do servidor de banco de dados e disponibilize no cache local do ClientDataSet. O valor default -1, com isso, ao efetuarmos um Open no Cds, todos os registros retornados pela instruo SQL sero retornados, porm, se esta instruo retornar um grande nmero de registro, certamente teremos problemas. Contudo, se configurarmos PacketRecords para um valor como exemplo 50, os registros sero recebidos em pacotes de 50 registros conforme a demanda e com isso melhorando drsticamente a performance. Uma das grandes diferenas entre a arquitetura BDE e a arquitetura provider/resolver utilizada na dbExpress, que voc necessita chamar o mtodo ApplyUpdates do ClientDataSet para aplicar as mudanas registradas no log de alteraes ao banco de dados. Antes de chamar o ApplyUpdates voc poder verificar se existe alguma pendncia ser aplicada verificando o valor da propriedade ChangeCount. Ainda, no mtodo ApplyUpdates, vale ressaltar que ele recebe um nico parmetro que especifica o nmero de erros permitidos durante a aplicao do log de alteraes ao banco de dados, antes do processo de interrompido e a transao ser revertida. Geralmente, passamos o valor zero como parmetro, no admitindo assim nenhum erro! Passando 1, o DataSetProvider ir tentar aplicar o que for possvel e ignorar os registros onde ocorrerem erros. Durante a atualizao, caso algum erro seja detectado, o evento OnReconcileError do ClientDataSet ser acionado. Para tratar os erros durante o processo de atualizao, siga os seguintes passos: 1. V ao menu File | New | Other | Dialogs e adicione um Reconcile Error Dialog e salve a unit gerada; 2. Declare a unit referente o Reconcile Error Dialog na clusula uses d DataModule;

Figura 1 DataModule caso de uma deleo de registros, o processamento exatamente o oposto, ou seja, se voc apaga um registro master, primeiro devero ser deletados os seus dependentes e somente aps isso, ele prprio. Assim sendo, pelo fato do conjunto de dados detalhe estarem aninhados ao master, o DataSetProvider assegura que as atualizaes so processadas com total segurana evitando erros no servidor de banco de dados. Vamos ver algumas das propriedades mais importantes do ClientDataSet. O Cds tem vrias propriedades teis, como exemplo a Aggregates que possibilita definir campos agregados mantidos automaticamente pelo Cds, onde podemos executar operaes como totalizao, valor mnimo, valor mximo, contagem e mdia a partir de qualquer campo no conjunto de dados. Os agregados podem ser agrupados por qualquer ndice existente. Vale ressalta que para os agregates funcionem, a propriedade AggregatesActive deve estar igual a true. Um detalhe bastante interessante em relao a ndices no Cds, que voc no necessita ter um ndice fsico no banco de dados para poder alterar a ordem de visualizao dos registros. Tudo que voc precisar fazer, informar (digitar) na propriedade IndexFieldNames o nome do(s) campo(s) pelo qual deseja ordenar, lembrando que se for mais de um, separe-os por ponto-e-vrgula. Outra propriedade bastante til a CommandText, atravs da qual podemos alterar as instrues SQL existentes no componente que prov os dados ao DataSetProvider (SQLQuery/ SQLDataSet). Isso bastante simples, bastando fechar o ClientDataSet, alterar o CommandText e torn-lo a abrir e assim ter uma nova consulta (lembre-se de alterar a propriedade

MeGAZINE

Delphi
3. Configure o Reconcile Error Dialog para no ser criado automaticamente (menu Project | Options); 4. Acione o evento OnReconcileError no EmployeeCds e adicione a seguinte instruo: Action := HandleReconcileError (DataSet, UpdateKind, E); Se algum erro ocorrer quando o usurio aplicar as atualizaes, o Reconcile Error Dialog ir mostrar a mensagem de erro, o registro que est com problemas, e um conjunto de opo para que o usurio possa escolher uma ao para a soluo do problema. Para concluirmos nosso projeto de exemplo, siga os passos seguntes: 1. Adicione dois componentes Panel, dois DBGrids, e dois DBNavigators no formulrio principal de nosso projeto, deixandoos arranjados como mostra a figura 2. 2. Adicione na clusula uses a unit referente o DataModule; 3. Aponte a propriedade DataSource do primeiro DBGrid e DBNavigator para EmployeeSrc; 4. Aponte a propriedade DataSource do segundo DBGrid e DBNavigator para HistorySrc; 5. Adicione um componente Label e um componente ComboBox o qual dever ser nomeado para DeptCombo e o Caption do Label para Selecione o Departamento; 6. No evento OnChange do DeptCombo, programe o seguinte: procedure TMainForm.DeptComboChange( Sender:TObject); begin with MainDm.EmployeeCds do begin if Active then CheckBrowseMode; Close; Params.ParamByName(DEPT_NO).AsString := Copy(DeptCombo.Text, 1, 3); Open; end;//with end; 7. Adicione um boto (TButton) sobre o panel do topo, configure seu nome para SaveBtn e seu caption para Salvar Alteraes; 8. No evento OnClick do SaveBtn, programe o seguinte: procedure TMainForm.SaveBtnClick(Sender:TObject); begin with MainDm do begin if EmployeeCds.ChangeCount > 0 then begin if HistoryCds.Active then HistoryCds.CheckBrowseMode; if EmployeeCds.Active then EmployeeCds.CheckBrowseMode; EmployeeCds.ApplyUpdates(0); EmployeeCds.Refresh; end;//if end;//with end; 9. Vamos criar um mtodo para o preenchimento do ComboBox. Confira o cdigo na listagem 1. procedure TMainForm.LoadDeptCombo; begin with MainDm do begin DeptQry.Open; while not DeptQry.Eof do begin DeptCombo.Items.Add(DeptQryDept_No.AsString+ +DeptQryDepartment.AsString); DeptQry.Next; end; //while DeptQry.Close; end; //with end; listagem 1 mtodo para preencher o ComboBox. 10. No evento OnCreate do formulrio, adicione as seguintes instrues: procedure TMainForm.FormCreate(Sender: TObject); begin MainDm.EmployeeCds.Open; LoadDeptCombo; end;

BDE x dbExpress
Iremos agora fazer um comparativo entre as caractersticas do BDE e do dbExpress, comparando vrios tens para lhe dar uma viso geral de ambas as arquiteturas.

MeGAZINE

Delphi

Figura 2 layout sugerido

Tabela 2 Correspondncia de componentes Tabela 1 Comparao entre BDE x dbExpress O conceito de sesses no existe na dbExpress, por isso, no existem componentes (TSession) anlogos ao BDE na dbExpress. No caso do TUpdateSQL, o mesmo s funciona (BDE) quando acionamos a propriedade CachedUpdates da Query. J na dbExpress, o componente ClientDataSet faz o papel do CachedUpdates. E finalmente, o controle feito pelo TNestedDataSet (BDE) feito plo DataSetProvider e ClientDataSet na dbExpress.

Migrando aplicaes C/S BDE para C/S dbExpress


Aqui, iremos relacionar alguns passos para auxili-lo na migrao de suas aplicaes para dbExpress. Substitua o componente Database por um SQLConnection; Substitua o componente Query por SQLQuery ou SQLDataSet e StoredProc por SQLStoredProc ou SQLDataSet; Adicione componentes DataSetProvider e ClientDataSet para cada SQLQuery, SQLDataSet ou SQLStoredProc que voc necessitar torn-los navegveis (bi-direcionais);

MeGAZINE

Delphi
Substituindo Database por SQLConnection
Cada componente Database dever ser substitudo por um SQLConnection. 1. Parmetros de conexo O componente SQLConnection oferece basicamente dois mecnismos para ler os parmetros de conexo. Um seria utilizar uma conexo nomeada no prprio componente e com isso as configuraes ficariam estticas na prpria aplicao, sem possibilidade de mudana. Outra possibilidade disponibilizar as configuraes em um arquivo INI e carreg-las em run-time, sendo esta a mais indicada pela flexibilidade que oferece. 2. Controlando transaes Como mencionamos anteriormente, no h necessidade de abrir transaes explcitas no dbExpress, visto isso ser controlado automaticamente pelo mecnismo Provider/Resolver ao executarmos o mtodo ApplyUpdates. Dessa forma, tudo que voc ter que fazer fazer chamadas a este mtodo para que o log de alteraes seja aplicado ao banco de dados. Contudo, em situaes em que voc utilizar instrues SQL DML para manipulao de dados (INSERT, UPDATE e DELETE) e precisar ter um melhor controle sobre esta atualizao, voc dever fazer o controle de transao explcito, geralmente protegido em um bloco try|except|end, tendo assim a possibidade de confirmar ou reverter a seqencia de instrues executadas. Uma outra situao que pode ser necessrio utilizar transaes explcitas seria quando voc necessitar atualizar N ClientDataSets, garantindo a atualizao bem sucedida de todos ou nenhum. Contudo, a chamada explcita de transaes traz alguns inconvenientes: Voc tem que chamar o mtodo Commit sempre aps efetuar um ApplyUpdates; Analisar onde ir fazer as chamadas StartTransaction para que no mantenha transaes de vida longa penduradas no servidor, o que com certeza no uma boa idia; Ter que configurar um objeto TTransactionDesc para passar como parmetro ao StartTransaction; Como voc pode ver, bem menos trabalhoso remover suas chamadas StartTransaction (caso utilizasse no BDE), do que adapt-las ao mecnismo da dbExpress. Dessa forma, fica mais simples (e com melhor resultado) apenas acrescentar as chamadas ao mtodo ApplyUpdates e deixar o controle de transao por conta do mecnismo Provider/Resolver e utilizar transaes explcitas somente em casos realmente necessrios. Um detalhe que no poderamos deixar passar sobre o controle de transaes na dbExpress, que esta arquitetura possibilita trabalhar com mltiplas transaes, contrariando o BDE, tendo em comum apenas os mtodos STARTTRANSACTION, COMMIT e ROLLBACK. Porm, para que possamos ter mltiplas transaes foi necessrio atribuirmos um parmetro do tipo TtransactionDesc aos mtodos acima mencionados, tendo a seguinte estrutura: TTransactionDesc = packed record TransactionID : LongWord; GlobalID : LongWord; IsolationLevel : TTransIsolationLevel; CustomIsolation : LongWord; end; Para cada transao simultnea, voc tem que declarar uma varivel do tipo TtransactionDesc e atribuir um ID nico para identifcar a transao atravs do parmetro TransactionId. O parmetro GlobalId s utilizado com bancos de dados Oracle. IsolationLevel deve ser configurado para um destes valores: xilDIRTYREAD, xilREADCOMMITTED ou xilREPEATABLEREAD. E finalmente, o parmetro CustomIsolation a princpio, no utilizado.

Substituindo todos os componentes DataSet


Substituir todos os seus componentes datasets, sem dvidas ser o mais trabalhoso no processo de converso. Voc ter que substituir cada componente Query por SQLQuery ou SQLDataSet, cada StoredProc por SQLStoredProc ou SQLDataSet. O processo trabalhoso devido ao fato que os componentes do BDE tm propriedades e eventos que o dbExpress no tm, e assim, qualquer referncia em seu cdigo para as propriedades ou eventos tero que ser removidas. Se voc estiver utilizando componentes UpdateSQL, dever remov-los, lembrando que no existe componente anlogo a este na dbExpress. Para cada SQLQuery, SQLDataSet ou SQLStoredProc que necessitar de acesso bidirecional ou possibilidade de edio de registros, voc necessitar adicionar um DataSetProvider e um ClientDataSet. Outro detalhe importante, que os eventos que voc possua na Query BDE, devero ser vinculados agora no ClientDataSet, visto que neste componente que voc ir trabalhar na manuteno no banco de dados. Para minimizar um pouco o trabalho, voc poder nomear seus ClientDataSets com o mesmo nome das Querys que possua em seu DM ou Form e o mesmo para o SQLStoreProc. Apesar de voc referenciar-se ao ClientDataSet praticamente para tudo, voc dever adicionar os campos ao Fields Editor no SQLQuery ou SQLDataSet e efetuar a configurao da propriedade ProviderFlags neste componente, conforme o exemplo anteriormente sugerido. Recomendamos trabalhar com UpdateMode = upWhereKeyOnly e com isso, voc dever

MeGAZINE

Delphi
configurar o ProviderFlags dos campos referente sua Primary Key marcando ptInkey. Pode haver casos em que voc no ir necessitar ter DataSetProvider e ClientDataSet. Por exemplo, suponha que voc possua uma consulta cujo resultado ser apenas a totalizao de um campo da tabela o qual voc necessite apresentar em um Label... para isso, bastar abrir seu SQLQuery ou SQLDataSet e atribuir o valor diretamente ao Label. Finalmente, lembre-se que dever chamar o mtodo ApplyUpdates no ClientDataSet para que sejam postadas ao banco o log de alteraes, caso contrrio, ficaro apenas em cache e tero efeito algum. suportado pela dbExpress e importar seus dados para o mesmo. Basicamente, temos trs modos para fazer isto. Junto ao Delphi encontrar uma ferramenta chamada Data Pump a qual faz praticamente todo o trabalho de migrao. Caso v migrar para Interbase/Firebird, poder encontrar ferramentas gratutas mais poderosas que o Data Pump no site www.ibphoenix.com; Utilizar ferramentas nativas do prprio banco de dados. Por exemplo, o Microsoft SQLServer possui uma ferramenta bastante poderosa chamada Import and Export Data a qual permite realizar esta tarefa; Escreva seu prprio programa de converso de dados. Um detalhe importante que o servidor de banco de dados escolhido pode no aceitar todos os tipos de dados existentes em suas tabelas Paradox ou dBase. Por exemplo, no Paradox temos campos lgicos (Boolean), mas a maioria dos servidores SQL no possuem este campo. Neste caso, a soluo bastante simples, bastando definir um campo CHAR gravando S ou N, ou ainda, um campo INTEGER gravando 0 ou 1. Nestes casos, faz-se necessrio de que a ferramenta utilizada na importao dos dados permite fazer este tipo de mapeamento entre os campos para no gerar erros no processo de converso. A maioria dos servidores SQL aceitam campos do tipo CHAR e VARCHAR para armazenamento de strings, ao passo que tabelas Paradox e dBase possuem um nico tipo. Tenha certeza de que o tipo escolhido o mais apropriado para cada campo no momento da converso. Voc pode querer mudar os tipos de dados por vrios razes. Por exemplo, tabelas Paradox armazenam todos os dados numricos reais em formato de ponto flutuante. J, a maioria dos servidores SQL permitem armazenar numricos no formato de ponto fixo, como exemplo o tipo NUMERIC ou DECIMAL. Ao contrrio do formato ponto flutuante, representaes em ponto fixo so menos sujeitos a problemas de arredondamentos, evitando assim problemas em clculos.

Mapeamento dos tipos de dados


Na dbExpress temos dois novos tipos de dados que no tnhamos na BDE. Todo tipo referente a valores numricos (NUMERIC) ou de dupla preciso de ponto flutuante (DOUBLE PRECISION) sero reconhecidos como tfields TFMTBCDField. O TFMTBCDField. armazena valores como TBCD que na realidade um verdadeiro BCD com uma preciso mxima de at 32 dgitos. Para atribuir ou obter valores deste tipo de campo, utilize a propriedade SeuCampo.AsBDD ou ainda SeuCampo.AsVariant, caso contrrio ter problemas. Outro tipo interessante encontrado na dbExpress o utilizado para armazenamento de valores data-hora (TIMESTAMP). Estes valores so mapeados como tfields TSQLTimeStampField. O TSQLTimeStampField armazena as informaes de data-hora em uma varivel TSQLTimeStamp, o qual guarda os valores separados em ano, ms, dia, hora, segundo e frao, este ltimo, sendo a representao em milisegundos. A principal vantagem deste tipo de armazenamento o fato de no haver perda de preciso. Para atribuir valores a este tipo de campo, existe uma funo de converso chamada DateTimeToSQLTimeStamp, atribuindo o valor para a propriedade SeuCampo.AsSQLTimeStamp.

Substituindo o componente TBatchMove


Na dbExpress no temos nenhum componente anlogo ao BatchMove e neste caso, se voc estiver utilizando-o em sua aplicao, dever remov-lo e implementar sua funcionalidade via cdigo ou ainda, o mais recomendado fazer via instrues SQL DML, quando possvel.

Garantia de segurana
Entre muitas vantagens ao se adotar um servidor SQL destaca-se os mecnimos de segurana dos dados. Um servidor SQL possui controle dos usurios que podero acessar os objetos dos banco, sendo possvel definir tipos de acesso, como exemplo, somente leitura, permitir inserir dados, alterar dados, etc. Tabelas desktop possibilitam criptografar dados para que usurios sem autorizao no acessem os dados, contudo, isso pouco comum em servidores SQL. Ao invs de criptografia, a segurana depende do sistema operacional, de forma que o SO que no pode permitir acesso fsico ao arquivo de dados.

Se voc pretende migrar aplicaes desktop que utilizam tabelas de dados como Paradox ou dBase para dbExpress, voc ir ter que contornar velhos problemas... Vamos l!

Migrando aplicaes desktop BDE para dbExpress

Converso dos Dados


Visto que a dbExpress no d suporte a tabelas Paradox ou dBase, voc ter que adotar um servidor de banco de dados

10

MeGAZINE

Delphi
Normalmente, os nicos usurios que tm acesso fsico aos arquivos do banco de dados so o DBA e o programador, este ltimo, nem sempre. E finalmente, a terceira opo ir exigir mudanas de cdigo significativas, visto que aplicaes projetadas para ambiente cliente/servidor tipicamente foram o usurio a entrar com critrios de seleo antes de ser apresentado quaisquer dados ao mesmo. Os critrios de seleo so usados para compor a clusula WHERE em uma consulta SQL e com isso a consulta ir retornar um nmero pequeno de registros, o que com certeza ser extremamente rpido. Uma vez que o usurio conclui as operaes nos registros selecionados, ele ir fazer uma nova parametrizao a fim de receber um novo conjunto de registros com base nesta nova parametrizao e assim sucessivamente. A princpio, tudo isso pode parecer um pouco complexo ou mesmo, pouco funcional, mas posso lhe assegurar que os resultados obtidos so compensadores.

Mudando conceitos
Geralmente em aplicaes desktop permitimos aos usurios abrirem e navegarem tabelas inteiras atravs do componente Table. Porm, este tipo de abordagem no nenhum pouco recomendada quando trabalhamos com servidores SQL, pois, ao solicitar a abertura de uma tabela inteira, todos os registros da mesma iro trafegar na rede do servidor a estao que fez a requisio para poderem ser armazenados na estao de trabalho, o que com certeza no ter uma boa performance. Vale ressaltar que os registros armazenados em cache pelo ClientDataSet geralmente no constituem-se em problemas em uma aplicao Client/Server corretamente projetada, porque estas aplicaes vo buscar somente alguns registros no servidor (pacotes), conforme a demanda, porm, mesmo assim deve-se tomar cuidado para no abrir todo o contedo de uma tabela de uma s vez no ClientDataSet, visto isso apresentar problemas de performance. Ao iniciar a converso de uma aplicao desktop BDE para dbExpress, voc tem basicamente trs alternativas: 1. Substituir seus componentes Table por SQLTable, DataSetProvider e ClientDataSet; 2. Substituir seus componentes Table por SQLQuery ou SQLDataSet, DataSetProvider e ClientDataSet, utilizando um Select aberto em todas as colunas e todos os registros da tabela; 3. Substituir seus componentes Table por SQLQuery ou SQLDataSet, DataSetProvider e ClientDataSet e alterar radicalmente a aplicao utilizando conceitos Cliente/Servidor, sendo esta opo um pouco mais trabalhosa, mais sem dvidas a mais indicada; A primeira alternativa sem dvidas a mais simples de ser implementada, visto o componente SQLTable, a grosso modo ser parecido com o componente Table (BDE). Isso ir funcionar bem em aplicaes que manipulam um volume pequeno de dados. A principal desvantagem que no temos como parametrizar o SQLTable para trazer um conjunto menor de registros caso necessrio, sendo necessrio nestes casos substituir o SQLTable por SQLQuery ou SQLDataSet, por isso, vejo esta alternativa como a menos indicada em um processo migratrio. A segunda opo j uma boa escolha. Embora esteja utilizando um Select aberto, o que traz todo o contedo da tabela e se a mesma possuir um grande volume de dados, a performance no ser nada agradvel, porm, tudo que voc necessitar fazer parametrizar esta SQLQuery/SQLDataSet e o problema ser resolvido.

Concluso
Migrando suas aplicaes BDE para dbExpress voc ter muitos benefcios, entre eles: Transaes de tempo bastante reduzido; Maior controle sobre o trfego de informaes na rede e recursos; Reduo no tamanho e consumo de recursos do sistema; Aumento na performance; Facilidade no desenvolvimento; Distribuio menor e mais simples; Desenvolvimento multi-plataforma; Como puderam observar ao longo deste tutorial, que a migrao de aplicaes desenvolvidas com BDE para dbExpress, apesar de um pouco trabalhosa, no algo to traumtico e os benefcios valem o trabalho demandado. Outra vantagem que trabalhando com o conjunto de componentes SQLQuery/ SQLDataSet, DataSetProvider e ClientDataSet voc dar um grande passo rumo a uma futura migrao para a arquitetura DataSnap, arquitetura em fase de grande crescimento. Procurei citar aqui alguns dos pontos mais importantes no processo migratrio, contudo, devido a particularidades de cada aplicativo podem surgir situaes no previstas neste artigo, mas estamos a disposio para outros esclarecimentos que se faam necessrios. Forte abrao todos, Download do projeto de exemplo referente a este artigo. http://www.theclub.com.br/revista/download/ MigrandoBDE2dbExpress.zip

Sobre o autor
Alessandro Ferreira, Consultor Tcnico do The Club alessandro@theclub.com.br

MeGAZINE

11

Delphi

Trabalhando com Units


Por Claudinei Rodrigues

Quando voc comea a desenvolver uma aplicao, por menor que ela seja um item que voc deve ficar atento em relao organizao. A sua aplicao pode comear a crescer e ficar muito difcil para dar manuteno. A minha idia neste arquivo descrever como voc pode dividir o seu projeto em mdulos utilizando apenas units, para organizar melhor a sua aplicao.

de rotinas teis, voc provavelmente as armazenar em uma unit. Voc pode criar quantas units achar necessrio em seu projeto. A idia e ter uma unit para verificar dados em banco de dados, outra para verificar datas e etc.

Estrutura de uma unit


Voc j deve ter analisado a estrutura de uma unit do Delphi, mas mesmo assim veja a explicao a seguir. unit Unit1; { Nome da unit } interface { Nesta seo as rotinas so informadas que esto disponveis para uso em outras units. } uses { A lista dos nomes das units cujas as nossas rotinas querem usar } implementation { Esta seo tem todo o cdigo fonte que define todos os tipos listados e definidos na seo interface. } uses { A lista opcional de nomes de units cuja nossas rotinas

O que uma unit?


No geral um programa em Delphi construdo em um mdulo onde est o cdigo fonte que chamamos de unit. Cada unit armazenada em um arquivo com extenso .pas; e compilado separadamente, as units compiladas so somadas para criar uma aplicao. Os forms so blocos de construo visveis de uma aplicao Delphi. Cada form em um projeto Delphi est associado a uma unit. A unit contm o cdigo ligado a qualquer evento do form ou de seus componentes. Muito do trabalho feito por uma aplicao executado por eventos que fornecem uma resposta a ao do usurio. Ao lado do cdigo fonte onde esto os eventos correspondentes ao form e aos componentes includos nestes forms, voc pode escrever suas prprias procedures e funes. Voc pode criar por exemplo uma funo que verifica se uma data ou no vlida. No entanto, as units no precisam ser obrigatoriamente associadas a um form. Se voc quiser reutilizar as rotinas que voc escreveu, o melhor criar uma unit separada para as suas rotinas. Criando as units autnomas, ou seja, que no tem nenhum form associado. Assim voc pode facilmente utilizar as suas rotinas em outros projetos. A unit contm cdigos que so chamados a partir de outras units do projeto. Quando voc comea a construir uma biblioteca

12

MeGAZINE

Delphi
queiram usar. } initialization { Esta uma seo opcional que contm todo o cdigo necessrio para ser executado quando a unit referenciada pela primeira vez. } finalization { Esta seo tambm opcional e necessria apenas se tivermos a seo initialization. Aqui ns escrevemos o cdigo necessrio para ser executado quando o form for removido da memria. Se sua unit precisar executar qualquer limpeza quando a aplicao terminar, como por exemplo liberar qualquer recurso alocado durante a inicializao. } end. { final da unit} Agora que voc conhece pelo menos na teoria o que vem a ser uma unit no Delphi, est na hora de ver como criar um programa que inclui um determinado numero de units. Para rodar uma aplicao em Delphi, so necessrias muitas informaes em background, como por exemplo como interagir com o sistema e como criar forms e componentes como botes, edits e etc. Esta informao contida em diversas units que so parte padro do Delphi. Esta coleo de units referenciada como Run Time Library. Vamos analisar uma unit padro gerada pelo Delphi. unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} end. Primeiro vamos ver como o Delphi d manuteno a esta lista. Quando voc cria um novo form, o Delphi inclui todas as units necessrias na clusula uses da seo interface. Ainda que voc no tenha adicionado qualquer componente ao form ou ainda tenha digitado qualquer cdigo. Voc j tem uma aplicao completa que voc pode compilar e rodar. Ao rodar voc ver um form em branco. cdigo que cria uma nova instancia do form.

A unit A usa a unit B


Pare por um minuto, veja na seo uses da seo interface ou implementation a lista dos nomes das units, rotinas, variveis e tipos que nossa unit quer usar. O que exatamente isto? Quem mantm esta lista? Como voc sabe qual unit a nossa unit vai utilizar? Como saber em qual unit est uma determinada funo que queremos utilizar?

Como o Delphi mantm a origem da units


Apenas entender a estrutura da unit no o bastante para que um programador novato em Delphi comece a programar. Os programadores frequentemente no sabem qual unit usar e como usar. Antes de criarmos nossos prprios cdigos, vamos ver como o Delphi gerencia as units necessrias.

Examinando uma unit


Toda a vez que o Delphi inicia ou cria um novo projeto, a ide do Delphi mostra um novo form para que voc comece a trabalhar. No editor de cdigos voc ir notar que na unit gerada declarado um novo tipo de classe para o formulrio e inclui o

Colocando componentes no form


O Delphi vem com muitos componentes para serem includos no seu form. natural que todos aqueles componentes no esto definidos somente nestas units, apesar de tudo, cada componente de terceiros ou componentes que voc mesmo venha a criar tenha dentro de sua prpria unit.

MeGAZINE

13

Delphi
Voc no precisa saber o nome exato da unit que pertence um determinado componente. Vamos supor que voc adicione um componente Button, que est na palheta Standard, ao form e escreva uma instruo qualquer no evento OnClick. O cdigo da unit ficar da seguinte forma: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin ShowMessage(Teste do The Club); end; end. Vamos analisar o cdigo anterior. O componente Button est definido na unit StdCtrls. O prprio Delphi se encarregou de declarar esta unit na seo uses logo abaixo de interface. O que isto quer dizer? Quer dizer que em muitos casos voc no precisa saber exatamente o nome da unit a qual um determinado componente pertence. Para cada componente que voc colocar no form o Delphi ir adicionar na seo uses o nome da unit a qual ele pertence. Mas ateno. Se voc remover um componente, ou seja, deletar um componente do form o Delphi no ir remover a unit a qual ele declarou quando voc incluiu o componente.

Usando as units do Delphi (Rotinas VCL/RTL)


Run Time Library ou rotinas VCL so funes e procedures que so construdas dentro do Delphi. Por exemplo, a unit StrUtils fornece rotinas para manipulao de strings, a unit DateUtils para manipulao de datas. Agora vamos supor que voc tenha um componente Edit no seu form. Quando o usurio clicar um boto o caption do form ir receber o contedo descrito no componente Edit em ordem inversa. Veja o cdigo: procedure TForm1.Button1Click(Sender: TObject); begin Caption := ReverseString(Edit1.Text); end; Se voc apenas digitar este cdigo, voc receber um erro. O erro o seguinte: Undeclared identifier: ReverseString Este erro significa que o compilador no encontrou a funo ReverseString() isto pode ser porque esta funo pertena a outra unit que no est declarada na seo uses desta unit. Para utilizar as rotinas do Delphi voc dever saber exatamente a qual unit ela pertence. Para resolver este problema voc ter que manualmente declarar a unit StrUtils na seo uses, veja o exemplo: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StrUtils; type TForm1 = class(TForm) Button1: TButton; Mas agora vem a pergunta, como eu vou saber quais as funes que o Delphi tem disponvel? Um caminho para te ajudar chamar o Help do Delphi e digitar Routines, quick reference, by category. Voc ter acesso as vrias rotinas do Delphi.

14

MeGAZINE

Delphi
Se voc esquecer de declarar uma determinada unit o compilador do Delphi ir lhe mostrar um erro ao compilar e posiciona o cursor sobre o cdigo que no conseguiu processar. Normalmente, voc encontrar rotinas que no esto declaradas na lista uses. O sistema de help do Delphi dever lhe dizer qual unit voc deve adicionar. Para isto clique sobre o nome da rotina e pressione a tecla F1. Note que voc viu como o Delphi mantm a lista de units declaradas, e o que precisa ser feito para que o Delphi utilize as rotinas, sendo assim voc j est pronto para criar as suas prprias units. unit Unit2; interface function NossaRotina(a : string) : string; implementation function NossaRotina(a : string) : string; begin if a <> then Result := O parametro informado foi + a else Result := O parametro est em branco; end; end. Como voc pode ver, ns criamos uma rotina bem simples. Mas voc pode montar rotinas muito mais complexas. No h um limite para o nmero de procedures ou funes. Uma unit pode ser usada para definir sua prpria classe, ou seu componente, etc. Diversas rotinas escritas na sua unit podem compartilhar do mesmo conjunto de variveis, constantes, etc. Se voc definir uma varivel dentro da seo interface ela ser visvel dentro de todas as units que utilizem esta sua unit. Mas se voc definir um identificador dentro da seo implementation ele no ser visto em outras units. Quando voc planejar a estrutura da sua aplicao, essencial que voc tenha entendido estas informaes.

Criando e utilizando o seu prprio cdigo em uma unit


Agora que voc sabe a estrutura de uma unit, e como o Delphi auxilia a manter uma unit, est na hora de criarmos a nossa unit com as nossas prprias funes e/ou procedures. Dependendo do seu conhecimento a criao e utilizao do cdigo na unit pode ser fcil de entender ou pode se tornar confuso a primeira vista.

Nova Unit
O caminho mais simples para se criar uma nova unit para o seu projeto ir at o menu do Delphi e clicar em File | New | Unit. Feito isto voc ver o editor de cdigos da seguinte forma: unit Unit2; interface implementation end.

Usando as units padres (RTL)


Quando voc cria a sua prpria unit, voc responsvel pela lista de units que a sua unit ir utilizar. Voc precisar adicionar diferentes units padres do Delphi, de acordo com as rotinas que voc utilizar em sua unit.

Nomeando a Unit
O cabealho da unit mostra o nome da mesma logo aps a palavra reservada unit. Vale lembrar que dentro do seu projeto voc no pode ter duas units com o mesmo nome. Para mudar o nome desta unit, v at o menu do Delphi e clique em File | Save As... Agora d um novo nome a esta unit.

Concluso
Este ms eu publiquei uma matria bem bsica que ir ajudar a diversos programadores que esto iniciando a sua programao em Delphi. At a prxima edio.

Criando rotinas em uma unit


Agora ns vamos rapidamente criar uma nova rotina em nossa unit. Estando na unit2 digite o cabealho da sua funo na seo interface. Agora repita o cabealho da rotina logo abaixo da seo implementation e digite o corpo da rotina. A sua unit ficar da seguinte forma:

Sobre o autor
Claudinei Rodrigues, Consultor Tcnico do The Club nei@theclub.com.br

MeGAZINE

15

Retrospectiva

Retrospectiva
Estamos em 1996. Diante de inmeros boatos, ditos e desmentidos, os programadores perdidos, sem saber muito bem o que a CA (Computer Associates) iria fazer devido ao grande descontentamento do pblico em geral com os seus novos produtos, o Clipper 5.3 e Visual Objects. O THE CLUB neste ms, anunciava oficialmente que estava abandonando o barco e no daria continuidade, optando por no adotar o Clipper 5.3 e o Visual Objects. Entre inmeros motivos, pode-se lembrar a interface confusa, uma ambiente de desenvolvimento pesado, a imcompatibilidade entre o Clipper 5.3 e as verses anteriores, tampouco entre ele e o Visual Objects, que deveria ser uma coisa lgica. Enfim, a Computer Associates conseguiu enterrar uma linguagem de programao amplamente utilizada, diga-se de passagem at os dias de hoje, onde at mesmo grandes empresas ainda preferem ficar com seus sistemas antigos em Clipper aliando estabilidade e velocidade da aplicao. O Clipper (verso 5.2 e anteriores) com certeza foi o maior sucesso de uma linguagem de programao no Brasil. Foi lamentvel o tratamento que recebeu da Computer Associates, e mais lamentvel ainda a deciso da empresa de deix-lo cair no esquecimento e no fazer outras atualizaes. No mnimo, eles poderiam ter jogado no lixo os projetos do Clipper 5.3 e Visual Objects e comear tudo de novo. Tenho certeza que muitos programadores esperariam com satisfao um produto que viesse a suprir todas as nossas necessidades. Destaca-se tambm nesta edio a matria sobre o saudoso Apollo que resolveu grandes problemas de banco de dados, mas que foi sucedido exemplarmente pelo Advantage Database Server, distribudo aqui no Brasil pela Renet Tecnologia, representante nacional da Extend Systems. Tambm podemos citar a matria do Mauro SantAnna, Imprimindo em baixssimo nvel, e tambm sobre as mensagens do Delphi, uma linguagem que todos estvamos comeando a assimilar, e j comeavam a surgir vrias empresas ministrando cursos sobre ela. Por este ms nossa retrospectiva, de maneira triste pelo fracasso e erros da Computer Associates pelo Clipper 5.3 e Visual Objects fica por aqui. At o ms que vem.

16

MeGAZINE

Delphi

Cadastro de Clientes com Intraweb


Parte III (Final)
Sobre o autor
Emerson Facunte Consultor de Tecnologia com diversos livros publicados, especialista em desenvolvimento de aplicaes ebusiness utilizando a ferramenta Delphi, baseado em webSnap, dataSnap, BizSnap e ISAPI/Apache Modules. Emersonf@livrariasaraiva.com.br

Salve, salve Delphi People! Chegamos na ltima parte de nossa trilogia. Neste artigo iremos desenvolver o formulrio para manuteno geral, responsvel pelo controle da nossa aplicao.

Altere a propriedade Name do formulrio para FmManutencao e BackGroundColor para $00DDFFFF. . Grave a unit com o nome un_manutencao. Insira os componentes que seguem no FmManutencao..

Criando o Formulrio de Manuteno


Atravs das opes File/New/Other..., selecione a seo Intraweb e escolha o modelo Application Form (figura 1).

Com o foco no objeto IWRegion1, insira os componentes que seguem.

Figura 1: Criando um novo formulrio

18

MeGAZINE

Delphi
Curiosidade:
Repare que estamos repetindo o campo COD_CLIENTE diversas vezes. Fazemos isto para substituir os mtodos de chamada de operaes, devido um BUG no Intraweb. At a verso 5.51 (que vm junto com o D7), o BUG de vnculo com controles (Control) ainda no estava corrigido. Existe uma maneira de associar um objeto, como por exemplo, um boto a um evento do Grid. Iramos fazer isso para disparar as rotinas de alterao e excluso, mas infelizmente, devido ao BUG, estamos substituindo por outro mtodo. Vamos configurar as colunas inseridas.

Em nosso formulrio iremos utilizar objetos de acesso a dados. Insira um objeto do tipo TDataSource e outro do tipo TSQLQuery (dbExpress), configurando as propriedades que seguem

Repare que estamos colocando o comando SELECT *, na propriedade SQL do objeto SQLPesquisa. Fazemos isso apenas para nos auxiliar na montagem do Grid. Com o foco no formulrio, insira um objeto do tipo TIWDBGrid, e altere as propriedades que seguem.

Atravs do duplo-clique na propriedade Columns, insira os campos conforme a figura 2. Agora vamos codificar o nosso formulrio. Na clusula uses insira as seguintes units. uses ServerController, DataModuleUnit, un_alteracao; Figura 2: Campos do grid. Em seguida devemos criar uma procedure pblica para

MeGAZINE

19

Delphi
auxiliar no posicionamento do registro, de maneira que possamos atribuir o contedo do banco de dados, aos campos do formulrio fmAltera. Defina a procedure LOCALIZA, como segue. public procedure Localiza(Cliente: integer); E na seo implementation, insira o cdigo a seguir. procedure Tfmmanutencao.Localiza(Cliente:integer); begin SQLPesquisa.Locate(cod_cliente, Cliente, []); end; Neste cdigo estamos apenas posicionando o ponteiro do registro de acordo com a seleo do usurio. Agora vamos codificar o objeto btPesquisa. Insira o cdigo que segue no evento OnClick. SQLPesquisa.SQL.Clear; SQLPesquisa.SQL.Add(SELECT * FROM TBCLIENTE WHERE RAZAO_SOCIAL LIKE ++%+edPesquisa.Text+%+); SQLPesquisa.Open; Neste cdigo estamos preparando uma consulta SQL, baseada na informao do usurio, extrada do objeto edPesquisa. As informaes so apresentadas no Grid, devido ao vnculo com o objeto. Coloque o cdigo a seguir, no evento OnClick do objeto btVolta. Hide; Agora vamos codificar a operao de alterao do Grid. Atravs da propriedade Columns do IWDBGrid1, selecione a coluna 3 (Altera), e insira o cdigo que segue no evento OnClick. var fmAltera:TfmAltera; begin fmAltera:=TFmAltera.Create(WebApplication); {Atribui o cdigo a Query} with fmAltera do begin FmAltera.SQLDataSet1.Params[0].Value:=StrtoInt(AValue); {Atribui os valores} fmAltera.lbCodigo.Caption:=Avalue; fmAltera.Show; end; Vamos analisar o cdigo. No bloco a seguir, estamos definindo um objeto do tipo TfmAltera, para que possamos manipular o objeto. var fmAltera:TfmAltera; No bloco que segue, instanciamos o objeto FmAltera. begin fmAltera:=TFmAltera.Create(WebApplication); Em seguida atribumos o cdigo do cliente, extrado da varivel AValue (constante da procedure), ao objeto SQLDataSet1. with fmAltera do begin FmAltera.SQLDataSet1.Params[0].Value:=StrtoInt(AValue); fmAltera.SQLDataSet1.Open; O bloco a seguir, atribui as informaes do SQLDataSet1 aos campos do objeto fmAltera, apresentando o formulrio de alterao de clientes. edRazao.Text:=SQLDataSet1RAZAO_SOCIAL.AsString; edEndereco.Text:=SQLDataSet1ENDERECO.AsString; edCidade.Text:=SQLDataSet1CIDADE.AsString; edCEP.Text:=SQLDataSet1CEP.AsString; edUF.ItemIndex:=edUF.Items.IndexOf( QLDataSet1ESTADO.AsString); edEmail.Text:=SQLDataSet1EMAIL.AsString; {Atribui os valores} fmAltera.SQLDataSet1.Open; edRazao.Text:=SQLDataSet1RAZAO_SOCIAL.AsString; edEndereco.Text:=SQLDataSet1ENDERECO.AsString; edCidade.Text:=SQLDataSet1CIDADE.AsString; edCEP.Text:=SQLDataSet1CEP.AsString; edUF.ItemIndex:=edUF.Items.IndexOf( QLDataSet1ESTADO.AsString); edEmail.Text:=SQLDataSet1EMAIL.AsString;

20

MeGAZINE

Delphi
fmAltera.lbCodigo.Caption:=Avalue; fmAltera.Show; Agora vamos codificar a operao de excluso do Grid. Atravs da propriedade Columns do IWDBGrid1, selecione a coluna 4 (Exclui), e insira o cdigo que segue no evento OnClick. try with DataModule1.SQLExclui do begin ParamByName(pcodigo).Value:=StrtoInt(AValue); ExecSQL; end; WebApplication.ShowMessage(Cliente Excluido com sucesso,smSameWindow); except WebApplication.ShowMessage(Houve um problema na exclusao do cliente, smSameWindow); end; Vamos analisar o cdigo. No cdigo que segue estamos criando um bloco protegido; atribuindo um parmetro para o objeto SQLExclui, e finalmente apresentando uma mensagem ao usurio, em caso de sucesso da operao. try with DataModule1.SQLExclui do begin ParamByName(pcodigo).Value:=StrtoInt(AValue); ExecSQL; end; WebApplication.ShowMessage(Cliente Excluido com sucesso,smSameWindow); No bloco a seguir estamos tratando a exceo, apresentando para o usurio uma mensagem de alerta. except WebApplication.ShowMessage (Houve um problema na exclusao do cliente, smSameWindow); end; Grave a unit un_manutencao e selecione o formulrio principal. A figura 3 ilustra o nosso formulrio de manuteno.

Figura 3: Formulrio de manuteno Vamos codificar o formulrio principal, para concluir a aplicao. Na clusula uses do formulrio principal (formMain), insira as units que seguem. uses ServerController, un_Inclusao, un_manutencao; Agora vamos codificar a opo Incluso de Clientes do Menu Principal. No evento OnClick da opo, insira o cdigo a seguir. var fmInclusao:TFmInclusao; begin fmInclusao:=TFMInclusao.Create(WebApplication); fmInclusao.Show; end; Neste cdigo estamos instanciando o objeto FmInclusao e apresentando ao usurio. E agora, vamos codificar a opo Manuteno/Consulta.Coloque o cdigo que segue no evento OnClick da opo. var fmManutencao:TFmManutencao; begin fmManutencao:=TFMManutencao.Create(WebApplication); fmManutencao.Show; end; Com isso conclumos o nosso projeto de Cadastro de Clientes. As figuras 4 a 9, ilustram nossa aplicao em tempo de execuo.

MeGAZINE

21

Delphi

Figura 4: Menu principal

Figura 7: Manuteno

Figura 5: Formulrio de incluso

Figura 8: Alterao de clientes

Figura 6: Informaes sobre a aplicao Repare que na tela de manuteno existe um rollover passeando entre os registros. Para que voc possa fazer qualquer tipo de operao, clique no cdigo do cliente, correspondente operao (altera ou exclui). Voc poder digitar apenas uma parte da razo social do cliente, por exemplo: digitando Facunte, so apresentados todos os registros que contm a palavra Facunte, independente da posio. Figura 9: Finalizando a aplicao Com isso conclumos a nossa trilogia. No prximo ms iniciaremos nossa jornada com o todo poderoso Delphi 8. Forte abrao e sucesso a todos. Emerson Facunte

22

MeGAZINE

Delphi

PocketStudio: Poder, mais Produtividade e Facilidade de Uso


Por: Marcio Alexandroni
Uma das ferramentas de desenvolvimento Palm mais conceituadas e utilizadas pelos desenvolvedores nacionais ganha uma nova verso: PocketStudio 2. PocketStudio teve seu desenvolvimento iniciado em 1999 pela antiga PocketTechnologies, uma empresa dos Estados Unidos que era chefiada por Doug Olson, com quem costumo trocar e-mails at hoje, um visionrio que queria criar uma ferramenta que pudesse ser acessvel aos desenvolvedores Pascal e chamar a ateno da comunidade Delphi. Para desenvolver o compilador para a plataforma PalmOS, a Pocket-Technologies contratou na poca uma empresa da Repblica Eslovaca (fica na Europa, entre a Polnia, ustria e Hungria), a WinSoft (www.winsoft.sk) conhecida por desenvolver ferramentas de apoio a desenvolvedores na plataforma Windows. O responsvel tcnico da WinSoft chama-se Erik Salaj, uma pessoa extremamente tcnica e que conhece as necessidades do mundo do desenvolvimento. Quando entrei no programa de Beta Teste da primeira verso do PocketStudio, no incio do ano 2000, percebi que a ferramenta no s vinha de encontro com minha experincia em desenvolvimento em Pascal e Delphi, mas que tambm tinha caractersticas muito importantes para quem pretende desenvolver aplicaes para computadores portteis, com poucos recursos e poder de processamento (hoje, claro...). Entre as caractersticas mais importantes da ferramenta, o que mais me chamou a ateno foi: O compilador era extremamente pequeno e rpido; Gerao de cdigo nativo PalmOS, sem necessidade de runtime; Acesso a toda a API do PalmOS, portanto, qualquer recurso que pudesse ser utilizado no Palm, tambm era suportado pelo PocketStudio; A aplicao gerada era bem pequena, comparada na poca com as aplicaes que eu escrevia em CodeWarrior. Quando a primeira verso do IDE ficou pronta, percebi que a ferramenta facilitaria ainda mais o meu desenvolvimento pois o ambiente era totalmente integrado, com o desenho dos formulrios em um Editor prprio, da maneira tradicional que costumamos fazer em qualquer IDE como o Delphi; a configurao das propriedades e o gerenciamento dos cdigos dos eventos era feito por um Component Inspector, praticamente idntico ao Object Inspector do Delphi e o modo de compilar e executar a aplicao tambm era familiar, o CTRL+F9 e F9. Resolvi mudar. Ao invs de escrever toda a parte visual das aplicaes Palm em CodeWarrior, comecei a desenvolver tudo em PocketStudio e para confirmar que eu havia escolhido corretamente, at hoje, no h uma s aplicao que no pode ser escrita em PocketStudio, e com qualidade no resultado. Quando o PocketStudio foi vendido para a WinSoft, fato usual no mercado pelo mundo todo, muitos achavam que terminaria a histria de sucesso do PocketStudio, mas eu pensava diferente, pois a ferramenta havia voltado para as mos de quem realmente a criou: a WinSoft! Mais uma vez, participei de todo o processo de Beta Teste da ferramenta, agora na verso 2.0, desde Outubro/2003, e a principal caracterstica que precisava ser implementada para tornar o PocketStudio ainda mais produtivo foi introduzida: formulrios, cdigos e eventos em units .PAS separadas. Explico: na verso 1.X, havia um nico arquivo .RC que continha a declarao de todos os objetos visuais da aplicao, todos os formulrios com seus objetos eram declarados ali. Havia tambm um arquivo .EVN que concentrava todos os eventos dos formulrios, ou seja, cdigos que associavamos a botes, listas, tables, etc. Acontece que medida que a aplicao crescia e o

WINSOFT

MeGAZINE

23

Delphi
cdigo ficava maior, o gerenciamento de cdigo no arquivo .EVN no era prtico, alm de ser impossvel a reutilizao de cdigo entre projetos diferentes. O PocketStudio 2.0 trouxe a mudana que a ferramenta realmente necessitava, um novo IDE! Para quem j trabalha com a ferramenta desde a verso 1.X, vai notar que o IDE ficou muito mais rpido e que a sintaxe utilizada para declarar os objetos visuais exatamente a mesma da verso 1.X, mas agora feita em uma unit .PAS para cada formulrio. Veja a imagem do ambiente logo abaixo: A comunicao com o Emulador tambm ficou muito melhor. Para quem ainda tem uma mquina um pouco antiga ou que est carregada com milhares de programas e quem sabe MP3, agora podem contar com a configurao de tempos de acesso ao Emulador do PalmOS, para adaptar as condies da sua mquina ao seu ambiente de trabalho. O IDE tambm ficou mais simples. O Editor de Cdigo da verso 1.2 tinha vrios recursos, muitos deles nunca utilizados pelos desenvolvedores. A verso 2.0 trouxe mais simplicidade e rapidez na edio dos cdigos. Definir Alerts e Bitmaps agora na prpria unit, ou seja, basta clicar no objeto na barra de ferramentas e colocar sobre o prprio Editor e configurar o texto que ser exibido no Alert diretamente no Editor. Quer que explique novamente o motivo do ttulo do artigo ser Poder, mais produtividade e facilidade de uso? Veja abaixo: Poder - Tem acesso toda API do Sistema Operacional PalmOS. - Gera executveis nativos PalmOS sem necessidade de runtime. - Permite instrues assembler no meio do cdigo (inline assembler). - Suporte a PalmOS 2.0 a 5.3. - Suporte a HandEra, Kyocera, HandSpring, Symbol, Sony, etc. - Acessa Bancos de Dados mveis como o Oracle Lite e IBM DB2. - Suporte s bibliotecas de comunicao remota da ASTA, com uma interface muito familiar, a AstaObjects for PocketStudio. - Suporte a impressoras de qualquer tipo atravs do acesso aos gerenciadores de impresso mais poderosos do mercado como o IRPrint, PrintBoy e PalmPrint. - No limita o desenvolvedor quando o Cliente pede caractersticas mais complexas e avanadas na aplicao. Mais Produtividade - PSLibrary - Interface de acesso objetos visuais do formulrio e tambm bancos de dados que facilita imensamente o trabalho do desenvolvedores PalmOS. - IDE - Ambiente integrado que gera os eventos dos formulrios em units .PAS separadas, organizando o cdigo e permitindo a reutilizao do formulrio em outros projetos. Facilidade de uso - Ambiente similar ao do Delphi.

A aplicao que vocs esto vendo no IDE a aplicao exemplo do meu produto SyncAnywhere, j portada para o PocketStudio 2. No levei 5 minutos para portar a aplicao, as tarefas foram as seguintes: Executar as duas verses do PocketStudio, a 1.2 e a 2.0. Abrir o arquivo RC da verso 1.2, criar o formulrio na 2.0, copiar e colar as definies dos objetos visuais. Pronto, ao abrir o desenho do formulrio, todos os objetos encontravam-se exatamente no lugar certo. Copiar as variveis globais do arquivo EVN na verso 1.2 para a unit .PAS do formulrio na verso 2.0. Copiar o tratamento dos eventos do EVN na verso 1.2 para a unit .PAS do formulrio na verso 2.0. As units de bancos de dados e units auxiliares que j eram usadas na verso 1.2 foram copiadas integralmente, no h necessidade de nenhuma modificao. Outra caracterstica interessante que a uses clause das units, que precisava conter cada unit da PSLibrary que utilizvamos no cdigo, agora basta conter: uses PSL; Mais nada!

24

MeGAZINE

Delphi
- Debug passo-a-passo. - Editor de Resources WYSIWYG. Por todos estes motivos, o ClubePalm continua ministrando cursos de PocketStudio desde o incio de 2002, agora j adaptado verso PocketStudio 2! J treinamentos mais de uma centena de desenvolvedores nesta excelente ferramenta e a qualidade final das aplicaes escritas nesta ferramenta pode ser atestada por todos. O material e o curso de PocketStudio foram aprovados por tantos desenvolvedores que a concorrncia resolveu nos copiar, ministrando treinamento com o contedo exato do nosso material. O instrutor desses cursos? Quem sabe? Quem busca qualidade, seriedade e principalmente experincia, conte com quem trabalha com a ferramenta desde o incio e principalmente com quem ajudou no processo de criao: o ClubePalm. Aguardem nossa primeira turma de PocketStudio 2 para o incio de 2004 em So Paulo. Quem quiser reservar sua vaga, basta escrever para cursos@clubepalm.com.br. Quer uma verso Trial? Acesse www.winsoft.sk/pstudio.htm e baixe a sua cpia de avaliao! Se interessou pela ferramenta? Em breve mais novidades ainda, aqui no site do ClubePalm e tambm no site do The Club.

Aviso importante: O ClubePalm est comercializando apostilas/CD em portugus para desenvolvimento em PocketStudio. Voc que associado do The Club tem vantagem na aquisio deste kit. Ao adquirir o kit voc ganhar 5% de desconto, basta informar o cdigo THECLUB2004.
WinSoft e PocketStudio so marcas registradas da WinSoft. Palm and PalmOS so marcas registradas da Palm Inc. Delphi marca registrada da Inprise Corporation. ASTA marca registrada da Asta Technology Group.

Sobre o autor
Marcio Alexandroni marcio@clubepalm.com.br ClubePalm A referncia do desenvolvedor PalmOS.

MeGAZINE

25

NEWS

Controlando pacotes de dados


Por: Andr Colavite

ClientDataSet

No artigo deste ms iremos montar um pequeno projeto onde utilizados o controle de pacotes de dados do componente ClientDataSet, ao qual nos permitir visualizar os pacotes sendo descarregados e cancelar o processo caso seja necessrio. Mas, antes de iniciarmos os trabalhos vamos entender um pouco como funcionam os pacotes de dados do ClientDataSet. Na maioria dos casos sempre visualizamos poucos registros em nossos selects, com isso o processo para descarregar esses dados bastante rpido. Mas em alguns casos precisamos visualizar muitos registros, com isso o processo para descarregar esses registros fica pesado e lento, sendo o usurio obrigado a aguardar todo o processamento dos dados sem na verdade saber se o mesmo ainda est processando ou se a mquina travou. neste momento que o controle de pacotes do ClientDataSet entre em funcionamento, pois podemos dividir a visualizao dessa grande quantidade de dados em pequenos pacotes que sero descarregados conforme a necessidade do usurio. Podemos determinar o tamanho desses pacotes, isso quantos registros ir conter cada pacote, atravs da propriedade PacketRecords do componente ClientDataSet. Essa propriedade por default vem configurada com o valor -1 isso indica que no haver criao de pacotes de dados e, todos os registros solicitados para a visualizao sero descarregados de uma nica vez. Podemos configurar essa propriedade com o valor que acharmos mais adequado, pois esse valor indica exatamente a quantidade de registros que iremos ter em cada pacote. O processo que ir descarregar esses pacotes pode ser automtico ou manual, e o que define se automtico ou manual a propriedade FetchOnDemand do componente ClientDataSet, sendo que o valor True deixa automtico e False manual. Quando est no Automtico a solicitao de novos

pacotes realizada toda vez que o ponteiro dos dados ultrapassar o ltimo registro visvel, sendo assim um novo pacote solicitado e apresentado em seguida. No processo Manual toda vez que o ponteiro ultrapassar o ltimo registro visvel a indicao ser de que chegou ao final da tabela ( EOF ), e para descarregar um novo pacote devemos utilizar o mtodo GetNextPacket do componente ClientDataSet. Bem, neste momento j temos uma idia de como os pacotes funcionam, sendo assim vamos criar o nosso projeto ao qual poderemos ver na prtica o seu funcionamento.

Criando um simples projeto


Vamos criar o nosso projeto contendo um Form, chamado Form1, e um Datamodule, chamado DM. Neste DM iremos colocar os componentes para visualizao dos dados ao qual iremos utilizar os componentes do DBExpress, portanto coloque neste DM os seguintes componentes: SQLConnection, SQLDataSet, DataSetProvider e ClientDataSet. No componente SQLConnection faa a conexo ao banco de dados; No componente SQLDataSet faa a ligao ao componente SQLConnection atravs de sua propriedade SQLConnection e na propriedade CommandText coloque a instruo para visualizar os dados, por exemplo: SELECT * FROM CADASTRO No componente DataSetProvider faa a ligao com o SQLDataSet atravs da sua propriedade DataSet; No componente ClientDataSet faa a ligao com o

26

MeGAZINE

Delphi
DataSetProvider atravs da sua propriedade ProviderName. Inicialmente no iremos configurar as propriedades FetchOnDemand e PacketRecords do ClientDataSet, pois primeiro iremos verificar como fica o processo para descarregar todos os registros sem a utilizao do pacotes. Vamos agora montar o Form1, onde estaro os componentes de visualizao dos dados, so eles: DataSource, DBNavigator, DBGrid, Button e StatusBar. Para o DataSource visualizar o ClientDataSet no DM, declare na seo implementation da unit do Form1 a unit do DM, veja exemplo: implementation Uses UnDM; No componente DataSource ligue a sua propriedade DataSet ao componente ClientDataSet do DM; No componente DBNavigator ligue a sua propriedade DataSource ao componente DataSource; No componente DBGrid ligue a sua propriedade DataSource ao componente DataSource; O componente StatusBar ser utilizado para apresentar a quantidade de registros visveis no momento, portanto iremos colocar a instruo que ir apresentar essa informao no evento DataChange do componente DataSource, veja exemplo: procedure TForm1.DataSource1DataChange (Sender: TObject; Field: TField); begin StatusBar1.SimpleText := Registro + IntToStr(DM.ClientDataSet1.Recno)+ /+ IntToStr(DM.ClientDataSet1.RecordCount); end; O componente Button ser utilizado para abrir a visualizao dos dados do componente ClientDataSet, sendo assim na sua propriedade Caption escreva o seguinte Texto: Abrir ClientDataSet Figura1: Form para visualizao dos dados. Neste momento estamos com a visualizao dos dados criada de uma forma padro, caso a nossa tabela contenha muitos dados o processo de abertura do ClientDataSet ficar um pouco lento, vamos fazer os testes? Para quem fez o teste podemos observar atravs da informao apresentada no StatusBar que todos os registros foram descarregados de uma nica vez. No evento onClick do componente Button coloque a instruo para abrir a visualizao do dados, veja exemplo: procedure TForm1.BitBtn1Click(Sender: TObject); begin DM.ClientDataSet1.Open; end; Aps montar o nosso Form1 ele ficar parecido com a figura 1.

Configurando os pacotes de dados


A seguir iremos configurar os pacotes de dados, portanto iremos indicar na propriedade PacketRecords do componente ClientDataSet quantos registros sero descarregados em cada pacote. Como exemplo, colocarei o valor 50 nesta propriedade. A propriedade FetchOnDemand do ClientDataSet ficar com

MeGAZINE

27

Delphi
o valor True, indicando o processo automtico. Neste momento vamos fazer o mesmo teste realizado anteriormente, mas agora poderemos observar que somente 50 registros sero visualizados. Vamos descer com o cursor dentro do DBGrid visualizando os dados e quando o ponteiro ultrapassar o ltimo registro visvel, automaticamente mais um pacote de 50 registros ser descarregado. O problema desse modo automtico que se mandarmos o ponteiro para o ltimo registro da tabela, automaticamente todos os pacotes pendentes sero descarregados, tornando o processo lento novamente quando h muitos registros. Vamos fazer o teste, estando com o ClientDataSet aberto clique no boto do DBNavigator que manda o ponteiro para o ltimo registro, veja que todos os pacotes foram descarregados. { Retorna somente o prximo pacote } CDS.GetNextPacket else begin { Retorna todos os pacotes pendentes } With TFrm_Progresso.Create(Application) do begin try { Apresenta Form contendo boto para cancelar processo } Show; { Retorna o prximo pacote de dados } While (DM.ClientDataSet1.GetNextPacket > 0) and (not SB_Cancela.Down) do begin { apresenta a qtde de forms retornados } Label1.Caption := IntToStr(CDS.RecordCount); Update; Application.ProcessMessages; end; finally { fecha o form ao final } Close; end; end; end; end; Faa a declarao da procedure Retorna_Pct acima da seo var da unit do DM, veja exemplo a seguir: procedure Retorna_Pct(CDS: TClientDataSet; Todos: Boolean);

Implementando um simples controle nos pacotes de dados


A idia deste projeto, alm de usar o pacotes de dados do ClientDataSet controlar esses pacotes descarregados, mostrando para o usurio uma janela quando todos os pacotes forem solicitados permitindo ao mesmo cancelar o processo. Sendo assim o usurio no ficar com a impresso que o programa travou quando muitos registros foram requisitados. A partir deste momento vamos implementar em nosso projeto esses pequenos controles de uma forma bem simples, portanto mos a obra. O primeiro item da nossa idia deixar o processo de solicitao de pacotes de uma forma Manual, sendo assim altere a propriedade FetchOnDemand do ClientDataSet para o valor False. Agora toda vez que o ponteiro chegar ao ltimo registro teremos que solicitar o prximo pacote atravs do mtodo GetNextPacket. Vamos criar uma procedure dentro do DM que ser encarregada de executar o GetNextPacket para retornar o prximo pacote ou todos os pacotes pendentes. Esta procedure ter dois parmetros, o primeiro o ClientDataSet em uso e o segundo boolean e atravs dele iremos indicar se para trazer apenas o prximo pacote ou todos os pacotes pendentes. A seguir temos a instruo da procedure Retorna_Pct criada: procedure Retorna_Pct(CDS: TClientDataSet; Todos: Boolean); begin if not Todos then

Entendendo a Procedure Retorna_Pct


Nesta procedure Retorna_Pct podemos observar que usamos o mtodo GetNextPacket para retornar apenas o prximo pacote ou criamos um While ao qual ser executado enquanto esse mtodo GetNextPacket retornar um valor maior que zero, pois isso indica que o mtodo retornou registros. O outro controle enquanto o SpeedButton estiver com a propriedade Down igual a False, pois isso indica que o usurio no clicou sobre o boto Cancela. Veja em destaque a linha do While, utilizada: While (DM.ClientDataSet1.GetNextPacket > 0) and (not SB_Cancela.Down) do Outro detalhe dentro do While a chamada de um Form chamado Frm_Progresso. Esse form ficar visvel enquanto os

28

MeGAZINE

Delphi
pacotes estiverem sendo descarregados, apresentando a quantidade de registros visveis pelo ClientDataSet e ser fechado automaticamente ao final do processo ou caso o usurio pressionar o boto SB_Cancelar. Vamos criar agora esse novo form colocando a sua propriedade Name como Frm_Progresso. Neste novo form coloque dois componentes Labels e um componente SpeedButton. O componente SpeedButton ser utilizado para cancelar o processamento, sendo assim escreva no seu Caption o texto: Cancelar. O seu evento onclick no ter instrues, pois iremos utilizar a sua possibilidade de ficar clicado para saber se o mesmo foi clicado ou no pelo usurio. Para utilizar esse controle do SpeedButton devemos alterar a sua propriedade GroupIndex para o valor 1 e assim quando o usurio clicar sobre o boto ele ficar clicado e a sua propriedade Down ficar com o valor True. Altera a propriedade Name deste SpeedButton escrevendo o nome SB_Cancela. O componente Label1 ser utilizado para apresentar a quantidade de registros retornados, portanto no ter configuraes. No componente Label2 escreva o seguinte texto na propriedade Caption: Registros lidos Agora para finalizar esse form, inclua no evento onClose a seguinte instruo: procedure TFrm_Progresso.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := cafree; end;

Figura2: Frm_Progresso Volte a unit do DM e declara na seo implementation a unit do Frm_Progresso, veja a seguir: implementation uses Unit2;

Chamando a procedure Retorna_Pct


A procedure Retorna_Pct dever ser chamada quando o usurio pedir para o ponteiro se posicionar no ltimo registro da tabela, ou quando o ponteiro ultrapassar o ltimo registro visvel. Para verificarmos se o ponteiro ultrapassou o ltimo registro visvel, podemos utilizar o evento AfterScroll do componente ClientDataSet, onde iremos colocar a seguinte instruo: procedure TDM.ClientDataSet1AfterScroll(DataSet: TDataSet); begin { Verificamos se o ponteiro ultrapassou o ltimo registro visvel } if DataSet.Eof then Retorna_Pct(TClientDataSet(Dataset), False); end; Observe que chamamos o Retorna_Pct passando o valor False, para assim retornar apenas o prximo pacote de dados. A outra chamada que faremos a essa procedure ser quando o usurio pressionar os botes nbLast ou nbRefresh do componente DBNavigator, que correspondem as aes de Mandar o ponteiro para ltimo registro da tabela e Atualizao respectivamente. Para controlar esses botes iremos utilizar o evento BeforeAction do componente DBNavigator, onde iremos colocar a seguinte instruo: procedure TForm1.DBNavigator1BeforeAction (Sender: TObject;

{ Destroi o form da memria }

Pronto o Frm_Progresso est construdo, no se esquea que este form ser criado dinamicamente, portanto ele no pode ficar como Auto-Create e sim como Available Forms. Na figura2 podemos verificar como ficou o Frm_Progresso aps a sua construo:

MeGAZINE

29

Delphi
Button: TNavigateBtn); begin Case Button of nbLast, nbRefresh: Retorna_Pct(DM.ClientDataSet1, True); end; end; Observe que chamamos o Retorna_Pct passando o valor True, pois aqui desejamos que seja retornado todos os pacotes pendentes. Pronto, neste momento estamos com o nosso projeto pronto e controlando os pacotes de dados, sendo assim execute o projeto e clique no boto do DBNavigator que envia o ponteiro para o ltimo registro, assim poder observar a apresentao do Frm_Progresso mostrando os registros descarregados, veja exemplo na figura 3. No se esquea de clicar no boto Cancelar para verificar o cancelamento do processo. pacotes de dados do componente ClientDataSet. Tentei montar de uma forma bem simples, ao qual facilite na hora de implementar em nossos projetos. A idia desse projeto saiu a partir da indicao de alguns scios, portanto continuem mandando suas idia para que assim cada vez mais possamos colocar matrias que solucionem suas dvidas. Um grande abrao a todos e at a prxima. Andr. O projeto de exemplo referente a essa matria est disponvel em nosso site: http://www.theclub.com.br/revista/download/CDS_Pacotes.zip

Sobre o autor
Andr Colavite Consultor Tcnico do The Club colavite@theclub.com.br

Concluso
Nesta matria montamos um controle bem simples ao qual permite visualizar os registros sendo descarregados atravs dos

Figura 3: Apresentando o Frm_Progresso

30

MeGAZINE

Pergunta: Para desenvolver um sistema utilizando Delphi 7, pensando em um dia migrar para o Delphi 8, qual seria o gerador de relatrios e a forma de conexo que eu deveria usar? Resposta: No Delphi 8 temos o Rave Report, o qual compatvel com a verso existente no Delphi 7. Contudo, acredito que os fabricantes de outros geradores, assim como o Report Builder e QuickReport tero verso para Delphi 8, isso ser apenas uma questo de tempo, pois, caso contrrio, estes fabricantes correm um srio risco de sair do mercado. A respeito da tecnologia de acesso, a Borland manteve o BDE, dbExpress e Interbase Express, contudo, utilizando uma aplicao tipo VCL.Net.
Dvida enviada por Assistec Agrcola S/C Ltda, Piracicaba/ SP.

var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.BotaoMostraTextoClick (Sender: TObject); begin Caption := THackGrid(Seu_DBGrid).GetEditText(2,1); end; Dvida enviada por Marcelo da Silva, Ribeiro Preto/SP. Pergunta: Existe alguma forma de se obter a quantidade de registros atualizados por um comando update executado em um TQuery? Eu gostaria de obter essa informao para poder exibir e registrar em histrico. Resposta: Aps efetuar o Update poder obter o nmero de registros assim: Caption := Format (Registros Atualizados: %d, [Query.RowsAffected]); Dvida enviada por Unimed de Sorocaba, Sorocaba/SP.

Pergunta: Eu gostaria de pegar o valor de uma clula do DBGrid durante a digitao. Vi alguma coisa sobre um mtodo chamado GetEditText, mas no consegui utiliz-la. Como fazer? Resposta: Para utilizar este mtodo ser necessrio herdar
uma classe a partir da classe TCustomGrid, veja um simples exemplo abaixo: type THackGrid = class(TCustomGrid);

MeGAZINE

31

Anda mungkin juga menyukai