Didiron 0 Denunciar post Postado Junho 5, 2010 Olá pessoal, me chamo Dionei Cardozo, eu frequento bastante o fórum de ASP aqui do imasters, já aqui no fórum de delphi sou um novato. Bem sou iniciante no Delphi, e estou tendo uns pequenos problemas para inserir, registros dentro de um record e depois dentro de um arquivo com a extensão ".bin". Eu estou fazendo um curso de Delphi, e já fizemos um sistema de cadastro de clientes, utilizando record, etc.. Eu utilizei uma boa parte daquele código, só que estou tendo alguns problemas. Eu tenho uma primeira Unit chamado UPrincipal,e nela eu tenho esse código: uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type alunos = record Codigo:Integer; Nome:String[200]; DataNascimento:String[25]; Sexo: String[50]; NomeMae:String[200]; NomePai:String[200]; Matricula: Integer; Serie: String[20]; CPF:String[20]; RG: String[20]; Sala:Integer; NotaPortugues: Integer; FaltasPortugues: Integer; NotaMatematica: Integer; FaltasMatematica: Integer; NotaHistoria: Integer; FaltasHistoria: Integer; end; Claro que tenho ainda mais códigos de botões, etc.. E tenho ainda um outro form CadastroAlunos, com esse código: procedure TFrmCadastroAlunos.BtnCadastrarAlunoClick(Sender: TObject); Var ender: alunos; Arq: file of alunos; begin AssignFile(Arq, ExtractFilePath(Application.ExeName)+'\alunos.bin'); rewrite(arq); int:= 1; seek(arq, filesize(arq)-1); read(arq, ender); int := ender.Codigo+1; ender.Codigo := int; ender.Nome := EdNomeAluno.Text; ender.DataNascimento = EdDataNasc.Text; ender.Sexo := EdSexo.Text; ender.NomeMae := EdNomeMae.Text ender.NomePai := EdNomePai.Text; ender.Matricula := EdMatricula.Text; ender.Serie := EdSerie.Text; ender.CPF := EdCpf.Text; ender.RG := EdRg.Text; ender.Sala := EdSala.Text; ender.NotaPortugues := EdNotaPortugues.Text; ender.FaltasPortugues := EdFaltasPortugues.Text; ender.NotaMatematica := EdNotaMatematica.text; ender.FaltasMatematica := EdFaltasMatematica.text; ender.NotaHistoria := EdNotaHistoria.Text; ender.FaltasHistoria := EdFaltasHistoria.Text; seek(arq, filesize(arq)); Write(arq, ender); reset(arq); seek(arq, filesize(arq)-1); read(arq, ender); Showmessage('Aluno cadastrado com sucesso!') end; Só que ele está me dando um erro na linha onde está o seguinte código: ender: alunos; E o erro é esse: Undeclared identifier: 'alunos' Alguém poderia pelo menos me dar uma luz de como resolver esse problema? Grato a todos. Abraços. Compartilhar este post Link para o post Compartilhar em outros sites
Daniel Sanches 0 Denunciar post Postado Junho 5, 2010 ele não está reconhecendo a classe alunos ... ela foi declarada na UPrincipal pelo que percebi... na outra unit onde você referencia "ender: alunos", você deve declarar lá em cima em uses, abaixo do implementation: "uses UPrincipal;" Compartilhar este post Link para o post Compartilhar em outros sites
Didiron 0 Denunciar post Postado Junho 5, 2010 Bem isso já resolveu o problema anterior, muito obrigado. Só que dai aconteceu um erro no int := 1; Como se essa variável não havia sido declarada, então lá dentro do vars, eu coloquei assim: Var ender: alunos; Arq: file of alunos; int: Integer; Assim ele não me retornou nenhume erro, mas me deixou uma observação lá em baixo assim: Value assigned to 'int' never used. Só que ele deixou rodar o programa. mas quando eu clico em cadastrar Aluno, ele me dá o seguinte erro: Project PrPrincipal.exe raised exception class EinOutError with message 'I/O error 131'.Process stopped. Use step or Run to cotinue. Voce sabe o que poderia estar acontecendo. Valeu pela ajuda. Compartilhar este post Link para o post Compartilhar em outros sites
Daniel Sanches 0 Denunciar post Postado Junho 6, 2010 quanto ao primeiro problema que você mencionou é o seguinte: observe esta parte do seu código: int:= 1; seek(arq, filesize(arq)-1); read(arq, ender); int := ender.Codigo+1; você colocou "int:= 1" e 3 linhas abaixo "int:= ender.Codigo+1"... o primeiro comando não serve pra nada, pois logo em seguida você está colocando outro valor na variável int. quanto ao seguindo erro mencionado, aparentemente está relacionado com o arquivo que está trabalhando ... tipo, o arquivo está bloqueado ou com algum erro ... tente localizar qual a linha que contém erro ... tente debugar o programa com F9 para localizar a linha que contém erro ... Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Junho 6, 2010 é, realmente o problema (como disse o Daniel Sanches) parece se no arquivo. Va la na linha "AssignFile(Arq, ExtractFilePath(Application.ExeName)+'\alunos.bin');" e precione F5, ela ficará marcada em vermelho. Quando rodadr o programa e clicar no botão para salvar o aluno, o delphi ira parar nestea linha. Vá apertando F8 até o erro aparecer. Depois poste ai em qual linha foi o erro. :D Compartilhar este post Link para o post Compartilhar em outros sites
Daniel Sanches 0 Denunciar post Postado Junho 6, 2010 um erro que constatei neste código é o seguinte: AssignFile(Arq, ExtractFilePath(Application.ExeName)+'\alunos.bin'); a função ExtractFilePath retorna o path já com \ no final... do jeito que tá aí vai retornar algo assim: c:\path da aplicação\\alunos.bin corrija nos demais locais e verifique se o erro persiste ... Compartilhar este post Link para o post Compartilhar em outros sites
Didiron 0 Denunciar post Postado Junho 6, 2010 Então seguindo o que o Raficcha disse, o erro apareceu nesta linha: seek(arq, filesize(arq)-1); Compartilhar este post Link para o post Compartilhar em outros sites
Daniel Sanches 0 Denunciar post Postado Junho 6, 2010 pra você que pretende trabalhar com records, dá uma lida nesse tutorial abaixo: Iniciando Aqui pretendo empregar técnicas para aumentar as possibilidades de criação RAD do Delphi obtendo, desta maneira, a criação simplificada de inúmeros aplicativos. Importante - Todas as técnicas empregadas aqui funcionam perfeitamente desde o ambiente Turbo Pascal. Definimos a estrutura deste tipo de Arquivo antes do próprio corpo do objeto principal, dentro do comando Type, segundo o exemplo: Trecho de Código: type cartao = record posic : integer; // Posição do Cartão Nome : String[30]; // Nome Ender : String[30]; // Endereço Empres : String[30]; // Empresa Telef : String[30]; // Telefone Observ : String[30]; // Observações ExcCar : Boolean; // Cartão Excluído : S ou N end; TF_Cartao = class(TForm) // resto do objeto tudo em linguagem Object Pascal é definido basicamente como Variáveis. O próprio Formulário, por exemplo é uma, o conceito dos arquivos nativos não escapam desta definição, então vamos criar as variáveis que ajudarão o controle do Arquivo: Trecho de Código public RegCartao:Cartao;// Registro que contém a estrutura tpCartao:file of Cartao: // Nome interno do arquivo NomArq: TfileName; // guarda o nome externo end; Para o acesso (ou criação) do Arquivo , pode ser utilizada a seguinte função, que através do comando AssignFile associa o arquivo com o comando Reset e caso o arquivo não exista prepara-o para a Criação do mesmo com o comando ReWrite: Trecho de Código: function TF_Cartao.GeraArquivo : Boolean; begin AssingFile(tpCartao, NomArq); {$ I-} Reset(tpCartao); {$ I-} if IoResult <> 0 then ReWrite(tpCartao); // para a primeira criação Para a abertura do arquivo pode ser usado o objeto TOpenDialog do seguinte modo: if OpenDialog1.Execute then begin NomArq := OpenDialog1.FileName; if not GeraArquivo then Raise Exception.Create ('Arquivo não encontrado'); // Arquivo Inválido Importante - Sempre que se Utilizar desta função não se esqueça de fechar o arquivo com o comando CloseFile. Localizando e Carregando A localização dos registros dentro do arquivo é feita através do comando Seek os registros dentro deste tipo de arquivo são localizados através da posição física do registro, para localizar um determinado registro do Arquivo construiremos a seguinte função: Trecho de Código: function TF_Cartao.Carrega (PosReg: Interger) : boolean; begin result := False; Seek(tpCartao, PosReg); If not EOF (tpCartao) then begin // Não é Fim de Arquivo Read (tpCartao, RegCartao); if RegCartao.ExcCar then // Cartão Excluído MessageDlg('Este Cartão foi excluído, utilize a recuperação', mtInformatio, [mbOK], 0); else result := True; end; end; Importante - Podemos construir arquivos de índices contendo apenas dois campos, a Posição física dentro do arquivo e o campo ao qual queremos que sirva como chave. Realizando periodicamente a organização deste arquivo paralelo por este campo chave definido, então toda a pesquisa é realizada neste arquivo por localização seqüencial e depois localiza-se o registro no arquivo principal através do comando Seek. Podemos mostrar determinado registro do Arquivo depois de Localizado atrav;es de objetos do tipo Edit colocados num formulário, mas lembre-se que eles não estão vinculados como os objetos DBEdit então devemos controlar o que deverá ser mostrado bem como o tamanho do que pode será inserido. Em alguns casos podemos nos utilizar do objeto MaskEdit: Trecho de Código: procedure TF_Cartao.Mostra; begin with RegCartao do begin EdtNome.Text := Nome; EdtEnder.Text :=Ender; EdtEmpres.Text := Empres; EdtTelef.Text := Telef; EdtObserv.Text := Observ; end; end; Para carregar os dados dos objetos do tipo Edit para o registro do Arquivo podemos criar um procedimento único para a utilização da Inclusão (Tipo=1), Alteração(Tipo=2), Exclusão Lógica (Tipo = 3) e Recuperação Lógica (Tipo = 4): Trecho de Código: procedure TF_Cartao.CarrArq(Tipo, PosReg : Interger); begin with F_Cartao do begin case tipo of 3 : ExcCar := True; 4 : ExcCar := False; else with RegCartao do begin Posic := PosReg; Nome := EdtNome.Text; Ender := EdtEnder1.Text; Empres := EdtEmpres.Text; Telef := EdtTelef.Text; Observ := EdtObserv.Text; ExcCar := False; end; end; Seek (tpCartao, PosReg); // Relocaliza Write (tpCartao, RegCartao); // Gravar end; end; Para limitar o tamanho dos campos pode ser criado um procedimento Global que não deixa o Edit ultrapassar o número de casas pre-determinada: Trecho de Código: procedure TF_Cartao.DevMaior(var Campo: Tedit; Tam : Interger); begin if Length (campo.Text) >Tam then begin Campo.Text := Copy (Campo.Text,1,Tam); MessageBeep (0); end; end; Coloque no evento OnChange de cada Edit a limitar a chamada ao procedimento, por exemplo, no edit do Nome: Trecho de Código procedure TF_Cartao.EdtNomeChange (Sender: Tobject); begin DevMaior(EdtNome, 30); end; Manipulação dos Dados Aproveitando os procedimentos realizados vamos criar o proce3dimento para inserir um novo registro: Trecho de Código: procedure TF_Cartao.InseriClick(Sender: Tobject); begin GeraArquivo; CarrArquivo(1, FileSize(tpCartao)); CloseFile(tpCartao); end; Importante - Não esqueça de limpar os Edits comText := "antes de incluir O procedimento para atualizar o registro N (sendo Na posição - em Inteiro -- do registro a alterar): Trecho de Código procedure TF_Cartao.AtualizaClick(Sender : TObject); begin GeraArquivo; if Carrega (N) then CarrArq(2, N); CloseFile(tpCartao); end; O procedimento para Excluir, é realizado apenas logicamente, marcando determinado registro N (sendo N a posição - em Inteiro - do registro a excluir): Trecho de Código procedure TF_Cartao.ExcluiClick(Sender : TObject); begin GeraArquivo; if Carrega (N) then CarrArq(3, N); CloseFile(tpCartao); end; Importante - Não esqueça de Proteger os Edits com ReadOnly com True antes de excluir O procedimento que servirá para Recuperar o registro N (sendo N a posição - em Inteiro - do registro a recuperar) do arquivo excluído logicamente: Trecho de Código: procedure TF_Cartao.RecuperaClick(Sender : Tobject); begin GeraArquivo; if Carrega (N) then CarrArq(4, N); CloseFile(tpCartao); end; Importante - Não esqueça de proteger os Edits com ReadOnly com True antes de recuperar. Para eliminar do arquivo os registros marcados como excluídos (ou Excluídos logicamente), pode ser utilizado um arquivo temporário idêntico e feito um Balance-Line, varrendo o arquivo principal e copiando os registros determinados, seguindo os seguintes passos: 1. Crie as variáveis para um arquivo temporário: Trecho de Código: private RegCartaoB : Cartao; // Registro que contém a estrutura tpCartaoB : file of Cartao; // Nome interno do arquivo 2. disponibilize a unidade que contém variáveis do Arquivo principal: Trecho de Código: uses fCartao; 3. Crie o procedimento: Trecho de Código: procedure TF_Cartao.ButEliminaClick(Sender: TObject); var IndReg, Corre: Integer; NomArqB: TfileName; begin // Cria o arquivo temporário NomArqB := Copy (F_Cartao.NomArq,1, Legth (F_Cartao.NomArq) -4) + '.TMP'; AssignFile(tpCartaoB, NomArqB); {$I-} Reset(tpCartaoB); {$I-} if IoResult <> 0 then ReWrite(tpCartaoB); // Carrega os Registros IndReg := 0; Corre := 0; Repeat Seek(F_Cartao.tpCartao,Corre); if not EOF(F_Cartao.tpCartao) then begin Read(F_Cartao.tpCartao, F_Cartao.RegCartao); With F_Cartao.RegCartao do begin if not ExcCar then begin // se o registro não tiver excluído transfere os Registros. RegCartaoB.Posic := IndReg; RegCartaoB.Nome := Nome; RegCartaoB.Ender := Ender; RegCartaoB.Empres := Empres; RegCartaoB.Telef := Telef; RegCartaoB.Observ := Observ; RegCartaoB.ExcCar := ExcCar; Seek (tpCartaoB, FileSize (tpCartaoB)); Write (tpCartaoB, RegCartaoB); // grava Inc(indReg); end; end; end; Inc(Corre); until EOF(F_Cartao,tpCartao); CloseFile(F_Cartao.tpCartao); // Elimina o arquivo Erase(F_Cartao.tpCartao); CloseFile(tpCartaoB); Rename(tpCartaoB, F_Cartao.NomArq); // Renomeia o arquivo end; A mesma técnica pode ser utilizada para a organizar o arquivo por qualquer campo. Repita os passos 1, 2 e 3 e recrie o procedimento principal da seguinte maneira: Trecho de Código: procedure TF_Cartao.ButOrganizaClick(Sneder: TObject); var IndReg, Numero: Interger; Campo, Monta: String; Achei: Boolean; NomArqB : TfileName; begin // acertar a lista Lista.Items.Clear; IndReg := -1; with F_Cartao do repeat Inc(IndReg); Seek (tpCartao, IndReg); if not EOF(tpCartao) then begin Read (tpCartao, RegCartao); with RegCartao do begin if RadNome.Checked then Campo := Nome; if RadEnder.Checked then Campo := Ender; if RadEmpres.Checked then Campo := Empres; if RadTelef.Checked then Campo := Telef; if RadObserv.Checked Then Campo := Observ; Campo := Campo + ' {' + IntToStr(Posic) +'}'; end; E_Organiz.Lista.Items.Add(Campo); end; Util EOF(F_Cartao.tpCartao); // cria arq. Temporário NomArqB := copy(F_Cartao.NomArq, 1, Length (F_Cartao.NomArq)-4) + '.TMP'; AssingFile(tpCartaoB, NomArqB); {$ I-} Reset (tpCartaoB); {$ I-} if IoResult <> 0 then ReWrite(tpCartaoB); for IndReg := 0 to (F_Organiz.Lista.Items.Count -1) do begin // Carrega os Registros Campo := Lista.Items[IndReg]; Achei := False; Monta := ''; for numero := 1 to Legth (Campo) do begin // Localiza o Registro Correto. if Achei then begin if Campo[Numero] = ']' then Break; Monta := Monta + Campo[Numero]; end; if Campo[Numero] = '{' then Achei := True; end; Seek(F_Cartao.tpCartao, StrToInt(Monta)); Read(F_Cartao.tpCartao, F_Cartao.RegCartao); With F_Cartao.RegCartao do begin // Acerta Registro RegCartaoB.Posic := IndReg; RegCartaoB.Nome := Nome; RegCartaoB.Ender := Ender; RegCartaoB.Empres := Empres; RegCartaoB.Telef := Telef; RegCartaoB.Observ := Observ; RegCartaoB.ExcCar := ExcCar; end; Seek(tpCartaoB, FileSize (tpCartaoB)); // grava Write(tpCartaoB, RegCartaoB); end; CloseFile (F_Cartao.tpCartao); Erase(F_Cartao.tpCartao); // Elimina o Arquivo CloseFile(tpCartaoB); Rename(tpCartaoB, F_Cartao.NomArq); // Renomeia end; Terminando tudo Nota-se, com tudo o que foi explanado, que o conjunto Delphi com a estrutura do Record pode ampliar drasticamente o número de aplicativos construídos, e evitar a construção de sistemas que se utilizam de partes de estruturas de dados sejam desenvolvidas com bancos complexos e acessos via BDE gastando tempo bem para os seguintes aplicativos: >> Coletores de informações; >> Importação e Exportação de arquivos em mídia rápida; >> Em aplicativos de Jogos, criação de Scorescontendo os melhores resultados; >> Criação de arquivo de configuração para sistemas coorporativos mas também não precisa exagerar tentando reinventar a roda e recriando inúmeras funções para criar um complexo sistema de Bancos de Dados quando as opções de mercado nesta área são vastas, recomendo a utilização visando o seguinte propósito: >> Sistemas de Pequenos / Médio Porte: dBase, Access e Paradox >> Sistemas de grande porte: MS-SQL e Interbase >> Sistemas Coorporativos e Integrados: ORACLE Todos estes bancos acima citados se comportam excelentemente bem nestes espaços pré-determinados. texto retirado do site www.ramosdainformatica.com.br Autor: Raphael Rissato Compartilhar este post Link para o post Compartilhar em outros sites
Didiron 0 Denunciar post Postado Junho 6, 2010 Eu olhei o artigo mas infelismente nãoo ajudou muito.. Compartilhar este post Link para o post Compartilhar em outros sites
Daniel Sanches 0 Denunciar post Postado Junho 8, 2010 olha ... quanto ao erro neste comando seek, como não tenho muita experiência trabalhando com record, deixo aos amigos do fórum tentar te ajudar .... do mais, estarei acompanhando o tópico para tentar ajudar ... Compartilhar este post Link para o post Compartilhar em outros sites
Didiron 0 Denunciar post Postado Junho 8, 2010 Então pessoal, depois de muito tempo quebrando a cabeça, eu consegui resolver o problema. Eu comecei a refazer todo os sistema do 0. :mellow: E dai funcionou logo na primeira vez. huahuahuahuahuahuahuahhauahahauhaua Aquele ero eu até agora ainda não solucionei, mas foi bom que funcionou agora, espero nunca mais passar por este erro. Agora só estou tendo alguns pequenos problemas em trabalhar com Strnggrid, mas vou ver se consigo resolver se não eu volto aqui ao fórum. :D :D Agradeço a quem ajudou. ;) Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Junho 9, 2010 Então seguindo o que o Raficcha disse, o erro apareceu nesta linha: seek(arq, filesize(arq)-1); Hum... qual é o tamanho do arquivo? Se este arquivo estiver vazio, vai dar erro sim! Ele vai tentar dar seek na posiçõ "-1". Compartilhar este post Link para o post Compartilhar em outros sites