Función que devuelve el tamaño de un directorio y sus subdirectorios en bytes, KB, megas ….., según el parámetro pasado

// Resumen: Devuelve el tamaño del contenido de un directorio 
// y todos sus subdirectorios
//
// Sintaxis:
//[ <Result> = ] gfSizeFolder (<pcDirectorio> is string 
//       [, <pcTipeReturn> is string [, <sError> is string]])
//
// Parámetros:
//            pcDirectorio (ANSI string): Ruta <root> del 
//                         directorio a tratar
//            pcTipeReturn (ANSI string - valor 
//                         predeterminado="B"):
//                         Devolver el valor como: B (defecto)
//                         , KB, MB, GB, TB, PB, EB
//            sError (ANSI string - valor predeterminado=""): 
//                         Si se produce un error, se devuelve 
//                         el mensaje del error
// Valor de retorno:
//            numeric: Un valor correspondiente al parámetro 
/7                         "pcTipeReturn" o -1 si ocurre un error
//
// Ejemplo:
//            gfSizeFolder("c:\temp","MB")
//
PROCEDURE gfSizeFolder(LOCAL pcDirectorio is string, 
       LOCAL pcTipeReturn is string = "B", 
       LOCAL sError is string = "")

//*---------------------------------------------------------------
//*
//* Devuelve el tamaño del directorio pasado como parámetro (y 
//*         subdirectorios)
//*         NOTA: if ocurre Error, devuelve -1
//*
//*         Exabyte (EB)
//*         Petabyte (PB)
//*         Terabyte (TB)
//*         Gigabyte (GB)
//*         Megabyte (MB)
//*         Kilobyte (KB)
//*         byte (B)
//*
//*---------------------------------------------------------------
lnSizeBytes, lnSizeReturn are numeric


WHEN EXCEPTION IN

     lnSizeBytes         = fDirSize(pcDirectorio)

              
     // Si ha ocurrido un error

     IF ErrorOccurred THEN

           // Lanzamos la excepción para capturar el error

           ExceptionThrow(1,ErrorInfo(errMessage))

     END

     
     SWITCH pcTipeReturn

           CASE "KB"

                 lnSizeReturn = lnSizeBytes / 1024
           CASE "MB"

                 lnSizeReturn = lnSizeBytes / (1024^2)
           CASE "GB"

                 lnSizeReturn = lnSizeBytes / (1024^3)
           CASE "TB"

                 lnSizeReturn = lnSizeBytes / (1024^4)
           CASE "PB"

                  lnSizeReturn = lnSizeBytes / (1024^5)
           CASE "EB"

                   lnSizeReturn = lnSizeBytes / (1024^6)
           OTHER CASE

                  lnSizeReturn = lnSizeBytes

      END

DO
     lnSizeReturn = -1
     sError = ExceptionInfo(errMessage)
END

RESULT (lnSizeReturn) 

Cómo obtener una imagen de la web y mostrarlo en un control IMAGEN

// Obtenemos la imagen
IF HTTPRequest("https://www.flasof.com/web/image/website/1/logo/Flash%20Software")
      sHeader is string = HTTPGetResult(httpHeader)
      
      // Si la cabecera ha devuelto un OK (código 200)
      IF Left(ExtractString(sHeader,2," "),3) = "200"
            
            // Cargamos al imagen en el control de imagen
            IMG_SinNombre1    = HTTPGetResult(httpResult)
      ELSE
            
            // Error, no se carga imagen
            IMG_SinNombre1=""
      END
END

Controlar excepciones

Al igual que otros lenguajes de programación, Windev dispone de varias opciones para controlar las excepciones que puedan ocurrir en la ejecución de los distintos procesos.  Para más información, consultar la siguiente dirección https://ayuda.windev.es/es-ES/?3034004

También es posible, aunque no siempre recomendable, el uso de una EXCEPCIÓN GENERAL que se ejecutará siempre que ocurra un error fuera de la gestión de otro control de EXCEPCIÓN.  Para ver más información, consultar la siguiente dirección https://ayuda.windev.es/es-ES/?3034001

Si ponemos el siguiente código en el inicio de nuestro proyecto, cuando ocurra un error, fuera del otro control de excepciones, se grabará el error en el fichero de LOG y se cerrará la aplicación  (aquí se podría personalizar nuestro método de registro de errores y avisos al usuario)

gdDiaInicio is Date = Today()
gtHoraInicio is Time = TimeSys()

// Este código se ejecuta cuando ocurre un error fuera de un control de EXCEPCIÓN.
// Se captura cualquier error que se produzca y se muestra el mensaje siguiente y se finaliza la aplicación
WHEN EXCEPTION
   fSaveText("Errores_generales.log",gdDiaInicio.ToString("DD:MM:YYYY") + " " + gtHoraInicio.ToString("HH:MM:SS") + CR + "Error: " + ExceptionInfo())
   EndProgram()
END

NOTA: En FoxPro se puede poner el siguiente comando: “ ON ERROR * ”, lo que hará es que la aplicación no muestre ni trate ninguno de los errores que se produzcan, continuando el código siguiente al error producido.  En Windev, si se hace uso del código anterior y no se finaliza el programa, al ocurrir un segundo error no se ejecutaría dicho código, ya que solo se puede ejecutar una vez.

Exportar a Excel

A la hora de exportar los grids, haciendo uso de la opción del botón derecho, se hace con los valores por defecto, pero se pueden configurar más opciones con la función AAFConfigure  ( https://ayuda.windev.es/es-ES/?1000022108&name=AAFConfigurar&lf=us )

Por ejemplo, si se quiere que se exporten los títulos y que conserve la posición de la columna del usuario y el aspecto del grid (colores), se debe poner la siguiente instrucción (mejor en la inicialización del proyecto para que afecte a todas las exportaciones de los grids):

AAFConfigure(aafTableToExcel, taColumnsTitles + taColumnDisplayedOrder + taWithLayout)

Lentitud del editor

Puede ser que tu editor le cueste cargarse cuando trabajas con tablas de 100.000 registros y en remoto. Para que no te cargue esos registros tienes en las propiedades del proyecto la opción DATA LIVE / VIEW

Campos de un DataSource

El siguiente código te devuelve los nombres de campo del Data Source entre comillas y separador por TAB

// Resumen: Devuelve una cadena con los nombres de campo del 
// Data Source entre comillas y separados por TAB
// Descripción de los parámetros de entrada/salida de 'GetDataSourceEncabezado':
//
// Sintaxis:
//[ <Result> = ] GetDataSourceEncabezado (<dsTabla> is data source)
//
// Parámetros:
//            dsTabla (data source): <indique aquí el rol de dsTabla>
// Valor de retorno:
//            ANSI string: //    Ninguno
//
// Ejemplo:
// Indique un ejemplo.
//
PROCEDURE GetDataSourceEncabezado(LOCAL dsTabla is Data Source):string
 
sReturn is string
sListItm is string
 
WHEN EXCEPTION IN
               
       // Lista campos en el Data Source
       sListItm = HListItem(dsTabla)
               
       // Componemos la cabecera
       FOR EACH STRING sAnItem OF sListItm SEPARATED BY CR
           sReturn += [TAB] + """"+sAnItem + """"
       END      
 
DO
       sReturn  = ""
       Error( ExceptionInfo(errMessage) )
END
 
RESULT (sReturn)

Volcar el contenido de un Datasource a un fichero ASCII

Seguramente pensarás en ExportToCSV y la verdad es que funciona para pequeñas cantidades de registros como 3.000 ó 4.000 registros.

Yo me tuve que enfrentar a una exportación de 500.000 registros y la verdad se moria… Cuando habían pasado 45 minutos, cancelé el proceso y busque otra forma de hacerlo. Aquí está el resultado que realizó el mismo proceso en menos de 1 minuto.

// Resumen: Vuelca el contenido de un Data Source a un fichero 
// ASCII, entrecomillando los campos y separando con un TABULADOR
//
// Sintaxis:
//
//[ <Result> = ] DataSourceToCSV (<nFileNum> is int, <dsTabla> 
//            is data source, <sTextoProgressBar> is string)
//
// Parámetros:
//            nFileNum (int): Identificador creado por FOPEN.  
//                    Será usado para escribir en el fichero
//            dsTabla (data source): Data source a tratar
//            sTextoProgressBar (ANSI string): Texto que se 
//                    mostrará en la barra de status junto al 
//                    ProgressBar
//            nFactorEscrituras (int OPCIONAL): Sirve para reducir 
//                    el número de veces que se escribe en disco.  
//                    Se acumulan tantas líneas como el factor 
//                    especificado y cuando se cumple, se escribe 
//                    en el fichero
// Valor de retorno:
//            boolean: // Ninguno
//
//
PROCEDURE DataSourceToCSV(LOCAL nFileNum is int, LOCAL dsTabla is Data Source, 
          LOCAL sTextoProgressBar is string, 
          LOCAL nFactorEscrituras is int = 100):boolean
 
bReturn is boolean = True
 
nLinea, nLineas are int
vValue is Variant
sLineToWrite is string
sListItm is string
 
// Cadena de texto que se usará para acumular texto y reducir el número 
// de escrituras en disco
sCadenaTextoParaEscribir is string
 
WHEN EXCEPTION IN
               
     nLinea  = 1
               
     // Número de registros en el Data Source
     nLineas = HNbRec(dsTabla)
               
     // Lista campos en el Data Source
     sListItm = HListItem(dsTabla)
 
     sCadenaTextoParaEscribir = ""
 
     ProgressBar(nLinea, nLineas,sTextoProgressBar, DarkBlue)
     Multitask(-1)
               
    // Procesamos todos los registros           
    HReadFirst(dsTabla)
    WHILE HOut(dsTabla) = False
                              
        sLineToWrite = ""
                              
        // Creamos el contenido entre comillas y separado por TAB
        FOR EACH STRING sAnItem OF sListItm SEPARATED BY CR
            vValue = {"dsTabla." + sAnItem, indItem}
            sLineToWrite += [TAB] + """"+ vValue + """"
        END
                              
       // Si se cumple el factor, escribimos la cadena en el fichero
       IF modulo(nLinea, nFactorEscrituras) = 0 THEN
 
           // Si la ventana tiene una barra de estado con una barra 
           // de progreso, se muestra en ella
           ProgressBar(nLinea, nLineas,sTextoProgressBar, DarkBlue)
           Multitask(-1)
                                              
           // Añadimos la línea sin CR al final, ya que la función: fWriteLine, lo añadirá
           sCadenaTextoParaEscribir += sLineToWrite
                                              
           // Escribimos la línea
           fWriteLine(nFileNum, sCadenaTextoParaEscribir)
                                              
           sCadenaTextoParaEscribir = ""
       ELSE
          // Añadimos un retorno de carro
          sCadenaTextoParaEscribir += sLineToWrite + CR
       END
                              
       nLinea ++
                              
       HReadNext(dsTabla)
   END
 
   // Si ha quedado texto sin escribir
   IF sCadenaTextoParaEscribir <> "" THEN
      // Escribimos la línea
     fWriteLine(nFileNum, sCadenaTextoParaEscribir)
   END
DO
   bReturn = False
   Error( ExceptionInfo(errMessage) )
END
 
RESULT(bReturn)