Ir para conteúdo
Fórum Script Brasil
  • 0

(Resolvido)Selecionar Linhas no DBGrid


João Paulo Taraciuk

Pergunta

Boa tarde pessoal, lá vamos nós de novo

Estou trabalhando em uma tela de faturamento, onde tenho dois DBGrid, em um deles tenho as compras dos clientes, no segundo tem as parcelas destas compras , então o que eu quero fazer é o seguinte,

No grid 1, se eu clico em uma linha, que é um pedido, quero que selecione no grid 2 as parcelas referentes ao pedido selecionado no grid 1, pois, por exemplo, tem um pedido no grid 1 que é uma linha, no grid 2 estão as parcelas referentes a este pedido, e não sei nem por onde começar a fazer este processo...

Se alguém tiver uma dica, eu agradeço!!!

Valeu.

Editado por João Paulo Taraciuk
Link para o comentário
Compartilhar em outros sites

Posts Recomendados

  • 0
No grid 1, se eu clico em uma linha, que é um pedido, quero que selecione no grid 2 as parcelas referentes ao pedido selecionado no grid 1, pois, por exemplo, tem um pedido no grid 1 que é uma linha, no grid 2 estão as parcelas referentes a este pedido, e não sei nem por onde começar a fazer este processo...

João Paulo Taraciuk, o negócio é "esquecer" o componente e pensar no que ele representa (ou apresenta) - dados de um dataset (tabela ou consulta SQL).

Com isto em mente, basta que você filtre o dataset, cujos os dados são apresentados no DBGrid2, baseado no campo que o relaciona com o dataset no DBGrid1.

você não citou maiores detalhes das suas tabelas, mas vamos tomar como exemplo as tabelas envolvidas na figura 1, logo abaixo. Baseado na 3 forma normal, a tabela Pedido mantém um código de relacionamento (CodCliente) aos dados do cliente localizados na tabela Cliente e, de modo similar, a tabela Parcelas mantém um código de relacionamento (CodPedido) aos dados de um pedido localizados na tabela Pedido:

relacionais0.png

Figura 1: Relacionamento entre as tabelas.

Isto implica em que para da item relacionado na tabela Pedido, haverá um respectivo item na tabela Clientes, bem como itens na tabela Parcelas. Mantendo o foco da questão, ao selecionarmos um item na tabela Pedido, através do campo de relacionamento, temos condições de encontrar todas as referências feitas a ele na tabela de Parcelas.

A figura 2 ilustra os resultados para cada pedido avalidado:

relaciona2py4.png

Figura 2: Itens na tabela Parcelas para cada pedido na tabela Pedido.

Existem alguns modos de filtrarmos os datasets baseados em algum campo, dependendo do dataset (componente) utilizado:

- propriedades: Filter e Filtered;

- métodos SetRangeStart/SetRangeEnd ou SetRange, ApplayRange e CancelRange;

- cláusula WHERE de uma consulta SQL.

Irei exemplificar utilizando uma consulta SQL. Então, baseado no exemplo da figura 1, a consulta na tabela Parcelas ficaria assim:

SELECT NumParcela, VlrParcela, DatVencimento, DatPagamento
FROM Parcelas WHERE CodPedido = :CodPedido
ORDER BY NumParcela
Tendo colocado esta instrução SQL em um componente tipo query (chamarei QryParcelas), precisamos fazer com que ela seja executada com o parâmetro correto (CodPedido) a cada linha do dataset dos pedidos que estiver sendo selecionada (utilizarei um componente query e nome QryPedidos). Para isto devemos inicializar o valor parâmetro com o valor do campo CodPedido do dataset QryPedidos. Obs: cabe salientar que a qualquer momento que lemos o conteúdo de um campo de um determinado dataset, estamos lendo seu valor no registro corrente (a linha atualmente selecionada - independente de estarmos utilizando um DBGrid). Há duas formas de inicializarmos o parâmetro no momento em que um registro no dataset QryPedidos for selecionado e ambos fazem uso do componente TDataSource (chamarei DSPedidos) o qual deverá referenciar este dataset:
  1. selecionando na propriedade DataSource do dataset QryParcelas, o datasource DSPedidos. Para o correto funcionamento é necessário que o nome do parâmetro corresponda ao nome do campo no dataset de onde iremos obter seu valor; (o método mais simples)
  2. utilizando o evento OnDataChange do datasource DSPedidos, que sinalizará a mudança de registro, e implementando o código que inicializará o parâmetro e atualizará a consulta QryParcelas. No nosso exemplo ficaria mais ou menos assim:
    procedure TForm1.DSPedidosDataChange(Sender: TObject; Field: TField);
    begin
      QryParcelas.Close;
      QryParcelas.ParamByName('CodPedido').AsInteger := QryPedidos.FieldByName('CodPedido').AsInteger;
      QryParcelas.Open;
    end;

.

Espero ter ajudado na compreensão da "mecânica da coisa", porque isto ajudaria a resolver muitos problemas similáres, principalmente em relatórios onde sua aplicação seria mais comum.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Bom, o select deu certinho, agora vem o segundo problema, o cliente quer que

Quando ele clique em cima de um pedido no grid1, fiquem selecionadas as parcelas correspondentes ao mesmo no grid dois, seria mais ou menos assim

Ele clica no pedido no grid1, no caso o pedido 161

imagemgrid1gg0.png

Aí ficaria selecionado as parcelas referentes a esse pedido no grid2, assim

imagemgrid2px1.png

Agora, como eu faço para deixar selecionado estas linhas?

Eu vou colocar no OnDoubleClick do grid1 para ActivePageIndex:=1, que aparece o grid2, o das parcelas, e ele já está com o Options > dgMultiSelect como true, eu não tenho nem idéia de como deixar selecionadas estas linhas.

Qualquer dica, eu agradeço

Valeu!!!

Link para o comentário
Compartilhar em outros sites

  • 0

Bom pessoal, ainda não consegui fazer o proposto acima, e estava pensando, será que com um StringGrid eu poderia realizar este procedimento?, e de repente, se puder dar uma dica de como manipular este componente, para fazer estas tarefas eu ficarei muito grato.

Link para o comentário
Compartilhar em outros sites

  • 0

Oi, 'João Paulo Taraciuk'!

Eu tenho um dbgrid que possui um campo informando se o documento já foi impresso ou não. Quando ele está marcado como impresso o dbgrid muda automaticamente a cor das letras de azul para vermelho. Isto é feito no data set. Você não tem como fazer isto mudando a cor de fundo? para seu cliente é indiferente se está selecionado ou não. O que ele quer é que esteja destacado como se estivesse selecionado.

Procure aqui no forum (lugar onde encontrei a rotina para mudança de cor) a rotina para você adaptar à sua necessidade.

O código abaixo é o que eu uso em minha rotina

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
Field: TField; State: TGridDrawState);
begin
   if Table1.FieldByName('Pagou').Value = True then
      DBGrid1.Canvas.Brush.Color := clGreen
   else
      DBGrid1.Canvas.Brush.Color := clRed;
   DBGrid1.Canvas.FillRect(Rect);
   DBGrid1.DefaultDrawDataCell(Rect,Field,State);
end;

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Denis Courcy, deu certinho, coloriu as linhas da maneira que eu queria, eu peguei o número direto das células do DBGrid, o código ficou assim

procedure Tfrm_vendas.DBGrid3DrawDataCell(Sender: TObject;
  const Rect: TRect; Field: TField; State: TGridDrawState);
begin
      if DBGrid3.Fields[0].Value = DBGrid2.Fields[0].AsInteger then begin
      DBGrid3.Canvas.Brush.Color := clInactiveCaptionText;
      DBGrid3.Canvas.Font.Color:=clRed;
      end
   else
      DBGrid3.Canvas.Brush.Color := clWhite;
      DBGrid3.Canvas.Font.Color:=clBlack;
   DBGrid3.Canvas.FillRect(Rect);
   DBGrid3.DefaultDrawDataCell(Rect,Field,State);
end;

Agora, o único problema é que as linhas do DBGrid não mostram as linhas coloridas se elas estiverem para baixo do final do DBGrid, tem que rolar manualmente o BDGrid, porque da maneira que eu fiz, não setei nada na ZQuery. Mas destaca exatamente as linhas que forem do mesmo pedido.

Obrigado!!

