• Publicidad

Carga de información de Excel a base de datos

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

Re: Carga de información de Excel a base de datos

Notapor Txemaracas » 2011-06-06 08:18 @387

Hola explorer. Así es como me ha quedado el código pero tengo los problemas o las dudas que he escrito en el código con "#". ¿Me puedes echar un vistazo rápido y decirme si lo tengo bien? Por cierto, cuando lo ejecuto me da el siguiente error:

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
syntax error at Abrir.pl line 111 near "$sheet ("
syntax error at Abrir.pl line 161 near "}"
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Estoy en Windows porque tiene que correr en Windows el programa.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.     #!c:/perl/bin
  2.      
  3.     use Spreadsheet::Read;
  4.     use Spreadsheet::XLSX;                # Módulos requeridos  por el programa
  5.     use strict;
  6.     use warnings;
  7.     use DBI;
  8.     use ConectarDB;
  9.     use autodie;
  10.     use Modern::Perl;
  11.      
  12.     # cargar excel.
  13.      
  14.     my $excel = Spreadsheet::XLSX -> new ('test.xlsx');
  15.      
  16.     # Subrutina crear. ¿Está bien hecho el pasarle a la variable $dbh el valor?
  17.     # ¿O debería llamar otra vez a la base de datos desde  aquí dentro? ¿Debería devolver  al  final  el dbh?
  18.      
  19.     sub  crearTabla {
  20.      
  21.         my $dbh = $_[1];
  22.      
  23.         eval  {$dbh->do("CREATE TABLE $_[0] (nombre VARCHAR(40), palabra VARCHAR(50))")};
  24.      
  25.         if ($@) {
  26.             printf("La tabala existe \n")
  27.         }
  28.     }
  29.      
  30.     # Subrutina  comparar. Sigo pasándole el valor de dbh como parámetro de entrada.
  31.     # ¿Hago bien la comparación en el while? Porque no sé cómo usar boleanos, por eso invento la variable encontrado
  32.      
  33.     sub comparar{
  34.      
  35.      
  36.             my($dbh,$sth,$encontrado);
  37.      
  38.             $dbh = $_[3];
  39.      
  40.             $sth = $dbh->prepare("SELECT * FROM $_[2]");
  41.      
  42.             $sth->execute();
  43.      
  44.             $encontrado = 0;
  45.      
  46.             while (my $ref = $sth->fetchrow_hashref()or $encontrado==0) {
  47.      
  48.                    if  ( $_[0] = $ref->{'palabra'}){
  49.      
  50.                           $encontrado = 1;
  51.                     }
  52.             }
  53.      
  54.             $sth->finish();
  55.      
  56.             return $encontrado;
  57.     }
  58.      
  59.     # Subrutina  insertar. Aquí sigo igual pasando el parámetro dbh. Esto creo que está bien, pero
  60.     # ¿debería devolver el parámetro dbh?
  61.      
  62.     sub insertar {
  63.      
  64.             my($dbh,$sth);
  65.      
  66.             $dbh = $_[3];
  67.      
  68.             $sth = $dbh->prepare("INSERT INTO $_[2](nombre, palabra) VALUES (?,?)") or die("Couldn't prepare statement: " . $dbh->errstr);
  69.      
  70.             $sth->execute($_[1]-> {Val},  $_[0]->{Val}) or die("Couldn't execute statement: " . $sth->errstr);
  71.      
  72.             $sth->finish;
  73.     }
  74.      
  75.     # Conectar base de datos y mirar si existe. Esto está bien porque me lo pasaste tu, pero
  76.     # ¿el say @databases no debería mostrar por pantalla las  bases de datos? Lo pregunto porque no lo hace
  77.      
  78.     my($dbh,$sth);
  79.      
  80.     my @databases = DBI->data_sources("mysql", {host => 'localhost', user => 'root', password => 'mybase'});
  81.      
  82.     say "@databases";
  83.      
  84.     my $base_datos = 'abrir';
  85.      
  86.     my $dsn = "DBI:mysql:$base_datos";
  87.      
  88.     unless ($dsn ~~ @databases) {
  89.      
  90.             my $drh = DBI->install_driver("mysql");
  91.      
  92.             my $rc = $drh->func("createdb", $base_datos, 'localhost', 'root', 'mybase', 'admin');
  93.      
  94.             say "[$rc]";
  95.     }
  96.     else {
  97.      
  98.             say "La base de datos $base_datos ya está creada";
  99.      
  100.     }
  101.      
  102.      
  103.     @databases = DBI->data_sources("mysql", {host => 'localhost', user => 'root', password => 'mybase'});
  104.      
  105.     say "@databases";
  106.      
  107.     $dbh = ConectarDB->connect()
  108.      
  109.     #Leer excel.
  110.      
  111.     foreach my $sheet (@{$excel -> {Worksheet}}) {
  112.      
  113.             printf("Sheet: %s\n", $sheet->{Name});
  114.      
  115.             my$hoja = $sheet->{Name};
  116.      
  117.             &crearTabala($hoja, $dbh);   # llamada a crear y le paso los parámetros para que me la  cree.
  118.      
  119.             my $cell3 = "NoValor";       # Aquí tengo dudas porque como el parámetro cell3 no tiene valor,
  120.                                          # le asigno este por si acaso una  palabra no tiene un  nombre
  121.                                          # en la celda de su izquierda.
  122.      
  123.             $sheet -> {MaxRow} ||= $sheet -> {MinRow};
  124.      
  125.              foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) {
  126.      
  127.                     $sheet -> {MaxCol} ||= $sheet -> {MinCol};
  128.      
  129.                     foreach my $col ($sheet -> {MinCol} ..  $sheet -> {MaxCol}) {
  130.      
  131.                             my $cell = $sheet -> {Cells} [$row] [$col];
  132.      
  133.                             my $cell2;
  134.      
  135.                             if (exists $cell->{Val}and $cell->{Val} =~ m/a/i) {
  136.      
  137.                                 my $cell2 = $sheet -> {Cells} [$row] [--$col];
  138.      
  139.                                 if (exists $cell2->{Val} and $cell2->{Val} !~ m/a/i ) {
  140.      
  141.                                             # Comprobar que la palabra no existe en la base de datos y
  142.                                             # asignarle el valor de esta cell2 a cell 3 por si la siguiente
  143.                                             # palabra  no tiene nombre asignarle este mismo.
  144.      
  145.                                            if( &comparar($cell, $cell2, $hoja, $dbh) == 0 ){
  146.      
  147.                                                     &insertar($cell, $cell2, $hoja, $dbh);
  148.      
  149.                                                     $cell3=$cell2;
  150.                                             }
  151.      
  152.                                  }else{
  153.      
  154.                                             if( &comparar($cell, $cell3, $hoja, $dbh) == 0 ){
  155.                                                 # si no tiene valor la cell2 hacemos lo mismo que arriba pero pasando cell3
  156.      
  157.                                                     &insertar($cell, $cell3, $hoja, $dbh);
  158.      
  159.                                             }
  160.                                            
  161.                                  }
  162.                             }
  163.      
  164.                     }
  165.             }
  166.      }
  167.      
  168.     # Desconectar base de datos.
  169.      
  170.     $dbh->disconnect;
Coloreado en 0.005 segundos, usando GeSHi 1.0.8.4
Txemaracas
Perlero nuevo
Perlero nuevo
 
Mensajes: 136
Registrado: 2011-04-04 10:06 @462

Publicidad

Re: Carga de información de Excel a base de datos

Notapor explorer » 2011-06-06 09:17 @428

El error de la línea 111 es porque la 107 no termina en ';'.

Del resto del programa, ya lo miraré, cuando tenga tiempo.
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: Carga de información de Excel a base de datos

Notapor explorer » 2011-06-06 16:10 @715

Cosas que he visto...

* Líneas 5 y 6: no necesitas activar los warnings y el strict, porque de ello ya se encarga el módulo Modern::Perl

* Línea 117: está mal escrita el nombre de la subrutina crearTabla()

* Si, suponemos, que hemos usado el módulo ConectarDB para realizar la conexión a la base de datos, es normal pasar la variable $dbh a todas las subrutinas que van a necesitar conectarse a la base de datos. Es una forma de programar en la que las subrutinas reciben toda la información desde fuera, y no dependen del valor de variables globales. Eso sí, lo de leer $_[1] o $_[3], es fatal... debes pasarle a las subrutinas solo los valores que va a necesitar, y nada más. Y dentro de la subrutina, leer todos los parámetros (si queda alguno sin pasar, es que se ha escrito mal la llamada a la subrutina). Por ejemplo, en la línea 21 se llama $dbh = $_[1]; ¿Qué ha pasado con $_[0]?

* En el while de la 46 a la 52, estás leyendo todas las líneas devueltas por la consulta. Y quieres salir en cuanto encuentres algo específico. En Perl, una forma de "romper" y "salir inmediatamente" de un bucle es con el comando last. Así que no te hace falta poner ninguna variable semáforo para saber cuándo debes salir.

Una cosa: la línea 48 está mal escrita: has puesto '=', indicando una asignación. Querrás poner un '==' (comparador de igualdad numérico) o un 'eq' (comparador de igualdad de cadena de caracteres).

Quedaría así:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1.             while (my $ref = $sth->fetchrow_hashref()) {
  2.      
  3.                    if  ( $_[0] eq $ref->{'palabra'}){
  4.                           $sth->finish();
  5.                           return 1;
  6.                     }
  7.             }
  8.             $sth->finish();
  9.  
  10.             return 0;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


* Línea 60. No entiendo por qué preguntas si deberías devolver el valor de $dbh. ¿Por qué va a devolver una subrutina un valor que ya recibe como argumento? Se supone que si alguien llama a la subrutina con ese parámetro, lo seguirá sabiendo cuando regrese de la subrutina...

* Mi código presenta las bases de datos, conectándose a la base de datos MySQL a través de una conexión TCP. Es posible que tu motor MySQL no tenga activada esa posibilidad.

* Estás usando el módulo Spreadsheet::XLSX, pero no el Spreadsheet::Read, así que te sobra la línea 3.

* Línea 133 sobra, porque está repetida en la 137 (declaración de la variable $cell2.

* Línea 137: estás decrementando el valor del $col, que es incompatible con el hecho de que es una variable controladora de bucle (línea 129), así que me temo que estás provocando un bucle infinito.

No he mirado más, sobre todo la parte de la lógica de programa a partir de la línea 139.
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: Carga de información de Excel a base de datos

Notapor Txemaracas » 2011-06-07 11:38 @526

Hola explorer,

gracias por mirarlo y en cuanto a lo que me preguntas de "Por ejemplo, en la línea 21 se llama $dbh = $_[1]; ¿Qué ha pasado con $_[0]?".

En la $_[0] le he pasado como parámetro el nombre de la hoja y lo he usado en
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. eval  {$dbh->do("CREATE TABLE $_[0] (nombre VARCHAR(40), palabra VARCHAR(50))")};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En cuanto al uso de la variable last() he mirado un poco y ¿se pondría así? ¿Y por qué pones otro $sth->finish() dentro del if()?

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. while (my $ref = $sth->fetchrow_hashref()) {
  2.      
  3.                last  if  ( $_[0] eq $ref->{'palabra'}){
  4.                           $sth->finish();
  5.                           return 1;
  6.                     }
  7.             }
  8.             $sth->finish();
  9.  
  10.             return 0;
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


En cuanto a
* Línea 137: estás decrementando el valor del $col, que es incompatible con el hecho de que es una variable controladora de bucle (línea 129), así que me temo que estás provocando un bucle infinito."
Lo que quiero es pasarle a cell2 el valor de la celda anterior a cell.


Y bueno, sé que todavía no has mirado lo último pero cuando lo ejecuto el programa funciona pero no hace lo que quiero puesto que cuando llega a los if(línea 145 y 154) que usa la subrrutina comparar() me inserta siempre otra vez todos los valores, sean iguales o no. Al final tengo duplicados todos los valores. ¿Eso a qué se debe?
Txemaracas
Perlero nuevo
Perlero nuevo
 
Mensajes: 136
Registrado: 2011-04-04 10:06 @462

Re: Carga de información de Excel a base de datos

Notapor explorer » 2011-06-07 13:42 @612

El ejemplo que te he puesto no es el mejor. Debería haberte dicho el de la subrutina comparar(), que es más lioso el uso de @_.

Es cierto que te he comentado el uso de la sentencia (no variable) last(), pero a la hora de escribir el código, me he dado cuenta de que era mejor salir de la subrutina por medio del return(). Perdón por tanto lío.

Si quieres obtener el valor de la celda anterior, deberías poner $col - 1, pero tendrás un problema para el caso de la primera columna.

Sigo sin saber qué es lo que quieres hacer...

Es decir, quieres meter la información de Excel a la base de datos, pero no veo qué tiene que ver aquí lo de mirar por celdas unas iguales a otras...

¿Lo puedes explicar? ¿Puedes poner ejemplos?
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: Carga de información de Excel a base de datos

Notapor Txemaracas » 2011-06-07 15:10 @674

Hola explorer. Si te explico lo que quiero hacer es lo siguiente:

--En una hoja de Excel contendrá una columna que será nombre y otra columna que será la palabra. En la columna "Nombre" estará el significado en castellano de la palabra que está en la columna "Palabra (significado en otro idioma)" en su misma fila. Pero si una de las palabras no contiene ningún nombre asociado, se le asociará el último que se ha escrito puesto que quiere decir que es la misma palabra en otro idioma. Por ejemplo:

si tengo el nombre "Hola" y en la columna palabra tengo "Hello". Pero también tengo en alemán "Hallo" y no contiene ningún nombre a su lado porque es el mismo que el de la palabra anterior con lo cual querría almacenarla con el nombre de la palabra anterior.


Lo que quiero hacer con la subrutina comparar es mirar si el usuario a añadido algún significado más de "Hola" en otros idiomas y añadirlo a la base de datos; sino, no se añade.
Txemaracas
Perlero nuevo
Perlero nuevo
 
Mensajes: 136
Registrado: 2011-04-04 10:06 @462

Re: Carga de información de Excel a base de datos

Notapor explorer » 2011-06-07 19:02 @834

Bien, aclarado el tema...

Salvo que entonces, en el código, ¿para qué pones las exp. reg. m/a/i?
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: Carga de información de Excel a base de datos

Notapor Txemaracas » 2011-06-08 05:35 @274

Bueno eso es por que lo usé para que solo me buscase las que empezasen por esa letra. Esa misma expresión la he quitado del if() de la línea 139 porque estaba mal, pero en el if() de la línea 135 está bien.
Txemaracas
Perlero nuevo
Perlero nuevo
 
Mensajes: 136
Registrado: 2011-04-04 10:06 @462

Re: Carga de información de Excel a base de datos

Notapor Txemaracas » 2011-06-08 10:54 @496

Pero lo que no sé es por qué me introduce otra vez todos los datos en vez de introducir solo los que se han añadido nuevos en el Excel.
Txemaracas
Perlero nuevo
Perlero nuevo
 
Mensajes: 136
Registrado: 2011-04-04 10:06 @462

Re: Carga de información de Excel a base de datos

Notapor explorer » 2011-06-08 13:27 @602

Yo lo ejecutaría con el depurador, ejecutándolo paso a paso, para saber en qué momento y por qué empieza a duplicar la información.

Quizás el problema esté en la famosa línea 48, y en lugar de

if ( $_[0] eq $ref->{'palabra'}) {

debería ser

if ( $_[0]->{Val} eq $ref->{'palabra'}) {

ya que es con {Val}, el método que usas para insertar los valores en la base de datos, según la línea 70.
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 12 invitados