tag:blogger.com,1999:blog-337748622024-03-07T02:16:48.700-04:00Professor Carlos AraújoSantarém (PA) <br>
Desenvolvimento de Software <br>
Linguagens de ProgramaçãoProfessor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.comBlogger77125tag:blogger.com,1999:blog-33774862.post-67770329204430090852011-08-12T13:37:00.000-04:002011-08-12T13:37:50.771-04:00Lazarus - Recursos do Editor de CódigoNeste post vamos apresentar alguns dos inúmeros recursos que o Editor de Código oferece aos desenvolvedores. O Editor pode ser configurado via menu em <b>Tools | Options | Editor</b>. Estas opções também podem ser acessadas através do menu de contexto.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3Ev7GEI8C5_49rRu0m5DCUeAKkE0nk6y5bwFyTrfa8fDw83QJqBvSD4DvaYXHtA2TLYBc7BOeOdGLAodD-ijD88Tn0214Tnf360mZ6tnKlGgOjSvZHKDJRabjyw7_ETEZrGEZ/s1600/configeditor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3Ev7GEI8C5_49rRu0m5DCUeAKkE0nk6y5bwFyTrfa8fDw83QJqBvSD4DvaYXHtA2TLYBc7BOeOdGLAodD-ijD88Tn0214Tnf360mZ6tnKlGgOjSvZHKDJRabjyw7_ETEZrGEZ/s320/configeditor.png" width="320" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"></div>O detalhamento das opções e configuração do Editor exige um post específico, portanto não iremos nos ater a isso no momento. Queremos falar de recursos que a ferramenta oferece para facilitar o trabalho do programador.<br />
<br />
<b><i>Syncron</i></b><br />
<br />
Esta é uma opção onde podemos rapidamente modificar o nome de um identificador em um trecho de código selecionado.<br />
<div class="separator" style="clear: both; text-align: center;"></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3axCPEh7vBgNKW-jLuzgCzRFo-FbY97ShCjDsL7yHFHuJg_OH3ThOq5S50bBtCjlJvl6_Tug6fBaork1ln7tmfhFXyuwLkyDmKgnb18RCVUc4E7bEi8ARBqOiZTR9dJhPA2NP/s1600/syncron1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="81" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3axCPEh7vBgNKW-jLuzgCzRFo-FbY97ShCjDsL7yHFHuJg_OH3ThOq5S50bBtCjlJvl6_Tug6fBaork1ln7tmfhFXyuwLkyDmKgnb18RCVUc4E7bEi8ARBqOiZTR9dJhPA2NP/s320/syncron1.png" width="320" /></a></div>Quando você seleciona um trecho do código (ou o código inteiro), no lado esquerdo do Editor aparece um ícone com uma caneta. Clique nesse ícone ou tecle <i>CTRL + J</i>. A área selecionada muda de cor e o cursor é movido para uma instância do identificador, destacando cada uma de suas ocorrências naquela área. Modifique o identificador e cada ocorrência dele será alterada automaticamente.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqmJ6pxkDGmluuxgp1_NN7u8ZwtP-R16xfJfb1lT65bUJlCiZkC6J1Zy0S6SR54lfXZNg7zG5i6twIn1Tb7tErjNH5zRV1ewGask03FSGDc652YsTpCwqXZGIoLblfe_9wpiTU/s1600/syncron2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="64" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqmJ6pxkDGmluuxgp1_NN7u8ZwtP-R16xfJfb1lT65bUJlCiZkC6J1Zy0S6SR54lfXZNg7zG5i6twIn1Tb7tErjNH5zRV1ewGask03FSGDc652YsTpCwqXZGIoLblfe_9wpiTU/s320/syncron2.png" width="320" /></a></div>Volte a clicar no ícone ou tecle <i>ESC</i> para sair do modo <i>syncron</i>.<br />
<br />
O Code Completion é um dos recursos que pode poupar muito tempo de digitação. Dependendo da posição do cursor no Editor, várias funções podem ser chamadas.<br />
<br />
<b>Complementação de classe</b><br />
<br />
Se você escreveu uma classe incluindo propriedades e métodos, este recurso irá adicionar o corpo do método, variáveis e métodos de acesso às propriedades, etc. Suponha que você tenha criado a seguinte classe:<br />
<br />
<pre class="brush: pascal" xml:space="preserve">TPessoa = class(TObject)
constructor Create;
destructor Destroy; override;
property nome: string;
end;
</pre><br />
Posicione o cursor no interior da classe e pressione <i>CTRL + SHIFT + C</i>. O código seguinte será gerado, e o cursor será movido para que o corpo do primeiro método seja digitado.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">type
{ TPessoa }
TPessoa = class(TObject)
private
Fnome: string;
procedure Setnome(AValue: string);
published
constructor Create;
destructor Destroy; override;
property nome: string read Fnome write Setnome;
end;
implementation
{ TPessoa }
procedure TPessoa.Setnome(AValue: string);
begin
if Fnome=AValue then exit;
Fnome:=AValue;
end;
constructor TPessoa.Create;
begin
end;
destructor TPessoa.Destroy;
begin
inherited Destroy;
end;</pre><br />
<b>Complementação de declaração de variável</b><br />
<br />
Se o cursor é posicionado em um identificador e for pressionado <i>CTRL + SHIFT + C</i>, é adicionado ao código uma declaração de variável local. Por exemplo, imagine o seguinte código fonte:<br />
<br />
<pre class="brush: pascal" xml:space="preserve">procedure TForm1.FormClick(Sender: TObject);
begin
i := 5;
end;</pre><br />
Posicione o cursor na variável <i>i</i> (antes ou depois) e pressione <i>CTRL + SHIFT + C</i>. O código será modificado e ficará assim:<br />
<br />
<pre class="brush: pascal" xml:space="preserve">procedure TForm1.FormClick(Sender: TObject);
var
i: Integer;
begin
i := 5;
end;</pre><br />
O tipo da variável é deduzida a partir da expressão.<br />
<br />
<b>Message Composer</b><br />
<br />
O <b>Message Composer</b> é uma ferramenta que auxilia na criação de caixas de diálogos, tais <b>ShowMessage</b>, <b>MessageDlg</b> e <b>InputBox</b>. Para isso é necessário instalar o pacote <i>messagecomposerpkg</i>. Vá em <b>Package | Install/Uninstall packages</b>. Na lista <b>Do not install</b> localize e selecione <i>messagecomposerpkg</i>. Clique em <b>Install selection</b> e depois em <b>Save and rebuild IDE</b>. Em seguida clique no botão <b>Continue</b> para confirmar. Após o IDE ser reiniciado uma nova opção será adicionada ao menu <b>Source</b>. Você também pode usar o atalho <i>CTRL + M</i>. Esta opção irá abrir a seguinte janela:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwwPbLVmKJtb4GtYiKx5ut_mX7UBInO6c7JmeLQRW9ZFkexIqfeA74TReeUxAXB5rd5iYxmPR6N0EHZqJZyv2msmKRoG4mGyQ4aFXIL0WpzpRcU7BcrKlwshGZ_j64xJYQEE4d/s1600/composer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwwPbLVmKJtb4GtYiKx5ut_mX7UBInO6c7JmeLQRW9ZFkexIqfeA74TReeUxAXB5rd5iYxmPR6N0EHZqJZyv2msmKRoG4mGyQ4aFXIL0WpzpRcU7BcrKlwshGZ_j64xJYQEE4d/s320/composer.png" width="320" /></a></div>Após escolher o tipo de mensagem, os parâmetros demais opções, confirme em OK e o diálogo selecionado será adicionado no seu código na posição do cursor.<br />
<br />
<b>Dicas para funções e procedimentos</b><br />
<br />
Se você não lembra dos parâmetros, ordem, tipos de dados de uma função ou procedimento, digite a mesma e dentro dos parênteses tecle <i>CTRL + SHIFT + ESPAÇO</i>. Irá aparecer uma janela de dica com os argumentos:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdVVNK7jMitHAWuOdW1BBmtajaSx6Bkkx8LxBZrSx2ZDuu2MlxKSsOtYHuLoH7LMc5ue4fhmWNMxmjJadvxTwf70me8cxdZI4UKCSmNV-xTwHSaCCggX0Ta-j43lZc2ckYf8Pi/s1600/dicas.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="65" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdVVNK7jMitHAWuOdW1BBmtajaSx6Bkkx8LxBZrSx2ZDuu2MlxKSsOtYHuLoH7LMc5ue4fhmWNMxmjJadvxTwf70me8cxdZI4UKCSmNV-xTwHSaCCggX0Ta-j43lZc2ckYf8Pi/s320/dicas.png" width="320" /></a></div>À medida que um argumentos é digitado, o próximo fica em destaque na janela. Um botão à direita permite colar os parâmetros no código fonte.<br />
<br />
<b>Templates</b><br />
<br />
Templates são modelos que podem ser inseridos no código. Por exemplo, suponha que você deseja inserir um comando <b>case</b> no seu código. Digite <i>casee</i> no ponto onde deseja inserir e tecle <i>CRTL + J</i>. Será inserido o seguinte código, e o cursor será posicionado no local onde deve ser inserida a variável do comando.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO37EvJp2id-hhqEfrmPtyzdubTWaDvJNHz3vwhI3x36whMthHL36SgnNGmAY7OWTDA-f_hRbo8_pTmaW2hc4TN7i7d6rTnG7fg5TSFhho0YvwVkxE7WX9IwlQWK-ZJ5kTo7wK/s1600/template.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO37EvJp2id-hhqEfrmPtyzdubTWaDvJNHz3vwhI3x36whMthHL36SgnNGmAY7OWTDA-f_hRbo8_pTmaW2hc4TN7i7d6rTnG7fg5TSFhho0YvwVkxE7WX9IwlQWK-ZJ5kTo7wK/s320/template.png" width="320" /></a></div>Existem vários modelos prontos, mas você pode criar os seus próprios templates usando a opção <i>Tools | Code Templates</i>. Na janela que será aberta você usará o botão <b>Add</b> para adicionar novo modelo.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8jozer4HkGimJYzdVX8jl_0Hz5m-yAlbTmY4UYyc72bv-ooCv_jJRv4lIjwN7Os__eZ5zeQsWJGdd-v0wbbk5Nl6J_n4c1Xb6XaQ4xEEQeYBTHz2f-HslXd-zQmZ_Vo6QXkej/s1600/codetemplate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8jozer4HkGimJYzdVX8jl_0Hz5m-yAlbTmY4UYyc72bv-ooCv_jJRv4lIjwN7Os__eZ5zeQsWJGdd-v0wbbk5Nl6J_n4c1Xb6XaQ4xEEQeYBTHz2f-HslXd-zQmZ_Vo6QXkej/s320/codetemplate.png" width="314" /></a></div>Clique <a href="http://wiki.lazarus.freepascal.org/IDE_Window:_Code_Templates">aqui</a> para ver um rápido tutorial de como criar novos modelos. Por enquanto é isso que temos. Aproveite os recursos e explore mais possibilidades com o LazarusProfessor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com9tag:blogger.com,1999:blog-33774862.post-17854911803739913212011-07-23T07:40:00.000-04:002011-07-23T07:40:01.433-04:00Lazarus - Usando Dicionários de DadosNos dois posts anteriores:<br />
<a href="http://professorcarlos.blogspot.com/2011/07/lazarus-o-lazarus-data-desktop.html">Lazarus - O Lazarus Data Desktop</a> e<br />
<a href="http://professorcarlos.blogspot.com/2011/07/lazarus-dicionarios-de-dados.html">Lazarus - Dicionário de Dados</a><br />
estudamos a ferramenta Lazarus Data Desktop e como criar dicionários de dados. Neste artigo iremos mostrar como usar os dicionários nas aplicações desenvolvidas usando Lazarus.<br />
Como já falamos, um dicionário de dados descreve entre outras coisas os atributos dos campos das tabelas de um esquema de banco de dados. E essa descrição, também chamada de metadados, pode ser usada nas aplicações para evitar que tenhamos que repetir essas definições em cada <b>DataSet</b>. Assim, vamos supor que já exista um dicionário de dados criado para um tabela chamada PRODUTO. E vamos mostrar como usar o dicionário de dados em tempo de execução e como aplicá-lo em tempo de desenvolvimento.<br />
O primeiro passo é o mesmo necessário para acessar qualquer tabela sem usar o recurso do dicionário de dados. Supondo que estejamos usando <b>ZeosLib</b>, coloque todos os componentes que são precisos, no <b>Data Module</b>: <b>ZConnection</b>, <b>ZQuery</b> e um <b>DataSource</b>. Faça todas as configurações exigidas. Agora crie os campos persistentes <b>TFields</b> para a <b>ZQuery </b>- este é um procedimento obrigatório para o funcionamento do dicionário de dados. Dê um duplo clique na <b>ZQuery</b> e você verá uma pequena janela como na figura abaixo:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-zQNijSsFG4qI93cpjSHBcLrtIJ3EgzXADU6DBsDm8Ig3MsF1g2nb_qnuO-fr_7FkzNBHTDViIXvhUlSCvNT8X_JHjgRcCZ-Fa0nEJhufmciePCIOWkK_bVSzhZYsniUeeN38/s1600/tfields.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-zQNijSsFG4qI93cpjSHBcLrtIJ3EgzXADU6DBsDm8Ig3MsF1g2nb_qnuO-fr_7FkzNBHTDViIXvhUlSCvNT8X_JHjgRcCZ-Fa0nEJhufmciePCIOWkK_bVSzhZYsniUeeN38/s320/tfields.png" width="234" /></a></div>Clique no botão com o sinal de <b>+</b> ou pressione <i>CTRL + INS</i> para inserir os campos. Uma nova janela mostrando todos os campos da tabela correspondente será mostrada, como a figura a seguir:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeyer4yrUP85LkoGuoffJxPI0eM4rE6mmBh-FocIe5-iVP6iyNxVF7nJNS17aJeo6ID8WmIWIQ2AfQ9DGvY2PNXKTQnIWVTSJhU5srzVWP94w71tcHJf4pLHAwqdgkcp8jsMSP/s1600/tfields1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeyer4yrUP85LkoGuoffJxPI0eM4rE6mmBh-FocIe5-iVP6iyNxVF7nJNS17aJeo6ID8WmIWIQ2AfQ9DGvY2PNXKTQnIWVTSJhU5srzVWP94w71tcHJf4pLHAwqdgkcp8jsMSP/s1600/tfields1.png" /></a></div>Selecione todos os campos e pressione o botão <b>Create</b>.<br />
<br />
<b>Usando dicionário de dados em run-time</b><br />
<br />
Uma maneira de usar o dicionário de dados em tempo de execução é inserir o código, por exemplo, no evento <b>OnCreate</b> do <b>Data Module</b>. A classe <b>TFPDataDictionary</b> está localizada na <i>unit</i> <b>fpdatadict</b>. Portanto, é necessário declarar esta <i>unit</i> na cláusula uses no módulo onde será instanciada <b>TFPDataDictionary</b>. Assim, nosso código poderá ficar assim:<br />
<br />
<pre class="brush: pascal" xml:space="preserve">procedure TdmData.DataModuleCreate(Sender: TObject);
var
Dict : TFPDataDictionary;
begin
Dict := TFPDataDictionary.Create;
// carrega o arquivo do dicionário de dados
Dict.LoadFromFile('produto.fpd');
// aplica o dicionário ao DataSet
Dict.ApplyToDataset(queProduto);
// libera a memória usada pelo dicionário de dados
Dict.Free;
end;
</pre><br />
Num form você pode inserir um <b>TDBGrid</b>, onde serão mais facilmente visualizados os efeitos que desejamos. Associe essa grade ao <b>DataSource</b> que está ligado ao <b>DataSet</b> onde foi aplicado o dicionário.<br />
Agora execute o programa e você poderá constatar que todas as definições feitas no dicionário de dados serão assumidas pelos <b>TFields</b> que foram criados.<br />
<br />
<b>Usando dicionário de dados em tempo de projeto</b><br />
<br />
Neste caso, o primeiro passo é registrar no projeto o dicionário desejado. Isso é feito usando a opção de menu <b>Project > Data Dictionary > Set ...</b> Quando selecionar este item de menu um diálogo será aberto:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiE1O8cEf-lglB1EyC5Fv51ETVtDACxbPrWMdh-uo2k92Fos-0QvZXEDZ4Cz0-WJ3wcIOe0KY8r9gskq2TXFpyQiC9j0HkLVp395dHw7W_bsowzxRXKx4uw6NzGtibaL-ydDE2/s1600/setdict.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiE1O8cEf-lglB1EyC5Fv51ETVtDACxbPrWMdh-uo2k92Fos-0QvZXEDZ4Cz0-WJ3wcIOe0KY8r9gskq2TXFpyQiC9j0HkLVp395dHw7W_bsowzxRXKx4uw6NzGtibaL-ydDE2/s320/setdict.png" width="320" /></a></div>Marque a caixa <b>Use Data dictionary for this project</b>. E selecione o dicionário de dados desejado. Confirme pressionando <b>OK</b>.<br />
Agora localize o <b>DataSet</b> e clique com o botão direito sobre ele. Selecione o item <b>Data dictionary</b> e depois em <b>Apply</b>.<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8S8uFO9yMP0zhxEDRzKnNFnAYsdwVY-tktZ1iIu7LaxyN1V8N_QUZSa96e9DlclaIhhghoMgKA6lAQfYBIyNqz2iVdbvjm_WW_U8VG9ao5Q-1g8X5YMBL4zkSO4K5JHopQvzn/s1600/menulocal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8S8uFO9yMP0zhxEDRzKnNFnAYsdwVY-tktZ1iIu7LaxyN1V8N_QUZSa96e9DlclaIhhghoMgKA6lAQfYBIyNqz2iVdbvjm_WW_U8VG9ao5Q-1g8X5YMBL4zkSO4K5JHopQvzn/s320/menulocal.png" width="237" /></a></div>Isso irá aplicar o dicionário ao <b>DataSet</b>, da mesma forma que fizemos usando código. Agora podemos executar o programa e aproveitar o recurso.<br />
Post escrito tendo como referência o livro <b>Lazarus - the Complete Guide</b>, publicado pela <a href="http://www.blaisepascal.eu/index.php?actie=./subscribers/lazarusbookinfoEnglish">Blaise Pascal Magazine</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com0tag:blogger.com,1999:blog-33774862.post-23989897044835138132011-07-10T22:22:00.001-04:002011-07-18T06:35:49.674-04:00Lazarus - Dicionários de DadosDicionários de dados são repositórios com metadados sobre bancos de dados, que descrevem a estrutura básica de um esquema de banco de dados. Num dicionário de dados as seguintes informações são armazenadas: as tabelas e os campos correspondentes, e os índices existentes nas tabelas. Além disso, os dicionários de dados contém atributos que definem como o conteúdo dos campos devem ser visualizados: número de casas decimais, o rótulo, a dica (<i>hint</i>) mostrada, tamanho do campo, entre outros.<br />
Um dicionário de dados pode ser usado por uma aplicação Lazarus para definir as propriedades dos objetos <b>TField</b>; pode ser usado para criar comandos SQL, por exemplo, para criar o banco de dados descrito; e, a partir da comparação entre dois dicionários, as diferenças entre eles podem ser usadas para criar um script de atualização.<br />
Os dicionários de dados podem ser mantidos usando o Lazarus Data Desktop, que começamos a descrever no post <a href="http://professorcarlos.blogspot.com/2011/07/lazarus-o-lazarus-data-desktop.html">Lazarus - o Lazarus Data Desktop</a>. Usando esta ferramenta podemos criar um dicionário novinho em folha ou importá-lo a partir de um banco de dados existente.<br />
<br />
<b>Criando um Dicionário de Dados</b><br />
<br />
Para criar um novo dicionário clique no botão correspondente na barra de ferramentas conforme mostra a figura, ou tecle <i>CTRL + N</i>.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuvkxOm2P1tBxaSt1Za21AZuFR0_YTaBCgtvsfpl8mTkv8hLstSEBeT8FVm-4XTw5r8hJHxH9KyafpkW2JLqdS3DLC1NmRSZJJZnaxQ2jE9RosM7Z6c5EAIJlSHFLtRcDS9X_8/s1600/novo_dict.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuvkxOm2P1tBxaSt1Za21AZuFR0_YTaBCgtvsfpl8mTkv8hLstSEBeT8FVm-4XTw5r8hJHxH9KyafpkW2JLqdS3DLC1NmRSZJJZnaxQ2jE9RosM7Z6c5EAIJlSHFLtRcDS9X_8/s320/novo_dict.png" width="320" /></a></div>Isso irá criar uma nova aba. Clique com o botão direito no interior da aba e em seguida na opção <i>New Table</i>, ou tecle <i>CTRL + T</i>, para criar uma nova tabela. Digite o nome da tabela na caixa de diálogo e confirme.<br />
Agora clique com o botão direito sobre o nome da tabela recém-criada e escolha a opção <i>New Field</i>. Digite o nome do campo e confirme. Um novo campo será criado e um formulário para definir as propriedades do campo será aberto no lado direito da interface, como podemos ver na figura abaixo.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGD2OXb6AZI4bxRywzcBo1m8jzvN90HmhJTxv5DhPdXuxFxKo-kO_bQvhpx_4FisgNaEaugBd5P9qiGZJlmC8lsNcLOCIxpoPWSD5ix-cp2XTpeCxkhygYOeGYY_xVP6N1IyXM/s1600/novo_campo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhGD2OXb6AZI4bxRywzcBo1m8jzvN90HmhJTxv5DhPdXuxFxKo-kO_bQvhpx_4FisgNaEaugBd5P9qiGZJlmC8lsNcLOCIxpoPWSD5ix-cp2XTpeCxkhygYOeGYY_xVP6N1IyXM/s320/novo_campo.png" width="320" /></a></div>Algumas propriedades que podem ser definidas, entre outras:<br />
<b>DisplayName</b> - rótulo do campo que poderá ser visualizado em uma <b>TDBGrid</b>, por exemplo;<br />
<b>DisplayWidth</b> - tamanho com que o campo será exibido;<br />
<b>FieldType</b> - tipo de dado do campo;<br />
<br />
Após criar todas as tabelas e campos, tecle <i>CTRL + S</i> para salvar.<br />
<br />
<b>Gerando comandos SQL a partir do Dicionário</b><br />
<br />
Para gerar os comandos SQL pressione o botão correspondente conforme mostra a figura abaixo ou tecle <i>CTRL + G</i>.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMPuWXT5CbCNHfSq2GJNQngIeXyZP220GNCNY0tv8rJKIF0xZwde2KHRpx7X6nEZjaKFA6IHylOgPuHLP6EGf-QlWQdFkzIP-8V-dhaUIXd2l374NULhTJeXyb-Tr5ZFOQoSRn/s1600/gerar_sql.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMPuWXT5CbCNHfSq2GJNQngIeXyZP220GNCNY0tv8rJKIF0xZwde2KHRpx7X6nEZjaKFA6IHylOgPuHLP6EGf-QlWQdFkzIP-8V-dhaUIXd2l374NULhTJeXyb-Tr5ZFOQoSRn/s320/gerar_sql.png" width="320" /></a></div>Essa ação irá abrir um novo formulário. Escolha a tabela para a qual deseja gerar os comandos SQL. Na lista <i>Key fields</i> selecione o(s) campo(s) que será chave primária. Na lista <i>Select/Update/Insert fields</i> selecione o(s) campo(s) que serão usados nos comandos SELECT, UPDATE e INSERT. Pressione o botão <i>Generate SQL</i>. Clique em cada uma das abas para ver os comandos gerados. Na figura seguinte mostramos o comando CREATE TABLE que foi gerado.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdVCE2tQPYODptqolREgOpVQnxjCz1CTgK9Sm7LWwRWP_d4ikOnIFpqKxosSQDq-EbomzZbNu-wEG5GhSkaVQILPcMYaUdjmbiMnTTDuUS7cRGTODRTEccU7y7VUXLwqP4X7ll/s1600/comandosql.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="167" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdVCE2tQPYODptqolREgOpVQnxjCz1CTgK9Sm7LWwRWP_d4ikOnIFpqKxosSQDq-EbomzZbNu-wEG5GhSkaVQILPcMYaUdjmbiMnTTDuUS7cRGTODRTEccU7y7VUXLwqP4X7ll/s320/comandosql.png" width="320" /></a></div><br />
<b>Importando o Dicionário de Dados</b><br />
<br />
Se já tivermos um banco de dados criado, podemos criar o dicionário a partir dele - processo que é chamado engenharia reversa.<br />
Inicialmente crie uma conexão para o banco de dados existente conforme mostramos em <a href="http://professorcarlos.blogspot.com/2011/07/lazarus-o-lazarus-data-desktop.html">Lazarus - o Lazarus Data Desktop</a>. Em seguida selecione no menu <i>Dictionary > Import > From connection</i>. As conexões criadas na ferramenta estarão disponíveis nessa opção. Escolha aquela para a qual você precisa criar o dicionário.<br />
Uma caixa de diálogo será aberta mostrando as tabelas do esquema. Selecione as tabelas desejadas, deixe marcada a caixa <i>Update existing tables</i> para atualizar tabelas que já existem e confirme.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9HGsRtXR7eXgoPlQbwzZTNYsK47iQuaLm6uCnYn_HNdxXtyJG5exnbNCcXpS2eRxc176F-5Zy4OrmJuoiywcJQHdsAitlZi0pvRGOrBxVT0F8cz-DqqCNe1H4yPT5rupPV4a2/s1600/importar.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9HGsRtXR7eXgoPlQbwzZTNYsK47iQuaLm6uCnYn_HNdxXtyJG5exnbNCcXpS2eRxc176F-5Zy4OrmJuoiywcJQHdsAitlZi0pvRGOrBxVT0F8cz-DqqCNe1H4yPT5rupPV4a2/s320/importar.png" width="320" /></a></div>Se houver um dicionário ativo na ferramenta, você será questionado se deseja atualizar ou criar um novo. Clique <i>CTRL + S</i> para salvar o dicionário. Os dicionários de dados são salvos com a extensão <b>.fpd</b>. Você pode visualizar o arquivo de dicionário de dados usando qualquer programa que abre arquivos texto.<br />
Fica para o próximo post a utilização de dicionários de dados em aplicações Lazarus.<br />
Post escrito tendo como referência o livro <b>Lazarus - the Complete Guide</b>, publicado pela <a href="http://www.blaisepascal.eu/index.php?actie=./subscribers/lazarusbookinfoEnglish">Blaise Pascal Magazine</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com1tag:blogger.com,1999:blog-33774862.post-19193852462130182842011-07-04T13:58:00.001-04:002011-07-04T20:02:28.036-04:00Lazarus - O Lazarus Data DesktopSe em suas aplicações você utiliza diversos bancos de dados, é provável que também precise de uma ferramenta específica para cada SGBD, com a finalidade de criar tabelas, criar comandos DML e DDL, entre outros. A fim de centralizar todas as tarefas do desenvolvedor no Ambiente de Desenvolvimento, o Lazarus oferece o Lazarus Data Desktop. Também chamado Database Desktop, esta ferramenta dispõe de vários recursos, dentre os quais destacamos:<br />
<ul><li>Acesso a todos os bancos de dados suportados pelo Lazarus;</li>
<li>Criação de um dicionário de dados onde as propriedades de <b>TFields</b> podem ser armazenadas;</li>
<li>Criação de comandos DDL e DML a partir do dicionário de dados;</li>
<li>Consulta à tabelas;</li>
<li>Exportação de dados de tabelas para diversos formatos: XML, JSON, CSV, entre outros.</li>
</ul>Para usar esta ferramenta. primeiramente é necessário compilá-la. Ela está localizada em <i>tools/lazdatadesktop</i>, no diretório home do Lazarus. Abra então o projeto <i>lazdatadesktop</i> e compile-o.<br />
Para integrar a ferramenta ao IDE, abra e instale o pacote <i>lazDataDict</i>, localizado no diretório <i>components/datadict</i>. Após isso o IDE será estendido em três novas opções:<br />
<ol><li>Um novo item de menu será registrado no menu <i>Project </i>- com o nome <i>Data Dictionary</i>. Esta opção irá permitir que escolhamos um dicionário de dados para o projeto;</li>
<li>No menu <i>Tools</i> será acrescentado o item de menu <i>Database Desktop</i>, que executa o Lazarus Data Desktop;</li>
<li>Finalmente no <i>Form Designer</i>, um novo item é registrado no menu local que pode ser usado para aplicar o dicionário de dados a um <i>TDataset</i> - o item de menu <i>Data Dictionary</i>.</li>
</ol>Vejamos então como utilizar o Lazarus Data Desktop.<br />
<br />
<b>Conectando-se a bancos de dados</b><br />
<br />
Para fazer uma conexão use a opção de menu <i>Connections > New connection</i>, como mostra a figura abaixo:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCmYKfJaUP9tbmr5BHOwG7Dy-0FyihlR0WJpRTxb2xe7KNWC7Ub1EEJmNs3mqhpmiSniuDwUl0ZuBg7NASTlF0pGQzrQMO96TVbvGkRr8bbe-dpNed59T7idsGKs-K7h6zMoYq/s1600/datadesktop.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCmYKfJaUP9tbmr5BHOwG7Dy-0FyihlR0WJpRTxb2xe7KNWC7Ub1EEJmNs3mqhpmiSniuDwUl0ZuBg7NASTlF0pGQzrQMO96TVbvGkRr8bbe-dpNed59T7idsGKs-K7h6zMoYq/s320/datadesktop.png" width="320" /></a></div>Esta ação abrirá uma caixa de diálogo onde você irá escolher o banco de dados:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzDxZixtbc3wsBdUGi_fqx_B6Ji79pfH7LEwQD2_Khsq0Ufz2G4L6Xe5Ue2v5vvJga-yPFGr2IYCUzpciOL8CBEOfDCS9KybT5SiH7Ia0WFG_jElUgZEEjadaCCbhRRbjubUf/s1600/selecionar+bd.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="254" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzDxZixtbc3wsBdUGi_fqx_B6Ji79pfH7LEwQD2_Khsq0Ufz2G4L6Xe5Ue2v5vvJga-yPFGr2IYCUzpciOL8CBEOfDCS9KybT5SiH7Ia0WFG_jElUgZEEjadaCCbhRRbjubUf/s320/selecionar+bd.png" width="320" /></a></div>Selecione o banco de dados e você será levado a um novo diálogo para informar os dados da conexão:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2CQh5Xa_a1QIpiVCOtxRZNEnewNW-LGV9oX8yTMcom0Fj7u3z0oAaZjClj8L1An28aeXi55SzyTIqsCW6b3qQ4OUQKgkWOQrlmN-HCeL06QGLRFyP4S1XjXom-bjqT7NJwowW/s1600/dadosconex%25C3%25A3o.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2CQh5Xa_a1QIpiVCOtxRZNEnewNW-LGV9oX8yTMcom0Fj7u3z0oAaZjClj8L1An28aeXi55SzyTIqsCW6b3qQ4OUQKgkWOQrlmN-HCeL06QGLRFyP4S1XjXom-bjqT7NJwowW/s320/dadosconex%25C3%25A3o.png" width="320" /></a></div>Após informar os dados e confirmar será solicitado um nome para a conexão. Confirme também, após informar o nome e será adicionada uma nova aba ao ambiente com as informações da conexão. No lado direito da tela existe a aba <i>Run Query</i>, que possibilita executar uma consulta e exportar o resultado da consulta, entre outros recursos.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSA6GRDNShDa4fkTvEbkoX1brDcaTiVGXNWbK3C30-cK7PcnV0Kw_wN2bt56h18OW6o7J3-PbaYewyEI8_ysIW8d7xXfUIKLC-JKxSgnQ7xr0ytLsawZizwS5lNmeZEoIsenW1/s1600/query.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSA6GRDNShDa4fkTvEbkoX1brDcaTiVGXNWbK3C30-cK7PcnV0Kw_wN2bt56h18OW6o7J3-PbaYewyEI8_ysIW8d7xXfUIKLC-JKxSgnQ7xr0ytLsawZizwS5lNmeZEoIsenW1/s320/query.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;"><b>Exportando dados de uma tabela</b></div><div class="separator" style="clear: both; text-align: left;"><br />
</div>Para exportar os dados resultantes de uma consulta, use o botão <i>Export this data</i> que será habilitado após a execução bem sucedida de uma <i>Query</i>. Em seguida escolha o tipo de arquivo, por exemplo CSV, e confirme. Então será mostrado um diálogo onde se pode escolher os campos da tabela a serem exportados, o caminho e o nome do arquivo destino e opções de formatação, conforme pode ser visto na figura a seguir.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR8vNUpz5IJpjdaQPyKBTKBAzHru4GVDqwovIbaDVErqnj19xkPf7PNeHhqMKc8cw8RNLOzcwQ4BCQnz05GeBXDaH22Dr2hSSg4hwOejPBmVIdiaYnFicL7GRD554MdbGG-WcH/s1600/exportar+dados.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR8vNUpz5IJpjdaQPyKBTKBAzHru4GVDqwovIbaDVErqnj19xkPf7PNeHhqMKc8cw8RNLOzcwQ4BCQnz05GeBXDaH22Dr2hSSg4hwOejPBmVIdiaYnFicL7GRD554MdbGG-WcH/s320/exportar+dados.png" width="320" /></a></div>Depois de confirmar o arquivo exportado será criado.<br />
<br />
<b>Gerando código Free Pascal</b><br />
<br />
Outro recurso importante do Lazarus Data Desktop é a criação de código em Free Pascal. Pode-se gerar código quando estamos visualizando o resultado de uma <i>Query </i>ou quando estamos examinando a definição de uma tabla no dicionário de dados.<br />
Os códigos que podem ser gerados são:<br />
<ul><li>Uma constante string a partir do comando SQL quando se está visualizando o resultado de uma consulta;</li>
<li>O código para criar uma tabela DBF a partir dos dados que estão sendo mostrados;</li>
<li>Uma classe Object Pascal e suas propriedades baseados em um <i>Dataset </i>e seus campos;</li>
<li>Uma declaração de classe tiOPF para usar com Object Persistence Framework.</li>
</ul>Por exemplo, na aba <i>Run Query</i>, após executar uma consulta, clique no botão <i>Create pascal code for this data</i>. Escolha em seguida a opção <i>Simple object/collection for the data</i>. Será aberto o seguinte diálogo:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-y8coYNFrMquOfXYrIyK_R2GWe_sn6acdkZnQijtqPH4XDc63VWkuiK3Xy0izGdFeeMG3p3gn08lvic6CsEqVoEbmat_gjsJItEKeD0av2wvUCJ0VLhozu1W6seDDwGeV-IjM/s1600/gera+codigo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-y8coYNFrMquOfXYrIyK_R2GWe_sn6acdkZnQijtqPH4XDc63VWkuiK3Xy0izGdFeeMG3p3gn08lvic6CsEqVoEbmat_gjsJItEKeD0av2wvUCJ0VLhozu1W6seDDwGeV-IjM/s1600/gera+codigo.png" width="320" /></a></div>Nessa tela você define o caminho e nome do arquivo onde deseja salvar o código e os campos da tabela que serão propriedades da classe. Para cada campo da tabela é possível definir propriedades, bem como definir algumas propriedades da própria classe na aba <i>Options</i>. Confirme e uma tela com o código gerado será aberta, conforme mostra a figura seguinte:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTnGA9TbimGYJusYyXGDoK_KFHpb_67DACr8LbXeqgfCNXsKgpssLe8t9TjeQ-vUuxaQovSt6GtPtl9cFm_1NwxF8-otNkXyzkoOaJiZtIIFeZo-BriXbENnDmSoLrkVqV9efO/s1600/codigo+gerado.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTnGA9TbimGYJusYyXGDoK_KFHpb_67DACr8LbXeqgfCNXsKgpssLe8t9TjeQ-vUuxaQovSt6GtPtl9cFm_1NwxF8-otNkXyzkoOaJiZtIIFeZo-BriXbENnDmSoLrkVqV9efO/s320/codigo+gerado.png" width="320" /></a></div>Apesar de ter um botão <i>Save</i>, isso não será mais necessário, pois o código já está salvo no arquivo informado na tela anterior.<br />
No próximo post veremos os procedimentos para criar dicionários de dados no Lazarus Data Desktop e como utilizá-los em nossas aplicações de banco de dados.<br />
Post escrito tendo como referência o livro <b>Lazarus - the Complete Guide</b>, publicado pela <a href="http://www.blaisepascal.eu/index.php?actie=./subscribers/lazarusbookinfoEnglish">Blaise Pascal Magazine</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com2tag:blogger.com,1999:blog-33774862.post-68912264393305158142011-07-03T17:32:00.001-04:002011-07-03T17:32:18.571-04:00Lazarus - Livro sobre Lazarus em Português<b>"Desenvolvendo Aplicativos com Lazarus" (agbook, 2011, 344 páginas)</b>, produzido pelo paraense Jean Patrick, reúne um conjunto de informações valiosas sobre o IDE Lazarus, que chegam em boa hora para suprir uma necessidade urgente daqueles que, ou pretendem adotar uma nova ferramenta de desenvolvimento ou gostariam de melhorar seu conhecimento sobre o IDE.<br />
O livro está organizado em 14 capítulos e 5 apêndices. Sendo que os nove primeiros capítulos passam por vários tópicos, alguns bem superficialmente tal como as paletas de componentes, e dá mais destaque à configuração no IDE no Capítulo 6.<br />
Para os que preferem ação, ela começa mesmo no Capítulo 10. Nesse capítulo são desenvolvidos três projetos, o que dá uma boa noção do poder de fogo do Lazarus. Os projetos usam componentes básicos e há farta utilização de eventos e código. Desta forma o leitor terá um bom suporte para o que vem pela frente, que é o desenvolvimento usando banco de dados.<br />
Uma introdução a banco de dados é feita no Capítulo 11. No Capítulo 12 são usados os componentes nativos do Lazarus para conexão a bancos de dados - a paleta SQLdb. Aqui é criada uma aplicação para controle de cheques usando o banco de dados <a href="http://sqlite.org/">sqlite</a>.<br />
Um cadastro de produtos usando banco de dados Firebird é criado no Capítulo 13. Neste caso o livro apresenta o conjunto de componentes <a href="http://zeos.firmos.at/">ZeosLib</a>, ZeosLib é uma biblioteca de terceiros e considerada melhor que SQLdb para aplicações de maior porte.<br />
A criação de relatórios é abordada no Capítulo 14, onde se destaca o conjunto LazReport, nativo do Lazarus. Documentação sobre LazReport é muito raro. Esse é capítulo que vai ajudar muito aos desenvolvedores.<br />
Nos apêndices destacamos os recursos do IDE para tratamento de arquivos texto e algumas dicas para programar aplicações multiplataforma. Inclusive é criada uma pequena aplicação para demonstrar o uso dos componentes oferecidos pelo Lazarus para acessar arquivos texto.<br />
É uma obra que precisa do incentivo da comunidade para crescer ainda mais. Costumo dizer que só com a divulgação de conteúdo de valor é que será possível a disseminação do uso deste poderoso IDE.<br />
Os interessados em adquirir um exemplar acessem o site da <a href="http://www.agbook.com.br/book/46758--Desenvolvendo_Aplicativos_com_Lazarus">agbook</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com0tag:blogger.com,1999:blog-33774862.post-6115398624659840122011-06-14T20:08:00.005-04:002011-07-03T09:45:12.410-04:00Curso de Introdução ao Free Pascal/Lazarus - GratuitoDesenvolver aplicações usando um IDE como o Lazarus, pressupõe conhecimento da linguagem de programação subjacente. Pois a criação de um programa sempre irá precisar que se escreva algum código, principalmente para os eventos. No caso do Lazarus estamos falando do Free Pascal. Este é um curso introdutório ao Free Pascal oferecido na modalidade à distância e está organizado em oito módulos:<br />
<br />
1. Princípios básicos, tipos, variáveis, constantes e comando de atribuição<br />
2. Comandos condicionais (if)<br />
3. Comandos de repetição (while, repeat e for)<br />
4. Tipos definidos pelo usuário (subrange, set, enumerados, arrays, registros)<br />
5. Ponteiros<br />
6. Procedimentos e funções<br />
7. Manipulação de strings<br />
8. Classes e objetos<br />
<br />
O curso será ministrado no ambiente virtual de aprendizagem <a href="http://moodle.org/">Moodle</a>. É uma ferramenta voltada para ensino à distância com todos os recursos de um ambiente dessa natureza: chat, fórum, exercícios, questionários, etc.<br />
Caso você tenha interesse em fazer o curso, faça sua pré-inscrição aqui. Assim que completarmos a turma enviaremos um e-mail a você informando a data de início do curso e seu login e senha de acesso ao ambiente de aprendizagem.<br />
<b>Pré-inscrições encerradas.</b><br />
<br />
<div style="color: white;"><span style="background-color: red;">Atualizado em 03/07/2011.</span></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com23tag:blogger.com,1999:blog-33774862.post-51414694448397861782011-06-01T10:42:00.000-04:002011-06-01T10:42:39.739-04:00Free Pascal - Usando TListA classe <b>TList </b>é usada para gerenciar uma coleção de ponteiros, com a grande vantagem de ser dinâmica. Ela dispõe de métodos para fazer busca na lista e ordenar os elementos, entre outros. No exemplo abaixo fazemos uso de alguns desses métodos.<br />
<br />
<br />
<pre class="brush: pascal" xml:space="preserve">unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
TContato = class
private
NomeContato : String;
TelefoneContato : String;
public
property Nome : String
read NomeContato;
property Telefone : String
read TelefoneContato;
constructor Create(const pNomeContato : String;
const pTelefoneContato : String);
end;
{ TfrmTlist }
TfrmTlist = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
Agenda : TList;
procedure MostraAgenda;
public
{ public declarations }
end;
var
frmTlist: TfrmTlist;
implementation
{$R *.lfm}
constructor TContato.Create(const pNomeContato : String;
const pTelefoneContato : String);
begin
self.NomeContato := pNomeContato;
self.TelefoneContato := pTelefoneContato;
end;
function comparaPorNome(Item1 : Pointer; Item2 : Pointer) : Integer;
var
contato1, contato2 : TContato;
begin
contato1 := TContato(Item1);
contato2 := TContato(Item2);
if contato1.Nome > contato2.Nome
then Result := 1
else if contato1.Nome = contato2.Nome
then Result := 0
else Result := -1;
end;
procedure TfrmTlist.Button1Click(Sender: TObject);
var
contato : TContato;
begin
Agenda := TList.Create;
contato := TContato.Create('Nádia Alves', '3523-0001');
Agenda.Add(contato);
contato := TContato.Create('Célio Silva', '3524-0000');
Agenda.Add(contato);
Agenda.Add(TContato.Create('Hélio Costa', '3320-1000'));
Agenda.Add(TContato.Create('Aldo Sousa', '3321-0001'));
MostraAgenda;
ShowMessage('Ordenando pelo nome. Pressione OK');
Agenda.Sort(@comparaPorNome);
MostraAgenda;
ShowMessage('Inserindo novo contato. Pressione OK');
Agenda.Insert(2, TContato.Create('Luis Gonzaga', '3325-4000'));
MostraAgenda;
ShowMessage('Excluindo um contato. Pressione OK');
Agenda.Delete(4);
ShowMessage('Pressione OK');
Agenda.free;
end;
procedure TfrmTlist.MostraAgenda;
var
i : Integer;
begin
ListBox1.Items.Clear;
for i := 0 to Agenda.Count-1 do
begin
ListBox1.Items.Add(TContato(Agenda[i]).Nome+' - '+
(TContato(Agenda[i]).Telefone));
end;
end;
end.
</pre><br />
<br />
No exemplo criamos uma classe <i>Contato </i>que será usada para povoar um <b>TList</b> que denominamos <i>Agenda</i>. Um <b>TListBox </b>é usado para apresentar os dados do <b>TList</b>.<br />
Nas linhas que vão de 74 a 95 é onde acontece tudo que pretendemos mostrar. Inicialmente o <b>TList </b>é criado. Em seguida, são criados vários objetos <i>Contato</i>, que são adicionados à <i>Agenda </i>utilizando o método <b>Add()</b>. Este método sempre adiciona um objeto no fim da lista.<br />
Após isso chamamos o método <i>MostraAgenda</i>, que foi criado para visualizar os dados da <i>Agenda</i> no <b>TListBox</b>. Na linha 86 há uma chamada ao método <b>Sort()</b>, que recebe como argumento o método <b>comparaPorNome()</b>. Aqui cabe uma explicação mais detalhada.<br />
A ordenação de uma lista de objetos não é uma coisa tão natural como ordenar números inteiros ou strings. Como sabemos um objeto tem vários campos e por isso precisamos definir qual o critério que será usado para decidir que um objeto A é maior, menor ou igual a um outro objeto B. Por este motivo o método <b>Sort()</b> deve receber como parâmetro uma variável procedural, ou seja, um método que estabelece o critério de ordenação.<br />
Dessa forma, foi criado o método <b>comparaPorNome()</b>, que recebe os ponteiros dos dois objetos a serem comparados. Tal método deve retornar -1 se o primeiro objeto for menor que o segundo, 1 se for maior e 0 se forem iguais. No nosso exemplo definimos que dois <i>Contatos </i>são iguais quando tem nomes iguais. Leia mais sobre variáveis procedurais no post <a href="http://professorcarlos.blogspot.com/2011/05/free-pascal-variaveis-procedurais.html">Free Pascal - Variáveis Procedurais</a>. Deve-se ressaltar que o Free Pascal define apenas como deve ser a assinatura do método que ele espera receber em <b>Sort()</b>. A implementação cabe ao desenvolvedor.<br />
Na linha 90 um novo objeto é inserido na posição 2 do <b>TList</b>. Note que a primeira posição é 0.<br />
Usamos o método <b>Delete()</b> para deletar um objeto em uma determinada posição. Na linha 93 excluímos o objeto da posição 4.<br />
Quando a <b>TList </b>não é mais necessária, liberamos a memória usada chamando <b>Free</b>. Para criar uma lista de strings prefira usar <b>TStrings </b>ou sua descendente <b>TStringList</b>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com8tag:blogger.com,1999:blog-33774862.post-75866562667666242132011-05-15T16:22:00.003-04:002011-05-15T19:25:18.047-04:00Lazarus - Acessando banco de dados com SQLdb - Parte IIIMuita coisa mudou no Lazarus desde que começamos a dedicar este blog à divulgação deste poderoso IDE. Quando iniciamos usávamos a versão 0.9.28 e publicamos dois artigos voltados para o uso do conjunto de componentes <b>SQLdb</b>:<br />
<br />
<a href="http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-com.html">Lazarus - Acessando banco de dados com SQLdb - Parte I</a> <br />
<a href="http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-com_24.html">Lazarus - Acessando banco de dados com SQLdb - Parte II</a> <br />
<br />
Hoje estamos com a versão 0.9.31. Neste post iremos apresentar algumas mudanças para melhor na utilização desses componentes.<br />
<br />
<b>Referências aos campos de uma tabela - criação de TFields</b><br />
<br />
Para criar os <b>TFields</b> ainda é necessário que a <b>TSQLQuery</b> esteja ativa. Dê um duplo clique na <b>TSQLQuery</b> e você verá uma janela como esta:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhruHCQ09NOnPPxBGTyEQJJu0vcYI6ATw0mXiF46ENyujwM-dYG4DM-NgDfUtqMNUXfpP1w5ICDgaVsB-RotUjzOP89euSC45AxFMSDMCv_efnvNYZ3OCCqoh-4qbo4J-y4tWVb/s1600/editfields.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhruHCQ09NOnPPxBGTyEQJJu0vcYI6ATw0mXiF46ENyujwM-dYG4DM-NgDfUtqMNUXfpP1w5ICDgaVsB-RotUjzOP89euSC45AxFMSDMCv_efnvNYZ3OCCqoh-4qbo4J-y4tWVb/s320/editfields.png" width="234" /></a></div><br />
Esta janela oferece uma barra de ferramentas bastante intuitiva. O botão adicionar irá abrir uma nova janela onde você poderá selecionar os campos da tabela que se deseja adicionar. Após selecionar os campos pressione o botão <b>Create</b>. O botão novo campo permite criar um campo de dado, calculado ou <i>lookup</i>. O uso desse botão irá abrir a seguinte janela:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDgb5jCkAQVexksF66iy8bB5GaC2NqR-yd6614a95qR-S9f3v8Og5BdxmAOFJJzhLgdmGxEdPLaTiJgWjLMcE4YNqlMQllG4J0BguqaYDd2fLRepWUDE_HSDV2hyphenhyphenEoEGcCrDmG/s1600/newfield.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDgb5jCkAQVexksF66iy8bB5GaC2NqR-yd6614a95qR-S9f3v8Og5BdxmAOFJJzhLgdmGxEdPLaTiJgWjLMcE4YNqlMQllG4J0BguqaYDd2fLRepWUDE_HSDV2hyphenhyphenEoEGcCrDmG/s320/newfield.png" width="320" /></a></div>Aqui você escolhe o tipo do campo em <b>Field Type</b>. Em <b>Field properties</b> podemos definir os valores das propriedades do campo. Depois confirme tudo pressionando <b>Ok</b>. Esteja sempre atento que as tabelas envolvidas na criação dos campos devem estar abertas.<br />
Note também que esse procedimento irá criar variáveis do tipo <b>TField</b>, que podem ser usadas no código do nosso programa. Essas variáveis são criadas abaixo do <b>Data Module</b> conforme podemos ver na figura:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhczxezHm9ydn8Rb_nB5cXju8LGzPs58osSKdcltE6JTLN4E0A7EB9Ao_nrzcBDbqqTqubLbHPHqqObey9wW7LRDc08hrOnJ8TBHxVt3ipYP-qPN1pXvLtCqKt_Tvdv1TwtglfP/s1600/tfields.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="226" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhczxezHm9ydn8Rb_nB5cXju8LGzPs58osSKdcltE6JTLN4E0A7EB9Ao_nrzcBDbqqTqubLbHPHqqObey9wW7LRDc08hrOnJ8TBHxVt3ipYP-qPN1pXvLtCqKt_Tvdv1TwtglfP/s320/tfields.png" width="320" /></a></div><br />
A partir disso, podemos acessar os campos da tabela usando essas variáveis, lembrando que elas são objetos. Veja alguns exemplos de utilização desses objetos:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">queCidadeidcidade.Value; <span style="color: blue;">// lê o valor do campo, inteiro nesse caso</span></div><div style="font-family: "Courier New",Courier,monospace;">queCidadeidcidade.AsString; <span style="color: blue;">// lê o valor do campo convertido para string</span></div><br />
Criação de <b>TFields</b> não é uma novidade. Isso já existia nas versões anteriores. Apenas ficou um pouco mais intuitivo e fácil manipular a criação desses objetos.<br />
<br />
<b>Referência aos parâmetros de um comando SQL</b><br />
<br />
Como sabemos, é possível escrever comandos SQL utilizando parâmetros. Um exemplo é mostrado no código abaixo:<br />
<br />
<pre class="brush: pascal" xml:space="preserve">procedure TfrmConsCidade.btnPesquisarClick(Sender: TObject);
begin
with dmDados.queConsCidade do
begin
Close;
SQL.Clear;
if (rgCampo.ItemIndex = 0) then
begin
// pidcidade é um parâmetro
SQL.Add('select * from cidade where idcidade = :pidcidade');
// atribuição do valor do parâmetro
ParamByName('pidcidade').Value := StrToInt(edValor.Text);
//Params[0].Value := StrToInt(edValor.Text);
end
else
begin
SQL.Add('select * from cidade where nome like :pnome');
ParamByName('pnome').Value := edValor.Text + '%';
end;
Open;
end;
end;
</pre><br />
Em versões anteriores não havia o método <b>ParamByName()</b>. O acesso a um parâmetro era feito usando <b>Params[]</b>. Isso é mostrado na linha de código 13, que aparece comentada. O uso de <b>ParamByName()</b> torna o código mais legível.<br />
O <b>SQLdb</b> melhorou muito, mas ainda aconselhamos o uso de <b>ZeosLib</b>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com8tag:blogger.com,1999:blog-33774862.post-86322055202830686132011-05-01T23:24:00.005-04:002011-05-03T11:06:21.367-04:00Free Pascal - Variáveis ProceduraisDepois de um longo tempo afastado do blog, estamos retornando. Iremos iniciar uma série de artigos dedicados às estruturas de dados do Free Pascal. Mas antes de iniciar é necessário uma breve introdução a variáveis procedurais. <br />
Variáveis procedurais ou tipos procedurais são um recurso do Free Pascal que permite armazenar métodos, funções e procedimentos em variáveis. Tais variáveis podem ser normalmente tratadas, passando-as como parâmetros e chamando os métodos quando for necessário.<br />
Para exemplificar o uso deste recurso vejamos como declarar um tipo procedural:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">type<br />
TFuncaoSemParametro = function(): String;<br />
TFuncaoComParametro = function(x: String): String;</div><br />
O primeiro exemplo declara um tipo que armazena um função que não recebe argumentos. O segundo exemplo declara um tipo que armazena uma função que recebe parâmetros.<br />
Tipos procedurais também podem ser declarados de mais duas maneiras, como pode ser visto abaixo. O primeiro declara um tipo para armazenar um procedimento e o segundo armazena um método de uma classe:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">type</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> TProcedimento = procedure;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> TMetodo = procedure of Object;</span><br />
<br />
Prosseguindo então com nosso exemplo, em seguida iremos declarar as funções:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"> function AloMundo: String;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">begin</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> Result := 'Alo Mundo';</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">end;</span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">function AloNovamente(S: String): String;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">begin</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> Result := 'Alo ' + S;</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">end;</span><br />
<br />
Essas duas funções serão usadas como argumentos nas chamadas aos dois procedimentos seguintes, que recebem como parâmetros os tipos procedurais declarados.<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">procedure Primeiro(f: TFuncaoSemParametro);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">begin</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> WriteLn(f());</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">end;</span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">procedure Segundo(f: T</span><span style="font-family: 'Courier New', Courier, monospace;">FuncaoComParametro</span><span style="font-family: 'Courier New', Courier, monospace;">);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">begin</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> WriteLn(f('Novamente'));</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">end; </span><br />
<br />
Observe que tanto o procedimento Primeiro, quanto o procedimento Segundo executam a função que recebem como parâmetro. As funções chamadas irão retornar Strings que serão escritas no console através de <b>writeln</b>.<br />
Para testar a funcionalidade apenas chame os procedimentos assim:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">Primeiro(@AloMundo);</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">Segundo(@AloNovamente);</span><br />
<br />
O símbolo @ converte a variável em um ponteiro. É desta forma que a função é passada como parâmetro.<br />
É importante observar que o compilador verifica se a função ou o procedimento que está sendo passado como parâmetro corresponde exatamente ao esperado, ou seja, possui os mesmos parâmetros, o mesmo tipo de retorno, etc.<br />
O mecanismo usado pelos eventos de componentes da biblioteca do Lazarus é exatamente este. Veja como pode ser criado um componente dinamicamente e como atribuir um método a um evento de um <i>TButton</i> no post <a href="http://professorcarlos.blogspot.com/2010/05/lazarus-componentes-em-run-time.html">Lazarus - Criando componentes em run-time</a>.<br />
A seguir o código completo da aplicação console:<br />
<br />
<pre class="brush: pascal" xml:space="preserve">program procvar;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Classes
{ you can add units after this };
type
TFuncaoSemParametro = function(): String;
TFuncaoComParametro = function(x: String): String;
function AloMundo: String;
begin
Result := 'Alo Mundo';
end;
function AloNovamente(S: String): String;
begin
Result := 'Alo ' + S;
end;
procedure Primeiro(f: TFuncaoSemParametro);
begin
WriteLn(f());
end;
procedure Segundo(f: TFuncaoComParametro);
begin
WriteLn(f('Novamente'));
end;
{$R *.res}
begin
Primeiro(@AloMundo);
Segundo(@AloNovamente);
ReadLn;
end.
</pre><br />
<div style="color: white;"><span style="background-color: red;">Atualizado em 03/05/2011.</span></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com2tag:blogger.com,1999:blog-33774862.post-50373243800821439912010-10-07T16:45:00.003-04:002010-10-07T16:48:40.105-04:00Lazarus – Herança de form e criação de componentes em run-timeNeste post vamos mostrar como criar um formulário de cadastro, independente da tabela do banco de dados. A idéia é que, ao abrir o formulário, um trecho de código identifica cada campo da tabela, instancia um TDBEdit para esse campo e ainda o identifica com um TLabel. Além do mais esse código será implementado em um formulário pai. Cada formulário de cadastro será derivado – ou herdado – deste. Nosso demo terá um form principal que chamará o form de cadastro, o form pai onde todas as ações irão acontecer, um form de cadastro derivado e um <b>Data Module</b>.<br />
No <b>Data Module</b> colocamos os componentes de acesso ao banco de dados. Para isso iremos utilizar <b>ZeosLib</b> com banco de dados PostgreSQL. Coloque então um <b>TZConnection</b> para conectar ao seu banco de dados e o configure adequadamente. Coloque também uma <b>TZQuery</b> e um <b>TZUpdateSQL</b>. Consulte o post <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-postgresql-com.html" target="_blank">Lazarus – Conectando PostgreSQL com ZeosLib</a> se tiver dúvida de como fazer essas definições. Não coloque <b>TDataSource</b> no <b>Data Module</b>. Iremos colocá-lo no form pai.<br />
<br />
<b>O form Pai</b><br />
<br />
Já existe um form na aplicação. Vamos inserir um novo form e deixar esse primeiro para ser o principal. No novo form vamos criar a propriedade <b>Query</b> conforme mostra o código abaixo. Inclua a unit <b>ZDataset</b> na cláusula <b>uses</b>.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">private
{ private declarations }
fQuery: TZQuery;
function GetQuery: TZQuery;
procedure SetQuery(NewQuery: TZQuery);
public
{ public declarations }
property Query: TZQuery read GetQuery write SetQuery;
end;
var
frmDinamico: TfrmDinamico;
vetorCampos: array of TDBEdit;
vetorLabel: array of TLabel;
implementation
{$R *.lfm}
procedure TfrmDinamico.FormShow(Sender: TObject);
var
Coluna : integer;
NomeColuna : TDBEdit;
NomeLabel : TLabel;
Topo : integer;
begin
Topo := 65;
dsTabela.DataSet := fQuery;
fQuery.Open;
SetLength(vetorCampos, fQuery.FieldCount);
SetLength(vetorLabel, fQuery.FieldCount);
for Coluna := 0 to fQuery.FieldCount - 1 do
begin
NomeColuna := TDBEdit.Create(Self);
NomeColuna.Parent := Self;
NomeColuna.Left := 105;
NomeColuna.Top := Topo;
NomeColuna.Width := 15 + fQuery.Fields[Coluna].DisplayWidth * 7;
NomeColuna.DataSource := dsTabela;
NomeColuna.DataField := fQuery.Fields[Coluna].FieldName;
NomeColuna.Tag := Coluna;
Topo := Topo + 25;
NomeColuna.Visible := True;
NomeColuna.Name := 'DBEdit' + IntToStr(Coluna);
vetorCampos[Coluna] := NomeColuna;
NomeLabel := TLabel.Create(Self);
NomeLabel.Parent := Self;
NomeLabel.Left := 5;
NomeLabel.Top := NomeColuna.Top - NomeLabel.Height;
NomeLabel.Caption := fQuery.Fields[Coluna].DisplayName;
NomeLabel.Tag := Coluna;
NomeLabel.Visible := True;
NomeLabel.Name := 'Label' + IntToStr(Coluna);
vetorLabel[Coluna] := NomeLabel;
end;
if Topo + 25 > 445 then
Height := 445
else
Height := Topo + 25;
end;
procedure TfrmDinamico.FormClose(Sender: TObject; var CloseAction: TCloseAction
);
begin
fQuery.Close;
CloseAction := caFree;
end;
function TfrmDinamico.GetQuery: TZQuery;
begin
Result := fQuery;
end;
procedure TfrmDinamico.SetQuery(NewQuery: TZQuery);
begin
fQuery := NewQuery;
end;
</pre><br />
Implemente os métodos <b>GetQuery</b> e <b>SetQuery</b> conforme mostrado no código. Na seção <b>var</b> declaramos dois arrays dinâmicos para receber os objetos <b>TDBEdit</b> e <b>TLabel</b>. Agora vamos analisar com mais detalhes o código do evento <b>OnShow</b>. É nesse código que serão criados os objetos em tempo de execução, de acordo com os campos da tabela. No post <a href="http://professorcarlos.blogspot.com/2010/05/lazarus-componentes-em-run-time.html">Lazarus - Criando componentes em run-time</a> nós mostramos como criar componentes em tempo de execução.<br />
Inicialmente no método nós definimos o tamanho dos arrays de acordo com o número de campos da tabela usando o procedure <b>SetLength</b>. Em seguida, dentro de um <b>for</b> que percorre os campos da tabela, é criado um <b>TDBEdit</b> e um <b>TLabel</b> para cada campo. Cada componente é guardado em seu array correspondente. Depois disso é verificada a necessidade de se aumentar a altura do form para que ele possa mostrar todos os componentes criados. Essa verificação é feita através da variável <i>Topo</i> que guarda a posição vertical de cada componente. Como o nosso form é dinâmico, nós liberamos a memória ocupada por ele assim que o mesmo for fechado.<br />
<br />
<b>Herdando o form Pai</b><br />
<br />
Depois disso vamos criar o form de cadastro propriamente dito. Para isso selecione o menu <b>File | New</b> e clique em <b>Inherited Component</b>. Na caixa da direita irão aparecer os forms que podem ser herdados. Escolha o form Pai que foi criado anteriormente e pressione <b>OK</b>. Um novo form será criado com todos os membros do form Pai. Agora selecione a opção de menu <b>Project | Project Options</b>. Clique em <b>Forms</b> e transfira o form Filho para a caixa da direita. Isso determina que o form Filho será instanciado em tempo de execução. Para que tudo funcione perfeitamente no form Filho, devemos implementar os métodos herdados e informar a palavra chave <b>inherited</b>. No nosso caso precisamos implementar apenas os método dos eventos <b>OnShow</b> e <b>OnClose</b>, como mostra o código abaixo.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">procedure TfrmCidade.FormShow(Sender: TObject);
begin
inherited
end;
procedure TfrmCidade.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
inherited
end;
</pre><br />
Para testar nosso demo, vamos ao form principal. Coloque um botão e escreva o seguinte código no evento <b>OnClick</b>.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">if TfrmCidade(Application.FindComponent('frmCidade')) = nil then
frmCidade := TfrmCidade.Create(Application);
frmCidade.Query := dmDados.queCidade;
frmCidade.Show;
</pre><br />
Estamos supondo que o nome do form Filho é <i>frmCidade</i>, que o nome do <b>Data Module</b> é <i>dmDados</i> e que a <b>TZQuery</b> no <b>Data Module</b> chama-se <i>queCidade</i>. Pronto você pode executar o programa e pressionar o botão. Você terá uma tela assim:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0RpyM56ojCu2YyDFOwsfzJD-oBPRid75AJOs1E-8hKGPN5-hCLSQK1_HZlX3EER_u9Eii9DtaOvopA8YFT0QDFbvVKzqlW0Gwq0a91yFC8V-VGPbx3K1quZc-MGlmIO7Bki23/s1600/heranca.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="178" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0RpyM56ojCu2YyDFOwsfzJD-oBPRid75AJOs1E-8hKGPN5-hCLSQK1_HZlX3EER_u9Eii9DtaOvopA8YFT0QDFbvVKzqlW0Gwq0a91yFC8V-VGPbx3K1quZc-MGlmIO7Bki23/s320/heranca.jpg" width="320" /></a></div><br />
<br />
Você pode agora repetir esse procedimento para todas as tabelas que precisem de formulários de cadastro. Bem, certamente não é um form de cadastro perfeito, pois todos os campos são definidos com <b>TDBEdit</b>, mas a partir daqui você pode tentar vôos mais altos.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com2tag:blogger.com,1999:blog-33774862.post-45936946448219618802010-09-27T20:04:00.008-04:002010-09-28T17:09:29.197-04:00Lazarus - AutoCommit no ZeosLib com PostgreSQLPor padrão, o PostgreSQL trata cada comando SQL como sendo executado dentro de uma transação. Ou seja, cada comando DML (INSERT, UPDATE ou DELETE) tem um comando de início de transação (BEGIN) e um comando COMMIT – caso seja bem sucedido – executados implicitamente antes e depois. Para a execução de múltiplos comandos DML isso leva a um <i>overhead</i>. Desta forma, sugere-se fortemente envolver todos os comandos DML em uma única transação – se a lógica da sua aplicação permitir. Para demonstrar esta recomendação fizemos um teste simples. Escrevemos um pequeno programa para inserir 5.000 linhas em uma tabela. Primeiro fizemos o teste com o controle de transação padrão - cada uma das 5.000 linhas tem seu próprio BEGIN e COMMIT - e depois modificamos o código para controlar a transação manualmente. Neste último teste todas as 5.000 linhas são inseridas dentro de uma única transação.<br />
Para nosso teste usamos ZeosLib. Por padrão o ZeosLib também opera no modo Auto-Commit, ou seja, cada comando é executado no contexto de uma transação. Não mostraremos aqui como conectar ao PG usando Zeos, pois isso já foi apresentado no post <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-postgresql-com.html">Lazarus - Conectando PostgreSQL com ZeosLib</a>. Vejamos o primeiro teste. A unit <b>Dateutils</b> deve ser incluida na cláusula <b>uses</b> para poder usar a função <br />
<b>MilliSecondsBetween()</b>. <i>dbBanco</i> é um <b>ZConnection</b>, <i>dmDados</i> é um <b>Data Module</b> e <i>queCidade</i> uma <b>ZQuery</b>.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">var
i: integer;
a, b: TDateTime;
begin
dmDados.queCidade.SQL.Clear;
dmDados.queCidade.SQL.Add('insert into cidade values (:id, :nome)');
a := time;
for i := 1 to 5000 do
begin
dmDados.queCidade.ParamByName('ID').Value:= i;
dmDados.queCidade.ParamByName('NOME').Value:='SANTAREM';
dmDados.queCidade.ExecSql;
end;
b := time;
ShowMessage(IntToStr(MilliSecondsBetween(b,a)));
end;
</pre><br />
Neste primeiro código o tempo médio de inserção das 5.000 linhas foi de 11,6 segundos. Alteramos então nosso código para que todas as linhas fossem inseridas dentro de uma única transação. Para isso chamamos <b>StartTransaction</b> antes de iniciar os <b>INSERT</b>s. Observe o código abaixo.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">var
i: integer;
a, b: TDateTime;
begin
a := time;
dmDados.queCidade.SQL.Clear;
dmDados.queCidade.SQL.Add('insert into cidade values (:id, :nome)');
dmDados.dbBanco.StartTransaction;
for i := 1 to 5000 do
begin
dmDados.queCidade.ParamByName('ID').Value:= i;
dmDados.queCidade.ParamByName('NOME').Value:='SANTAREM';
dmDados.queCidade.ExecSql;
end;
dmDados.dbBanco.Commit;
b := time;
ShowMessage(IntToStr(MilliSecondsBetween(b,a)));
end;
</pre><br />
Neste caso o tempo médio de execução do código foi de 2,9 segundos. Um ganho de tempo considerável em relação à execução em modo padrão.<br />
Fizemos também um teste usando <b>TZUpdateSQL</b>, implementado de acordo com o post citado acima. O código é apresentado em seguida e o tempo médio de execução foi de 3,8 segundos. Um desempenho um pouco pior do que o teste anterior.<br />
<br />
<pre class="brush: pascal" xml:space="preserve">var
i: integer;
a, b: TDateTime;
begin
a := time;
dmDados.queCidade.Open;
dmDados.dbBanco.StartTransaction;
for i := 1 to 5000 do
begin
dmDados.queCidade.Insert;
dmDados.queCidade.FieldByName('ID').Value := i;
dmDados.queCidade.FieldByName('NOME').Value:='SANTAREM';
dmDados.queCidade.Post;;
end;
dmDados.dbBanco.Commit;
b := time;
ShowMessage(IntToStr(MilliSecondsBetween(b,a)));
end;
</pre><br />
Estes teste foram feitos em Windows e servidor de BD e cliente rodando na mesma máquina. Certamente se você executar esses testes em outro ambiente, os tempos serão diferentes, mas comparativamente você deverá chegar à mesma conclusão.<br />
Sabe-se que uma falha no sistema, enquanto uma transação estiver ativa, causa a execução de um ROLLBACK pelo SGBD, fazendo com que todas as atualizações feitas a partir do BEGIN sejam canceladas. Portanto, use esta recomendação com cautela e bom senso. Longas transações ativas estão sujeitas a perdas de dados muito maiores que transações curtas, em caso de falhas no sistema.<br />
<br />
<div style="color: white;"><span style="background-color: red;">Atualizado em 28/09/2010.</span></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com13tag:blogger.com,1999:blog-33774862.post-68251207603900711622010-08-18T15:03:00.002-04:002010-08-27T17:12:15.223-04:00Lazarus - Aplicação WinCE usando tabelas DBFHá algum tempo eu escrevi um artigo aqui no blog chamado <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-criando-uma-aplicacao-para.html">Lazarus - Criando uma aplicação para WinCE</a>. Nesse artigo usei SQLite para WinCE. E a implementação tinha bastante código pois usava a unit <b>sqlite3ds</b>. Agora vou mostrar que é possível desenvolver usando tabelas Dbase, aquelas que tem a extensão DBF. Para isso vamos usar o componente <b>TDbf</b> da aba <b>Data Access</b>. A seguir os passos necessários:<br />
<br />
1) Crie uma tabela Dbase.<br />
2) Inicie uma nova aplicação e coloque um <b>TDbf</b> no <b>DataModule</b>. Na propriedade <b>TableName</b> localize a tabela que foi criada.<br />
3) Nas propriedades <b>FilePath</b> e <b>FilePathFull</b> ele vai automaticamente definir o caminho do PC onde está a tabela. Depois vamos resolver isso.<br />
4) Coloque um <b>TDataSource</b> no <b>Data Module</b> e faça a associação necessária com o <b>TDbf</b>.<br />
5) Agora vamos ao form da interface e coloque os controles (da aba <b>Data Controls</b>) necessários para cada campo da tabela. Associe a propriedade <b>DataSource</b> de cada controle com o <b>DataSource </b>inserido no passo 4. Na propriedade <b>DataField</b> você pode digitar o nome do campo da tabela DBF ou, se a tabela estiver ativa, selecionar na caixa combinada. Lembre que neste form deve ser incluida a linha <b>uses</b> referente a <i>unit</i> do <b>Data Module</b>.<br />
6) Coloque um <b>TDBNavigator</b> e ligue a propriedade <b>DataSource</b> adequadamente.<br />
7) No evento <b>OnShow</b> do form digite o seguinte:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">dbf1.FilePath := '';</div><div style="font-family: "Courier New",Courier,monospace;">dbf1.FilePathFull := '';</div><span style="font-family: "Courier New",Courier,monospace;">dbf1.Open;</span><br />
<br />
Se você tiver mudado a propriedade <b>Name</b> do <b>TDbf</b>, substitua o <i>dbf1</i> no código acima pelo nome que você escolheu. <br />
Para compilar um projeto WinCE é necessário fazer algumas configurações em <b>Project -> Project options</b>. Na opção <b>Paths</b> abaixo de <b>Compiler Options</b> selecione <i>wince</i> em <b>LCL Widget Type (various)</b>. Na opção <b>Code generation</b> escolha <i>WinCE</i> em <b>Target OS (-T)</b> e <i>arm</i> em <b>Target CPU family (-P)</b>. Pronto. O compilador irá gerar um executável que executa apenas no PDA. Dessa forma para compilar use sempre <b>CTRL + F9</b>. Nos testes eu usei o <b>Lazarus 0.9.29</b>. Se você utiliza a versão <b>0.9.28</b> o caminho para essas configurações está em <b>Project -> Compiler options</b>.<br />
Copie o executável e a tabela para o PDA e execute. Pronto, simples assim. Fiz testes com sucesso em um PDA com WM 5 e no emulador WM 6.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com14tag:blogger.com,1999:blog-33774862.post-51997387437915723962010-07-09T22:29:00.008-04:002010-07-10T21:39:51.589-04:00Lazarus - Relatório Mestre detalhe com LazReportNeste post iremos mostrar como criar um relatório mestre detalhe usando o componente LazReport. No artigo <a href="http://professorcarlos.blogspot.com/2010/04/lazarus-criando-relatorios-com.html">Lazarus - Criando relatórios com FortesReport (Parte I)</a> mostramos como instalar o LazReport. Para o exemplo que será criado aqui usaremos o banco de dados Firebird e o conjunto de componentes ZeosLib. Use o seguinte <a href="http://sites.google.com/site/carlosctrl/documentos-1/script.sql?attredirects=0&d=1">script</a> para criar as tabelas.<br />
<br />
<b>O Data Module</b><br />
<br />
Inicie uma aplicação no Lazarus e insira um <b>Data Module</b>. Selecione a aba <b>Zeos Access</b> e coloque um <b>TZConnection</b> no <b>Data Module</b>. Defina as propriedades da seguinte forma:<br />
<br />
<b>Database</b> - informe o banco de dados Firebird que foi criado.<br />
<b>Name</b> - dê um nome ao componente. Por exemplo: <i>dbVendas</i>.<br />
<b>Password</b> - <i>masterkey</i>.<br />
<b>Protocol</b> - <i>firebird-2.0</i> ou a versão que está sendo usada.<br />
<b>User</b> - <i>sysdba</i>.<br />
<br />
Mude Connected para <i>true</i>, para verificar se a conexão está configurada corretamente.<br />
Coloque um <b>TZReadOnlyQuery</b> e defina:<br />
<br />
<b>Connection</b> - selecione o <b>TZConnection</b>.<br />
<b>Name</b> - defina um nome para o componente. Por exemplo: <i>queVenda</i>.<br />
<b>SQL</b> - <i>select a.id_venda, a.data_venda, b.nome from venda a, cliente b where a.id_cliente = b.id_cliente</i>.<br />
<br />
Selecione a aba <b>Data Access</b> e coloque um <b>TDataSource</b>, onde <b>DataSet</b> deve estar associado à Query anterior. Defina <b>Name</b> como <i>dsVenda</i>.<br />
<br />
Coloque um segundo <b>TZReadOnlyQuery</b>, defina <b>Connection</b> da mesma maneira e em <b>Name</b> digite <i>queItem</i>, por exemplo. Na propriedade <b>SQL</b> informe <i>select a.id_produto, b.nome, a.quantidade, b.preco_venda, a.quantidade * b.preco_venda total from item a, produto b where a.id_produto = b.id_produto and id_venda = :id_venda</i>.<br />
<br />
Defina a propriedade <b>DataSource</b> desta Query com <i>dsVenda</i>. Isto, juntamente com o parâmetro :<i>id_venda</i> definem o relacionamento mestre detalhe entre as duas Queries. O parâmetro <i>:id_venda</i> é definido por <i>queVenda</i> através de <i>dsVenda</i>.<br />
<br />
Coloque mais um <b>TDataSource</b> e defina a propriedade <b>DataSet</b> com a Query <i>queItem</i>. Defina <b>Name</b> como <i>dsItem</i>. Salve o <b>Data Module</b> e chame a unit de <i>u_dmdados</i>. Leia mais para conexão com Firebird em <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-firebird.html">Lazarus - Conectando Firebird com SQLdb ou ZeosLib</a>.<br />
<br />
<b>O relatório</b><br />
<br />
No form onde será criado o relatório digite logo abaixo de <b>Implementation</b> a linha <i>uses u_dmdados</i>. Localize a aba <b>LazReport</b> e coloque um <b>TfrDBDataSet</b> e defina sua propriedade <b>DataSource</b> como <i>dsVenda</i>, e na propriedade <b>Name</b> digite <i>frDBVenda</i>. Coloque outro <b>TfrDBDataSet</b> e defina sua propriedade <b>DataSource</b> como <i>dsItem</i>, e na propriedade <b>Name</b> digite <i>frDBVenda</i>. Coloque um <b>TfrReport</b> e, na propriedade <b>DataSet</b> informe <i>frDBVenda</i>. Agora coloque um <b>TfrDesigner</b>. Dê um duplo clique no <b>frReport</b>. A seguinte tela deverá aparecer:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMF_FW2bdWR0nKEY7xmK617KeD8rKOyFsCvUjD3YolLFVi9cQWaSHMpLilnzfCeyPx-4oAmOnoVordhgY9QFKeauonmTGvRzm0PgcRJfz8aiJMnzKiavyVlYvf3EtGs5tBILbd/s1600/desginer_fr.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMF_FW2bdWR0nKEY7xmK617KeD8rKOyFsCvUjD3YolLFVi9cQWaSHMpLilnzfCeyPx-4oAmOnoVordhgY9QFKeauonmTGvRzm0PgcRJfz8aiJMnzKiavyVlYvf3EtGs5tBILbd/s400/desginer_fr.jpg" width="400" /></a></div><br />
Este é o designer do <b>LazReport</b>. Insira uma banda e escolha o tipo <b>Page Header</b>. Coloque um objeto <b>Text</b> e informe o título do cabeçalho, por exemplo, <i>Relação de Vendas</i>. Escolha um tamanho de fonte e centralize o objeto adequadamente na banda.<br />
Insira nova banda e escolha o tipo <b>Master Data</b>. Ele vai abrir uma janela solicitando a escolha de um <b>DataSet</b>. Escolha <i>frDBVenda</i>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzr9OR1xjvheFe-j28cERX5DNfrpqGo6y8ig-zwbXWjd1iCEXJlm4JfSxGKza2J6jM58BQMajIsfJvAd_4JowLY4YPK7BBcnvz-rdLQCEuxBlVqwAQKUE0vl6MKcU5xLzMqsp/s1600/masterdate.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="78" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguzr9OR1xjvheFe-j28cERX5DNfrpqGo6y8ig-zwbXWjd1iCEXJlm4JfSxGKza2J6jM58BQMajIsfJvAd_4JowLY4YPK7BBcnvz-rdLQCEuxBlVqwAQKUE0vl6MKcU5xLzMqsp/s400/masterdate.jpg" width="400" /></a></div><br />
Insira objetos <b>Text</b> de forma que a banda fique como na figura acima. Em um objeto <b>Text</b> é possível digitar um texto, informar uma variável ou um campo de tabela. Do <b>DataSet</b> <i>frDBVenda</i>, informamos o <i>ID</i>, a <i>DATA</i> e o <i>NOME</i> do cliente. Os objetos restantes são todos textos.<br />
Insira outra banda e escolha o tipo <b>Detail Data</b>. Escolha o <b>DataSet</b> <i>frDBItem</i>. Coloque cinco objetos <b>Text</b> e informe os campos <i>ID_PRODUTO, NOME, QUANTIDADE, PRECO_VENDA</i> e <i>TOTAL</i>. Para formatar <i>PRECO_VENDA</i> e <i>TOTAL</i> informe <b>Text</b> da seguinte forma:<br />
<br />
[dmDados.zqItem."PRECO_VENDA" #N##,##0.00]<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEQi7lBkk2iZyXEv4J5f7y0Xr2gMLndhCkvUtK8Wt-P2vT5d3S-CGhdZp8981IbqhKsAGmcl1dNaR_ao6NMheGniJ2vgFmEY5pTcRr3L5qzikKfwm781IINzAUdG27ZictXXoc/s1600/detaildata.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEQi7lBkk2iZyXEv4J5f7y0Xr2gMLndhCkvUtK8Wt-P2vT5d3S-CGhdZp8981IbqhKsAGmcl1dNaR_ao6NMheGniJ2vgFmEY5pTcRr3L5qzikKfwm781IINzAUdG27ZictXXoc/s400/detaildata.jpg" width="400" /></a></div><br />
Insira nova banda e selecione o tipo <b>Detail Footer</b>. Coloque dois objetos <b>Text</b>. Em um deles informe <i>Total da venda</i>: No segundo digite:<br />
<br />
[SUM([dmDados.zqItem."TOTAL"]) #N##,##0.00]<br />
<br />
Esse campo somará o total da venda e o mostrará formatado. Salve o relatório. Dê a ele o nome <i>venda.lrf</i>, por exemplo. Feche e volte ao form. Coloque dois botões. Em um deles digite <i>Editar</i> no <b>Caption</b>. Dê um duplo clique nele e digite no editor de código:<br />
<br />
<span style="font-family: Courier New;">frVenda.LoadFromFile('vendas.lrf');<br />
frVenda.DesignReport;</span><br />
<br />
Esse botão permitirá alterar o desenho do relatório. No segundo botão digite <i>Preview</i> no <b>Caption</b>. Dê um duplo clique e digite no editor de código:<br />
<br />
<span style="font-family: Courier New;">frVenda.LoadFromFile('vendas.lrf');<br />
frVenda.ShowReport;</span><br />
<br />
Este é o botão que visualizará o relatório na tela, conforme mostra a figura a seguir:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSdE1rOqtAyojaRaZHhGTAQzeQgBadV0nlEyuN7Y7FC36zSHnCjji44rXCq94TZISq_TP4AjBmohVtfjuD0DfICZwJlmu7DpSP0fDKzA4k4BLGZil2U4AX92nagD23tVsO-Gg-/s1600/lazreport.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjSdE1rOqtAyojaRaZHhGTAQzeQgBadV0nlEyuN7Y7FC36zSHnCjji44rXCq94TZISq_TP4AjBmohVtfjuD0DfICZwJlmu7DpSP0fDKzA4k4BLGZil2U4AX92nagD23tVsO-Gg-/s400/lazreport.jpg" width="400" /></a></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com1tag:blogger.com,1999:blog-33774862.post-85939193838050205402010-06-23T20:31:00.006-04:002010-06-24T23:08:00.985-04:00Lazarus - Dicas de LazReportNeste post vou apresentar algumas dicas para criar relatórios com mais eficiência em LazReport. No post <a href="http://professorcarlos.blogspot.com/2010/04/lazarus-criando-relatorios-com.html">Lazarus - Criando relatórios com FortesReport (Parte I)</a> eu mostrei como instalar o LazReport e o link para um tutorial que ensina passo a passo como criar um relatório.<br />
<br />
<b>Exportando um relatório para PDF</b><br />
<br />
Esse é um procedimento bastante simples, mas é necessário instalar dois pacotes. Para exportar um relatório para PDF você precisa do <b>LazReportPDFExport</b>. Este componente está em <i>source\addons\pdfexport</i> no mesmo diretório do LazReport. Mas este componente depende do <b>PowerPDF</b>. Você pode fazer o download do pacote <b>PowerPDF</b> no <a href="http://sourceforge.net/projects/lazarus-ccr/files/">repositório de componentes e código Lazarus</a>. Instale o <b>PowerPDF</b> e depois o <b>LazReportPDFExport</b>. O <b>PowerPDF</b> irá aparecer em uma nova aba de componentes e o <b>LazReportPDFExport</b> será um novo componente -<b>TfrTNPDFExport</b> - na aba do LazReport.<br />
Supondo que você já criou o relatório, coloque um <b>TfrTNPDFExport</b> no mesmo form onde está o <b>TfrReport</b>. Execute o seu programa e visualize o relatório. Clique no botão <b>Save report</b>. Clique na caixa <b>Tipo</b> e deve aparecer a opção <i>Adobe Acrobat PDF (*.pdf)</i>. Selecione esta opção, dê um nome ao arquivo e pressione o botão <b>Salvar</b>. Agora você tem um arquivo pdf com o seu relatório. Também existem componentes que permitem você exportar para HTML ou CSV.<br />
<br />
<b>Object Inspector</b><br />
<br />
Semelhante ao <b>Object Inspector</b> do Lazarus, com ele podemos manipular propriedades de alguns objetos, tais como: nome, posição, tamanho e visibilidade. No LazReport ele é tratado como uma <b>ToolBar</b>. Pode ser mostrado ou ocultado. Para mostrar a janela do <b>Object Inspector</b> selecione <b>Tools -> ToolBars -> Object Inspector</b>. Depois simplesmente selecione um objeto no relatório para visualizar/alterar suas propriedades.<br />
<br />
<b>Destacando objetos</b><br />
<br />
Em certos relatórios pode ser necessário mudar a cor da fonte e/ou do fundo de objetos, baseado em certas condições. Para isso selecione o objeto alvo e pressione o botão <b>Highlight attributes</b> na barra de ferramentas de formatação de texto, como mostra a figura abaixo.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG92qOhsT-tIawAZAxJyTDYda12k0GSifOnnapJUi5WiWMBzlCdhUl8KsZU00n8kWXADOoaUOyTTBoYKOUcq6vSAwUYvrEQ-y-tZ8qG2NJFLU7kXKsdWxO-OS_MkUrZZ3U_len/s1600/toolbar_lazreport.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="76" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjG92qOhsT-tIawAZAxJyTDYda12k0GSifOnnapJUi5WiWMBzlCdhUl8KsZU00n8kWXADOoaUOyTTBoYKOUcq6vSAwUYvrEQ-y-tZ8qG2NJFLU7kXKsdWxO-OS_MkUrZZ3U_len/s400/toolbar_lazreport.jpg" width="400" /></a></div><br />
Vamos supor que tenhamos um relatório de vendas mensais efetuadas pelos vendedores de uma loja e que a meta para aquele mês seja 10.000 reais. Então, queremos que os valores abaixo de 10.000 apareçam com fonte em vermelho. Na caixa de texto <b>Condition</b> da janela <b>Highlight attributes</b> informe <i>Value < 10000</i>. Selecione a cor da fonte e/ou a cor de fundo e pressione o botão <b>OK</b>. Veja a figura seguinte. Agora o relatório irá mostrar os valores de venda menores que 10.000 em vermelho. Condições mais complexas podem ser criadas usando o recurso de script que será apresentado mais adiante.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWZjVwkWc9ogQXmSNCeDlHG1JUy3hMz1QbrcSZsMNPhbJDHqcMWH1Gm_yZa4H2Qp56DwsmlT2q_8yJ1jjkyac70g4yAgmiLU7W-1VWaaZe16zrUsZI-iNYblkhVgQjUeyUgVnV/s1600/tela_highlight.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWZjVwkWc9ogQXmSNCeDlHG1JUy3hMz1QbrcSZsMNPhbJDHqcMWH1Gm_yZa4H2Qp56DwsmlT2q_8yJ1jjkyac70g4yAgmiLU7W-1VWaaZe16zrUsZI-iNYblkhVgQjUeyUgVnV/s320/tela_highlight.jpg" /></a></div><br />
<b>Programando eventos</b><br />
<br />
Em certos casos pode ser necessário imprimir dados que não estão em bancos de dados. Uma opção é usar os eventos do componentes <b>TfrReport</b>. Dois desses eventos são <b>OnGetValue</b> e <b>OnEnterRect</b>. <b>OnGetValue</b> ocorre toda vez que um objeto <b>Text</b> encontra uma variável e precisa atribuir um valor a ela. Se a variável não possuir um valor então esse valor é definido através de código, por exemplo:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">procedure TForm1.frReport1GetValue(const ParName: String; var ParValue: Variant</span><span style="font-family: "Courier New",Courier,monospace;">);</span><br />
<span style="font-family: "Courier New",Courier,monospace;">begin</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> if ParName = 'Variavel1' then</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> ParValue := 100</span>;<br />
<span style="font-family: "Courier New",Courier,monospace;"></span><span style="font-family: "Courier New",Courier,monospace;">end;</span><br />
<br />
Onde <b>ParName</b> tem o nome da variável como string e <b>ParValue</b> recebe o valor dessa variável. Por sua vez o evento <b>OnEnterRect</b> acontece antes que um objeto seja desenhado. Podemos, por exemplo, imprimir um dado bem específico em uma linha ou coluna do relatório.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">procedure TForm1.frReport1EnterRect(Memo: TStringList; View: TfrView);<br />
begin<br />
if (FCol=3)and(FRow=3) then<br />
view.Memo.Text := 'ALO';<br />
end;</div><br />
<b>FCol</b> e <b>FRow</b> definem uma coluna e uma linha do relatório respectivamente. No exemplo será impressa a palava <i>ALO</i> na linha 3 e coluna 3.<br />
<br />
<b>Programando um script</b><br />
<br />
LazReport possui um interpretador interno semelhante ao Pascal que tem as seguintes características:<br />
<br />
<ul><li>Operador de atribuição (:=);</li>
<li>Estruturas <i>if ... then ... else</i>, <i>while ... do</i> e <i>repeat ... until</i>;</li>
<li>Delimitadores de blocos <i>begin</i> e <i>end</i>;</li>
<li>Variávies não tipadas;</li>
<li>Acesso aos objetos do LazReport e suas propriedades.</li>
</ul>Sempre que um objeto ou banda for impresso, o script associado a ele é executado. O editor de script é acessível no editor memo sempre que a caixa <b>Script</b> estiver marcada. Para visualizar o editor memo de um objeto como <b>Text</b>, por exemplo, basta dar um duplo clique nele. Em uma banda tecle <b>CTRL + ENTER</b>. Veja o editor memo abaixo com o editor de script habilitado.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbzUzP-g8mHlz8XHEedOt-VfJnxX2kVh1uQJVzFwZf94lw0CWzc4jAAZ3opOne7Kn7yiZMeVAV92oQJH9c7y26Mdbq_UV0MKIhjV3DeR5kI1zu8_c2otIW5a1HDwHBXWRx29cM/s1600/editortext.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbzUzP-g8mHlz8XHEedOt-VfJnxX2kVh1uQJVzFwZf94lw0CWzc4jAAZ3opOne7Kn7yiZMeVAV92oQJH9c7y26Mdbq_UV0MKIhjV3DeR5kI1zu8_c2otIW5a1HDwHBXWRx29cM/s320/editortext.jpg" /></a></div><br />
Algumas propriedades de objetos visuais que podem ser usadas nos scripts são:<br />
<br />
<b>Visible</b> - determina a visibilidade do objeto (boolean);<br />
<b>FillColor</b> - determina a cor de fundo do objeto. Valores possíveis: <i>clRed</i>, <i>clBlue</i>, etc.;<br />
<b>Text</b> - conteúdo do memo;<br />
<br />
Objetos <b>Text</b> tem também as seguintes propriedades:<br />
<br />
<b>FontName</b>, <b>FontSize</b>, <b>FontColor</b> - nome, tamanho e cor da fonte;<br />
<b>FontStyle</b> - estilo da fonte (<i>1</i> - itálico, <i>2</i> - negrito e <i>3</i> - sublinhado);<br />
<b>Adjust</b> - alinhamento do texto (<i>1</i> - direita, <i>2</i> - centro).<br />
<br />
Por exemplo, voltando ao nosso relatório de vendas, vamos supor que queremos imprimir em verde os valores acima do dobro da meta, em vermelho os valores abaixo da meta e em azul os demais. O código ficaria como abaixo, supondo que o valor seja dado por [TotalVendas]:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">if [TotalVendas] < 10000 then </div><div style="font-family: "Courier New",Courier,monospace;"> FontColor := clGreen </div><div style="font-family: "Courier New",Courier,monospace;">else if [TotalVendas] < 20000 then </div><div style="font-family: "Courier New",Courier,monospace;"> FontColor := clBlue </div><div style="font-family: "Courier New",Courier,monospace;">else </div><div style="font-family: "Courier New",Courier,monospace;"> FontColor := clRed;</div><br />
Vamos continuar explorando os recursos do LazReport. No próximo post vamos mostrar como criar um relatório mestre-detalhe.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com6tag:blogger.com,1999:blog-33774862.post-15121312010177569302010-06-13T11:13:00.002-04:002010-06-13T11:21:44.747-04:00Java - Strings, memória e imutabilidadeO entendimento sobre <b>pilha</b> e <b>heap</b> pode facilitar em muuito a compreensão de temas como passagem de parâmetros, polimorfismo, garbage collector, etc. Mas neste post darei apenas uma rápida visão para poder falar o assunto principal que é a forma como Java trata os objetos <b>String</b>.<br />
Em geral, variáveis de instância, objetos e arrays - que também são objetos - residem no <b>heap</b>. Já as variáveis locais, tanto de tipos primitivos quanto as referências, residem na <b>pilha</b>.<br />
Sabemos que uma <b>String</b> pode ser instanciada de várias maneiras, como nestes exemplos:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">String s = new String("abcd"); // ou</div><div style="font-family: "Courier New",Courier,monospace;">s = "abcd";</div><br />
Para que o uso da memória seja mais eficiente em Java, a JVM mantém uma área especial de memória chamada <b>pool de Strings constantes</b>. Quando o compilador encontra um literal <b>String</b>, ele verifica se existe uma <b>String</b> idêntica no <b>pool</b>. Se existir, a referência ao novo literal é direcionada à <b>String</b> existente e não é criado novo objeto <b>String</b>. Mas quando um objeto <b>String</b> é criado usando <b>new</b>, por exemplo:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">String s = new String("abc"));</div><br />
Esse novo objeto é criado no <b>heap</b> - a memória onde residem todos os objetos em Java - e "abc" é inserida no <b>pool de Strings constantes</b>, se não existir.. Além disso, as <b>Strings</b> são imutáveis. Por exemplo:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> String s = "abc";</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> s.concat("def"); // concatena o argumento ("def") à String "abc"</span><br />
<br />
Nesse momento Java cria uma nova <b>String</b> com o valor "abcdef", mas ela fica perdida na memória, pois a variável <i>s</i> não muda seu valor e continua valendo "abc". No entanto se a segunda linha for alterada para:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> s = s.concat("def");</span><br />
<br />
Então <i>s</i> passará a valer "abcdef". A variável <i>s</i> será uma nova <b>String</b>. A <b>String</b> "abc" fica perdida na memória. Ou seja, se o resultado da expressão não for atribuido a uma variável seu valor será perdido. Analise esse código:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> String s1 = "abc";</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> String s2 = "abc";</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> String s3 = "abc";</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> s3 = s3.concat("def");</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> System.out.println(s1 + " " + s2 + " " + s3);</span><br />
<br />
Inicialmente as <b>Strings</b> <i>s1</i>,<i> s2</i>,<i> s3</i> referem-se ao mesmo objeto no <b>pool</b>, pelo que foi exposto acima. No entanto, diferente do que possamos pensar, quando criamos um novo objeto e o referenciamos com <i>s3</i>, os valores de <i>s1</i> e <i>s2</i> não se alteram pelo princípio da imutabilidade.<br />
A classe <b>StringBuffer</b> se comporta de forma diferente. Ela não é imutável.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> String sb1 = new StringBuffer("abc");</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> String sb2 = </span><span style="font-family: "Courier New",Courier,monospace;">new StringBuffer(</span><span style="font-family: "Courier New",Courier,monospace;">"abc");</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> String sb3 = </span><span style="font-family: "Courier New",Courier,monospace;">new StringBuffer(</span><span style="font-family: "Courier New",Courier,monospace;">"abc");</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sb3.concat("def");</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> System.out.println(sb1 + " " + sb2 + " " + sb3);</span><br />
<br />
<br />
Mesmo o código acima produzindo o mesmo resultado do código usando <b>String</b>, a explicação é que <i>sb1</i>, <i>sb2</i> e <i>sb3</i> são três objetos diferentes. Observe que este código produz algo diferente, pois agora só existe um objeto e três referências:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">StringBuffer sb1 = new StringBuffer("abc");</span><br />
<span style="font-family: "Courier New",Courier,monospace;">StringBuffer sb2 = sb1;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">StringBuffer sb3 = sb2;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">sb3.append("def");</span><br />
<span style="font-family: "Courier New",Courier,monospace;">System.out.println(sb1 + " " + sb2 + " " + sb3);</span><br />
<br />
Espero que o comportamento de <b>Strings</b> em Java tenha ficado mais claro para você. Leia mais sobre strings no <a href="http://java.sun.com/docs/books/tutorial/java/data/strings.html">tutorial sobre strings no site da Sun</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com0tag:blogger.com,1999:blog-33774862.post-38288841108997676752010-06-07T19:24:00.007-04:002010-06-13T12:00:15.224-04:00Lazarus - Conectando Oracle com SQLdb ou ZeosLibA Oracle oferece uma versão free do Oracle Database 10g. É o <a href="http://www.oracle.com/technology/products/database/xe/index.html">Oracle Database 10g Express Edition</a>. Utilizamos esta versão neste artigo. Além disso, utilizamos a versão 0.9.29 do Lazarus, Free Pascal 2.4.1 e ZeosLib 7.0.0.<br />
Para os testes usamos o usuário do Oracle <b>hr</b>, que é criado em uma nova instalação. Depois de instalado o banco de dados, o usuário <b>hr</b> deve ser desbloqueado pelo DBA e definida uma senha. Esse usuário tem acesso às tabelas do schema <b>hr</b>, também instalado junto com o banco. No entanto criamos uma nova tabela para os testes, de forma a manter as tabelas originais inalteradas. Criamos então nossa famosa tabela CIDADE.<br />
<br />
<pre class="code">CREATE TABLE "CIDADE"
( "ID_CIDADE" NUMBER NOT NULL ENABLE,
"NOME" VARCHAR2(40),
CONSTRAINT "CIDADE_PK" PRIMARY KEY ("ID_CIDADE") ENABLE
)</pre><br />
Existe ferramenta de administração visual na instalação do Oracle, mas não é objetivo deste artigo expor a utilização da mesma.<br />
<br />
<b>Conexão com SQLdb</b><br />
<br />
Para fazer a conexão vamos usar como sempre um <b>Data Module</b> onde os componentes de banco de dados serão colocados.<br />
<br />
Localize na aba <b>SQLdb</b> o componente <b>TOracleConnection</b> e coloque no <b>Data Module</b>. Defina suas propriedades como segue:<br />
<br />
<b>DatabaseName</b> - informe aqui o SID do banco de dados. No nosso caso é <i>XE</i>, o SID do Oracle Database Express Edition.<br />
<b>Hostname</b> - informe o nome ou IP da máquina onde está o servidor do banco de dados. Como meu teste foi feito na máquina onde está o servidor, eu informei <i>localhost</i>, ou poderia ter informado <i>127.0.0.1</i>.<br />
<b>Password</b> - informe a senha do usuário <i>hr</i>. Ou de qualquer usuário com acesso ao banco de dados.<br />
<b>UserName</b> - informe <i>hr</i>, ou outro usuário com acesso ao banco de dados.<br />
Para fazer um teste na conexão, mude a propriedade <b>Connected</b> para <i>True</i>. Depois volte para <i>False</i>. <br />
<br />
Coloque um <b>TSQLTransaction</b> e defina a propriedade <b>Database</b> com o nome do <b>TOracleConnection</b> que foi colocado anteriormente.<br />
<br />
Coloque um <b>TSQLQuery</b>. Defina suas propriedades como mostrado a seguir:<br />
<br />
<b>Database</b> - selecione o <b>TOracleConnection</b> anterior.<br />
<b>SQL</b> - informe <i>SELECT * FROM CIDADE</i>.<br />
<br />
Finalize colocando um <b>TDataSource</b> da aba <b>Data Access</b>. Defina a propriedade <b>DataSet</b> com a <b>SQLQuery</b> colocada antes.<br />
No evento <b>AfterPost</b> da <b>TSQLQuery</b> digite o código:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">SQLQuery1.ApplyUpdates;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">SQLTransaction1.CommitRetaining;</span><br />
<br />
No evento <b>AfterDelete</b> selecione o mesmo método para não repetir código.<br />
Pronto. Está feita a configuração de acesso, tanto para leitura quanto para escrita, em uma tabela do Oracle. Crie uma interface seguindo os passos descritos no post <a href="http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-com.html">Lazarus - Acessando banco de dados com SQLdb - Parte I.</a> <br />
Lembre de abrir a conexão. Pode ser no evento <b>OnCreate</b> do <b>Data Module</b>, com o código:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">OracleConnection1.Open;</div><br />
<b>Conexão com ZeosLib</b><br />
<br />
Coloque um <b>TZConnection</b> no <b>Data Module</b>. Defina as propriedades:<br />
<br />
<b>AutoCommit</b> - deixe em <i>True</i> para que as transações no banco sejam comitadas automaticamente.<br />
<b>Database</b> - informe o nome ou IP da máquina do servidor do banco de dados, por exemplo: <i>localhost</i> se estiver na mesma máquina.<br />
<b>HostName</b> - informe o SID do banco de dados. <i>XE</i> no nosso caso. Observe que as propriedades <b>HostName</b> e <b>Database</b> são informadas de forma invertida em relação ao <b>SQLdb</b>.<br />
<b>Password</b> - informe a senha do usuário com acesso ao banco. Neste caso foi usado<i> hr</i>.<br />
<b>Protocol</b> - informe <i>oracle</i> ou <i>oracle-9i</i>. Ambos funcionam.<br />
<b>User</b> - informe o nome do usuário. Neste caso é <i>hr</i>.<br />
<br />
Mude <b>Connected</b> para <i>True</i> para testar a conexão. Depois de conectar com sucesso volte <b>Connected</b> para <i>False</i>.<br />
<br />
Coloque um <b>TZQuery</b> e um <b>TZUpdateSQL</b> e configure-os como foi feito no artigo <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-postgresql-com.html">Lazarus - Conectando PostegreSQL com ZeosLib</a>.<br />
No <b>TZUpdateSQL</b> defina essas propriedades assim:<br />
<br />
<b>DeleteSQL</b> - <i>DELETE FROM CIDADE WHERE ID_CIDADE = :OLD_ID_CIDADE;</i><br />
<b>InsertSQL</b> - <i>INSERT INTO CIDADE VALUES (:ID_CIDADE, :NOME);</i><br />
<b>ModifySQL</b> - <i>UPDATE CIDADE SET NOME = :NOME WHERE ID_CIDADE = :OLD_ID_CIDADE;</i><br />
<br />
<br />
Coloque um <b>TDataSource</b> da aba <b>Data Access</b> e na propriedade <b>DataSet</b> selecione a <b>TZQuery</b> anterior. Está pronta nossa conexão e acesso a uma tabela. Agora crie a interface com nos posts anteriores. Não esqueça de abrir a conexão com o comando:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">ZConnection1.Connect;</div><br />
Pode ser no evento <b>OnCreate</b> do <b>Data Module</b>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com4tag:blogger.com,1999:blog-33774862.post-79120895384772626902010-05-27T22:36:00.003-04:002010-06-08T14:33:17.773-04:00Tipos de dados no SQLiteEm SQLite, diferente de outros motores de banco de dados, o tipo de dado de um valor está associado com o valor propriamente dito, e não com o seu contêiner. É um sistema de tipo dinâmico. Um campo de uma tabela em SQLite pode receber qualquer tipo de dado. Assim, o SQLite simplesmente ignora o tipo informado no comando CREATE TABLE.<br />
Então, dizemos que no SQLite existem classes de armazenamento. E essas classes são:<br />
<br />
<b>NULL</b> - como em qualquer outro banco de dados.<b><br />
INTEGER</b> - inteiro com sinal, armazenado em 1, 2, 3, 4, 6 ou 8 bytes dependendo da grandeza do valor.<br />
<b>REAL</b> - valor de ponto flutuante armazenado em 8 bytes.<br />
<b>TEXT</b> - uma string armazenada usando UTF-8, UTF-16BE ou UTF-16LE.<br />
<b>BLOB</b> - armazena um blob, como indica o nome.<br />
<br />
Uma coluna INTEGER PRIMARY é uma exceção. Só aceita números inteiros. Qualquer valor em um comando SQL tem uma classe de armazenamento implícita. Durante a execução do comando SQL, o SQLite pode converter valores entre classes numéricas (INTEGER e REAL) e TEXT.<br />
<br />
<b>Tipo Boolean</b><br />
<br />
Não existe uma classe Boolean. Pode-se considerar os inteiros 0 (false) e 1 (true).<br />
<br />
<b>Tipos Data e Hora</b><br />
<br />
Não existem classes de armazenamento para armazenar data e/ou hora. Existem funções capazes de tratar TEXT, REAL ou INTEGER como data e hora:<br />
<br />
TEXT - como string ISO8601 ("YYYY-MM-DD HH:MM:SS.SSS").<br />
REAL - como dias Julianos. A origem (dia 0) é o meio dia de 24 de novembro de 4714 A.C., pelo calendário Gregoriano.<br />
INTEGER - como a hora no Unix. A origem é o dia 1º de janeiro de 1970.<br />
<br />
<b>Funções de Data e Hora</b><br />
<br />
São cinco as funções:<br />
<br />
date(timestring, modifier, modifier, ...) - retorna a data no formato YYYY-MM-DD.<br />
time(timestring, modifier, modifier, ...) - retorna a hora no formato HH:MM:SS.<br />
datetime(timestring, modifier, modifier, ...) - retorna data e hora no formato "YYYY-MM-DD HH:MM:SS".<br />
julianday(timestring, modifier, modifier, ...) - retorna do dia Juliano.<br />
strftime(format, timestring, modifier, modifier, ...) - retorna a data formatada de acordo com o formato especificado no primeiro argumento.<br />
<br />
Todas recebem uma string de tempo e 0 ou mais modificadores como argumentos. Uma string de tempo pode ter um dos seguintes formatos, além de outros que podem ser encontrados em <a href="http://www.sqlite.org/lang_datefunc.html">http://www.sqlite.org/lang_datefunc.html</a>:<br />
<br />
YYYY-MM-DD<br />
YYYY-MM-DD HH:MM:SS<br />
HH:MM<br />
HH:MM:SS<br />
now<br />
<br />
O formato 'now' é convertido na data e hora correntes. Por exemplo:<br />
<br />
SELECT date('now'); - calcula da data corrente.<br />
<br />
Os modificadores alteram a string de data e hora. Alguns dos modificadores disponíveis são:<br />
<br />
NNN days<br />
NNN hours<br />
NNN minutes<br />
NNN.NNNN seconds<br />
NNN months<br />
NNN years<br />
start of month<br />
start of year<br />
<br />
Os primeiros seis modificadores simplesmentes adicionam a quantidade de tempo especificada à data e hora especificadas pela string de tempo. Por exemplo:<br />
<br />
SELECT date('now', '+1 days'); - calcula a data corrente mais um dia.<br />
SELECT date('now', 'start of month'); - calcula o primeiro dia do mês corrente.<br />
<br />
O parâmetro formato pode assumir alguns desses valores:<br />
<br />
%d - dia do mês<br />
%H - hora (de 00 a 24)<br />
%J - dia Juliano<br />
%w - dia da semana de 0 a 6 (domingo = 0)<br />
<br />
Por exemplo:<br />
<br />
SELECT strftime('%J', 'now'); - calcula o dia Juliano equivalente à data corrente.<br />
<br />
Este post foi baseado no texto original em inglês em <a href="http://www.sqlite.org/datatype3.html">http://www.sqlite.org/datatype3.html</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com3tag:blogger.com,1999:blog-33774862.post-69714168767494833692010-05-20T23:49:00.003-04:002010-05-23T09:28:44.671-04:00Lazarus - Aplicação embarcada com Firebird e ZeosLibUma aplicação embarcada, ou embutida, com Firebird é uma aplicação que não necessita do servidor de banco de dados para executar. É uma solução excelente para criar demos de programas, criar um catálogo de produtos em CD, entre outras aplicações. Resumidamente, o motor do Firebird embedded está em uma dll.<br />
A versão embedded do Firebird executa apenas em modo local, não reconhecendo nem mesmo <b>localhost</b>. Ela ignora qualquer instância do Firebird executando na mesma máquina. Procure usar sempre o usuário SYSDBA para a conexão com o banco. Como não existe a figura de um servidor de banco de dados, você poder rodar quantas aplicações forem necessárias. Cada uma será uma instância diferente. Tudo depende da memória da máquina.<br />
<br />
<b>Instalação do Firebird</b><br />
<br />
O primeiro passo consiste em fazer o download da versão embarcada do Firebird. Escolha a versão e a plataforma desejada em <a href="http://www.firebirdsql.org/index.php?op=files">http://www.firebirdsql.org/index.php?op=files</a>. Vamos mostrar aqui apenas o procedimento para o ambiente Windows. Você deve baixar a versão <b>embedded</b>. Por exemplo, se optar pela versão 2.1.3, você pode baixar este <a href="http://sourceforge.net/projects/firebird/files/firebird-win32/2.1.3-Release/Firebird-2.1.3.18185-0_Win32_embed.zip/download">zip</a>. Depois disso, crie um diretório (p.ex. <b>C:\MeuPrograma</b>) onde ficará sua aplicação e descompacte o zip que você baixou dentro dele. Esse diretório será o home do Firebird embutido. O banco de dados deve ficar nesse mesmo diretório. Em seguida faça o seguinte:<br />
1) Edite o arquivo firebird.conf e modifique a seguinte linha para ficar assim:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">RootDirectory = C:\MeuPrograma</div><br />
2) Altere o nome do arquivo <b>fbembed.dll</b> para <b>fbclient.dll</b>, se você for usar o <b>ZeosLib</b>. Se for usar o <b>SQLdb</b>, renomeie para <b>gds32.dll</b>.<br />
<br />
Se sua aplicação utilizar <b>UDF</b>s, copie-as para o diretório <b>UDF</b>. <b>Collates</b> e <b>charsets</b> devem ser copiados para o diretório <b>INTL</b>.<br />
<br />
<b>Conectando ao banco de dados com ZeosLib</b><br />
<br />
Coloque um <b>TZConnection</b> no <b>Data Module</b>. Defina as seguintes propriedades assim:<br />
<br />
<b>Database</b> - informe apenas o nome do arquivo do banco de dados.<br />
<b>HostName</b> - deixe em branco.<br />
<b>Name</b> - <i>dbEmbutido</i>, por exemplo. <br />
<b>Password</b> - <i>masterkey</i>.<br />
<b>Protocol</b> - <i>firebird-2.0</i>.<br />
<b>User</b> - <i>sysdba</i>.<br />
<br />
Não tente conectar ao banco em tempo de desenvolvimento. Não irá conectar. Escreva o seguinte código no evento <b>OnCreate</b> do <b>Data Module</b>:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">dbEmbutido.Connect;</div><br />
Os outros procedimentos são exatamente os mesmos de uma conexão normal como mostramos em <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-firebird.html">Lazarus - Conectando Firebird com ZeosLib ou SQLdb</a>. Para construir uma interface leia os posts <a href="http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-com.html">Lazarus - Acessando banco de dados com SQLdb - Parte I</a> e <a href="http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-com_24.html">Parte II</a>.Se preferir usar <b>SQLdb</b> para embarcar sua aplicação siga exatamente o mesmo procedimento do post anterior. Só lembre de renomear <b>fbembed.dll</b> para <b>gds32.dll</b>.<br />
<br />
<div style="color: white;"><span style="background-color: red;">Atualizado em 23/05/2010.</span></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com7tag:blogger.com,1999:blog-33774862.post-51242745723083991522010-05-15T11:59:00.007-04:002010-05-16T09:28:26.935-04:00Lazarus - Criando componentes em run-timeA primeira pergunta que alguém pode fazer é "Por que eu preciso criar componentes em tempo de execução?" Posso dar vários motivos e vou citar apenas dois. Primeiro: suponhamos que você permita que o usuário do seu sistema crie novos campos em um tabela. Para que ele possa usar esses novos campos são necessários novos componentes no form, correto? Segundo: eu quero criar um relatório genérico que possa imprimir dados de qualquer tabela. Apenas em tempo de execução eu irei saber quais e quantos componentes eu irei usar nesses casos. Então vamos à prática. Para nosso exemplo irei criar um botão da classe <b>TButton</b>. Mas poderia ser qualquer componente que você precise criar.<br />
<br />
<b>Criando um TButton em tempo de execução</b> <br />
<br />
A primeira coisa a fazer é declarar uma variável para o botão, por exemplo:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">Botao: TButton;</div><br />
Pode ser necessário incluir a unit <b>StdCtrls</b>. Em seguida escrevemos o código que cria o componente:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">Botao := TButton.Create(nil);</div><br />
O construtor <b>Create</b> espera receber o dono do componente (<b>Owner</b>) como parâmetro. Nesse caso informamos que o Botão não tem dono. Você pode ainda informar <b>Self</b> ou <b>Application</b>. Se for informado um desses dois últimos, o objeto criado será destruído juntamente com o seu dono. No nosso exemplo o objeto deve ser destruído explicitamente usando o método <b>Free</b>.<br />
<br />
Quando um objeto é criado, muitas propriedades recebem valores padrão. Dessa forma precisamos definir pouca coisa mais.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Botao.Parent := Form1;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Botao.Name := 'Botao';</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Botao.Caption :='Ok';</span><br />
<br />
A propriedade <b>Parent</b> informa onde o componente será colocado. Ou seja <b>Parent</b> indica o componente que contém o botão. Se tivermos um <b>TPanel</b> chamado <i>Panel1</i> dentro do <i>Form1</i> e desejarmos inserir o botão nesse painel, só precisamos informar <i>Botao.Parent := Panel1</i>. Podemos definir valores para as propriedades <b>Left</b> e <b>Top</b> do botão. Esses valores são sempre relativos ao <b>Parent</b>. Ambas serão inicializadas com 0, caso não atribuirmos valores para elas.<br />
Se desejarmos definir um método para um evento do componente, é necessário criar o método primeiro. Por exemplo, supondo que queremos programar o evento <i>OnClick</i> do botão:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">procedure TForm1.Clica(Sender: TObject);</div><div style="font-family: "Courier New",Courier,monospace;">begin</div><div style="font-family: "Courier New",Courier,monospace;"> ShowMessage('Componente dinâmico'); </div><div style="font-family: "Courier New",Courier,monospace;">end;</div><br />
Assim, podemos referenciar o método durante a criação do componente com o comando:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">Botao.OnClick := @Clica;</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div>Para liberar a memória quando não precisarmos mais do componente usamos o seguinte comando, que pode ser colocado no evento <i>OnClose</i> do form.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">Botao.Free;</div><div style="font-family: "Courier New",Courier,monospace;"></div><br />
<b>Um novo item de menu </b><br />
<br />
Para incluir um novo item de menu, vamos supor que já exista um <b>TPopupMenu</b> chamado <i>PopupMenu1</i>. Declaramos um novo <b>TMenuItem</b>:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">ItemNovo: TMenuItem;</div><br />
E o código para cirar o novo item:<br />
<div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;">ItemNovo := TMenuItem.Create(nil);</div><div style="font-family: "Courier New",Courier,monospace;">ItemNovo.Caption := 'Nova opção';</div><div style="font-family: "Courier New",Courier,monospace;">ItemNovo.Name := 'ItemNovo';</div><div style="font-family: "Courier New",Courier,monospace;">ItemNovo.OnClick := @Clica; </div><div style="font-family: "Courier New",Courier,monospace;">PopupMenu1.Items.Add(ItemNovo);</div><br />
Agora, resta exceutar o programa e experimentar nossos componentes dinâmicos.<br />
<br />
<div style="color: white;"><span style="background-color: red;">Atualizado em 16/05/2010.</span></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com4tag:blogger.com,1999:blog-33774862.post-79490729606595034972010-05-06T22:57:00.006-04:002010-06-07T19:08:03.643-04:00Lazarus - Conectando MySQL com SQLdb ou ZeosLibVamos mostrar duas maneiras de acessar MySQL no Lazarus. Uma usando os componentes nativos SQLdb e outra usando ZeosLib. Utilizamos no exemplo a <a href="http://mirrors.ucr.ac.cr/MySQL/Downloads/MySQL-5.1/mysql-essential-5.1.46-win32.msi">versão 5.1.46 do MySQL</a>. O SQLdb da versão 0.9.28.2 não funciona com essa versão do MySQL. Dessa forma, foi instalado o snapshot Lazarus-0.9.29-25198-fpc-2.4.1-20100505-win32.exe (usamos o Windows XP nos testes). <a href="http://www.hu.freepascal.org/lazarus/">Snapshots</a> são builds noturnos do Lazarus compilados com os últimos códigos fonte, corrigindo alguns erros e provavelmente introduzindo outros.<br />
<br />
Crie o banco dados no MySQL. Vamos usar o mesmo banco usado em artigos anteriores. Este é o script de criação das tabelas:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">create table cidade (id_cidade int not null primary key, nome varchar(30));</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;">create table cliente (id_cliente int not null primary key, nome varchar(40), endereco varchar(40), id_cidade integer references cidade(id_cidade), telefone varchar(14), tipo char(1));</div><br />
<b>Usando SQLdb</b><br />
<br />
Selecione a aba <b>SQLdb</b> e coloque no <b>Data Module</b> um <b>TMySQL50Connection</b>. Ele que fará a conexão com o banco. Defina então as seguintes propriedades:<br />
<br />
<b>DatabaseName</b> - informe o nome do banco de dados que foi criado.<br />
<b>HostName</b> - informe o nome ou o IP do servidor de banco de dados.<b><br />
Name</b> - informe um nome para a conexão. Por exemplo: <i>dbCliente</i>.<br />
<b>Password</b> - informe a senha do usuário. Se usar <i>root</i> como nome de usuário, informe a senha definida no momento da instalação do MySQL.<br />
<br />
<b>UserName</b> - informe o nome do usuário. Pode ser o <i>root</i>.<br />
<br />
Coloque agora um <b>TSQLTransaction</b> e selecione <i>dbCliente</i> na propriedade <b>Database</b>, e na propriedade <b>Name</b> digite <i>trCliente</i>, por exemplo.<br />
Volte ao <b>TMySQL50Connection</b> e informe <i>trCliente</i> na propriedade <b>Transaction</b>. Coloque a propriedade <b>Connected</b> em <i>True</i> para verificar se a conexão é feita. Se retornar uma mensagem de falta da dll <i>libmySQL</i>, localize a mesma no diretório bin do MySQL e copie-a para o diretório system32. Depois volte a propriedade para <i>False</i>.<br />
Coloque um <b>TSQLQuery</b> no <b>Data Module</b> e defina suas propriedades:<br />
<br />
<b>Database</b> - selecione <i>dbCliente</i>.<br />
<b>Name</b> - defina <i>queCidade</i>.<br />
<b>SQL</b> - informe <i>SELECT * FROM CIDADE</i>.<br />
<b>Transaction</b> - selecione <i>trCliente</i>.<br />
<br />
Coloque agora um <b>TDataSource</b> da aba <b>Data Access</b> e mude <b>Name</b> para <i>dsCidade</i> e em <b>DataSet</b> selecione <i>queCidade</i>.<br />
No evento <b>AfterPost</b> de <i>queCidade</i> digite o código:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">queCidade.ApplyUpdates;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">trCliente.CommitRetaining;</span><br />
<br />
No evento <b>AfterDelete</b> selecione o mesmo método para não repetir código.<br />
Pronto. Está feita a configuração de acesso, tanto para leitura quanto para escrita, em uma tabela do MySQL. Crie uma interface seguindo os passos descritos no post <a href="http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-com.html">Lazarus - Acessando banco de dados com SQLdb - Parte I.</a> <br />
Selecione o form principal e, no editor de código, digite abaixo de Implementation:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">uses u_dmdados;</div><br />
Localize o evento <b>OnShow</b> na aba <b>Eventos</b> do <b>Inspetor de objetos</b>. Dê um duplo clique à direita e digite:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">dmDados.dbCliente.Open;</div><br />
Assim, sempre que o programa for iniciado a conexão com o banco de dados será aberta.<br />
<br />
<b>Usando ZeosLib</b><br />
<br />
Usaremos a versão 7.0 do ZeosLib disponível no grupo <a href="http://lazarus-br.googlegroups.com/web/ZEOSDBO-7.0.0.0_Lazarus_edition-UTF8-snapshot.tar.bz2?hl=pt-BR&gda=B58kCmsAAADakKt8IurhzXqfCouvlDZSMPh3EAiUTqpMDanfqtCQs5v_7o9Clujhjr2F9RJXnvCiXBrB627tHNivPVR3Ntxg08LvZ-gx_PzY0klPiqEDtB8yN8DVh6351trlLMJAptLAjAIKVZkh8Fq1MevJ33c9">Lazarus-BR</a>. Para instalar o pacote siga as instruções apresentadas no post <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-postgresql-com.html">Lazarus - Conectando PostgreSQL com ZeosLib</a>. Coloque um <b>TZConnection</b> no <b>Data Module</b>. Defina as propriedades:<br />
<br />
<b>AutoCommit</b> - deixe em <i>True</i> para que as transações no banco sejam comitadas automaticamente.<br />
<b>Database</b> - informe o nome do banco de dados criado anteriormente.<br />
<b>HostName</b> - informe o nome ou IP do servidor do banco. Para máquina local informe <i>localhost</i>.<br />
<b>Name</b> - digite <i>dbCliente</i>.<br />
<b>Password</b> - informe a senha do usuário. Em geral a senha do usuário <i>root</i>.<br />
<br />
<b>Protocol</b> - informe <i>mysql-5</i>. Observe a versão do MySQL que você está usando.<br />
<b>User</b> - informe o nome do usuário. Geralmente é <i>root</i>.<br />
<br />
<b>TransactionIsolation</b> - define o nível de isolamento da transação. No nosso caso vamos usar <i>tiReadCommitted</i>.<br />
Mude <b>Connected</b> para <i>True</i>. No Windows deve ocorrer um erro de ausência de dll. Faça o download <a href="http://www.niftrasoft.com/download/aplikasi/libmysql51.zip">aqui</a> e copie-a para system32 do Windows. Depois de conectar com sucesso volte <b>Connected</b> para <i>False</i>.<br />
<br />
Coloque um <b>TZQuery</b> e um <b>TZUpdateSQL</b> e configure-os como foi feito no artigo <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-postgresql-com.html">Lazarus - Conectando PostegreSQL com ZeosLib</a>.<br />
No <b>TZUpdateSQL</b> defina essas propriedades assim:<br />
<br />
<b>DeleteSQL</b> - DELETE FROM CIDADE WHERE ID_CIDADE = :OLD_ID_CIDADE;<br />
<b>InsertSQL</b> - INSERT INTO CIDADE VALUES (:ID_CIDADE, :NOME);<br />
<b>ModifySQL</b> - UPDATE CIDADE SET NOME = :NOME WHERE ID_CIDADE = :OLD_ID_CIDADE;<br />
<br />
<br />
Coloque um <b>TDataSource</b> da aba <b>Data Access</b> e defina <b>Name</b> como <i>dsCidade</i> e em <b>DataSet</b> selecione a <b>TZQuery</b> anterior. Ai está. Agora crie a interface com nos posts anteriores.<br />
<br />
<div style="color: white;"><span style="background-color: red;">Atualizado em 04/06/2010.</span></div>Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com13tag:blogger.com,1999:blog-33774862.post-56368411395926786242010-05-03T15:13:00.002-04:002010-05-03T17:53:18.206-04:00Firebird - Vem ai a versao 2.5 O banco de dados Firebird®, de código aberto, possui excelente performance e expressiva escalabilidade, indo desde modelos embarcados (mono-usuário) até sistemas empresariais com múltiplos bancos de mais de 500GB e centenas de conexões simultâneas. <br />
O Firebird suporta o padrão ACID, triggers, stored procedures, UDF e eventos; roda nas versões 32 e 64 bits do Windows, Linux, MacOS X, HP-UX, FreeBSD, etc., sendo muito fácil a migração entre essas plataformas. <br />
Um dos recursos chave do Firebird é a arquitetura multi-geracional, que permite o desenvolvimento e suporte de sistemas híbridos OLTP e OLAP. Suporta o padrão ACID, triggers, stored procedures, UDF e eventos; possui suporte compreensivo ao padrão SQL92, além de inúmeras opções de conectividade. <br />
A combinação de alta performance, baixo consumo de recursos, escalabilidade suprema, instalação simples e silenciosa e distribuição 100% livre de royalties, fazem do Firebird uma escolha atrativa para todos os tipos de desenvolvedores e fornecedores de software. È utilizado por aproximadamente um milhão de desenvolvedores de software em todo o mundo.<br />
Participe da campanha de divulgação acessando <a href="http://www.mindthebird.com/">MindTheBird</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com0tag:blogger.com,1999:blog-33774862.post-25893620297965134622010-05-03T10:27:00.005-04:002010-05-11T15:19:24.568-04:00Java - Certificado de Programador Sun (SCJP)Há pouco tempo escrevi um artigo na revista Urissanê - revista eletrônica do curso de Sistemas de Informação do CEULS/ULBRA, onde trabalho. Nesse artigo eu apresento diretrizes gerais sobre uma das certificações de TI mais procuradas - a SCJP. Abordamos cada certificação Java que a Sun oferece, mostrando as diferenças entre elas, como e onde se inscrever para o exame, como se preparar, dicas gerais sobre o conteúdo do exame, informações sobre o exame propriamente dito e o que acontece depois do exame. Leia o <a href="http://psiu.org.br/revista/v1_n1/v1_n1.php">artigo 4 no site do curso</a>. Logo estarei iniciando neste blog uma série de artigos com informações fundamentais para os candidatos a essa certificação, uma espécie de tutorial Java de preparação.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com1tag:blogger.com,1999:blog-33774862.post-85330980231743845432010-04-29T23:56:00.004-04:002010-04-30T10:15:59.805-04:00Lazarus - Criando relatórios com FortesReport (Parte II)No post <a href="http://professorcarlos.blogspot.com/2010/04/lazarus-criando-relatorios-com.html%20">Lazarus - Criando relatórios com FortesReport (Parte I)</a> mostramos a criação de um relatório simples com agrupamento. Neste artigo vamos mostrar como criar um relatório mestre detalhe usando o FortesReport. Para implementar o exemplo usei um banco de dados Firebird e ZeosLib. Use o seguinte <a href="http://sites.google.com/site/carlosctrl/documentos-1/script.sql?attredirects=0&d=1">script</a> para criar as tabelas. Neste caso o relacionamento mestre detalhe é formado pelas tabelas <i>VENDA</i> e <i>ITEM</i>.<br />
<br />
<b>O Data Module</b> <br />
<br />
Inicie uma aplicação no Lazarus e insira um <b>Data Module</b>. Selecione a aba <b>Zeos Access</b> e coloque um <b>TZConnection</b> no <b>Data Module</b>. Defina as propriedades da seguinte forma:<br />
<br />
<b>Database</b> - informe o banco de dados Firebird que foi criado.<br />
<b>Name</b> - dê um nome ao componente. Por exemplo: <i>dbVendas</i>.<br />
<b>Password</b> - <i>masterkey</i>.<br />
<b>Protocol</b> - <i>firebird-2.0</i> ou a versão que está sendo usada.<br />
<b>User</b> - <i>sysdba</i>.<br />
<br />
Mude Connected para <i>true</i>, para verificar se a conexão está configurada corretamente.<br />
Coloque um <b>TZReadOnlyQuery</b> e defina:<br />
<br />
<b>Connection</b> - selecione o <b>TZConnection</b>.<br />
<b>Name</b> - defina um nome para o componente. Por exemplo: <i>queVenda</i>.<br />
<b>SQL</b> - <i>select a.id_venda, a.data_venda, b.nome from venda a, cliente b where a.id_cliente = b.id_cliente</i>.<br />
<br />
Selecione a aba <b>Data Access</b> e coloque um <b>TDataSource</b>, onde <b>DataSet</b> deve estar associado à Query anterior. Defina <b>Name</b> como <i>dsVenda</i>.<br />
<br />
Coloque um segundo <b>TZReadOnlyQuery</b>, defina <b>Connection</b> da mesma maneira e em <b>Name</b> digite <i>queItem</i>, por exemplo. Na propriedade <b>SQL</b> informe <i>select a.id_produto, b.nome, a.quantidade, b.preco_venda, a.quantidade * b.preco_venda total from item a, produto b where a.id_produto = b.id_produto and id_venda = :id_venda</i>.<br />
<br />
Defina a propriedade <b>DataSource</b> desta Query com <i>dsVenda</i>. Isto, juntamente com o parâmetro :<i>id_venda</i> definem o relacionamento mestre detalhe entre as duas Queries. O parâmetro <i>:id_venda</i> é definido por <i>queVenda</i> através de <i>dsVenda</i>.<br />
<br />
Coloque mais um <b>TDataSource</b> e defina a propriedade <b>DataSet</b> com a Query <i>queItem</i>. Defina <b>Name</b> como <i>dsItem</i>. Leia mais para conexão com Firebird em <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-firebird.html">Lazarus - Conectando Firebird com SQLdb ou ZeosLib</a>.<br />
<br />
<b>O relatório</b><br />
<br />
Esse é o aspecto do relatório que iremos construir:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRkJA-xAcnGnDu4XMOOrkEdHG05KPUp23_IgBO8LO5FY6_AEh1u-OCrMD6Y7Kww5lJ8OdnGNqHy0SFpHNu7jrUhhkIPOw0RVqEoSow8pzAvZFYdivUpUSEh3LpTIYgZguB-Nj9/s1600/mestredetalhe.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRkJA-xAcnGnDu4XMOOrkEdHG05KPUp23_IgBO8LO5FY6_AEh1u-OCrMD6Y7Kww5lJ8OdnGNqHy0SFpHNu7jrUhhkIPOw0RVqEoSow8pzAvZFYdivUpUSEh3LpTIYgZguB-Nj9/s400/mestredetalhe.JPG" width="400" /></a></div><br />
<br />
Agora adicione um novo form à aplicação. Localize a aba <b>Fortes Report</b> e coloque um <b>TRLReport</b>. No <b>Inspetor de Objetos</b> expanda a propriedade <b>AllowedBands</b> e coloque em <i>True</i> as opções <b>btColumnHeader</b>, <b>btDetail</b> e <b>btHeader</b>. Na propriedade <b>DataSource</b> selecione <i>dsVenda</i>, a tabela mestre.<br />
Agora coloque um <b>TRLBand</b>. Defina a propriedade <b>BandType</b> como <i>btHeader</i>. Aumente a altura da banda e coloque um <b>TRLLabel</b> sobre a <b>TRLBand</b>. Defina a propriedade <b>Caption</b> como <i>Relatório de Vendas</i>. Na propriedade <b>Align</b> selecione <i>faCenter</i>, para centralizar o rótulo na banda. Expanda a propriedade <b>Font</b> e defina <b>Size</b> como <i>14</i>, por exemplo. Coloque um <b>TRLSystemInfo</b> no lado esquerdo da banda. Na propriedade <b>Info</b> selecione <i>itDate</i>. Isso mostrará a data atual na banda. Coloque outro <b>TRLSystemInfo</b>, este no lado direito da banda e defina a propriedade <b>Info</b> como <i>itPageNumber</i>. Isso mostra o número da página.<br />
Coloque outro <b>TRLBand</b> e defina a propriedade <b>BandType</b> como <i>btDetail</i>. Sobre essa banda, que deve mostrar os dados da tabela mestre, coloque <b>TRLLabels</b> definindo seus <b>Caption</b> como <i>Venda</i>, <i>Data</i>, <i>Cliente</i>, <i>CÓDIGO</i>, <i>NOME</i>, <i>QTDE</i>, <i>PREÇO</i> e <i>TOTAL</i>. Coloque também três <b>TRLDBTexts</b>. Defina seus <b>DataSource</b> como <i>dsVenda</i> e <b>DataField</b> como <i>ID_VENDA</i>, <i>DATA_VENDA</i> e <i>NOME</i>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKdw_3FfcLiKL8PSkFyOeRPoIHjh7EBHjy_YVG-MV7TBw_CewTD8tWZRtoeqmbn8Pe1c6YrlJT6erSDUOqzMVvx3GgD_lI0EIJ__GOW4ow1RXXvBsW_yEbwT2_c5GxbRqHYzQC/s1600/desenhorelatorio.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="95" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKdw_3FfcLiKL8PSkFyOeRPoIHjh7EBHjy_YVG-MV7TBw_CewTD8tWZRtoeqmbn8Pe1c6YrlJT6erSDUOqzMVvx3GgD_lI0EIJ__GOW4ow1RXXvBsW_yEbwT2_c5GxbRqHYzQC/s400/desenhorelatorio.PNG" width="400" /></a></div><br />
A banda deve ser dimensionada adequadamente de acordo com a figura acima. Coloque um <b>TRLSubDetail</b> e defina a propriedade <b>DataSource</b> como <i>dsItem</i>. Esta banda irá mostrar os dados da tabela detalhe. Expanda a propriedade <b>AllowedBands</b> e coloque em <i>True</i> as opções <b>btDetail </b>e <b>btSummary</b>. Sobre essa banda coloque um <b>TRLBand</b>. Defina <b>BandType</b> como <i>btDetail</i>. Coloque cinco <b>TRLDBTexts</b> e defina DataSource como <i>dsItem</i>. Em <b>DataField</b> informe <i>ID_PRODUTO, NOME, QUANTIDADE, PRECO_VENDA e TOTAL</i>. Coloque outro <b>TRLBand</b> sobre <b>TRLSubDetail</b> e defina <b>BandType</b> como <i>btSummary</i>. Esta banda é usada para imprimir totais de relatórios ou grupos. Sobre esta banda coloque um <b>TRLLable</b> e defina seu <b>Caption</b> como <i>Total da Venda:</i>. Ao lado dele coloque um <b>TRLDBResult</b>. Este componente é usado para totalizar uma coluna, por exemplo. Defina <b>DataSource</b> como <i>dsItem</i>. Em <b>DataField</b> informe <i>TOTAL</i>. A propriedade <b>Info</b> define a operação que será realizada. Defina como <i>riSum</i>. que indica que a coluna <i>TOTAL</i> será somada. Na propriedade <b>DisplayMask</b> escreva <i>#,###,##0.00</i>. Isso irá formatar o valor mostrado. Pode-se definir <b>DisplayMask</b> para os <b>TRLDBTexts</b> referentes a <i>PRECO_VENDA</i> e <i>TOTAL</i>.<br />
<br />
No form que irá chamar o relatório coloque um botão e no evento OnClick escreva o código que mostrar uma prévia do relatório:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">frmMestreDetalhe.rlVendas.Preview();</div><br />
É necessário informar na cláusula uses o nome da unit do relatório. Abrir a conexão e as Queries também é necessário para que o relatório seja visualizado. Faça o download do exemplo <a href="http://sites.google.com/site/carlosctrl/documentos-1/mestredetalhe.zip?attredirects=0&d=1">aqui</a>.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com10tag:blogger.com,1999:blog-33774862.post-66983844826805813572010-04-27T08:15:00.003-04:002010-04-27T10:28:21.698-04:00Lazarus - Emulador WinCE/Windows MobileHá alguns dias escrevi um post mostrando o <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-criando-uma-aplicacao-para.html">desenvolvimento de uma pequena aplicação para WinCE</a> usando SQLite. Na época fiz os testes em um PDA, não usei emulador. Muitas pessoas tem entrado em contato comigo questionando sobre emuladores. Sempre tive dificuldades com os emuladores da Microsoft. Mas passei a procurar por um emulador que funcione e acabei por encontrar no site da <a href="http://www.pdaexpert.net/downloads/windows-mobile/windows-mobile-6-emulator-localized-images/">PDAExpert</a>. Lá encontrei as versões Standard e Professional do emulador para Windows Mobile 6. Por limitações de banda fiz o download da versão Standard que oferece três emuladores diferentes. Consegui executar o exemplo do artigo, como mostra a figura.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirI4hOjnf7y7WQpqWom947PPQrE58sD36DrHJgvIXlRnzvyoZiRlMCsTwEE_kJ4UgWAJwxeEqOmeyH3W93AlOdlPigPwEWqIzK5r0Ik9MDQHl5_Hq18bSvhjrUfj_yGcq_7ZCQ/s1600/emulador.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirI4hOjnf7y7WQpqWom947PPQrE58sD36DrHJgvIXlRnzvyoZiRlMCsTwEE_kJ4UgWAJwxeEqOmeyH3W93AlOdlPigPwEWqIzK5r0Ik9MDQHl5_Hq18bSvhjrUfj_yGcq_7ZCQ/s320/emulador.jpg" alt="Emulador Windows Mobile 6"/></a></div>No entanto, o programa não consegue acesso ao banco SQLite. Minha forte suspeita é que a dll não é compatível com Windows Mobile 6. Ainda não tenho dados suficientes para afirmar isso. Por conta disso, pretendo criar uma nova aplicação que grava os dados em XML ou mesmo em arquivo texto usando TFixedFormatDataSet, como mostrei no post <a href="http://professorcarlos.blogspot.com/2010/03/lazarus-tratamento-de-arquivos-texto.html">Lazarus - Tratamento de Arquivos Texto</a>. De qualquer forma, se alguém tiver tido experiência com esse emulador rodando SQLite, gostaria de trocar idéias.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com9tag:blogger.com,1999:blog-33774862.post-61533343273448654382010-04-26T11:08:00.004-04:002010-05-04T15:20:35.106-04:00Lazarus - Relógio para jogar XadrezPara os aficcionados do milenar jogo de Xadrez que não querem ou não podem pagar por um relógio, estou disponibilizando um programa bem simples que simula um relógio, cujo <a href="http://sites.google.com/site/carlosctrl/documentos-1/Relogio.rar?attredirects=0&d=1">executável pode ser baixado aqui</a>. O programa não requer instalação, podendo inclusive ser executado em um pendrive. Ele foi desenvolvido usando a fantástica ferramenta Lazarus/FreePascal e substitui com eficiência os relógios de mesa. Além disso, aqueles que estão dando os primeiros passos em Lazarus encontrarão um exmplo de programa que usa bastante componentes e código para seus exercícios.<br />
Antes de mostrar o código vou mostrar a interface e explicar o funcionamento do relógio.<br />
<br />
<b>A interface</b> <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR4bIltInB9AJnF3qwkxVBubCgmLViSFb6VjFn0oKFuSYY_wk7nZawRGtb_9hzALU8bIXZUg6udm4diMR79ZJGGSLGBf9uDT9IZrYsSGnjtJVpybSc1xpJtE-rs_UTvj_CJjYG/s1600/relogio.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR4bIltInB9AJnF3qwkxVBubCgmLViSFb6VjFn0oKFuSYY_wk7nZawRGtb_9hzALU8bIXZUg6udm4diMR79ZJGGSLGBf9uDT9IZrYsSGnjtJVpybSc1xpJtE-rs_UTvj_CJjYG/s400/relogio.jpg" width="400" /></a></div><br />
Na parte superior do relógio está a configuração do tempo que será usado na partida. Há três caixas de texto (<b>TEdit</b>). Uma para hora, a segunda para minutos e a terceira para segundos. À direita encontram-se três botões (<b>TButton</b>). O primeiro para iniciar o relógio, o segundo para reset e o terceiro para pausar.<br />
Abaixo temos mais dois <b>TButton</b> que servirão para simular o pressionamento do botão do relógio de cada jogador. Mais abaixo tem-se dois <b>TGroupBox</b> com <b>TLabel</b> dentro deles. Os rótulos são usados para mostrar o tempo de reflexão de cada jogador. E, finalmente, dois <b>TProgressBar</b> para mostrar visualmente o progresso do tempo das brancas e das pretas. As barras de progresso também ficam dentro de <b>TGroupBox</b>.<br />
Além dos componentes visuais são usados dois <b>TTimer</b>, usados para controlar o tempo de cada jogador.<br />
<br />
<b>O funcionamento</b><br />
<br />
Para iniciar uma partida, inicialmente definimos o tempo da partida. Certamente o tempo é o mesmo, tanto para as brancas quanto para as pretas. Definido o tempo, pressiona-se o botão iniciar. Imediatamente o tempo das brancas começa a correr, habilitando-se o <b>TTimer</b> das brancas. As brancas fazem sua jogada e pressionam qualquer tecla do teclado que possa ser detectada pelo evento <b>OnKeyPress</b>. Nesse momento o <b>TTimer</b> das pretas é habilitado e o das brancas é desabilitado. O processo continua até que um dos jogadores estoure o tempo ou a partida seja encerrada. Se o botão <i>Pausar</i> for pressionado, os dois <b>TTimer</b> são desabilitados e o rótulo dele muda para <i>Continuar</i>. Pressionando-se o botão novamente a partida prossegue do ponto onde parou.<br />
O componente <b>TTimer</b> dispara um evento a determinados intervalos definidos na propriedade <b>Interval</b>. O valor informado em <b>Interval</b> é em milissegundos. Deixamos a propriedade com o valor padrão 1000 milissegundos. Ou seja, o evento <b>OnTimer</b> irá acontecer a cada segundo.<br />
<br />
<b>O código</b><br />
<br />
Grande parte do código é bem simples e não merece maiores explicações. Vou apresentar o método do evento <b>OnClick</b> do botão <i>Pausar/Continuar</i>. Para o funcionamento correto, declarei duas variáveis <b>boolean</b> globais: <i>blPausa</i>, que define se o relógio está em pausa ou em andamento, e<i> blBrancas</i>, que define de quem é o relógio que está em andamento.<br />
<br />
<pre class="brush: pascal">procedure TfrmRelogio.btPausarClick(Sender: TObject);
begin
if not blPausa then
begin
if blBrancas then
timBrancas.Enabled := false
else
timPretas.Enabled := false;
btParar.Enabled := false;
blPausa := true;
btPausar.Caption := 'Continuar';
end
else
begin
if blBrancas then
begin
timBrancas.Enabled := true;
btBrancas.SetFocus;
end
else
begin
timPretas.Enabled := true;
btPretas.SetFocus;
end;
blPausa := false;
btParar.Enabled := true;
btPausar.Caption := 'Pausar';
end
end;
</pre><br />
De acordo com o estado de<i> blPausa</i>, habilita-se/desabilita-se o <b>TTimer</b> correspondente e ora o botão das brancas recebe o foco, ora o botão das pretas é quem recebe o foco. Nesse evento muda-se o rótulo do botão, alternando-se entre <i>Pausar</i> e <i>Continuar</i>.<br />
<br />
Os eventos <b>OnTimer</b> tanto das brancas quanto das pretas são similares. Mostro apenas o método referente às brancas.<br />
<br />
<pre class="brush: pascal">procedure TfrmRelogio.timBrancasTimer(Sender: TObject);
var
bTotal, bParcial: integer;
begin
bSeg := bSeg + 1;
if bSeg > 59 then
begin
bSeg := 0;
bMin := bMin + 1;
if bMin > 59 then
begin
bMin := 0;
bHor := bHor + 1;
end
end;
lbBrancas.Caption := StrZero(bHor, 2, 0) + ':' + StrZero(bMin, 2, 0)+':'+StrZero(bSeg, 2, 0);
bTotal := StrToInt(edHora.Text) * 3600 + StrToInt(edMinuto.Text) * 60 + StrToInt(edSegundo.Text);
bParcial := bHor * 3600 + bMin * 60 + bSeg;
pbBrancas.Position := (100 * bParcial div bTotal);
if (StrZero(bHor, 2, 0) >= edHora.Text) and (StrZero(bMin, 2, 0) >= edMinuto.Text) and (StrZero(bSeg, 2, 0) >= edSegundo.Text) then
begin
timBrancas.Enabled := false;
ShowMessage('As brancas estouraram o tempo');
end;
end;
</pre><br />
Nas linhas de 5 a 15, o tempo é incrementado. Observe que temos uma variável para hora, minutos e segundos. Em seguida o tempo é mostrado no rótulo correspondente ao display do relógio, na linha 16. Nas linhas de 17 a 19, é calculado o percentual de tempo decorrido e esse valor é mostrado no <b>TProgressBar</b>. Finalmente, é verificado se o tempo limite foi atingido. Caso positivo, o relógio é parado e a mensagem de estouro de tempo é mostrado.<br />
A função StrZero() foi criada para preencher um número inteiro com zeros à esquerda. O código pode ser encontrado no download.<br />
Baixe o programa completo <a href="http://sites.google.com/site/carlosctrl/documentos-1/Relogio_Lazarus.rar?attredirects=0&d=1">aqui</a> e divirta-se jogando Xadrez e aprendendo mais um pouco sobre Lazarus/FreePascal.Professor Carloshttp://www.blogger.com/profile/10347668022241306511noreply@blogger.com0