• Publicidad

Crear programa Perl que lea archivos Excel

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

Re: Crear programa Perl que lea archivos Excel

Notapor explorer » 2009-11-09 18:49 @826

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

Buena pregunta...

Yo el método que uso es hacer un bucle por las filas mientras exista contenido en la columna que yo sé que siempre debe contener información.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. my $BASE = ReadData($FICHERO_BASE, cells => 0, attr => 1);
  2. die "ERROR: Base de datos no encontrada" if not $BASE;
  3.  
  4. my %HOJAS = %{$BASE->[0]->{sheet}};             # Relación hojas -> índices
  5.  
  6. my $HOJA = $BASE->[ $HOJAS{$sector} ]->{cell};  # Referencia a la hoja $sector
  7.  
  8. for (my $fila = 1; $HOJA->[$columna]->[$fila]; $fila++) {
  9.     # Hacer algo con el contenido de la celda $HOJA->[$columna]->[$fila]
  10. }
Coloreado en 0.003 segundos, usando GeSHi 1.0.8.4

Este trozo de código hace lo siguiente:
  1. Leemos el fichero Excel. Como opciones, le indico (cells=>0) que no estoy interesado en que cree los accesos del tipo {A3}, sino que voy a acceder usando las coordenadas de fila y columna. Además (attr=>1) quiero que me saque otra estructura matricial semejante a las celdas, con los atributos de cada celda, porque quiero saber si lo que contienen son números, fórmulas o con qué codificación está escrito el texto que hay en la celda.
  2. Si no ha podido leerlo, terminamos.
  3. Inicializo el diccionario %HOJAS con los nombres de las hojas presentes en el libro Excel. Resulta que Spreadsheet::Read guarda en el arreglo que crea, en el elemento [0], una serie de informaciones. Una de ellas es un hash con datos del libro Excel. Y una de las claves es 'sheet', que contiene una referencia a otro hash que relaciona el nombre de cada hoja con el número de hoja dentro del libro. Así, si sabemos que la hoja se llama 'Hoja 1', esto nos indicará que es la hoja 1 (o la 2 o la 3, etc.) del libro Excel. Esto nos servirá para la siguiente línea.
  4. $sector contiene el nombre de la hoja. Así que $HOJAS{$sector} nos devuelve el número que es esa hoja dentro del libro. Ese número lo usamos como índice dentro de todo el libro $BASE, y con eso apuntamos a la hoja. De ella, nos interesa solo las celdas, así que extraemos una referencia a ellas que está bajo la clave 'cell'. Al final, en $HOJA tenemos una referencia a una estructura bidimensional de las celdas.
  5. Aquí, inicializo $fila a 1 porque los objetos Spreadsheet::Read lo hacen de esa manera, para facilitar el acceso. En cada vuelta, lo voy incrementando. Y el bucle se termina si el contenido de la celda no contiene ningún valor (o un valor indefinido), en la $columna y $fila correspondiente.

Pero... hay una forma más cómoda... Spreadsheet::Read sí que guarda el número máximo de filas y columnas. Lo hace como atributos de la hoja. En nuestro ejemplo, sería con
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $maximo_filas = $BASE->[ $HOJAS{$sector} ]->{maxrow};
my $maximo_cols  = $BASE->[ $HOJAS{$sector} ]->{maxcol};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

y a partir de aquí ya se puede hacer un bucle.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
for my $fila ( 1 .. $maximo_filas ) {
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


El porqué lo hago de la primera manera es porque estoy seguro que mi $columna contiene datos en todas las filas con información. Si lo hago de la segunda manera, es posible que haga ciclos sobre filas que no contienen información interesante (hay muchos casos en los que hay hojas Excel con filas que aparentemente no contienen información, pero sí estilos, o que tuvieron información y luego se borró, pero mantienen la información de formato de celda).
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Publicidad

Re: Crear programa Perl que lea archivos Excel

Notapor giote » 2009-11-11 09:53 @453

Muchas gracias por tu respuesta... me ha sido muy útil... ya he podido leer el Excel.

Ahora tengo dos problemitas.
  1. Tengo una columna en formato fecha... Visualmente se ve como "05/11/2009" y automáticamente se coloca en formato de celda Fecha corta en Excel. Cuando leo esta celda se muestra el siguiente número "40122".
    ¿Cómo hago para que cuando se lea, respete lo que hay visualmente? (Ya que creo que es más complicado decirle al cliente que cambie sus archivos... podría tenderse al error cuando no se haga)
  2. Por el momento me lee correctamente los xls. Estoy tratando de leer un xlsx y me genera error. No sé si deba instalar algo más para que pueda realizarse.

Muchas gracias
giote
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-11-09 18:01 @792

Re: Crear programa Perl que lea archivos Excel

Notapor explorer » 2009-11-11 10:36 @483

Excel guarda las fechas como días que han pasado desde 1900.

Spreadsheet::Read usa el módulo Spreadsheet::ParseExcel, que ofrece las funciones value() y unformatted(), que devuelven el valor de la celda de forma formateada (lo visual) y no formateada (lo que se almacena). El S::R, por defecto, siempre guarda el valor no formateado en la estructura bidimensional que está en {cell}. Y guarda el valor formateado si en el momento de la lectura del fichero le permitimos crear las entradas de las celdas con nomenclatura clásica.

Ejemplo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;

use Data::Dumper;
use Spreadsheet::Read;

my $BASE = ReadData('hoja.xls', cells => 1, attr => 1);

my $Hoja1 = $BASE->[ $BASE->[0]->{sheet}->{'Hoja1'} ];

my $columna = 2;
my $fila    = 24;

my $celda   = cr2cell($columna, $fila);

print "Celda:      [", $celda,                                      "]\n";   # Celda: [B24]

print "Original:   [", $Hoja1->{cell}->[$columna]->[$fila],         "]\n";   # Original: [40158]

print "Formateada: [", $Hoja1->{$celda},                            "]\n";   # Formateada: [11/12/09]

print "Atributos:  [", Dumper($Hoja1->{attr}->[$columna]->[$fila]), "]\n";   # Atributos:  [$VAR1 = {
#          'halign' => undef,
#          'locked' => 1,
#          'bold' => 0,
#          'valign' => 'bottom',
#          'enc' => undef,
#          'italic' => 0,
#          'font' => 'Arial',
#          'size' => '10',
#          'uline' => 0,
#          'fgcolor' => undef,
#          'bgcolor' => undef,
#          'format' => 'DD/MM/YY',
#          'wrap' => 0,
#          'hidden' => 0,
#          'merged' => 0,
#          'type' => 'date'
#        };
#]
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

En este hoja de cálculo, en la posición B24 he puesto una fecha. Le he pedido a S::R que cree las celdas con la nomenclatura clásica con la opción cells => 1 (que por defecto, es lo que hace, así que podríamos quitarlo). Accedemos a la hoja y leemos el contenido de la celda de las dos formas posibles. Y muestra en pantalla las dos formas.

Como añadidura, también le he pedido que genere la matriz de atributos y que nos muestre los que contiene esa celda. Vemos el formato que tiene ('DD/MM/YY').


Para el tema del xlsx, ¿has instalado el módulo 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: Crear programa Perl que lea archivos Excel

Notapor giote » 2009-11-11 11:41 @528

De nuevo muchas gracias...
Todo ha salido muy bien debido a sus explicaciones.
giote
Perlero nuevo
Perlero nuevo
 
Mensajes: 3
Registrado: 2009-11-09 18:01 @792

Re: Crear programa Perl que lea archivos Excel

Notapor jacks » 2011-04-12 07:16 @345

Hola. Estuve mirando un poco el programa de ejemplo que pusiste arriba, y la verdad, me da los siguientes errores y no sé por qué.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!c:/perl/bin
  2.  
  3. use Spreadsheet::Read;
  4. use strict;
  5. use warnings;
  6.  
  7. my $ref = ReadData("test.xls");  # Leer fichero <span class="posthilit">Excel</span>
  8. my $a3  = $ref->[1]{A3}, "\n";   # Contenido de la celda A3 de la hoja 1
  9. print $a3;                       # Imprime contenido  
  10. print $ref->[1]{label}, "\n";
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Errores:
-Useless use of a constant in void context at line 9.
-Use of uninitialized value in print at line 9.
-Can´t use an undifined value as an ARRAY reference at line 10.
jacks
Perlero nuevo
Perlero nuevo
 
Mensajes: 148
Registrado: 2011-04-05 11:14 @510

Re: Crear programa Perl que lea archivos Excel

Notapor explorer » 2011-04-12 09:30 @437

Me parece que $ref no contiene nada. Mejor dicho, contiene el valor undef, indicando que la ejecución de ReadData("test.xls") ha fallado.

¿Seguro que test.xls está en el mismo directorio en donde estás ejecutando tu programa?
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: Crear programa Perl que lea archivos Excel

Notapor jacks » 2011-04-12 09:37 @442

Pues tengo tanto el programa como el fichero Excel en la misma carpeta en el Escritorio. ¿Lo debería poner en otro lado?
jacks
Perlero nuevo
Perlero nuevo
 
Mensajes: 148
Registrado: 2011-04-05 11:14 @510

Re: Crear programa Perl que lea archivos Excel

Notapor explorer » 2011-04-12 09:54 @454

No, no tienen que estar en un determinado sitio.

Podrías poner la siguiente prueba para ver si el programa tiene acceso a ese fichero o no:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $fichero_excel = 'test.xls';

if (-f $fichero_excel) {
    print "Localizado. El fichero tiene ", -s $fichero_excel, " bytes\n";
}
else {
    print "$fichero_excel no localizado\n";
}
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
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: Crear programa Perl que lea archivos Excel

Notapor jacks » 2011-04-12 10:19 @471

Hola. He probado lo que me dijiste y sí que lo encuentra, pero me sigue poniendo esto:
Adjuntos
Dibujo.JPG
Dibujo.JPG (22.65 KiB) Visto 1154 veces
jacks
Perlero nuevo
Perlero nuevo
 
Mensajes: 148
Registrado: 2011-04-05 11:14 @510

Re: Crear programa Perl que lea archivos Excel

Notapor explorer » 2011-04-12 10:26 @476

Lo único que se me ocurre es que el fichero Excel esté creado con una versión muy moderna de Excel. ¿Qué versión Excel es?
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

AnteriorSiguiente

Volver a Básico

¿Quién está conectado?

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