Crear un fichero XML

MyXMLDoc is a xmlDocument

MyXMLDoc.rss.Channel[1].Title          = "Título"
MyXMLDoc.rss.Channel[1].Link           = "Enlace"
MyXMLDoc.rss.Channel[1].Description    = "Descripción de la entrada"
MyXMLDoc.rss.Channel[1].Copyright      = "Copyright @"
MyXMLDoc.rss.Channel[1].Webmaster      = "Web Master"
MyXMLDoc.rss.Channel[1].Image          = "Imagen"
MyXMLDoc.rss.Channel[1].Generator      = "Windev"

// Guarda el documento sin formato
XMLSave(MyXMLDoc, "c:\temp\sss.xml")

// Guarda el documento con formato (disponible a partir de la versión 22)
XMLSave(MyXMLDoc, "c:\temp\sss_formato.xml", XMLFormatting)

Permite [% %] en las cadenas

A partir de la versión 22 tienes una opción en las propiedades de compilación del Proyecto que permite poner el nombre de las variables dentro de una cadena. Esto es muy util pues clarifica la programación.

Lo configuras en:

Y compara el código antes de la versión 22:

SQLData is Data Source
lcCadena is string

lcCadena = [

   Select SEMANA, [%1] from fechas….

]

IF NOT HExecuteSQLQuery ( SQLData, MiConexion, hQueryWithoutCorrection, StringBuild(lcCadena, year1)) Then
     Error (HErrorInfo())
END

Después de la versión 22:

lcCadena = [

        Select SEMANA, [%year1%] from fechas….
]

IF NOT HExecuteSQLQuery ( SQLData, Miconexion, hQueryWithoutCorrection) Then
    Error (HErrorInfo())
END

Conectarse a SQL Server

Puedes hacerlo con el Driver que te vende Windev o con OLE DB. Aquí te muestro la forma de hacerlo por OLE DB

MiConexion is Connection

// Completa valores generales de la conexión
MiConexion..Server = "MiPC\SQLEXPRESS"
MiConexion..Database = "BasedeDatos1"
MiConexion..Access = hOReadWrite
MiConexion..Provider = hOledbSQLServer
MiConexion..CursorOptions = hClientCursor + hStaticCursor + hReadOnlyCursor

// Conexión con USR y PASS
IF True THEN
       MiConexion..User        = "sa"
       MiConexion..Password    = "xxxxx"
       MiConexion..ExtendedInfo = ""

// Conexión Windows Authentication
ELSE 
       MiConexion..User        = ""
       MiConexion..Password    = ""
       MiConexion..ExtendedInfo = "Trusted_Connection=YES"
END

IF NOT HOpenConnection(MiConexion) THEN
      Error(HErrorInfo())
      EndProgram()
END

Descomprimir ficheros ZIP con Windev

// Tres parámetros desde comandos
// [1] - zipPath - ubicación del archivo a descomprimir
// [2] - zipName - nombre del archivo a descomprimir
// [3] - zipExtPath - ubicación de descompresión del archivo zip

zipPath is string = CommandLine(1)
zipName is string = CommandLine(2)
zipExtPath is string = CommandLine(3)

IF fFileExist(zipPath+"\"+zipName) THEN
   IF NOT fDirectoryExist(zipExtPath) THEN
      fMakeDir(zipExtPath)
   END

   zipOpen("zipArchive", zipPath+"\"+zipName)
   zipExtractAll("zipArchive", zipExtPath)
   Info("Zip descomprimido")
ELSE
    Info("Zip no encontrado"+CR+"ZipPath: "+zipPath+CR+"ZipName:         "+zipName+CR+"ZipExtractPath: "+zipExtPath)
END

La función HReadSeekFirst

Estaba usando la función de Windev “HReadSeekFirst”,  para saber si un registro existía en disco y me estaba tardando mucho.  Realizar 20 llamadas a esta función le llevaba 40 segundos :-O.

La base de datos es SQL-SERVER y se accede por OleDB

La tabla sobre la que se hace la búsqueda está indexada por el campo a buscar

La tabla solo tiene 65.000 registros

Viendo el resultado que estaba teniendo, he optado por crear mi propia función de búsqueda un SELECT SQL directo a la base de datos, y ejecutando las mismas 20 consultas, el resultado es instantáneo, por poner algo sería 1 segundo.

CONCLUSIÓN:  Para tablas “pequeñas”, se pueden usar las funciones de Windev, pero para tablas medianas o grandes, lo mejor es usar el SQL del  propio motor (SQL-SERVER, MySQL, etc).

OLEDB y Timeout

Si trabajas con OLEDB, te interesa conocer estos dos valores para la cadena de conexión:   WD Connection Timeout    WD Command Timeout

En el enlace: https://help.windev.com/?9000124&name=optional_connection_information  explican su uso.

Estaba teniendo un problema con SQL Server, ya que tengo un SQL que inserta 400.000 registros con un INSERT SQL ….. SELECT otra tabla,   y en la ejecución en LOCAL me tarda entre 25-30 segundos.  A veces me funcionaba bien pero otras veces, me daba error de TIMEOUT y no se ejecutaba.  Cuando lo ejecuto contra el servidor de producción, el tiempo se va a 50-60 segundos y SIEMPRE me da error de TIMEOUT.

Windev, por defecto tiene establecido 30 segundos de espera para la ejecución de comandos SQL para conexiones nativas o por OLEDB, y si la instrucción dura más de 30 segundos, la cancela.

La forma de solucionarlo, es usar “WD Command Timeout=xxxxx” segundos en la cadena de conexión.

Le he puesto “WD Command Timeout=3600” (una hora) y …. ¡FUNCIONA!  J, ahora las consultas grandes que duran 1-3 minutos se ejecutan sin problemas.

Tipo de Dato RECORD que permite hacer SCATTER y GATHER (como en Fox)

/////////////////////////////////////
// Ejemplo para insertar un registro
////////////////////////////////////

rgCondMod1 is Record of condiciones_modificaciones

// Inicializamos los valores, Similar a un SCATTER MEMVAR de Fox

HReset(rgCondMod1)

// Si quisieramos cargar un registro existente, usaríamos primero: HReadSeek( 
//if hreadseek(condiciones_modificaciones,FKIMPORTA,1) THEN
     // Inicializamos los valores, Similar a un SCATTER MEMVAR de Fox
     // rgCondMod1 = condiciones_modificaciones
//END

// Actualizamos valores

rgCondMod1.FKIMPORTA= 1
rgCondMod1.NTIPOMODI= 2
rgCondMod1.FKIDCONDIC= 3

// Volcamos el registro sobre la tabla, Similar a un GATHER MEMVAR de Fox

condiciones_modificaciones = rgCondMod1

// Insertamos el registro en disco

HAdd(condiciones_modificaciones)

La ventaja de usar un RECORD, es que lo puedes pasar como parámetro entre clases, métodos, etc

Si se necesita una explicación más exhaustiva sobre el paso de parámetros, se puede consultar la ayuda https://ayuda.windev.es/es-ES/?1514077&name=passing_parameters

Para pasar parámetros a una ventana hija,  y que los cambios en ella se vean reflejados en la variable de la ventana padre, no hay que hacer nada especial, se pasan como a cualquier otro proceso.

Siguiendo el ejemplo anterior y teniendo una ventana hija llamada “Win_prueba2”, la llamada se haría así:

Open(WIN_prueba2, rgCondMod1)

En la sección de declaración de la ventana WIN_prueba2 se pondría así:

PROCEDURE WIN_prueba2(rgCondModWin is Record of condiciones_modificaciones)

*- NOTA: No es obligatorio poner el tipo de variable “is Record of condiciones_modificaciones”, pero si se pone, Windev nos ofrece la ayuda en línea para la variable, mostrando el nombre de los campos al poner el “.”

No hace falta devolver ningún valor a la ventana padre, ya que por defecto Windev pasa los parámetros por referencia.  Los cambios que se hagan sobre la variable en la ventana hija se verán reflejados en la variable de la ventana padre.

Si se quiere forzar a que se pasen los parámetros por valor (evitando que los cambios en la ventana hija afecten a la padre), se puede declarar la variable usando el comando LOCAL.  Quedaría así:

PROCEDURE WIN_prueba2(LOCAL rgCondModWin is Record of condiciones_modificaciones)