• Publicidad

Pasar de .xls a .csv

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Pasar de .xls a .csv

Notapor hughgrc » 2017-12-20 07:14 @343

Hola.

Llevo varios días investigando por Internet y no soy capaz de hacer un programa en Perl para pasar un archivo Excel en formato ".xls" a formato ".csv".

Si alguien me puede pasar un script de ejemplo (y a poder ser, sencillo ¡jajaja!) sobre cómo se haría; me sería de mucha ayuda.

¡Muchas gracias y un saludo!
hughgrc
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2017-12-20 03:32 @189

Publicidad

Re: Pasar de .xls a .csv

Notapor explorer » 2017-12-20 08:43 @405

Bienvenido a los foros de Perl en Español, hughgrc.

Hay un módulo en CPAN, llamado Spreadsheet::XLSX::Utility2007, que contiene un método llamado xls2csv().

Este es un ejemplo de lo que se puede hacer con Spreadsheet::XLSX::Utility2007 y Spreadsheet::XLSX.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2.  
  3. use Spreadsheet::XLSX;
  4. use Text::Iconv;
  5.  
  6. # Conversor de codificación
  7. #my $converter = Text::Iconv -> new ("utf-8", "windows-1251");
  8.  
  9. # Creación del objeto
  10. #my $excel = Spreadsheet::XLSX->new('test.xlsx', $converter);
  11. my $excel = Spreadsheet::XLSX->new('clinicamym.xlsx');
  12.  
  13. # Hojas que hay en el libro
  14. for my $hoja (@{$excel -> {Worksheet}}) {
  15.     printf("Hoja: %s\n", $hoja->{Name});
  16. }
  17.  
  18. # Hoja de donde sacaremos los datos
  19. my $hoja = $excel->worksheet('noticias');
  20.  
  21. # Número máximo de filas, si no está definido
  22. $hoja->{MaxRow} ||= $hoja->{MinRow};
  23.  
  24. # Contenido de la hoja, para todas las filas
  25. for my $fila ($hoja->{MinRow} .. $hoja->{MaxRow}) {
  26.  
  27.     for my $columna ($hoja->{MinCol} .. $hoja->{MaxCol}) {
  28.  
  29.         my $celda = $hoja->{Cells}[$fila][$columna];
  30.  
  31.         if ($celda) {
  32.             printf("( %s , %s ) => %s\n", $fila, $columna, $celda->{Val});
  33.         }
  34.     }
  35. }
  36.  
  37.  
  38. # Llamar al método xlsx2csv de forma directa
  39. # Extraer solo una región de la hoja
  40. use Spreadsheet::XLSX::Utility2007 'xls2csv';
  41.  
  42. # definición de la región: hoja-rango
  43. my $region = '1-C1:E17';
  44. print xls2csv('clinicamym.xlsx', $region, 0);
  45.  
  46. $region = '3-C3:F7';
  47. print xls2csv('clinicamym.xlsx', $region, 0);
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Como ves, al final del programa, es muy fácil sacar una región de una determinada hoja, dentro del libro Excel.

Ahora bien... esto solo se puede hacer si ANTES parcheas el código de Utility2007.pm. Estas son las líneas que debes cambiar:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     # start the excel object now
  2.     my $oExcel = Spreadsheet::XLSX->new($filename);
  3.     #my $oBook  = $oExcel->Parse($filename);
  4.  
  5.     # open the sheet
  6.     my $oWkS = $oExcel->{Worksheet}[$sheet];
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

La salida del método xls2csv() es una cadena de texto con los campos separados por comas. Luego te queda como trabajo guardar el resultado a un archivo en disco.

Por estos foros hay algunos hilos referidos al formato xlsx. Usa el sistema de búsqueda.

En CPAN puedes encontrar muchos módulos para tratar archivos xlsx, incluso más modernos que este Spreadsheet::XLSX.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Pasar de .xls a .csv

Notapor hughgrc » 2017-12-21 07:27 @352

¡Muchas gracias por la respuesta!

No he sido capaz de instalar el módulo que me has comentado... Estoy utilizando el programa "Padre, The perl IDE". Y no sé si es el más indicado ya que me suele dar bastantes problemas con la instalación de los módulos.

¿Cuál me recomendaríais usar? Perdonad por estas preguntas tan de principiante, pero es que llevo programando en Perl menos de dos semanas.

Gracias de nuevo y un saludo.
hughgrc
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2017-12-20 03:32 @189

Re: Pasar de .xls a .csv

Notapor explorer » 2017-12-21 11:09 @506

Yo lo he instalado en mi sistema con el comando cpanm (cpanminus) en mi directorio local de usuario, así no tengo que depender del Perl del sistema.

Tienes lo básico en este hilo: Instalación de módulos y bibliotecas en Perl.

No sé si estás en Linux o Windows. Si es Windows, mira la guía anterior. Si es Linux, puedes hacerte root del sistema, e instalar el módulo si lo trae tu gestor de paquetes. Por ejemplo, si es un Linux basado en Debian, sí que existe el paquete libspreadsheet-xlsx-perl, por lo que solo tendrás que ejecutar

apt-get install libspreadsheet-xlsx-perl

y ya está.

Si no está disponible de esta forma, tendrás que ejecutar el comando cpan o cpanp para instalarlo "a mano":

cpan Spreadsheet::XLSX

Bueno, no fue tampoco tan fácil. Tuve antes que instalar Sub::Identify y Archive::Zip (también disponibles como paquetes en Debian como libsub-identify-perl y libarchive-zip-perl).
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Pasar de .xls a .csv

Notapor hughgrc » 2018-01-02 07:05 @337

Muchas gracias, pero sigo teniendo problemas con la instalación de los módulos de Perl.

Por lo tanto, he estado mirando alternativas y he encontrado este script para pasar al formato .csv:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. use strict;
  2. use warnings;
  3. use IO::Handle;
  4. use FileHandle;
  5. use Spreadsheet::ParseExcel;
  6.  
  7. my $xlsparser = Spreadsheet::ParseExcel->new();
  8. my $xlsbook   = $xlsparser->parse('d:\\PERL\Archivos CSV\Creados\\SHNT_R.xls');
  9. my $xls       = $xlsbook->worksheet(0);
  10. my ( $row_first, $row_last ) = $xls->row_range();
  11. my ( $col_first, $col_last ) = $xls->col_range();
  12. my $csv = '';
  13. for my $row ( $row_first .. $row_last ) {
  14.     for my $col ( $col_first .. $col_last ) {
  15.         my $cell = $xls->get_cell( $row, $col );
  16.         next unless $cell;
  17.         $csv .= $cell->unformatted();
  18.         if ( $col == $col_last ) {
  19.             $csv .= "\n";
  20.         }
  21.         else {
  22.             $csv .= ",";
  23.         }
  24.     }
  25. }
  26. open( my $FH, '>', "d:\\PERL\\Archivos CSV\\Creados\\SHNT_R.csv" ) or die "oops!";
  27. while ( my $line = <$xlsbook> ) {
  28.     print $FH $line;
  29. }
  30.  
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Pero al ejecutarlo me da el siguiente error:

"NOT a GLOB reference at pasar a csv.pl line 27"

¿Sabrías decirme cómo solucionar ese error?

¡Gracias y un saludo!
hughgrc
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2017-12-20 03:32 @189

Re: Pasar de .xls a .csv

Notapor explorer » 2018-01-02 08:42 @404

El error indica que $xlsbook no es un identificador de archivo, por lo que no se puede usar en esa línea.

Efectivamente, contiene un objeto hoja (Spreadsheet::ParseExcel::Worksheet), así que no se puede usar como si estuviéramos leyendo de un archivo.

El archivo xls ya lo estás leyendo en las líneas anteriores. Solo te queda guardar las filas en formato CSV, y eso es justo lo que ocurre con la variable $csv.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Pasar de .xls a .csv

Notapor hughgrc » 2018-01-03 03:40 @195

¿Me podrías decir cómo tendría que hacer para que me lo guarde en formato .csv? ¿Cambiar la variable $xlsbook por la variable $csv en la línea 27?
hughgrc
Perlero nuevo
Perlero nuevo
 
Mensajes: 5
Registrado: 2017-12-20 03:32 @189

Re: Pasar de .xls a .csv

Notapor explorer » 2018-01-04 10:21 @473

Tienes que hacer el open del archivo antes del doble bucle for(). La línea 27 no tiene sentido, así que quítala. No sé de dónde lo habrás copiado, pero este programa no debería funcionar.

Y luego, tienes que llevar el print $FH $csv; al final del bucle más interno, que es cuando ha terminado de leer todas las columnas de una fila.

Faltaría por poner un close $FH; al final del archivo, y ya está.


P.D.: estamos en el foro Intermedio, donde se supone que deberías saber hacer estas cosas, al menos entender qué es lo que el código hace.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España


Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado