Fórum Cadastrar se não existir #623784

18/07/2025

0

Pessoal, o que estou fazendo é o seguinte:

No OnCreate do formulário populo um ComboBox com CODIGO e MOTIVO de uma TABELA
No OnChange deste combobox eu uso um filter para ir buscando o MOTIVO conforme vou digitando

Caso eu digite um MOTIVO que não está cadastrado, gostaria de fazer o cadastro de forma silenciosa, então pensei no seguinte:

  if edMotivo.Text <> EmptyStr then //só entra na rotina se o campo estiver preenchido
  begin
    try  //tenta obter o codigo. Se não conseguir(pois é uma nova descrição), gera a exceção e cadastra
      edCodMotivo.Text := IntToStr(Integer(edMotivo.Items.Objects[edMotivo.ItemIndex]));
    except
      if edCodMotivo.Text = EmptyStr then //significa que o motivo não existe no banco
      begin
        if not FrmDm.qrMotivos.Active then
          FrmDm.qrMotivos.Open;

        FrmDm.qrMotivos.Append;
        FrmDm.qrMotivosMOTIVO.AsString := edMotivo.Text;
        FrmDm.qrMotivos.Post;
        FrmDm.trBoletos.CommitRetaining;
        FrmDm.qrMotivos.Close;
      end;
    end;
  end;


Minha linha de pensamento foi de que se não tenho um código, significa que o item digitado é novo e precisa ser cadastrado, porém fazer esse cadastro gerando uma exceção me parece um pouco estranho, embora funcione.

Alguém teria uma sugestão diferente?
Renan

Renan

Responder

Post mais votado

18/07/2025

Não existe certo ou errado aqui. Existe o que funciona e o que não funciona.

Sempre podemos fazer um código que checa as possibilidades, evitando os erros.

Por exemplo, no seu caso, você poderia checar se o ItemIndex é maior ou igual a zero. Se for, é porque achou. Do contrário, é novo.

Porém, quando você digita algo e não encontra, não quer dizer que o que foi digitado está correto ou que é o motivo completo.

Se você pode digitar o que quiser, talvez fosse interessante detectar o pressionamento do ENTER, por exemplo, antes de verificar se inclui ou não o item. Além disso, pode perguntar se o usuário deseja cadastrar o novo motivo. Isto evitaria um monte de "lixo", cadastrado automaticamente, sempre que alguém digita algo errado.

Quanto a utilizar exceções, elas existem para ser utilizadas. Cabe a você definir o que é mais simples, legível e fácil de dar manutenção. É uma questão de gosto pessoal.

Arthur Heinrich

Arthur Heinrich
Responder

Gostei + 1

Mais Posts

18/07/2025

Arthur Heinrich

Outra coisa que deve fazer é, ao cadastrar um novo código/motivo, deve incluí-lo no ComboBox, evitando que o usuário tente cadastrar mais de uma vez a mesma mensagem.
Responder

Gostei + 1

21/07/2025

Renan

Olá, Arthur.

Eu pensei justamente no itemindex no final de semana e me parece uma forma mais pratica de detectar se o registro existe no banco.
No caso de recarregar os itens, eu faço o create do form, então após o cadastro, o formulário é fechado e caso o usuario acesse novamente aquele formulário, os dados serão carregados atualizados.
Questionar o usuario se deseja ou não cadastrar é uma boa alterativa para evitar "lixo" no banco, pois de fato um erro de digitação vai cadastrar um registro errado.

Obrigado pelas dicas.
Responder

Gostei + 0

21/07/2025

Renan

Não consigo usar uma comparação para verificar se o index é maior que 0, pois quando for uma nova descrição, vai gerar a exceção list index out of bounds (-1).
Então, até onde pude pensar, a melhor forma de cadastrar uma nova descrição é dentro da exceção.
No código, falta ainda adicionar uma pergunta questionando se desaja cadastrar, mas creio que o codigo deverá ficar assim.

procedure TFrmPgtoCheque.CadastraMotivo;
var
  Indice : Integer;
begin
  if edMotivo.Text <> EmptyStr then
  begin
    try  //tenta obter o codigo, se não conseguir(pois é uma nova descrição no edit, gera a exceção e cadastra
      Indice := Integer(edMotivo.Items.Objects[edMotivo.ItemIndex]);
    except
      if not FrmDm.qrMotivos.Active then
        FrmDm.qrMotivos.Open;

      FrmDm.qrMotivos.Append;
      FrmDm.qrMotivosMOTIVO.AsString := edMotivo.Text;
      FrmDm.spBoletos.ParamByName('TABELA').AsString := 'TBMOTIVOS';
      FrmDm.spBoletos.ExecProc;
      FrmDm.qrMotivosCODIGO.AsInteger := FrmDm.spBoletos.ParamByName('RESULT').AsInteger;
      FrmDm.qrMotivos.Post;
      FrmDm.trBoletos.CommitRetaining;

      FrmDm.qrMotivos.Close;
    end;
  end;
end;
Responder

Gostei + 0

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

Aceitar