PDA

Ver la Versión Completa : Como Leo un TXT y lo guardo en una tabla?


danytorres
19-10-2004, 19:01:31
Buenos dias a todos los del foro, Sr. tengo un pequeño problema tengo un TXT de esta forma;

__________________________
005,26.00,0.00,285
006,26.00,0.00,285
007,26.00,0.00,285
008,26.00,0.00,285
__________________________

los datos estan separados por coma el primer dato el numero de empleado que es el me servira de guia para buscar en la tabla para guardar las dema variables, el motor es DBF, como hago para leer cada linea por ejemplo la primera es el empleado 005 tiene 26.00 horas extras y 286 horas acumuladas yo debo buscar su ficha en la tabla y guardar esta data y luego debo pasar a la suiente linea, hasta llegar al final. Como lo hago.
:confused:

AGAG4
19-10-2004, 19:12:20
Asigna el archivo a una variable tipo TextFile:
Pasos:
1.-Lees Linea
2.-Extraes Datos guiandote con el Separador "coma" (el Signo)
3.-Al separarlos vas a asignando cada dato al campo correspondiente.
4.- Regresar al Paso 1 hasta que No sea Fin de Archivo.

Que tengas buen día.

danytorres
19-10-2004, 20:02:15
Gracias por responder los pasos los conocos el problema es que la sintaxis no la conosco este es el codigo que utilizo para leer el TXT;

code:
_____________________________________________
procedure TConfiguracion.Button1Click(Sender: TObject);
Var
F1: TextFile;
Ch: string;
begin

AssignFile(F1, 'c:\text.txt');

Reset(F1);

Readln(F1, ch);

CloseFile(F1);
end;
_______________________________________________________

lo que se me dificulta es leer linea a linea para guardar en las tablas?? coo es la sintaxis????????

roman
19-10-2004, 20:09:36
Yo creo que la técnica que explico en este hilo (http://www.clubdelphi.com/foros/showthread.php?t=14398&highlight=TStringList) puede servirte.

// Saludos

AGAG4
19-10-2004, 21:56:59
Para leer de linea a linea utiliza un..

//Mientras no sea Fin de Archivo
While EOF(Archi) do begin
Readln(Archi,Linea);//Linea =String
........
{ ExtraeDatoDelimitador(Linea,'1',',');
Primer Parámetro: Linea=Variable String
Segundo Parámetro: '1' que dato va agarrar en este caso el dato de la 1er Coma
Tercero Parámetro: ','=Caracter Separador
}
Tabla.Insert;
Tabla.Campo1.Value:=ExtraeDatoDelimitador(Linea,'1',',');
Tabla.Campo2.Value:=ExtraeDatoDelimitador(Linea,'2',',');
Tabla.Campo3.Value:=ExtraeDatoDelimitador(Linea,'3',',');
Tabla.Campo4.Value:=ExtraeDatoDelimitador(Linea,'4',',');
Tabla.Post
end;

La opción que dice Roman de usar TStringList es Excelente, pero tengo la duda, como saber cual es el Delimitador para separar los datos????
ó ya esta estandarizado que se tiene que usar entre comillas separado con comas????

Espero te haya ayudado.
Saludos.

danytorres
19-10-2004, 22:02:49
Gracias por responder Roman, observe el hilo que me indicaste pero no se adapta a lo que quiero la sintaxi que uso es la siguiente;

Code:
______________________________________________________________
Var
ArchivoCsv, Campos: TStringList;
I, J: Integer;
F1: TextFile;
Ch: string;
begin
ArchivoCsv := TStringList.Create;
Campos := TStringList.Create;

try
ArchivoCsv.LoadFromFile('c:\HV.txt');
for I := 0 to ArchivoCsv.Count - 1 do
begin
Campos.Clear;
Campos.CommaText := ArchivoCsv[I];

for J := 0 to DataModule2.Table1.FieldCount do
begin
DataModule2.Table1.Insert;
DataModule2.Table1.Fields[J].Value := Campos[J];
DataModule2.Table1.Post;
end;
end;
finally
ArchivoCsv.Free;
Campos.Free;
end;
____________________________________________________________

El txt tien esta forma;

005,260.00,0.00,25
006,2.00,0.00,285
007,2600.00,15.00,25
008,55.00,45.00,25

el problema que tengo es que los datos estan separados por coma pero el detalle es que no tienen la misma longitud por ejemplo en la linea uno 005 es el codigo del trabajador que lo uso como referencia para buscar en la tabla, el 260.00 es dato que debo guaradar en la tabla al igual que el 0.00 y el 25, como hago para determinar el tamaño y guardar corectamente el campo sin cortarlo ?????????


Ayuda :(

danytorres
19-10-2004, 22:16:32
Gracias por responder AGAG4, el codigo me da error como declaro el ExtraeDatoDelimitador??

roman
19-10-2004, 22:23:07
Gracias por responder Roman, observe el hilo que me indicaste pero no se adapta a lo que quiero


Yo creo que se adapta perfectamente.


el problema que tengo es que los datos estan separados por coma pero el detalle es que no tienen la misma longitud


El ejemplo sirve justamente para cuando los campos no tienen longitud fija sino que están separados por un delimitador (coma en este caso).



por ejemplo en la linea uno 005 es el codigo del trabajador que lo uso como referencia para buscar en la tabla


Luego de la asignación

Campos.CommaText := ArchivoCsv[I];

en Campos[0] tienes el código a buscar.


el 260.00 es dato que debo guaradar en la tabla al igual que el 0.00 y el 25, como hago para determinar el tamaño y guardar corectamente el campo sin cortarlo

¿En qué parte del código piensas que se va a cortar el campo?

Igual que antes, una vez que llenas Campos en cada línea del archivo, Campos[0], Campos[1], Campos[3], etc. tendrán los valores de cada campo y con un Length(Campo[n]) calculas la longitud del valor del campo n-ésimo.

Está claro que la tabla dbase debe tener la estructura adecuada para recibir los valores pero esto ya no es una cuestión del código sino de que el archivo de texto proporcionado con los datos se ajuste al formato de la tabla.

// Saludos

AGAG4
20-10-2004, 01:31:49
ExtraeDatoDelimitador es una función que no esta en Delphi, tu mismo la tienes que programar, es por eso que te di el algoritmo para que lo implementes, pero aqui te doy un ejemplo para 2 campos lo puedes modificar para que sea para cualquier número de campos, para que te guies:

//Ahora el 2do parámetro es de Tipo Byte
//ExtraeDatoDelimitador(Linea,1,',');
function ExtraeDatoDelimitador( Linea:String; Parte:byte; Delimitador:char;):String;
var x,pos:byte;
Campo1,Campo2:String;
begin
Campo1:=''; Campo2:='';
Pos:=0;
//Separar Campo1
for x:=1 to length(Linea) do
if Linea[x]<>Delimitador then
Campo1:=Campo1+Linea[x]
else begin
Pos:=x;
Break;
end;

//Separar Campo2
for x:=Pos+1 to length(Linea) do
Campo2:=Campo2+Linea[x];
if Parte=1 then
result:=Campo1
else
result:=Campo2;
end;

Saludos.

AGAG4
20-10-2004, 02:10:21
Puedes Usar esta otra:
Ejemplo de uso:
Texto:='aaaaa,bbbbb,ccccccccc,dddddd'
For bucle:=0 to SeparaCount(Texto,',')
do ShowMessage(Separa(Texto,',',bucle) );

Function Separa(Linea: String; Separador: String; Indice: Integer): String;
var
aa,ll: Integer;
inici,conta: Integer;
begin
ll:=length(separador);
Result := '';
conta:=0;
// Treiem separadors del inici de la cadena
if copy(linea,1,ll)=separador then linea:=copy(linea,2,length(linea));
// Posem un separador al final si no es que hi sigui
if not(copy(linea,length(linea)-ll+1,ll)=separador) then Linea:=Linea+Separador;
inici:=1;
For aa:=1 to length(linea) do begin
if copy(linea,aa,length(separador))=separador
then begin
conta:=conta+1;
if conta=indice then begin
Result := copy(linea,inici,(aa)-inici);
Break;
end;
inici:=aa+ll;
end;
end;
end;
Function SeparaCount(Linea: String; Separador: String): Integer;
var
aa: Integer;
begin
if EsVuit(linea) then result:=0 else result:=1;
For aa:=2 to length(linea)-1
do if separador=copy(linea,aa,length(separador)) then result:=result+1;
end;

Saludos.

danytorres
20-10-2004, 23:51:52
Amigo roman necesito de tu ayuda, estoy utilizando el codigo que me diste lo adapte a mis necesidades pero me da un error que espero tu me puedas ayudar

Code:
______________________________________________________________
procedure TForm1.Button1Click(Sender: TObject);
Var
ArchivoCsv, Campos: TStringList;
I, J: Integer;

begin
ArchivoCsv := TStringList.Create;
Campos := TStringList.Create;

try
ArchivoCsv.LoadFromFile('c:\HV.txt');

for I := 0 to ArchivoCsv.Count -1 do
begin
Campos.Clear;
Campos.CommaText := ArchivoCsv[I];

for J := 0 to DataModule2.Table1.FieldCount -1 do
begin

DataModule2.Table1.Locate('Ficha',Campos[0],[]);

DataModule2.Table1.Edit;
DataModule2.Table1.Fields[1].Value := Campos[1];
DataModule2.Table1.Fields[2].Value := Campos[2];
DataModule2.Table1.Post;

end;

end;
finally
ArchivoCsv.Free;
Campos.Free;
end;
end;
_________________________________________________________

cuando corro el procedimiento me da este error "List index of bound (3)"

como hago para que no mede este error. Ayuda

:confused:

danytorres
21-10-2004, 13:16:00
Buenos dias amigos tengo un pequeño problema estoy utilizando el codigo que me dio el amigo Roman que me a servido de mucha ayuda pero me da un error cuando corro el procedimiento me da este error "List index of bound (0)", que debo hacer para que no me siga dando este error. Agradesco la ayuda amigos. :confused:

El codigo que utilizo es el siguente
____________________________________________________________
procedure TForm1.Button1Click(Sender: TObject);
Var
ArchivoCsv, Campos: TStringList;
I, J: Integer;

begin
ArchivoCsv := TStringList.Create;
Campos := TStringList.Create;

try
ArchivoCsv.LoadFromFile('c:\HV.txt');

for I := 0 to ArchivoCsv.Count -1 do
begin
Campos.Clear;
Campos.CommaText := ArchivoCsv[I];

for J := 0 to DataModule2.Table1.FieldCount -1 do
begin

DataModule2.Table1.Locate('Ficha',Campos[0],[]);

DataModule2.Table1.Edit;
DataModule2.Table1.Fields[1].Value := Campos[1];
DataModule2.Table1.Fields[2].Value := Campos[2];
DataModule2.Table1.Post;

end;

end;
finally
ArchivoCsv.Free;
Campos.Free;
end;
end;
_______________________________________________________


Que hago para corregirlo.????

roman
21-10-2004, 15:37:25
Supongo que el error te lo marca en la línea

DataModule2.Table1.Locate('Ficha',Campos[0],[]);

y diera la impresión de que la lista Campos está vacía. Revisa el formato del archivo de texto pues es posible que tenga algunas líneas en blanco.

// Saludos

danytorres
21-10-2004, 21:46:01
Gracias Roman por ayudarme tienes razon la ultima fila del TXT estaba en blanco y me daba ese error, este es el codigo que utilizo para realizar una busqueda de un campo que se encuentra en el txt y es buscado en una tabla e insertando los campos separados por coma en la misma tabla;

Code:
_______________________________________________________________
procedure TForm1.BitBtn3Click(Sender: TObject);
Var
ArchivoCsv, Campos: TStringList;
I, J: Integer;

begin
ArchivoCsv := TStringList.Create;
Campos := TStringList.Create;

try
ArchivoCsv.LoadFromFile('c:\HV.txt');

for I := 0 to ArchivoCsv.Count -1 do
begin
Campos.Clear;
Campos.CommaText := ArchivoCsv[I];


If DataModule2.Table1.Locate('Ficha',Campos[0],[locaseinsensitive,lopartialkey])then
begin
DataModule2.Table1.Edit;
DataModule2.Table1.Fields[1].Value := Campos[1];
DataModule2.Table1.Fields[2].Value := Campos[2];
DataModule2.Table1.Post;
end;


end;
finally
ArchivoCsv.Free;
Campos.Free;
end;
end;
_______________________________________________________
Gracia a todos;
:D

JuanBCT
27-10-2004, 14:35:47
Buenos días...... tengo que hacer algo muy parecido a lo de danytorres, por lo que me pareció innecesario comenzar un nuevo hilo.....
También tengo que pasar a una tabla datos de un TXT, y puse en práctica la técnica de separar los campos aquí explicada, pero tengo un problemita...

Supongamos que tengo esta línea:
P304 004/02500002/60/ 00000000364AAAA0000001LOMO ARCHIV. MANT.MIL.
Yo digo que pase campos[3] al campo descripción de mi tabla, y lo pasa bien.

Pero en el caso de esta otra línea...
P304 N/ 017125/3 / 00000000074AAAA0000010FUSIBLE

Como hay espacios en el 2do campo, la descripción ya no es campos[3]; por lo que pasa "/".... lo que sí se es que, con espacio o sin espacio, cada campo está en la misma posición dentro de la línea.

Mi pregunta es: como hago para expresar "de la posición 48 a la 73 es el campo descripción, haya espacios o no"?

Muchas gracias desde ya, espero haberme explicado bien.

JuanBCT
27-10-2004, 14:41:01
Perdón, acabo de comprobar algo.... ni siquiera el primero pasa bien, pues sólo pasa la cadena ARCHIV.
Bueno, de todas formas, definiéndolo de la manera que pregunto resolvería la cuestión......

roman
27-10-2004, 16:18:45
Mi pregunta es: como hago para expresar "de la posición 48 a la 73 es el campo descripción, haya espacios o no"?

Pero en tu caso no se trata de archivos donde los valores estén separados por un delimitador sino que se trata de campos de ancho fijo. En este caso puedes extraer cada campo con la función Copy.


var
Linea: String;
I: Integer;

begin
for I := 0 to ArchivoCsv.Count - 1 do
begin
Linea := ArchivoCsv[I];
...
Campo := Copy(Linea, 48, 73 - 48);
...
end;


Es decir, lo que tú conoces es la posición en que inicia cada campo (offset) y su longitud. Copy(Linea, Offset, Longitud) devuelve la parte de Linea que comienza en el caracter Offset y tiene longitud Longitud.

// Saludos

JuanBCT
27-10-2004, 18:52:24
Roman:
Me anduvo de maravilla, muchas gracias por tu ayuda... saludos!

danytorres
29-10-2004, 16:52:13
buenos dias amigos del foro, pense que tenia la solucion pero me da problemas este codigo

Code:
_______________________________________________________________
procedure TForm1.BitBtn2Click(Sender: TObject);
Var
Archivo, Campos: TStringList;
I, J: Integer;
begin
Archivo:= TStringList.Create;
Campos:= TStringList.Create;

try
Archivo.LoadFromFile('c:\HV.txt');


for I := 0 to Archivo.Count -1 do
begin
Campos.Clear;
Campos.CommaText:= Archivo[I];


If DataModule2.Table2.Locate('CODEMP',Campos[0],[]) then
begin
DataModule2.Table2.Edit;
DataModule2.Table2Z001.Value:= strtofloat(Campos[1]);
DataModule2.Table2.Post;
end;

end;

finally
Archivo.Free;
Campos.Free;
end;
_____________________________________________________

el campos[0] me trae un valor pequeño el cual busca en la table, cuando corro el procedimiento y desavilito el contenido del if no se detiene el proceso termina la busqueda bien con el locate pero el problema es cuando avilito la edicion y guardado el proceso de queda guindad. que puede ser???

Lepe
30-10-2004, 04:45:05
Hombre, date cuenta que no haces ningun tipo de comprobación, así el código es muy, pero que muy propenso a fallos y dolores de cabezas.

La única comprobación que haces es enel bucle for (no entra si está vacio el archivo)

Despues de asignar el CommaText, deberías poner condicionales por si se encuentra con una linea en blanco, o por si el segundo campo no tiene dato. Si no me equivoco, intentar convertir la cadena vacia '' a numero flotante te debe dar una excepción.

Si el locate no encuentra al empleado, ni si quiera muestra un mensaje por pantalla, así que se está comiendo un registro y ni si quiera te enteras.


el campos[0] me trae un valor pequeño el cual busca en la table, cuando corro el procedimiento y desavilito el contenido del if no se detiene el proceso termina la busqueda bien con el locate pero el problema es cuando avilito la edicion y guardado el proceso de queda guindad. que puede ser???

Lo he leido 3 veces y no me acabo de enterar de qué es lo que pasa, ni de lo que estas intentanto hacer :confused:

Sugiero más claridad en las preguntas si quieres claridad en las respuestas :p

Chalo78
08-02-2006, 22:37:28
Y como hacer lo mismo cuando las líneas están separadas por Tabuladores y comas???
LLevo casi 3 días tratando de hacer esto y aun cuando sé que es sencillo, por alguna razón no doy con el problema.
A modo de ejemplo, las lineas con la cadena de caracteres es la siguiente:

31/01/2006 12:06:38 $GPXTE,V,V,,,N,S*43
31/01/2006 12:06:38 $PGRME,15.0,M,22.5,M,27.0,M*1A
31/01/2006 12:06:38 $PGRMZ,6,f,3*1D
31/01/2006 12:06:38 $PGRMM,WGS 84*06
31/01/2006 12:06:38 $SDDBT,29.8,f,9.09,M,4.97,F*3F
31/01/2006 12:06:38 $SDDPT,9.09,0.00*57

En donde el valor que necesito rescatar es el que viene después de los caracteres "$SDDPT,". Es un archivo de texto que está cambiando cada varias décimas de segundos, por lo que es un archivo dinámico.
Lo único que me interesa, es capatar el dato que viene después de "$SDDPT,", ya sea en una DB o en un TLabel, me da igual.
Si alguien tiene la solución a mi problema, lo agradeceré. Demás está decir que ya probé los codigos de Delphi que están en este Hilo y no me funcionaron.