martes, 5 de marzo de 2024

Qué es un Queue!? ... en Clarion

Publicado por EMoreno el 11/01/2006 - LWP

Hola que tal.
Una QUEUE es una estructura en memoria. Puede ser de un campo hasta "n" números de campos, con 1 registro o "n" número de registros, dependiendo de la manipulación que hagas de ellos.

Cuando haces un browse, realmente lo que ves en pantalla es una QUEUE, esta declarada de la misma manera que el archivo, Clarion lo que hace es cargar desde el archivo a la QUEUE.

A una QUEUE la puedes manipular:
       - Agregando Registros (Add)
      - Modificando datos (Put)
      - Eliminando registros (Delete)
      - Ordenarla (Sort)
      - Obtener un registro determinado (Get)
Entre otras cosas.

Como es una estructura en memoria las QUEUE's trabajan súper rápido (obviamente esto va de la mano de acuerdo con el procesador que cuentes).

La manera en que declaras un archivo en tu diccionario es similar en cuanto a los campos a como se declara una QUEUE ya dentro de la aplicación, la diferencia es que al archivo en el DCT le puedes agregar llaves e índices, y a la QUEUE no le puedes agregar ni llaves e índices, pero le puedes poner ordenamiento.

Las QUEUE's las puedes usar para muchas cosas, su uso es muy variable.
Puede ser para procesamiento de datos, para imprimir reportes complejos, para crear listados etc..

Un ejemplo algo simple de una QUEUE es el siguiente:


QEjemplo QUEUE,PRE()
Campo_Clave Short
Campo_Nombre String(20)
END

Free(QEjemplo) ! Liberar y limpiar QUEUE
QEjemplo.Campo_Clave = 4
QEjemplo.Campo_Nombre = 'Perro'
Add(QEjemplo)

QEjemplo.Campo_Clave = 2
QEjemplo.Campo_Nombre = 'Delfin'
Add(QEjemplo)

Sort(QEjemplo, QEjemplo.Campo_Clave)
Loop ABC# = 1 To Records(QEjemplo)
Get(QEjemplo, ABC#)
Message(QEjemplo.Campo_Clave & '|' & QEjemplo.Campo_Nombre)
End

Sort(QEjemplo, QEjemplo.Campo_Nombre)
Loop ABC# = 1 To Records(QEjemplo)
Get(QEjemplo, ABC#)
Message(QEjemplo.Campo_Clave & '|' & QEjemplo.Campo_Nombre)
End



Espero haber sido de ayuda.
Saludos

P.D. A mí las QUEUE's me facilitan mucho el trabajo y me ahorran mucho tiempo.


jueves, 6 de julio de 2023

Caracteres válidos

Muchas veces cuando se procesa un archivo desde nuestra aplicación; ya sea un .txt, .csv, .xls, etc.; necesitamos controlar ciertos caracteres que pueden grabarse en tablas y que no son compatibles. Un ejemplo claro es la letra "Ñ", "ñ" o algunos tipos de tildes (acentos) y cualquiera sea el caso muchas veces se guardan símbolos medios raros que después quedan reflejados en Grillas o Reportes y que no se ven bien.

Es por eso que acá dejo un código, que me ha servido de mucho para sortear esas eventualidades al procesar información que llega desde otros medios de almacenamiento. Yo normalmente, lo utilizo como una Subrutina, pero a criterio de quién quiera incorporarlo dentro de su aplicación lo puede hacer como mejor y cómodo le sea. 

Variables:

&ii Tipo Numeric (4)
&largo Tipo Numeric (4)
&string Tipo Character (30)
&Posicion Tipo Character (1)

Código:

Sub 'CaracterValido'
&ii = 1 
&largo = &string.Length() 
do while &ii <= &largo 
&Posicion = &string.Substring(&ii, 1)
do case 
  case &Posicion = '¥'
        &string = strreplace(&string,&Posicion,'Ñ')
  case &Posicion = '^' 
  &string = strreplace(&string,&Posicion,'') 
  case &Posicion = '+' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '/' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '*' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '?' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = 'º' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '!' 
        &string = strreplace(&string,&Posicion,'') 
  case &Posicion = '#' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '%' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '&' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '(' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = ')' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '=' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '¿' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '<' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '>' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '@' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '\' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '~' 
        &string = strreplace(&string,&Posicion,'') 
  case &Posicion = '?' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '¬' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '{' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '}' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '[' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = ']' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '´' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = 'Ç' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = 'ç' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion='Á' or &Posicion='Â' or &Posicion='Ä'
  &string = strreplace(&string,&Posicion,'A') 
  case &Posicion = 'Ã'
&string = StrReplace(&string, &Posicion, '')
  case &Posicion='É' or &Posicion='Ê' or &Posicion='Ë' 
&string = strreplace(&string,&Posicion,'E') 
  case &Posicion='Í' or &Posicion='Î' or &Posicion='Ï' 
&string = strreplace(&string,&Posicion,'I') 
  case &Posicion='Ó' or &Posicion='Ô' or &Posicion='Ö' 
&string = strreplace(&string,&Posicion,'O') 
  case &Posicion='Ú' or &Posicion='Û' or &Posicion='Ü' 
&string = strreplace(&string,&Posicion,'U')
  case &Posicion='"' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '`' 
&string = strreplace(&string,&Posicion,'')
  case &Posicion = '`' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '´' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = '©' 
&string = strreplace(&string,&Posicion,'') 
  case &Posicion = "'" 
&string = strreplace(&string,&Posicion,'')
endcase 
&ii = &ii + 1 
enddo
endsub

Como se puede ver en el código a medida que se me presentaban caracteres extraño o que se grababan mal en la tabla iba agrregando nuevos "case ..." para reemplazarlos.
Como siempre digo se puede mejorar, cualquier critica es bienvenida, espero sirva y se comprenda el ejemplo.

viernes, 23 de junio de 2023

Procedimiento para retornar una fecha con un formato específico II

En esta ocasión vamos a definir un procedimiento que ingrese una fecha de tipo caracter o cadena, y, devolvamos o retornaremos un Date o sea una fecha válida.

Sin más vamos al ejemplo, el nombre del objeto en cuestión es a criterio de cada uno lo vamos a llamar para este caso, "ConvertirDDMMAAAAaDate" (Convertir cadena "DDMMAAAA" y retornar una Fecha)

Rules:

parm(in:&FechaTxt, out:&Fecha);
&Fecha de tipo Character (10).
&Fecha de tipo Date, propiedad Picture 99/99/9999.
La variable &FechaTxt puede ser con formato "dd/mm/aaaa", "dd-mm-aaaa" etc.

Suorce:

Vamos a suponer que el parámetro entrante es: "23/06/2023"

&dia =  Val(SubStr(&FechaTxt,1,2)) --> &dia de tipo Numeric(2)
&mes =  Val(SubStr(&FechaTxt,4,2)) --> &mes de tipo Numeric(2)
&anio = Val(SubStr(&FechaTxt,7,4)) --> &mes de tipo Numeric(4)
&Fecha = YMDtoD(&anio,&mes,&dia)

Es muy similar al anterior, pero esta vez ingresa una cadena de caracteres como fecha y debemos transformarla. Se puede seguir trabajando, se puede agregar más controles. No explaye mucho en el tema puesto que se comprende bien el código en su lógica. Como siempre digo cualquier critica es bien recibida.

jueves, 22 de junio de 2023

Procedimiento para retornar una fecha con un formato específico

En este ejemplo, vamos a crear un Procedimiento donde ingresaremos dos parámetros de entrada y retronaremos un formato de fecha personalizado. El nombre del objeto en cuestión es a elección, por eso a manera de ejemplo lo llamare "FechaDDMMAAAA". 

Los parámetros a utilizar son tres, pero si se prefiere se podría enviar uno solo. 

Rules:

parm(in:&Fecha, in:&Separador, out:&FechaTxt);  

&Fecha es de tipo Date y la propiedad Picture: "99/99/9999"
&Separador de tipo Character(1) *
&FechaTxt es tipo Character(10)

* La variable "&Separador" puede ser: "dd/mm/aaaa", "dd-mm-aaaa", etc. 

Source:

&FechaTxt=PadL(Trim(Str(&Fecha.Day(),2,0)),2,'0')+&Separador+          PadL(Trim(Str(&Fecha.Month(),2,0)),2,'0')+&Separador+          PadL(Trim(Str(&Fecha.Year(),4,0)),4,'0')

De esta forma vamos a obtener el día, mes y año con los método Day(), Month() y Year() lo concatenamos con el Separador que enviamos por parámetros. 

Las funciones utilizadas:

PadL: Permite construir una expresión de carácter a partir de otra, añadiendo N veces, un carácter específico o espacios en blanco a su lado izquierdo.
Str: Convierte una expresión numérica en una cadena.

Como digo siempre se puede mejorar, por ejemplo retornar el Año de dos dígitos, en ese caso deberíamos utilizar la función SubStr() o el método .SubString(). Se podría retonar la Hora y los Minutos con el formato "HHMM", concatenados a la variable &FechaTxt, solo restaría modificar la propiedad "Length" de la misma. Cualquier crítica es bienvenida siempre que sea constructiva.

martes, 13 de junio de 2023

Diferencia o resta entre dos fechas

este ejemplo veremos como restar dos fechas que ingresan por parámetro, para obtener la cantidad de días como resultado.

Pasemos a lo parámetros...

Rules:

parm(in:&DFechaFin, in:&DFechaInicio, out:&NTotalDias, out:&NAnios, out:&NMes, out:&NDias); 

Variables:

&DFechaAuxiliar de tipo Date
&DFechaProximoMes de tipo Date
&DFechaFin de tipo Date
&DFechaInicio de tipo Date
&NTotalDias de tipo Numeric (10)
&NAnios de tipo Numeric (4) En 
&NMes de tipo Numeric (2)
&NDias de tipo Numeric (2)

Source:

&NTotalDias = &DFechaFin - &DFechaInicio
&NAnios = 0
&NMeses = 0
&NDias = 0

if &NTotalDias > 29 
    &DFechaAuxiliar = &DFechaInicio
    &DFechaProximoMes = &DFechaInicio // Años
    do while &DFechaProximoMes <= &DFechaFin
        &DFechaProximoMes = AddYr(&DFechaAuxiliar, 1)
        if &DFechaProximoMes <= &DFechaFin
            &NAnios += 1
            &DFechaAuxiliar = &DFechaProximoMes
        endif
    enddo

    &DFechaProximoMes =&DFechaAuxiliar // Meses
    do while &DFechaProximoMes <= &DFechaFin
      &DFechaProximoMes = AddMth(&DFechaAuxiliar, 1)
      if &DFechaProximoMes <= &DFechaFin
        &NMeses += 1
        &DFechaAuxiliar = &DFechaProximoMes
      endif
    enddo
    &NDias = &DFechaFin- &DFechaAuxiliar
    if &NDias < 0
        &NDias = 0
    endif
else
        &NDias = &NTotalDias
endif

Como se puede apreciar es un sencillo procedimiento que se puede utilizar en donde se lo requiera dentro de nuestra KB. El nombre del mismo es a criterio de cada uno.

Como digo siempre se puede mejorar y cualquier crítica es bienvenida, siempre que sea constructiva.

Ingresar un número de mes y retornar su nombre

En este ejemplo, vamos a crear un procedimiento en el que ingresando un número de mes (1,2,3,4,etc.); nos retorne el nombre en letras. 

Para ello vamos a necesitar 3 parámetros en la reglas del mismo:

Rules:

parm(in:&NumeroMes, in:&Case, out:&NombreMes );

Variable &NúmeroMes es de tipo Numeric (2)

Variable &Case ('CAMEL', 'MAY', 'MIN') es de tipo Character (5) de acuerdo a lo que enviemos en segundo parámetro no retornará el nombre del mes en Mayúscula, Minúscula o si deseamos dejarlo como está, con la primera en mayúscula. 

Variable &NombreMes es de tipo Character (10)

Source: 

do case
    case &NumeroMes = 1
        &NombreMes = 'Enero'
    case &NumeroMes = 2
        &NombreMes = 'Febrero'
    case &NumeroMes = 3
        &NombreMes = 'Marzo'
    case &NumeroMes = 4
        &NombreMes = 'Abril'
    case &NumeroMes = 5
        &NombreMes = 'Mayo'
    case &NumeroMes = 6
        &NombreMes = 'Junio'
    case &NumeroMes = 7
        &NombreMes = 'Julio'
    case &NumeroMes = 8
        &NombreMes = 'Agosto'
    case &NumeroMes = 9
        &NombreMes = 'Septiembre'
    case &NumeroMes = 10
        &NombreMes = 'Octubre'
    case &NumeroMes = 11
        &NombreMes = 'Noviembre'
    case &NumeroMes = 12
        &NombreMes = 'Diciembre'
endcase
Do case
    case &Case = 'CAMEL'
        //Dejarlo como está, con la primera en mayúscula
    case &Case = 'MAY'
        &NombreMes = &NombreMes.ToUpper()
    case &Case = 'MIN'
        &NombreMes = &NombreMes.ToLower()
EndCase

Como se puede apreciar es un sencillo procedimiento que se puede utilizar en donde se lo requiera dentro de nuestra KB. El nombre del mismo es a criterio de cada uno.

Como digo siempre se puede mejorar y cualquier crítica es bienvenida, siempre que sea constructiva.



lunes, 12 de junio de 2023

Procedimiento que valida CUIL/CUIT

En este ejemplo mostrare un procedimiento que utilizo hace tiempo para validad una CUIT/CUIL;
el mismo controla que la clave ingresada sea válida. Y retorna un valor numérico que de acuerdo al mismo podemos exteriorizar mensajes al usuario desde un Web Panel si hay o no un error en la carga.

Lo valores que retorna:

0 - La clave es correcta
1 - La clave es incorrecta 
2 - El largo de la clave no corresponde.

Se reciben 2 parámetros:
Rules
parm(in:&Numero ,out:&Retorno);

&Numero:de tipo dato Character (11).
&Retorno: de tipo de dato Number (1).

Surce:
        &Acum: (Acumulador) de tipo de dato Number (5). 
        &Resto: de tipo de dato Number (2)
        &Operador: de tipo de datos Number (1), Dimensions "Vector", Rows "10"
        &Digito: de tipo de datos Number (1)
        &Contador: de tipo de datos Number (2)

A continuación el código completo del Procedimiento (no voy a ponerle nombre eso queda a criterio).

&Acum = 0
&Resto = 0
    if(&Numero.Length() = 11)
        &Operador(1)  = 5
        &Operador(2)  = 4
        &Operador(3)  = 3
        &Operador(4)  = 2
        &Operador(5)  = 7
        &Operador(6)  = 6
        &Operador(7)  = 5
        &Operador(8)  = 4
        &Operador(9)  = 3
        &Operador(10) = 2
        &Digito = val(&Numero.Substring(11, 1))
        
        &Contador = 1
        
        Do while &Contador < 11
            &Acum = &Acum + val(&Numero.Substring(&Contador, 1)) * &Operador(&Contador)
            &Contador = &Contador + 1
        Enddo
        
        &Resto = &Acum - (int(&Acum / 11) * 11)
        
        If (&Resto = 0)
            &Resto = 11
        Endif
        
        If ((11-&Resto) = &Digito)
            &Retorno = 0 // Ok
        else
            &Retorno = 1 // CUIL incorrecto
        Endif
    else 
            &Retorno = 2 // Largo CUIL incorrecto
    endif 

Espero sirva el ejemplo yo le vengo usando hace tiempo en varias aplicaciones. Como siempre digo se puede mejorar; se aceptan todo tipo de criticas siempre y cuando sean constructivas.

Qué es un Queue!? ... en Clarion

Publicado por  EMoreno  el 11/01/2006 - LWP Hola que tal. Una QUEUE es una estructura en memoria. Puede ser de un campo hasta "n...