Editado por João Paulo Taraciuk
Link para o comentário
Compartilhar em outros sites

  • 0

João Paulo Taraciuk, desculpe ter deixado meio de lado seu tópico, mas é porque perdi ele de vista mesmo. :blush:

Na minha visualização só vejo os posts do dia, e como não acessei no dia em que você postou...

Eu havia inicialmente entendido que no 2º DBGrid seriam mostradas apenas as parcelas do pedido selecionado no 1º DBGrid, e mais nada.

Agora vejo que você mostra todas as parcelas existentes e apenas que destacar aquelas referentes ao pedido selecionado.

Agora, o único problema é que as linhas do DBGrid não mostram as linhas coloridas se elas estiverem para baixo do final do DBGrid, tem que rolar manualmente o BDGrid, porque da maneira que eu fiz, não setei nada na ZQuery. Mas destaca exatamente as linhas que forem do mesmo pedido.

Que bom que a sugestão do Denis Courcy lhe ajudou.

Esta questão, de o registro ficar "escondido", não é bem um problema, já que no seu DBGrid você tem, a meu ver, mais informações do que deveria.

Mas você poderia contornar isto utilizando o locate no dataset deste 2º DBGrid, assim, você forçaria o reposicionamento das linhas no grid para que aquelas parcelas que não estão "visíveis" possam receber o foco e aparecerem. Entretanto, você pode ainda não obter um resultado bom. É testar para ver.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
desculpe ter deixado meio de lado seu tópico, mas é porque perdi ele de vista mesmo

Não tem problema não Micheus, eu só tenho a agradecer a vocês colegas do fórum, pois têm me ajudado muito.

Realmente no início do post o objetivo estava meio confuso, e utilizando a dica do Denis Courcy e a dica do Locate deu exatamente da maneira que eu precisava, ele destaca as linhas referentes ao pedido e com o locate vai direto para as linhas destacadas,aí vai o código, se alguém tiver com a mesma dúvida

procedure Tfrm_vendas.DBGrid3DrawDataCell(Sender: TObject;
  const Rect: TRect; Field: TField; State: TGridDrawState);
begin
   if DBGrid3.Fields[0].Value = DBGrid2.Fields[0].AsInteger then begin
   DBGrid3.Canvas.Brush.Color := clInactiveCaptionText;
   DBGrid3.Canvas.Font.Color:=clRed;
   end
 else
   DBGrid3.Canvas.Brush.Color := clWhite;
   DBGrid3.Canvas.Font.Color:=clBlack;
   DBGrid3.Canvas.FillRect(Rect);
   DBGrid3.DefaultDrawDataCell(Rect,Field,State);
end;
aí eu coloquei o locate no OnShow do TabSheet que é onde está o DBGrid3, ficando assim
procedure Tfrm_vendas.TS_Contas_receberShow(Sender: TObject);
begin
   ZQuery2.Locate('numero_documento',ZQuery1.Fields[0].AsString,[LoPartialKey,LoCaseInsensitive]);
   {No caso, Zquery2 é a do DBGrid3 e ZQuery1 é a do DBGrid2, 'numero_documento' é o nome do campo da ZQuery2 que está relacionado com a Zquery1}
end;

Valeu!!!

Editado por João Paulo Taraciuk
Link para o comentário
Compartilhar em outros sites

  • 0
Guest --valdmirv --

Olá todos tudo bem. Estou iniciando no mundo Delphi.

E tambem tentando fazer um programa de orcamento. A minha dúvida é muito parecida como do inicio tópico. O pessoal colocou bem mas para quem está iniciando muitas coisas que parece simples fica como dificilissimo m parece grego. Como: aonde colocar os comandos citados etc etc..

Já procurei em varios sites de delphi, apostilas etc e que se aplicou a minha duvida foi esse tópico.

Muitos dizem que é para outro comando.

Vamos lá: Na realidade o que quero é igual ao tópico mas sem a coloracao do que o amigo queria.

Tenho duas tabelas uma de servico e outra dependente chamada insumos. Usando 2 dbgrid : O primeiro deve apresentar o servico, e ao escolher o servico no segundo dbgrid deve aparecer apenas os insumos relativos ao selecionado acima, é o que micheus colocou na figura em cima. Igualzinho.

Ao selecionar o servico no primeiro dbgrid deve aparecer os insumos no segundo db, aí seleciono esses insumos e jogo para a tabela pedidos.

Logo em seguida devo selecionar outro servico e embaixo deve mostrar os insumos relacionados a esse servico gravo os servico na tabela Pedido até concluir o orcamento. Basicamente é isso aí . Já fiz um vinculo usando table -datasource mas a tabela servico na parte de cima aparece apenas um item e embaixo não seleciona o que foi definido.

Creio que preciso de algo mais.

Na realidade o tópico está esclarecedor para aquele que já possui um bom conhecimento que não é o meu caso.

Meus agradecimentos antipadamente

Link para o comentário
Compartilhar em outros sites

  • 0
Já fiz um vinculo usando table -datasource mas a tabela servico na parte de cima aparece apenas um item e embaixo não seleciona o que foi definido.

valdmirv, parece-me que você pode não estar com os vínculos configurados adequadamente.

Explique melhor, citando os datasets em questão, de que tipo são (table ou query), como você faz o filtro dos insumos ligados aos serviços (via: Datasource, Filter ou parametrização);

Quanto mais detalhes neste sentido, mais fácil de compreender a causa de seu problema e de exemplificar.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Caro Micheeus, Primeiro em novo form coloquei um Table chamando de tableservico fazendo sua ligacao com a tabela servico, a que vai ficar na parte de cima.

Depois coloquei um datasource que chamei de datasourceservico, ligando ele a table (em dataset escolhir "tableservico". Creio que liguei os dois.

Coloquei outra Table com o nome de tableinsumo e ligando ela a tabela insumo ( essa tabela insumo é dependente de servico). Creiei depois outro datasource que chamei de datasourceinsumo e liguei ao tableinsumo. O que fiz com um fiz com o outro ou seja -> datasourceservico -> table servico e datasourceinsumo -> tableinsumo. Vi na internet que deveria fazer uma ligacao do ligacao entre o tableservico e tableinsumo.

No tableservico em MasterSource selecionei o tableinsumo inclusive só tem essa possibilidade de escolha. Até ai nenhum erro.

Já fiz um lookup entre as tabelas servico e insumo na criação das tabelas , sem problema ( fazendo cod_servico do insumo dependente do cod_servico da tabela servico. Na tableservico ainda selecionei MasterFields , lá aparece os links de servico e insumo , seleciono os dois que estao ligados que são: Cod_servico do servico e cod_servico do insumo e adiciono na janela de baixo ficando assim(cod_servico -> cod_servico) dou ok. Sem Problemas.

Coloco 2 dbgrid : um em cima que será relativo a servico e outro embaixo relativo ao insumo. No de cima em datasource seleciono a tableservico. Ele é preenchido com os dados do servico. Aí é que aparece o problema aparece apenas o primeiro registro e na tabela de servico existem 2 servicos que cadastrei ou seja nessa tabela deveria aparecer os dois servicos para eu puder escolher um deles. Mas não aparece um ficou escondido.

Na dbgrid de baixo faco a mesma coisa : em datasource seleciono a tableinsumo : nessa tabela aparece todos os registros mas deveria aparecer apenas o que eu selecionasse na tabela de cima o que não acontece.

ao executar o programa funciona normalmente digo sem apresentar erro mas esse problema aparece: na parte de cima aparece apenas um item e na parte de baixo aparece todos os itens. Creio que necessita de algum comando ou linha de codigo que faça que a tabela de cima mostre todos os registros e não apenas o primeiros e que o dbgrid de baixo fique dependente do de cima que creio que já estar

Um detalhe que percebi é que parece que está funcioando ao contrario : se escolher no dbgrid de baixo , o insumo em cima muda o servico para o numero 2. Na realidade isso deveria ser ao contrario: ao selecionar um registro em cima deveria mostrar os ligados a ele em baixo.

A sequencia que fiz foi essa aí sem acrescentar nada.

É isso assim.

grato

Link para o comentário
Compartilhar em outros sites

  • 0
O que fiz com um fiz com o outro ou seja -> datasourceservico -> table servico e datasourceinsumo -> tableinsumo. Vi na internet que deveria fazer uma ligacao do ligacao entre o tableservico e tableinsumo.
valdmir, até esta parte você fez tudo certinho, mas ...

No tableservico em MasterSource selecionei o tableinsumo inclusive só tem essa possibilidade de escolha. Até ai nenhum erro.
... como eu imaginava, aqui está o "erro".

Entre as duas tabelas, quem é a tabela master (mestre) no relacionamento? Não é a servico?!

Esta propriedade MasterSource (fonte mestre), funciona da mesma forma. Ela indicará quem é a tabela master, que será utilizada para filtrar o campo que você indica em MasterFields. Logo, você deve usar esta propriedade na tabela filha (detalhe), quando você estará indicando a tabela pai (mestre) - ou seja, no seu dataset tableinsumo.

No mais, você está no caminho certo.

A título de sugestão, abrevie o table no nome dos seus datasets. Você verá em vários post o pessoal prefixando o nome de datasets usando algo como tab ou tb (para Tables), qry (Query), cds (ClientDataSet), spr (StoredProcedure), ....

Isto vai lhe poupar escrita. ;)

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Caro Micheus, perfeito. Ao fazer a inversão ficou como eu queria, Realmente perfeito.

Agora como fazer para que ao escolher os insumos na parte de baixo eu faça com eles fiquem gravados na tabela pedidos?

A medida que for selecionando quero jogá-los no pedido.

Algum manual de instrução SQL?

Muito agradecido pela ajuda

Valeu

Editado por valdmir
Link para o comentário
Compartilhar em outros sites

  • 0
Agora como fazer para que ao escolher os insumos na parte de baixo eu faça com eles fiquem gravados na tabela pedidos?

A medida que for selecionando quero jogá-los no pedido.

Algum manual de instrução SQL?

valdmir, como você está iniciando e está trabalhando com tables, não há porque falarmos em instruções SQL. Voce pode fazer este processo de forma mais direta: cada insumo selecionado, você "envia" para a tabela de itens dos pedidos.

Isso deve ser algo simples de você fazer. Supondo que você tenha um botão para enviar tal item para a tabela de pedidos, o processo seria mais ou menos assim:

procedure TForm1.BtnSelecionaItem(Sender :TObject);
begin
  tableItens_pedidos.Append;  // você "abre" um registro em branco
 // na sequencia você inicializa os campos com as informações provenientes
 // da tabela de insumos. 
 // Tenha em mente que é do item selecionado que estas informações 
 // estarão vindo. É simples assim.

  tableItens_pedidosCodigoInsumo.value = tableInsumoCodigoInsumo.Value;
 // ... move e inicializa outros campos aqui

  tableItens_pedidos.Post;  // você grava o item "enviado"
end;

Isto é bem simplista, mas seria o básico no seu caso. Voce provavelmente deveria verificar se tal item a ser "enviado" já não estaria no pedido e isto pode ser feito de vários modos: Findkey se há índice para o campo referente ao insumo na tabela de pedidos ou Locate.

Eu sugeriria que você começasse com algo como acima e observando como isto funcionará, você vai verificando o que precisa melhorar no código. Vá construindo seu conhecimento em etapas e você vai entender como cada uma delas influencia no todo.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Amigão, tentei mas ficou em parte . Olhe como ficou o que fiz:

TablePedidos.append;

TablePedidoscod_insumo.value:= Dbgrid2.Columns[0].

TablePedidos.Post;

Na segunda linha faltou os 2 pontos. Deu um trabalho danado para descobrir. Logo em seguinda faz referencia a tableinsumocoddigoinsumo mas na realidade o quero é jogar do Dbgrid2 e não direto da tabela de insumo

Quero jogar uma coluna do dbgri2 que está selecionado da linha tal . Ou seja só quero gravar a primeira coluna da linha tal. não sei se deu para entender.

Depois de Dbgrid2.columns[0] deve ter algo dizendo que é a linha selecionada para defenir dois pares (x, y).

Espero que entendam

grato

Link para o comentário
Compartilhar em outros sites

  • 0
Na segunda linha faltou os 2 pontos. Deu um trabalho danado para descobrir.
foi mal. :blush:

Logo em seguinda faz referencia a tableinsumocoddigoinsumo mas na realidade o quero é jogar do Dbgrid2 e não direto da tabela de insumo

Quero jogar uma coluna do dbgri2 que está selecionado da linha tal . Ou seja só quero gravar a primeira coluna da linha tal. não sei se deu para entender.

valdmir, eu entendi sim. Mas acho que você e que não me entendeu.

A linha selecionada no seu DBGrid2 é a linha correntemente selecionada no dataset que ele está mostrando. A coluna 0 do seu DBGrid2, está mostrando a informação de uma coluna neste seu dataset.

Eu sugiro que você entenda deste modo. Não pense no DBGrid como uma planilha do excel, porque ele não é, e desenvolver seu raciocínio deste modo vai lhe prejudicar.

Observe que seu DBGrid2 está mostrando apenas alguns registros da sua tabela insumos (são os referentes ao servico selecionado no outro DBGrid). Digamos que você tenha umas 5 linhas (5 linhas da tabela insumos) sendo mostrada no DBGrid2 e que hajam 3 colunas (codigo, descricao e preço).

Então, você deve entender da seguinte forma:

- A linha 1 representa a primeira linha na tabela insumo, para aquele servico selecionado no DBGrid1. A coluna 1 (columns[0]) apresenta o valor do campo (field) Codigo desta linha; a coluna 2, representa o valor do campo descricao e a coluna 3, o valor do campo preço.

- A linha 2 representa a segunda linha na tabela insumo, para aquele servico selecionado no DBGrid1. A coluna 1 (columns[0]) apresenta o valor do campo (field) Codigo desta linha; a coluna 2, representa o valor do campo descricao e a coluna 3, o valor do campo preço.

- e assim sucessivamente...

Depois de Dbgrid2.columns[0] deve ter algo dizendo que é a linha selecionada para defenir dois pares (x, y).
não tem não. Quando você lê a propriedade columns[0] (ou outra coluna qualquer), você poderá buscar qualquer referencia ao campo da linha atualmente selecionada. Neste caso você usaria DBGrid2.columns[0].Field.Value

Isto exposto, no caso de você precisar copiar todas as linhas sendo visualizadas no DBGrid2 (e não são todas existentes na tabela - lembre-se que você filtrou o campo servico), você deverá fazer um laço nestes moldes:

tableinsumo.First;
while not tableinsumo.EOF do
begin
  tablepedido.append;
  tablepedidocodigo.value := tableinsumocodigo.value;
// ou
// tablepedido.FieldByName('codigo').value := tableinsumo.FieldByName('codigo').value;
// ou
// tablepedido.Fields[0].value := tableinsumo.Fields[0].value;
  tablepedidodescricao.value := tableinsumodescricao.value;
  tablepedidopreco.value := tableinsumopreco.value;
  ... 
  tablepedido.post;
  tableinsumo.Next;
end;
...

se for para copiar a linha selecionada, já comentei no post anterior. E se for para pegar uma linha específica, tipo a 3ª linha, sem que seja a linha selecionada (tipo de procedimento pouco comum), então você deverá fazer o loop como se fosse para copiar todos os itens, porém, você usa um contador e executa o procedimento de cópia dentro do laço (o append, atribuições e posts) apenas quando o contador atingir o número da linha desejada.

Será que agora ficou mais claro?

Link para o comentário
Compartilhar em outros sites

  • 0

Ficou muito claro agora. Fiz como indicou das duas formas tanto para copiar um registro como para todos mostrados na dbgrid2. Mas quando uso da tableinsumocod_insumo ele para aí apontando sempre depois do insumo no "o" . Qaundo coloquei outro campo para teste por exemplo data e rodou mas ao clicar no botao para iniciar o preocesso aprensenta "key violation" e pára mostrando "end." no final.

grato

Link para o comentário
Compartilhar em outros sites

  • 0
Mas quando uso da tableinsumocod_insumo ele para aí apontando sempre depois do insumo no "o" .

valdmir, não entendi. Seria melhor postar o código e citar o problema.

Qaundo coloquei outro campo para teste por exemplo data e rodou mas ao clicar no botao para iniciar o preocesso aprensenta "key violation" e pára mostrando "end." no final.

Uma coisa básica, é que você não pode ter campos chaves duplicados na tabela. Este é o motivo da mensagem "Key violation" (violação da chave).

Supondo que você tenha adicionado um item do insumo ao pedido e depois tente adicioná-lo novamente, isto com certeza deverá gerar este erro. É aí que vai entrar aquele comentário que fiz, sobre verificar se um item já existe no pedido antes de incluí-lo, usando FindKey, Locate ... (você encontra alguma coisa aqui no forum, pesquisando por estas palavras)

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Amigo, segue o codigo:

tableinsumos.open;

tableinsumos.First;

while not tableinsumos.EOF do

begin

tablepedidos.append;

tablepedidoscod_insumo.value := tableinsumoscod_insumo.value;

tablepedidos.post;

tableinsumos.Next;

apresenta esses erros abaixo e fica com indicacao em "tableinsumoscod_insumo

[Error] CadastroPedidos.pas(78): Undeclared identifier: 'tableinsumoscod_insumo'

[Error] CadastroPedidos.pas(78): Missing operator or semicolon

[Fatal Error] VH.dpr(10): Could not compile used unit 'CadastroPedidos.pas'

Pode ser diferenca de campos nas duas tabelas?

o campo cod_insumo na tabela de pedidos está como I - long integer sem chave e o campo na tabela de insumos está cod-insumo é + - auto icrement com chave. Pode ser isso o erro?

mais uma vez grato

Link para o comentário
Compartilhar em outros sites

  • 0
tablepedidoscod_insumo.value := tableinsumoscod_insumo.value;

tablepedidos.post;

tableinsumos.Next;

apresenta esses erros abaixo e fica com indicacao em "tableinsumoscod_insumo

[Error] CadastroPedidos.pas(78): Undeclared identifier: 'tableinsumoscod_insumo'

valdmir, este erro significa que não há no dataset tableinsumo o campo cod_insumo adicionado - veja em fields editor se o campo está lá (e não deverá estar). Veja se você usou o mesmo nome de campo.

Pode ser diferenca de campos nas duas tabelas?
você tem que usar em cada dataset os campos que estão nas respectivas tabelas e usa no relacionamento os campos correlatos, mesmo que tenham nomes diferentes.

o campo cod_insumo na tabela de pedidos está como I - long integer sem chave e o campo na tabela de insumos está cod-insumo é + - auto icrement com chave. Pode ser isso o erro?
a questão do tipo, está correta. Mas, se você usou em insumos cod-insumo com o "-" e não com "_", então o erro está correto, porque você não teria o campo que ele está indicando.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Micheus, obrigado mais uma vez e desculpe pela insistencia.

Conseguir passar daquele ponto os codigos estão assim agora:

tableinsumos.open;

tablepedidos.Open;

tableinsumos.First;

while not tableinsumos.EOF do

begin

tablepedidos.edit;

Tablepedidos.Insert;

tablepedidos.append;

if not Tablepedidos.Locate('Cod_insumo', tableinsumos.FieldByName('cod_insumo').value,[]) then

tablepedidos.FieldByName('cod_insumo').value := tableinsumos.FieldByName('cod_insumo').value;

tablepedidos.post;

tableinsumos.Next;

end;

Mas ele apresenta um erro agora na linha " tablepedidos.post; e sinaliza aí o erro mostrando Tablepedidos: dataset not in editor or insert mode.

Como pode ver acima já existe tablepedidos.insert mas mesmo assim continua apresentando o erro.

o que posso fazer agora?

Link para o comentário
Compartilhar em outros sites

  • 0
Micheus, obrigado mais uma vez e desculpe pela insistencia.
tudo bem, mas vejo que você não leu muito a respeito do assunto ou não entendeu.

Você nunca vai colocar esta sequência para um mesmo dataset:

tablepedidos.edit;

Tablepedidos.Insert;

tablepedidos.append;

Edit => coloca o dataset em modo edição. Se o dataset estiver vazio(na primeira vez), equivale ao append;

Insert => insere uma nova linha "em branco" no dataset, na posição atual (baseado em que registro está posicionado);

Append => insere uma nova linha "em branco" no dataset, no final do mesmo.

Acho que você entendeu minha afirmação. ;)

Vamos lá... O motivo da mensagem "dataset not in editor or insert mode" (dataset não está em modo edição - ou mesmo inserção) deve-se ao fato de que voce primeiro o colocou em modo edição/inserção (usando os 3 métodos :huh: ) e depois utilizou o método Locate para verificar se o registro já existia. Sempre que você mover o "ponteiro" do registro no dataset, automaticamente ele sairá do modo edição/inserção (caso esteja) e em algumas situações, será automaticamente tentado realizar um Post (gravação dos dados).

Mas o que seria mais lógico? O mais lógico, é que você primeiro faça a verificação e caso seja necessário, aí sim, execute todo aquele procedimento para inclusão da nova informação. (esta lógica, é uma regra para tudo que você deva fazer uma verificação antes de executar uma ação).

Já vou antecipar, que para executar várias ações dependentes de um if .. then, você precisará utilizar o delimitador de blocos begin..end;.

Outra observação que estava por fazer, é que supondo que este procedimento seja feito através do pressionar de um botão (como você citou inicialmente) e que os dados de origem já estão sendo visualizados em um DBGrid (tabela insumos), não faz sentido que você utilize a linha "tableinsumos.open" porque esta tabela já se encontra aberta e sendo visualizada em um DBGrid (e assim deverá permanecer). A tabela pedidos (tablepedidos), também já deverá estar aberta visto que você deverá estar visualizando os itens do pedido no terceiro DBGrid.

Aplicando o que foi comentado, seu código ficará mais ou menos assim:

tableinsumos.First;
while not tableinsumos.EOF do
begin
  if not Tablepedidos.Locate('Cod_insumo', tableinsumos.FieldByName('cod_insumo').value,[]) then
  begin
    tablepedidos.append;
    tablepedidos.FieldByName('cod_insumo').value := tableinsumos.FieldByName('cod_insumo').value;
   // outras atribuições vão aqui...
    tablepedidos.post;
  end;
  tableinsumos.Next;
end;

Dica: o uso de identação (estas tabulações que organizam a visualização do fluxo do programa) ajudam muito, então, tente usá-las e aqui no forum, faça uso das TAGs CODE e /CODE (devem estar entre couchetes [...] e o seu código entre as duas tags) - ajuda muito na visualização e auxílio.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
Guest --valdmirv --

Obrigado mais uma vez . Mas continua apresentando erro. Grava apenas o primeiro item da tabela insumo e apresenta oseguinte erro :

Field value out of lookup table range.

Fiz um teste com outro campo que tenho na mesma tabela pedidos e funcionou normalmente apenas na tabela insumo apresenta esse problema.

grato

Link para o comentário
Compartilhar em outros sites

  • 0

Olá amigos, conseguir resolver o problema :D . Na realidade fiz duas coisas: a primeira foi verificar que o cod_insumo da tabela insumos estava em segundo lugar na tabela e não em primeiro lugar devido ser sequencial e chave.(não se realmente infuencia alguma coisa)!!!

Mudei para o primeiro campo da tabela funcionou mas quando escolhia o dbgrid1 o dbgrid2 não mostrava como antes .

Aí fiz um referential integrity na tabela insumo com a de servico que são ligadas. Pronto funciona normalmente sem travamentos.

Agora mas uma duvida: Por exemplo no dbgrid2 tenho 4 itens a serem gravados na tabela. Tenho que gravar de um a um. Como posso gravar os 4 de vez ou todos aqueles que aparecer no dbgrid2 e jogar de uma só vez? temo como fazer isso?

Micheus mais uma vez meus sinceros agradecimentos

grato

Editado por valdmir
Link para o comentário
Compartilhar em outros sites

  • 0
Agora mas uma duvida: Por exemplo no dbgrid2 tenho 4 itens a serem gravados na tabela. Tenho que gravar de um a um. Como posso gravar os 4 de vez ou todos aqueles que aparecer no dbgrid2 e jogar de uma só vez? temo como fazer isso?

valdmir, você está brincando comigo. Não é?! <_<

Leia denovo o post #17, bem no meio dele, onde eu começo dizendo: "Isto exposto, no caso de você precisar copiar todas as linhas ..."

t+

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152k
    • Posts
      651,7k
×
×
  • Criar Novo...