Fórum Erro no CDS #371445
20/06/2009
0
Tenho o seguinte problema:
Precisava de uma tabela contendo todos os estados brasileiros. Fiz a tabela, liguei as outras q precisa à ela e até ai td bem...
Só que td vez q executo a minha aplicação, aparece o seguinte erro:
CDSFORNECEDOR : TYPE MISMATCH FOR FIELD ´UF´, EXPECTING: STRING ACTUAL: FMTCDFIELD.
Só q assim, os campos são todos do msm tipo, e eu não sei o pq desse erro
Se alguem ja teve um problema parecido e sabe a solução...
Boa tarde a todos!!
Juli
Curtir tópico
+ 0Posts
20/06/2009
Discorpio
Este acontece porque voce inicialmente deve ter configurado o campo na tabela como FMTCDField e ao linká-lo nos componentes do Delphi ele assumiu este formato. Quando voce decidiu mudar o campo para String ele continuou como FMTCDField.
Faça o seguinte:
1º) Click duas vezes dentro do componente que lê a tabela e ao abrir o Fields Editor, selecione todos os campos e apague.
2º) Feche a conexão com o banco clicando no SQLConnection ou outro componente qualquer de conexão com o banco e desative a conexão
3º) Ative novamente a conexão.
4º) Depois click com o botão direito dentro do Fields Editor e em Add All Fields para ajustar para o tipo de campo certo.
Gostei + 0
21/06/2009
Juli
Sem quere abusar da sua bondade, vc sabe como programar os botões:
Adicionar
Excluir
Alterar
Se puder me ajudar nessa tbm, fico muito grata
Bom domingo!! :D
Gostei + 0
21/06/2009
Discorpio
Primeiramente eu preciso saber qual o banco de dados que voce usa e também quais os componentes que voce está fazendo a conexão. :?: :?: :?:
Gostei + 0
21/06/2009
Juli
Estou usando o Interbase 6.5...
E os componentes são: Query, ClienteDataSet, DataSetProvider e DataSource..
Se puder me ajudar...
Gostei + 0
22/06/2009
Discorpio
Ótimo, fizeste uma boa opção. Voce está utilizando os componentes DBExpress.
Primeiramente gostaria de explicar como funciona os componentes do DBExpress para que voce tenha uma idéia ampla do funcionamento de cada um, pois isso é fundamental para o desenvolvedor.
O DBExpress utiliza os seguintes componentes:
1º) [color=blue:da12486964]SQLConnection:[/color:da12486964] Responsável por fazer a conexão com o banco de dados, interpretando cada driver do mesmo, ele também é responsável por controlar a transação no momento em que os dados são enviados e ou solicitados do banco.
2º) [color=blue:da12486964]SQLTable:[/color:da12486964] Responsável por ler uma tabela do banco, ele é conectado ao SQLConnection por meio da sua propriedade SQLConnection e a tabela é configurada na propriedade TableName. A leitura da tabela é feita de modo que ele traz todos os registros da tabela.
3º) [color=blue:da12486964]SQLQuery[/color:da12486964] Este componente é similar ao SQLTable, porém tem um recurso a mais, permite o desenvolvedor escrever a sua instrução SQL prórpria, que é feito através da propriedade SQL.
4º) [color=blue:da12486964]SQLStoredProc:[/color:da12486964]: Este componente é também similar ao SQLTable, porém com a diferença de ler procedimentos armazenados dentro do Banco de Dados (Stored Procedure), onde a Stored Procedure é configurada através da sua propriedade StoredProcName.
5º) [color=blue:da12486964]SQLDataSet:[/color:da12486964]. Este é o melhor de todos, pois engloba todas as funções do SQLTable, SQLQuery e SQLStoredProc, onde na sua propriedade Command Type voce define se vai ser ctTable, ctQuery ou ctStoredProc. Em caso de ctTable ou ctStoredProc, na propriedade Command Text voce define o nome da tabela e ou Stored Procedure, em caso ctQuery ele abre umas reticências do lado da propriedade onde clicando nela, vai abrir uma janela para voce configurar a instrução SQL necessária.
Bom, todos os componentes de leitura da dados no banco acima citados (SQLTable, SQLQuery, SQLStoredProc e SQLDataSet, ), retornam os dados e se desconectam do banco, e são componentes que retornam dados ´Unidirecional´, ou seja, a navegação dos registros é ´Forward Only´ (Somente para frente), se voce movimentar o registro do primeiro para o décimo registro por exemplo, ele não volta ao primeiro. Por esta razão é que criaram os demais componentes abaixo citados.
6º) [color=blue:da12486964]DataSetProvider:[/color:da12486964] Responsável por extrair os dados e enviar ao ClientDataSet para atualização dos dados na cache de HD.
7º) [color=blue:da12486964]ClientDataSet: [/color:da12486964] Já este componente é Bidirecional, permite a navegação do registros para frente e para trás. Recebe os dados do DataSetProvider para atualização do mesmo no cache de disco.
Bom, agora vamos ao código.
De acordo com o que foi dito acima, voce deve ter reparado que a atualização dos dados são feitos em duas etapas. Na primeira etapa, os dados são extraídos do Banco de Dados e armazenado no cache do HD onde estes dados são manipulados pelo ClientDataSet, portanto toda atualização dos dados (Inclusão, Edição, Deleção e Consulta) tem que ser feita atráves do ClientDataSet. Na segunda etapa, os dados tem que ser atualizados no banco físico através da transação do SQLConection.
1º) [color=blue:da12486964]Botão Incluir:[/color:da12486964]
procedure TForm1.btnIncluirClick(Sender: TObject); begin ClientDataSet1.Append; end;
2º) [color=blue:da12486964]Botão Editar:[/color:da12486964]
procedure TForm1.btnEditarClick(Sender: TObject); begin ClientDataSet1.Edit; end;
3º) [color=blue:da12486964]Botão Excluir:[/color:da12486964]
procedure TForm1.btnExcluirClick(Sender: TObject); begin if MessageBox(Handle, PChar(´Deseja excluir o registros´), ´Exclusão´, MB_YESNO + MB_ICONQUESTION) = IDYES then ClientDataSet1.Delete; end;
4º) [color=blue:da12486964]Botão Salvar:[/color:da12486964]
procedure TForm1.btnSalvarClick(Sender: TObject); begin ClientDataSet1.Post; end;
5º) [color=blue:da12486964]Botão Cancelar:[/color:da12486964]
procedure TForm1.btnCancelarClick(Sender: TObject); begin ClientDataSet1.Cancel; end;
Bom, aqui estão configurados os procedimentos da primeira etapa, ou seja, a atualização dos dados no cache do HD (ClientDataSet), agora vamos a segunda etapa: Temos que escolher o momento em que estes dados serão empacotados pelo DataSetProvider e enviados ao componente (SQLTable, SQLQuery ou SQLDataSet) que por sua vez enviará ao SQLConnection para realizar a transação dos dados. Este momento é voce que escolhe, pode ser no momento antes em que o SQLConnection é desativado, no momento em que se fecha um formulário (esta é opção ideal), e etc. Vamos escolher esta última opção:
Selecione o Form e no Object Inspector, vá aba Events e dentro da caixa de texto do combo do evento OnCloseQuery dê dois cliques para montar a sua procedure
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var mens: String; TD: TTransactionDesc; begin mens := ´Salvando dados no Banco.´ + #13; mens := mens + ´Se houver falha na conexão,´ + 13; mens := mens + ´O form não será fechado´ + 13; TD.TransactionID := 1; TD.IsolationLevel := xilREADCOMMITTED; SQLConnection1.StartTransaction(TD); try MessageBox(Handle, PChar(mens),´Fechando form e salvando dados´,MB_OK); ClientDataSet1.ApplyUpdates(0); SQLConnection1.Commit(TD); CanClose := True; // Aqui permite o fechamento do Form. except MessageBox(Handle, PChar(´Houve erro na conexão com o banco´),´falha na conexão´,MB_OK); SQLConnection1.Rollback(TD); CanClose := False; // Aque evita o fechamento do Form; end; end;
Bom, por enquanto é só, se houver qualquer dúvida, é só postar
Gostei + 0
22/06/2009
Juli
Me ajudou mto msm..
Mais ainda tem uma questão..sem querer abusar da sua boa vontade..
Eu tenho a seguinte tela(exigida pelo professor)
1-campo para o usuario digitar o que quer encontrar
2-Botão pesquisar
3-Botão ok
4-Botão sair
Esse botão OK ao ser clicado deverá exibir os dados encontrados pelo usuário na lookup da outra form
Vc saberia me dizer como faço isso???
Desde já agradeço toda a ajuda q tem me dado!!
Gostei + 0
22/06/2009
Romario
Normalmente se ve respostas laconicas sobre um assunto. Esta foi uma explicação completa. Quem sabe, sabe e deve ensinar e nos temos a obrigação de agradecer a que se dispoem a tão bem detalhar o problema.
Muito Obrigado
Romario
Gostei + 0
24/06/2009
Discorpio
Romario, eu é que agradeço a vocês, pois a suas dúvidas são o meu aprendizado.
Juli, vou explicar a você como se faz um formulário de pesquisa genérico, que servirá para voce usá-lo em todas as tabelas, pois esta é vantagem de se trabalhar com linguagem orientada a objetos, voce pode construir classes, bibliotecas, formulários e etc, como genéricos que servem para vários aplicativos.
Vamos lá.
1º) Vamos primeiro construir um formulário para pesquisa. Vá no menu ´File-> New -> Form´, e quando aparecer o form na tela, configure no Object Inspector as seguintes propriedades com os respectivos valores:
Align = alCustom; BorderStyle = bsDialog; Height = 124; Name = frmMaskInputBox; Position = poScreenCenter; Width = 347; WindowState = wsNormal;
2º) Agora vá na palheta Additional e arraste para dentro desse form, dois componentes TBitBtn, que são componentes idênticos aos TButtons, porém eles permitem colocar ícones como imagens neles, onde já há algumas imagens embutidas, e voce verá isto quando configurá-los conforme abaixo:
Primeiro BitBtn Caption = OK; Kind = bkOk // aqui ele já configura a imagem ModalResult = mrOk; Name = btnOk; Segundo BitBtn Caption = Sair // poderia ser Sancelar, porém seu professor pediu Sair Kind = bkCancel; ModalResult = mrCancel; Name = btnCancel
3º) Arraste para dentro do form um componente TMaskEdit da palheta Additional e na propriedade Name configure como ´MaskEdit´ e coloque também um componente TLabel da palheta Standard no Form e o seu Name como ´lblPrompt´. Ajuste os componentes de modo tal que eles fiquem posicionados de maneira adequada dentro do form, ou seja, o TLabel lblPrompt em cima do MaskEdit e os dois TBitBtns alinhados em baixo do MaskEdit.
4º) Ainda no formulário ´frmMaskInputBox´, voce vai declarar uma variável do tipo string com o nome ´Value´, no bloco Public da classe do form, assim:
type
TfrmMaskInputBox = class(TForm)
MaskEdit: TMaskEdit;
lblPrompt: TLabel;
btnOK: TBitBtn;
btnCancel: TBitBtn;
private
{ Private declarations }
public
{ Public declarations }
Value: string; // aqui voce declara essa variável.
end;
5º) No Delphi, vá no menu Project -> Options e voce verá uma caixa de listagem com o nome ´Auto-Create Forms´ e uma outra com o nome ´Available´ Forms´, em Auto-Create Forms selecione o frmInputBox e click no botão ´>´ para transferí-lo para a caixa Available Forms, isto significa dizer que voce configurou o frmInputBox para não ser criado (Instanciado em memória) quando da iniciação do Aplicativo, se por ventura voce quiser transferir também os demais forms poderá fazê-lo, a exceção do Form principal que necessita ser criado na iniciação do aplicativo, porém os demais forms voce deve abrir com o código idêntico ao código de abertura do frmInputBox que vou te passar mais adiante, em caso de transferí-los para Available Forms.
6º) Ainda no frmInputBox, vamos configurar os eventos OnClick dos TBitBtns, clique duas vezes no BitBtn OK e configure o seguinte código.
procedure TfrmMaskInputBox.btnOKClick(Sender: TObject); var I: Integer; begin if MaskEdit.EditMask = ´´ then Value := MaskEdit.Text else for I := 1 to Length(MaskEdit.Text) do if MaskEdit.Text[I] <> ´ ´ then Value := Value + MaskEdit.Text[I] else begin Value := ´Não foi preenchida todas as casas númericas´ + 13; Value := Value + ´Preencha todas as casas númericas´; Application.MessageBox(PChar(Value), ´Erro´, MB_OK + MB_ICONERROR); Value := ´´; ModalResult := mrCancel; Break; end; end;
7º) Agora com o TBitBtn Sair, clique duas vezes nele, e eis o código:
procedure TfrmMaskInputBox.btnCancelClick(Sender: TObject); begin Value := ´´; end;
Bom para esse Post não ficar muito grande, vou postar essa parte agora e logo em seguida eu posto a a outra.
Gostei + 0
24/06/2009
Discorpio
Bom, pra começar, para tornar esse form genérico em todos os forms, bom será criar uma biblioteca para todos os Forms,
portanto vamos criar uma Unit separada que servirá de biblioteca, e vou também aproveitar para incluir algumas rotinas
auxiliares que com certeza lhe trará certas vantagens, como por exemplo, exibir mensagens. Deixemos de lenga lenga e vamos
ao que interessa.
Antes porém, eu esqueci ainda de fazer uma coisa no form frmMaskInputBox, que foi renomear a sua Unit para MaskInputBox,
assim:
Salve a Unit MaskInputBox.
1º) No Delphi, vá no menu ´File -> New -> Unit´ e voce vai acrescentar uma Unit pura com esse código:
unit Unit1; interface implementation end.
2º) Renomeie a Unit com o nome ´Biblio´ de Biblioteca ou com o nome que voce quiser, assim:
3º) Acrescente o seguinte código na Unit:
unit Biblio; interface uses Windows, SysUtils, Forms, Controls, MaskInputBox; type TMsgs = (msgAviso, msgErro); var UserLog, Perfil, Mens, Box: string; procedure Mensagem(APrompt, ACaption: string; Msg: TMsgs); function YesNo(APrompt, ACaption: string): boolean; function MaskInputBox(const ACaption, APrompt, AMask: string): string; implementation procedure Mensagem(APrompt, ACaption: string; Msg: TMsgs); var Flags: Integer; begin if Msg = msgAviso then Flags := MB_OK + MB_ICONWARNING + MB_APPLMODAL else Flags := MB_OK + MB_ICONERROR + MB_APPLMODAL; Application.MessageBox(PChar(APrompt),PChar(ACaption),Flags); end; function YesNo(APrompt, ACaption: string): boolean; var Resp, Flags: Integer; begin Flags := MB_YESNO + MB_ICONQUESTION + MB_APPLMODAL; Resp := Application.MessageBox(PChar(APrompt),PChar(ACaption),Flags); if Resp = IDYES then Result := True else Result := False; end; function MaskInputBox(const ACaption, APrompt, AMask: string): string; begin Application.CreateForm(TfrmMaskInputBox, frmMaskInputBox); with frmMaskInputBox do try Caption := ACaption; lblPrompt.Caption := APrompt; if AMask = ´*´ then begin MaskEdit.PasswordChar := ´*´; MaskEdit.EditMask := ´´; end else begin MaskEdit.PasswordChar := #0; MaskEdit.EditMask := AMask; end; if ShowModal = mrOk then Result := Value; finally FreeAndNil(frmMaskInputBox); end; end; end.
4º) Salve a Unit Biblio, depois vamos a Formulário que vai receber a informação, ou seja, o Lookup (Pensei que fosse um DBGrid) que voce mencionou, na seção Uses desse form, declare a unit Biblio, assim:
5º) Coloque um botão, podendo ser TButton mesmo ou TBitBtn, com o Caption ´Pesquisa´ e Name ´btnPesquisa´ e digite o seguinte código no evento OnClick:
procedure TfrmPesquisa.btnPesquisaClick(Sender: TObject); begin Box := MaskInputBox(´Pesquisando o campo Lookup, ´Digite um valor para o Lookup´, ´´); if Box = ´´ then Mensagem(´Campo em branco ou operação cancelada´,´Abortando pesquisa´,msgErro) else with SQlQuery1 do begin Close; SQL.Clear; SQL.Add(´Select * From Tabela ´); SQL.Add(´Where Campo = :CAMPO´); ParamByName(´CAMPO´).AsString := Box; Open; if Eof then Mensagem(´Registro não encontrado´,´Pesquisa encerrada sem sucesso´,msgAviso); end;
Comentários.
1º) Dentro desse formulário que vai receber o valor pesquisado, presumo que voce configurou um componente TSQLQuery cujo TDataSetProvider e TClientDataSet já esteja configurado dentro do form, ao realizar tal pesquisa e vai trazer os Dados para DataSetProvider e depois para ClientDataSet, e consequentemente este esteja ligado um TDataSource que vai linkar a outros componentes como DBGrid por exemplo. E citei o exemplo do TSQuery, pode ser também um TSQLDataSet.
2º) Repare as variáveis ´Box´ e ´Mens´, bem como o método ´Mensagem´ que voce não precisou declarar dentro do seu Form que vai receber a pesquisa, isto pois elas já estão declaradas dentro da Unit Biblio como globais, isto evita de voce ficar declarando variável a toda hora, bem como também os métodos, assim como a função MaskInputBox que automaticamente vai criar o Form de pesquisa para voce e vai lhe retornar o valor para dentro da variável ´Box´
3º) Se houver um componente TDBGrid linkado a um TDataSource que esteja linkado ao TClientDataSet, que esteja linkado a um TDataSetProvider, e por último linkado a este TSQLQuery, quando a pesquisa retornar algum registro no TSQLQuery, automaticamente o DBGrid será preenchido.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)