Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Exportar DBGrid a txt con formato. (https://www.clubdelphi.com/foros/showthread.php?t=73109)

darkone2k4 01-04-2011 05:08:25

Exportar DBGrid a txt con formato.
 
Salu2 amigos.

Se me ha encomendado la tarea de realizar la exportación de datos de un archivo MDB a un TXT.
La información a exportar primero debe ser visualizada en un DBGRID.
Sé como recorrer el DBGRID y pasar los datos al archivo TXT, pero la exportación debe realizarse con ciertas condiciones, como por ejemplo:
1.- Los campos se deben justificar a la derecha.
2.- Los campos deben ir de forma continua, sin ningún tipo de separador. Esto lo sé hacer.
3.- Cada campo tiene su tamaño específico al momento de exportar.

Por ejemplo:
Código del comprobante, debe tener un largo 10.
Numero del documento, debe tener un largo 10.
Fecha del documento, debe tener un largo 8.
Razón Social, debe tener un largo 50.
Pero si el dato ocupa menos caracteres, como agrego los espacios a la izquierda para completar el largo, si el dato tiene un largo de 3 caracteres por ejemplo?

Espero que se haya entendido lo que escribí XD.

salu2.



ecfisa 01-04-2011 07:52:32

Hola darkone2k4.

Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  BM: TBookMarkStr;
  i: Integer;
  s: string;
  ArchTexto: TextFile;
begin
  AssignFile(ArchTexto,'C:\A_LA_DERECHA.TXT');
  Rewrite(ArchTexto);
  BM:= DBGrid1.DataSource.DataSet.Bookmark;
  DBGrid1.DataSource.DataSet.DisableControls;
  DBGrid1.DataSource.DataSet.First;
  while not DBGrid1.DataSource.DataSet.Eof do
  begin
    s:= '';
    for i:= 0 to DBGrid1.FieldCount - 1 do
    begin
      (* llenar con blancos a la izquierda (largo físico de campo - largo) y concatenar *)
      s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth -
                           Length(DBGrid1.Fields[i].AsString)) +
                           DBGrid1.Fields[i].AsString;
    end;
    Writeln(ArchTexto, s); (* guardar campos formateados del registro  *)
    DBGrid1.DataSource.DataSet.Next;
  end;
  CloseFile(ArchTexto);
  DBGrid1.DataSource.DataSet.Bookmark:= BM;
  DBGrid1.DataSource.DataSet.EnableControls;
end;

Un saludo.

darkone2k4 01-04-2011 07:55:14

Hola ecfisa.

Muchas gracias por la respuesta.
Voy a probar de inmediato el código que me has dado.


salu2.


----------------EDIT---------------
Acabo de probar el código y funciona muy bien.
Ahora tengo una consulta.

Los datos que muestro en el DBGRID, como los puedo ajustar para que el largo corresponda a los requerimientos??, ya que en algunos campos se supera en número de caracteres por campo que se necesitan en el archivo TXT.

salu2.



ecfisa 01-04-2011 08:33:14

Hola darkone2k4.

Revisá estos enlaces:

Colocar Ancho De columna de un DBGrid ...
Ajuste de columnas en un DBGrid
AutoAjustar un dbgrid

Un saludo.

darkone2k4 01-04-2011 08:45:18

gracias nuevamente por la respuesta ecfisa.

Hice una revisión de los links que me diste, pero no se ajusta a lo que necesito.

Creo que expliqué mal lo que necesito.
La verdad es que en el DBGRID me da lo mismo el largo( caracteres ) que tengan los campos, lo que es importante es que al momento de pasarlos al archivo de texto, éstos cumplan con los requerimientos de longitud.
Estoy jugando con copy, trim, length para ver si por ahí me funciona.

desde ya, muchas gracias.

urixiv 01-04-2011 09:02:34

Pues si te he entendido bien, ya lo tienes.
Para cada campo miras su longitud con el length.
Y si es más corto que la longitud que debe tener en el txt le añades los espacios. Y sino pues haces un Copy de 0 al numero de caracteres que quieres o bien un LeftStr.

Espero haber sido de ayuda!:)

darkone2k4 01-04-2011 09:17:57

gracias por la respuesta urixiv.

al final lo he hecho utilizando Copy.
Claro que como son 15 columnas de distinto tamaño en longitud, he incluido un case donde, dependiendo de la columna, hiciera el recorte de caracteres.

salu2.


ecfisa 01-04-2011 09:28:18

Hola darkone2k4.

Me alegro que lo hayas podido realizar pero, no entiendo la necesidad de usar copy para ajustar el largo al guardar en el archivo.
De eso se encargan la propiedad DisplayWidth y Length en la línea:
Código Delphi [-]
  s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth -
                      Length(DBGrid1.Fields[i].AsString)) +
                      DBGrid1.Fields[i].AsString;
Si no alterás los valores de presentación tendran por defecto los declarados en el DataSet y por lo tanto el campo cumplirá los requerimientos de longitud. Es decir que un campo de 10 caracteres con 3 ocupados, se guardará con 10 caracteres (7 espacios y los 3 ocupados).

Un saludo.

darkone2k4 01-04-2011 17:19:31

gracias por responder nuevamente.

Tuve que utilizar Copy, ya que la información que se muestra en la dbgrid, viene de un archivo excel, el cual tiene un formato predeterminado y al pasarlo a TXT algunos campos quedan con una longitud de 255 caracteres, es por eso que he utilizado COPY para acortar los campos.

salu2.


Cita:

Empezado por ecfisa (Mensaje 395376)
Hola darkone2k4.

Me alegro que lo hayas podido realizar pero, no entiendo la necesidad de usar copy para ajustar el largo al guardar en el archivo.
De eso se encargan la propiedad DisplayWidth y Length en la línea:
Código Delphi [-]
  s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth -
                      Length(DBGrid1.Fields[i].AsString)) +
                      DBGrid1.Fields[i].AsString;
Si no alterás los valores de presentación tendran por defecto los declarados en el DataSet y por lo tanto el campo cumplirá los requerimientos de longitud. Es decir que un campo de 10 caracteres con 3 ocupados, se guardará con 10 caracteres (7 espacios y los 3 ocupados).

Un saludo.


ecfisa 01-04-2011 18:12:06

Hola darkone2k4.

Ahora entiendo, gracias por la aclaración.

Un saludo.

darkone2k4 01-04-2011 18:38:47

Cita:

Empezado por ecfisa (Mensaje 395421)
Hola darkone2k4.

Ahora entiendo, gracias por la aclaración.

Un saludo.

de nada amigo.

gracias por la ayuda brindada..

salu2.

darkone2k4 05-04-2011 12:52:07

Hola nuevamente.

Te hago una consulta??
Utilizando el código que pusiste, se puede modificar para asignar un número determinado de caracteres dependiendo de las columnas del dbgrid?, he tratado de hacerlo pero no lo he podido lograr.

salu2.

ecfisa 09-04-2011 05:33:03

Hola darkone2k4.
Cita:

Utilizando el código que pusiste, se puede modificar para asignar un número determinado de caracteres dependiendo de las columnas del dbgrid?
Dependiendo de que cualidad de las columnas, ¿ del ancho ?

Un saludo.

ezequiel913 02-06-2011 04:28:27

informacion!!
 
Cita:

Empezado por ecfisa (Mensaje 395365)
Hola darkone2k4.

Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  BM: TBookMarkStr;
  i: Integer;
  s: string;
  ArchTexto: TextFile;
begin
  AssignFile(ArchTexto,'C:\A_LA_DERECHA.TXT');
  Rewrite(ArchTexto);
  BM:= DBGrid1.DataSource.DataSet.Bookmark;
  DBGrid1.DataSource.DataSet.DisableControls;
  DBGrid1.DataSource.DataSet.First;
  while not DBGrid1.DataSource.DataSet.Eof do
  begin
    s:= '';
    for i:= 0 to DBGrid1.FieldCount - 1 do
    begin
      (* llenar con blancos a la izquierda (largo físico de campo - largo) y concatenar *)
      s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth -
                           Length(DBGrid1.Fields[i].AsString)) +
                           DBGrid1.Fields[i].AsString;
    end;
    Writeln(ArchTexto, s); (* guardar campos formateados del registro  *)
    DBGrid1.DataSource.DataSet.Next;
  end;
  CloseFile(ArchTexto);
  DBGrid1.DataSource.DataSet.Bookmark:= BM;
  DBGrid1.DataSource.DataSet.EnableControls;
end;

Un saludo.





hola ecfisa!!
solo queria pedirte si podes mandarme un mensaje detallandome mas o menos que se hace con la rutina, osea se que es para exportar los datos del DBgrid a un archivo TXT pero si podes comentar las lineas de codigo puntuales, por ejemplo para que sirve el BOOKMARK, como hacer para que tambien se exporten los nombres de las columnas y que no este todo hacia la derecha, para saber como se maneja, asi no es solo copy-paste, sino saber como funciona.

desde ya muchas gracias!!
saludos

ecfisa 02-06-2011 07:05:13

Hola ezequiel913.

Te documento el código linea a linea:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  BM: TBookMarkStr;
  i: Integer;
  s: string;
  ArchTexto: TextFile;
begin
  // Asociar un nombre de archivo a una variable de tipo File
  AssignFile(ArchTexto,'C:\A_LA_DERECHA.TXT');
  // Crear un archivo, abrirlo
  Rewrite(ArchTexto);
  // Guardar posición actual del DataSet
  BM:= DBGrid1.DataSource.DataSet.Bookmark;
  // Desactivar el mostrado en los controles data-aware asociados al DataSet
  DBGrid1.DataSource.DataSet.DisableControls;
  // Posicionarnos en el primer registro del DataSet
  DBGrid1.DataSource.DataSet.First;
  // Mientras el DataSet tenga registros...
  while not DBGrid1.DataSource.DataSet.Eof do
  begin
    s:= ''; // Inicializar cadena a vacío
    for i:= 0 to DBGrid1.FieldCount - 1 do  // desde el 1er al último campo
    begin
      // Concatenar en 's' cada campo con tantos espacios a la izquierda 
      // como le falten al largo actual del campo para llegar al largo declarado
      s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth -
                           Length(DBGrid1.Fields[i].AsString)) +
                           DBGrid1.Fields[i].AsString;
    end;
    // Guardar el campo ajustado en el archivo de texto
    Writeln(ArchTexto, s);
    // Desplazarnos al próximo registro del DataSet
    DBGrid1.DataSource.DataSet.Next;
  end;
  // Cerrar archivo.
  CloseFile(ArchTexto);
  // Volver a posición previamente guardada del DataSet
  DBGrid1.DataSource.DataSet.Bookmark:= BM;
  // Activar el mostrado en los controles data-aware asociados al DataSet
  DBGrid1.DataSource.DataSet.EnableControls;
end;
Lo que puede quedar un poco confuso es el uso de StringOfChar, que devuelve n caracteres iguales al especificado.
Si queremos mostrar la palabra 'hola' (de longitud 4) ajustada a longitud 7 rellenando con '@' los lugares faltantes a la izquierda sería:
Código Delphi [-]
   ShowMessage(StringOfChar('@',7-Length('hola'))+'hola'); // muestra: @@@hola 
  //Que es el resultado de concantenar  tantos '@' como le faltan a 'hola'
  //para llegar a una longitud de 7 caracteres y la palabra 'hola'
De todas formas si hay algo en lo que no me expliqué bién, te ruego que me lo hagas saber y gustoso busco otra forma de hacerlo.

Saludos. :)

delphi.com.ar 02-06-2011 22:11:47

Cita:

Empezado por darkone2k4 (Mensaje 395358)
La información a exportar primero debe ser visualizada en un DBGRID.
Sé como recorrer el DBGRID y pasar los datos al archivo TXT, pero la exportación debe realizarse con ciertas condiciones, como por ejemplo:
1.- Los campos se deben justificar a la derecha.
2.- Los campos deben ir de forma continua, sin ningún tipo de separador. Esto lo sé hacer.
3.- Cada campo tiene su tamaño específico al momento de exportar.

Un poco tarde, pero... ¿Has visto mis componentes Firesoft ExportSuite?

Uno de ellos TDataToAscii hace exactamente lo que pides!... Puedes asignarle las columas de un DBGrid o bien definir campo a campo de forma explícita o bien puedes dejar que el componente los tome autmáticamente del dataset!



Cita:

Empezado por darkone2k4 (Mensaje 395358)
1.- Los campos se deben justificar a la derecha.

Cada campo tiene la propiedad Alignment que la puedes asignar o la copia del campo/columna asignado

Cita:

Empezado por darkone2k4 (Mensaje 395358)
2.- Los campos deben ir de forma continua, sin ningún tipo de separador.

Si defines las propiedades Separator y Quote = #0 del TDataToAscii no escribe estos valores.


Cita:

Empezado por darkone2k4 (Mensaje 395358)
3.- Cada campo tiene su tamaño específico al momento de exportar.

Cada campo tiene la propiedad FixedLength que es copiada automáticamente de la propiedad DisplayWidth.

Saludos!

ecfisa 03-06-2011 03:38:42

Cita:

hola ecfisa!!!

Ante todo gracias por la explicacion que me diste en el hilo.

ahora bien, necesito si podes explicarme para que sirve la variable BM de tipo TBookMarkStr, tambien como hacer para que no lo

tire todo hacia la derecha,y por ultimo para que tambien exporte el nombre de las columnas del DBGrid. con eso no te molesto mas.
te vuelvo a repetir, muchisimas gracias por la explicacion anterior.

saludos.

Hola ezequiel913.

Tal como me solicitaste por correo privado intentaré explicarte los tres puntos que consultas.

1) Marcas de posición
Empecemos por TBookmark de tipo Pointer, que puede almacenar la posición de un registro de un TDataSet y por lo tanto regresar a él despues de realizar algún desplazamiento en el DataSet. Es decir que nos permite 'marcar' un punto del DataSet para luego retornar a él.

Su uso va aparejado de tres métodos: GetBookmark, GotoBookmark y FreeBookmark.
GetBookmark nos permite obtener la posición del registro actual del DataSet.
GotoBookmark nos posiciona en el registro previamente guardado en Bookmark
FreeBookmrk libera el recurso utilizado.

Ejemplo:
Código Delphi [-]
...
var
  BM: TBookmark;
begin
  BM:= DataSet.GetBookmark;   // guardar en BM la posición del registro actual
  try
    while not DataSet.Eof do  // desplazarse hasta el fin del DataSet
      DataSet.Next;
  finally
    DataSet.GotoBookmark(BM); // volver al registro almacenado en BM
    DataSet.FreeBookmark;     // liberar el recurso
  end;
end;

Pero existe el tipo TBookmarkStr con igual finalidad y resultado.TBookmarkStr es de tipo string (no Pointer) y usándolo, el ejemplo anterior quedaría:
Código Delphi [-]
...
var
  BM: TBookmarkStr;
begin
  BM:= DataSet.Bookmark;     // guardar en BM la posición del registro actual
  while not DataSet.Eof do   // desplazarse hasta el fin del DataSet
    DataSet.Next;
  DataSet.Bookmark:= BM;     // volver al registro almacenado en BM.
end;
Como verás este es más simple de usar.

2) Texto a la derecha o izquierda.
Simplificando es sólo una manipulación de cadenas de caracteres. Por ejemplo si quiero ajustar un string a una longitud de 30 caracteres y este tiene 12,
le faltan 18 para completar los 30. Entonces:

Completar 30 caracteres con contenido a la izquierda:
Código Delphi [-]
var
 st: string;
begin
  st:= 'TBookmarkStr';
  st:= StringOfChar(' ',30-Length(st)) + st; 
  // ahora st vale '                    TBookmarkStr'

Completar 30 caracteres con contenido a la derecha:
Código Delphi [-]
var
  st: string;
begin
  st:= 'TBookmarkStr';
  st:= st + StringOfChar(' ',30-Length(st)); 
  // ahora st vale 'TBookmarkStr                     '

Centrar contenido en 30 caracteres:
Código Delphi [-]
var
  st: string;
begin
  st:= 'TBookmarkStr';
  st:= StringOfChar('.',(30-Length(st)) div 2)
       +st+
       StringOfChar('.',(30-Length(st)) div 2);
   // ahora st vale '       TBookmarkStr         '
  ...
end;

3)Para exportar el título de las columnas agregamos: (texto en negrita)
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  BM: TBookMarkStr;
  i: Integer;
  s: string;
  ArchTexto: TextFile;
begin
  AssignFile(ArchTexto,'C:\A_LA_DERECHA.TXT');
  Rewrite(ArchTexto);
  BM:= DBGrid1.DataSource.DataSet.Bookmark;
  DBGrid1.DataSource.DataSet.DisableControls;
  // Comienza exportar titulos de columnas
  s:= '';
  for i:= 0 to DBGRid1.Columns.Count -1 do
    s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth-
                         Length(DBGrid1.Columns[i].Title.Caption)) +
                         DBGrid1.Columns[i].Title.Caption;
  Writeln(ArchTexto, s);
  Writeln(ArchTexto);
  // Fin exportar titulos de columnas
  DBGrid1.DataSource.DataSet.First;
  for i:= 0 to DBGrid1.Column
  while not DBGrid1.DataSource.DataSet.Eof do
  begin
    s:= '';
    for i:= 0 to DBGrid1.FieldCount - 1 do
    begin
      (* llenar con blancos a la izquierda (largo físico de campo - largo) y concatenar *)
      s:= s + StringOfChar(' ', DBGrid1.Fields[i].DisplayWidth -
                           Length(DBGrid1.Fields[i].AsString)) +
                           DBGrid1.Fields[i].AsString;
    end;
    Writeln(ArchTexto, s); (* guardar campos formateados del registro  *)
    DBGrid1.DataSource.DataSet.Next;
  end;
  CloseFile(ArchTexto);
  DBGrid1.DataSource.DataSet.Bookmark:= BM;
  DBGrid1.DataSource.DataSet.EnableControls;
end;

Saludos.


La franja horaria es GMT +2. Ahora son las 15:53:56.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi