Mostrando postagens com marcador Delphi. Mostrar todas as postagens
Mostrando postagens com marcador Delphi. Mostrar todas as postagens

terça-feira, agosto 25, 2009

DbTreeView no Delphi - JvDbTreeView

Bom, depois de apanhar um pouco para conseguir colocar para funcionar, aqui vai a dica de como fazer um plano de contas ser mostrado numa TreeView, no caso vamos usar a jvDbTreeView que é uma TreeView dbaware no Delphi.

Como vamos usar o componente na JVCL, aqui vai o link para baixar http://sourceforge.net/projects/jvcl/, é um excelente pacote de componentes, praticamente tudo que você precisar, acaba descobrindo que tem lá.

Criei a minha tabela no Firebird, a estrutura abaixo:

Campo Tipo Descrição
Cta_ID integer Numero da conta
Cta_Master integer Conta “pai”
Cta_Descricao Varchar(30) Nome da conta

Coloque um componente JvDbTreeView no formulário, conecte-o via a propriedade DataSource à tabela do banco de dados.

Ajuste as suas propriedades do JvDbTreeView como abaixo:
Obs.: No meu caso o dataSource chama-se dsPlanContas.

Propriedade Valor
DataSource dsPlanContas
DetailField Cta_Master
ItemField Cta_Descricao
MasterField Cta_ID

   Pronto, já está OK e pronto para funcionar.

A explicação das propriedades é a seguinte:
DataSource: Obviamente é a conexão à base de dados;

DetailField: É o campo que contém o valor que aponta para a conta pai.

ItemField: é o texto que vai aparecer na TreeView.

MasterField: é a chave única da tabela.

       Quem reescreveu o componente deve ter problemas sérios para atribuir nomes às propriedades, custei para conseguir entender, mas aí está o mapa da mina.

Abaixo um exemplo do que está no banco de dados:

Cta_Id Cta_Master Cta_Descricao
1 0 DESPESAS
2 1 DESPESAS FIXAS
3 2 PESSOAL
4 11 ALUGUEL
5 11 CONDOMINIO
6 0 RECEITAS
7 6 RECEITAS DIRETAS
8 3 CLT
9 3 FREES
10 2 CUSTOS DIRETOS
11 10 IMÓVEIS
12 1 DESPESAS VARIAVEIS
13 12 COMBUSTIVEIS
14 12 COMISSÕES
15 12 MATERIAL DE EXPEDIENTE
16 12 MANUTENÇÕES
17 12 EXAMES MÉDICOS

quarta-feira, abril 01, 2009

Rotas com o Google Maps no Delphi – versão simplificada.

 

      Após publicar as matérias anteriores sobre como mostrar os mapas do Google e como traçar rotas do Google a partir de aplicativos Delphi, conversando com o Paulo Geloramo da Assis Informática de Assis – SP, ele me mostrou uma versão mais simplificada que ele fez da rotina.

     Durante a nossa conversa, acabamos indo pesquisar o que seriam alguns dos parâmetros que existem no final da URL de pesquisa que carrega o mapa e traça a rota.

      Fazendo algumas experimentações, chegamos à conclusão e constatamos que a rotina funciona mesmo sem aqueles parâmetros, o que a torna mais simplificada ainda.

     Bom, aqui abaixo mais uma função para mostrar o mapa e traçar a rota, agora bem mais simplificada:

procedure Rota(Logradouro1, Numero1, Cidade1, UF1, CEP1, Logradouro2, Numero2, Cidade2, UF2, CEP2: string);
var
    strUrl: String;
begin
  strURL := 'http://maps.google.com.br/maps?f=q&source=s_q&hl=pt-BR&geocode=&q=' +
            ' from: ' +  AnsiToUtf8(Logradouro1) + ', ' +  Numero1 + ', ' +
            AnsiToUtf8(Cidade1) + ', ' +  UF1 + ', ';
  if Length(CEP1) > 1 Then
     strURL := strURL + FormatMaskText('99999-999;0; ', CEP1);
  strURL := strURL + ' to: ' +  AnsiToUtf8(Logradouro2) + ', ' +
                      Numero2 + ', ' +  AnsiToUtf8(Cidade2) + ', ' + UF2 + ', ';
  if Length(CEP2) > 1 Then                     
     strURL := strURL + FormatMaskText('99999-999;0; ', CEP2)' + ‘&ie=UTF8’;
  ShellExecute(0, nil, PChar(strURL), nil, nil, 0);
end;

    Veja que os parâmetros de CEP podem não ser informados (passar uma string vazia como parâmetro), mas se o endereço existir em duplicidade na cidade (como é o caso de São Paulo), você terá problemas ao traçar a rota.

    Para definir corretamente o endereço, passe o parâmetro de CEP para a API processar a URL sem ambiguidades.

    Você pode acrescentar o parâmetro de zoom ao final da URL, utilizando o parâmetro ‘&z=’, se optar por não utilizar este parâmetro será retornado o mapa com o zoom abrangendo toda a rota, e o usuário poderá posicionar e escolher o nível de zoom manualmente.

     Veja também que foi usada a função AnsiToUtf8 do Delphi, isto é para os casos em que você possui acentuação no nome do endereço, se não usar esta conversão, a função não irá funcionar como o esperado.

www.spectrus.com.br

domingo, março 29, 2009

Traçar rotas a partir do Delphi com o Google Maps

 

         Continuando a partir do artigo anterior “Mapas do Google no seu aplicativo Delphi”, vamos agora avançar um pouco mais, traçar rotas entre dois pontos, e mostrar isto ao usuário.

          Esta é uma funcionalidade interessante para aplicativos como CRM ou de logística. Você pode obter informações completas sobre como utilizar as APIs do Google Maps em www.google.com/apis/maps, a maioria dos exemplos contempla Java, Javascript, PHP ou Python, porém não é dificil adaptá-los à linguagem que você utiliza, como estamos fazendo com o Delphi.

           Para usar as APIs do Google, você precisa obter uma chave única e exclusiva sua, é de graça, e lhe dá acesso à todas as funcionalidades do Google Maps. Neste exemplo não vamos utilizar esta chave, é apenas um exemplo, muito embora você possa utilizar sem ter uma chave, como você pode constatar pelo código neste artigo, é aconselhável que você obtenha esta chave, por uma questão de copyright.

          Bueno, vamos botar a mão na massa.

          Primeiro de tudo você irá precisar, para mostrar o mapa, das coordenadas do ponto a ser mostrado na tela, normalmente você mostrará na tela o ponto inicial da rota, permitindo ao usuário que acompanhe a rota a partir do ponto de origem, porém você pode mostrar o ponto final da rota, a seu critério. Por este motivo criamos uma função para retornar as coordenadas.

          As coordenadas (e mais uma série de informações sobre o endereço) são retornadas em um arquivo xml, você também pode solicitar que seja retornado em formato csv (separado por vírgulas). No caso de um arquivo xml a API do Google Maps retorna informações bem completas, incluindo até mesmo o CEP, no caso de arquivo CSV serão retornadas apenas as coordenadas.

        Neste artigo iremos trabalhar com o arquivo XML, pois se você desejar obter mais informações sobre o endereço basta incrementar o código.

        Como este artigo é direcionado para todos os desenvolvedores DELPHI, incluindo os iniciantes, vou tentar manter o código o mais simples possível, mesmo que em algumas partes pareça que há redundância ou que o código poderia ser reduzido, creio que desta forma fica fácil para todos acompanharem a metodologia, sinta-se a vontade para refatorar o código.

       Para este código você deverá declarar a unit XMLDOC na parte de interface da sua unit.

Vamos também declarar um objeto do tipo XMLDocument para trabalhar com as informações retornadas pelo Google.

vXMLDoc : TXMLDocument;

       Na inicialização da Unit, ou no evento onCreate do Form, você deverá criar o XMLDocument:

    vXMLDoc := TXMLDocument.Create(Self);

      Vamos criar a função que irá preencher as coordenadas, apenas para fins informativos mantivemos o array com 3 dimensões, na primeira iremos manter as coordenadas como recuperadas do arquivo xml, isto é apenas para fins informativos, você poderá consultar esta ocorrência do array para verificar como as coordenadas foram lidas. No seu aplicativo final de produção você pode eliminar esta ocorrência.

function getCoordenadas(Logradouro, Numero, Cidade, UF, Pais: String): String;

var

//Vamos declarar um array para trabalhar com as coordenadas:
   strCoordenadas: array[0..2] of String;
   strURL: String;
   idx, inicio, tamanho : integer; // para manipular as strings de retorno

begin

Try

  Result := ‘’;

   strURL := ‘http://maps.google.com/maps/geo?q=’ +
                  Logradouro + ‘, ‘ + Numero + ‘ – ‘ + Cidade +
                  ‘ – ‘ + UF + ‘, ‘ + Pais + ‘&output=xml’;
   // O parâmetro final da string output determina o tipo de
   //    informação retornada (csv ou xml).
   //  Agora fazemos o xmldocument ler o retorno da URL

   vXMLDoc.FileName := strURL;
   vXMLDoc.Active := True;

   // Se você quiser aprender mais sobre o retorno do Google.
   // coloque um TMemo no formulário e passe o texto retornado
  //  para este TMemo, para ver o que é retornado, como abaixo:

  Memo1.Lines.Clear;
  Memo1.Lines.Add(vXMLDoc.XML.Text);

  if not vXMLDoc.Active Then
     exit;

For idx := 0 to vXMLDoc.XML.Count -1 do
    begin
    If Pos('<coordinates>', vXMLDoc.XML[idx]) > 0 Then
       begin
       inicio := Pos('<coordinates>', vXMLDoc.XML[idx]) + 13;
       tamanho := (Length(vXMLDoc.XML[idx]) - inicio) - (Length(vXMLDoc.XML[idx]) - (Pos('</coordinates>', vXMLDoc.XML[idx])));
       strCoordenadas[0] := Copy((vXMLDoc.XML[idx]), inicio, tamanho);
       end;
    end;

If length(strCoordenadas[0]) > 0 Then
   begin
   strCoordenadas[1] := Copy(strCoordenadas[0], 1, Pos(',', strCoordenadas[0]) -1);
   strCoordenadas[2] := Copy(strCoordenadas[0], Pos(',', strCoordenadas[0])+ 1, Length(StrCoordenadas[0]));
   if Pos(',', strCoordenadas[2]) > 0 Then
      StrCoordenadas[2] := Copy(strCoordenadas[2], 1, Pos(',', strCoordenadas[2]) - 1);
   end;

// Se você colocou um Memo para verificar o que é retornado,
//      pode adicionar as coordenadas para verificar se está tudo OK.
//  Lembre-se de retirar isto no software de produção.
Memo1.Lines.Add(strCoordenadas[0]);
Memo1.Lines.Add(strCoordenadas[1]);
Memo1.Lines.Add(strCoordenadas[2]);
Result := strCoordenadas[2] + ‘,’ + strCoordenadas[1];

Finally

End;

end;

 

    Agora vamos declarar uma função para receber os endereços, as coordenadas e retornar a URL para traçar a rota. As URLs para buscar as coordenadas e para traçar as rotas, ficam mais fácil de gerenciar se você declarar na parte de interface da unit. Aqui declaramos as URLs no corpo das procedures e functions para facilitar o seu entendimento, apenas para fins didáticos.

Function Rotear( De_onde, Para_onde, coordenadas: String): String;
var
  strURL : String;
begin
   Try
       
Result := ‘’;

   // URL para traçar a rota no google
   // O parâmetro z (o último da URL) é o fator de zoom
   //  a ser aplicado ao mapa, experimente com outros
   // valores (valores maiores, mais zoom, e vice-versa).

   strURL := ‘http://maps.google.com/maps?f=d&source=s_d&saddr=’ + 
                   De_onde + ‘&daddr=’ + 
                   Para_onde + ‘&hl=pt-BR&geocode=&mra=pe&mrcr=0&ie=UTF8&ll=’ +
                   coordenadas + ‘&z=16’;

Result := strURL;

Finally

end;

end;

 

   Agora vamos usar a mesma função que usamos no outro artigo sobre mostrar mapas do google no delphi, para mostrar o mapa com a rota traçada:

     Temos uma tabela de Clientes, 5 campos desta tabela nos interessam, que contém os dados que usaremos para pesquisar no mapa.

    Logradouro = Contém o nome do logradouro do endereço, por exemplo “Rua Jesuíno Arruda”.
    Numero = Contém o número do endereço, apenas o número e não o complemento (sala, loja, etc), por exemplo: 769 
    Cidade = O nome da cidade, por exemplo: São Paulo
    UF = A sigla do estado, exemplo SP.
    País = O nome do país;

    E agora criar uma função que vai fazer o trabalho, é simples, prático e bem rápido.

procedure TForm1.CarregaMapa;
var

   strURL, deOnde, paraOnde, coordenadas : String;
begin
  // Localizamos o endereço inicial

  Clientes.Locate(‘ClienteID’, VarArrayOf([clienteInicial]),[]);

   Coordenadas := getCoordenadas(Clientes.FieldByName('Logradouro').AsString, Clientes.FieldByName('Numero').AsString,       Clientes.FieldByName('Cidade').AsString, Clientes.FieldByName('UF').AsString, Clientes.FieldByName(‘Pais’).AsString);

  deOnde := Clientes.FieldByName('Logradouro').AsString + ', ' +
                  Clientes.FieldByName('Numero').AsString + ', ' + 
                  Clientes.FieldByName('Cidade').AsString + '-' +
                  Clientes.FieldByName('UF').AsString + ‘, ‘ +
                  Clientes.FieldByName(‘Pais’).AsString;

 

// Vamos localizar o endereço de destino
  Clientes.Locate(‘ClienteID’, varArrayOf([clientefinal]), []);

        paraOnde := Clientes.FieldByName('Logradouro').AsString + ', ' +
                  Clientes.FieldByName('Numero').AsString + ', ' + 
                  Clientes.FieldByName('Cidade').AsString + '-' +
                  Clientes.FieldByName('UF').AsString + ‘, ‘ +
                  Clientes.FieldByName(‘Pais’).AsString;

  strURL := Rotear(deOnde, paraOnde, Coordenadas);
  ShellExecute(0, Nil,  PChar(strURL), Nil, Nil, 0);

// Fiz a chamada acima para que ficasse mais claro, mas você
// pode otimizar a clareza do código fazendo a chamada :
// ShellExecute(0, Nil,  PChar(Rotear(deOnde, paraOnde, Coordenadas)), Nil, Nil, 0);


end;

    Bom, com isso você já consegue colocar a funcionalidade de fazer rotas no seu aplicativo, você pode usar um TWebBrowser e embutir isto dentro do seu software. Há vantagens e desvantagens nisto, eu pessoalmente prefiro chamar um browser externo.

     Como o TWebBrowser é baseado na engine do Internet Explorer, se o usuário tiver outro browser instalado (Opera, FireFox, Safari, etc), e não tiver o Internet Explorer instalado, seu aplicativo vai apresentar erro, e a bela funcionalidade que você implementou não irá funcionar. Da maneira como fizemos, o browser padrão do usuário é que será chamado, seja ele qual for.

    www.spectrus.com.br

Mapas do Google no seu aplicativo Delphi.

 

      Bom, você certamente já pesquisou algum endereço pelo google maps, e ficou imaginando que colocar aquilo no seu aplicativo seria uma boa idéia.
      Pois agora, seus problemas “acabaram-se”, com o novo googlemapeitorparaseuaplicativeitor Tabajara, as coisas finalmente vão acontecer.

      Veja abaixo como fazer para colocar o Google para trabalhar para você, e mostrar para seus clientes, ou para o chefe, como você é esperto (Não tanto quanto o Larry Page e o Sergey Brin, pois eles ganham fortunas com o Google, e você ainda está bem distante de conseguir comprar 1 Boeing só para fazer baladas nos céus como eles fazem).

     Mãos à obra entonces:

     Temos uma tabela de Clientes, 4 campos desta tabela nos interessam, que contém os dados que usaremos para pesquisar no mapa.

    Logradouro = Contém o nome do logradouro do endereço, por exemplo “Rua Jesuíno Arruda”.
    Numero = Contém o número do endereço, apenas o número e não o complemento (sala, loja, etc), por exemplo: 769 
    Cidade = O nome da cidade, por exemplo: São Paulo
    UF = A sigla do estado, exemplo SP.

Vamos criar uma função que vai fazer o trabalho, é simples, prático e bem rápido.

procedure TForm1.CarregaMapa;
begin
  ShellExecute(0, Nil,
    PChar('http://maps.google.com.br/maps?f=q&source=s_q&hl=pt-BR&geocode=&q=' +Clientes.FieldByName('Logradouro').AsString + ', ' + Clientes.FieldByName('Numero').AsString + ', ' +
      Clientes.FieldByName('Cidade').AsString + '-' + Clientes.FieldByName('UF').AsString + '&jsv=143c&sll=-23.186453,-46.884453' +
      '&sspn=0.478436,0.545883&g=&ie=UTF8&ct=clnk&cd=1'), Nil, Nil, 0);
end;

    Basta chamar a função e será carregado o browser com o mapa correspondente ao endereço passado.

    No próximo post vamos ver como fazer para, além de mostrar o mapa, traçar a rota entre dois endereços.

    Como sempre falo : Google é seu amigo, use-o.
    www.spectrus.com.br

Movendo colunas e linhas em um StringGrid.

 

      Na maioria dos componentes Grids, de terceiros, você pode observar que o usuário pode mover colunas e linhas usando o mouse. Aliás, o usuário espera este comportamento de um Grid. Então, como fazer isso usando um TStringGrid?

      Como sempre, se é isso que você estava querendo implantar em seu aplicativo, mais uma vez “seus pobrêma se acabaram-se”,  apresentamos o incrível GridColumnRowMoveitor Tabajara.

      Mais uma vez… mão na massa e chega de enrolação.

      Primeiro de tudo, se você der uma olhada mais aprofundada no componente TCustomGrid você verá que os métodos MoveColumn e MoveRow estão lá, fazem parte do componente, mas eles estão ocultos no TStringGrid, eles são herdados do ancestral TCustomGrid porém não estão acessíveis no descendente, o motivo?? Ora, vai lá saber o que se passa na cabeça dos garotos da Codegear…

      Como resolver esse problema? Simples e fácil, sem maiores complicações, basta fazer uma herança de TStringGrid e redeclarar estes métodos como public.

type
    TNovoGrid = class(TStringGrid)
    public
    procedure MoveColumn(FromIndex, ToIndex: LongInt);
    procedure MoveRow(FromIndex, ToIndex: LongInt);
   end;

   Para implementar estes métodos é muito simples, basta na implementação, chamar o ancestral e passar para ele o comando:

procedure TNovoGrid.MoveColumn(FromIndex, ToIndex: LongInt);
begin
    inherited;
end;

procedure TNovoGrid.MoveRow(FromIndex, ToIndex: LongInt);
begin
    inherited;
end;

     Você não precisa registrar este componente na paleta de componentes. Use o TStringGrid ou qualquer descendente de TCustomGrid normalmente como já faz hoje, e quando você precisar usar estes métodos, simplesmente faça um typecast (conversão de tipos) para a nova classe, e pronto. Veja o exemplo abaixo:

procedure TForm1.Button1Click(Sender: TObject);
begin
       TNovoGrid(StringGrid1).MoveColumn(2, 5);
end;

    Bom, é isso aí, até a próxima.
    www.spectrus.com.br