• Publicidad

Leer archivo.xls con SpreadSheet::ParseExcel

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Leer archivo.xls con SpreadSheet::ParseExcel

Notapor panterozo » 2010-04-05 09:06 @421

Bueno, el problema que tengo es que el archivo que estoy analizando tiene caracteres de portugués, y muestra basura con caracteres como ç o ê..

Pensé en un comienzo que utf8 no era capaz de realizar el reconocimiento de esto, así que utilicé iso-8859-1 en la función Spreadsheet::ParseExcel::FmtJapan::TextFmt.

Luego, me percato de que si cambio a iso-8859-1 debo cambiar miles de otras cosas, por lo que realmente necesito que sea en utf8. Busqué y utf8 sí acepta estos caracteres.

Aquí una página:

http://www.periodni.com/es/codificacion ... icode.html

El problema, ya para no alargarme más, es que este módulo no lee los caracteres antes descritos, y envía ������ por cada carácter que no es capaz de leer (supongo que debe ser eso).

... Sí se pueden leer estos caracteres con iso-8859-1, pero no con UTF-8...

Espero comentarios.

Muchas gracias
panterozo
Perlero nuevo
Perlero nuevo
 
Mensajes: 160
Registrado: 2010-01-26 08:36 @400

Publicidad

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor explorer » 2010-04-05 10:15 @468

De basura nada... ;) seguro que lo que está viendo son caracteres codificados de forma distinta a lo que tu ordenador tiene configurado como codificación de caracteres de pantalla.

Yo también usaba antes la familia Spreadsheet Excel, pero ahora uso Spreadsheet::Read, porque me permite acceder a los contenidos de las celdas de forma muy gráfica, y con los contenidos de las mismas, tanto en su valor original, como en el de presentación. Y es justamente eso lo que tienes que averiguar: en qué están codificadas las celdas que contienen esos caracteres.

Por ejemplo, yo hace poco he tenido que hacer un programa que mostrara el contenido de una hoja Excel, subida por el cliente a un servidor, en una tabla HTML dentro de una página web. El problema era que las celdas, si no tenían acentos, venían codificadas en iso-8859-1, mientras que las que sí los tenían, venían codificadas en UCS2-LE (utf16), el nativo de varias versiones de Windows).

Al principio, lo resolví (con el módulo anterior), mirando los atributos de cada celda a pintar:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.                 if ($ATTR->[$columna]->[$fila]->{enc}) {
  2.                     my $b = from_to($contenido_celda, $ATTR->[$columna]->[$fila]->{enc}, "iso-8859-1");
  3.                 }
  4.  
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Con la ayuda de la función from_to() del módulo Encode, era fácil pasarlo todo a iso-8859-1.

Más tarde, me dí cuenta que, usando la función row(), el módulo me devolvía los contenidos de toda la fila, y ya convertidos:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     my @fila = row($HOJA, $fila);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

así que ya no tenía que preocuparme de hacer conversiones (o, al menos, la conversión se hacía hacia el iso-8859-1 de Perl, y con eso me bastaba para sacar la información hacia el exterior).

En tu caso... recuerda que Data::Dumper es tu amigo... haz volcados de los contenidos de la hoja Excel leída, para ver en qué codificación está, o a ver si te lo dice en el hash de atributos de cada celda.

Por lo que veo, con la función $cell->value() se puede sacar el valor formateado de la celda, mientras que con $cell->unformatted(), el no formateado (lo estoy viendo en la sinopsis del módulo Spreadsheet::ParseExcel).

En vez de Spreadsheet::ParseExcel::FmtJapan::TextFmt, ¿has probado con Spreadsheet::ParseExcel::FmtDefault::TextFmt? Según veo en su código, esta función devuelve caracteres en unicode, a partir de enteros de 16 bits (codificación utf16):
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     return pack( 'U*', unpack( 'n*', $sTxt ) );
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

El FmtJapan intentará hacer conversión a cp932 :)
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor panterozo » 2010-04-05 10:57 @498

No quiere nada de na :s

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $parser   = Spreadsheet::ParseExcel->new();
           my $workbook = $parser->parse('CopiaGranCuenta.xls');

           if ( !defined $workbook ) {
               die $parser->error(), ".\n";
           }
               

                for my $worksheet ( $workbook->worksheets() ) {

               my ( $row_min, $row_max ) = $worksheet->row_range();
                           my $i=0;
               for my $row ( $row_min .. $row_max ) {
                   

                       my $cell = $worksheet->get_cell( $row, 0 );
                       if($cell->value()){
                       
                       
                        $cell = $worksheet->get_cell( $row, 7 );
                        my $hola;#nosé que se le envia mas abajo... Si quiero hacerle un new a FmtDefault, tampoco entiendo que es lo que se le envia :s
                        my $area = Spreadsheet::ParseExcel::FmtDefault::TextFmt($hola,$cell->value());#El problema :s
                        print "\n".$area."\n";
                       
                       $i++;
                                   }
               }
           }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



Los datos que se encuentran en el archivo Excel son estos:

Emil-Figge-Str. 76-80
Savignyplatz 3
11 couris vlmy
4th Floor
38 Anson Road 
125 Robin Dr
Vibaekvej 100, Brylle
Lägerhyddsvägen 2, Hus 38 #Aquí muere :S

L�gerhyddsv�gen 2, Hus 38 #Lo que muestra


He probado de todo :s, los módulos que tiene SpreadSheet::ParseExcel...

Suizas el problema sea que estoy implementando mal el módulo, y ruego por ayuda.. ya me explosiona la cabeza con este problema :s...

¿Como se haría el volcado con Data::Dumper para saber el tipo de codificación en que se encuentra el archivo?
panterozo
Perlero nuevo
Perlero nuevo
 
Mensajes: 160
Registrado: 2010-01-26 08:36 @400

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor panterozo » 2010-04-05 11:10 @507

He probado esto, y me indica de que sí es utf8 :s
Retorna 1.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$cell = $worksheet->get_cell( $row, 7 );
                        my $flag=utf8::valid($cell->value());
                        print $flag."\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
panterozo
Perlero nuevo
Perlero nuevo
 
Mensajes: 160
Registrado: 2010-01-26 08:36 @400

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor panterozo » 2010-04-05 11:22 @515

Por fin :D

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
                        $cell = $worksheet->get_cell( $row, 7 );
                        my $flag=utf8::is_utf8($cell->value());
                        my $data = $cell->value();
                        my $largo = Encode::from_to($data, "iso-8859-1", "utf8"); #1
                                                $data = decode("iso-8859-1", $data);
                        print $data."\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



Gracias, explorer, por las indicaciones ;)
panterozo
Perlero nuevo
Perlero nuevo
 
Mensajes: 160
Registrado: 2010-01-26 08:36 @400

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor explorer » 2010-04-05 11:55 @538

Creo que la línea marcada como #1, sobra. Y la de is_utf8(), también.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor panterozo » 2010-04-06 07:51 @369

Así es, explorer.

La emoción no me dejó ser más recatado con lo que publiqué :P

Al final quedó de la siguiente manera:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$cell = $worksheet->get_cell( $row, 6 );
my $data = $cell->value();
my $largo = Encode::from_to($data, "iso-8859-1", "utf8");
my $celda = decode("iso-8859-1", $data);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Puedo leer ahora todo tipo de caracteres.
Gracias nuevamente ;)
panterozo
Perlero nuevo
Perlero nuevo
 
Mensajes: 160
Registrado: 2010-01-26 08:36 @400

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor explorer » 2010-04-06 07:58 @374

¿Seguro que la línea de la función from_to(), no sobra?
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor panterozo » 2010-04-06 08:09 @381

Es curioso... sin la función from_to() obtengo lo siguiente

Vl S�o Franc

Y con ella...

Vl São Franc


En perldoc aparece el uso de ambas

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
from_to($data, "iso-8859-1", "utf8"); #1
$data = decode("iso-8859-1", $data);  #2

Both #1 and #2 make $data consist of a completely valid UTF-8 string but only #2 turns UTF8 flag on
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Según entiendo, en la segunda fila es donde se vuelve realmente utf8.
panterozo
Perlero nuevo
Perlero nuevo
 
Mensajes: 160
Registrado: 2010-01-26 08:36 @400

Re: Leer archivo.xls con SpreadSheet::ParseExcel

Notapor explorer » 2010-04-06 11:18 @512

El párrafo que comentas, en Encode, comienza por:

CAVEAT: The following operations look the same but are not quite so;

que quiere decir:

ADVERTENCIA: Las siguientes operaciones tienen el mismo aspecto, pero no lo son tanto;

Por eso te decía que las dos hacen lo mismo: convierten la ristra de octetos en datos UTF8 válidos, pero solo la segunda activa, además, la bandera de que el escalar almacena realmente una cadena UTF8.

Yo, sospecho, que la hoja Excel no está codificada como iso-8859-1, sino como ucs2-le (en los atributos de las celdas aparecería 'ucs2' en encoding). Si ese fuera el caso, con la siguiente línea sería más que suficiente:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$data = decode("ucs2", $data);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


De todas formas, sería mejor ver los ficheros con calma...

En el último programa que he hecho con Excel, he usado estas líneas para hacer la conversión:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
        $titulo = $HOJA->[4]->[$fila];                      # Valor no formateado

        if ($ATTR->[4]->[$fila]->{enc}) {
            my $b = from_to($titulo, $ATTR->[4]->[$fila]->{enc}, "utf-8");
        }
        else {
            my $b = from_to($titulo, "latin1", "utf-8");
        }
 
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

es decir, miro a ver la codificación de la celda (atributo 'enc' que me da Spreadsheet::Read). Si está especificada alguna, la paso tal cual a from_to(), para que lo pase a utf8. Pero si no hay ninguna codificación indicada, llamo a from_to() para que haga la conversión desde latin1 (codificación por defecto en Windows, similar a iso-8859-1).

No uso decode(), porque no estoy trabajando con utf8 todo el tiempo. Me vale con mandar la salida de $titulo a la página web, que ya tiene puesta la cabecera de charset a utf8.

Quizás para la próxima vez sí que lo use.

P.D. Me apunto otro módulo para usar en el futuro: Spreadsheet::DataFromExcel, aparte de revisar Spreadsheet::WriteExcel::Examples.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14482
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados