Página 1 de 1

Pasar de .xls a .csv

NotaPublicado: 2017-12-20 07:14 @343
por hughgrc
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!

Re: Pasar de .xls a .csv

NotaPublicado: 2017-12-20 08:43 @405
por explorer
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.

Re: Pasar de .xls a .csv

NotaPublicado: 2017-12-21 07:27 @352
por hughgrc
¡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.

Re: Pasar de .xls a .csv

NotaPublicado: 2017-12-21 11:09 @506
por explorer
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).

Re: Pasar de .xls a .csv

NotaPublicado: 2018-01-02 07:05 @337
por hughgrc
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!

Re: Pasar de .xls a .csv

NotaPublicado: 2018-01-02 08:42 @404
por explorer
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.

Re: Pasar de .xls a .csv

NotaPublicado: 2018-01-03 03:40 @195
por hughgrc
¿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?

Re: Pasar de .xls a .csv

NotaPublicado: 2018-01-04 10:21 @473
por explorer
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.