GARANTIR DESCONTO

Fórum Erro em rotina de auto incremento. #267895

09/02/2005

0

Boa Tarde amigos,

Tenho uma pequena aplicação onde controla um numero sequencial em um campo chave. Uso ACCESS com ADO e coloquei a procedure abaixo no evento ONNEWRECORD da tabela DESPESAS_DIARIAS do Data Module DATAMOD. Não sei porque mas no momento em que a rotina ´DataMod.ADOTable_Despesas_Diarias.Last;´ é processada o DELPHI emite a mensagem: ´iNDICE OU CHAVE PRIMARIA NAO PODE CONTER UM VALOR NULL´.

VOCES PODERIAM ME AJUDAR E DEFINIR O QUE ESTA ERRADO?


procedure TDataMod.ADOTable_Despesas_DiariasNewRecord(DataSet: TDataSet);
var MainKey: integer;
LancCod: string;
begin
{ Inicializando variáveis }
DataMod.ADOTable_Despesas_DiariasDES_DATA.Value := Date;

{ Determinando um novo código de Lançamento }
DataMod.ADOTable_Despesas_Diarias.Open;
DataMod.ADOTable_Despesas_Diarias.Last;
MainKey := DataMod.ADOTable_Despesas_DiariasDes_Cod.AsInteger;
Inc(MainKey);
{DataMod.ADOTable_Despesas_Diarias.Insert;}
LancCod := formatcurr(´0000000000´,MainKey);
DataMod.ADOTable_Despesas_DiariasDes_Cod.AsString := LancCod;
DataMod.ADOTable_Despesas_Diarias.Refresh;
end;


Muito Obrigado,

Alexsandro


Alexsandro

Alexsandro

Responder

Posts

09/02/2005

Gandalf.nho

Você está inserindo um valor na tabela e ao mesmo tempo indo no último registro dela sem completar o registro recém-inserido. Tente fazer sua pesquisa do último valor num dataset separado para evitar problemas. Outra sugestão, em vez de dar LAST para obter o valor, tente usar uma query do tipo SELECT MAX(campo_chave) FROM tabela.


Responder

Gostei + 0

09/02/2005

Alexsandro

Oi Gandalf,

Entendo que coloquei esta rotina no evento ON NEW RECORD da tabela e este evento é chamado no momento de eu pressionar o botão ´+´ do navegador certo? O que você está me dizendo é que neste momento eu ja´estou com aquela famosa linha em aberto (com * indicando novo registro) e que não posso me mover para o ultimo por que ele valida a chave primaria vazia. LEGAL: Entendi tudo...Só não consigo entender por que muitas pessoas aqui do fórum colocam rotinas simples, sem a necessidade de usar QUERY, como a de baixo e dizem que ela funciona. O que preciso fazer para ela funcionar? Seria um outro evento? Sem usar o DBNAGIVATOR? Resumindo: Eu gostaria de fazer a rotina funcionar sem a necessidade de query. Agradeço mais comentários...

Veja o código abaixo que encontrei no Fórum:

´Caro amigo, esperimente fazer assim, no momento de adicionar um novo registro, sem a necessidade da query:

var cod:integer; //criar a variavel cod
begin
TBCandidatos.last; //ultimo registro da tabela
cod:=TBCandidatosCodCandidato.value; //pega o valor do último código
inc(cod); //incrementa 1
DBEdit1.text:=inttostr(cod); //define DBEdit1´

Onde coloco este evento? É possível usá-lo com o DBNAVIGATOR?

Muito Obrigado,

Alexsandro Áfio


Responder

Gostei + 0

09/02/2005

Gandalf.nho

Tente pôr Required=False nos TFields do seu dataset e além disso, não atribua valores para outros campos (como o campo tipo DATE em seu código) antes de fazer o LAST para obter o último valor. Deve ser isso que está causando o problema.


Responder

Gostei + 0

09/02/2005

Alexsandro

GEEENNNNIALL GANDALF,

Foi so tirar a inicialização da Data que funcionou...Agora o problema está com o evento .INSERT que está chamando a routina ONNEWRECORD novamente...tipo ficando em LOOP...Provavlemnete isso acontece porque o botão ´+´ do DBNAVIGATOR já chamou a rotina INSERT certo? Você teria alguma sugestão....????? POis sem o evento .INSERT, no momento que vou atribuir o novo código ao campo do Data Module ele dá um erro dizendo que a tabela não está em INSERT ou EDIT???

Alex


Responder

Gostei + 0

09/02/2005

Gandalf.nho

Nos meus antigos programas em Paradox eu usava o evento BeforeInsert para buscar o valor do novo registro. (testando antes se o campo já está preenchido ou não)


Responder

Gostei + 0

09/02/2005

Alexsandro

Oi Gandalf,

Sei que tô perto de resolver este mistério, mas ainda não foi dessa vez.
Estou em um ´Se correr o bicho pega, Se ficar o bicho come...´

Tanto no evento OnNewRecord como no BeforeInsert, quando o evento .INSERT abaixo processa ele recomeça a rotina e fica em LOOP.

Se eu não colocar o EVENTO .INSERT o Delphi dar a mensagem de erro no momento em que eu estou atribuíndo o novo código ao campo chave: ´dataset is not in edit or insert mode´...

E Agora? O que é que eu faço???

Muito Obrigado,

Alex

procedure TDataMod.ADOTable_Despesas_DiariasNewRecord(DataSet: TDataSet);
var MainKey: integer;
LancCod: string;
begin
{ Determinando um novo código de Lançamento }
DataMod.ADOTable_Despesas_Diarias.Open;
DataMod.ADOTable_Despesas_Diarias.Last;
MainKey := DataMod.ADOTable_Despesas_DiariasDes_Cod.AsInteger;
Inc(MainKey);
DataMod.ADOTable_Despesas_Diarias.Insert;
LancCod := formatcurr(´0000000000´,MainKey);
DataMod.ADOTable_Despesas_DiariasDes_Cod.AsString := LancCod;
DataMod.ADOTable_Despesas_Diarias.Refresh;
end;


Responder

Gostei + 0

09/02/2005

Gandalf.nho

Primeiro, retire aquela linha do Open, que é desnecessária (afinal, a tabela já está aberta). Nos meus antigos sistemas, havia uma variável Integer declarada na seção Private do Form para armazenar o valor da chave. No evento BeforeInsert era executado o comando LAST para obter o valor e incrementá-lo (outra coisa, use o comando DisableControls antes de dar o LAST para evitar a atualização desnecessária dos DBEdits. Não esqueça de reativá-los depois). Depois no evento BeforePost era atribuído o valor ao campo, checando primeiro se o mesmo já tinha valor ou não.


Responder

Gostei + 0

10/02/2005

Alexsandro

Oi Gandalf,

Obrigado pelo seu empenho, mas acredito que sua solução não resolve meu problem por conta de um detalhe: Eu gostaria que o novo número aparecesse na tela no momento em que eu pressiono o botão de inclusão ´+´ do DBNAVIGATOR. Se eu colocar a atribuição do campo no evento BEFOREPOST, o novo número só vai ser visto depois.

Talvez tenha uma solução: Posso usar no form uma variável EDIT no lugar de uma DBEDIT vinculada à tabela, atualizo esta
variável e quando for salvar, no BEFOREPOST. O que você acha disso?

Mesmo assim gostaria de entender porque uma rotina que todos falam ser tão simples simples não funciona da forma que colocam.
Se alguém puder ajudar eu agradeço.

Alex


Responder

Gostei + 0

10/02/2005

Gandalf.nho

Talvez haja diferenças de um mecanismo de acesso a dados para outro. Meu exemplo era Paradox com BDE, o seu caso usa ADO. No caso da sua sugestão do Edit, estava olhando o código e vi que o valor era atribuído direto ao DBEdit e não ao campo


Responder

Gostei + 0

10/02/2005

Alexsandro

Oi Gandalf,

Matei a Xarada: O que acontece é que o evento .LAST coloca a tabela em status de BROWSE. Por isso no código sugerido pelo pessoal eles colocam o .INSERT novamente. Acontece que não posso colocar o evento .INSERT dentro do ONNEWRECORD ou BEFOREINSERT porque isso chama o evento novamente causando o LOOP. E, se não coloco o INSERT, ocorre um erro de exceção dizendo que a tabela não está em status de INSERT ou EDIT. LOGO, a lógica do pessoal está furada.

Quando deixei de executar o LAST e no lugar disso estou gravando o código do ultimo numero em uma outra tabela. com isso tudo se resolveu e agora entendi porque algumas pessoas sugeriram códigos usando outra tabela e a prórpia aplicação da Borland: MASTAPP usa outra tabela. Obrigado por suas explicações pois me ajudaram...

Alex


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar