Skip to main content
Announcements
NEW Customer Portal: Initial launch will improve how you submit Support Cases. FIND OUT MORE
cancel
Showing results for 
Search instead for 
Did you mean: 
Import
Creator
Creator

Carga de xls por hojas.

Buen día.

Solicito su colaboración para el siguiente inconveniente que me tiene frenado:

Estoy realizando una carga de información de diferentes archivos .xls; esta información viene un archivo mensual, pero las semanas están separadas por hojas, eso hace que haya algunos archivos con 4 hojas u otros con 5 hojas. Realicé la creación de un ciclo que me lee todos los archivos, pero no encuentro la forma para que me lea las hojas del archivo y me las cargue por semana.

Si alguien tiene una solución o algún link donde la pueda encontrar le agradezco.

1 Solution

Accepted Solutions
hector_munoz
Specialist
Specialist

Hola Juan,

Una solución podría ser usar la variable ErrorMode para evitar que el script se termine de ejecutar si encuentra un error, como podría ser el no encontrar cierta pestaña esperada dentro de un fichero.

Mira el siguiente código:

FOR EACH vsFile IN FileList('2017??.xlsx')

     FOR vsSlide = 1 TO 5

          IF $(vsSlide) = 5 THEN

               SET ErrorMode = 0;

          ENDIF

          LOAD SubField(FileName(), '\', -1) AS FICHERO,

               $(vsSlide) AS PESTAÑA,

               COMERCIAL,

               VENTAS

          FROM $(vsFile) (ooxml, embedded labels, table is [$(vsSlide)]);

          IF $(vsSlide) = 5 THEN

               SET ErrorMode = 1;

          ENDIF

     NEXT

NEXT vsFile

En él se ejecutan 2 bucles FOR similares (imagino) a los que tienes en tu script: el primero recorre los ficheros con la máscara 201???.xlsx (ficheros de año y mes, p.e. 201701.xlsx) y el segundo las supuestas 5 pestañas que podría tener cada uno de los ficheros dentro de sí. Si la semana es 5 se actualiza a 0 el valor de la variable ErrorMode para que el script no aborte en caso de error ya que es posible que no encuentre una pestaña con ese número en el fichero de la iteración.

No es lo más elegante que existe pero funciona. Te adjunto un ejemplo.

Saludos,

H

View solution in original post

9 Replies
hector_munoz
Specialist
Specialist

Hola Juan,

Una solución podría ser usar la variable ErrorMode para evitar que el script se termine de ejecutar si encuentra un error, como podría ser el no encontrar cierta pestaña esperada dentro de un fichero.

Mira el siguiente código:

FOR EACH vsFile IN FileList('2017??.xlsx')

     FOR vsSlide = 1 TO 5

          IF $(vsSlide) = 5 THEN

               SET ErrorMode = 0;

          ENDIF

          LOAD SubField(FileName(), '\', -1) AS FICHERO,

               $(vsSlide) AS PESTAÑA,

               COMERCIAL,

               VENTAS

          FROM $(vsFile) (ooxml, embedded labels, table is [$(vsSlide)]);

          IF $(vsSlide) = 5 THEN

               SET ErrorMode = 1;

          ENDIF

     NEXT

NEXT vsFile

En él se ejecutan 2 bucles FOR similares (imagino) a los que tienes en tu script: el primero recorre los ficheros con la máscara 201???.xlsx (ficheros de año y mes, p.e. 201701.xlsx) y el segundo las supuestas 5 pestañas que podría tener cada uno de los ficheros dentro de sí. Si la semana es 5 se actualiza a 0 el valor de la variable ErrorMode para que el script no aborte en caso de error ya que es posible que no encuentre una pestaña con ese número en el fichero de la iteración.

No es lo más elegante que existe pero funciona. Te adjunto un ejemplo.

Saludos,

H

Import
Creator
Creator
Author

Esta solución podría funcionar, el dilema es que las pestañas no están numeradas, por ejemplo, para enero están de la siguiente forma:

Captura.PNG

y así para todos los meses.

Esto me lleva a preguntarme si en la Sentencia FOR puedo colocar los nombres directos de las pestañas? O qué posible solución alterna podría tener.

Gracias.

Quedo atento.

hector_munoz
Specialist
Specialist

Hola Juan,

Prueba lo siguiente ahora (cambios en naranja):

FOR EACH vsFile IN FileList('2017??.xlsx')

       LET vsMesIteracion    = Pick(Num(Right(SubField(SubField('$(vsFile)', '\', -1), '.', 1), 2)), 'ENERO', 'FEBRERO', 'MARZO', .., 'DICIEMBRE');

    FOR vsSlide = 1 TO 5

          IF $(vsSlide) = 5 THEN

              SET ErrorMode = 0;

          ENDIF

         

          LET vsSlide2    = $(vsSlide) & 'ª ' & '$(vsMesIteracion)';

          LOAD SubField(FileName(), '\', -1) AS FICHERO,

              $(vsSlide) AS PESTAÑA,

              COMERCIAL,

              VENTAS

          FROM $(vsFile) (ooxml, embedded labels, table is [$(vsSlide2)]);

          IF $(vsSlide) = 5 THEN

              SET ErrorMode = 1;

          ENDIF

    NEXT

NEXT vsFile

Saludos,
H

Import
Creator
Creator
Author

Hola Hector.

El día de ayer realice lo siguiente, no sé si es lo más optimo pero me funciono. Me gustaría conocer tus comentarios al respecto.

FOR Each vFileName in Filelist ('$(v_RutaXls)\*.xls');

  LET vMes = Replace(Mid('$(vFileName)', Index('$(vFileName)',' ',-2), (Index('$(vFileName)',' ',-1)-Index('$(vFileName)',' ',-2))),' ','');

  SET vLash = 'ª $(vMes)$';

  FOR vSlide = 1 to 5

  If $(vSlide) = 5 or $(vSlide) = 4 or $(vSlide) = 3 or $(vSlide) = 2 THEN

  SET ErrorMode = 0;

  ENDIF

  Archivo:

  LOAD SubField(FileName(), '\', -1) AS FICHERO,

  '$(vSlide)$(vLash)' AS PESTAÑA,

  *

  FROM

  [$(vFileName)]

  (biff, no labels, table is [$(vSlide)$(vLash)]);

  LET vNombreTablaSave = SubField('$(vFileName)','\',-1);

  STORE Archivo into $(vSaveDataExt)$(vNombreTablaSave)_$(vSlide)_$(vLash).qvd (qvd);

  DROP Table Archivo;

  If $(vSlide) = 5 or $(vSlide) = 4 or $(vSlide) = 3 or $(vSlide) = 2 THEN

  SET ErrorMode = 1;

  ENDIF

  NEXT

NEXT vFileName

hector_munoz
Specialist
Specialist

Hola Juan,

Bajo mi punto de vista está fenomenal y seguro que tiene un muy buen rendimiento. Lo único es que yo sustituiría "IF $(vSlide) = 5 or $(vSlide) = 4 or $(vSlide) = 3 or $(vSlide) = 2 THEN" por "IF $(vSlide) > 1 THEN" por simplificarlo un poco, pero nada más.

Saludos,
H

Import
Creator
Creator
Author

Vale Hector, Muchas gracias!!!

Import
Creator
Creator
Author

Hector, quería preguntarte, este mismo código me serviría si requiero salir de la carpeta y entrar a otra? Lo pregunto por que ahora tengo varias carpetas y en cada carpeta estos archivos y el lío es que no sé si este me funcioné para lo mismo o si se puede realizar algo diferente. Por cierto, tengo que devolverme dos carpetas ya que los archivos están en CARPETA_CLIENTE\AÑO\Nombre archivo y solo voy a cargar los archivos que se encuentran el la carpeta 2017.

Agradezco mucho tu ayuda y respuesta.

Saludos.

hector_munoz
Specialist
Specialist

Hola Juan,

Aquí lo que haría sería crear una subrutina que leyese los ficheros de una ruta que se le pasa como parámetro y luego se llamase a sí misma, recursivamente, para procesar las subcarpetas existentes en la carpeta actual. Un ejemplo similar lo tienes en el manual de referencia (pág 271 FOR EACH..LOOP):

// lista de todos los archivos relativos a QV en disco

SUB DoDir (Root)

          FOR Each Ext in 'qvw', 'qva', 'qvo', 'qvs'

                    FOR Each File in filelist (Root&' \*.' &Ext)

                              LOAD     '$(File)' as Name,

                                            FileSize( '$(File)' ) as Size,

                                            FileTime( '$(File)' ) as FileTime

                              autogenerate 1;

                    NEXT File

          NEXT Ext

          FOR Each Dir in dirlist (Root&' \*' )

               call DoDir (Dir)

          NEXT Dir

ENDSUB

CALL DoDir ('C:');

En tu caso si en la sentencia CALL DoDir(<Directorio>) le pasas como <Directorio> la ruta en la que tienes las carpetas de los comerciales y combinas el código anterior con este de arriba, lo tendrías hecho.

Espero que te sirva!

Saludos,

H

Import
Creator
Creator
Author

Gracias Hector, es muy amable. esto es perfecto para lo que necesito.

Saludos