Forum: Rails-ES Exportar datos a excell

Posted by Jhony Alex (alex123)
on 2009-06-23 22:09
Hola

En estos dias he estado tratando de exportar unos datos a csv pero tengo
un problema es demasiada información y habeces se queda mucho tiempo y
nunca exporta, otra es que muchas veces el mongrel muere y el mensaje es
que ha terminado por una causa desconocida.

Como puedo hacer para que no se cuelgue el servidor y para que la
exportación sea mas ligera.

Gracias
Posted by Ceritium (Guest)
on 2009-06-24 02:48
(Received via mailing list)
Podrías pegar [1] el código que tienes para poder ayudarte?

1- http://pastie.org/


2009/6/23 Jhony Alex <ruby-forum-incoming@andreas-s.net>:
Posted by Jhony Alex (alex123)
on 2009-06-24 15:13
Ceritium wrote:
> Podr�as pegar [1] el c�digo que tienes para poder ayudarte?
> 
> 1- http://pastie.org/
> 
> 
> 2009/6/23 Jhony Alex <ruby-forum-incoming@andreas-s.net>:

En el controlador tengo esto
# el sql
sql="SELECT 
p.name'project',i.project_id'id',i.id'tid',i.id'tarea_id',concat(firstname,' 
',lastname)'nombre',subject'actividad',g.NOMBRE 
'gerencia',c.value'aplicacion',f.value'planeada',I.CCOSTOS'ccosto',estimated_hours 
'Estimado',hours'Dedicado',spent_on'freporte',comments'comentario',done_ratio'ejecucion',e.name'facturable',i.due_date'termina',i.start_date'comienza',it.name'estado'
              FROM TIME_ENTRIES T LEFT JOIN ISSUES I
                            ON T.ISSUE_ID=I.ID,,
                          JOIN ISSUE_STATUSES IT
                            ON IT.ID=I.STATUS_ID
                          JOIN PROJECTS P
                            ON T.PROJECT_ID=P.ID
                          LEFT JOIN GERENCIAS G
                            ON I.GERENCIA_ID=G.ID
                          JOIN ENUMERATIONS E
                            ON E.ID=T.ACTIVITY_ID
                          JOIN USERS U
                            ON T.USER_ID=U.ID
                         LEFT JOIN CUSTOM_VALUES C
                            ON T.ISSUE_ID=C.CUSTOMIZED_ID
                            AND C.CUSTOM_FIELD_ID=43
                         LEFT JOIN CUSTOM_VALUES F
                            ON T.ISSUE_ID=F.CUSTOMIZED_ID
                            AND F.CUSTOM_FIELD_ID=40 "
      sql << " WHERE I.PROJECT_ID in (#{@projects.join(',')})
               AND T.USER_ID in (#{@users.join(',')})"
      sql <<"  AND T.SPENT_ON >= ('%s')" % @date_from
      sql <<"  AND T.SPENT_ON <= ('%s')" % @date_to
      sql <<"  AND i.status_id in (#{@issues_status.join(',')})"
      sql << " AND t.activity_id in (#{@activities.join(',')})"
      if @gerencia != ""
            sql << " AND g.id = %s"%@gerencia
      end
      if @aplicacion[0] != '-1'
            sql << " AND c.value = ('%s')"%@aplicacion
      end
            sql<<" order by 2,5,13"

      @issues = ActiveRecord::Base.connection.select_all(sql)
# El metodo para exportar a csv
    respond_to do |format|
        format.csv  { 
send_data(issues_to_csv(@issues,@users,@date_from,@date_to,@activities,@estimado,@totalf).read, 
:type => 'text/csv; header=present', :filename => 'export.csv') }
    end

#En el helper tengo esto.


def issues_to_csv(issues,users,from,to,activities,estimado,totalf)
    @projects=""
    ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')
    decimal_separator = l(:general_csv_decimal_separator)
    export = StringIO.new
    CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|

      issues.each do |issue|

      # Por cada  proyecto debo sumar unas horas estimadas.
      if issue['id'] != @projects
        csv << ''
        sql="SELECT sum(hours)'hours'
          FROM time_entries t, issues i
          WHERE i.id=t.issue_id
          AND t.user_id in (#{users.join(',')})
          AND i.project_id = #{issue['id']}
          AND t.activity_id in (#{activities.join(',')})
          AND t.spent_on >= ('#{from}')
          AND t.spent_on <= ('#{to}')
            GROUP BY i.project_id"
         total=0
              @total = ActiveRecord::Base.connection.select_all(sql)
              @total.each do |z|
                total = z['hours'].to_f
              end

        total=(total.to_f).round(2)

        @projects=issue['id']
        projects = [issue['project'],
                       total,
                       l(:field_hours)
                       ]
        csv << projects.collect {|c| begin; ic.iconv(c.to_s); rescue; 
c.to_s; end }
        csv << ''
      end

      # cabeceras.

      headers = [ l(:field_subject),
                       "F.Inicio",
                       "F.Fin",
                       l(:field_status),
                       l(:informe_gerencia_label),
                       l(:informe_aplicacion_label),
                       "C.C",
                       "Planeada",
                       "T.Estimado",
                       "T.Dedicado",
                       "F.Reporte",
                       "Detalle",
                       "Facturable",
                       l(:field_assigned_to),
                  ]

      csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; 
c.to_s; end }
      #tareas
        fields = [issue['actividad'],
                    issue['comienza'],
                    issue['termina'],
                    issue['estado'],
                    issue['gerencia'],
                    issue['aplicacion'],
                    issue['ccosto'],
                    issue['planeada'],
                    issue['Estimado'],
                    issue['Dedicado'],
                    issue['freporte'],
                    issue['comentario'],
                    issue['facturable'],
                    issue['nombre']
                   ]

        csv << fields.collect {|c| begin; ic.iconv(c.to_s); rescue; 
c.to_s; end }

      end
      totales=["",
                   "",
                   "",
                   "",
                   "",
                   "",
                   "",
                   "",
                  estimado,
                  totalf,
                  "",
                  "",
                  "",
                  ""]
        csv << totales.collect {|c| begin; ic.iconv(c.to_s); rescue; 
c.to_s; end }
    end
    export.rewind
    export
  end
-------------------------------------------------------------------------

En el momento se estan recibiendo desde las bd 20.000 registros y esto 
tiende a aumentar

Gracias por cualquier ayuda
Posted by Rafael García (rafa)
on 2009-06-24 15:30
(Received via mailing list)
¿Cuánto le cuesta ejecutar cada consulta? Si el problema no es el tiempo
de ejecución de las consultas yo probaría a usar FasterCSV en vez de
CSV::Writer porque me da a mi que CSV::Writer es lentillo(de ahí el
nombre de la gema).

Suerte

Jhony Alex wrote:
> En el controlador tengo esto
>                           JOIN PROJECTS P
>                          LEFT JOIN CUSTOM_VALUES F
>       end
> :type => 'text/csv; header=present', :filename => 'export.csv') }
>     CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
>           AND i.project_id = #{issue['id']}
>         total=(total.to_f).round(2)
>
>                        "T.Estimado",
>         fields = [issue['actividad'],
>                     issue['comentario'],
>                    "",
>                   ""]
>
> Gracias por cualquier ayuda
>   


--
Rafa
Posted by Jorge Calás Lozano (Guest)
on 2009-06-24 16:33
(Received via mailing list)
Excel o CSV? para excel mirate http://spreadsheet.rubyforge.org/

Yo lo utilizo en varios proyectos y me va muy bien.

Para CSV FasterCSV, como te han recomendado, también está muy bien.

Otra recomendación, no cargues tanto los controladores, mete todo lo que
puedas en los modelos, clases propias y módulos y en los controladores
utiliza respond_to

def show
@issue = Issue.find....
respond_to do |format|
  format.html
  format.xml {...}
  format.csv { @issue.to_csv } # el to_csv lo tendrías que implementar
  format.xls { @issue.to_xls } # o algo como MyXLSClass.export(@issue)
  format.pdf { @issue.to_pdf } #
  format.png { @issue.to_png } #
end
end

sds

Jorge
Posted by Jhony Alex (alex123)
on 2009-06-25 05:51
Rafael García wrote:
> ¿Cuánto le cuesta ejecutar cada consulta? Si el problema no es el tiempo
> de ejecución de las consultas yo probaría a usar FasterCSV en vez de
> CSV::Writer porque me da a mi que CSV::Writer es lentillo(de ahí el
> nombre de la gema).
> 
> Suerte
> 
> Jhony Alex wrote:
>> En el controlador tengo esto
>>                           JOIN PROJECTS P
>>                          LEFT JOIN CUSTOM_VALUES F
>>       end
>> :type => 'text/csv; header=present', :filename => 'export.csv') }
>>     CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
>>           AND i.project_id = #{issue['id']}
>>         total=(total.to_f).round(2)
>>
>>                        "T.Estimado",
>>         fields = [issue['actividad'],
>>                     issue['comentario'],
>>                    "",
>>                   ""]
>>
>> Gracias por cualquier ayuda

Gracias por la respuesta,

Tienen algun ejemplo sencillo de como utilizar fastercsv

Gracias
>>   
> 
> 
> --
> Rafa
Posted by Jhony Alex (alex123)
on 2009-06-25 06:51
Hola estuve haciendo pruebas de performance con fastercsv y la 
exportacion de 36131 filas se demoro 1 minuto con 40 segundos.

Mejoro mucho el tiempo de respuesta y el servidor no se muere.

Muchas gracias por todo

Otra pregunta
esto esta en el metodo de exportacion
ic = Iconv.new('ISO-8859-15', 'UTF-8')
    decimal_separator = l(:general_csv_decimal_separator)
    export = FasterCSV.generate(:col_sep => l(:general_csv_separator)) 
do |csv|

y muchos de los datos que son exportados tienen tilde, el problema es 
que muchos de estos quedan con la tilde bien pero otros quedan con los 
caracteres rraros pero yo pensaba que con iconv este error no volveria a 
pasar pero esto ya fue algo demasiado raro que formateara algunos datos 
y otros no


Muchas gracias por toda la ayuda que me han dado hacerca del tema.
Posted by Jorge Calás Lozano (Guest)
on 2009-06-25 06:59
(Received via mailing list)
Jhony Alex wrote:

> Tienen algun ejemplo sencillo de como utilizar fastercsv
> 
http://fastercsv.rubyforge.org/classes/FasterCSV.html
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.