Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Impresión
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 25-03-2022
novato_erick novato_erick is offline
Miembro
 
Registrado: ago 2010
Ubicación: Panamá
Posts: 396
Poder: 14
novato_erick Va por buen camino
Optimización en exportación a Excel

Saludos primeramente Chicos:

realizando consulta por el club y encontrando varias códigos de interés a mi propósito para exportación desde Delphi utilizando ClientDataSet seguí dichas indicaciones de esta forma:

Código Delphi [-]
procedure EmiteInformeVenta(FechaVentasIni, FechaVentasFin:TDate;
  mGridExport :TDataSet);
  var
   rangoExcel : Excel2000.ExcelRange;
   I, Fila : Integer;
   mMarcador : TBookmark;
   mTabla : TDataSet;
   AplicacionExcel:  TExcelApplication;
begin
with  dmReportes.qInformeVentaNombreClientes do
begin
  ParamByName('FECHAINI').AsDate := FechaVentasIni;
  ParamByName('FECHAFIN').AsDate := FechaVentasFin;
  ExecSQL;
end;
  if dmReportes.cdsInformeVentaNombreCliente.Active = True then
  begin
    dmReportes.cdsInformeVentaNombreCliente.EmptyDataSet;
    dmReportes.cdsInformeVentaNombreCliente.Active := False;
  end;
  dmReportes.cdsInformeVentaNombreCliente.Active := True;
  //procedimiento de ajdsoft   https://www.ajpdsoft.com/modules.php...owpage&pid=117
  //Creamos el libro de Excel (Abriendo Excel)
  AplicacionExcel := TExcelApplication.Create(Nil);
  //Asociamos el dataset (tabla) del DBGrid con la tabla
  //que utilizaremos en esta función
  mTabla := dmReportes.cdsInformeVentaNombreCliente;
  AplicacionExcel.Visible[0] := True;
  //Creamos el nuevo libro de Excel
  AplicacionExcel.ConnectKind := ckNewInstance;
//https://delphi.cjcsoft.net/viewthread.php?tid=46003
//mejoras de codigo porque me enviaba despues de 900 registro error raised exception class EOleException with message 'OLE error 800AC472'. delphi
  AplicacionExcel.Connect;
  AplicacionExcel.Workbooks.Add(NULL, 0);
  //primera fila con los nombres de las columnas
  //para ello recorremos todos las columnas de la tabla
  //y mostramos en Excel el valor de "DisplayLabel"
  rangoExcel := AplicacionExcel.ActiveCell;
  for I := 0 to mTabla.FieldCount -1 do
    begin
      rangoExcel.Value := mTabla.Fields[i].DisplayLabel;
      rangoExcel := rangoExcel.Next;
    end;
  //aplicamos un autoformato de Excel a las filas y columnas añadidas
  rangoExcel.AutoFormat(10, NULL, NULL, NULL, NULL, NULL, NULL);
  mTabla.DisableControls;
  try
    mMarcador := mTabla.Bookmark;
       try
     //recorremos todos los registros de la tabla para ir añadiéndolos
     //a la hoja actual de Excel
      mTabla.First;
      Fila := 2;
      while not mTabla.Eof do
      begin
        rangoExcel := AplicacionExcel.Range['A' + IntToStr(Fila), 'A' +
         InttoStr(Fila)];
        for I := 0 to mTabla.Fields.Count -1 do
          begin
            rangoExcel.Value := mTabla.Fields[i].AsString;
            rangoExcel := rangoExcel.Next;
          end;
          mTabla.Next;
          Inc(Fila);
      end;
       finally
         mTabla.Bookmark := mMarcador;
         mTabla.EnableControls;
       end;
  finally
     AplicacionExcel.Disconnect;
     AplicacionExcel.Free;
  end;
end;

en fin al ejecutar la exportación de 10,000 mil registro es demasiado lento casi 4 minutos.

Alguien podría ayudarme a la optimización para que sea más rápida la exportación ?

Agradeciendo su colaboración;

Saludos;

novato_erick
Responder Con Cita
  #2  
Antiguo 25-03-2022
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.275
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Así viendo el código por encima, no parece que se pueda hacer muchas cosa en él para optimizarlo.
Primero hace un recorrido por los títulos y luego para cada fila/registro (WHILE) recorre las columnas (FOR) para obtener los valores.

No veo mucha posible mejora, salvo que intentes utilizar Threads. Pero en ese caso no hablamos de reducir el tiempo, sino que al utilizar threads, lo que consigues es hacerlo en un proceso "secundario" y no "bloquear" la aplicación principal.

Lo otro que se me ocurre (que esto sí puede que reduzca el tiempo), es que intentes conectar a excel utilizando ADO, en lugar de TExcelApplication.
Es decir, puedes configurar una conexión a Excel utilizando el TADOconnection, de forma que la hoja de Excel se consulta como una tabla.

En los foros ya hemos hablado del tema (ADO+Excel); Busca mensajes antiguos para que puedas ver ejemplos de conexión y diría que en el FTP puedes encontrar incluso ejemplos de ello.
Si no encuentras nada, dilo.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #3  
Antiguo 25-03-2022
Avatar de fjcg02
[fjcg02] fjcg02 is offline
Miembro Premium
 
Registrado: dic 2003
Ubicación: Zamudio
Posts: 1.410
Poder: 22
fjcg02 Va camino a la fama
Hola,
tal como lo planteas abriendo el excel como un objeto OLE no se puede acelerar. El tiempo se va en la sincronización de la exportación de la aplicación con el excel, celda a celda.

Si sólo trabajas con una pestaña, puedes exportar a csv y luego cargar el dato en excel.

Si no, las alternativas que tienes son:
- utilizar alguna libería que genere los ficheros excel directamente ( las hay gratuitas aunque no sé cual recomendarte)
- utilizar las hojas excel como tablas tal y como te indica Neftalí.

La diferencia es sustancial.

Un saludo
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino -
Responder Con Cita
  #4  
Antiguo 25-03-2022
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Solucion a Excel lento

Mira en la parte final de este post respondi esa pregunta, espero te sirva:


https://www.clubdelphi.com/foros/showthread.php?t=94464
Responder Con Cita
  #5  
Antiguo 25-03-2022
Avatar de mRoman
mRoman mRoman is offline
Miembro
 
Registrado: nov 2003
Posts: 599
Poder: 21
mRoman Va por buen camino
Componentes de FireSoft

Hola Novato_Erick

En esta página https://torry.net/authorsmore.php?id=6057 podras bajar unos componentes que te puedan ayudar (Autor:Federico Firenze). FireSoft ExportSuite V.1, son Free.

Talvez te ayuden a ser mas rápido la exportación.

Saludos.
__________________
Miguel Román

Afectuoso saludo desde tierras mexicanas....un aguachile?, con unas "cetaseas" bien "muertas"?, VENTE PUES !!
Responder Con Cita
  #6  
Antiguo 26-03-2022
novato_erick novato_erick is offline
Miembro
 
Registrado: ago 2010
Ubicación: Panamá
Posts: 396
Poder: 14
novato_erick Va por buen camino
Cita:
Empezado por marco3k Ver Mensaje
Mira en la parte final de este post respondi esa pregunta, espero te sirva:


https://www.clubdelphi.com/foros/showthread.php?t=94464

Tenias razón marcos utilizando el Componente ADO la exportación fue en dos pestañazos .

Esto fué lo que implementé Gracias a ustedes:
Código Delphi [-]
procedure EmiteInformeVentas2(FechaVentasI, FechaVentasF: TDate); // Ver2
var
  I, fila: Integer;
  ExcelApp, ExcelLibro, ExcelHoja: OleVariant;
  RutaExcel, FechaInfo: String;
begin
  with dmReportes.qInformeVentaNombreClientes do
  begin
    ParamByName('FECHAINI').AsDate := FechaVentasI;
    ParamByName('FECHAFIN').AsDate := FechaVentasF;
    ExecSQL;
  end;
  if dmReportes.cdsInformeVentaNombreCliente.Active = True then
  begin
    dmReportes.cdsInformeVentaNombreCliente.EmptyDataSet;
    dmReportes.cdsInformeVentaNombreCliente.Active := False;
  end;
  dmReportes.cdsInformeVentaNombreCliente.Active := True;
  TotalRegistroData := dmReportes.cdsInformeVentaNombreCliente.RecordCount;
  dmReportes.ADODataSetInforme.FieldDefs.Assign
    (dmReportes.cdsInformeVentaNombreCliente.FieldDefs);
  dmReportes.ADODataSetInforme.CreateDataSet;
  try
    dmReportes.cdsInformeVentaNombreCliente.DisableControls;
    // dmReportes.ADODataSetInforme.Active := True;
    dmReportes.ADODataSetInforme.DisableControls;
    dmReportes.cdsInformeVentaNombreCliente.First;
    while not dmReportes.cdsInformeVentaNombreCliente.Eof do
    begin
      dmReportes.ADODataSetInforme.Insert;
      for I := 0 to dmReportes.cdsInformeVentaNombreCliente.FieldCount - 1 do
      begin
        dmReportes.ADODataSetInforme.Fields[i].Value :=
          dmReportes.cdsInformeVentaNombreCliente.Fields[i].Value;
        // dmReportes.ADODataSetInforme.Post;
      end;
      dmReportes.cdsInformeVentaNombreCliente.Next;
    end;
    FechaInfo := StringReplace(DateToStr(Now), '/', '', [rfReplaceAll]);
    RutaExcel := ExtractFilePath(Application.ExeName) + 'Informe' + FechaInfo;
    // dmReportes.ADODataSetInforme.SaveToFile(RutaExcel + '.xls');
  finally
    dmReportes.ADODataSetInforme.EnableControls;
    dmReportes.cdsInformeVentaNombreCliente.EnableControls;
  end;
    // Crea el objeto Excel, el objeto workBook y el objeto sheet
    ExcelApp := CreateOleObject('Excel.Application');
  try
    ExcelLibro := ExcelApp.Workbooks.Add();
    // Añadimos una Hoja
    ExcelHoja := ExcelLibro.Worksheets.Add();
    // aca puedes recorrer los encabezados y otras cosas que desees No he logrado poner los encabezado 
    ExcelHoja.Range['A2'].CopyFromRecordset
      (dmReportes.ADODataSetInforme.Recordset);  // .CopyFromRecordset(Rs.Recordset);
    // esta es el método importante del Excel y como parametro tiene un objeto ADO
    // y por eso la necesidad de usar este objeto.
    MessageDLG('¡Se exportó correctamente!', mtInformation, [mbOk], 0);
    ExcelApp.Visible := True;
  except
    ExcelApp.Quit;
    dmReportes.ADODataSetInforme.EnableControls;
    Showmessage('No se pudo crear el Archivo Excel.');
    raise;
  end;
end;

como coloque en el comentario: "No he logrado poner los encabezado" de la tabla

igual está funcional mejoraré y al términar pondré el código final.

Saludos;

novato_erick
Responder Con Cita
  #7  
Antiguo 26-03-2022
novato_erick novato_erick is offline
Miembro
 
Registrado: ago 2010
Ubicación: Panamá
Posts: 396
Poder: 14
novato_erick Va por buen camino
Se me olvido poner que en mi ADODataSetInforme le puse en la propiedad ConnectionString: Provider=Microsoft.Jet.OLEDB.4.0; Mode=ReadWrite;Extended Properties=Excel 8.0;Persist Security Info=False

Saludos;

novato_erick
Responder Con Cita
  #8  
Antiguo 28-03-2022
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Cita:
Empezado por novato_erick Ver Mensaje
Tenias razón marcos utilizando el Componente ADO la exportación fue en dos pestañazos .

Esto fué lo que implementé Gracias a ustedes:
Código Delphi [-]procedure EmiteInformeVentas2(FechaVentasI, FechaVentasF: TDate); // Ver2 var I, fila: Integer; ExcelApp, ExcelLibro, ExcelHoja: OleVariant; RutaExcel, FechaInfo: String; begin with dmReportes.qInformeVentaNombreClientes do begin ParamByName('FECHAINI').AsDate := FechaVentasI; ParamByName('FECHAFIN').AsDate := FechaVentasF; ExecSQL; end; if dmReportes.cdsInformeVentaNombreCliente.Active = True then begin dmReportes.cdsInformeVentaNombreCliente.EmptyDataSet; dmReportes.cdsInformeVentaNombreCliente.Active := False; end; dmReportes.cdsInformeVentaNombreCliente.Active := True; TotalRegistroData := dmReportes.cdsInformeVentaNombreCliente.RecordCount; dmReportes.ADODataSetInforme.FieldDefs.Assign (dmReportes.cdsInformeVentaNombreCliente.FieldDefs); dmReportes.ADODataSetInforme.CreateDataSet; try dmReportes.cdsInformeVentaNombreCliente.DisableControls; // dmReportes.ADODataSetInforme.Active := True; dmReportes.ADODataSetInforme.DisableControls; dmReportes.cdsInformeVentaNombreCliente.First; while not dmReportes.cdsInformeVentaNombreCliente.Eof do begin dmReportes.ADODataSetInforme.Insert; for I := 0 to dmReportes.cdsInformeVentaNombreCliente.FieldCount - 1 do begin dmReportes.ADODataSetInforme.Fields[i].Value := dmReportes.cdsInformeVentaNombreCliente.Fields[i].Value; // dmReportes.ADODataSetInforme.Post; end; dmReportes.cdsInformeVentaNombreCliente.Next; end; FechaInfo := StringReplace(DateToStr(Now), '/', '', [rfReplaceAll]); RutaExcel := ExtractFilePath(Application.ExeName) + 'Informe' + FechaInfo; // dmReportes.ADODataSetInforme.SaveToFile(RutaExcel + '.xls'); finally dmReportes.ADODataSetInforme.EnableControls; dmReportes.cdsInformeVentaNombreCliente.EnableControls; end; // Crea el objeto Excel, el objeto workBook y el objeto sheet ExcelApp := CreateOleObject('Excel.Application'); try ExcelLibro := ExcelApp.Workbooks.Add(); // Añadimos una Hoja ExcelHoja := ExcelLibro.Worksheets.Add(); // aca puedes recorrer los encabezados y otras cosas que desees No he logrado poner los encabezado ExcelHoja.Range['A2'].CopyFromRecordset (dmReportes.ADODataSetInforme.Recordset); // .CopyFromRecordset(Rs.Recordset); // esta es el método importante del Excel y como parametro tiene un objeto ADO // y por eso la necesidad de usar este objeto. MessageDLG('¡Se exportó correctamente!', mtInformation, [mbOk], 0); ExcelApp.Visible := True; except ExcelApp.Quit; dmReportes.ADODataSetInforme.EnableControls; Showmessage('No se pudo crear el Archivo Excel.'); raise; end; end;


como coloque en el comentario: "No he logrado poner los encabezado" de la tabla

igual está funcional mejoraré y al términar pondré el código final.

Saludos;

novato_erick

Agregar encabezados en sencillo, por ejemplo agrega esto mas o menos así:

Código Delphi [-]
var o_Excel,o_Libro, o_Hoja : OleVariant; 
begin
    o_Excel := CreateOleObject('Excel.Application');    
    o_Libro := o_Excel.Workbooks.Add;    
    o_hoja := o_Libro.Worksheets.Add;   
    o_hoja.range['A1']:='Código';    
    o_hoja.range['B1']:='Nombre';    
    o_hoja.range['C1']:='Fecha';    
    o_hoja.range['D1']:='Valor';    
    o_hoja.range['E1']:='Estado';
    ...
end;
Responder Con Cita
  #9  
Antiguo 29-03-2022
novato_erick novato_erick is offline
Miembro
 
Registrado: ago 2010
Ubicación: Panamá
Posts: 396
Poder: 14
novato_erick Va por buen camino
Cita:
Empezado por marco3k Ver Mensaje
Agregar encabezados en sencillo, por ejemplo agrega esto mas o menos así:

Código Delphi [-]
var o_Excel,o_Libro, o_Hoja : OleVariant; 
begin
    o_Excel := CreateOleObject('Excel.Application');    
    o_Libro := o_Excel.Workbooks.Add;    
    o_hoja := o_Libro.Worksheets.Add;   
    o_hoja.range['A1']:='Código';    
    o_hoja.range['B1']:='Nombre';    
    o_hoja.range['C1']:='Fecha';    
    o_hoja.range['D1']:='Valor';    
    o_hoja.range['E1']:='Estado';
    ...
end;

Ohhh gracias... Quedo de anillo al dedo.

Saludos y Bendiciones por su ayuda.

novato_erick
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Error con exportacion a Excel jafera Servers 2 28-08-2014 11:53:15
Personalizar exportacion a excel ilichhernandez Conexión con bases de datos 12 08-06-2011 20:52:59
QReport Exportación a PDF, Excel, TXT, ETC pmtzg Impresión 1 11-05-2010 00:10:50
exportacion de access a excel luxus Conexión con bases de datos 3 15-04-2008 20:30:59
Exportacion a Excel incorrecta jfloro Servers 4 19-09-2003 08:48:36


La franja horaria es GMT +2. Ahora son las 18:31:21.


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
Copyright 1996-2007 Club Delphi