Sie sind auf Seite 1von 247

INTRODUCCIÓN A LA

PROGRAMACIÓN
ADVPL I
1. Lógica de Programación y Algaritmos .....................................................................................7
1.1. Lógica de Programación....................................................................................... 7
1.2. Desarrollo de algoritmos ...................................................................................... 9
1.2.1. Estudio de algoritmos................................................................................... 10
1.2.2. Prueba de mesa............................................................................................. 12
2. Estructuras de Programación ................................................................................................. 14
2.1. Diagrama de bloque............................................................................................ 14
2.2. Estructuras de decisión y repetición.................................................................. 18
2.2.1. Estructuras de decisión................................................................................. 18
2.2.2. Estructuras de repetición .............................................................................. 21
3. ESTRUCTURA DE UN PROGRAMA ADVPL ............................................................................ 28
3.1. Áreas de un Programa ADVPL ......................................................................... 30
4. DECLARACIÓN Y ATRIBUCIÓN DE VARIABLES..................................................................... 34
4.1. Tipo de Datos....................................................................................................... 34
4.2. Declaración de variables..................................................................................... 35
4.3. Alcance de variables ........................................................................................... 36
4.4. Cómo influye el alcance de las variables ........................................................... 41
4.5. Operaciones con Variables................................................................................. 42
4.5.1. Atribución de variables ................................................................................ 42
4.5.2. Operadores del lenguaje ADVPL................................................................. 44
4.5.3. Operación de Macrosustitución.................................................................... 50
4.5.4. Funciones de manipulación de variables...................................................... 51
5. ESTRUCTURAS BÁSICAS DE PROGRAMACIÓN..................................................................... 59
5.1. Estructuras de repetición ................................................................................... 59
5.1.1. Cómo influir en el flujo de repetición .......................................................... 63
5.2. Estructuras de decisión....................................................................................... 65
6. ARRAYS Y BLOQUES DE CÓDIGO ........................................................................................... 70
6.1. Arrays .................................................................................................................. 70
6.1.1. Iniciando arrays ............................................................................................ 73
6.1.2. Funciones de manipulación de arrays .......................................................... 74
6.1.3. Copia de arrays............................................................................................. 76
6.2. Listas de Expresiones y Bloques de Código ...................................................... 78
6.2.1. Premisas para utilización de Bloques de Código ......................................... 78
6.2.2. Lista de expresiones ..................................................................................... 80
6.2.3. Bloques de Código ....................................................................................... 82
6.2.4. Funciones para manipulación de bloques de código .................................... 85
7. FUNCIONES .............................................................................................................................. 86
7.1. Tipos y alcances de funciones............................................................................. 87
7.2. Paso de parámetros entre funciones.................................................................. 91
8. DIRECTIVAS DE COMPILACIÓN.............................................................................................. 98
9. ADVPL Y ERP MICROSIGA PROTHEUS................................................................................. 106

Página 2 Introducción a la Programación ADVPL I


9.1. El Entorno Protheus ......................................................................................... 106
9.2. Organización y configuración inicial del entorno Protheus .......................... 112
9.3. El Configurador del Protheus.......................................................................... 119
9.3.1. Funcionalidades Abordadas ....................................................................... 119
9.3.2. Estructuras básicas de la aplicación ERP Protheus .................................... 119
9.3.3. Cómo acceder al módulo Configurador ..................................................... 123
9.4. Funcionalidades del Configurador .................................................................. 126
9.4.1. Diccionario de Datos de la aplicación ERP................................................ 127
9.4.2. Adición de tablas al Diccionario de Datos ................................................. 128
9.4.3. Adición de campos a las tablas del Diccionario de Datos.......................... 130
9.4.4. Adición de índices para las tablas del Diccionario de Datos...................... 136
9.4.5. Adición de disparadores para los campos de las tablas del Sistema .......... 140
9.4.6. Creación de Tablas Genéricas .................................................................... 143
9.4.7. Creación de Parámetros.............................................................................. 144
10. TOTVS DEVELOPMENT STUDIO ........................................................................................... 146
11. ACCESO Y MANIPULACIÓN DE BASES DE DATOS EN ADVPL........................................... 150
11.1. Diferencias y compatibilizaciones entre bases de datos................................. 151
11.2. Funciones de acceso y manipulación de datos ................................................ 153
11.3. Diferencia entre variables y nombres de campos........................................... 159
11.4. Control de numeración secuencial................................................................... 160
12. PERSONALIZACIONES PARA LA APLICACIÓN ERP ............................................................ 163
12.1. Personalizaciones de campos – Diccionario de Datos .................................... 163
12.1.1. Validaciones de campos y preguntas.......................................................... 163
12.1.2. Pictures de formato disponibles ................................................................. 166
12.2. Personalización de disparadores – Configurador .......................................... 168
12.3. Personalización de parámetros – Configurador ............................................ 169
12.3.1. Funciones para manipulación de parámetros ............................................. 170
12.3.2. Cuidados en la utilización de un parámetro ............................................... 171
12.4. Puntos de Entrada – Conceptos, Premisas y Reglas ...................................... 172
13. INTERFACES VISUALES.......................................................................................................... 174
13.1. Sintaxis y componentes de las interfaces visuales .......................................... 174
13.2. Interfaces estándar para actualizaciones de datos......................................... 177
13.2.1. AxCadastro() .............................................................................................. 177
13.2.2. MBrowse() ................................................................................................. 179
13.2.3. AxFunctions() ............................................................................................ 183
14. UTILIZACIÓN DE SANGRÍA ................................................................................................... 186
15. LETRA CAPITAL EN PALABRAS CLAVE ................................................................................ 188
15.1. Palabras en mayúscula ..................................................................................... 188
16. UTILIZACIÓN DE LA NOTACIÓN HÚNGARA....................................................................... 189
17. PALABRAS RESERVADAS ...................................................................................................... 190
Conversión entre tipo de datos ..................................................................................... 191
CTOD() ............................................................................................................... 191
CVALTOCHAR()............................................................................................... 191

Introducción a la Programación ADVPL I Página 3


DTOC() ............................................................................................................... 192
DTOS() ............................................................................................................... 192
STOD() ............................................................................................................... 193
STR() .................................................................................................................. 193
STRZERO() ........................................................................................................ 193
VAL().................................................................................................................. 194
Verificación de tipo de variables................................................................................... 195
TYPE()................................................................................................................ 195
VALTYPE()........................................................................................................ 195
Manipulación de arrays................................................................................................. 196
Array() ................................................................................................................ 196
AADD() .............................................................................................................. 197
ACLONE().......................................................................................................... 198
ADEL() ............................................................................................................... 199
ASIZE() .............................................................................................................. 200
ASORT()............................................................................................................. 200
ASCAN() ............................................................................................................ 202
AINS() ................................................................................................................ 203
Manipulación de bloques de código.............................................................................. 204
EVAL() ............................................................................................................... 204
DBEVAL().......................................................................................................... 205
AEVAL() ............................................................................................................ 206
Manipulación de strings ................................................................................................ 207
ALLTRIM() ........................................................................................................ 207
ASC() .................................................................................................................. 207
AT() .................................................................................................................... 209
CHR().................................................................................................................. 209
LEN() .................................................................................................................. 210
LOWER()............................................................................................................ 210
STUFF().............................................................................................................. 211
SUBSTR()........................................................................................................... 211
UPPER() ............................................................................................................. 212
Manipulación de variables numéricas.......................................................................... 212
ABS() .................................................................................................................. 212
INT() ................................................................................................................... 213
NOROUND()...................................................................................................... 213
ROUND()............................................................................................................ 214
Manipulación de archivos ............................................................................................. 215
SELECT() ........................................................................................................... 215
DBGOTO() ......................................................................................................... 215
DBGOTOP() ....................................................................................................... 216
DBGOBOTTON() .............................................................................................. 216
DBSELECTAREA()........................................................................................... 217
DBSETORDER()................................................................................................ 218
DBSEEK() y MSSEEK() .................................................................................... 219
DBSKIP()............................................................................................................ 220
DBSETFILTER()................................................................................................ 221
DBSTRUCT() ..................................................................................................... 222
RECLOCK() ....................................................................................................... 223
MSUNLOCK() ................................................................................................... 224
SOFTLOCK() ..................................................................................................... 225
DBDELETE() ..................................................................................................... 226

Página 4 Introducción a la Programación ADVPL I


DBUSEAREA().................................................................................................. 226
DBCLOSEAREA()............................................................................................. 227
Control de numeración secuencial................................................................................ 228
GETSXENUM() ................................................................................................. 228
CONFIRMSXE() ................................................................................................ 228
ROLLBACKSXE()............................................................................................. 229
Validación ....................................................................................................................... 229
EXISTCHAV() ................................................................................................... 229
EXISTCPO()....................................................................................................... 229
NAOVAZIO()..................................................................................................... 230
NEGATIVO() ..................................................................................................... 230
PERTENCE()...................................................................................................... 230
POSITIVO()........................................................................................................ 231
TEXTO()............................................................................................................. 231
VAZIO() ............................................................................................................. 231
Parámetros...................................................................................................................... 232
GETMV()............................................................................................................ 232
GETNEWPAR() ................................................................................................. 232
PUTMV()............................................................................................................ 233
SUPERGETMV() ............................................................................................... 233
Componentes de la interfaz visual ................................................................................ 234
MSDIALOG()..................................................................................................... 234
MSGET() ............................................................................................................ 235
SAY().................................................................................................................. 236
BUTTON().......................................................................................................... 236
SBUTTON() ....................................................................................................... 237
Interfaces de archivo...................................................................................................... 238
AXCADASTRO()............................................................................................... 238
MBROWSE()...................................................................................................... 238
AXPESQUI() ...................................................................................................... 238
AXVISUAL() ..................................................................................................... 239
AXINCLUI()....................................................................................................... 239
AXALTERA() .................................................................................................... 241
AXDELETA()..................................................................................................... 241
Funciones visuales para aplicaciones ........................................................................... 242
ALERT() ............................................................................................................. 242
AVISO().............................................................................................................. 242
FORMBACTH() ................................................................................................. 243
MSGFUNCTIONS()........................................................................................... 244
Funciones ADVPL para aplicaciones ........................................................................... 245
GETAREA() ....................................................................................................... 245
RESTAREA() ..................................................................................................... 245

Introducción a la Programación ADVPL I Página 5


OBJETIVOS DEL CURSO
Objetivos específicos del curso:

Al final del curso el participante debe haber desarrollado los siguientes conceptos,
habilidades y actitudes:

a) Conceptos que se aprenderán

ƒ Fundamentos y técnicas de programación


ƒ Principios básicos del lenguaje ADVPL
ƒ Comandos y funciones específicas de Microsiga

b) Habilidades y técnicas que se aprenderán

ƒ Resolución de algoritmos mediante sintaxis orientadas al lenguaje


ADVPL
ƒ Análisis de fuentes de baja dificultad de aplicación ERP Protheus
ƒ Desarrollo de pequeñas personalizaciones para el ERP Protheus

c) Actitudes que se desarrollarán

ƒ Adquirir conocimientos por medio del análisis de las funcionalidades


disponibles en el ERP Protheus
ƒ Fundamentar la realización de otros cursos relativos al lenguaje
ADVPL

Página 6 Introducción a la Programación ADVPL I


Módulo 01: Introducción a la
Programación

1. LÓGICA DE PROGRAMACIÓN Y ALGARITMOS

En el aprendizaje de cualquier lenguaje de programación es esencial desarrollar los


conceptos relacionados con la lógica y la técnica de escritura de un programa.

Con enfoque en esta necesidad, este tópico describirá resumidamente los conceptos
involucrados en el proceso de desarrollo de un programa, por medio de los
conceptos relacionados con:

; Lógica de programación
; Algoritmos
; Diagramas de bloques

1.1. Lógica de Programación

Lógica

La lógica de programación es necesaria para personas que desean trabajar con


el desarrollo de sistemas y programas. Ésta, permite definir la secuencia lógica
para el desarrollo de un programa. Entonces, ¿qué es lógica?

Lógica de programación es la técnica de concatenar pensamientos para


alcanzar determinado objetivo.

Secuencia Lógica

Estos pensamientos pueden describirse como una secuencia de instrucciones,


que deben seguirse para cumplir con una determinada tarea.

Una secuencia lógica se conforma de los pasos ejecutados hasta alcanzar


un objetivo o solución de un problema.

Introducción a la Programación ADVPL I Página 7


Instrucciones

En el lenguaje común, se entiende por instrucciones “un conjunto de reglas o


normas definidas para la realización o utilización de algo”.

Sin embargo, en informática instrucción es la información que indica a una


computadora una acción elemental por ejecutar. Conviene resaltar que un
orden aislado no permite realizar el proceso completo, para ello es necesario
un conjunto de instrucciones colocadas en orden secuencial lógica.

Por ejemplo, si queremos hacer una tortilla de papas, necesitaremos colocar


en práctica una serie de instrucciones: pelar las papas, batir los huevos, freír las
papas, etc. Es evidente que estas instrucciones tienen que ejecutarse en un
orden adecuado, no puede pelarse las papas después de freírlas.

De esta manera, una instrucción tomada por separado no tiene mucho


sentido, para obtener el resultado, necesitamos poner en práctica el conjunto
de todas las instrucciones, en el orden correcto.

Las instrucciones son un conjunto de reglas o normas definidas para la


realización o utilización de algo. En informática, es lo que indica a una
computadora una acción elemental por ejecutar.

Algoritmo

Un algoritmo es formalmente una secuencia finita de pasos que llevan a la


ejecución de una tarea. Podemos pensar en algoritmo como un ingreso, una
secuencia de instrucciones para alcanzar una meta específica. Estas tareas no
pueden ser redundantes ni subjetivas en su definición, deben ser claras y
exactas.

Como ejemplos de algoritmos podemos mencionar los algoritmos de las


operaciones básicas (adición, multiplicación, división y sustracción) de
números reales decimales. Otros ejemplos serían los manuales de aparatos
electrónicos, como un videocasete, que explican paso a paso como, por
ejemplo, grabar un evento.

Incluso las cosas más sencillas pueden describirse en secuencias lógicas, tales
como:

; “Chupar un caramelo”.
1. Agarrar un caramelo.
2. Retirar el papel.
3. Chupar el caramelo.

Página 8 Introducción a la Programación ADVPL I


4. Botar el papel en la basura.

; “Sumar dos números cualquiera”


1. Escriba el primer número en el rectángulo A.
2. Escriba el segundo número en el rectángulo B.
3. Sume el número del rectángulo A con el número del rectángulo B y
coloque el resultado en el rectángulo C.

1.2. Desarrollo de algoritmos

Pseudocódigo

Los algoritmos se describen en un lenguaje denominado pseudocódigo. Este


nombre es una alusión a la posterior implementación en un lenguaje de
programación, es decir, cuando se utilice el lenguaje de programación
propiamente dicha como, por ejemplo, ADVPL.

Por ello, los algoritmos son independientes de los lenguajes de programación


y al contrario de un lenguaje de programación, no existe una formalidad rígida
de cómo debe escribirse el algoritmo.

El algoritmo debe ser fácil de interpretar y fácil de codificar. Es decir, debe ser
el intermediario entre el lenguaje hablado y el lenguaje de programación.

Reglas para la construcción del Algoritmo

Para escribir un algoritmo necesitamos describir la secuencia de instrucciones,


de manera sencilla y objetiva. Para ello, utilizaremos algunas técnicas:

1. Usar solamente un verbo por frase.


2. Imaginar que está desarrollando un algoritmo para personas que no
trabajan con informática.
3. Usar frases cortas y sencillas.
4. Ser objetivo.
5. Usar palabras que no tengan sentido ambiguo.

Fases

Para implementar de un algoritmo de sencilla interpretación y codificación,


inicialmente es necesario dividir el problema presentado en tres fases
fundamentales:

Introducción a la Programación ADVPL I Página 9


; ENTRADA: Son los datos de entrada del algoritmo.
; PROCESAMIENTO: Son los procedimientos utilizados para alcanzar el
resultado final.
; SALIDA: Son los datos procesados.

1.2.1. Estudio de algoritmos

En este tópico se mostrarán algunos algoritmos del día a día, los cuales se
implementaron utilizando los principios descritos en los tópicos anteriores.

 Masticar un chicle.
 Utilizar un teléfono público – tarjeta.
 Freír un huevo.
 Cambiar focos.
 Pelar papas.
 Jugar al ahorcado.
 Calcular el promedio de las notas.
 Jugar el tres en raya – contra el algoritmo.

Masticar un chicle

1. Agarrar el chicle.
2. Retirar el papel.
3. Masticar.
4. Botar el papel en la basura.

Utilizar un teléfono público - tarjeta

1. Descolgar el teléfono.
2. Esperar el tono de línea.
3. Poner la tarjeta.
4. Marcar el número.
5. Hablar por teléfono.
6. Colgar el teléfono

Freír un huevo

1. Agarrar la sartén, el huevo, el aceite y la sal.


2. Poner aceite en la sartén.
3. Encender la cocina.
4. Poner la sartén en la candela.
5. Esperar que se caliente el aceite.

Página 10 Introducción a la Programación ADVPL I


6. Partir el huevo en la sartén.
7. Botar la cáscara a la basura.
8. Retirar la sartén de la cocina cuando el huevo esté en el punto.
9. Apagar la cocina.
10. Colocar sal al gusto.

Cambiar focos

1. Si el foco estuviera fuera de alcance, agarrar una escalera.


2. Agarrar el foco nuevo.
3. Si el foco quemado estuviera caliente, agarrar un paño.
4. Retirar foco quemado.
5. Poner foco nuevo.

Pelar papas

1. Agarrar un cuchillo, una vasija y papas.


2. Colocar agua en la vasija.
3. Mientras haya papas, pelas las papas.
3.1. Colocar las papas peladas en la vasija.

Jugar al ahorcado

1. Elegir la palabra.
2. Construir el diagrama del juego.
3. Mientras haya espacios vacíos y el cuerpo esté incompleto:
3.1. Si acierta la letra: escriba en el espacio correspondiente.
3.2. Si se equivoca de letra: dibujar una parte del cuerpo en la horca.

Calcular el promedio de las notas

1. Mientras haya notas por recibirse:


1.1. Recibir la nota.
2. Sumar todas las notas recibidas.
3. Dividir el total obtenido entre la cantidad de notas recibidas.
4. Mostrar el promedio de las notas.

Jugar el tres en raya – contra el algoritmo

1. Mientras haya un cuadrado libre y nadie haya ganado o perdido el juego:


1.1. Espere que el adversario haga su jugada y continúe después.
1.2. Si el centro estuviera libre: juegue en el centro.
1.3. Si no, si el adversario tiene 2 cuadrados en línea con un cuadrado libre,

Introducción a la Programación ADVPL I Página 11


juegue en ese cuadrado.
1.4. Si no, si hay algún espacio libre, juegue en ese espacio.

1.2.2. Prueba de mesa

Después de desarrollar un algoritmo, siempre debe ser puesto a prueba. Esta


prueba se denomina PRUEBA DE MESA, que significa seguir las instrucciones
del algoritmo de manera exacta para verificar si el procedimiento utilizado está
correcto.

Para evaluar la realización de la prueba de mesa, utilizaremos el algoritmo de


calcular el promedio de las notas:

Algoritmo: Calcular el promedio de las notas

1. Mientras haya notas por recibirse:


a. Recibir la nota.

2. Sumar todas las notas recibidas.


3. Dividir el total obtenido entre la cantidad de notas recibidas.
4. Mostrar el promedio de las notas.

Prueba de mesa:

1. Por cada nota informada, recibir y registrar en la siguiente tabla:

ID Nota

2. Al finalizar las notas, la tabla debe tener todas las notas informadas, como
se muestra a continuación:

ID Nota
1 8.0
2 7.0
3 8.0
4 8.0
5 7.0
6 7.0

3. Sumar todas las notas: 45


4. Dividir la suma de las notas entre el total de notas informado: 45/6 Æ 7.5
5. Mostrar el promedio obtenido: Mensaje (Promedio: 7.5)

Página 12 Introducción a la Programación ADVPL I


Mejorar los siguientes algoritmos descritos en la separata:

; Usar teléfono público – tarjeta.


; Freír un huevo.
; Masticar un chicle.
; Cambiar focos.
; Pelar papas.
; Jugar al ahorcado.

Introducción a la Programación ADVPL I Página 13


2. ESTRUCTURAS DE PROGRAMACIÓN

2.1. Diagrama de bloque

El diagrama de bloques es una forma estándar y eficaz para representar los


pasos lógicos de un determinado procesamiento.

Con el diagrama podemos definir una secuencia de símbolos, con significado


bien definido, por lo tanto, su principal función es facilitar la visualización de
los pasos de un procesamiento.

Simbología

Existen diversos símbolos en un diagrama de bloque. En el siguiente cuadro


están representados algunos de los símbolos más utilizados:

Símbolo Función

Indica el inicio y el final de un


procesamiento.
Finalizador

Procesamiento en general.

Procesamiento

Indica la entrada de datos por medio del


teclado.
Entrada
Manual

Indica un punto en el cual debe realizarse


una elección entre dos situaciones
posibles.
Decisión

Muestra los resultados obtenidos con un


procesamiento.
Exhibición
Indica un documento utilizado por el
procesamiento, ya sea para entrada de
información o para exhibición de los
Documento datos disponibles después de un

Página 14 Introducción a la Programación ADVPL I


procesamiento.

• Cada símbolo tendrá una descripción correspondiente a la forma con


la cual se utilizó en el flujo, indicando el procesamiento o la
información que éste representa.

Representación de algoritmos por medio de diagramas de bloque

Algoritmo 01: Freír un huevo

1. Agarrar la sartén, el huevo, el aceite y la sal.


2. Poner aceite en la sartén.
3. Encender la cocina.
4. Poner la sartén en la candela.
5. Esperar que se caliente el aceite.
6. Partir el huevo en la sartén.
7. Botar la cáscara a la basura.
8. Retirar la sartén de la cocina cuando el huevo esté en el punto.
9. Apagar la cocina.
10. Colocar sal al gusto.

Introducción a la Programación ADVPL I Página 15


Página 16 Introducción a la Programación ADVPL I
Algoritmo 02: Calcular el promedio de las notas

1. Mientras haya notas por recibir


a. Recibir la nota.

2. Sumar todas las notas recibidas.


3. Dividir el total obtenido entre la cantidad de notas recibidas.
4. Mostrar el promedio de las notas.

Introducción a la Programación ADVPL I Página 17


2.2. Estructuras de decisión y repetición

La utilización de estructuras de decisión y repetición en un algoritmo permite


la realización de acciones relacionadas con situaciones que influyen en la
ejecución y solución del problema.

Como enfoque en la utilización del lenguaje ADVPL, se ilustrarán las siguientes


estructuras:

; Estructuras de decisión
o IF...ELSE
o DO CASE ... CASE

; Estructuras de repetición
o WHILE...END
o FOR...NEXT

2.2.1. Estructuras de decisión

Los comandos de decisión se utilizan en algoritmos cuya solución no se


obtiene por medio de la utilización de acciones meramente secuenciales,
permitiendo que estos comandos de decisión evalúen las condiciones
necesarias para optar por una u otra manera de continuar su flujo.

Las estructuras de decisión que se analizarán son:

; IF...ELSE
; DO CASE ... CASE

IF...ELSE

La estructura IF...ELSE (Si/Sí no) permite el análisis de una condición, a partir de


la cual se ejecutará una de las dos acciones posibles: Si el análisis de la
condición resulta en un valor verdadero o si el análisis de la condición resulta
en un valor falso.

Página 18 Introducción a la Programación ADVPL I


Representación 01: IF...ELSE con acciones para ambas situaciones

Esta estructura también permite que se ejecute únicamente una acción, en la


situación en que el análisis de la condición resulta en un valor verdadero.

Representación 02: IF...ELSE solamente con una acción para situación verdadera

Introducción a la Programación ADVPL I Página 19


A pesar de que los lenguajes de programación tienen variaciones para
la estructura IF...ELSE, conceptualmente todas las representaciones
pueden describirse con base en el modelo presentado.

El lenguaje ADVPL tiene una variación para la estructura IF...ELSE,


descrita como IF...ELSEIF...ELSE.

Con esta estructura es posible realizar el análisis de diversas


condiciones en secuencia, para las cuales solamente se evaluará la
acción de la primera expresión cuyo análisis resulte en un valor
verdadero.

DO CASE...CASE

La estructura DO CASE...ENDCASE (Caso) permite el análisis de diversas


condiciones consecutivas, para las cuales solamente la condición para la
primera condición verdadera será su acción vinculada y ejecutada.

El recurso de análisis de múltiples condiciones es necesario para la solución de


los problemas más complejos, en los cuales las posibilidades de solución
superan el simple análisis de un único resultado verdadero o falso.

Página 20 Introducción a la Programación ADVPL I


A pesar de que los lenguajes de programación tienen variaciones para
la estructura DO...CASE, conceptualmente todas las representaciones
pueden describirse con base en el modelo presentado.

2.2.2. Estructuras de repetición

Los comandos de repetición se utilizan en algoritmos en las situaciones en que


es necesario realizar una determinada acción o un conjunto de acciones para
un número definido o indefinido de veces, o también mientras una
determinada condición sea verdadera.

Las estructuras de decisión que se analizarán son:

; WHILE...END
; FOR...TO...NEXT

Introducción a la Programación ADVPL I Página 21


WHILE...END

En esta estructura, el conjunto de acciones se ejecutará mientras el análisis de


una condición de referencia resulte en un valor verdadero. Es importante
observar que el bloque solamente se ejecutará si en el primer análisis la
condición resulta en un valor verdadero.

Representación: WHILE...END

Existen diversas variaciones para la estructura WHILE...END, en la cual


hay la posibilidad de que la primera ejecución se realice sin el análisis de
la condición, la cual valdrá únicamente a partir de la segunda ejecución.

El lenguaje ADVPL acepta la sintaxis DO WHILE...ENDDO, que en otros


lenguajes representa la situación descrita anteriormente (análisis de la
condición solamente a partir de la segunda ejecución), pero en ADVPL
ésta sintaxis tiene el mismo efecto del WHILE...END.

Página 22 Introducción a la Programación ADVPL I


FOR...TO...NEXT

En esta estructura, el conjunto de acciones se ejecutará una determinada


cantidad de veces, normalmente denominada como “paso”.

Para cada “paso” realizado por la estructura FOR...TO...NEXT, se evaluará una


condición que verificará si se alcanzó el número de ejecuciones previamente
definido. De esta manera, la estructura abarca un control de número de
“pasos” ejecutados, el cual se incrementa en el análisis de la expresión NEXT.

Semejante a la estructura WHILE...END, la primera acción solamente se


realizará mediante un resultado verdadero en el análisis de la condición.

Representación: FOR...TO...NEXT

Introducción a la Programación ADVPL I Página 23


La estructura FOR...TO...NEXT, dependiendo del lenguaje de
programación, permite la realización de un incremento sencillo en
cada ejecución de la instrucción NEXT, o la adición de otro valor al
contador, el cual debe especificarse de acuerdo con la sintaxis del
lenguaje.

En ADVPL puede utilizarse la instrucción “STEPS” para modificar el


valor que se agregará al contador de pasos a cada ejecución de la
instrucción NEXT, cuyo valor podrá ser incluso negativo, haciendo
posible un recuento decreciente .

Construir los diagramas de bloques para los algoritmos desarrollados en el ejercicio


anterior:

; Usar teléfono público – tarjeta.


; Freír un huevo.
; Masticar un chicle.
; Cambiar focos.
; Pelar papas.
; Jugar al ahorcado.

Página 24 Introducción a la Programación ADVPL I


Módulo 02: El Lenguaje ADVPL
El lenguaje ADVPL tuvo su inicio en 1994, el cual en realidad es una evolución en la
utilización de lenguajes en el estándar XBase por Microsiga Software S.A. (Clipper,
Visual Objects y posteriormente, FiveWin). Con la creación de la tecnología Protheus,
era necesario crear un lenguaje que reconociera el estándar XBase para el
mantenimiento de todo el código existente del sistema de ERP SIGA Advanced.
Entonces, se creó el lenguaje Advanced Protheus Language.

El ADVPL es una extensión del estándar XBase de comandos y funciones,


operadores, estructuras de control de flujo y palabras reservadas que cuenta
también con funciones y comandos puestos a disposición por MICROSIGA, que lo
convierten en un lenguaje completo para la creación de aplicaciones ERP listas para
la Internet. También es un lenguaje orientado a objetos y eventos, lo cual permite al
programador desarrollar aplicaciones visuales y crear sus propias clases de objetos.

Cuando se compilan todos los archivos de código, se convierten en unidades de


inteligencia básicas denominada APO (Advanced Protheus Objects). El PROTHEUS
mantiene dichos APO en un repositorio y se activan dinámicamente para su
ejecución. Como no existe la linkedición, o unión física del código compilado con un
determinado módulo o aplicación, las funciones creadas en ADVPL pueden
ejecutarse en cualquier punto del entorno Advanced Protheus.

El servidor PROTHEUS (PROTHEUS Server) es el compilador y el intérprete del


lenguaje ADVPL. Hay un entorno visual de desarrollo integrado (PROTHEUSIDE)
donde se puede crear, compilar y depurar el código.

Los programas en ADVPL pueden tener comandos o funciones de interfaz con el


usuario. De acuerdo con esta característica, dichos programas se subdividen en las
siguientes categorías:

Programación con interfaz propia con el usuario

En esta categoría están los programas desarrollados para ejecutarse por medio del
terminal remoto de Protheus: Protheus Remote. Protheus Remote es la aplicación
encargada de la interfaz y de la interacción con el usuario y todo el procesamiento
del código en ADVPL, el acceso a la base de datos y la administración de conexiones
se efectúa en el Protheus Server. El Protheus Remote es el principal medio de acceso
a la ejecución de rutinas escritas en ADVPL en el Protheus Server. En virtud de ello,
permite ejecutar cualquier tipo de código, tenga o no tenga interfaz con el usuario.
Sin embargo, en esta categoría sólo se consideran los programas que realizan algún
tipo de interfaz remota utilizando el protocolo de comunicación del Protheus.

Se pueden crear rutinas para la personalización del sistema ERP Microsiga Protheus,
desde procesos adicionales hasta informes. La gran ventaja es aprovechar el entorno
elaborado por los módulos del ERP Microsiga Protheus. Pero, con el ADVPL, es

Introducción a la Programación ADVPL I Página 25


posible crear incluso toda una aplicación o módulo desde el inicio.

Todo el código del sistema ERP Microsiga Protheus está escrito en ADVPL.

Programación sin interfaz propia con el usuario

Las rutinas creadas sin interfaz se consideran en esta categoría porque generalmente
tienen una utilización más específica que un proceso adicional o un informe nuevo.
Dichas rutinas no tienen interfaz con el usuario por medio de Advanced Protheus
Remote y cualquier intento en este sentido (como la creación de una ventana
estándar) ocasionará una excepción en tiempo de ejecución. Estas rutinas son
solamente procesos, o jobs, ejecutados en Protheus Server. Algunas veces, la interfaz
de estas rutinas queda a cargo de aplicaciones externas, desarrolladas en otros
lenguajes, que son responsables por iniciar los procesos en el servidor Protheus, por
medio de los medios de integración y conectividad disponibles en Protheus.

De acuerdo con el uso y con el medio de conectividad utilizado, estas rutinas tienen
la siguiente división de categorías:

; Programación por Procesos

Rutinas escritas en ADVPL pueden iniciarse como procesos individuales (sin interfaz)
en el Protheus Server de dos maneras: por medio de otra rutina ADVPL, por medio
de la ejecución de funciones como StartJob() o CallProc() o automáticamente al
iniciar el Protheus Server (cuando esté correctamente configurado).

; Programación de RPC

En una biblioteca de funciones disponible en el Protheus (una API de comunicación),


pueden ejecutarse rutinas escritas en ADVPL directamente en el Protheus Server, por
medio de aplicaciones externas escritas en otros lenguajes. Es lo que se denomina
RPC (Remote Procedure Call o Llamada Remota de Procedimientos).

El servidor Protheus también puede ejecutar rutinas en ADVPL en otros servidores


Protheus por medio de conexión TCP/IP directa, utilizando el concepto RPC. Del
mismo modo, aplicaciones externas pueden solicitar la ejecución de rutinas escritas
en ADVPL por medio de la conexión TCP/IP directa.

Programación Web

Protheus Server también puede ejecutarse como un servidor Web, respondiendo a


solicitudes HTTP. Cuando se hacen dichas solicitudes, pueden ejecutarse rutinas
escritas en ADVPL como procesos individuales y enviar el resultado de las funciones
como respuesta a las solicitudes al cliente HTTP (como por ejemplo un Browser de
Internet). Cualquier rutina escrita en ADVPL que no contenga comandos de interfaz
puede ejecutarse por medio de solicitudes HTTP. El Protheus permite la compilación
de archivos HTML con el código ADVPL embutido. Son los archivos denominados

Página 26 Introducción a la Programación ADVPL I


ADVPL ASP, que hacen la creación de páginas dinámicas.

; Programación TelNet

TelNet forma parte de la variedad de protocolos TCP/IP que permite la conexión a


una computadora remota por medio de una aplicación cliente de este protocolo. El
PROTHEUS Server puede emular un terminal TelNet por medio de la ejecución de
rutinas escritas en ADVPL. Es decir, pueden escribirse rutinas ADVPL cuya interfaz
final será un terminal TelNet o un recolector de datos móvil.

Introducción a la Programación ADVPL I Página 27


3. ESTRUCTURA DE UN PROGRAMA ADVPL

Un programa de computadora no es más de lo que un grupo de comandos


lógicamente dispuestos, con el objetivo de ejecutar determinada tarea. Estos
comandos se graban en un archivo texto que se transforma en un lenguaje
ejecutable por una computadora, por medio de un proceso denominado
compilación. La compilación reemplaza los comandos de alto nivel (comprendidos
por los humanos) por instrucciones de bajo nivel (comprendidas por el sistema
operativo ejecutado por la computadora). En el caso del ADVPL, no es el sistema
operativo de una computadora el que ejecutará el código compilado, sino el
Protheus Server.

Dentro de un programa, los comandos y funciones utilizados deben cumplir las


reglas de sintaxis del lenguaje utilizado, pues de lo contrario el programa se
interrumpirá a causa de errores. Los errores pueden ser de compilación o de
ejecución.

Errores de compilación son aquellos encontrados en la sintaxis y que no permiten


que se compile el archivo de código del programa. Pueden ser comandos
especificados de forma equivocada, uso inválido de operadores, etc.

Errores de ejecución son aquellos que ocurren después de la compilación, cuando el


programa está en ejecución. Pueden ocurrir por varias razones, pero generalmente
se refieren a las funciones no existentes, a las variables no creadas o iniciadas, etc.

Líneas de Programa

Las líneas existentes en un archivo de texto de código de programa pueden


ser líneas de comando, líneas de comentario o líneas mixtas.

; Líneas de Comando

Las líneas de comando tienen los comandos o instrucciones que se ejecutarán.


Por ejemplo:

Local nCnt
Local nSoma := 0
For nCnt := 1 To 10
nSoma += nCnt
Next nCnt

; Líneas de Comentario

Las líneas de comentario tienen texto, pero no se ejecutan. Su función es la de


documentar y hacer más fácil el entendimiento del programa. Hay tres formas

Página 28 Introducción a la Programación ADVPL I


de comentar en las líneas de texto. La primera es utilizar el * (asterisco) al inicio
de la línea:

* Programa para cálculo del total


* Autor: Microsiga Software S.A.
* Fecha: 2 de octubre de 2001

Todas las líneas que comienzan con un asterisco se consideran como


comentarios. Se puede utilizar la palabra NOTE o dos símbolos de la letra "y"
comercial (&&) para realizar la función del asterisco. Sin embargo, todas estas
formas de comentario de líneas son obsoletas y existen solamente para que
sean compatibles con el estándar xBase. La mejor manera de comentar líneas
en ADVPL es utilizar dos barras transversales:

// Programa para cálculo del total


// Autor: Microsiga Software S.A.
// Fecha: 2 de octubre de 2001

Otra forma de documentar textos es utilizar las barras transversales junto con
el asterisco para comentar un bloque de texto, para que no sea necesario
comentar línea por línea:

/*
Programa para cálculo del total
Autor: Microsiga Software S.A.
Fecha: 2 de octubre de 2001
*/

Todo el texto que se encuentra entre la apertura (indicada por los caracteres
/*) y el cierre (indicado por los caracteres */) es el comentario.

; Líneas Mixtas

El ADVPL también permite la existencia de líneas de comando con


comentarios. Ello es posible cuando se agregan las dos barras transversales (//)
al final de la línea de comando y se agrega el texto del comentario:

Local nCnt
Local nSoma := 0 // Inicia la variable con cero para la suma.
For nCnt := 1 To 10
nSoma += nCnt
Next nCnt

; Tamaño de la Línea

Tal como la línea física, delimitada por la cantidad de caracteres que se


pueden digitar en el editor de textos, hay una línea considerada línea lógica. La

Introducción a la Programación ADVPL I Página 29


línea lógica es la que se tiene en cuenta para la compilación como una única
línea de comando.

Cada línea digitada en el archivo de texto se diferencia de la otra después que


se pulsa la tecla <Enter>. Es decir, la línea lógica es la línea física en el archivo.
Sin embargo, algunas veces, por limitación física del editor de texto o por
estética, se puede dividir la línea lógica en más de una línea física en el archivo
de texto. Esto se hace con el uso de punto y coma (;).

If !Empty(cNome) .And. !Empty(cEnd) .And. ; <enter>


!Empty(cTel) .And. !Empty(cFax) .And. ; <enter>
!Empty(cEmail)

GravaDados(cNome,cEnd,cTel,cFax,cEmail)

Endif

En este ejemplo, hay una línea de comando para la verificación de las variables
utilizadas. Como la línea es muy grande, es posible dividirla en más de una
línea física utilizándose de punto y coma. Si se olvida un punto y coma en las
dos primeras líneas, ocurrirá un error durante la ejecución del programa, pues
se entenderá que la segunda línea física es una segunda línea de comando en
la compilación. Durante la ejecución, esta línea no tendrá sentido.

3.1. Áreas de un Programa ADVPL

Aunque no es un lenguaje de estándares rígidos respecto a la estructura del


programa, es importante identificar algunas de sus partes. Considere el
siguiente programa:

#include protheus.ch

/*
+===========================================+
| Programa: Cálculo del Factorial |
| Autor : Microsiga Software S.A. |
| Fecha : 02 de octubre de 2001 |
+===========================================+
*/

User Function CalcFator()

Local nCnt
Local nResultado := 1 // Resultado del factorial

Página 30 Introducción a la Programación ADVPL I


Local nFator := 5 // Número para el cálculo

// Cálculo del factorial


For nCnt := nFator To 1 Step -1
nResultado *= nCnt
Next nCnt

// Muestra el resultado en la pantalla, por medio de la función alert


Alert("El factorial de " + cValToChar(nFator) + ;
" es " + cValToChar(nResultado))

// Termina el programa
Return

La estructura de un programa ADVPL está compuesta de las siguientes áreas:

; Área de Identificación
9 Declaración de los includes
9 Declaración de la función
9 Identificación del programa

; Área de Ajustes Iniciales


9 Declaración de las variables

; Cuerpo del Programa


9 Preparación para el procesamiento
9 Procesamiento

; Área de Finalización

Área de Identificación

Esta área no es obligatoria y está dedicada a la documentación del programa.


Cuando existe, contiene comentarios sobre su finalidad, fecha de creación,
autor, etc. y aparece al comienzo del programa, antes de cualquier línea de
comando.

No hay formato definido para este programa. Se puede colocar cualquier tipo
de información deseada y elegir la configuración apropiada.

#include “protheus.ch”

/*
+==========================================+
| Programa: Cálculo del Factorial |
| Autor : Microsiga Software S.A. |

Introducción a la Programación ADVPL I Página 31


| Fecha : 02 de octubre de 2001 |
+==========================================+
*/

User Function CalcFator()

Es opcional incluir definiciones de constantes utilizadas en el programa o


inclusión de archivos de encabezamiento en esta área.

Área de Ajustes Iniciales

En esta área se hacen, generalmente, los ajustes iniciales, importantes para el


correcto funcionamiento del programa. Entre los ajustes se encuentran
declaraciones de variables, iniciaciones, apertura de archivos, etc. Aunque el
ADVPL no es un lenguaje rígido y las variables se pueden escribir en cualquier
lugar del programa, es aconsejable hacerlo en esta área para que el código sea
más legible y sea más fácil la identificación de variables no utilizadas.

Local nCnt
Local nResultado := 0 // Resultado del factorial
Local nFator := 10 // Número para el cálculo

Cuerpo del Programa

En esta área se encuentran las líneas de código del programa. Es donde se


realiza la tarea necesaria por medio de la organización lógica de estas líneas
de comando. Se espera que las líneas de comando estén organizadas de tal
modo que al final de esta área se obtenga el resultado esperado, ya sea
almacenado en un archivo o en variables de memoria, preparado para
mostrarse al usuario por medio de un informe o de la pantalla.

// Cálculo del factorial


For nCnt := nFator To 1 Step -1
nResultado *= nCnt
Next nCnt

La preparación para el procesamiento está formada del conjunto de


validaciones y procesamientos necesarios antes de la realización del
procesamiento.

Al evaluar el procesamiento de cálculo del factorial descrito anteriormente, se


puede definir que la validación inicial que se realizará es el contenido de la
variable nFator, pues ésta determinará la correcta ejecución del código.

Página 32 Introducción a la Programación ADVPL I


// Cálculo del factorial
nFator := GetFator()
// GetFator – función ilustrativa en la que la variable recibe la información del
usuario.

If nFator <= 0
Alert(“Información inválida”)
Return
Endif

For nCnt := nFator To 1 Step -1


nResultado *= nCnt
Next nCnt

Área de Cierre

En esta área se efectúan las finalizaciones. Es donde se cierran los archivos


abiertos y donde se utiliza el resultado de la ejecución del programa. Se puede
mostrar el resultado almacenado en una variable o en un archivo o
simplemente finalizar, si la tarea ya se completó en el cuerpo del programa. En
esta área se encuentra el final del programa. Todo programa en ADVPL debe
terminar siempre con la palabra clave return.

// Muestra el resultado en la pantalla, por medio de la función alert


Alert("El factorial de " + cValToChar(nFator) + ;
" es " + cValToChar(nResultado))

// Termina el programa
Return

Introducción a la Programación ADVPL I Página 33


4. DECLARACIÓN Y ATRIBUCIÓN DE VARIABLES

4.1. Tipo de Datos

El ADVPL no es un lenguaje fuertemente tipado (strongly typed), lo que


significa que variables de memoria pueden recibir diferentes tipos de datos
durante la ejecución del programa.

Las variables también pueden contener objetos, pero los tipos primarios de
lenguaje son:

Numérico

El ADVPL no distingue valores enteros de valores con punto flotante, por lo


tanto, es posible crear variables numéricas con cualquier valor dentro del
intervalo permitido. Los siguientes elementos son del tipo de dato numérico:

2
43.53
0.5
0.00001
1000000

Una variable de dato numérico puede contener un número de dieciocho cifras,


incluido el punto flotante, en el intervalo entre 2.2250738585072014 E–308 y
1.7976931348623158 E+308.

Lógico

Valores lógicos en ADVPL se identifican con .T. o .Y. para verdadero y .F. o .N.
para falso (independientemente de que los caracteres sean mayúsculos o
minúsculos).

Carácter

Strings o cadenas de caracteres se identifican en ADVPL por bloques de texto


entre comillas dobles (") o comillas simples ('):

"¡Hola mundo!"
'Esta es una string'
"Esta es 'otra' string"

Una variable del tipo carácter puede contener strings con un máximo de 1MB,

Página 34 Introducción a la Programación ADVPL I


es decir, 1.048.576 caracteres.

Fecha

El ADVPL tiene un tipo de datos específicos para fechas. Internamente, las


variables de este tipo de dato se almacenan como un número correspondiente
a la fecha Juliana.

Variables del tipo de datos Data no pueden declararse directamente, sino por
medio de la utilización de funciones específicas como, por ejemplo, CTOD()
que convierte una string a data.

Array

El Array es un tipo de dato especial. Es la disposición de otros elementos en


columnas y líneas. El ADVPL soporta arrays unidimensionales (vectores) o
multidimensionales (matrices). Los elementos de un array se acceden por
medio de índices numéricos iniciados en 1, identificando la línea y columna
para cuantas dimensiones existan.

Los Arrays deben utilizarse con cautela, porque si son muy grandes, pueden
consumir la memoria del servidor.

Bloque de Código

El bloque de código es un tipo de dato especial. Se utiliza para almacenar


instrucciones escritas en ADVPL que podrán ejecutarse posteriormente.

4.2. Declaración de variables

Variables de memoria son unos de los recursos más importantes de un


lenguaje. Son áreas de memoria creadas para almacenar información utilizada
por un programa para la ejecución de tareas. Por ejemplo, cuando el usuario
digita una información cualquiera, como el nombre de un producto, en una
pantalla de un programa, esta información se almacena en una variable de
memoria para grabarse o imprimirse posteriormente.

A partir del momento que se crea una variable, ya no es necesario hacer


referencia a su contenido, sino a su nombre.

El nombre de una variable es un identificador único el cual debe respetar un


máximo de 10 caracteres. El ADVPL no impide la creación de una variable de
memoria cuyo nombre contenga más de 10 caracteres, sin embargo, sólo se
considerarán los 10 primeros para la localización del contenido almacenado.

Introducción a la Programación ADVPL I Página 35


Por lo tanto, si se crean dos variables cuyos 10 primeros caracteres sean
iguales, como nTotalGeralAnual y nTotalGeralMensal, las referencias a
cualquiera de ellas en el programa serán iguales, es decir, tendrán la misma
variable:

nTotalGeralMensal := 100
nTotalGeralAnual := 300
Alert("Valor mensual: " + cValToChar(nTotalGeralMensal))

Cuando se muestre el contenido de la variable nTotalGeralMensal, su valor


será 300. Esto sucede porque en el momento que se atribuyó este valor a la
variable nTotalGeralAnual, el ADVPL sólo consideró los 10 primeros caracteres
(de la misma forma como lo hace cuando debe mostrar el valor de la variable
nTotalGeralMensal), es decir, las consideró como si fuesen la misma variable.
De esta manera, el valor original de 100 se sustituyó por 300.

4.3. Alcance de variables

El ADVPL no es un lenguaje de tipos rígidos para variables, es decir, no es


necesario informar el tipo de datos que determinada variable tendrá cuando
se realice su declaración y su valor puede cambiar durante la ejecución del
programa.

Tampoco hay necesidad de declarar variables en una sección específica de su


código fuente, aunque es aconsejable declarar todas las variables necesarias al
inicio, propiciando un mantenimiento más fácil y evitando la declaración de
variables innecesarias.

Para declarar una variable debe utilizarse un identificador de alcance. Un


identificador de alcance es una palabra clave que indica a qué contexto del
programa pertenece la variable declarada. El contexto de variables puede ser
local (visualizadas únicamente dentro del programa actual), público
(visualizadas por cualquier otro programa), entre otros.

El Contexto de Variables dentro de un Programa

Las variables declaradas en un programa o función son visibles de acuerdo con


el alcance que se les definió. De la misma manera, el tiempo de existencia de
las variables declaradas en un programa o función depende del alcance
definido para ellas. La definición del alcance de una variable se realiza en el
momento de su declaración.

Local nNúmero := 10

Página 36 Introducción a la Programación ADVPL I


Esta línea de código declara una variable denominada nNúmero, indicando
que el alcance al que pertenece es local.

Los identificadores de alcance son:

; Local
; Static
; Private
; Public

El ADVPL no es rígido con relación a la declaración de variables al inicio del


programa. La inclusión de un identificador de alcance no es necesaria para la
declaración de una variable, siempre y cuando se le haya atribuido un valor.

nNumero2 := 15

Cuando se atribuye un valor a una variable en un programa o función, el


ADVPL crea la variable si no se declaró anteriormente. La variable se crea
como si se hubiera declarado como Private.

Debido a esta característica, cuando se pretende realizar una atribución a una


variable declarada previamente, pero se escribe el nombre de la variable de
forma incorrecta, el ADVPL no genera ningún error de compilación o de
ejecución. Pues considerará el nombre de la variable escrita de forma
incorrecta como si fuera la creación de una nueva variable. Esto modificará la
lógica del programa y es un error muchas veces, difícil de identificar.

Variables de alcance local

Variables de alcance local pertenecen únicamente al alcance de la función


donde se declararon y deben declararse explícitamente con el identificador
LOCAL, como en el siguiente ejemplo:

Function Principal()
Local nVar := 10, aMatriz := {0,1,2,3}
.
<comandos>
.
Secundaria()
.
<más comandos>
.
Return(.T.)

Introducción a la Programación ADVPL I Página 37


En este ejemplo, la variable nVar se declaró como local y se le atribuyó el valor
10. Cuando se ejecuta la función Secundaria, nVar aún existe pero no puede
accederse. Cuando la ejecución de la función Principal termina, se destruye la
variable nVar. No se afecta ninguna variable con el mismo nombre del
programa que llamó la función Principal.

Las variables de alcance local se crean automáticamente, cada vez que se


active la función donde se declaran. Ellas continúan existiendo y mantienen su
valor hasta que se termine de activar la función (es decir, hasta que la función
devuelve el control al código que la ejecutó). Si se llama recursivamente una
función (por ejemplo, se llama a sí misma), cada llamada recursiva crea un
nuevo conjunto de variables locales.

La visibilidad de variables de alcance locales es idéntica al alcance de su


declaración, es decir, la variable es visible en cualquier lugar del código fuente
en el que se declaró. Si una función se llama recursivamente, sólo son visibles
las variables de alcance local creadas en la activación más reciente.

Variables de alcance static

Variables de alcance static funcionan básicamente como variables de alcance


local, pero mantienen su valor por medio de su ejecución y deben declararse
obligatoriamente en el código , con el identificador STATIC.

El alcance de las variables static depende de dónde se declaran. Si se


declararan dentro del cuerpo de una función o procedimiento, su alcance se
limitará a aquella rutina. Si se declaran fuera del cuerpo de cualquier rutina, su
alcance afecta a todas las funciones declaradas en el fuente.

En este ejemplo, la variable nVar se declaró como static y se inició con el valor
10.

Function Principal()
Static nVar := 10
.
<comandos>
.
Secundaria()
.
<más comandos>
.
Return(.T.)

Cuando se ejecuta la función Secundaria, nVar aún existe pero no puede


accederse. A diferencia de las variables declaradas como LOCAL o PRIVATE,
nVar continúa existiendo y mantiene su valor actual cuando se termina la
ejecución de la función Principal. Sin embargo, sólo puede accederse por

Página 38 Introducción a la Programación ADVPL I


medio de ejecuciones subsiguientes de la función Principal.

Variables de alcance private

La declaración es opcional para variables privadas. Pero pueden declararse con


el identificador PRIVATE.

Además, la atribución de un valor a una variable que no se haya declarado,


crea automáticamente una variable privada. Después de crear una variable
privada, ésta continúa existiendo y mantiene su valor hasta que se termine el
programa o función donde se creó (es decir, hasta que la función donde se
creó regrese al código que la ejecutó). En este momento se destruye
automáticamente.

Es posible crear una nueva variable privada con el mismo nombre de una
variable que ya existe. Sin embargo, la nueva (duplicada) variable sólo puede
crearse en un nivel de activación inferior al nivel donde la variable se declaró
por primera vez (es decir, sólo en una función llamada por la función donde la
variable ya se había creado). La nueva variable privada esconderá cualquier
otra variable privada o pública (vea la documentación sobre variables
públicas) que exista con el mismo nombre.

Cuando se crea una variable privada, ésta puede visualizarse en todo el


programa, mientras no se destruya automáticamente cuando la rutina que la
creó termine o se cree otra variable privada con el mismo nombre en una
subfunción llamada (en este caso, la variable existente queda inaccesible hasta
que se destruya la nueva variable privada).
En otras palabras, una variable privada es visible dentro de la función de
creación y por todas las funciones llamadas por ésta, a menos que una función
llamada cree su propia variable privada con el mismo nombre.

Por ejemplo:

Function Principal()
Private nVar := 10
<comandos>
.
Secundaria()
<más comandos>
.
Return(.T.)

Introducción a la Programación ADVPL I Página 39


En este ejemplo, la variable nVar se crea con el alcance private y se inicia con
el valor 10. Cuando se ejecuta la función Secundaria, nVar aún existe, y a
diferencia de una variable de alcance local, puede accederse por medio de la
función Secundaria. Cuando termine la función Principal, nVar será destruida y
cualquier declaración anterior de nVar será nuevamente accesible.

• En el entorno ERP Protheus, hay una determinación adicional que


debe respetarse, la cual consiste en que, las variables que la aplicación
esté usando, no se manipulen incorrectamente. En esta determinación
debe agregarse el carácter “_” antes del nombre de las variables
PRIVATE y PUBLIC. Más información para evaluar el tópico: Buenas
Prácticas de Programación.

Ejemplo: Private _dData

Variables de alcance public

Pueden crearse dinámicamente variables de alcance public, en el código con el


identificador PUBLIC. Las variables de este alcance continúan existiendo y
mantienen su valor hasta que se finalice la ejecución de la thread (conexión).

Es posible crear una variable de alcance private con el mismo nombre de una
variable de alcance public existente, sin embargo, no se permite crear una
variable de alcance public con el mismo nombre de una variable de alcance
private existente.

Cuando se crea una variable de alcance public, ésta es visible en todo el


programa en el que se declaró, hasta que sea escondida por una variable de
alcance private, creada con el mismo nombre. La nueva variable de alcance
private esconde la variable de alcance public existente y ésta quedará
inaccesible hasta que se destruya la nueva variable private. Por ejemplo:

Página 40 Introducción a la Programación ADVPL I


Function Principal()
Public nVar := 10
<comandos>
.
Secundaria()
<más comandos>
.
Return(.T.)

En este ejemplo, nVar se crea como public y se inicia con el valor 10. Cuando
se ejecuta la función Secundaria, nVar aún existe pero no puede accederse. A
diferencia de las variables locales o privates, nVar aún existe después de haber
terminado la ejecución de la función Principal.

A diferencia de los otros identificadores de alcance, cuando una variable se


declara como pública sin que se haya iniciado, el valor asumido será falso (.F.)
y no nulo (nil).

En el entorno ERP Protheus, hay una determinación adicional que debe


respetarse, la cual consiste en que, las variables que la aplicación esté
usando, no se manipulen incorrectamente. En esta determinación debe
agregarse el carácter “_” antes del nombre de las variables PRIVATE y
PUBLIC. Más información para evaluar el tópico: Buenas Prácticas de
Programación.

Ejemplo: Public _cRotina

4.4. Cómo influye el alcance de las variables

Considere las líneas de código de ejemplo:

nResultado := 250 * (1 + (nPercentual / 100))

Si se ejecuta esta línea en un programa ADVPL, ocurrirá un error de ejecución


con el mensaje "variable does not exist: nPercentual", pues esta variable está
en uso en una expresión de cálculo sin haber sido declarada. Para solucionar

Introducción a la Programación ADVPL I Página 41


este error, debe previamente declararse la variable:

Local nPercentual, nResultado


nResultado := 250 * (1 + (nPercentual / 100))

En este ejemplo, las variables se declaran previamente, utilizando el


identificador de alcance local. Cuando se ejecute la línea de cálculo, ya no
ocurrirá el error de variable no existente. Sin embargo, variables no iniciadas
siempre tienen el valor estándar nulo (Nil) y este valor no puede utilizarse en
un cálculo, pues también generará errores de ejecución (nulo no puede
dividirse entre 100). La resolución de este problema se realiza iniciando la
variable por medio de una de las formas:

Local nPercentual, nResultado


nPercentual := 10
nResultado := 250 * (1 + (nPercentual / 100))

Local nPercentual := 10, nResultado


nResultado := 250 * (1 + (nPercentual / 100))

La diferencia entre el último ejemplo y los dos anteriores, es que la variable se


inicia en el momento de la declaración. En ambos ejemplos, primero se declara
la variable y después se inicia en otra línea de código.

Es aconsejable optar por el operador de atribución compuesto de dos puntos


y signo igual, pues el operador de atribución, que utiliza solamente el signo
igual, puede fácilmente confundirse con el operador relacional (para
comparación), durante la creación del programa.

4.5. Operaciones con Variables

4.5.1. Atribución de variables

Después que se le atribuye un valor, el tipo de dato de una variable es igual al


tipo de dato del valor atribuido. Es decir, una variable se transforma en
numérica si se le atribuye un número; y se transforma en carácter si se le
atribuye una string de texto, etc. Sin embargo, aunque una variable sea de
determinado tipo de dato, es posible cambiarla atribuyéndole otro tipo:

Página 42 Introducción a la Programación ADVPL I


01 Local xVariavel // Declara la variable inicialmente con valor nulo
02
03 xVariavel := "Ahora la variable es carácter..."
04 Alert("Valor del Texto: " + xVariavel)
05
06 xVariavel := 22 // Ahora la variable es numérica
07 Alert(cValToChar(xVariavel))
08
09 xVariavel := .T. // Ahora la variable es lógica
10 If xVariavel
11 Alert("La variable tiene un valor verdadero...")
12 Else
13 Alert("La variable tiene un valor falso...")
14 Endif
15
16 xVariavel := Date() // Ahora la variable es data
17 Alert("Hoy es: " + DtoC(xVariavel))
18
19 xVariavel := nil // Nulo nuevamente
20 Alert("Valor nulo: " + xVariavel)
21
22 Return

En el programa de ejemplo anterior, la variable xVariavel se utiliza para


almacenar diversos tipos de dato. La letra "x" en minúscula al inicio del
nombre se utiliza para indicar una variable que puede tener diversos tipos de
dato, de acuerdo con la Notación Húngara (consulte la documentación
específica para detalles). Este programa cambia los valores de la variable y
muestra su contenido al usuario por medio de la función ALERT(). Esta función
recibe un parámetro que debe ser del tipo string de carácter, por ello,
dependiendo del tipo de dato de la variable xVariavel, es necesario que antes
se realice una conversión.

A pesar de esta flexibilidad de utilización de variables, deben tomarse algunos


cuidados en el paso de parámetros a funciones o comandos y en la
concatenación (o suma) de valores. Vea la línea 20 del programa de ejemplo.
Cuando se ejecute esta línea, la variable xVariavel tiene el valor nulo. El intento
de suma de tipo de datos diferentes genera un error de ejecución en el
programa. En esta línea del ejemplo ocurrirá un error con el mensaje "type
mismatch on +".

Con excepción del caso de valor nulo, para los demás deben utilizarse
funciones de conversión, cuando es necesario concatenar tipo de datos
diferentes (por ejemplo, en las líneas 07 y 17).

Note también que cuando una variable es del tipo de dato lógico, puede
utilizarse directamente para verificación (línea 10):

Introducción a la Programación ADVPL I Página 43


If xVariavel
es lo mismo que
If xVariavel = .T.

4.5.2. Operadores del lenguaje ADVPL

Operadores comunes

En la documentación sobre variables hay una breve demostración de cómo


atribuir valores a una variable de la forma más sencilla. El ADVPL amplía
significativamente la utilización de variables, por medio del uso de expresiones
y funciones.

Una expresión es un conjunto de operadores y operandos, cuyo resultado


puede atribuirse a una variable o analizarse para la toma de decisiones. Por
ejemplo:

Local nSalario := 1000, nDesconto := 0.10


Local nAumento, nSalLiquido
nAumento := nSalario * 1,20
nSalLiquido := nAumento * (1-nDesconto)

En este ejemplo se utilizan algunas expresiones para calcular el sueldo neto


después de un aumento. Los operandos de una expresión pueden ser una
variable, una constante, un campo de archivo o una función.

Operadores Matemáticos

Los operadores utilizados en ADVPL para cálculos matemáticos son:

+ Adición
- Sustracción
* Multiplicación
/ División
** o ^ Exponenciación
% Módulo (Resto de la División)

Operadores de String

Los operadores utilizados en ADVPL para tratamiento de caracteres son:

Página 44 Introducción a la Programación ADVPL I


+ Concatenación de strings (unión).
- Concatenación de strings con eliminación de los espacios finales
de las strings intermediarias.
$ Comparación de Substrings (incluido en).

Operadores Relacionales

Los operadores utilizados en ADVPL para operaciones y evaluaciones


relacionales son:

< Comparación Menor


> Comparación Mayor
= Comparación Igual
== Comparación Exactamente Igual (para caracteres)
<= Comparación Menor o Igual
>= Comparación Mayor o Igual
<> o # Comparación Diferente
o !=

Introducción a la Programación ADVPL I Página 45


Operadores Lógicos

Los operadores utilizados en ADVPL para operaciones y evaluaciones lógicas


son:

.And. Y lógico
.Or. O lógico
.Not. o ! NO lógico

Operadores de Atribución

Los operadores utilizados en ADVPL para atribución de valores a variables de


memoria son:

:= Atribución Simple
+= Adición y Atribución en Línea
-= Sustracción y Atribución en Línea
*= Multiplicación y Atribución en Línea
/= División y Atribución en Línea
**= o ^= Exponenciación y Atribución en Línea
%= Módulo (resto de la división) y Atribución en Línea

; Atribución Simple

El signo de igualdad se utiliza para atribuir valor a una variable de memoria.


nVariavel := 10

; Atribución en Línea

El operador de atribución en línea se caracteriza por dos puntos y el signo de


igualdad. Tiene la misma función del signo de igualdad sólito, pero aplica la
atribución a las variables. Con éste puede atribuirse más de una variable al
mismo tiempo.

nVar1 := nVar2 := nVar3 := 0

Cuando se inician diversas variables en una misma línea, la atribución empieza


de la derecha a la izquierda, es decir, nVar3 recibe inicialmente el valor cero,
nVar2 recibe el contenido de nVar3 y nVar1 recibe el contenido de nVar2 por
final.

Con el operador de atribución en línea es posible sustituir los inicios


individuales de cada variable por solamente un inicio:

Página 46 Introducción a la Programación ADVPL I


Local nVar1 := 0, nVar2 := 0, nVar3 := 0
por
Local nVar1 := nVar2 := nVar3 := 0

El operador de atribución en línea también puede utilizarse para sustituir


valores de campos en una base de datos.

; Atribución Compuesta

Los operadores de atribución compuesta son una facilidad del lenguaje ADVPL
para expresiones de cálculo y atribución. Con ellos no es necesario realizar la
digitación:

Operador Ejemplo Equivalente a


+= X += Y X=X+Y
-= X -= Y X=X-Y
*= X *= Y X=X*Y
/= X /= Y X=X/Y
**= o ^= X **= Y X = X ** Y
%= X %= Y X=X%Y

Operadores de Incremento/Decremento

El lenguaje ADVPL tiene operadores para realizar incremento o decremento de


variables. Se entiende por incremento el aumento del valor de una variable
numérica en 1 y se entiende por decremento la disminución del valor de la
variable en 1. Los operadores son:

++ Incremento Post o Prefijado


-- Decremento Post o Prefijado

Los operadores de decremento/incremento pueden colocarse tanto antes


(prefijado) como después (postfijado) del nombre de la variable. Dentro de
una expresión, el orden del operador es sumamente importante, pues puede
modificar el resultado de la expresión. Los operadores incrementales se
ejecutan de izquierda a derecha dentro de una expresión.

Local nA := 10
Local nB := nA++ + nA

El valor de la variable nB es 21, pues la primera referencia a nA (antes del ++)


incluía el valor 10 que fue considerado e inmediatamente aumentado a 1. En la
segunda referencia a nA, ya se encontraba el valor 11. Lo que se realizó fue la
suma de 10 más 11, igual a 21. El resultado final después de la ejecución de
estas dos líneas es la variable nB con 21 y la variable nA con 11.

Introducción a la Programación ADVPL I Página 47


Sin embargo:

Local nA := 10
Local nB := ++nA + nA

Resulta 22, pues el operador incremental aumentó el valor de la primera nA


antes que se considere su valor.

Operadores Especiales

Además de los operadores comunes, el ADVPL tiene algunos otros operadores


o identificadores. Y sus finalidades son:

() Agrupamiento o Función
[] Elemento de Matriz
{} Definición de Matriz, Constante o Bloque de Código
-> Identificador de Apodo
& Macrosustitución
@ Paso de parámetro por referencia
|| Paso de parámetro por valor

9 Los paréntesis se utilizan para agrupar elementos en una expresión,


cambiando el orden de precedencia de la evaluación de la expresión (según
las reglas matemáticas, por ejemplo). También sirven para involucrar los
argumentos de una función.

9 Los corchetes se utilizan para especificar un elemento específico de una


matriz. Por ejemplo, A[3.2] se refiere al elemento de la matriz A en la línea 3,
columna 2.

9 Las claves se utilizan para la especificación de matrices literales o bloques


de código. Por ejemplo, A:={10,20,30} crea una matriz denominada A con tres
elementos.

9 El símbolo -> identifica un campo de un archivo, diferenciándolo de una


variable. Por ejemplo, FUNC->nome se refiere al campo nombre del archivo
FUNC. Aunque exista una variable denominado nombre, es el campo nombre
que se accederá.

9 El símbolo & identifica una evaluación de expresión por medio de macro y


es visto con detalles en la documentación sobre macrosustitución.

9 El símbolo @ se utiliza para indicar que durante el paso de una variable a


una función o procedimiento ésta se considere como una referencia y no
como valor.

Página 48 Introducción a la Programación ADVPL I


9 El símbolo || se utiliza para indicar que durante el paso de una variable a
una función o procedimiento, ésta se considere con el valor 1 y no como
referencia.

Orden de Precedencia de los Operadores

Dependiendo del tipo de operador, existe un orden de precedencia para la


evaluación de los operandos. En principio, todas las operaciones con los
operadores se realizan de izquierda a derecha si tienen el mismo nivel de
prioridad.

El orden de precedencia o nivel de prioridad de ejecución de los operadores


en ADVPL es:

1. Operadores de Incremento/Decremento prefijado


2. Operadores de String
3. Operadores Matemáticos
4. Operadores Relacionales
5. Operadores Lógicos
6. Operadores de Atribución
7. Operadores de Incremento/Decremento postfijado

En expresiones complejas con diferentes tipo de operadores, la evaluación


seguirá esta secuencia. Si existe más de un operador del mismo tipo (es decir,
con el mismo nivel), la evaluación se realiza de izquierda a derecha. Sin
embargo, para los operadores matemáticos hay una precedencia a seguir:

1. Exponenciación
2. Multiplicación y División
3. Adición y Sustracción

Considere el ejemplo:

Local nResultado := 2+10/2+5*3+2^3

El resultado de esta expresión es 30, pues en primer lugar se calcula la


exponenciación 2^3(=8), entonces, se calculan las multiplicaciones y divisiones
10/2(=5) y 5*3(=15); y finalmente las adiciones, lo que resultará en
2+5+15+8(=30).

; Modificación de la Precedencia

La utilización de paréntesis dentro de una expresión modifica el orden de


precedencia de los operadores. Operandos entre paréntesis se analizan antes
de los que se encuentran fuera de los paréntesis. Si existe más de un conjunto
de paréntesis no anidados, primero se evaluará el grupo que se encuentra más
a la izquierda y así sucesivamente.

Introducción a la Programación ADVPL I Página 49


Local nResultado := (2+10)/(2+5)*3+2^3

En el ejemplo anterior, primero se calculará la exponenciación 2^3(=8). A


continuación, se calculará 2+10(=12) y 2+5(=7), finalmente se realizará la
división y la multiplicación, lo que resultará en 12/7*3+8(=13.14).

Si existen varios paréntesis anidados, es decir, colocados uno dentro del otro,
la evaluación ocurrirá del paréntesis más entero en dirección al más externo.

4.5.3. Operación de Macrosustitución

El operador de macrosustitución, simbolizado por el "y" comercial (&), se


utiliza para la evaluación de expresiones en tiempo de ejecución. Funciona
como si una expresión almacenada fuera compilada en tiempo de ejecución,
antes de ser de hecho ejecutada.

Considere el ejemplo:

01 X := 10
02 Y := "X + 1"
03 B := &Y // El contenido de B será 11

A la variable X se le atribuye el valor 10, mientras a la variable Y se le atribuye


una string de caracteres con "X + 1".

La tercera línea utiliza el operador de macro. Esta línea hace que el número 11
se atribuya a la variable B. Se puede percibir que este es el valor resultante de
la expresión en formato de carácter incluida en la variable Y.

Por medio de una técnica matemática elemental, la sustitución, en la segunda


línea Y se define como "X + 1", entonces, puede sustituirse Y en la tercera
línea:

03 B := &"X + 1"
El operador de macro anula las comillas:
03 B := X + 1

Se puede percibir que el operador de macro retira las comillas, dejando un


pedazo de código por ejecutarse. Debe tenerse en cuenta que todo esto
sucede en tiempo de ejecución, lo que hace que todo sea bastante dinámico.
Una utilización interesante es crear un tipo de calculadora o evaluador de
fórmulas, que determina el resultado de algo que el usuario digita.

El operador de macro tiene una limitación: variables referenciadas dentro de la

Página 50 Introducción a la Programación ADVPL I


string de caracteres (X en los ejemplos anteriores) no pueden ser locales.

4.5.4. Funciones de manipulación de variables

Además de atribuir, controlar el alcance y macroejecutar el contenido de las


variables, es necesario manipular su contenido por medio de funciones
específicas del lenguaje para cada situación.

Las operaciones de manipulación de contenido más comunes en


programación son:

; Conversiones entre tipo de variables.


; Manipulación de strings.
; Manipulación de variables numéricas.
; Verificación de tipo de variables.
; Manipulación de arrays.
; Ejecución de bloques de código.

En este tópico se abordarán las conversiones entre tipo de variables y las


funciones de manipulación de strings y variables numéricas.

Conversiones entre tipo de variables

Las funciones más utilizadas en las operaciones de conversión entre tipo de


variables son:

 CTOD()

 CVALTOCHAR()

 DTOC()

 DTOS()

 STOD()

 STR()

 STRZERO()

 VAL()

Introducción a la Programación ADVPL I Página 51


CTOD()

Sintaxis CTOD(cData)
Realiza la conversión de una información del tipo carácter en el formato
Descripción “DD/MM/AAAA”, para una variable del tipo data.

CVALTOCHAR()

Sintaxis CVALTOCHAR(nValor)
Realiza la conversión de una información del tipo numérico en una string, sin la
Descripción
adición de espacios a la información.

DTOC()

Sintaxis DTOC(dData)
Realiza la conversión de una información del tipo data a un carácter, que
Descripción resultará en un formato “DD/MM/AAAA”.

DTOS()

Sintaxis DTOS(dData)
Realiza la conversión de una información del tipo data a un carácter, que
Descripción resultará en un formato “AAAAMMDD”.

STOD()

Sintaxis STOD(sData)
Realiza la conversión de una información del tipo carácter, con contenido en el
Descripción
formato “AAAAMMDD” a data.

Página 52 Introducción a la Programación ADVPL I


STR()

Sintaxis STR(nValor)
Realiza la conversión de una información del tipo numérico a una string,
Descripción
agregando espacios a la derecha.

STRZERO()

Sintaxis STRZERO(nValor, nTamanho)


Realiza la conversión de una información del tipo numérico en una string,
Descripción agregando ceros a la izquierda del número convertido, de tal manera que la
string generada tenga el tamaño especificado en el parámetro.

VAL()

Sintaxis VAL(cValor)
Descripción Realiza la conversión de una información del tipo carácter a numérica.

Manipulación de strings

Las funciones mas utilizadas en las operaciones de manipulación del contenido de


strings son:

 ALLTRIM()
 ASC()
 AT()
 CHR()
 CSTUFF()
 LEN()
 RAT()
 SUBSTR()

Introducción a la Programación ADVPL I Página 53


ALLTRIM()

Sintaxis ALLTRIM(cString)
Devuelve una string sin los espacios a la derecha y a la izquierda, referente al
contenido informado como parámetro.

Descripción
La función ALLTRIM() implementa las acciones de las funciones RTRIM (“right
trim”) y LTRIM (“left trim”).

ASC()

Sintaxis ASC(cCaractere)
Convierte una información carácter en su valor, de acuerdo con la tabla ASCII.
Descripción

AT()

Sintaxis AT(cCaractere, cString )


Devuelve la primera posición de un carácter o string, dentro de otra string
Descripción especificada.

Página 54 Introducción a la Programación ADVPL I


CHR()

Sintaxis CHR(nASCII)
Convierte un valor número referente a una información de la tabla ASCII, en el
Descripción carácter que esta información representa.

LEN()

Sintaxis LEN(cString)
Descripción Devuelve el tamaño de la string especificada en el parámetro.

LOWER()

Sintaxis LOWER(cString)
Devuelve una string con todos los caracteres minúsculos, con base en la string
Descripción
considerada como parámetro.

RAT()

Sintaxis RAT(cCaractere, cString)


Devuelve la última posición de un carácter o string, dentro de otra string
Descripción especificada.

STUFF()

Sintaxis STUFF(cString, nPosInicial, nExcluir, cAdicao)


Permite sustituir un contenido carácter en una string existente, especificando la
Descripción posición inicial para esta adición y el número de caracteres que se sustituirán.

Introducción a la Programación ADVPL I Página 55


SUBSTR()

Sintaxis SUBSTR(cString, nPosInicial, nCaracteres)


Devuelve parte del contenido de una string especificada, de acuerdo con la
Descripción posición inicial de este contenido en la string e inclusive, la cantidad de
caracteres que debe devolverse a partir de aquel punto.

UPPER()

Sintaxis UPPER(cString)
Devuelve una string con todos los caracteres mayúsculos, con base en la string
Descripción
considerada como parámetro.

Manipulación de variables numéricas

Las funciones mas utilizadas en las operaciones de manipulación del contenido de


strings son:

 ABS()
 INT()
 NOROUND()
 ROUND()

ABS()

Sintaxis ABS(nValor)
Devuelve un valor absoluto (independientemente del signo) con base en el valor
Descripción especificado en el parámetro.

INT()

Sintaxis INT(nValor)
Descripción Devuelve la parte entera de un valor especificado en el parámetro.

Página 56 Introducción a la Programación ADVPL I


NOROUND()

Sintaxis NOROUND(nValor, nCasas)


Devuelve un valor, truncando la parte decimal del valor especificado en el
Descripción parámetro de acuerdo con la cantidad de decimales solicitados.

ROUND()

Sintaxis ROUND(nValor, nCasas)


Devuelve un valor, redondeando la parte decimal del valor especificado en el
parámetro, de acuerdo con las cantidades de decimales solicitados, utilizando el
Descripción
criterio matemático.

Introducción a la Programación ADVPL I Página 57


Verificación de tipo de variables

Las funciones de verificación permiten la consulta al tipo de contenido de la variable,


durante la ejecución del programa.

 TYPE()
 VALTYPE()

TYPE()

Sintaxis TYPE(“cVariavel”)
Determina el tipo do contenido de una variable, la cual no se definió en la
Descripción función en ejecución.

VALTYPE()

Sintaxis VALTYPE(cVariável)
Determina el tipo do contenido de una variable, la cual no se definió en la
Descripción función en ejecución.

Página 58 Introducción a la Programación ADVPL I


5. ESTRUCTURAS BÁSICAS DE PROGRAMACIÓN

El ADVPL soporta varias estructuras de control que permiten cambiar la secuencia de


flujo de ejecución de un programa. Estas estructuras permiten la ejecución de
código con base en condiciones lógicas y la repetición de la ejecución de pedazos
de código en cualquier número de veces.

En ADVPL, todas las estructuras de control pueden ser "anidadas" dentro de todas
las otras estructuras, siempre y cuando estén adecuadamente anidadas.. Las
estructuras de control tienen un identificador de inicial y final y cualquier estructura
anidada debe encontrarse entre estos identificadores.

También existen estructuras de control para determinar qué elementos, comandos,


etc. se compilarán en un programa. Estas son las directivas del preprocesador
#ifdef...#endif y #ifndef...#endif. Consulte la documentación sobre preprocesador
para más detalles.

Las estructuras de control en ADVPL están divididas en:

; Estructuras de repetición
; Estructuras de decisión

5.1. Estructuras de repetición

Las estructuras de repetición se asignan para ejecutar una sección de código


más de una vez. Por ejemplo, vamos a imaginar la existencia de una función
para imprimir un informe y que se desea imprimir cuatro veces. Claro, se
puede simplemente, llamar la función de impresión cuatro veces en secuencia,
pero esto es algo poco profesional y no resolvería el problema si el número de
informes es variable.

En ADVPL existen dos comandos para la repetición de secciones de código,


que son los comandos FOR...NEXT y el comando WHILE...ENDDO.

El Comando FOR...NEXT

La estructura de control FOR...NEXT, o simplemente el bucle FOR, repite una


sección de código un determinado número de veces.

Introducción a la Programación ADVPL I Página 59


; Sintaxis

FOR Variable := nValorInicial TO nValorFinal [STEP nIncremento]


Comandos...
[EXIT]
[LOOP]
NEXT

; Parámetros

Variable Especifica una variable o un elemento de una matriz para actuar


como un contador. No es necesario que la variable o el elemento
de la matriz haya sido declarado antes de la ejecución del
comando FOR...NEXT. Si la variable no existe, se creará como una
variable privada.
nValorInicial TO nValorInicial es el valor inicial para el contador; nValorFinal es el
nValorFinal valor final para el contador. Se pueden utilizar valores numéricos
literales, variables o expresiones, siempre y cuando el resultado sea
del tipo de dato numérico.
STEP nIncremento es la cantidad que se incrementará o decrementará
nIncremento en el contador después de cada ejecución de la sección de
comandos. Si el valor de nIncremento es negativo, se disminuirá el
contador. Si se omitiera la cláusula STEP, se aumentará a 1 el
contador. Se pueden utilizar valores numéricos literales, variables o
expresiones, siempre y cuando el resultado sea del tipo de dato
numérico.
Comandos Especifica una o más instrucciones de comando ADVPL que se
ejecutarán.
EXIT Transfiere el control de dentro del comando FOR...NEXT al
comando inmediatamente siguiente NEXT, es decir, finaliza la
repetición de la sección comandos inmediatamente. Se puede
colocar el comando EXIT en cualquier lugar entre el FOR y el NEXT.
LOOP Devuelve el control directamente a la cláusula FOR, sin ejecutar el
resto de los comandos entre el LOOP y el NEXT. El contador se
aumenta o disminuye normalmente, como si se hubiera alcanzado
el NEXT. Se puede colocar el comando LOOP en cualquier lugar
entre el FOR y el NEXT.

Página 60 Introducción a la Programación ADVPL I


Una variable o un elemento de una matriz se utiliza como un contador
para especificar cuántas veces se ejecutan los comandos ADVPL dentro
de la estructura FOR...NEXT.

Los comandos ADVPL después del FOR se ejecutan hasta que se alcance
el NEXT. Entonces, se aumenta o disminuye el contador (Variable) con
el valor en nIncremento (si se omitiera la cláusula STEP, el contador se
aumentará en 1). Entonces, se compara el contador con el valor en
nValorFinal. Si fuera menor o igual al valor de nValorFinal, los
comandos siguientes al FOR se ejecutarán nuevamente.

Si el valor fuera mayor que el valor de nValorFinal, se finaliza la


estructura FOR...NEXT y el programa continúa la ejecución en el primer
comando después del NEXT.

Los valores de nValorInicial, nValorFinal e nIncremento sólo se


consideran al inicio. Sin embargo, cambiar el valor de la variable
utilizada como contador dentro de la estructura afectará el número de
veces que se ejecutará la repetición. Si el valor de nIncremento es
negativo y el valor de nValorInicial es mayor que el de nValorFinal, se
disminuirá el contador a cada repetición.

Ejemplo:

Local nCnt
Local nSomaPar := 0
For nCnt := 0 To 100 Step 2
nSomaPar += nCnt
Next
Alert( "La suma de los 100 primeros números pares es: " + ;
cValToChar(nSomaPar) )
Return

Este ejemplo imprime la suma de los 100 primeros números pares. La suma se
obtiene por medio de la repetición del cálculo, utilizando la propia variable de
contador. Como la cláusula STEP está en uso, siempre se aumentará en 2 la
variable nCnt. Y como el contador empieza con 0, su valor siempre será un
número par.

Introducción a la Programación ADVPL I Página 61


El Comando WHILE...ENDDO

La estructura de control WHILE...ENDDO, o simplemente el bucle WHILE, repite


una sección de código mientras una determinada expresión resulta verdadera
(.T.).

; Sintaxis

WHILE lExpressao
Comandos...
[EXIT]
[LOOP]
ENDDO

; Parámetros

lExpressao Especifica una expresión lógica cuyo valor determina cuándo se ejecutan
los comandos entre el WHILE y el ENDDO. Mientras el resultado de
lExpressao se considere verdadero (.T.), se ejecutará el conjunto de
comandos.
Comandos Especifica una o mas instrucciones de comando ADVPL, que se
ejecutarán mientras lExpressao se considere verdadero (.T.).
EXIT Transfiere el control de dentro del comando WHILE...ENDDO al comando
inmediatamente siguiente, el ENDDO, es decir, finaliza la repetición de la
sección de comandos inmediatamente. Se puede colocar el comando
EXIT en cualquier lugar entre el WHILE y el ENDO.
LOOP Devuelve el control directamente a la cláusula WHILE sin ejecutar el
resto de los comandos entre el LOOP y el ENDDO. La expresión en
lExpressao se reevalúa para decidir si los comandos continuarán
ejecutándose.

Página 62 Introducción a la Programación ADVPL I


Ejemplo:

Local nNumber := nAux := 350


nAux := Int(nAux / 2)
While nAux > 0
nSomaPar += nCnt
Next
Alert( "La suma de los 100 primeros números pares es: " + ;
cValToChar(nSomaPar) )
Return

Los comandos entre el WHILE y el ENDDO se ejecutan mientras el


resultado de la evaluación de la expresión en lExpressao permanezca
verdadero (.T.). Cada palabra clave WHILE debe tener una palabra
clave ENDDO correspondiente.

5.1.1. Cómo influir en el flujo de repetición

El lenguaje ADVPL permite la utilización de comandos que influyen


directamente en un proceso de repetición, los cuales son:

; LOOP
; EXIT

LOOP

La instrucción LOOP se utiliza para forzar un desvío en el flujo del programa de


regreso al análisis de la condición de repetición. De esta manera, todas las
operaciones que se realizarían dentro de la estructura de repetición después
del LOOP no se considerarán.

Ejemplo:

aItens:= ListaProdutos() // función ilustrativa que devuelve un array con datos de los
productos.
nQuantidade := Len(aItens)
nItens := 0

While nItens < nQuantidade

nItens++
IF BLOQUEADO(aItens [nItens]) // función ilustrativa que verifica si el

Introducción a la Programación ADVPL I Página 63


producto está
LOOP // bloqueado.
ENDIF

IMPRIME() // función ilustrativa que realiza la impresión de un ítem liberado


para uso.

End

// Si el producto estuviera bloqueado, éste no se imprimirá, pues la ejecución


de la // instrucción LOOP determinará que el flujo del programa regrese a
partir del análisis de la condición.

EXIT

La instrucción EXIT se utiliza para forzar el término de una estructura de repetición.


De esta manera, todas las operaciones que se realizarían dentro de la estructura de
repetición después del EXIT no se considerarán y el programa continuará la
ejecución a partir de la próxima instrucción posterior al término de la estructura
(END o NEXT).

Ejemplo:

While .T.

IF MSGYESNO(“¿Desea jugar al ahorcado?”)


JFORCA() // Función ilustrativa que implementa el algoritmo del juego
del ahorcado.
ELSE
EXIT
ENDIF
End

MSGINFO(“Final de Juego”)

// Mientras no se responda “No” a la pregunta: “Desea jugar al


// ahorcado”, se ejecutará la función del juego del ahorcado.
// Si se selecciona la opción “No”, se ejecutará la instrucción EXIT que
provocará el término del LOOP, permitiendo la ejecución del mensaje “Final de
Juego”.

Página 64 Introducción a la Programación ADVPL I


5.2. Estructuras de decisión

Las estructuras de desvío se asignan para ejecutar una sección de código si


determinada condición lógica resulta verdadera (.T.).

En ADVPL existen dos comandos para ejecución de secciones de código, de


acuerdo con evaluaciones lógicas, estos son IF...ELSE...ENDIF y el comando
DO CASE...ENDCASE.

El Comando IF...ELSE...ENDIF

Ejecuta un conjunto de comandos con base en valor de una expresión lógica.

; Sintaxis

IF lExpressao
Comandos
[ELSE
Comandos...]
ENDIF

; Parámetros

LExpressao Especifica una expresión lógica que se evalúa. Si lExpressao resulta


verdadero (.T.), se ejecutará cualquier comando siguiente al IF y anterior
al ELSE o ENDIF (lo que ocurra primero).
Si lExpressao resulta falso (.F.) y la cláusula ELSE estuviera definida, se
ejecutará cualquier comando después de esta cláusula y anterior al
ENDIF. Si no se define la cláusula ELSE, se ignorarán todos los
comandos entre el IF y el ENDIF. En este caso, la ejecución del
programa continúa con el primer comando siguiente al ENDIF.
Comandos Conjunto de comandos ADVPL que se ejecutarán dependiendo de la
evaluación de la expresión lógica en lExpressao.

Puede anidarse un bloque de comando IF...ELSE...ENDIF dentro de otro


bloque de comando IF...ELSE...ENDIF. Sin embargo, para la evaluación
de más de una expresión lógica, debe utilizarse el comando DO
CASE...ENDCASE o la versión por extenso de la expresión
IF...ELSE...ENDIF denominada IF...ELSEIF...ELSE...ENDIF.

Introducción a la Programación ADVPL I Página 65


Ejemplo:
Local dVencto := CTOD("31/12/01")
If Date() > dVencto
Alert("¡Vencimiento sobrepasado!")
Endif
Return

El Comando IF...ELSEIF...ELSE...ENDIF

Ejecuta el primer conjunto de comandos cuya expresión condicional resulta


verdadera (.T.).

; Sintaxis

IF lExpressao1
Comandos
[ELSEIF lExpressaoX
Comandos]
[ELSE
Comandos...]
ENDIF

; Parámetros

lExpressao1 Especifica una expresión lógica que se evalúa. Si lExpressao resulta


verdadero (.T.), se ejecutarán los comandos comprendidos entre el IF y
la próxima expresión de la estructura (ELSEIF o IF).
Si lExpressao resulta falsa (.F.), se evaluará la próxima expresión lógica
vinculada al comando ELSEIF, o si éste no existe, se ejecutará la acción
definida en el comando ELSE.
lExpressaoX Especifica una expresión lógica que se evaluará para cada comando
ELSEIF. Esta expresión solamente se evaluará si la expresión lógica,
especificada en el comando IF, resulta falsa (.F.).
Si la lExpressaoX evaluada resulta falsa (.F.), se evaluará la próxima
expresión lExpressaoX, vinculada al próximo comando ELSEIF, o si éste
no existe, se ejecutará la acción definida para el comando ELSE.
Comandos Conjunto de comandos ADVPL que se ejecutarán dependiendo de la
evaluación de la expresión lógica en lExpressao.

El campo IF...ELSE...ELSEIF...ENDIF tiene la misma estructura de decisión


que puede obtenerse con la utilización del comando DO
CASE...ENDCASE.

Página 66 Introducción a la Programación ADVPL I


Ejemplo:
Local dVencto := CTOD("31/12/01")
If Date() > dVencto
Alert("¡Vencimiento sobrepasado!")
ElseIf Date() == dVencto
Alert("¡Vencimiento en la fecha!")
Else
Alert("¡Vencimiento dentro del plazo!")
Endif
Return

El Comando DO CASE...ENDCASE

Ejecuta el primer conjunto de comandos cuya expresión condicional resulta


verdadera (.T.).

; Sintaxis

DO CASE
CASE lExpressao1
Comandos
[CASE lExpressao2
Comandos
...
CASE lExpressaoN
Comandos]
[OTHERWISE
Comandos]
ENDCASE

; Parámetros

CASE Cuando se encuentra la primera expresión CASE con el resultado


lExpressao1 verdadero (.T.), se ejecuta el siguiente conjunto de comandos. La
Comandos... ejecución del conjunto de comandos continúa hasta que se encuentre
la próxima cláusula CASE, OTHERWISE o ENDCASE. Al terminar la
ejecución de este conjunto de comandos, la ejecución continúa con el
primer comando siguiente al ENDCASE.
Si una expresión CASE resulta falsa (.F.), se ignorará a partir del
conjunto de comandos siguiente a ésta hasta la próxima cláusula.
Sólo se ejecuta un conjunto de comandos. Estos son los primeros
comandos cuya expresión CASE se evalúa como verdadera (.T.).
Después de la ejecución, se ignora cualquier otra expresión CASE
posterior (aunque su evaluación resulte verdadera).

Introducción a la Programación ADVPL I Página 67


OTHERWISE Si todas las expresiones CASE se evalúan como falso (.F.), la cláusula
Comandos OTHERWISE determinará si debe ejecutarse un conjunto adicional de
comandos. Si se incluye esta cláusula, se ejecutarán los siguientes
comandos y entonces el programa continuará con el primer comando
siguiente al ENDCASE. Si se omite la cláusula OTHERWISE, la ejecución
continuará normalmente después de la cláusula ENDCASE.

El Comando DO CASE...ENDCASE se utiliza en el lugar del comando


IF...ENDIF, cuando debe evaluarse un número mayor que una
expresión, sustituyendo la necesidad de más de un comando IF...ENDIF
anidados.

Ejemplo:

Local nMes := Month(Date())


Local cPeriodo := ""

DO CASE
CASE nMes <= 3
cPeriodo := "Primer Trimestre"
CASE nMes >= 4 . Piso. nMes <= 6
cPeriodo := "Segundo Trimestre"
CASE nMes >= 7 . Piso. nMes <= 9
cPeriodo := "Tercer Trimestre"
OTHERWISE
cPeriodo := "Cuarto Trimestre"
ENDCASE

Return

Ejercicio
Desarrollar un programa que implemente el algoritmo pelar papas, utilizando la
estructura de repetición While, para mostrar cuántas papas se pelaron:

Página 68 Introducción a la Programación ADVPL I


Ejercicio
Desarrollar un programa que implemente el algoritmo pelar papas, utilizando la
estructura de repetición FOR, para mostrar cuántas papas se pelaron:

Ejercicio
Desarrollar un programa que implemente el algoritmo pelar papas, utilizando la
estructura de repetición FOR, para mostrar cuántas papas se pelaron:

Ejercicios
Desarrollar un programa que implemente el algoritmo del Ahorcado:

Ejercicios

Desarrollar un programa que implemente el algoritmo del Tres en Raya:

Introducción a la Programación ADVPL I Página 69


6. ARRAYS Y BLOQUES DE CÓDIGO

6.1. Arrays

Arrays o matrices son colecciones de valores, semejantes a una lista. Una


matriz puede crearse por medio de diferentes maneras.

Cada ítem en un array se referencia por la indicación de su posición numérica


en la lista, iniciando por el número 1.

El siguiente ejemplo declara una variable, atribuye un array de tres elementos


a ésta y entonces, muestra uno de los elementos y el tamaño del array:

Lugar aLetras // Declaración de la variable


aLetras := {"A", "B", "C"} // Atribución del array a la variable
Alert(aLetras[2]) // Muestra el segundo elemento del array
Alert(cValToChar(Len(aLetras))) // Muestra el tamaño del array

El ADVPL permite la manipulación de arrays fácilmente. Mientras que en otros


lenguajes como C o Pascal es necesario asignar memoria para cada elemento
de un array (lo que hace la utilización de "punteros" necesaria), el ADVPL se
encarga de administrar la memoria y hace más sencillo agregar elementos a
un array, utilizando la función AADD():

AADD(aLetras,"D") // Agrega el cuarto elemento al final del array.


Alert(aLetras[4]) // Muestra el cuarto elemento.
Alert(aLetras[5]) // ¡Error! No hay un quinto elemento en el array.

Arrays como Estructuras

Una característica interesante del ADVPL es que un array puede tener


cualquier tipo de dato: números, fechas, lógicos, caracteres, objetos, etc., y al
mismo tiempo. En otras palabras, los elementos de un array no necesitan ser
necesariamente del mismo tipo de dato, en contraste con otros lenguajes
como C y Pascal.

aFunct1 := {"Pedro",32,.T.}

Este array contiene una string, un número y un valor lógico. En otros lenguajes
como C o Pascal, este "paquete" de informaciones puede denominarse "struct"
(estructura en C, por ejemplo) o un "record" (registro en Pascal, por ejemplo).
Como si fuera en verdad un registro de una base de datos, un paquete de

Página 70 Introducción a la Programación ADVPL I


informaciones construido con diversos campos. Cada campo con un pedazo
diferente de dato.

Suponga que en el ejemplo anterior, el array aFunct1 contenga informaciones


sobre el nombre de una persona, su edad y su situación matrimonial. Los
siguientes #defines pueden crearse para indicar cada posición de los valores
dentro de un array:

#define FUNCT_NOME 1
#define FUNCT_IDADE 2
#define FUNCT_CASADO 3

Y considere algunos arrays más para representar más personas:

aFunct2 := {"María" , 22, .T.}


aFunct3 := {"Antonio", 42, .F.}

Los nombres pueden imprimirse de esta manera:

Alert(aFunct1[FUNCT_NOME])
Alert(aFunct2[FUNCT_NOME])
Alert(aFunct3[FUNCT_NOME])

Ahora, al contrario de trabajar con variables individuales es posible agruparlas


en un otro array, de la misma manera que muchos registros se agrupan en una
tabla de base de datos:

aFuncts := {aFunct1, aFunct2, aFunct3}

Que es equivalente a esto:

aFuncts := { {"Pedro" , 32, .T.}, ;


{"María" , 22, .T.}, ;
{"Antonio", 42, .F.} }

aFuncts es un array con 3 líneas por 3 columnas. Como las variables separadas
se combinaron en un array, los nombres pueden mostrarse de esta manera:

Local nCount
For nCount := 1 To Len(aFuncts)
Alert(aFuncts[nCount, FUNCT_NOME])
// El acceso a elementos de un array multidimensional.
// también puede realizarse de esta manera:
// aFuncts[nCount][FUNCT_NOME]
Next nCount

Introducción a la Programación ADVPL I Página 71


La variable nCount selecciona el empleado (o la línea) que es de interés.
Entonces, la constante FUNCT_NOME selecciona la primera columna de
aquella línea.

Cuidados con Arrays

Arrays son listas de elementos, por lo tanto, la memoria es necesaria para


almacenas estas informaciones. Como estos arrays pueden ser
multidimensionales, la memoria necesaria será la multiplicación del número de
ítems en cada dimensión del array, considerándose el tamaño del contenido
de cada elemento incluido en ésta. Por lo tanto, el tamaño de un array puede
variar mucho.

La facilidad de la utilización de arrays, aunque sea para almacenar información


en paquetes como los descritos anteriormente, no compensa por la utilización
de memoria cuando el número de ítems en un array es muy grande. Cuando el
número de elementos sea muy grande es mejor buscar otras soluciones, como
la utilización de un archivo de base de datos temporal.

Página 72 Introducción a la Programación ADVPL I


6.1.1. Iniciando arrays

Algunas veces el tamaño de la matriz se conoce previamente. Otras veces el


tamaño del array solamente se conocerá durante el tiempo de ejecución.

Si se conoce el tamaño del array

Si se conoce el tamaño del array en el momento que se escribe el programa,


hay diversas maneras de implementar el código:

01 Local nCnt
02 Local aX[10]
03 Local aY := Array(10)
04 Local aZ := {0,0,0,0,0,0,0,0,0,0}
05
06 For nCnt := 1 To 10
07 aX[nCnt] := nCnt * nCnt
08 Next nCnt

Este código rellena el array con una tabla de cuadrados. Los valores serán 1, 4,
9, 16 ... 81, 100. Note que la línea 07 se refiere a la variable aX, pero también
podría trabajar con aY o aZ.

El objetivo de este ejemplo es mostrar tres modos de crear un array de


tamaño conocido cuando se crea el código.

1. En la línea 02 el array se crea usando aX[10]. Esto indica al ADVPL para


asignar espacio para 10 elementos en el array. Los corchetes [y ] se utilizan
para indicar el tamaño necesario.

2. En la línea 03 se utiliza la función array con el parámetro 10 para crear el


array y la devolución de esta función se atribuye a la variable aY. En la línea 03
se realiza lo que se llama "diseñar la imagen del array". Como se puede notar,
existen diez 0 en la lista encerrada entre llaves ({}). Claramente, este método
no se utiliza para crear una matriz de 1000 elementos.

3. El tercer método difiere de los anteriores porque inicia la matriz con los
valores definitivos. En los dos primeros métodos, cada posición de la matriz
contiene un valor nulo (Nil) y debe iniciarse posteriormente.

4. La línea 07 muestra cómo puede atribuirse un valor para una posición


existente en una matriz, especificando el índice entre corchetes.

Introducción a la Programación ADVPL I Página 73


Si no se conoce el tamaño del array

Si no se conoce el tamaño del array cuando se ejecuta el programa, hay


algunas maneras de crear un array y agregar elementos a éste. El siguiente
ejemplo ilustra la idea de la creación de un array vacío (sin ningún elmento), y
de adición de elementos dinámicamente.

01 Local nCnt
02 Local aX[0]
03 Local aY := Array(0)
04 Local aZ := {}
05
06 For nCnt := 1 To nSize
07 AADD(aX, nCnt*nCnt)
08 Next nCnt

1. La línea 02 utiliza corchetes para crear un array vacío. Aunque no tiene


ningún elemento, su tipo de dato es array.

2. En la línea 03, la llamada de la función array crea una matriz sin ningún
elemento.

3. En la línea 04 está declarada la representación de un array vación en


ADVPL. Una vez más, se están utilizando las llaves para indicar que el tipo de
datos de la variable es un array. Note que {) es un array vacío (tiene el tamaño
0), mientras {Nil) es un array con un único elemento nulo (tiene tamaño 1).

Porque cada uno de estos arrays no contiene elmentos, la línea 07 utiliza la


función AADDD() para agregar elementos sucesivamente hasta el tamaño
necesario (especificado por ejemplo en la variable nSize).

6.1.2. Funciones de manipulación de arrays

El lenguaje ADVPL tiene diversas funciones que ayudan en la manipulación de


arrays, entre las cuales podemos mencionar las más utilizadas:

 ARRAY()
 AADD()
 ACLONE()
 ADEL()
 ASIZE()
 AINS()
 ASORT()
 ASCAN()

Página 74 Introducción a la Programación ADVPL I


ARRAY()

Sintaxis ARRAY(nLinhas, nColunas)


La función Array() se utiliza en la definición de variables de tipo
Descripción
array, como una opción de sintaxis, utilizando llaves (“{}”).

AADD()

Sintaxis AADD(aArray, xItem)


La función AADD() permite la inserción de un ítem en un array
Descripción existente, cuyo ítem puede ser un simple elemento, un objeto u
otro array.

ACLONE()

Sintaxis AADD(aArray)
La función ACLONE() realiza la copia de los elementos de un
Descripción
array a otro array integralmente.

ADEL()

Sintaxis ADEL(aArray, nPosição)


La función ADEL() permite borrar un elemento del array. Al
Descripción borrar un elemento, todos los otros se reorganizan, de tal
manera que la última posición del array será nula.

ASIZE()

Sintaxis ASIZE(aArray, nTamanho)


La función ASIZE permite la redefinición de la estructura de un
Descripción
array que ya existe, agregando o eliminando ítems de éste.

ASORT()

Sintaxis ASORT(aArray, nInicio, nItens, bOrdem)


La función ASORT() permite que los ítems de un array se
Descripción
ordenen a partir de un criterio establecido previamente.

Introducción a la Programación ADVPL I Página 75


ASCAN()

Sintaxis ASCAN(aArray, bSeek)


La función ASCAN() permite que se identifique la posición del
Descripción array que contiene una determinada información, por medio del
análisis de una expresión descrita en un bloque de código.

AINS()

Sintaxis AINS(aArray, nPosicao)


La función AINS() permite la inserción de un elemento en el array
especificado, en cualquier punto de la estructura de éste,
Descripción prorrogando de esta manera, la función AADD(), la cual siempre
inserta un nuevo elemento al final de la estructura existente.

6.1.3. Copia de arrays

De acuerdo con lo comentado anteriormente, un array es un área en la


memoria, el cual tiene una estructura que permite que la información se
almacene y organice de las más diversas maneras.

Con base en este concepto, el array sólo puede considerarse como un “mapa”
o un “guía” de cómo está organizada la información y cómo puede
almacenarse o consultarse. Para copiarse un array debe tomarse en cuenta
este concepto, de lo contrario, no se obtendrá el resultado esperado al
ejecutar la “copia”.

Para “copiar” el contenido de una variable se utiliza el operador de atribución


“:=”, de acuerdo con lo siguiente:

nPessoas := 10
nAlunos := nPessoas

Al ejecutar la atribución de nAlunos con el contenido de nPessoas, el


contenido de nPessoas se atribuye a la variable nAlunos, causando el efecto de
copia del contenido de una variable a otra.

Esto porque el comando de atribución copia el contenido del área de


memoria, representada por el nombre “nPessoas” al área de memoria
representada por el nombre “nAlunos”. Pero al utilizar el operador de
atribución “:=”, de la misma forma que se utiliza en las variables simples, al

Página 76 Introducción a la Programación ADVPL I


copiarse un array el efecto es diferente:

aPessoas := {“Ricardo”, “Cristiane”, “André”, “Camila”}


aAlunos := aPessoas

La variable aPessoas representa un área de memoria que contiene la


estructura de un array (“mapa”), no la información del array, pues cada
información está en su propia área de memoria.

De esta manera, al atribuir el contenido representado por la variable aPessoas,


la variable aAlunos no “copia” la información, sino el “mapa” de las áreas de
memoria, donde la información está realmente almacenada.

Introducción a la Programación ADVPL I Página 77


Como se copió el “mapa” y no la información, cualquier acción utilizando el
rótulo aAlunos afectará la información del rótulo aPessoas. Con ello, en lugar
de obtener dos arrays distintos, se obtiene el mismo array con dos formas de
acceso (rótulos) diferentes.

Por esta razón, debe utilizarse el comando ACLONE() cuando se desea obtener
un array con la misma estructura e información que compone otro array
existente.

6.2. Listas de Expresiones y Bloques de Código

Bloques de código son un concepto existente hace mucho tiempo en


lenguajes xBase. No como algo que apareció de la noche para la mañana, sino
como una evolución progresiva utilizando la combinación de muchos
conceptos de lenguaje para su implementación.

6.2.1. Premisas para utilización de Bloques de Código

Primera premisa

El ADVPL es un lenguaje basado en funciones. Las funciones tienen un valor de


devolución. De la misma forma que el operador de atribución :=.

De esta manera, en lugar de escribir:

x := 10 // Atribuye el valor 10 a la variable denominada X


Alert("Valor de x: " + cValToChar(x))

Página 78 Introducción a la Programación ADVPL I


Se puede escribir:

// Atribuye y entonces muestra el valor de la variable X


Alert("Valor de x: " + cValtoChar(X := 10))

Primero se evalúa la expresión x:=10 y entonces, su resultado (el valor de X,


que ahora es 10) se pasa a la función cvaltochar para la conversión a carácter y
a continuación, a la función alert para exhibición. Debido a esta regla de
precedencia es posible atribuir un valor adicional a una variable al mismo
tiempo:

Z := Y := X := 0

Debido a esta regla, esta expresión se evalúa como si se escribiera así:

Z := ( Y := (X := 0) )

A pesar de que el ADVPL evalúa expresiones de izquierda a derecha, en el caso


de atribuciones esto sucede al contrario, de derecha a izquierda. El valor se
atribuye a la variable X, que devuelve el valor para que se atribuya a la variable
Y y así sucesivamente. Se puede decir que el cero se "propagó por medio de la
expresión".

Segunda premisa

En ADVPL se pueden juntar diversas líneas de código en una única línea física
de comando. Por ejemplo, el código:

If lAchou
Alert("¡Cliente encontrado!")
Endif
puede escribirse la siguiente manera:
If lAchou ; Alert("¡Cliente encontrado!").
Endif

El punto y coma indica al ADVPL que la nueva línea de código está por
empezar. Entonces, pueden colocarse diversas líneas lógicas de código en la
misma línea física, por medio del editor de texto utilizado.

A pesar de la posibilidad de escribir todo el programa de esta manera, en una


única línea física, no es recomendable, pues dificulta la legibilidad del
programa y, consecuentemente, el mantenimiento.

Introducción a la Programación ADVPL I Página 79


6.2.2. Lista de expresiones

La evolución de los bloques de código empieza con las listas de expresiones.


En los siguientes ejemplos, el símbolo ==> indicará la devolución de la
expresión después de su evaluación (ya sea para atribuir en una variable,
mostrar al usuario o imprimir en un informe), que se imprimirá en un informe,
por ejemplo.

Dos Líneas de Código

@00.00 PSAY x := 10 ==> 10


@00.00 PSAY y := 20 ==> 20

Cada una de las líneas tendrá la expresión evaluada y se imprimirá el valor de


la variable.

Dos líneas de código en una, utilizando punto y coma

Este es el mismo código que el anterior, pero escrito en una única línea:

Alert( cValToChar( x := 10 ; y := 20 ) ) ==> 10

A pesar de que este código se encuentra en una única línea física, existen dos
líneas lógicas separadas por el punto y coma. Es decir, este código equivale a:

Alert( cValToChar( x := 10 ) )
y := 20

Por lo tanto, sólo el valor 10 de la variable x se pasará a las funciones


cvaltochar y alert para exhibición. Y el valor 20 sólo se atribuirá a la variable y.

Conversión a una lista de expresiones

Cuando se colocan paréntesis alrededor del código y el signo de punto y


coma se sustituye por una coma simplemente, el código se transforma en una
lista de expresiones:

Alert( cValToChar ( ( X := 10 , Y := 20 ) ) ) ==> 20

El valor de devolución resultante de una lista de expresiones es el valor


resultante de la última expresión o elemento de la lista. Funciona como si
fuera un pequeño programa o función, que devuelve el resultado de su última
evaluación (realizadas de izquierda a derecha).

En este ejemplo, se evalúa la expresión x := 10 y entonces, la expresión y := 20,

Página 80 Introducción a la Programación ADVPL I


cuyo valor resultante se pasa a la función alert y cvaltochar y se exhibe.
Después que se ejecuta esta línea de código, el valor de X es igual a 10 y el de
y igual a 20, y se muestra 20.

Teóricamente, no hay limitación para el número de expresiones que pueden


combinarse en una lista de expresiones. En la práctica, el número máximo
tiene alrededor de 500 símbolos.
Depurar listas de expresiones es difícil porque las expresiones no están
divididas en líneas de código fuente, lo que determina que todas las
expresiones estén asociadas a una misma línea de código. Esto puede
ocasionar mucha dificultad para determinar dónde ocurrió un error.

¿Dónde puede utilizarse una lista de expresiones?

El propósito principal de una lista de expresiones es agruparlas en una única


unidad. En cualquier lugar del código ADVPL en que puede utilizarse una
expresión sencilla, puede utilizarse una lista de expresiones. Y además, puede
determinarse que sucedan varias cosas donde normalmente sucedería una
sola.

X := 10 ; Y := 20
If X > Y
Alert("X")
Z := 1
Else
Alert("Y")
Z := -1
Endif

Aquí tenemos el mismo concepto escrito utilizando listas de expresiones en la


función IIF():

X := 10 ; Y := 20
iif( X > Y , ;
( Alert("X"), Z := 1 ) , ;
( Alert("Y"), Z := -1 ) )

De listas de expresiones a bloques de código

Considere la siguiente lista de expresiones:

Alert( cValToChar( ( x := 10, y := 20 ) ) ) ==> 20

El ADVPL permite crear funciones, que son pequeños pedazos de código,


como si fuera un pequeño programa, utilizados para disminuir partes de tareas
más complejas y reaprovechar el código en más de un lugar en un programa.
Para más detalles consulte la documentación sobre la creación de funciones

Introducción a la Programación ADVPL I Página 81


en ADVPL. Sin embargo, la idea en este momento es que la lista de
expresiones, utilizada en la línea anterior, puede crearse como una función:

Function Lista()
X := 10
Y := 20
Return Y

Y la línea de ejemplo, con la lista de expresiones, puede sustituirse, obteniendo


el mismo resultado, por:

Alert( cValToChar( Lista() ) ) ==> 20

Como se mencionó anteriormente, una lista de expresiones es como un


pequeño programa o función. Con pocos cambios, una lista de expresiones
puede transformarse en un bloque de código:

( X := 10 , Y := 20 ) // Lista de Expresiones
{|| X := 10 , Y := 20 } // Bloque de Código

Note las llaves {} utilizadas en el bloque de código. Es decir, un bloque de


código es una matriz. Sin embargo, en realidad no es una lista de datos, sino
una lista de comandos, una lista de código.

// Esto es una matriz de datos


A := {10, 20, 30}
// Esto es un bloque de código, pero funciona como
// si fuera una matriz de comandos
B := {|| x := 10, y := 20}

6.2.3. Bloques de Código

A diferencia de una matriz, no se puede acceder a elementos de un bloque de


código por medio de un índice numérico. Sin embargo, bloques de código son
semejantes a una lista de expresiones y a una pequeña función.

Es decir, pueden ejecutarse. Para ejecución o evaluación de un bloque de


código debe utilizarse la función Eval():

nRes := Eval(B) ==> 20

Esta función recibe como parámetro un bloque de código y evalúa todas las
expresiones incluidas en este bloque de código, devolviendo el resultado de la
última expresión evaluada.

Página 82 Introducción a la Programación ADVPL I


Pasar Parámetros

Como los bloques de código son como pequeñas funciones, también es


posible pasar el contenido de parámetros a un bloque de código. Los
parámetros deben informarse entre las barras verticales (||), separados por
comas, al igual que en una función.

B := {| N | X := 10, Y := 20 + N}

Sin embargo, debe notarse que como el bloque de código recibe un


parámetro, debe pasarse un valor cuando se evalúe el bloque de código.

C := Eval(B, 1) ==> 21

Introducción a la Programación ADVPL I Página 83


Utilización de Bloques de Código

Bloques de código pueden utilizarse en diversas situaciones. Generalmente, se


utilizan para ejecutar tareas cuando eventos de objetos se activan o para
modificar el comportamiento estándar de algunas funciones.

Por ejemplo, considere la siguiente matriz:

A := {"GARY HALL", "FRED SMITH", "TIM JONES"}

Esta matriz puede ordenarse por el primer nombre, utilizándose la llamada de


la función asort(A), cuyo resultado en la matriz ordena los elementos de la
siguiente manera:

{"FRED SMITH", "GARY HALL", "TIM JONES"}

El orden estándar para la función asort es ascendiente. Este comportamiento


puede modificarse por medio de la información de un bloque de código que
ordena la matriz de forma descendiente:

B := { |X, Y| X > Y }
aSort(A, B)

El bloque de código (de acuerdo con la documentación de la función asort)


debe escribirse para aceptar dos parámetros que son los dos elementos de la
matriz para comparación. Note que el bloque de código no conoce los
elementos que se están comparando, la función asort selecciona los elementos
(tal vez utilizando el algoritmo QuickSort) y los pasa al bloque de código. El
bloque de código los compara y devuelve verdadero (.T.) si se encuentran en
el orden correcto, o falso (.F.) en caso contrario. Si el valor de devolución fuera
falso, entonces, la función asort cambiará los valores de lugar y seguirá
comparando el próximo par de valores.
Entonces, en el bloque de código anterior, la comparación X > Y es verdadera
si los elementos están en orden descendiente, lo que significa que el primero
valor es mayor que el segundo.

Para ordenar la misma matriz por el último nombre, también en orden


descendente, puede utilizarse el siguiente bloque de código:

B := { |X, Y| SUBSTR(X, At(" ",X)+1) > SUBSTR(Y, At(" ",Y)+1) }

Note que este bloque de código busca y compara las partes de los caracteres,
inmediatamente siguientes a un espacio en blanco. Después de utilizar este
bloque de código para la función asort, la matriz tendrá:

{"GARY HALL", "TIM JONES", "FRED SMITH"}

Página 84 Introducción a la Programación ADVPL I


Finalmente, para ordenar un subelemento (columna) de una matriz por
ejemplo, puede utilizarse el siguiente bloque de código:

B := { |X, Y| X[1] > Y[1] }

6.2.4. Funciones para manipulación de bloques de código

El lenguaje ADVPL tiene diversas funciones que ayudan en la manipulación de


bloques de código, entre las cuales podemos mencionar las más utilizadas:

 EVAL()
 DBEVAL()
 AEVAL()

EVAL()

Sintaxis EVAL(bBloco, xParam1, xParam2, xParamZ)


La función EVAL() se utiliza para la evaluación directa de un
bloque de código, utilizando la información disponible en el
Descripción momento de su ejecución. Esta función permite la definición y
paso de diversos parámetros que se considerarán en la
interpretación del bloque de código.

DBEVAL()

Sintaxis Array(bBloco, bFor, bWhile)


La función DBEval() permite que se analicen todos los registros
Descripción de una determinada tabla y que para cada registro se ejecute el
bloque de código definido.

AEVAL()

Sintaxis AEVAL(aArray, bBloco, nInicio, nFim)


La función AEVAL() permite que se analicen todos los elementos
Descripción de una determinada array y que para cada elemento se ejecute
el bloque de código definido.

Introducción a la Programación ADVPL I Página 85


7. FUNCIONES

La mayor parte de las rutinas escritas en programas están compuestas por un


conjunto de comandos, las cuales se repiten a lo largo de todo el desarrollo. Una
función no es más de lo que un conjunto de comandos que para utilizarse basta
llamarlos por su nombre.

Para que una función sea más flexible, al llamarla pueden pasarse parámetros con
los datos y la información que define el procesamiento de la función.

Los parámetros de las funciones descritas que utilizan el lenguaje ADVPL son
posicionales, es decir, al realizar el paso no importa el nombre de la variable, sino su
posición dentro de la lista de parámetros, lo cual permite ejecutar una función
escribiendo:

Calcula(parA, parB, parC) // Llamada de la función en una rutina

Y la función debe estar escrita de la siguiente manera:

User Function Calcula(x, y, z)

... Comandos de la Función

Return ...

En este caso, x asume el valor de parA y de parB; y z de parC.

La función también tiene la facultad de devolver una variable, pudiendo incluso ser
un Array. Para ello, se encierra la función con:

Return(campo)

De esta manera, A := Calcula(parA,parB,parC) atribuye a A el contenido de


devolución de la función Calcula.

En el ADVPL existen millares de funciones escritas por el equipo de Tecnología


20
Microsiga, por los analistas de soporte y por los propios usuarios.

Página 86 Introducción a la Programación ADVPL I


Existe un refrán que dice:

“Vale más un programador que conoce todas las funciones disponibles


en un lenguaje de lo que aquel que, siendo un genio, reinventa la rueda
a cada nuevo programa”.

En la TDN (TOTVS Developer Network) hay más de 500 funciones documentadas,


y este número tiende a aumentar exponencialmente con los nuevo procesos de
documentación que están en implantación en Tecnología e Inteligencia Protheus.

El objetivo del curso es presentar, mostrar y establecer la utilización de las


principales funciones, sintaxis y estructuras utilizadas en ADVPL.

En el ADVPL hasta los programas denominados de menú son funciones. En un


repositorio no puede haber funciones con el mismo nombre y para permitir que los
usuarios y analistas puedan desarrollar sus propias funciones sin que éstas entren en
conflicto con las que están disponibles en el entorno ERP, se implementó por medio
de la Tecnología Microsiga un tipo especial de función denominada “User Function”.

En los siguientes tópicos se detallarán los tipos de funciones disponibles en el


lenguaje ADVPL, sus formas de utilización y sus respectivas diferencias.

7.1. Tipos y alcances de funciones

En ADVPL pueden utilizarse los siguientes tipos de funciones:

; Function()
; User Function()
; Static Function()
; Main Function()

Function()

Funciones ADVPL convencionales, restringidas al desarrollo del área de


Inteligencia Protheus de Microsiga.

El interpretador ADVPL distingue los nombres de funciones del tipo Function()


hasta con diez caracteres. A partir del décimo carácter, a pesar de que el
compilador no indique ningún tipo de error, el interpretador ignorará los otros
caracteres.

Introducción a la Programación ADVPL I Página 87


Ejemplo:

// Fuente MATA100INCL.PRW
#INCLUDE "protheus.ch"

Function MATA100INCL01()

ALERT("01")
Return

Function MATA100INCL02()

ALERT("02")
Return

Al ejecutar la función MATA100INCL01() se mostrará el mensaje “01”, pero al


ejecutar la función MATA100INCL02() también se mostrará el mensaje “01”,
pues el interpretador considera el nombre de la función como “MATA100INC”.

1. Funciones del tipo Function() sólo pueden ejecutarse por medio


de los módulos del ERP.

2. Sólo podrán compilarse funciones del tipo Function() si el MP-IDE


tiene una autorización especial suministrada por Microsiga.

3. Funciones del tipo Function() son accesibles por cualquier otra


función en uso por medio de la aplicación.

User Function()

Las “User Defined Functions” o funciones definidas por los usuarios, son tipos
especiales de funciones implementadas por el ADVPL, para garantizar que
desarrollos específicos no realizados por la Inteligencia Protheus de Microsiga
superpongan las funciones estándar desarrollados para el ERP.

El interpretador ADVPL considera que el nombre de una User Function está


compuesto por el nombre definido para la función, precedido de los
caracteres “U_”. De esta manera, el interpretador tratará la User Function
XMAT100I como “U_XMAT100I”.

Página 88 Introducción a la Programación ADVPL I


1. Como ocurre la adición de los caracteres “U_” en el nombre de la
función y el interpretador sólo considera los diez primeros
caracteres de la función, para su diferenciación se recomienda
que los nombres de las User Functions sólo tengan ocho
caracteres, evitando resultados indeseables durante la ejecución
de la aplicación.

2. Funciones del tipo User Function pueden accederse por cualquier


otra función que la aplicación esté utilizando, siempre y cuando
se llamen con los caracteres “U_”, en conjunto con el nombre de
la función.

Las User Functions pueden ejecutarse a partir de la pantalla inicial del


client del ERP (Microsiga Protheus Remote), pero las aplicaciones que
pretenden poner a disposición esta opción deben tener una preparación
adicional de entorno.

Para más información, consulte en el TDN el tópico sobre preparación


de entorno y la documentación sobre la función RpcSetEnv().

Static Function()

Funciones ADVPL tradicionales, cuya visibilidad se restringe a las funciones


descritas en el mismo archivo de código fuente en el cual están definidas.

Ejemplo:

//Fuente FINA010.PRW

Function FINA010()

CriaSx1(“FIN010”)
Return

Static Function CRIASX1()


//Fuente FINA020.PRW

Function FINA020()

CriaSx1(“FIN020”)
Return

Introducción a la Programación ADVPL I Página 89


Static Function CRIASX1()

En el ejemplo anterior, existen dos funciones denominadas CRIASX1(),


definidas en archivos de código fuente distintos: FINA010.PRW y
FINA020.PRW.

La función FINA010() sólo tendrá visibilidad de la función CRIASX1(), definida


en el archivo de código fuente FINA010.PRW. Lo mismo ocurre con la función
FINA020().

Este recurso permite aislar funciones de uso exclusivo de un archivo de código


fuente, evitando la superposición o duplicación de funciones en la aplicación.

En este contexto las Static Functions() se utilizan para:

1. Estandarizar el nombre de una determinada función, que tiene la misma


finalidad, pero que su implementación puede variar de acuerdo con la
necesidad de la función principal / aplicación.

2. Redefinir una función estándar de la aplicación, adecuándola a las


necesidades específicas de una función principal / aplicación.

3. Proteger funciones de uso específico de un archivo de código fuente /


función principal.

El Entorno de desarrollo utilizado en la aplicación ERP (MP-IDE)


valida si existen Functions(), Main Functions() o User Functions() con
el mismo nombre pero en archivos de código fuente distintos,
evitando la duplicación o superposición de funciones.

Main Function()

Main Function() es otro tipo de función especial del ADVPL incorporado, para
permitir tratamientos diferentes en la aplicación ERP.

Una Main Function() tiene la característica de poder ejecutarse por medio de la


pantalla inicial de parámetros del client del ERP (Microsiga Protheus Remote),
de la misma forma que una User Function, con la diferencia de que las Main
Functions solamente pueden desarrollarse con el uso de la autorización de
compilación, determinando que su uso se restrinja a la Inteligencia Protheus
de Totvs.

En la aplicación ERP es común el uso de las Main Functions(), en las siguientes

Página 90 Introducción a la Programación ADVPL I


situaciones:

1. Definición de los módulos de la aplicación ERP: Main Function Sigaadv()

2. Definición de actualizaciones y updates: AP710TOMP811()

3. Actualizaciones específicas de módulos de la aplicación ERP: UpdateATF()

7.2. Paso de parámetros entre funciones

Los parámetros de las funciones descritas que utilizan el lenguaje ADVPL son
posicionales, es decir, al realizar el paso no importa el nombre de la variable,
sino su posición dentro de la lista de parámetros.

En complemento a esta definición pueden utilizarse dos formas distintas de


pasar parámetros a funciones descritas en el lenguaje ADVPL:

; Paso de parámetros por contenido.


; Paso de parámetros por referencia.

Paso de parámetros por contenido

El paso de parámetros por contenido es la forma convencional de definición


de los parámetros recibidos por la función llamada, en la cual la función recibe
los contenidos que la función llamadora pasa, en el orden en que se informan.

User Function CalcFator(nFator)

Local nCnt
Local nResultado := 0

For nCnt := nFator To 1 Step -1


nResultado *= nCnt
Next nCnt

Alert("El factorial de " + cValToChar(nFator) + ;


" es " + cValToChar(nResultado))

Return

Evaluando la función CalcFator() descrita anteriormente, podemos verificar que

Introducción a la Programación ADVPL I Página 91


ésta recibe como parámetro para su ejecución la variable nFator.

Con base en esta función, podemos describir dos formas de paso de


parámetros por contenido:

; Paso de contenidos directos.


; Paso de variables como contenidos.

Ejemplo 01 – Paso de contenidos directos

User Function DirFator()

Local nResultado := 0

nResultado := CalcFator(5)

El paso de contenidos directos implica en la definición explícita del valor del


parámetro, en la ejecución de la llamada de la función. En este caso se informó
el contenido 5 (numérico) como contenido para el primer parámetro de la
función CalcFator.

Como el lenguaje ADVPL trata los parámetros de forma posicional, el


contenido 5 se atribuirá directamente a la variable, definida como primer
parámetro de la función llamada, en este caso, nFator.

Por ser una atribución de parámetros por contenido, el interpretador del


lenguaje ejecuta básicamente una operación de atribución normal, es decir,
nFator := 5.

Dos características del lenguaje ADVPL hacen necesaria una


atención especial en la llamada de funciones:

1. El lenguaje ADVPL no es un lenguaje tipado, de tal manera que


las variables no tienen un tipo previamente definido, aceptando
el contenido que se les imponga por medio de una atribución.

2. Los parámetros de una función se atribuyen de acuerdo con el


orden en que dichos parámetros se definen en la llamada. No se
realiza ningún tipo de consistencia, con relación a los tipos de
contenido y obligatoriedad de parámetros en esta acción.

Página 92 Introducción a la Programación ADVPL I


Los parámetros de una función se caracterizan como variables de
alcance LOCAL a efecto de ejecución.

De esta manera, éstos no deben definirse nuevamente como LOCAL, en


el área de definición e inicio de variables, pues si esto ocurre habrá una
pérdida de los valores recibidos por la redefinición de las variables en la
función.

Si fuera necesario garantizar un contenido estándar para un


determinado parámetro, debe utilizarse el identificador ESTÁNDAR, de
acuerdo con lo detallado en el tópico “Tratamiento de valores estándar
para parámetros de funciones”.

Ejemplo 02 – Paso de variables como contenidos

User Function DirFator()

Local nResultado := 0
Local nFatorUser := 0

nFatorUser := GetFator() // Función ilustrativa en la cual el usuario informa el factor


que se utilizará.

nResultado := CalcFator(nFatorUser)

El paso de contenidos como variables implica en la utilización de variables de


apoyo para ejecutar la llamada de una función. En este caso, se informó la
variable nFatorUser, que el usuario definirá por medio de la función ilustrativa
GetFator(). El uso de variables de apoyo flexibiliza la llamada de otras
funciones, pues ellas se parametrizarán de acuerdo con las necesidades de
aquel procesamiento específico, en el cual se encuentra la función llamadora.

Como el lenguaje ADVPL trata los parámetros de forma posicional, el


contenido de la variable nFatorUser se atribuirá directamente a la variable
definida como primer parámetro de la función llamada, en este caso, nFator.

Por ser una atribución de parámetros por contenido, el interpretador del


lenguaje ejecuta básicamente una operación de atribución normal, es decir,
nFator := nFatorUser..

Introducción a la Programación ADVPL I Página 93


El paso de parámetros no necesita que las variables informadas en la
función llamadora tengan los mismos nombres de las variables
utilizadas en la definición de parámetros de la función llamada.

De esta manera, podemos tener:


User Function DirFator()
Local nFatorUser := GetFator()
nResultado := CalcFator(nFatorUser)
...
__________________________________________________________________________
Function CalcFator(nFator)
...
__________________________________________________________________________

Las variables nFatorUser y nFator pueden tener nombres diferentes,


pues el interpretador realizará la atribución de contenido con base en el
orden de los parámetros y no por el nombre de las variables.

Paso de parámetros por referencia

El paso de parámetros por referencia es una técnica bastante común en los


lenguajes de programación, la cual permite que variables de alcance LOCAL
tengan su contenido manipulado por funciones específicas, manteniendo el
control de estas variables restringido a la función que las definió y a las
funciones deseadas por la aplicación.

El paso de parámetros por referencia utiliza el concepto de que una variable es


un área de memoria y por lo tanto, pasar un parámetro por referencia no es
más de lo que, al contrario de pasar el contenido a la función llamada, pasar el
área de memoria utilizada por la variable.

Página 94 Introducción a la Programación ADVPL I


Paso de parámetros tradicional – Dos variables vs. Dos áreas de memoria

Paso de parámetros por referencia – Dos variables vs. una única área de memoria

De esta manera, la función llamada no sólo tiene acceso al contenido, sino a la


variable en si, pues el área de memoria es la variable y cualquier modificación
en ésta, será visible para la función llamadora cuando reciba la devolución de
esta función.

Introducción a la Programación ADVPL I Página 95


Tratamiento de contenidos estándar para parámetros de funciones

El tratamiento de contenidos estándar para parámetros de funciones es


bastante utilizado en las funciones estándar de la aplicación ERP, para
garantizar la correcta ejecución de estas funciones por cualquier función
llamadora, evitando situaciones de ocurrencias de errores por la falta da
definición de parámetros necesarios para la correcta utilización de la función.

El lenguaje ADVPL no obliga a que se pasen todos los parámetros


descritos en la definición de la función, pero los parámetros que no se
informen se considerarán con contenido nulo.

De esta manera el uso del identificador ESTÁNDAR permite que el


desarrollador garantice que al utilizar la función, determinados parámetros
tengan el valor con un tipo adecuado a la función.

Página 96 Introducción a la Programación ADVPL I


Ejemplo:

User Function CalcFator(nFator)

Local nCnt
Local nResultado := 0
Default nFator := 1

For nCnt := nFator To 1 Step -1


nResultado *= nCnt
Next nCnt

Return nResultado

En el ejemplo descrito, si no se informó el parámetro nFator en la función


llamadora, éste tendrá su contenido definido como 1.

Si este tratamiento no se realizara y con ello, no se informara el parámetro


nFator, ocurriría el siguiente evento de error:

Ejemplo:

User Function CalcFator(nFator)

Local nCnt
Local nResultado := 0

For nCnt := nFator To 1 Step -1 // nFator está como Nulo, por lo tanto nCnt es nulo
nResultado *= nCnt
Next nCnt // Al efectuar el Next, el interpretador realiza la acción nCnt += 1.

Return nResultado

Como el interpretador realizará la acción nCnt += 1 y el contenido de la


variable nCnt es nulo, ocurrirá el error de “type mismath on +=, expected N Æ
U”, pues los tipos de las variables involucradas en la operación son diferentes:
nCnt Æ nulo (U) y 1 Æ numérico (N).

Si se informa el parámetro que tiene la opción ESTÁNDAR, descrita en


el fuente, la línea de ESTÁNDAR no se ejecutará, manteniendo de esta
manera el contenido que la función llamadora pasó.

Introducción a la Programación ADVPL I Página 97


8. DIRECTIVAS DE COMPILACIÓN

El compilador ADVPL tiene una funcionalidad denominada procesador previo, el cual


no es más de lo que un programa que examina el programa fuente escrito en
ADVPL y ejecuta ciertas modificaciones en él, con base en las Directivas de
Compilación.

Las directivas de compilación son comandos que no se compilan, dirigiéndose al


procesador previo, el cual se ejecuta por el compilador antes de la ejecución del
proceso de compilación propiamente dicho.

Por lo tanto, el procesador previo modifica el programa fuente, entregando al


compilador un programa modificado de acuerdo con las directivas de compilación,
las cuales se inician por los caracteres “#”.

Las directivas pueden colocarse en cualquier parte del programa. Las que el lenguaje
ADVPL implementó son:

; #INCLUDE
; #DEFINE
; #IFDEF
; #IFNDEF
; #ELSE
; #ENDIF
; #COMMAND

Las directivas de compilación también se conocen como UDC – User


Defined Commands.

Directiva: #INCLUDE

La directiva #INCLUDE indica en qué archivo de extensión “CH” (estándar


ADVPL) están los UDC que se utilizarán por medio del procesador previo.

La aplicación ERP tiene diversos includes, los cuales debe utilizarse según la
aplicación que se desarrollará, lo que permitirá la utilización de recursos
adicionales definidos para el lenguaje, implementados por medio del área de
Tecnología de Totvs.

Los includes más utilizados en las aplicaciones ADVPL, desarrollados por el


ERP son:

; PROTHEUS.CH: Directivas de compilación como estándares para el

Página 98 Introducción a la Programación ADVPL I


lenguaje. Contiene la especificación de la mayoría de las sintaxis utilizadas en
los fuentes, inclusive permitiendo la compatibilidad de la sintaxis tradicional
del Clipper para los nuevos recursos implementados en el ADVPL.

El include PROTHEUS.CH también contiene la referencia a otros includes


utilizados por el lenguaje ADVPL, que complementan esta funcionalidad de
compatibilidad con la sintaxis Clipper, tales como:

o DIALOG.CH
o FONT.CH
o INI.CH
o PTMENU.CH
o PRINT.CH

La utilización include “protheus.ch”, en los fuentes desarrollados para la


aplicación ERP Protheus es obligatoria y necesaria para el correcto
funcionamiento de las aplicaciones.

; AP5MAIL.CH: Permite la utilización de la sintaxis tradicional en la


definición de las siguientes funciones de envío y recepción de e-mail:

o CONNECT SMTP SERVER


o CONNECT POP SERVER
o DISCONNECT SMTP SERVER
o DISCONNECT POP SERVER
o POP MESSAGE COUNT
o SEND MAIL FROM
o GET MAIL ERROR
o RECEIVE MAIL MESSAGE

; TOPCONN.CH: Permite la utilización de la sintaxis tradicional en la


definición de las siguientes funciones de integración con la herramienta
TOPCONNECT (MP10 – DbAcess):

o TCQUERY

; TBICONN.CH: Permite la utilización de la sintaxis tradicional en la


definición de conexiones, con la aplicación Server del entorno ERP, por medio
de las siguientes sintaxis:

o CREATE RPCCONN
o CLOSE RPCCONN
o PREPARE ENVIRONMENT
o RESET ENVIRONMENT

Introducción a la Programación ADVPL I Página 99


o OPEN REMOTE TRANSACTION
o CLOSE REMOTE TRANSACTION
o CALLPROC IN
o OPEN REMOTE TABLES

; XMLXFUN.CH: Permite la utilización de la sintaxis tradicional en la


manipulación de archivos y strings en el estándar XML, por medio de las
siguientes sintaxis:

o CREATE XMLSTRING
o CREATE XMLFILE
o SAVE XMLSTRING
o SAVE XMLFILE
o ADDITEM TAG
o ADDNODE NODE
o DELETENODE

• Los recursos de tratamiento de e-mails, integración con la herramienta


TOPCONNECT (DbAcess), preparación de entornos y manipulación de
archivos y strings del estándar XML, se abordarán en el curso de ADVPL
Avanzado.

___________________________________________________________________________

• El directorio de includes debe especificarse en el Entorno de desarrollo


del ERP Protheus (MP-IDE), para cada configuración de compilación
disponible.

Si el directorio de includes no estuviera informado o estuviera informado


incorrectamente, se mostrará un mensaje de error informando:

“No fue posible crear el archivo <caminho\nome> .ERX”

___________________________________________________________________________

• Las funciones desarrolladas para la aplicación ERP acostumbran


utilizar includes, para definir el contenido de strings y variables diversas,
utilizadas por la aplicación en diferentes idiomas. De esta forma, es
común verificar que un fuente tenga un archivo“.CH” con el mismo
nombre, lo que caracteriza este tipo de include.

Página 100 Introducción a la Programación ADVPL I


Directiva: #DEFINE

La directiva #DEFINE permite que el desarrollador cree nuevos términos para


que se utilicen en el código fuente. Este término tiene el efecto de una variable
de alcance PUBLIC, pero que solamente afecta el fuente en la cual el #DEFINE
está definido, con la característica de no permitir la modificación de su
contenido.

De esta manera, un término definido por medio de la directiva #DEFINE puede


considerarse como una constante.

Los archivos de include definidos para los fuentes de la aplicación ERP


tienen directivas #DEFINE para las strings de textos de mensajes
exhibidas para los usuarios en los tres idiomas en los que se distribuye
la aplicación: portugués, inglés y español.

Por esta razón, la aplicación ERP tiene tres repositorios distintos para
cada una de las bases de datos homologadas por Microsiga, pues cada
compilación utiliza una directiva referente a su idioma.

Directivas: #IFDEF, IFNDEF, #ELSE y #ENDIF

Las directivas #IFDEF, #IFNDEF, #ELSE y #ENDIF permiten al desarrollador crear


fuentes flexibles y sensibles a determinadas configuraciones de la aplicación
ERP.

Por medio de estas directivas, pueden verificarse parámetros del Sistema, tales
como el idioma con el cual está parametrizado y la base de datos utilizada
para almacenar y administrar la información del ERP.

De esta manera, en lugar de escribir dos o más códigos fuentes que realizan la
misma función, pero que utilizan recursos distintos para cada base de datos o
muestran un mensaje para cada uno de los idiomas tratados por la aplicación,
el desarrollador puede preparar su código fuente para que el procesador
previo lo evalúe, el cual generará un código compilado de acuerdo con el
análisis de los parámetros de entorno.

Estas directivas de compilación están normalmente asociadas a las siguientes


verificaciones de entorno:

; Idioma: verifica las variables SPANISH e ENGLISH, que la aplicación pone a


disposición. El idioma portugués se determina por excepción:

Introducción a la Programación ADVPL I Página 101


#IFDEF SPANISH
#DEFINE STR0001 “¡Hola!”
#ELSE

#IFDEF ENGLISH
#DEFINE STR0001 “Hello !!!”
#ELSE
#DEFINE STR0001 “Olá !!!”
#ENDIF

#ENDIF

A pesar de la estructura semejante al IF-ELSE-ELSEIF-ENDIF, no existe la


directiva de compilación #ELSEIF, lo que hace necesario el uso de
diversos #IFDEF para la elaboración de una estructura que sería
fácilmente solucionada con IF-ELSE-ELSEIF-ENDIF.

La aplicación ERP pone a disposición la variable de alcance PUBLIC -


__LANGUAGE, la cual contiene una string que identifica el idioma que
el Sistema está usando, cuyos contenidos posibles son:

; “PORTUGUESE”

; “SPANISH”

; “ENGLISH”

; Base de Datos: Verifica las variables AXS y TOP para determinar si la base
de datos que la aplicación está usando se encuentra en el formato ISAM (DBF,
ADS, CTREE, etc.) o si está utilizando la herramienta TOPCONNECT (DbAcess).

#IFDEF TOP

cQuery := “SELECT * FROM ”+RETSQLNAME(“SA1”)


dbUseArea(.T., "TOPCONN", TcGenQry(,,cQuery), “SA1QRY”,.T.,.T.)

#ELSE
DbSelectArea(“SA1”)

Página 102 Introducción a la Programación ADVPL I


#ENDIF

Las bases de datos estándar AS400 no permiten la ejecución de queries


en el formato SQLANSI, por medio de la herramienta TOPCONNECT
(DbAcess).

De esta manera, es necesario realizar una verificación adicional en el


#IFDEF TOP antes de ejecutar una query, que en este caso se realiza
por medio del uso de la función TcSrvType(), la cual devuelve la string
“AS/400”, cuando ésta es la base en uso.

Para estas bases debe utilizarse la sintaxis ADVPL tradicional.

Directiva: #COMMAND

La directiva #COMMAND se utiliza principalmente en los includes del lenguaje


ADVPL para realizar la traducción de comandos en sintaxis CLIPPER, para las
funciones implementadas por la Tecnología Microsiga.

Esta directiva permite que el programador defina para el compilador cómo


debe interpretarse una expresión.

Trecho del archivo PROTHEUS.CH

#xcommand @ <nRow>, <nCol> SAY [ <oSay> <label: PROMPT,VAR > ] <cText> ;


[ PICTURE <cPict> ] ; [ <dlg: OF,WINDOW,DIALOG > <oWnd> ] ;
[ FONT <oFont> ] ; [ <lCenter: CENTERED, CENTER > ] ;
[ <lRight: RIGHT > ] ; [ <lBorder: BORDER > ] ;
[ <lPixel: PIXEL, PIXELS > ] ; [ <color: COLOR,COLORS > <nClrText> [,<nClrBack>
]];
[ SIZE <nWidth>, <nHeight> ] ; [ <design: DESIGN > ] ;
[ <update: UPDATE > ] ; [ <lShaded: SHADED, SHADOW > ] ;
[ <lBox: BOX > ] ; [ <lRaised: RAISED > ] ;
=> ;
[ <oSay> := ] TSay():New( <nRow>, <nCol>, <{cText}>,;
[<oWnd>], [<cPict>], <oFont>, <.lCenter.>, <.lRight.>, <.lBorder.>,;
<.lPixel.>, <nClrText>, <nClrBack>, <nWidth>, <nHeight>,;
<.design.>, <.update.>, <.lShaded.>, <.lBox.>, <.lRaised.> )

Por medio de la directiva #COMMAND, el programador determinó las reglas


para que la sintaxis tradicional del lenguaje CLIPPER, para el comando SAY, se

Introducción a la Programación ADVPL I Página 103


convierta en la especificación de un objeto TSAY() del ADVPL.

Ejercicio
Desarrollar un programa que permita al usuario buscar un cliente, informando su
Registro Nacional de Persona Jurídica (CNPJ) y si éste existe en la base, mostrar sus
principales informaciones.

Ejercicio
Por medio de la interfaz visual desarrollada para el ejercicio anterior, desarrollar la
función genérica GetTexto(), para que se utilice en las aplicaciones del Juego Tres en
Raya y el Juego del Ahorcado.

Ejercicio
Por medio de la función AVISO(), desarrollar un programa que permita al usuario
seleccionar la opción de búsqueda del Registro Nacional de Persona Jurídica (CNPJ)
por cliente o proveedor, y si lo encuentra que muestre sus datos principales.

Ejercicio
Desarrollar una rutina que capture varios Registros Nacionales de Personas Jurídicas
(CNPJ) de clientes informados por el usuario, y verifique para cada uno de ellos si
éste existe en la base de datos. Al final, informar qué CNPJ se informaron y de
acuerdo con la selección del usuario, mostrar los datos principales de uno de estos
clientes.

Ejercicio
Por medio de la función FORMBATCH(), desarrollar una rutina que verifique si para
cada ítem de una factura de entrada existe el respectivo encabezado y si encuentra
algún ítem inconsistente, comunique esta ocurrencia al usuario que está realizando
el procesamiento.

Página 104 Introducción a la Programación ADVPL I


Ejercicio
Vamos a desarrollar una rutina que, por medio del uso de un bloque de código,
convierta la estructura de la tabla SA1, obtenida con la función DBSTRUCT(), en una
string denominada cCampo.

Introducción a la Programación ADVPL I Página 105


Módulo 03: Desarrollo de pequeñas
personalizaciones

9. ADVPL Y ERP MICROSIGA PROTHEUS

El ADVPL (Advanced Protheus Language) es un lenguaje de programación


desarrollado por Totvs, que dispone de todas las instrucciones y funciones
necesarias para el desarrollo de un sistema, independiente de su complejidad.

El Sistema Protheus, por otro lado, es una plataforma tecnológica que abarca un
Servidor de Aplicación, un Diccionario de Datos y las Interfaces para conexión con el
usuario. Es el Protheus que ejecuta el código ADVPL y el debido acceso a la base de
datos.

El Protheus se compone del ERP (que abarca, además de las funcionalidades


descritas en los capítulos anteriores, más de treinta verticales aplicadas a áreas
específicas de negocios) y por el Configurador (programa que permite
personalizar fácilmente el Sistema para las necesidades del usuario).

9.1. El Entorno Protheus

El Sistema Protheus se constituye de un conjunto de Softwares que


componen los niveles de funcionalidades básicas para los servicios de
aplicación, interfaz, base de datos y repositorio, de acuerdo con el diagrama
de la siguiente figura:

Página 106 Introducción a la Programación ADVPL I


Figura: Niveles básicos del Entorno Protheus

Para ejecutar un programa desarrollado en ADVPL, es necesario, primero que


nada, escribirlo y compilarlo. Este procedimiento se realiza por medio de la
herramienta TOTVS DevStudio del Protheus (Totvs Development Studio).

El objetivo del TOTVS DevStudio es facilitar la tarea de escribir programas: por


medio de colores, indica si la palabra escrita es una instrucción, una variable
o un comentario; organiza la biblioteca de programas en proyectos y
administra el repositorio de objetos; señala errores de sintaxis; permite el
debug (ejecución paso a paso del programa, verificando el contenido de las
variables) y suministra asistentes (modelos) de programas.

Introducción a la Programación ADVPL I Página 107


Figura: Mantenimiento en el repositorio de objetos

Después de compilar el programa, el resultado es un objeto que se carga en la


memoria quedando disponible para su ejecución por medio de la aplicación
PROTHEUS.

El objeto no es un ejecutable, es decir, no está convertido al lenguaje nativo


del equipo. Quien hace este trabajo es el Protheus Server en tiempo de
ejecución. Por ello, el Protheus Server siempre está presente en la memoria en
tiempo de ejecución, lo que permite:

; Proteger el programa fuente, evitando que se modifique indebidamente,


pues sólo los objetos se distribuyen con una ejecución más rápida en función
de la compilación en el DEV-Studio.

; Flexibilización en la plataforma de trabajo. De esta manera, un mismo


programa puede rodar en Entornos Windows, Linux o incluso en Hand Held,
restando para el Servidor Protheus la tarea de adecuación.

; Que el Sistema crezca de forma ilimitada, pues los objetos están fuera del
ejecutable.

; El uso de macrosustituciones, es decir, el uso de rutinas exteriores al


Sistema, almacenadas en archivos y que el usuario puede fácilmente
modificarlas, pues el Server también interpreta el código fuente en tiempo de
ejecución.

Página 108 Introducción a la Programación ADVPL I


Figura: Diagrama esquemático de objetos Protheus

El Repositorio de Objetos es la biblioteca de objetos de todo el Entorno


Protheus, que incluye tanto los objetos implementados para las
funcionalidades básicas del ERP como aquellos generados por los usuarios. La
siguiente figura muestra la estructura y la interconexión entre los múltiples
niveles.

Introducción a la Programación ADVPL I Página 109


Figura: Estructura de interconexión del Protheus

Ésta también muestra que los datos que se procesarán pueden estar
almacenados en bases ISAM o en Bases de Datos estándar SQL. En el primer
caso, el server se comunica directamente con los datos. En Bases SQL, la
interfaz TOPCONNECT / DBACCESS convierte los comandos de entrada y
salida, adecuándose al SQL utilizado (SQl Server Microsoft, Oracle, DB2, etc.).

Después de concluir el procesamiento del objeto llamado, éste se descarta de


la memoria, es decir, el Protheus es un Sistema que puede crecer de forma
ilimitada, pues los objetos almacenados en un repositorio prácticamente no
ocupan espacio en el HD (Hard Disk).

El Protheus es una plataforma multinivel. Entre los diversos niveles, tenemos


la interfaz de presentación al usuario (Remote), el tratamiento para las reglas
de negocio implementadas (Server), el acceso a los objetos del
repositorio (Server), el acceso a los datos disponibles a la Base de Datos
(Server o TOPCONNECT / DBACCESS ) y a su gestión de servicios WEB
(Server). En este proceso, Protheus tiene básicamente cuatro aplicaciones que
se utilizan con finalidades diferentes.

; Protheus Server / TOTVS AppServer: Responsable por la comunicación


entre el cliente, la base de datos y el RPO. El nombre del ejecutable depende
de la versión del Sistema (TOTVSAPPSERVER.EXE), cuyas plataformas ISAM
soportadas por el Protheus Server son DBF y CTREE.

; Protheus Remote / TOTVS SmartClient: Instalado en el Server o en la


estación. El nombre también depende de la versión del Sistema

Página 110 Introducción a la Programación ADVPL I


(TOTVSSMARTCLIENT.EXE).

; TopConnect / DbAccess: Responsable por la conversión de los comandos


de la base de datos, adecuándolos al SQL utilizado.

; Protheus Monitor / TOTVS Monitor: Programa de análisis que verifica


quién está usando el Sistema y permite el envío de mensajes o incluso
interrumpir conexiones (TOTVSMONITOR.EXE).

Algunos nombres se refieren a un conjunto de programas para facilitar su


identificación:

; RPO: Es el archivo binario del APO (Advanced Protheus Objects), es decir,


los objetos.

; Build: Ejecutables, DLL y el RPO completo.

; Patch: Actualizaciones específicas del RPO, aplicadas por medio del IDE.

; Update: Paquete de actualización para el repositorio (RPO), liberado


periódicamente con todas las adecuaciones y mejoras puestas a disposición
para el Sistema en un determinado período, no acumulativo, aplicadas por
medio del DEV-Studio.

La interfaz de presentación se realiza por medio del SmartClient que procesa la


parte de la estación, básicamente, pantalla y teclado. Puede estar grabado en
el Server y cargarse por medio de la red a la memoria de la estación. O, de
preferencia, debe quedar almacenado en el HD de la estación. También puede
cargarse por medio del Internet Explorer, rodando dentro del propio browser
con el SmartClient ActiveX, haciendo posible el acceso al Protheus Server por
la Internet, con las mismas funcionalidades del SmartClient, cuyo browser tiene
que soportar el uso de la tecnología ActiveX.

Si existe algún Firewall o Proxy entre el WEB Server y el Browser que accederá
al SmartClient ActiveX, estos deben configurarse para permitir el download.

Introducción a la Programación ADVPL I Página 111


9.2. Organización y configuración inicial del entorno Protheus

El Protheus ocupa una carpeta que tiene la siguiente estructura:

Figura: Estructura básica de las carpetas del Protheus

 APO: Contiene el archivo RPO, repositorio de objetos del Protheus.


 SMARTCLIENT: Reúne un conjunto de archivos ejecutables, dll y archivos
de configuración del Sistema, para hacer posible el acceso al servidor.
 APPSERVER: Reúne un conjunto de ejecutables, dll y archivos de
configuración del Sistema que conforman el servidor.
 INCLUDE: Contiene ls bibliotecas necesarias para la compilación de
programas Protheus.
 DATA: Contiene la base de datos en el caso de la versión ISAM.
 SAMPLES: Ofrece un conjunto de programas ejemplo y archivos ADVPL
estándar de Microsiga.
 SPOOL: En esta carpeta el Sistema Protheus graba los informes generados
en disco.
 SYSTEM: Contiene los archivos de menús, los archivos de configuraciones
y los archivos de personalizaciones (SX) del sistema Protheus.

Página 112 Introducción a la Programación ADVPL I


 SYSTEMLOAD: Contiene el diccionario de datos en formato TXT. En este
archivo se encuentran todos los estándar y formatos para la generación de los
archivos de configuraciones y de personalizaciones (SX), de acuerdo con la
localización de país definida por el usuario, en la entrada al Sistema.
 MY PROJECTS: Se sugiere la creación de esta carpeta para almacenar
proyectos y fuentes de las personalizaciones realizadas por el usuario.
 UPDATES: Se sugiere esta carpeta para el almacenamiento de las
actualizaciones que se aplicarán en el Sistema Protheus.

Aunque la estructura ilustrada anteriormente indica que las carpetas están


subordinadas a la carpeta PROTHEUS, es posible que algunas de éstas puedan
estar en máquinas diferentes o incluso en Entornos computacionales
diferentes.

Figura: Formas de instalación y uso del Protheus

Introducción a la Programación ADVPL I Página 113


Para ello, es necesario configurar, es decir, informar al Protheus dónde está
cada una de ellas. Este tipo de información consta en los archivos de
parámetros de configuración del Sistema (TOTVSAPPSERVER.INI y
TOTVSSMARTCLIENT.INI) que existen en las respectivas carpetas APPSERVER y
SMARTCLIENT.

Los parámetros del TOTVSAPPSERVER.INI se leen por medio del programa


TOTVSAPPSERVER.EXE, al inicio de su ejecución. El mismo procedimiento
ocurre con relación a los parámetros del TOTVSSMARTCLIENT.INI, por medio
del programa TOTVSSMARTCLIENT.EXE. La ejecución de estos dos programas
se realiza por medio de la acción del usuario, facilitada por los accesos directos
TOTVS APPSERVER y TOTVS SMARTCLIENT.

Figura: Enlaces de los parámetros de configuración

Para que se ejecuten el TOTVS AppServer y el TOTVS SmartClient, los archivos


TOTVSAPPSERVER.INI y TOTVSSMARTCLIENT.INI deben estar disponibles en
las respectivas carpetas APPSERVER y SMARTCLIENT, pues son ellos que
indican la dirección de las demás carpetas, de acuerdo con la ilustración de la
figura anterior.

El detalle de rellenado de las propiedades de los respectivos accesos directos


TOTVS AppServer y el TOTVS SmartClient se muestran a continuación. En el
acceso directo del TOTV SAppServer es necesario que se informe el parámetro
“-debug” o “-consola”.

Página 114 Introducción a la Programación ADVPL I


Propiedades de los accesos directos

c:\protheus\bin\appserver\totvsappserver.exe

Ö
Destino:
- consola
Iniciar en: c:\protheus\bin\appserver

; -Consola o -Debug

Se ejecuta como una VentanaConsola, la información recibida de las


conexiones con el TOTVS Application Server se muestran directamente en la
pantalla de la consola del TOTVS Application Server, así como también, la
información de No Conformidades.

; -Install

Si el TOTVS Application Server no se instala como un Servicio del NT, esto


puede realizarse durante la instalación, ejecutándolo con la opción de Línea de
Comando.

; -Remove

Para borrarlo de la Lista de Servicios del NT, puede ejecutarse con la opción
Línea de Comando.

c:\protheus\bin\smartclient\totvssmartcliente.exe –

Ö
Destino:
M
Iniciar en: c:\protheus\bin\smartclient

; -Q (Quiet)

Indica que el TOTVS Smart Client, no debe mostrar el Splash (Imagen de


Presentación) y la pantalla de identificación de Parámetros Iniciales, necesita
estar acompañada de la (Cláusula –P).

; -P (Main Program)

Identifica el Programa (APO) Inicial.

; -E (Environment)

Nombre de la Sección de Environment, en el (Ini del Server), que se utilizará


para definiciones generales.

Introducción a la Programación ADVPL I Página 115


; -C (Connection)

Nombre de la Sección de Conexión, que se utilizará, para la conexión al TOTVS


Application Server.

; -M (AllowMultiSession)

Permite múltiples instancias (Copias) del TOTVS Smart Client, en la misma


máquina, lo que por Estándar no se permite.

Los parámetros que configuran el local del RPO, la Base de Datos (ISAM o
SQL), los archivos de menús, configuraciones y personalizaciones del sistema
en el archivo INI son:

; SourcePath: Indica el local de origen de los objetos. Es la dirección del


Repositorio de Objetos (Ejemplo: SourcePath=C:\PROTHEUS\APO).

; RootPath: Apunta a la carpeta raíz (inicial), a partir de la cual se localizarán


los datos (en el caso de ISAM), así como también, el propio Diccionario de
Datos (Ejemplo: RootPath=C:\PROTHEUS\PROTHEUS_DATA).

; StartPath: Indica cuál es la carpeta dentro de la carpeta raíz (informada en


el parámetro RootPath) que contiene los archivos de menús, los archivos de
configuraciones y los archivos de personalizaciones (SX) del Sistema
Protheus (Ejemplo: StartPath=\SYSTEM\).

No hay necesidad de que los parámetros estén en orden en los archivos de


configuración (.ini). Además de los parámetros detallados, existen otros que
pueden indicar la versión del Sistema, el tipo de base de datos, el idioma del
país en el que se está utilizando y las máscaras de edición y configuración.

Página 116 Introducción a la Programación ADVPL I


[ENVIRONMENT]
SOURCEPATHC:\PROTHEUS\APO
ROOTPATH=
C:\MP811\PROTHEUS_DATA
STARTPATH=\ PROTHEUS\
RPODB=TOP
RPOLANGUAGE=PORTUGUESE
RPOVERSION=101
LOCALFILES=ADS
TRACE=0
LOCALDBEXTENSION=.DBF
PICTFORMAT=DEFAULT
DATEFORMAT=DEFAULT

[DRIVERS]
ACTIVE=TCP

[TCP]
TYPE=TCPIP
PORT=1234

Figura: Ejemplo de un entorno en un archivo de parámetros

En el ejemplo de la figura anterior, el rótulo [environment] describe un


conjunto de parámetros que se iniciarán en el Sistema. Los rótulos [Drivers] y
[TCP] identifican la comunicación que puede establecerse entre el Protheus
Server y el Protheus Remote. Otros entornos pueden configurarse en el mismo
archivo (TOTVSAPPSERVER.INI).

Ya el archivo de parámetros del Protheus Remote (TOTVSSMARTCLIENT.INI)


sólo contiene las configuraciones locales, básicamente la información
necesaria para iniciar y comunicarse con el Protheus Server, de acuerdo con el
ejemplo de la siguiente figura.

Introducción a la Programación ADVPL I Página 117


[CONFIG]
LASTMAINPROG=SIGACFG
LANGUAGE=1

[DRIVERS]
ACTIVE=TCP

[TCP]
SERVER=172.16.72.41
PORT=1234

Figura: Ejemplo de un archivo de configuración del remote

; Active: Indica cuál es la forma de comunicación.

; Port: Indica el número del puerto que se utilizará para la comunicación


entre el Protheus Server y el Protheus Remote. Es necesario que el puerto
utilizado en la comunicación sea el mismo entre ambos (en el
TOTVSAPPSERVER.INI y en el TOTVSSMARTCLIENT.INI). Cabe resaltar que el
puerto 80 se reserva para Internet y puede causar conflictos si se utiliza en la
comunicación del Protheus.

; Server: Apunta a la dirección del servidor que puede ser la propia máquina
(localhost) o el nombre de la máquina (Server= Servidor_01) o incluso una
dirección IP (ejemplo Server=172.16.72.41).

Ejemplo:

El parámetro Server=172.16.72.41 en el archivo TOTVSSMARTCLIENT.INI indica al


Protheus Remote la dirección de la máquina en la cual está funcionando el Protheus
Server.

Página 118 Introducción a la Programación ADVPL I


9.3. El Configurador del Protheus

9.3.1. Funcionalidades Abordadas

El objetivo de este tópico no es abarcar toda la estructura y recursos del


módulo Configurador de la aplicación ERP, sino permitir la realización de
tareas de configuración simple que serán necesarias en el desarrollo de
pequeñas personalizaciones.

Con enfoque en este objetivo, se detallarán las siguientes operaciones:

; Configuración y creación de nuevas tablas en el Diccionario de Datos.


; Actualización de las estructuras del Diccionario de Datos.
o Tablas del sistema
o Validaciones de campos
o Índices de tablas
o Disparadores de campos

Para contextualizar la estructura de la aplicación ERP en el siguiente tópico se


detalla la forma como las tablas de datos del Sistema están divididas entre los
diversos módulos que conforman el Sistema Protheus.

9.3.2. Estructuras básicas de la aplicación ERP Protheus

Archivos de configuración del sistema

Archivo Descripción
SIGAMAT Archivo de empresas y sucursales del sistema
SIGAPSS Archivo de usuarios, grupos y contraseñas del sistema
SIX Índices de los archivos
SX1 Preguntas y respuestas
SX2 Mapeo de tablas
SX3 Diccionario de datos
SX4 Agenda del Schedule de procesos
SX5 Tablas
SX6 Parámetros
SX7 Disparadores de interfaz
SX8 Fuera de uso
SX9 Vinculación entre tablas
SXA Carpetas de registro apuntadas en el SX3
SXB Consulta por medio de la tecla F3 (Consulta Estándar)
SXD Control del Schedule de procesos
SXE Secuencia de documentos (+1)
SXF Secuencia de documentos (Próximo)
SXG Tamaño estándar para campos apuntado por el SX3
SXK Respuesta de Preguntas (SX1) por usuarios
Control de LOG por tabla
SXO

Introducción a la Programación ADVPL I Página 119


SXP Historial de Logs registrados en el SXO
Archivo de filtros inteligentes de la mbrowse (contiene la
SXQ
información necesarias para la creación del filtro).
Archivo de vinculación entre programa y filtro
SXR (el Protheus lo utiliza internamente para verificar en qué
programas se utilizarán los filtros).
Archivo de programas (se utiliza en la validación para
SXS
mostrar/inhibir los filtros en la ejecución de la mbrowse).
Tabla de usuarios (contiene la información de los usuarios
SXT
que podrán utilizar los filtros de la mbrowse).
Archivo de vinculación entre los entes (tablas) y las
SXOffice
consultas TOII.

Entornos y tablas

En la aplicación PROTHEUS, las tablas de datos pueden tener una estructura


más sencilla y económica, con tablas en DBF/ADS, del fabricante Extended
System o CTREE del fabricante FAIRCOM o una estructura más robusta y
compleja, con bases SQL (SQLSERVER de Microsoft, ORACLE, DB II de IBM,
SYBASE, MYSQL, POSTGREE, etc.).

En el caso del SQL, el acceso se realiza por medio del TOPCONNECT /


DBACESS, que convierte los comandos del ADVPL a este entorno.

Para permitir una utilización adecuada de las tablas de datos del Sistema por
cada uno de los Entornos de la aplicación ERP, las tablas se dividieron en
grupos denominados “familias”. Cada módulo puede utilizar una o más
familias de tablas específicas para sus actividades y además, compartir
información con otros módulos, por medio de de familias comunes a todas las
operaciones realizadas en el Sistema.

La siguiente tabla muestra algunos de los módulos que conforman la


aplicación ERP PROTHEUS actualmente:

Entorno Identificación
SIGAATF ACTIVO FIJO
SIGACOM COMPRAS
SIGACON CONTABILIDAD
SIGAEST STOCK Y COSTOS
SIGAFAT FACTURACIÓN
SIGAFIN FINANCIERO
SIGAFIS LIBROS FISCALES
SIGAPCP PLANIFICACIÓN Y CONTROL DE LA PRODUCCIÓN
SIGAGPE GESTIÓN DE PERSONAL
SIGAFAS FACTURACIÓN DE SERVICIOS
SIGAVEI VEHÍCULOS
SIGALOJA CONTROL DE TIENDAS/AUTOMATIZACIÓN
SIGATMK CALL CENTER
SIGAOFI TALLERES
SIGAPON RELOJ REGISTRADOR ELECTRÓNICO
SIGAEIC EASY IMPORT CONTROL

Página 120 Introducción a la Programación ADVPL I


Entorno Identificación
SIGATCF TERMINAL
SIGAMNT MANTENIMIENTO DE ACTIVOS
SIGARSP RECLUTAMIENTO Y SELECCIÓN DE PERSONAL
SIGAQIE INSPECCIÓN DE ENTRADA – CALIDAD
SIGAQMT METODOLOGIA – CALIDAD

El nombre de cada tabla en el Protheus se constituye de seis dígitos, los cuales


se utilizan para formar la siguiente representación:

F X X E E 0

Introducción a la Programación ADVPL I Página 121


En el cual:

F SF X El primer dígito representa la familia, el segundo dígito


puede utilizarse para detallar aún más la familia
especificada en el primer nivel (subfamilia) y el tercer
dígito es la numeración secuencial de las tablas de la
familia, iniciando en “0” y finalizando en “Z”.
E E 0 Los dos primeros dígitos identifican a qué empresa están
vinculadas las tablas, tomando en cuenta que la
información de la sucursal está incluida en los datos de la
tabla.
El último dígito es fijo en “0”.

La siguiente tabla muestra algunas de las principales familias de tablas


utilizadas por la aplicación ERP Protheus:

Familia Descripción
Tablas pertenecientes al sistema básico, también denominado
S -
Classic
Archivos de entes compartidos entre los Entornos (Clientes,
S A
Proveedores, Bancos, entre otros)
Archivos de los Entornos de Materiales (Productos, Saldos entre
S B
otros)
Archivos de movimientos diversos, utilizados por los entornos de
S C Materiales (Solicitud al Depósito, Solicitud de Compras, Pedido de
Compras, Pedido de Ventas, Órdenes de Producción, entre otros)
Archivos de movimientos de stock (Ítems de facturas de entrada y
S D
salida, movimientos internos de stock entre otros)
S E Archivo y movimientos del entorno Financiero
Archivos y Movimientos Fiscales (Encabezados de la facturas de
S F entrada y salida, archivo de tipos de entrada y salida, libros
fiscales, etc.)
S G Archivos del Entorno de Planificación y Control de Producción
S H Movimientos del Entorno de Planificación y Control de Producción
S I Archivos y movimientos del Entorno Contable (descontinuado)
S N Archivos y movimientos del Entorno Activo Fijo
S R Archivos y movimientos del Entorno Gestión de Personal
S X Tablas de configuración del sistema
S Z Tablas libres para utilización y proyectos específicos en clientes
A - Gestión de Proyectos
C - Contabilidad de Gestión
C T Contabilidad de Gestión
C V Contabilidad de Gestión
C W Contabilidad de Gestión
D - Transportadoras y derivados
E - Comercio exterior y derivados
G - Gestión Hospitalaria

Página 122 Introducción a la Programación ADVPL I


Familia Descripción
J - Gestión Educativa
N - Servicios Públicos
P - Reservado para proyectos de la fábrica de software
Q - Calidad y derivados
R - Recursos Humanos y derivados
T - Plan de Salud
W - Workflow
Z - Tablas libres para utilización y proyectos específicos en clientes en
adición a la familia SZ.

Índices

Cada tabla del Sistema tiene sus índices definidos en el archivo de


configuración SIX, el cual puede actualizarse por medio del módulo
Configurador.

Los archivos de índices de las tablas de Sistema se crearán de acuerdo con la


base de datos utilizada (ISAM o conexión por TOPCONNECT).

Para las bases de datos ISAM se generarán archivos con la misma


nomenclatura de la tabla de datos, pero con una extensión diferente
(actualmente .CDX). Si se utilizara una base de datos, cada índice tendrá una
numeración secuencial en función del nombre de la tabla original.

Las especificaciones de las claves de índices de cada una de las tablas está
disponible en el archivo de sistema SIX y la clave única de la tabla utilizada
para la base de datos está descrita en la tabla SX2.

Menús

Cada módulo de la aplicación ERP tiene un menú estándar con todas las
funcionalidades disponibles para el Entorno, el cual se define por medio de la
sintaxis XML (archivos .XNU).

Los menús tienen una estructura estándar que permite al usuario localizar e
identificar fácilmente cada una de las funcionalidades ofrecidas por el Entorno.

9.3.3. Cómo acceder al módulo Configurador

Para ejecutar el módulo Configurador es necesario que la aplicación Protheus


Server esté en ejecución y por medio de la aplicación Protheus Remote debe
informarse como programa inicial la opción SIGACFG.

Introducción a la Programación ADVPL I Página 123


Figura: Parámetros de inicio del Sistema

Después de la confirmación, se realiza la validación del acceso de acuerdo con


la siguiente pantalla:

Figura: Validación de acceso

Página 124 Introducción a la Programación ADVPL I


Figura: Confirmación del acceso al módulo Configurador

Inmediatamente después de la confirmación del usuario y la contraseña con


derecho de administrador, se mostrará la pantalla inicial del configurador, de
acuerdo con la siguiente figura:

Figura: Interfaz principal del módulo Configurador

Introducción a la Programación ADVPL I Página 125


9.4. Funcionalidades del Configurador

La personalización de un Sistema como el Protheus consiste en adaptar el


Sistema con el propósito de atender las necesidades del cliente.

La flexibilidad de un Sistema, es decir, su capacidad de adaptarse


(polimorfismo, aquel que asume varias formas) es una de las más importantes
características de una solución ERP.

Las funcionalidades tratadas por el Configurador definen la flexibilidad del ERP


Protheus. Flexibilizar sin estandarizar, es decir, todo lo que se personalizó
permanecerá válido, a pesar del desarrollo de nuevas versiones.

Figura: Principales funcionalidades del módulo Configurador

El Configurador es el programa básico para el proceso de personalización del


Protheus, por medio de la modificación de las tablas de la familia SX. En éstas,
el usuario o analista de soporte responsable por la implantación configura la
información que los otros entornos del Sistema utilizarán.

Esta información tiene desde simples parámetros hasta complejas expresiones


y comandos que se interpretan en tiempo de ejecución.

En los próximos tópicos se abordarás las funcionalidades de personalización


disponibles en el Entorno Configurador, relevantes para el objetivo de
desarrollo de pequeñas personalizaciones para la aplicación ERP.

Página 126 Introducción a la Programación ADVPL I


9.4.1. Diccionario de Datos de la aplicación ERP

La idea del Diccionario de Datos es permitir que el usuario pueda incluir o


inhibir campos o incluso modificar las propiedades de los campos existentes.
También puede crear nuevas tablas. Es decir, en lugar de que los programas
tengan los campos definidos e su código original, leen el Diccionario en
tiempo de ejecución, elaborando arrays con las propiedades de cada uno. A
partir de ello, su utilización es usual, por medio de la utilización de funciones
del ADVPL que tornan el trabajo del desarrollador transparente para esta
arquitectura.

El objetivo del Diccionario de Datos es permitir que el propio usuario cree


nuevas tablas o modifique los campos en las tablas existentes, en lo que se
refiere a su uso, orden de presentación, leyenda (en los tres idiomas),
validación, help, obligatoriedad de rellenado, inicio, etc.

Figura: Conjunto de paquetes que conforman el Diccionario de Datos

Introducción a la Programación ADVPL I Página 127


9.4.2. Adición de tablas al Diccionario de Datos

Procedimiento

1. Para agregar una tabla al diccionario de datos de una empresa, seleccione a


continuación, la opción Diccionario de Datos de la empresa que se actualizará.
(árbol de opciones de la parte izquierda de la interfaz visual del Administrador
de Bases de Datos).

2. Después de seleccionar la opción Diccionario de Datos se mostrarán las


tablas registradas en el archivo de sistema SX2.

Figura: Conjunto de tablas registradas en el SX2

3. Después de la visualización de las tablas registradas en el SX2 de la

empresa seleccionada, utilice el botón Incluir ( ). Al utilizar esta opción se


mostrará la pantalla para definición de los datos referentes a la nueva tabla
que se creará:

Página 128 Introducción a la Programación ADVPL I


Figura: Archivo de una nueva tabla

4. Realice el rellenado de la información solicitada de acuerdo con las


siguientes orientaciones y al finalizar, confirme el registro de la nueva tabla

con el botón Confirmar ( ).

Orientaciones para el registro de una nueva tabla

; El dominio SZ1 a SZZ (considerando todos los números y todas las letras en
el último byte) se reserva para datos exclusivos del usuario, pues el Sistema no
utilizará este intervalo. Si fuera necesario el dominio Z00 a ZZZ, también puede
emplearse para desarrollos específicos del cliente.

No deben crearse tablas específicas de clientes con cualquier otra


nomenclatura, porque puede afectar directamente un proceso de
actualización futuro.

; El nombre de la tabla se rellena automáticamente, agregando 990. Este


dato se refiere a la empresa 99 (Prueba Matriz) la cual se está agregando a la
tabla.

; El Path se refiere a la carpeta que incluirá efectivamente los datos de las


tablas, cuando sea ISAM. Las versiones con base de datos relacional no se

Introducción a la Programación ADVPL I Página 129


utilizan. Esta carpeta se creará dentro de la carpeta indicada en la
configuración del Sistema como ROOTTPATH.

; El modo de acceso compartido indica que el Sistema permitirá el uso


simultáneo de la tabla por dos o más sucursales. Si se comparte, el campo
Sucursal queda en blanco. Si es exclusivo, se graba el código de la sucursal
activa y sólo ésta tiene acceso al registro.

; Después de la confirmación, la tabla creada forma parte del archivo del


Diccionario de Datos, que sólo contiene el campo SUCURSAL, creado como
estándar por la funcionalidad del módulo.

9.4.3. Adición de campos a las tablas del Diccionario de Datos

Procedimiento

1. Para agregar un campo a una tabla del diccionario de datos de una


empresa, seleccione a continuación, la opción Diccionario de Datos de la
empresa que se actualizará. (árbol de opciones de la parte izquierda de la
interfaz visual del Administrador de Bases de Datos).

2. Después de seleccionar la opción Diccionario de Datos se mostrarán las


tablas registradas en el archivo de sistema SX2.

Página 130 Introducción a la Programación ADVPL I


Figura: Conjunto de tablas registradas en el SX2

3. Después de la visualización de las tablas registradas en el SX2 de la


empresa seleccionada, localice y seleccione la tabla que se actualizará y

utilice el botón Editar ( ). Al utilizar esta opción, se mostrará la pantalla


de mantenimiento de campos de la tabla seleccionada:

Figura: Estructura de una tabla registrada en el Sistema

4. Seleccione la opción Campos ( ), para que se muestren los


campos disponibles para la tabla en el archivo de sistema SX3.

Introducción a la Programación ADVPL I Página 131


Figura: Estructura de campos de una tabla registrada en el Sistema

5. Después de la visualización de los campos registrados en el SX3 de la tabla

seleccionada, utilice la opción Incluir ( ). Al utilizar esta opción se


mostrará la pantalla para definición de los datos referentes al nuevo campo
que se creará:

Página 132 Introducción a la Programación ADVPL I


Figura: Datos para parametrización de un nuevo campo en el Sistema

5. Realice el rellenado de la información solicitada de acuerdo con las


siguientes orientaciones y al finalizar, confirme el registro de la nueva tabla

con el botón Confirmar ( ).


6. Confirme las actualizaciones para la tabla seleccionada con el botón

Confirmar ( ).

7. Actualice las configuraciones del Sistema con el botón Actualizar ( ).

Introducción a la Programación ADVPL I Página 133


Figura: Actualización de los datos del Sistema

Orientaciones para el registro de un nuevo campo

1. Las propiedades definidas en el Diccionario de Datos (SX3) son las siguientes:

; Nombre del campo: Todos los campos tienen como prefijo el propio
nombre de la tabla y para las tablas de la familia “S”, el prefijo del campo se
compone solamente de los dos próximos dígitos. En el caso de las otras tablas,
el prefijo del campo será los tres dígitos identificadores de la tabla.

; Tipo de campo: Indica si es carácter, numérico, lógico, data o memo.


Lógicamente, el cambio de tipo de campo debe realizarse con mucho cuidado,
porque si tenemos un campo numérico usado en cálculos que se modifica a
carácter, sin duda ocurrirá un error.

; Tamaño del campo: Aquí también es necesario tomar cierto cuidado al


modificarlo, porque podremos tener interrupciones en informes y consultas en
las que hay espacio para contenidos mayores al original.

; Formato de edición: Define cómo aparece el campo en las pantallas y en


los informes.

; Contexto: Puede ser real o virtual. El contexto virtual sólo crea el campo
en la memoria y no en la tabla almacenada en el disco. Esto es necesario
porque los programas de registro y de consulta genérica muestran solamente
una tabla por cada vez. De esta manera, si queremos mostrar un campo de
otra tabla, o incluso, el resultado de un cálculo, sin que dicha información

Página 134 Introducción a la Programación ADVPL I


ocupe espacio físico en HD, utilizamos el contexto virtual. Los campos virtuales
generalmente se alimentan por disparadores.

; Propiedad: Indica si el usuario puede modificar un campo. Ejemplo: los


saldos generalmente no pueden, porque quien cuida de esta tarea son los
programas.

2. Otras características que deben observarse en la configuración del campo:

Solapa: Campo

; El campo Decimal sólo se solicitará para los campos de tipo numérico.

; El formato “!” indica que el carácter siempre será mayúsculo, independiente


de la acción del usuario. El formato “@!” indica que esta característica se
20
extiende por todo el campo.

; El contexto real indica que el campo existirá efectivamente en la base de


datos y el contexto virtual significa que el campo solamente existirá en el
diccionario de datos y no físicamente.

; La propiedad modificar indica que el campo puede modificarse.

; En esta ventana, los datos están clasificados en seis carpetas con carpetas
con objetivos de rellenado bien específicos:

Solapa: Información

; Contiene la información a respecto de los títulos.

; Título: Es la leyenda que aparece en las pantallas/informes. Hay, inclusive,


tres campos para esta finalidad: en portugués, español e inglés. Esta propiedad
puede modificarse cuando se desee, porque no interfiere en ningún
procesamiento.

; Descripción y Help: Son propiedades que tiene como objetivo documentar


el campo.

Solapa: Opciones

; Contiene los datos que facilitan la digitación.

Introducción a la Programación ADVPL I Página 135


Solapa: Validaciones

; Representan las reglas de validación del campo.

; Validaciones: En esta propiedad, se escribe una función de validación del


campo que está en digitación. Existe un conjunto de funciones disponibles en
el ADVPL apropiadas para este caso.

; Todas las validaciones informadas se ejecutarán cuando se rellene el propio


campo. Una validación puede ser una expresión lógica o una función de
usuario que devuelve un valor lógico Verdadero o Falso. El sistema sólo
permitirá el avance para el próximo campo cuando el rellenado respectivo
resulte Verdadero, en la expresión o en la devolución de la función.

Solapa: Uso

; Describe la forma de utilización del campo.

Solapa: Módulos

; Lista todos los módulos en el que se utilizará el campo.

9.4.4. Adición de índices para las tablas del Diccionario de Datos

De acuerdo con lo mencionado anteriormente, en el Entorno Protheus una


tabla puede tener varios índices, los cuales se generarán de acuerdo con la
base de datos configurada para el Sistema.

Los índices del Sistema ayudan en la selección y obtención de información de


la base de datos, además de determinar el orden de presentación de los
registros de una tabla en consultas e informes.

Procedimiento

1. Para agregar un índice a una tabla del diccionario de datos de una empresa,
seleccione a continuación, la opción Diccionario de Datos de la empresa que
se actualizará. (árbol de opciones de la parte izquierda de la interfaz visual del
Administrador de Bases de Datos).

2. Después de seleccionar la opción Diccionario de Datos se mostrarán las


tablas registradas en el archivo de sistema SX2.

Página 136 Introducción a la Programación ADVPL I


Figura: Conjunto de tablas registradas en el SX2

3. Después de la visualización de las tablas registradas en el SX2 de la


empresa seleccionada, localice y seleccione la tabla que se actualizará y utilice

el botón Editar ( ). Al utilizar esta opción, se mostrará la pantalla de


mantenimiento de campos de la tabla seleccionada:

Introducción a la Programación ADVPL I Página 137


Figura: Estructura de una tabla registrada en el Sistema

4. Seleccione la opción Índices ( ), para que se muestren los


índices disponibles para la tabla en el archivo de sistema SIX.

Figura: Índices disponibles para la tabla en el archivo de sistema SIX

5. Después de la visualización de los campos registrados en el SIX para la

tabla seleccionada, utilice la opción Incluir ( ). Al utilizar esta opción se


mostrará la pantalla para definición de los datos referentes al nuevo índice que
se creará:

Figura: Adición de un índice para una tabla

6. Realice el rellenado de la información solicitada de acuerdo con las


siguientes orientaciones y al finalizar, confirme el registro del nuevo índice para la

Página 138 Introducción a la Programación ADVPL I


tabla, con el botón Confirmar ( ).

7. Confirme las actualizaciones para la tabla seleccionada con el botón

Confirmar ( ).

8. Actualice las configuraciones del Sistema con el botón Actualizar ( ).

Figura: Actualización de los datos del Sistema

Introducción a la Programación ADVPL I Página 139


Orientaciones para el registro de un nuevo índice

; El Nickname es una identificación complementaria del índice, el cual puede


utilizarse para ayudar al desarrollador en la utilización de este orden en una
aplicación, la cual puede ser estándar del Sistema o específica de un cliente.

; Para seleccionar los campos registrados en la tabla, puede utilizarse el

botón Campos ( ). Esta facilidad rellena, automáticamente, los campos de


descripción.

; El campo relativo a la sucursal siempre forma parte de los índices, con


excepción del SM2, para que los registros en las tablas estén agrupados por
sucursales, independientemente de que esta tabla se comparta entre las
sucursales.

; Una tabla podrá tener varios índices registrados en el Diccionario de Datos.


Sin embargo, en determinado momento, uno de ellos ofrecerá acceso al
registro. Los programación de la aplicación puede modificar este orden en
tiempo de ejecución, por medio del comando DBSetOrder(), o mediante la
definición de un orden específico en la utilización de queries para acceder a
los datos directamente a la base de datos de Entornos TOPCONNECT
(DbAcess).

9.4.5. Adición de disparadores para los campos de las tablas del


Sistema

Procedimiento

1. Para agregar un disparador a un campo de una tabla del diccionario de


datos de una empresa, seleccione a continuación, la opción Diccionario de
Datos de la empresa que se actualizará. (árbol de opciones de la parte
izquierda de la interfaz visual del Administrador de Bases de Datos).

2. Después de la selección de la opción Disparadores se mostrarán los ítems


registrados en el archivo de sistema SX7.

Página 140 Introducción a la Programación ADVPL I


Figura: Conjunto de disparadores registrados en el SX7

3. Después de la visualización de los disparadores registrados en el SX7 de la

empresa seleccionada, utilice el botón Incluir ( ) para realizar el registro


de un nuevo disparador en el Sistema:

Figura: Datos para el registro de un nuevo disparador en el Sistema

4. Realice el rellenado de la información solicitada de acuerdo con las


siguientes orientaciones y al finalizar, confirme el registro del nuevo

disparador de sistema con el botón Confirmar ( ).

Introducción a la Programación ADVPL I Página 141


Orientaciones para el registro de un nuevo disparador

; Puede haber varios disparadores para el mismo campo. El orden de


ejecución se determinada por el campo Secuencia.

; Los tipos de Disparador Primario, Extranjero y de Posicionamiento definen


si el Contradominio es un campo de la misma tabla, de otra tabla o si el
disparador debe realizar un posicionamiento, respectivamente.

; La regla puede ser una expresión que resulta en un valor que se rellenará
en el Contradominio.

; El posicionamiento igual a Sí indica que se ejecutará un comando de


búsqueda del registro de acuerdo con la clave indicada.

; El Alias, el Orden y la Clave describen la tabla involucrada en el disparador,


su índice y la clave para que la funcionalidad se marque en el registro
adecuado.

Página 142 Introducción a la Programación ADVPL I


9.4.6. Creación de Tablas Genéricas

Procedimiento

1. Para agregar una tabla genérica, seleccione los menús Entorno, Archivos,
Tablas.

2. Después de la selección de la opción Tablas se mostrarán los ítems


registrados en el archivo de sistema SX5.

Figura: Conjunto de Tablas registradas en el SX5

3. Después de la visualización de las tablas registradas en el SX5 de la

empresa seleccionada, utilice el botón Incluir ( ) para realizar el registro


de una nueva tabla en el Sistema:

Introducción a la Programación ADVPL I Página 143


Figura: Datos para el registro de una nueva tabla en el Sistema

4. Realice el rellenado de la información solicitada de acuerdo con las


siguientes orientaciones y al finalizar, confirme el registro de la nueva tabla del

sistema con el botón Confirmar ( ).

9.4.7. Creación de Parámetros

Procedimiento

1. Para agregar un Parámetro, seleccione los menús Entorno, Archivos,


Parámetros.

2. Después de la selección de la opción Tablas se mostrarán los ítems


registrados en el archivo de sistema SX6.

Figura: Conjunto de Parámetros registrados en el SX6

Página 144 Introducción a la Programación ADVPL I


3. Después de la visualización de los Parámetros registrados en el SX6 de la

empresa seleccionada, utilice el botón Incluir ( ) para realizar el registro


de una nueva tabla en el Sistema:

Figura: Datos para el registro de un nuevo parámetro en el Sistema

4. Realice el rellenado de la información solicitada de acuerdo con las


siguientes orientaciones y al finalizar, confirme el registro del nuevo Parámetro

de sistema con el botón Confirmar ( ).

Introducción a la Programación ADVPL I Página 145


10. TOTVS DEVELOPMENT STUDIO

La herramienta TOTVS Development Studio es un programa que forma parte del


Protheus y permite el trabajo de edición, compilación y depuración de programas
escritos en ADVPL.

Proyecto

Para compilarse un programa debe vincularse a un proyecto. Generalmente,


programas que forman parte de un determinado módulo o entorno están en
un mismo proyecto.

La vinculación de los programas a un proyecto se realice por medio de los


archivos del tipo PRW. En realidad, un proyecto puede constituirse de uno o
más archivos de este tipo, que por su parte, pueden tener una o más
funciones, de acuerdo con lo que ilustra el siguiente diagrama:

Figura: Representación de la estructura de un proyecto en el DEV-Studio

Página 146 Introducción a la Programación ADVPL I


Compilación

Después de agruparse y agregarse a un proyecto sin incidencias de errores de


código, el objeto resultante se registrará en el RPO (Repositorio de Objetos) y
podrá utilizarse por medio de la aplicación ERP.

La compilación de los ítems de un proyecto puede realizarse individualmente,


por grupo de fuentes (carpetas) o incluso seleccionándolo por entero. Cada
uno de los fuentes se procesará y compilará por separado, permitiendo la
visualización del progreso de la operación y de los mensajes de aviso
(warnings) o errores (critical errors) en la solapa Mensajes.

Ejecución

Para que se utilicen los objetos compilados y disponibles en RPO, deben


observarse las siguientes reglas:

; Si el programa no manipula archivos, puede llamarse directamente del


DEV-Studio (nombre al lado derecho de la barra de herramientas).

; Si el programa manipula tablas hay dos opciones:

 Agregar el programa en el menú de uno de los Entornos y ejecutarlo por


medio del Remote.
 Realizar la preparación del Entorno en la propia rutina, permitiendo que
se ejecute directamente por el DEV-Studio.

; No se puede compilar un programa con el Remote y el Monitor abiertos,


aunque este indique que los finalizó porque estaban abiertos.

Análisis y depuración de errores

Para identificar las causas de errores, la herramienta DEV-Studio tiene diversos


recursos que ayudan al DEBUG.

La acción de DEBUG necesita que el programa se ejecute a partir del DEV-


Studio y es necesario seguir las siguiente reglas:

; Definir y marcar los puntos de parada más adecuados para análisis del
fuente.

; Ejecutar la rutina por medio del DEV-Studio, seleccionando su nombre


directamente, o el módulo que contiene la opción o la acción que la ejecutará.

; A partir del momento en que el DEV-Studio parar el procesamiento en uno


de los puntos de parada especificados previamente, pueden utilizarse las

Introducción a la Programación ADVPL I Página 147


ventanas de visualización, disponibles en el DEV-Studio:

 Variables Locales
 Variables Privates
 Variables Publics
 Variables Statics
 Ventana de la Watchs
 Ventana de Tablas y Campos
 Grupo de Llamadas

; Por medio de la Ventana de Watchs es posible determinar qué variables


deben mostrarse.

; Em el grupo de llamadas se verifica la secuencia de llamadas de las


funciones.

; En la carpeta de Comandos es posible, mientras el programa esté en pausa,


escribir cualquier comando y al pulsar Enter éste se ejecutará, permitiendo
buscar palabras y expresiones en el propio fuente o en cualquier fuente
almacenado en el HD.

; Al parar se puede continuar el programa hasta el próximo punto de parada,


si hay un otro definido, o ejecutar la rutina línea por línea.

Interfaz de la aplicación

Por ser un entorno integrado de desarrollo, el DEV-Studio proporciona todas


estas facilidades, por medio de una interfaz única como ilustra la siguiente
figura:

Página 148 Introducción a la Programación ADVPL I


Figura: Interfaz principal del TOTVS Development Studio

; El DEV-Studio muestra, al inicio de la pantalla, un conjunto de opciones de


menú y una serie de botones que facilitan su manipulación.

; En la pantalla central se muestra el código de las funciones en ADVPL. En la


parte inferior se muestran algunas carpetas que facilitan la ejecución de
comandos, exhibición de contenidos de variables y mensajes, así como
también, los datos sobre el proyecto.

Introducción a la Programación ADVPL I Página 149


Desarrollo de pequeñas
personalizaciones

11. ACCESO Y MANIPULACIÓN DE BASES DE DATOS EN


ADVPL

Como el lenguaje ADVPL se utiliza en el desarrollo de aplicación para el sistema ERP


Protheus, debe tener recursos que permitan el acceso y manipulación de
información, independientemente de la base de datos para la cual se configura el
Sistema.

De esta manera, el lenguaje tiene dos grupos de funciones distintos para actuar con
las bases de datos:

; Funciones de manipulación de datos genéricos.


; Funciones de manipulación de datos específicos para entornos TOPCONNECT /
DBACCESS.

Funciones de manipulación de datos genéricos

Las funciones de manipulación de datos, dichos como genéricos, permiten que


una aplicación ADVPL se escriba de la misma manera, independientemente de
si la base de datos configurada para el sistema ERP es del tipo ISAM o
estándar SQL.

Inicialmente, muchas de estas funciones se heredaron del lenguaje CLIPPER y


por medio de nuevas implementaciones del área de Tecnología de Microsiga
se mejoraron y adecuaron a las necesidades del ERP. Por esta razón es posible
encontrar en documentaciones del lenguaje CLIPPER información sobre
funciones de manipulación de datos utilizados en la herramienta ERP.

Entre las mejoras implementadas por el área de Tecnología de Microsiga,


podemos mencionar el desarrollo de nuevas funciones, como por ejemplo, la
función MsSeek(), versión de Microsiga para la función DbSeek() y la
integración entre la sintaxis ADVPL convencional y la herramienta de acceso a
la base datos en el estándar SQL – TOPCONNECT (DbAcess).

La integración entre la aplicación ERP y la herramienta TOPCONNECT, permite


que las funciones de acceso y manipulación de datos escritos en ADVPL se
interpreten y conviertan a una sintaxis compatible con el estándar SQL ANSI y
de esta manera, aplicados a los SGDB (Sistemas Administradores de Bases de
Datos) con su sintaxis nativa.

Página 150 Introducción a la Programación ADVPL I


Funciones de manipulación de datos para Entornos TOPCONNECT /
DBACCESS.

Para facilitar el acceso y poner a disposición en el Entorno ERP las


funcionalidades que utilicen de forma más adecuada los recursos de los SGDB
homologados para el Sistema, se implementaron funciones de acceso y
manipulación de datos específicos para Entornos TOPCONNECT/DBACCESS.

Estas funciones permiten que el desarrollador ADVPL ejecute comandos en


sintaxis SQL, directamente de un código fuente de la aplicación, poniendo a
disposición recursos como ejecución de queries de consulta, llamadas de
procedures y comunicación con otras bases de datos por medio de ODBC.

Las funciones específicas para Entornos TOPCONNECT se abordarán en


el material de ADVPL Avanzado.

11.1. Diferencias y compatibilizaciones entre bases de datos

Como la aplicación ERP puede configurarse para utilizar diferentes tipos de


bases de datos es importante mencionar las principales diferencias entre estos
recursos, lo que puede determinar la forma como el desarrollador optará por
escribir su aplicación.

Acceso a datos e índices

En el acceso a información, en bases de datos del estándar ISAM, siempre se


leen los registros enteros, mientras en el SQL sólo se pueden leer los campos
necesarios en aquel procesamiento.

El acceso directo se realiza por medio de índices que son tablas paralelas a las
tablas de datos y que tienen la clave y la dirección del registro, de forma
análoga al índice de un libro. Para cada clave se crea un índice propio.

En las bases de datos estándar ISAM los índices se almacenan en un único


archivo del tipo CDX, ya en las bases de datos estándar SQL cada índice se
crea con una numeración secuencial, con base en el nombre de la tabla al cual
está relacionado.

Cada vez que se incluye o modifica un registro se actualizan todos los índices,
lo que hace necesario planificar adecuadamente cuáles y cuántos índices se
definirán para una tabla, pues una cantidad excesiva puede comprometer el

Introducción a la Programación ADVPL I Página 151


desempeño de estas operaciones.

Debe considerarse la posibilidad de utilización de índices temporales para


procesos específicos, los cuales se crearán en tiempos de ejecución de la
rutina. Este factor debe tomar en consideración el “esfuerzo” del Entorno cada
vez que se ejecute la rutina y la periodicidad con que se ejecuta.

Estructura de los registros (información)

En las bases de datos estándar ISAM, cada registro tiene un identificador


nativo o ID secuencial y ascendente que funciona como la dirección base de
aquella información.

Este ID, más conocido como RECNO o RECNUMBER se genera en el momento


de inclusión del registro en la tabla y sólo se modificará si la estructura de los
datos de esta tabla recibe algún mantenimiento. Entre los mantenimientos que
una tabla de datos ISAM puede recibir, es posible mencionar la utilización del
comando PACK, el cual borrará físicamente los registros borrados de la tabla,
forzando una renumeración de los identificadores de todos los registros. Esta
situación también hace necesaria la recreación de todos los índices vinculados
a aquella tabla.

Esto ocurre en las bases de datos ISAM debido al concepto de borrado lógico
de registros que éstas tienen. Ya en las bases de datos estándar SQL
nativamente sólo se utiliza el concepto de borrado físico de registros, lo que
para otras aplicaciones sería transparente, pero no es el caso del ERP Protheus.

Para mantener la compatibilidad de las aplicaciones desarrolladas para bases


de datos estándar ISAM, el área de Tecnología y Base de Datos de Microsiga
implementó en las bases de datos estándar SQL, el concepto de borrado
lógico de registros existente en las bases de datos ISAM, por medio de la
creación de campos de control específicos: R_E_C_N_O_, D_E_L_E_T_ y
R_E_C_D_E_L.

Estos campos permiten que la aplicación ERP administre la información de la


base de datos, de la misma manera que la información en las bases de datos
ISAM.

Con ello, el campo R_E_C_N_O_ será un identificador único del registro dentro
de la tabla, funcionando como ID o RECNUMBER de una tabla ISAM, pero
utilizando un recurso adicional disponible en las bases de datos relacionales
conocido como Clave Primaria.

Para la aplicación ERP Protheus el campo de control R_E_C_N_O_ se define en


todas las tablas como su clave primaria, lo que transfiere el control de su
numeración secuencial a la base de datos.

Página 152 Introducción a la Programación ADVPL I


El campo D_E_L_E_T_ se trata internamente por medio de la aplicación ERP
como un “flag” o marca de borrado. De esta manera, los registros que estén
con este campo marcado se considerarán como borrados lógicamente. El
borrado del comando PACK, en una tabla de una base de datos estándar SQL,
tiene como objetivo borrar físicamente los registros con el campo D_E_L_E_T_
marcado, pero no causará el efecto de renumeración de RECNO (en el caso
R_E_C_N_O_) que ocurre en la tabla de bases de datos ISAM.

11.2. Funciones de acceso y manipulación de datos

Las funciones de acceso y manipulación de datos, descritas en este tópico, son


aquellas clasificadas anteriormente como funciones genéricas del lenguaje
ADVPL, permitiendo que éstas se utilicen independientemente de la base de
datos para la está configurada la aplicación ERP.

Las funciones de acceso y manipulación de datos definen básicamente:

; Tabla que se está tratando.


; Campos que deben leerse o actualizarse.
; Método de acceso directo a la información (registros y campos).

Entre las funciones ADVPL disponibles para acceso y manipulación de


información, este material detallará las siguientes opciones:

 SELECT()

 DBSELECTAREA()

 DBSETORDER()

 DBSEEK() y MSSEEK()

 DBSKIP()

 DBGOTO()

 DBGOTOP()

 DBGOBOTTON()

 DBSETFILTER()

 RECLOCK()

 SOFTLOCK()

 MSUNLOCK()

 DBDELETE()

Introducción a la Programación ADVPL I Página 153


 DBUSEAREA()

 DBCLOSEAREA()

DBRLOCK()

Sintaxis DBRLOCK(xIdentificador)
Función de base de datos, que efectúa el lock (trabamiento) del
registro identificado por el parámetro xIdentificador. Este
parámetro puede ser el Recno() para tablas en formado ISAM, o
la clave primaria para bases de datos relacionales.
Descripción
Si no se especifica el parámetro xIdentificador, se liberarán todos
los locks del área de trabajo, se trabará el registro marcado y se
agregará en una lista de registros bloqueados.

DBCLOSEAREA()

Sintaxis DbCloseArea()
Permite que se cierre un alias presente en la conexión, lo que
hace posible que se utilice nuevamente en otra operación. Este
Descripción comando sólo tiene efecto en el alias activo en la conexión,
haciéndose necesaria su utilización en conjunto con el comando
DbSelectArea().

DBCOMMIT()

Sintaxis DBCOMMIT()
Efectúa todas las actualizaciones pendientes en el área de
Descripción
trabajo activa.

DBCOMMITALL()

Sintaxis DBCOMMITALL()
Efectúa todas las actualizaciones pendientes en todas las área de
Descripción
trabajo, que están en uso por la thread (conexión) activa.

DBDELETE()

Sintaxis DbDelete()
Efectúa el borrado lógico del registro marcado en el área de
Descripción trabajo activa. Para ello, es necesaria su utilización en conjunto
con las funciones RecLock() y MsUnLock().

Página 154 Introducción a la Programación ADVPL I


DBGOTO()

Sintaxis DbGoto(nRecno)
Mueve el cursor del área de trabajo activa al record number
Descripción (recno) especificado, realizando una localización directa, sin
necesidad de búsqueda (seek) previa.

DBGOTOP()

Sintaxis DbGoTop()
Mueve el cursor del área de trabajo activa al primer registro
Descripción
lógico.

DBGOBOTTON()

Sintaxis DbGoBotton()
Mueve el cursor del área de trabajo activa al último registro
Descripción
lógico.

DBRLOCKLIST()

Sintaxis DBRLOCKLIST()
Devuelve un array con el record number (recno) de todos los
Descripción
registros trabados del área de trabajo activa.

DBSEEK() y MSSEEK()

Sintaxis DbSeek(cChave, lSoftSeek, lLast)


DbSeek: Con el cursor del área de trabajo activa es posible
marcar el registro con la información especificada en la clave de
búsqueda, suministrando una devolución lógica que indica si la
localización se realizó con éxito, es decir, si la información
especificada en la clave de búsqueda se localizó en el área de
trabajo.
Descripción
MsSeek(): Función desarrollada por el área de Tecnología de
Microsiga, la cual tiene las mismas funcionalidades básicas de la
función DbSeek(), con la ventaja de no necesitar acceder
nuevamente a la base de datos para localizar una información
utilizada por la thread (conexión) activa.

Introducción a la Programación ADVPL I Página 155


DBSKIP()

Sintaxis DbSkip(nRegistros)
Mueve el cursor del registro marcado al próximo (o anterior,
Descripción dependiendo del parámetro), en función del orden activo para el
área de trabajo.

DBSELECTAREA()

Sintaxis DbSelectArea(nArea | cArea)


Define el área de trabajo especificada como el área activa. Todas
las operaciones subsiguientes que hagan referencia a un área de
Descripción
trabajo para utilización, a menos que el área deseada se informe
explícitamente.

DBSETFILTER()

Sintaxis DbSetFilter(bCondicao, cCondicao)


Define un filtro para el área de trabajo activa, lo cual puede
Descripción describirse en la forma de un bloque de código o por medio de
una expresión sencilla

DBSETORDER()

Sintaxis DbSetOrder(nOrdem)
Define qué índice se utilizará por el área de trabajo activa, es
decir, por el área previamente seleccionada por medio del
Descripción comando DbSelectArea(). Los órdenes disponibles en el Entorno
Protheus son aquellos definidos en el SINDEX /SIX, o los órdenes
puestos a disposición por medio de índices temporales.

DBORDERNICKNAME()

Sintaxis DbOrderNickName(NickName)
Define qué índice creado por el usuario se utilizará. El usuario
Descripción puede incluir sus propios índices y en el momento de la inclusión
debe crear su NICKNAME.

Página 156 Introducción a la Programación ADVPL I


DBUNLOCK()

Sintaxis DBUNLOCK()
La misma funcionalidad de la función UNLOCK(), sólo que
recomendada para entornos de red en los cuales se comparten
los archivos.
Descripción
Libera el trabamiento del registro marcado en el área de trabajo
activa y
confirma las actualizaciones realizadas en aquel registro.

DBUNLOCKALL()

Sintaxis DBUNLOCKALL()
Libera el trabamiento de todos los registros de todas las áreas de
Descripción
trabajo disponibles en la thread (conexión) activa.

DBUSEAREA()

DbUseArea(lNovo, cDriver, cArquivo, cAlias, lComparilhado,;


Sintaxis
lSoLeitura)
Define un archivo de base de datos como un área de trabajo
Descripción
disponible en la aplicación.

MSUNLOCK()

Sintaxis MsUnLock()
Libera el trabamiento (lock) del registro marcado, confirmando
Descripción
las actualizaciones realizadas en este registro.

RECLOCK()

Sintaxis RecLock(cAlias,lInclui)
Efectúa el trabamiento del registro marcado en el área de trabajo
Descripción
activa, permitiendo que se incluya o modifique su información.

Introducción a la Programación ADVPL I Página 157


RLOCK()

Sintaxis RLOCK() Æ lSucesso


Efectúa el trabamiento del registro marcado en el área de trabajo
Descripción
activa.

SELECT()

Sintaxis Select(cArea)
Determina el número de referencia de un determinado alias en un
entorno de trabajo. Si el alias especificado no estuviera en uso en
Descripción
el Entorno, se devolverá el valor 0 (cero).

SOFTLOCK()

Sintaxis SoftLock(cAlias)
Permite la reserva del registro marcado en el área de trabajo
activa, de tal manera que otras operaciones, con excepción de la
actual, no puedan actualizar este registro. Difiere de la función
RecLock() porque no genera una obligación de actualización y
puede sustituirse por ésta.

Descripción
En la aplicación ERP Protheus, la opción SoftLock() se utiliza en los
browses, antes de la confirmación de la operación de modificación
y borrado, porque en este momento ésta aún no se hizo efectiva,
pero otras conexiones no pueden acceder a aquel registro porque
se encuentra en mantenimiento, lo cual permite la integridad de la
información.

UNLOCK()

Sintaxis UNLOCK()
Libera el trabamiento del registro marcado en el área de trabajo
Descripción activa y
confirma las actualizaciones realizadas en aquel registro.

Página 158 Introducción a la Programación ADVPL I


11.3. Diferencia entre variables y nombres de campos

Muchas veces una variable puede tener el mismo nombre que un campo de
un archivo o de una tabla abierta en el momento. En este caso, el ADVPL
privilegiará el campo, de tal manera que una referencia a un nombre, que
identifique tanto una variable como un campo, resultará en el contenido del
campo.

Para especificar cuál debe ser el elemento referenciado, debe utilizarse el


operador de identificación de apodo (->) y uno de los dos identificadores de
referencia, MEMVAR o FIELD.

cRes := MEMVAR->NOME

Esta línea de comando identifica que el valor atribuido a la variable cRes debe
ser el valor de la variable de memoria denominada NOME.

cRes := FIELD->NOME

En este caso, el valor atribuido a la variable cRes será el valor del campo
NOME, existente en el archivo o tabla abierto en el área actual.

El identificador FIELD puede sustituirse por el apodo de un archivo o tabla


abiertos, para evitar la necesidad de seleccionar el área antes de acceder al
contenido de determinado campo.

cRes := CLIENTES->NOME

Las tablas de datos, utilizadas por la aplicación ERP, reciben automáticamente


del Sistema el apodo o ALIAS, especificado para éstas en el archivo de sistema
SX2. De esta manera, si el campo NOME pertenece a una tabla de la aplicación
PROTHEUS, podrá referenciarse con la indicación del ALIAS definido
previamente de esta tabla.

cRes := SA1->NOME // SA1 – Archivo de Clientes

Introducción a la Programación ADVPL I Página 159


Para más detalles sobre la apertura de archivos con atribución de
apodos, consulte la documentación sobre el acceso a la base de datos o
a la documentación de la función dbUseArea().

El alias de las tablas de la aplicación ERP se estandariza en tres letras,


que corresponden a las iniciales de la tabla. Las configuraciones de
cada ALIAS, utilizado por el Sistema, pueden visualizarse por medio del
módulo Configurador -> Bases de Datos -> Diccionarios -> Bases de
Datos.

11.4. Control de numeración secuencial

El Sistema suministra algunos campos de numeración del Protheus orden


ascendente. Es el caso, por ejemplo, del número de pedido de venta y otros
que sirven como identificador de la información de las tablas. Es necesario
tener un control del suministro de estos números, en especial cuando varios
usuario están trabajando simultáneamente.

Los campos que reciben el tratamiento de numeración secuencial por la


aplicación ERP no deben considerarse como clave primaria de las tablas
a las cuales están vinculados.

En el caso específico de la aplicación ERP Protheus, la clave primaria en


Entornos TOPCONNECT será el campo R_E_C_N_O_, y para bases de
datos estándar ISAM, el concepto de clave primaria se implementa por
medio de la regla de negocio del sistema, pues este estándar de datos
no tiene el concepto de unicidad de datos.

Semáforos

Para definir el concepto de lo que es un semáforo de numeración debe


evaluarse la siguiente secuencia de eventos en el sistema:

; Al suministrarse un número, éste permanece reservado hasta la conclusión


de la operación que lo solicitó.

; Si se confirma esta operación, el número queda indisponible, pero si se

Página 160 Introducción a la Programación ADVPL I


anula la operación, el número volverá a estar disponible aunque en aquel
momento ya se hayan ofrecido y utilizado números mayores.

Con ello, aunque tengamos varios procesos solicitando numeraciones


secuenciales para una misma tabla, como por ejemplo, inclusiones simultáneas
de pedidos de venta, tendremos para cada pedido un número exclusivo y sin
intervalos y numeraciones no utilizadas.

Funciones de control de semáforos y numeración secuencial

El lenguaje ADVPL permite la utilización de las siguientes funciones para el


control de las numeraciones secuenciales utilizadas en las tablas de aplicación
ERP:

 GETSXENUM()

 CONFIRMSXE()

 ROLLBACKSXE()

GETSXENUM()

Sintaxis GETSXENUM(cAlias, cCampo, cAliasSXE, nOrdem)


Obtiene el número secuencia del alias especificado en el
parámetro, por medio de la referencia a los archivos de sistema
Descripción
SXE/SXF o al servidor de numeración, cuando esta configuración
está habilitada en el Entorno Protheus.

Introducción a la Programación ADVPL I Página 161


CONFIRMSXE()

Sintaxis CONFIRMSXE(lVerifica)
Confirma el número asignado por medio del último comando
Descripción
GETSXENUM().

ROLLBACKSXE()

Sintaxis ROLLBACKSXE()
Descarta el número suministrado por el último comando
Descripción GETSXENUM(), devolviendo la numeración disponible a otras
conexiones.

Página 162 Introducción a la Programación ADVPL I


12. PERSONALIZACIONES PARA LA APLICACIÓN ERP

En este tópico se abordarán las formas en que puede personalizarse la aplicación


ERP Protheus, con la utilización del lenguaje ADVPL.

Por medio de los recursos de configuración de la aplicación ERP, disponibles en el


módulo Configurador, es posible implementar las siguientes personalizaciones:

; Validaciones de campos y preguntas del Sistema y de usuarios.


; Inclusión de disparadores en campos de Sistemas y de usuarios.
; Inclusión de reglas en parámetros de Sistemas y de usuarios.
; Desarrollo de puntos de entrada para interactuar en funciones estándar del
Sistema

12.1. Personalizaciones de campos – Diccionario de Datos

12.1.1. Validaciones de campos y preguntas

Las funciones de validación tienen como característica fundamental una


devolución de tipo lógico, es decir, un contenido .T. – Verdadero o .F. – Falso.

Con base en esta premisa, la utilización de validaciones en el Diccionario de


Datos (SX3) o en las Preguntas de Procesos e Informes (SX1) siempre debe
enfocarse en la utilización de funciones o expresiones que resulten en una

Introducción a la Programación ADVPL I Página 163


devolución lógica.

Por medio del módulo Configurador es posible modificar las propiedades de


un campo o de una pregunta para incluir reglas de validación para las
siguientes situaciones:

; SX3 – Validación de usuario (X3_VLDUSER).


; SX1 – Validación de la pregunta (X1_VALID).

Se detallarán las funciones que el lenguaje ADVPL utiliza para la validación de


campos y preguntas, en conjunto con los recursos desarrollados por la
aplicación ERP:

 VAZIO()

 NAOVAZIO()

 EXISTCPO()

 EXISTCHAV()

 PERTENCE()

 POSITIVO()

 NEGATIVO()

 TEXTO()

EXISTCHAV()

Sintaxis ExistChav(cAlias, cConteudo, nIndice)


Devuelve .T. o .F. si el contenido especificado existe en el alias
especificado. Si existiera, se mostrará un help de Sistema con un
aviso informando la ocurrencia.

Descripción Esta función generalmente se utiliza para verificar si un


determinado código de registro existe en la tabla en la cual se
incluirá la información, como por ejemplo, el Registro Nacional
de Persona Jurídica (CNPJ) en el archivo de clientes o
proveedores.

Página 164 Introducción a la Programación ADVPL I


EXISTCPO()

Sintaxis ExistCpo(cAlias, cConteudo, nIndice)


Devuelve .T. o .F. si el contenido especificado existe en el alias
especificado. Si no existiera, se mostrará un help de Sistema con
un aviso informando la ocurrencia.

Descripción
Esta función generalmente se utiliza para verificar si la
información digitada en un campo, que depende de otra tabla,
realmente existe en aquella otra tabla, como por ejemplo, el
código de un cliente en un pedido de venta.

NAOVAZIO()

Sintaxis NaoVazio()
Devuelve .T. o .F. si el contenido del campo marcado en el
Descripción
momento no está vacío.

NEGATIVO()

Sintaxis Negativo()
Devuelve .T. o .F. si el contenido digitado para el campo es
Descripción
negativo.

PERTENCE()

Sintaxis Pertence(cString)
Devuelve .T. o .F. si el contenido digitado para el campo está
incluido en el string, definido como parámetro de la función.
Descripción Generalmente se utiliza en campos con la opción de lista de
opciones, porque de loo contrario se utilizaría la función
ExistCpo().

POSITIVO()

Sintaxis Positivo()
Devuelve .T. o .F. si el contenido digitado para el campo es
Descripción
positivo.

TEXTO()

Sintaxis Texto()

Introducción a la Programación ADVPL I Página 165


Devuelve .T. o .F. si el contenido digitado para el campo tiene
Descripción
solamente números o alfanuméricos.

VAZIO()

Sintaxis Vazio()
Devuelve .T. o .F. si el contenido del campo marcado en el
Descripción
momento está vacío.

12.1.2. Pictures de formato disponibles

Con base en los documentos disponibles en el TDN, el lenguaje ADVPL y la


aplicación ERP Protheus admiten las siguientes pictures:

Diccionario de Datos (SX3) y GET

Funciones
Contenido Funcionalidad
A Acepta solamente caracteres alfabéticos
C Muestra CR después de números positivos
E Muestra número con punto y coma invertidos (formato Europeo)
R Inserta caracteres diferentes de los caracteres de template en la
exhibición pero no los inserta en la variable del GET
S<n> Permite el desplazamiento horizontal del texto dentro del GET, <n>. Es
un número entero que identifica el tamaño de la región
X Muestra DB después de números negativos
Z Muestra ceros como blancos
( Muestra números negativos entre paréntesis con los espacios en
blanco iniciales
) Muestra números negativos entre paréntesis sin los espacios en blanco
iniciales
! Convierte caracteres alfabéticos a mayúsculas

Templates
Contenido Funcionalidad
X Permite cualquier carácter
9 Permite solamente dígitos para cualquier tipo de dato, incluyendo el
signo para numéricos
# Permite dígitos, signos y espacios en blanco para cualquier tipo de
dato
! Convierte caracteres alfabéticos a mayúsculas

Página 166 Introducción a la Programación ADVPL I


* Muestra un asterisco en lugar de los espacios en blanco iniciales en
números
. Muestra el punto decimal
, Muestra la posición de millar

Ejemplo 01 – Picture campo numérico

CT2_VALOR – Numérico – 17,2


Picture: @E 99,999,999,999,999.99

Ejemplo 02 – Picture campo texto, solamente con digitación en caja alta

A1_NOME – Carácter - 40
Picture: @!

SAY y PSAY

Funciones
Contenido Funcionalidad
C Muestra CR después de números positivos.
E Muestra un número con punto y coma invertidos (formato Europeo).
R Inserta caracteres diferentes de los caracteres de template.
X Muestra DB después de números negativos.
Z Muestra ceros como blancos.
( Involucra números negativos entre paréntesis.
! Convierte todos los caracteres alfabéticos mayúsculo.

Templates
Contenido Funcionalidad
X Muestra dígitos para cualquier tipo de dato.
9 Muestra dígitos para cualquier tipo de dato.
# Muestra dígitos para cualquier tipo de dato.
! Convierte caracteres alfabéticos a mayúsculas.
* Muestra un asterisco en lugar de los espacios en blanco e iniciales en
números.
. Muestra la posición del punto decimal.
, Muestra la posición de millar.

Ejemplo 01 – Picture campo numérico

CT2_VALOR – Numérico – 17,2


Picture: @E 99,999,999,999,999.99

Introducción a la Programación ADVPL I Página 167


12.2. Personalización de disparadores – Configurador

La aplicación ERP utiliza el recurso de disparadores en campo con la finalidad


de ayudar al usuario en el rellenado de información, durante su digitación. Las
funciones que pueden utilizarse en el disparador están directamente
relacionadas con la definición de la expresión de devolución, que se ejecutará
en la evaluación del disparador del campo.

Las reglas que deben observarse en la elaboración de un disparador y la


configuración de su devolución son:

; En la definición de la clave de búsqueda del disparador debe evaluarse qué


sucursal debe utilizarse como parte de la clave: la sucursal de la tabla de
origen del disparador o la sucursal de la tabla que se consultará. Lo que
generalmente determina la sucursal que se utilizará como parte de la clave, es
justamente la información que se consultará, donde:

Las consultas de información, entre tablas con estructura de encabezado e


ítems, deben utilizar la sucursal de la tabla de origen, pues ambas tablas
deben tener el mismo tratamiento de sucursal (compartido o exclusivo).

Ejemplos

Pedido de ventas -> SC5 x SC6


Factura de entrada -> SF1 x SD1
Ficha de inmovilizado -> SN1 x SN3
Presupuesto contable -> CV1 x CV2

La consulta de información de tablas de archivos debe utilizar la sucursal de la


tabla que se consultará, porque el uso compartido de los archivos
generalmente es independiente con relación a los movimientos y otros
archivos del Sistema.

Ejemplos

Archivo de clientes -> SA1 (compartido)


Archivo de proveedores -> SA2 (compartido)
Archivo de vendedores -> SA3 (exclusivo)
Archivo de transportadoras -> SA4 (exclusivo)

Consulta la información de tablas de movimientos que deben utilizar la sucursal de


la tabla que se consultará, porque aunque los movimientos de un módulo se ajusten
a un determinado estándar. La consulta puede realizarse entre tablas de módulos

Página 168 Introducción a la Programación ADVPL I


distintos, lo que podría generar una devolución incorrecta con base en las diferentes
parametrizaciones de estos Entornos.

Ejemplos

Cuentas por pagar -> SE2 (compartido)


Movimientos contables -> CT2 (exclusivo)
Pedidos de compra -> SC7 (compartido)
Ítems de la factura de entrada -> SD1 (exclusivo)

; En la definición de la regla de devolución debe considerarse el tipo do


campo que se actualizará, porque este campo determina qué tipo do
devolución se considerará válida para el disparador.

12.3. Personalización de parámetros – Configurador

Los parámetros de sistema utilizados por la aplicación ERP y definidos por


medio del módulo configurador tienen las siguientes características
fundamentales:

; Tipo de parámetro: de forma similar a una variable, un parámetro tendrá un


tipo de contenido definido previamente en su registro.
Esta información se utiliza por medio de las funciones de la aplicación ERP,
para la interpretación del contenido del parámetro y la devolución de esta
información a la rutina que la consultó.

; Interpretación del contenido del parámetro: Diversos parámetros del


Sistema tienen su contenido macro ejecutado durante la ejecución de una
rutina del ERP. Estos parámetros macroejecutables tienen como única
característica en común su tipo: carácter, pero no existe ningún identificador
explícito que permite la fácil visualización de los parámetros que tienen una
devolución simple y de qué parámetros tendrán su contenido macroejecutado
para determinar la devolución “real”.

La única forma eficaz de evaluar cómo se trata un parámetro (simple


devolución o macroejecución) es por medio del código fuente de la rutina, en
el cual debe evaluarse cómo se trata la devolución de una de estas funciones:

o GETMV()
o SUPERGETMV()
o GETNEWPAR()

Una devolución macroejecutada se determina por medio del uso del

Introducción a la Programación ADVPL I Página 169


operador “&” o de una de las funciones de ejecución de bloques de código,
en conjunto con una de las funciones mencionadas anteriormente.

12.3.1. Funciones para manipulación de parámetros

La aplicación ERP pone a disposición las siguientes funciones para la consulta


y actualización de parámetros:

 GETMV()

 SUPERGETMV()

 GETNEWPAR()

 PUTMV()

GETMV()

Sintaxis GETMV(cParametro)
Devuelve el contenido del parámetro especificado en el archivo
SX6, considerando la sucursal parametrizada en la conexión. Si el
Descripción
parámetro no existe, se mostrará un help del sistema informando
la ocurrencia.

GETNEWPAR()

Sintaxis GETNEWPAR(cParametro, cPadrao, cFilial)


Devuelve el contenido del parámetro especificado en el archivo
SX6, considerando la sucursal parametrizada en la conexión. Si el
parámetro no existe, se mostrará un help del sistema informando
la ocurrencia.
Descripción
Difiere del SuperGetMV() pues considera que el parámetro
puede no existir en la versión actual del Sistema y
consecuentemente no se mostrará el mensaje de help.

PUTMV()

Sintaxis PUTMV(cParametro, cConteudo)


Actualiza el contenido del parámetro especificado en el archivo
Descripción
SX6, de acuerdo con las parametrizaciones informadas.

Página 170 Introducción a la Programación ADVPL I


SUPERGETMV()

Sintaxis SUPERGETMV(cParametro , lHelp , cPadrao , cFilial)


Devuelve el contenido del parámetro especificado en el archivo
SX6, considerando la sucursal parametrizada en la conexión. Si el
parámetro no existe, se mostrará un help del sistema informando
la ocurrencia.
Descripción
Difiere del GetMv() porque los parámetros consultados se
agregan en un área de memoria, que permite que en una nueva
consulta no sea necesario acceder y buscar el parámetro en la
base de datos.

12.3.2. Cuidados en la utilización de un parámetro

Un parámetro de sistema tiene la finalidad de propiciar una devolución válida


a un contenido previamente definido en la configuración del módulo para una
rutina, proceso o cualquier otro tipo de funcionalidad disponible en la
aplicación.

Aunque existan parámetros que permitan la configuración de expresiones y


consecuentemente, la utilización de funciones para definir la devolución que
se obtendrá con la consulta de este parámetro, es expresamente prohibido
el uso de funciones en parámetros para manipular información de la base
de datos del Sistema.

Si hubiera necesidad de implementar un tratamiento adicional a un proceso


estándar del Sistema, éste debe utilizar el recurso de punto de entrada.

La razón de esta restricción es muy simple:

; Las rutinas de la aplicación ERP no protegen la consulta de contenidos de


parámetros, cuanto a grabaciones realizadas dentro o fuera de una
transacción.

; De esta manera, cualquier modificación en la base realizada por una rutina,


configurada en un parámetro, puede ocasionar la pérdida de la integridad de
la información del Sistema.

Introducción a la Programación ADVPL I Página 171


12.4. Puntos de Entrada – Conceptos, Premisas y Reglas

Conceptos

Un punto de entrada es una User Function desarrollada con la finalidad de


interactuar con una rutina estándar de la aplicación ERP.

La User Function debe tener un nombre establecido previamente en el


desarrollo de la rutina estándar del ERP y de acuerdo con esta disposición
previa y el momento en el cual el punto de entrada se ejecuta durante un
procesamiento, podrá:

; Complementar una validación realizada por la aplicación.

; Complementar las actualizaciones realizadas por el procesamiento en tablas


estándar del ERP.

; Implementar la actualización de tablas específicas durante el procesamiento


de una rutina estándar del ERP.

; Ejecutar una acción sin procesos de actualizaciones, pero que necesite


utilizar la información actual del Entorno, durante el procesamiento de la
rutina estándar para determinar las características del proceso.

; Sustituir un procesamiento estándar del Sistema por una regla específica


personalizada por el cliente.

Premisas y Reglas

; Un punto de entrada no debe utilizarse para otras finalidades, sino para


aquellas que fue definido, bajo pena de causar la pérdida de la integridad de
la información de la base de datos o provocar eventos de error durante la
ejecución de la rutina estándar.

; Un punto de entrada debe ser transparente para el proceso estándar, de tal


manera que todas las tablas accedidas por el punto de entrada y que se
utilicen por la rutina estándar, deben tener su situación inmediatamente
anterior a la ejecución del punto restaurado al término de éste, y para ello, se
recomienda el uso de las funciones GETAREA() y RESTAREA().

; Como un punto de entrada no se ejecuta de la forma tradicional, es decir,


no se llama como una función, éste no recibe parámetros. La aplicación ERP
pone a disposición una variable de Sistema denominada PARAMIXB, la cual

Página 172 Introducción a la Programación ADVPL I


recibe los parámetros de la función llamadora y los pone a disposición para
que la rutina personalizada los utilice.

; La variable PARAMIXB no tiene un estándar de definición en los códigos


fuentes de la aplicación ERP, de esta manera, su tipo puede variar de un
contenido simple (carácter, numérico, lógico, etc.) a un tipo complejo como un
array o un objeto. De esta manera, siempre es necesario evaluar la
documentación sobre el punto, así como también, proteger la función
personalizada de tipos de PARAMIXB no tratados por ésta.

Introducción a la Programación ADVPL I Página 173


13. INTERFACES VISUALES

El lenguaje ADVPL tiene dos formas distintas para la definición de interfaces visuales
en el Entorno ERP: sintaxis convencional, en los estándar del lenguaje CLIPPER y la
sintaxis orientada a objetos.

Además de las diferentes sintaxis disponibles para definición de las interfaces


visuales, el ERP Protheus tiene funcionalidades definidas previamente, las cuales ya
tienen todos los tratamientos necesarios para atender las necesidades básicas de
acceso y mantenimiento de la información del Sistema.

En este tópico se abordarán las sintaxis convencionales para definición de las


interfaces visuales del lenguaje ADVPL y las interfaces de mantenimiento,
disponibles en el Entorno ERP Protheus.

13.1. Sintaxis y componentes de las interfaces visuales

La sintaxis convencional para definición de componentes visuales del lenguaje


ADVPL depende directamente del fuente, en include especificado en el
encabezado. Los dos includes, disponibles para el Entorno ADVPL Protheus,
son:

; L RWMAKE.CH: Permite la utilización de la sintaxis CLIPPER en la definición


de los componentes visuales.
;
; PROTHEUS.CH: Permite la utilización de la sintaxis ADVPL convencional, la
cual es una mejora de la sintaxis CLIPPER, con la inclusión de nuevos atributos
para los componentes visuales puestos a disposición en el ERP Protheus.

Para ilustrar la diferencia de utilización de estos dos includes, se mencionan a


continuación las diferentes definiciones para los componentes Dialog y
MsDialog:

Ejemplo 01 – Include Rwmake.ch

#include “rwmake.ch”

@ 0.0 TO 400.600 DIALOG oDlg TITLE "Ventana en sintaxis Clipper"


ACTIVATE DIALOG oDlg CENTERED

Página 174 Introducción a la Programación ADVPL I


Ejemplo 02 – Include Protheus.ch

#include “protheus.ch”

DEFINE MSDIALOG oDlg TITLE "Ventana en sintaxis ADVPL "FROM 000.000 TO


400.600 PIXEL
ACTIVATE MSDIALOG oDlg CENTERED

Ambas sintaxis producirán el mismo efecto cuando se compilen y


ejecuten en el entorno Protheus, pero siempre debe utilizarse la sintaxis
ADVPL, por medio del uso del include PROTHEUS.CH.

Los componentes de la interfaz visual que se tratarán en este tópico, utilizando


la sintaxis ADVPL son:

 MSDIALOG()

 MSGET()

 SAY()

 BUTTON()

 SBUTTON()

BUTTON()

@ nLinha,nColuna BUTTON cTexto SIZE nLargura,nAltura


Sintaxis
UNIDADE OF oObjetoRef ACTION AÇÃO
Define el componente visual Button, con el cual es posible incluir
Descripción botones de operación en la pantalla de la interfaz, los cuales
sólo se visualizarán con un texto sencillo para su identificación.

MSDIALOG()

DEFINE MSDIALOG oObjetoDLG TITLE cTitulo FROM


Sintaxis
nLinIni,nColIni TO nLiFim,nColFim OF oObjetoRef UNIDADE
Define el componente MSDIALOG(), el cual se utiliza como base
Descripción para los demás componentes de la interfaz visual, pues un
componente MSDIALOG() es una ventana de la aplicación.

Introducción a la Programación ADVPL I Página 175


MSGET()

@ nLinha, nColuna MSGET VARIAVEL SIZE nLargura,nAltura


Sintaxis UNIDADE OF oObjetoRef F3 cF3 VALID VALID WHEN WHEN
PICTURE cPicture
Define el componente visual MSGET, el cual se utiliza para la
Descripción
captura de la información digitable en la pantalla de la interfaz.

SAY()

@ nLinha, nColuna SAY cTexto SIZE nLargura,nAltura


Sintaxis
UNIDADE OF oObjetoRef
Define el componente visual SAY, el cual se utiliza para mostrar
Descripción
textos en una pantalla de interfaz.

SBUTTON()

DEFINE SBUTTON FROM nLinha, nColuna TYPE N ACTION


Sintaxis
AÇÃO STATUS OF oObjetoRet
Define el componente visual SButton, el cual permite la inclusión
de botones de operación en la pantalla de la interfaz, los cuales
Descripción se visualizarán dependiendo de la interfaz del sistema ERP
utilizada solamente con un texto sencillo para su identificación, o
con una imagen (BitMap) definida previamente.

Interfaz visual completa

A continuación se muestra un código completo de interfaz, utilizando todos


los elementos de la interfaz visual descritos anteriormente:

DEFINE MSDIALOG oDlg TITLE cTitulo FROM 000.000 TO 080.300 PIXEL

@ 001.001 TO 040, 150 OF oDlg PIXEL

@ 010.010 SAY cTexto SIZE 55, 07 OF oDlg PIXEL

@ 010.050 MSGET cCGC SIZE 55, 11 OF oDlg PIXEL PICTURE "@R


99,999,999/9999-99";
VALID !Vazio()

DEFINE SBUTTON FROM 010, 120 TYPE 1 ACTION (nOpca := 1.oDlg:End());


ENABLE OF oDlg

DEFINE SBUTTON FROM 020, 120 TYPE 2 ACTION (nOpca := 2.oDlg:End());


ENABLE OF oDlg

Página 176 Introducción a la Programación ADVPL I


ACTIVATE MSDIALOG oDlg CENTERED

El código mostrado anteriormente se utiliza en los ejercicios de fijación


de este material y debe producir la siguiente interfaz:

13.2. Interfaces estándar para actualizaciones de datos

Los programas de actualización de archivos y digitación de movimientos


cumplen un estándar que se apoya en el Diccionario de Datos.

Básicamente, hay dos interfaces que permiten la visualización de la


información y la manipulación de los datos del Sistema.

; AxCadastro
; Mbrowse

Ambos modelos utilizan como premisa que la estructura de la tabla que se


utilizará esté definida en el diccionario de datos del sistema (SX3).

13.2.1. AxCadastro()

El AxCadastro() es una funcionalidad de archivo sencillo, con pocas opciones


de personalización, el cual se compone de:

¾ Browse estándar para visualización de la información de la base de datos,


de acuerdo con las configuraciones del SX3 – Diccionario de Datos (campo
browse).

¾ Funciones de búsqueda, visualización, inclusión, modificación y borrado de

Introducción a la Programación ADVPL I Página 177


estándares para visualización de registros sencillos, sin la opción de
encabezado e ítems.

; Sintaxis: AxCadastro(cAlias, cTitulo, cVldExc, cVldAlt)

; Parámetros

Alias estándar del sistema para utilización, el cual debe


cAlias
estar definido en el diccionario de datos – SX3.
cTitulo Título de la Ventana.
cVldExc Validación para Borrado.
cVldAlt Validación para Modificación.

Ejemplo:

#include "protheus.ch"

User Function XCadSA2()

Local cAlias := "SA2"


Local cTitulo := "Archivo de Proveedores"
Local cVldExc := ".T."
Local cVldAlt := ".T."

dbSelectArea(cAlias)
dbSetOrder(1)
AxCadastro(cAlias,cTitulo,cVldExc,cVldAlt)
Return

Página 178 Introducción a la Programación ADVPL I


13.2.2. MBrowse()

La Mbrowse() es una funcionalidad de archivo que permite la utilización de


recursos más perfeccionado en la visualización y manipulación de la
información del Sistema, con los siguientes componentes:

¾ Browse estándar para visualización de la información de la base de datos,


de acuerdo con las configuraciones del SX3 – Diccionario de Datos (campo
browse).

¾ Parametrización de funciones específicas para las acciones de visualización,


inclusión, modificación y borrado de información, lo que hace posible el
mantenimiento de la información con estructura de encabezados e ítems.

¾ Recursos adicionales como identificadores de estatus de registros, leyendas


y filtros para la información.

; Sintaxis simplificada: MBrowse(nLin1, nCol1, nLin2, nCol2, cAlias)

; Parámetros

nLin1, nCol1, Coordenadas de los cantos donde se mostrará el browse.


nLin2, nCol2 Para seguir el estándar de la AXCADASTRO() use 6,1,22,75 .
Alias estándar del sistema para utilización, el cual debe estar
cAlias
definido en el diccionario de datos – SX3.

Introducción a la Programación ADVPL I Página 179


; Variables private adicionales

Array con las funciones que se ejecutarán por el Mbrowse.


Este array puede parametrizarse con las funciones básicas de
la AxCadastro de acuerdo con lo siguiente:

AADD(aRotina,{"Buscar" ,"AxPesqui",0.1})
aRotina
AADD(aRotina,{"Visualizar" ,"AxVisual",0.2})
AADD(aRotina,{"Incluir" ,"AxInclui" ,0.3})
AADD(aRotina,{"Modificar" ,"AxAltera",0.4})
AADD(aRotina,{"Borrar" ,"AxDeleta",0.5})

cCadastro Título del browse que se mostrará.

Ejemplo:

#include "protheus.ch"

User Function MBrwSA2()

Local cAlias := "SA2"


Private cCadastro := "Archivo de Proveedores"
Private aRotina := {}

AADD(aRotina,{"Buscar" ,"AxPesqui",0.1})
AADD(aRotina,{"Visualizar" ,"AxVisual",0.2})
AADD(aRotina,{"Incluir" ,"AxInclui",0.3})
AADD(aRotina,{"Modificar" ,"AxAltera",0.4})
AADD(aRotina,{"Borrar" ,"AxDeleta",0.5})

dbSelectArea(cAlias)
dbSetOrder(1)
mBrowse(6,1,22,75,cAlias)
Return

Página 180 Introducción a la Programación ADVPL I


1. Cuando se utiliza la parametrización ejemplificada, el efecto
obtenido con el uso de la Mbrowse() será el mismo obtenido con
el uso de la AxCadastro().

2. La posición de las funciones en el array aRotina define el


contenido de una variable de control que se repasará a las
funciones llamadas a partir de la Mbrowse, denominada nOpc.
De esta forma, para mantener el estándar de la aplicación ERP,
el orden que debe seguirse en la definición del aRotina es:
1 – Buscar
2 – Visualizar
3 – Incluir
4 – Modificar
5 – Borrar
6 – Libre

Introducción a la Programación ADVPL I Página 181


Al definir las funciones en el array aRotina, si no se especifica el
nombre de la función con “()”, la Mbrowse pasará como parámetros a
las siguientes variables de control:

¾ cAlias: Alias activo definido para la Mbrowse.

¾ nRecno: Record number (recno) del registro marcado en el alias


activo.

¾ nOpc: Posición de la opción utilizada en el Mbrowse de acuerdo


con el orden de la función en el array aRotina.

Ejemplo: Función BInclui() que sustituye la función AxInclui()

#include "protheus.ch"

User Function MBrwSA2()

Local cAlias := "SA2"

Private cCadastro := "Archivo de Proveedores"


Private aRotina := {}

AADD(aRotina,{"Buscar" ,"AxPesqui",0.1})
AADD(aRotina,{"Visualizar" ,"AxVisual",0.2})
AADD(aRotina,{"Incluir" ,"U_BInclui" ,0.3})
AADD(aRotina,{"Modificar" ,"AxAltera",0.4})
AADD(aRotina,{"Borrar" ,"AxDeleta",0.5})

dbSelectArea(cAlias)
dbSetOrder(1)
mBrowse(6,1,22,75,cAlias)
Return

USER FUNCTION BInclui(cAlias, nReg, nOpc)

Local cTudoOk := "(Alert('OK'),.T.)"


AxInclui(cAlias,nReg,nOpc,,,,cTudoOk)

RETURN

Página 182 Introducción a la Programación ADVPL I


13.2.3. AxFunctions()

De acuerdo con lo mencionado en los tópicos sobre las interfaces estándar


AxCadastro() y Mbrowse(), existen funciones estándar de la aplicación ERP que
permiten la visualización, inclusión, modificación y borrado de datos en
formato simple.

Estas funciones son estándares en la definición de la interfaz AxCadastro() y


también pueden utilizarse de la construcción en el array aRotina, utilizado por
la Mbrowse(), las cuales se listan a continuación:

 AXPESQUI()

 AXVISUAL()

 AXINCLUI()

 AXALTERA()

 AXDELETA()

AXALTERA()

AxAltera(cAlias, nReg, nOpc, aAcho, cFunc, aCpos, cTudoOk,


Sintaxis lF3,; cTransact, aButtons, aParam, aAuto, lVirtual,
lMaximized)
Función de modificación de la información de un registro, en el
Descripción formato Enchoice, de acuerdo con lo que se muestra en el tópico
sobre la interfaz AxCadastro().

AXDELETA()

AXDELETA(cAlias, nReg, nOpc, cTransact, aCpos, aButtons,


Sintaxis
aParam,; aAuto, lMaximized)
Función de borrado de la información de un registro, en el
Descripción formato Enchoice, de acuerdo con lo que se muestra en el tópico
sobre la interfaz AxCadastro().

AXINCLUI()

AxInclui(cAlias, nReg, nOpc, aAcho, cFunc, aCpos, cTudoOk,


Sintaxis lF3,; cTransact, aButtons, aParam, aAuto, lVirtual,
lMaximized)
Función de inclusión estándar de la información de un registro,
Descripción en el formato Enchoice, de acuerdo con lo que se muestra en el
tópico sobre la interfaz AxCadastro().

Introducción a la Programación ADVPL I Página 183


AXPESQUI()

Sintaxis AXPESQUI()
Función de búsqueda estándar en los registros mostrados por
los browses del Sistema, la cual posiciona el browse en el
Descripción registro consultado. Muestra una pantalla que permite la
selección del índice que se utilizará en la búsqueda y la
digitación de la información que conforma la clave de búsqueda.

AXVISUAL()

AXVISUAL(cAlias, nReg, nOpc, aAcho, nColMens,


Sintaxis
cMensagem, cFunc,; aButtons, lMaximized )
Función de visualización estándar de la información de un
Descripción registro, en el formato Enchoice, de acuerdo con lo que se
muestra en el tópico sobre la interfaz AxCadastro().

Ejercicio
Desarrollar una validación para un campo específico del tipo carácter, cuyo
contenido esté relacionado con otra tabla y que muestre un mensaje de aviso si el
código informado no existe en esta tabla relacionada.

Ejercicio
Desarrollar una validación para un campo carácter existente en la base, para que se
evalúe si aquel código está registrado y en caso positivo, que se muestre un mensaje
advirtiendo sobre esta ocurrencia.

Ejercicio

Desarrollar un disparador que devuelva una descripción complementaria para un


campo vinculado al campo código utilizado en los ejercicios anteriores.

Página 184 Introducción a la Programación ADVPL I


Ejercicio
Personalizar el parámetro que define el prefijo del título de cuentas por pagar,
generado por la integración COMPRAS -> FINANCIERO por medio de la inclusión de
una factura de de entrada, de tal manera que el prefijo del título se genere con el
código de la sucursal en uso.

Ejercicio
Proteger la rutina desarrollada en el ejercicio anterior, para garantizar que en la
utilización de la sucursal como prefijo del título no ocurrirá duplicación de datos en
cuentas por pagar del financiero.

Ejercicio
Implementar una validación adicional en el archivo de clientes, por medio del punto
de entrada adecuado, de tal manera que el campo Registro Nacional de Persona
Jurídica (CNPJ) (A1_CGC) sea obligatorio para todos los tipos de cliente, excepto los
definidos como Exterior.

Introducción a la Programación ADVPL I Página 185


APÉNDICES

Buenas prácticas de programación

14. UTILIZACIÓN DE SANGRÍA

Es obligatorio utilizar la sangría, porque permite que el código sea mucho más
legible. Vea los siguientes ejemplos:

La utilización de la sangría según las estructuras de control de flujo (while, if, caso
etc), permite que la comprensión del código sea mucho más fácil:

Para realizar la sangría en el código utilice la tecla <TAB> y la herramienta DEV-


Studio, la cual puede configurarse por medio de la opción “Preferencias”:

Página 186 Introducción a la Programación ADVPL I


Introducción a la Programación ADVPL I Página 187
15. LETRA CAPITAL EN PALABRAS CLAVE

Una forma ampliamente difundida consiste en utilizar letras capitales en las palabras
claves, funciones, variables y campos por medio de una combinación de caracteres
en mayúscula y minúscula, con el fin de facilitar la lectura del código fuente. El
siguiente código:

local ncnt while ( ncnt++ < 10 ) ntotal += ncnt * 2 enddo

Quedaría mejor con las palabras claves y variables elaboradas con letras capitales:

Local nCnt While ( nCnt++ < 10 ) nTotal += nCnt * 2 EndDo

En las funciones de manipulación de datos que se inicien con “db”, la


letra capital sólo se colocará después del “db”:

; dbSeek()

; dbSelectArea()

15.1. Palabras en mayúscula

La regla es utilizar caracteres en mayúscula para:

; Contantes:
#define NUMLINES 60 #define NUMPAGES 1000

; Variables de memoria:
M-> CT2_CRCONV M->CT2_MCONVER := CriaVar("CT2_CONVER")

; Campos:
SC6->C6_NUMPED

; Queries:
SELECT * FROM...

Página 188 Introducción a la Programación ADVPL I


16. UTILIZACIÓN DE LA NOTACIÓN HÚNGARA

La notación húngara consiste en agregar los prefijos a los nombres de variables,


para identificar fácilmente su tipo. Esto facilita la creación de códigos fuente
extensos, pues al usar la Notación Húngara no es necesario regresar todo el tiempo
a la definición de una variable para recordar cuál es el tipo de datos que debe
colocarse en ella. Las variables deben tener un prefijo de Notación Húngara en
minúsculas, seguido de un nombre que identifique la función de la variable, cuya
letra inicial de cada palabra debe estar en mayúscula.

Es obligatorio utilizar esta notación para nombrar variables.

Notación Tipo de dato Ejemplo


a Array aValores
b Bloque de bSeek
código
c Carácter cNome
d Fecha dDataBase
l Lógico lContinua
n Numérico nValor
o Objeto oMainWindow
x Indefinido xConteudo

Introducción a la Programación ADVPL I Página 189


17. PALABRAS RESERVADAS

AADD DTOS INKEY REPLICATE VAL


ABS ELSE INT RLOCK VALTYPE
ASC ELSEIF LASTREC ROUND WHILE
AT EMPTY LEN ROW WORD
BOF ENDCASE LOCK RTRIM YEAR
BREAK ENDDO LOG SECONDS CDOW
ENDIF LOWER SELECT CHR EOF
LTRIM SETPOS CMONTH EXP MAX
SPACE COL FCOUNT MIN SQRT
CTOD FIELDNAME MONTH STR DATE
FILE PCOL SUBSTR DAY FLOCK
PCOUNT TIME DELETED FOUND PROCEDURE
TRANSFORM DEVPOS FUNCTION PROW TRIM
DOW IF RECCOUNT TYPE DTOC
IIF RECNO UPPER TRY AS
CATCH THROW

; Las palabras reservadas no pueden utilizarse para variables,


procedimientos o funciones.

; Las funciones reservadas pertenecen al compilador y no pueden


redefinirse por una aplicación.

; Todos los identificadores que empiezan con dos o más caracteres


“_” se utilizan como identificadores internos y son reservados.

Los identificadores de alcance PRIVATE o PUBLIC utilizados en


aplicaciones específicas desarrolladas por o para clientes deben tener su
identificación iniciada por un carácter “_”.

Página 190 Introducción a la Programación ADVPL I


GUÍA DE REFERENCIA RÁPIDA:
Funciones y Comandos ADVPL
En este guía de referencia rápida se describirán las funciones básicas del lenguaje
ADVPL, incluso las funciones heredadas del lenguaje Clipper, necesarias para el
desarrollo en el Entorno ERP.

Conversión entre tipo de datos

CTOD()

Realiza la conversión de una información del tipo carácter en el formato


“DD/MM/AAAA" a una variable del tipo data.

; Sintaxis: CTOD(cData)
; Parámetros:

cData Carácter en el formato “DD/MM/AAAA”.

Ejemplo:

cData := “31/12/06”
dData := CTOD(cData)

IF dDataBase >= dData


MSGALERT(“Fecha del sistema fuera de la competencia”)
ELSE
MSGINFO(“Fecha del sistema dentro de la competencia”)
ENDIF

CVALTOCHAR()

Realiza la conversión de una información del tipo numérico en una string, sin
la adición de espacios a la información.

; Sintaxis: CVALTOCHAR(nValor)
; Parámetros:

Introducción a la Programación ADVPL I Página 191


nValor Valor numérico que se convertirá a carácter.

Ejemplo:

FOR nPercorridos := 1 to 10
MSGINFO(“Pasos recorridos: ”+CvalToChar(nPercorridos))
NEXT nPercorridos

DTOC()

Realiza la conversión de una información del tipo data a un carácter, que


resultará en un formato “DD/MM/AAAA”.

; Sintaxis: DTOC(dData)
; Parámetros:

dData Variable con contenido data.

Ejemplo:

MSGINFO(“Database del sistema: ”+DTOC(dData)

DTOS()

Realiza la conversión de una información del tipo data a un carácter, que


resultará en un formato “AAAAMMDD”.

; Sintaxis: DTOS(dData)
; Parámetros:

dData Variable con contenido data.

Ejemplo:

cQuery := “SELECT A1_COD, A1_LOJA, A1_NREDUZ FROM SA1010 WHERE ”


cQuery += “A1_DULTCOM >=’”+DTOS(dDataIni)+“‘”

Página 192 Introducción a la Programación ADVPL I


STOD()

Realiza la conversión de una información del tipo carácter, con contenido en el


formato “AAAAMMDD” a data.

; Sintaxis: STOD(sData)
; Parámetros:

sData String en el formato “AAAAMMDD”.

Ejemplo:

sData := LERSTR(01.08) // Función que realiza la lectura de una string de un txt


previamente
// abierto
dData := STOD(sData)

STR()

Realiza la conversión de una información del tipo numérico a una string,


agregando espacios a la derecha.

; Sintaxis: STR(nValor)
; Parámetros:

nValor Valor numérico que se convertirá a carácter.

Ejemplo:

FOR nPercorridos := 1 to 10
MSGINFO(“Pasos recorridos: ”+CvalToChar(nPercorridos))
NEXT nPercorridos

STRZERO()

Realiza la conversión de una información del tipo numérico en una string,


agregando ceros a la izquierda del número convertido, de tal manera que la
string generada tenga el tamaño especificado en el parámetro.

; Sintaxis: STRZERO(nValor, nTamanho)

Introducción a la Programación ADVPL I Página 193


; Parámetros:

nValor Valor numérico que se convertirá a carácter.


nTamanho Tamaño total deseado para la string devuelta.

Ejemplo:

FOR nPercorridos := 1 to 10
MSGINFO(“Pasos recorridos: ”+CvalToChar(nPercorridos))
NEXT nPercorridos

VAL()

Realiza la conversión de una información del tipo carácter a numérica.

; Sintaxis: VAL(cValor)
; Parámetros:

cValor String que se convertirá a numérico.

Ejemplo:

Static Function Modulo11(cData)


LOCAL L, D, P := 0
L := Len(cdata)
D := 0
P := 1
While L > 0
P := P + 1
D := D + (Val(SubStr(cData, L, 1)) * P)
If P = 9
P := 1
End
L := L - 1
End
D := 11 - (mod(D,11))
If (D == 0 .Or. D == 1 .Or. D == 10 .Or. D == 11)
D := 1
End
Return(D)

Página 194 Introducción a la Programación ADVPL I


Verificación de tipo de variables

TYPE()

Determina el tipo do contenido de una variable, la cual no se definió en la


función en ejecución.

; Sintaxis: TYPE(“cVariavel”)
; Parámetros:

“cVariavel” Nombre de la variable que se desea evaluar, entre comillas (“”).

Ejemplo:

IF TYPE(“dDataBase”) == “D”
MSGINFO(“Database del sistema: ”+DTOC(“dDataBase”))
ELSE
MSGINFO(“Variable indefinida en el momento”)

VALTYPE()

Determina el tipo do contenido de una variable, la cual no se definió en la


función en ejecución.

; Sintaxis: VALTYPE(cVariavel)
; Parámetros:

cVariavel Nombre de la variable que se desea evaluar.

Ejemplo:

STATIC FUNCTION GETTEXTO(nTamanho, cTitulo, cSay)

LOCAL cTexto := “”
LOCAL nColF := 0
LOCAL nLargGet := 0
PRIVATE oDlg

Default cTitulo:= "Pantalla para informar texto"


Default cSay := "Informe el texto:"
Default nTamanho := 1

Introducción a la Programación ADVPL I Página 195


IF ValType(nTamanho) != “N” // Si el parámetro se pasó incorrectamente
nTamanho := 1
ENDIF

cTexto := Space(nTamanho)
nLargGet := Round(nTamanho * 2.5,0)
nColf := Round(195 + (nLargGet * 1,75) ,0)

DEFINE MSDIALOG oDlg TITLE cTitulo FROM 000.000 TO 120.nColF PIXEL


@ 005.005 TO 060, Round(nColF/2,0) OF oDlg PIXEL
@ 010.010 SAY cSay SIZE 55, 7 OF oDlg PIXEL
@ 010.065 MSGET cTexto SIZE nLargGet, 11 OF oDlg PIXEL ;
Picture "@!" VALID !Empty(cTexto)
DEFINE SBUTTON FROM 030, 010 TYPE 1 ;
ACTION (nOpca := 1.oDlg:End()) ENABLE OF oDlg
DEFINE SBUTTON FROM 030, 040 TYPE 2 ;
ACTION (nOpca := 0.oDlg:End()) ENABLE OF oDlg
ACTIVATE MSDIALOG oDlg CENTERED

cTexto := IIF(nOpca==1.cTexto,"")

RETURN cTexto

Manipulación de arrays.

Array()

La función Array() se utiliza en la definición de variables de tipo array, como


una opción de sintaxis, utilizando llaves (“{}”).

; Sintaxis: Array(nLinhas, nColunas)


; Parámetros:

nLinhas Determina el número de líneas con las cuales se creará el array.


nColunas Determina el número de columnas con las cuales se creará el
array.

Ejemplo:

aDados := Array(3.3) // Crea un array de tres líneas, cada cual con 3 columnas.

Página 196 Introducción a la Programación ADVPL I


Aunque el array definido por el comando Array() tenga la estructura
solicitada, no tiene contenido en ninguno de sus elementos, es decir:

aDados[1] -> array de tres posiciones

aDados[1][1] -> posición válida, pero con contenido nulo.

AADD()

La función AADD() permite la inserción de un ítem en un array existente, cuyo


ítem puede ser un simple elemento, un objeto u otro array.

; Sintaxis: AADD(aArray, xItem)


; Parámetros:

aArray Array existente en el cual se agregará el ítem definido en xItem.


xItem Ítem que se agregará al array.

Ejemplo:

aDados := {} // Define que la variable aDados es un array, sin especificar sus


dimensiones.
aItem := {} // Define que la variable aItem es un array, sin especificar sus
dimensiones.

AADD(aItem, cVariavel1) // Agrega un elemento en el array aItem de acuerdo con el


cVariavel1
AADD(aItem, cVariavel2) // Agrega un elemento en el array aItem de acuerdo con el
cVariavel2
AADD(aItem, cVariavel3) // Agrega un elemento en el array aItem de acuerdo con el
cVariavel3

// En este punto el array aItem tiene 03 elementos, los cuales pueden accederse con:
// aItem[1] -> corresponde al contenido de cVariavel1
// aItem[2] -> corresponde al contenido de cVariavel2
// aItem[3] -> corresponde al contenido de cVariavel3

AADD(aDados,aItem) // Agrega en el array aDados el contenido del array aItem

Ejemplo (continuación):

Introducción a la Programación ADVPL I Página 197


// En este punto, el array a aDados sólo tiene un elemento, que también es un array
// con 03 elementos:
// aDados [1][1] -> corresponde al contenido de cVariavel1
// aDados [1][2] -> corresponde al contenido de cVariavel2
// aDados [1][3] -> corresponde al contenido de cVariavel3

AADD(aDados, aItem)
AADD(aDados, aItem)

// En este punto, el array aDados tiene 03 elementos, donde cada cual es un array
con otros
// 03 elementos, donde:

// aDados [1][1] -> corresponde al contenido de cVariavel1


// aDados [1][2] -> corresponde al contenido de cVariavel2
// aDados [1][3] -> corresponde al contenido de cVariavel3

// aDados [2][1] -> corresponde al contenido de cVariavel1


// aDados [2][2] -> corresponde al contenido de cVariavel2
// aDados [2][3] -> corresponde al contenido de cVariavel3

// aDados [3][1] -> corresponde al contenido de cVariavel1


// aDados [3][2] -> corresponde al contenido de cVariavel2
// aDados [3][3] -> corresponde al contenido de cVariavel3

// De esta manera, el array aDados se elabora con una estructura de 03 líneas y 03


columnas, con
// el contenido definido por variables externas, pero con las misma forma obtenida
para el uso del
// comando: aDados := ARRAY(3.3).

ACLONE()

La función ACLONE() realiza la copia de los elementos de un array a otro array


integralmente.

; Sintaxis: AADD(aArray)
; Parámetros:

aArray Array existente que tendrá su contenido copiado al array


especificado.

Página 198 Introducción a la Programación ADVPL I


Ejemplo:

// Si se utiliza el array aDados, utilizado en el ejemplo de la función AADD()


aItens := ACLONE(aDados).

// En este punto, el array aItens tiene exactamente la misma estructura e información


del array
// aDados.

Por ser una estructura de memoria, un array no puede simplemente


copiarse a otro array, por medio de una atribución simple (“:=”).

Para más información sobre la necesidad de utilizar el comando


ACLONE(), verifique el tópico 6.1.3 – Copia de Arrays.

ADEL()

La función ADEL() permite borrar un elemento del array. Al borrar un


elemento, todos los otros se reorganizan, de tal manera que la última posición
del array será nula.

; Sintaxis: ADEL(aArray, nPosição)


; Parámetros:

aArray Array del cual se desea borrar una determinada posición.


nPosição Posición del array que se borrará.

Ejemplo:

// Cuando se utiliza el array aItens del ejemplo de la función ACLONE() tenemos:

ADEL(aItens,1) // Se borrará el primer elemento del array aItens.

// En este punto, el array aItens continúa con 03 elementos, donde:


// aItens[1] -> antiguo aItens[2], el cual se reordenó a consecuencia del borrado del
ítem 1.
// aItens[2] -> antiguo aItens[3], el cual se reordenó a consecuencia del borrado del
ítem 1.
// aItens[3] -> contenido nulo, porque se trata del ítem borrado.

Introducción a la Programación ADVPL I Página 199


ASIZE()

La función ASIZE permite la redefinición de la estructura de un array que ya


existe, agregando o eliminando ítems de éste.

; Sintaxis: ASIZE(aArray, nTamanho)


; Parámetros:

aArray Array existente que tendrá su estructura redimensionada.


nTamanho Tamaño con el cual se desea redefinir el array. Si el tamaño es
menor al actual, se borrarán los elementos finales del array, si el
tamaño es mayor al actual se insertarán ítem nulos al final del
array.

Ejemplo:

// Cuando se utiliza el array aItens, el cual tuvo un elemento borrado por el uso de la
función ADEL()

ASIZE(aItens,Len(aItens-1)).

// En este punto el array aItens tiene 02 elementos, ambos con contenidos válidos.

Utilizar la función ASIZE(), después del uso de la función ADEL(), es una


práctica recomendada y evita que se acceda a una posición del array
con un contenido inválido para la aplicación en uso.

ASORT()

La función ASORT() permite que los ítems de un array se ordenen a partir de


un criterio establecido previamente.

; Sintaxis: ASORT(aArray, nInicio, nItens, bOrdem)


; Parámetros:

aArray Array existente que tendrá se contenido ordenado por medio de


un criterio establecido.

Página 200 Introducción a la Programación ADVPL I


nInicio Posición inicial del array para inicio del orden. Si no se informa, el
array se ordenará a partir de su primer elemento.
nItens En lo que se refiere a ítems, estos deben ordenarse a partir de la
posición inicial. Si no se informa, se ordenarán todos los
elementos del array.
bOrdem Bloque de código que permite la definición del criterio de orden
del array. Si no se informa el bOrdem, se utilizará el criterio
ascendente.

Un bloque de código es básicamente una función escrita en línea. De


esta manera, su estructura debe “soportar” todos los requisitos de una
función que se reciben por medio del análisis y la interpretación de
parámetros recibidos, ejecutar un procesamiento y proporcionar una
devolución.

Con base en este requisito puede definirse un bloque de código con la


siguiente estructura:

bBloco := { |xPar1, xPar2, ... xParZ| Ação1, Ação2, AçãoZ } , donde:

|| -> define el intervalo donde están incluidos los parámetros

Ação Z-> expresión que se ejecutará por medio del bloque de código

Ação1... AçãoZ -> intervalo de expresiones que se ejecutarán por medio


del bloque de código, en el formato de lista de expresiones.

Devolución -> resultado de la última acción ejecutada por el bloque de


código, en el caso de AçãoZ.

Para más detalles sobre la estructura y utilización de bloques de


código, consulte el tópico 6.2 – Listas de Expresiones y Bloques de
código.

Ejemplo 01 – Orden ascendente

aAlunos := { “Mauren”, “Soraya”, “Andrea”}

aSort(aAlunos)

// En este punto, los elementos del array aAlunos serán {“Andrea”, “Mauren”,
“Soraya”}

Introducción a la Programación ADVPL I Página 201


Ejemplo 02 – Orden descendente

aAlunos := { “Mauren”, “Soraya”, “Andrea”}


bOrdem := {|x,y| x > y }

// Durante la ejecución de la función aSort(), la variable “x” recibirá el contenido del


ítem que está
// marcado. Como el ítem que está marcado es la posición aAlunos[x] y aAlunos[x] -
>
// string que contiene el nombre de un alumno, puede sustituir “x” por cNomeAtu.
// La variable “y” recibirá el contenido del próximo ítem que se evaluará y usando la
misma
// analogía de “x”, puede sustituirse “y” por cNomeProx. De esta manera el bloque
de código
// bOrdem puede reescribirse como:

bOrdem := {|cNomeAtu, cNomeProx| cNomeAtu > cNomeProx}

aSort(aAlunos,,bOrdem)

// En este punto, los elementos del array aAlunos serán {“Soraya” , “Mauren”,
“Andrea”}

ASCAN()

La función ASCAN() permite que se identifique la posición del array que


contiene una determinada información, por medio del análisis de una
expresión descrita en un bloque de código.

; Sintaxis: ASCAN(aArray, bSeek)


; Parámetros:

aArray Array existente en el cual se desea identificar la posición que


contiene la información consultada.
bSeek Bloque de código que configura los parámetros de la búsqueda
que se realizará.

Ejemplo:

aAlunos := {“Márcio”, “Denis”, “Arnaldo”, “Patrícia”}

bSeek := {|x| x == “Denis”}

nPosAluno := aScan(aAlunos,bSeek) // devolución esperada Æ 2

Página 202 Introducción a la Programación ADVPL I


Durante la ejecución de la función aScan, la variable “x” recibirá el
contenido del ítem que está marcado en el momento, en este caso
aAlunos[x]. Como aAlunos[x] es una posición del array que contiene el
nombre del aluno, “x” podría renombrarse como cNome y la definición
del bloque bSeek podría reescribirse como:

bSeek := {|cNome| cNome == “Denis”}

En la definición de los programas siempre es recomendable utilizar


variables con nombres significativos, de esta manera los bloques de
código no son excepción.

Opte siempre por analizar cómo se utilizará el bloque de código y al


contrario de “x”, “y” y similares, defina los parámetros con nombres que
representen su contenido. Será más sencillo su entendimiento y el
entendimiento de otro que analicen el código escrito.

AINS()

La función AINS() permite la inserción de un elemento en el array especificado,


en cualquier punto de la estructura de éste, prorrogando de esta manera, la
función AADD(), la cual siempre inserta un nuevo elemento al final de la
estructura existente.

; Sintaxis: AINS(aArray, nPosicao)


; Parámetros:

aArray Array existente en el cual se desea insertar un nuevo elemento.


nPosicao Posición el cual se insertará el nuevo elemento.

Ejemplo:

aAlunos := {“Edson”, “Robson”, “Renato”, “Tatiana”}

AINS(aAlunos,3)

// En este punto el array aAlunos tendrá el siguiente contenido:


// {“Edson”, “Robson”, nulo, “Renato”, “Tatiana”}

Introducción a la Programación ADVPL I Página 203


Similar al efecto de la función ADEL(), el elemento insertado en el array
por medio de la función AINS() tendrá un contenido nulo, que será
necesario tratarlo después de la realización de este comando.

Manipulación de bloques de código

EVAL()

La función EVAL() se utiliza para la evaluación directa de un bloque de código,


utilizando la información disponible en el momento de su ejecución. Esta
función permite la definición y paso de diversos parámetros que se
considerarán en la interpretación del bloque de código.

; Sintaxis: EVAL(bBloco, xParam1, xParam2, xParamZ)


; Parámetros:

bBloco Bloque de código que se interpretará.


xParamZ Parámetros que se pasarán al bloque de código. A partir del
pasaje del bloque, todos los otros parámetros de la función se
convertirán en parámetros para la interpretación del código.

Ejemplo:

nInt := 10
bBloco := {|N| x:= 10, y:= x*N, z:= y/(x*N)}

nValor := EVAL(bBloco, nInt)

// La devolución se realizará por la evaluación de la última acción de la lista de


expresiones, en este caso “z”.
// Cada una de las variables definidas, en una de las acciones de la lista de
expresiones, queda disponible
// para la próxima acción.
// De esta manera tenemos:
// N Æ recibe nInt como parámetro (10)
// X Æ tiene el valor 10 (10)
// Y Æ es el resultado de la multiplicación de X por N (100)
// Z Æ es el resultado de la división de Y por la multiplicación de X por N ( 100 /
100) Æ 1

Página 204 Introducción a la Programación ADVPL I


DBEVAL()

La función DBEval() permite que se analicen todos los registros de una


determinada tabla y que para cada registro se ejecute el bloque de código
definido.

; Sintaxis: Array(bBloco, bFor, bWhile)


; Parámetros

bBloco Bloque de código principal que contiene las expresiones que se


evaluarán para cada registro del alias activo.

bFor Condición para continuar el análisis de los registros, con el efecto


de una estructura For ... Next.

bWhile Condición para continuar el análisis de los registros, con el efecto


de una estructura While ... End.

Ejemplo 01

Si consideramos el trecho del siguiente código:

dbSelectArea(“SX5”)
dbSetOrder(1)
dbGotop()

While !Eof() .And. X5_FILIAL == xFilial("SX5") .And.; X5_TABELA <= mv_par02

nCnt++
dbSkip()
End

Lo mismo puede reescribirse con el uso de la función DBEVAL():

dbEval( {|x| nCnt++ },,{||X5_FILIAL==xFilial("SX5") .And. X5_TABELA<=mv_par02})

Ejemplo 02

Si consideramos el trecho del siguiente código:

dbSelectArea(“SX5”)
dbSetOrder(1)
dbGotop()

Introducción a la Programación ADVPL I Página 205


While !Eof() .And. X5_TABELA == cTabela
AADD(aTabela,{X5_CHAVE, Capital(X5_DESCRI)})
dbSkip()
End

Ejemplo 02 (continuación):

Lo mismo puede reescribirse con el uso de la función DBEVAL():

dbEval({|| aAdd(aTabela,{X5_CHAVE,Capital(X5_DESCRI)})},,{|| X5_TABELA==cTabela})

En la utilización de la función DBEVAL(), sólo debe informarse uno de


los dos parámetros: bFor o bWhile.

AEVAL()

La función AEVAL() permite que se analicen todos los elementos de una


determinada array y que para cada elemento se ejecute el bloque de código
definido.

; Sintaxis: AEVAL(aArray, bBloco, nInicio, nFim)


; Parámetros:

aArray Array que se evaluará en la ejecución de la función.


bBloco Bloque de código principal que contiene las expresiones que se
evaluarán para cada elemento del array informado.

nInicio Elemento inicial del array, a partir del cual se evaluarán los bloques
de código.
nFim Elemento final del array, hasta el cual se evaluarán los bloques de
código.

Ejemplo 01:

Si consideramos el trecho del siguiente código:

AADD(aCampos,”A1_FILIAL”)
AADD(aCampos,”A1_COD”)
SX3->(dbSetOrder(2))
For nX:=1 To Len(aCampos)

Página 206 Introducción a la Programación ADVPL I


SX3->(dbSeek(aCampos[nX]))
aAdd(aTitulos,AllTrim(SX3->X3_TITULO))
Next nX

Lo mismo puede reescribirse con el uso de la función AEVAL():

aEval(aCampos,{|x| SX3->(dbSeek(x)),IIF(Found(), AAdd(aTitulos,;


AllTrim(SX3->X3_TITULO)))})

Manipulación de strings

ALLTRIM()

Devuelve una string sin los espacios a la derecha y a la izquierda, referente al


contenido informado como parámetro.

La función ALLTRIM() implementa las acciones de las funciones RTRIM (“right


trim”) y LTRIM (“left trim”).

; Sintaxis: ALLTRIM(cString)
; Parámetros:

cString String que se evaluará para borrar los espacios a la derecha y a la


izquierda.

Ejemplo:

cNome := ALLTRIM(SA1->A1_NOME)

MSGINFO(“Dados do campo A1_NOME:”+CRLF


“Tamaño:” + CVALTOCHAR(LEN(SA1->A1_NOME))+CRLF
“Texto:” + CVALTOCHAR(LEN(cNome)))

ASC()

Convierte una información carácter en su valor, de acuerdo con la tabla ASCII.

; Sintaxis: ASC(cCaractere)
; Parámetros:

Introducción a la Programación ADVPL I Página 207


cCaractere Carácter que se consultará en la tabla ASCII.

Ejemplo:

USER FUNCTION NoAcento(Arg1)


Local nConta := 0
Local cLetra := ""
Local cRet := ""
Arg1 := Upper(Arg1)
For nConta:= 1 To Len(Arg1)
cLetra := SubStr(Arg1, nConta, 1)
Do Case
Case (Asc(cLetra) > 191 .and. Asc(cLetra) < 198) .or.;
(Asc(cLetra) > 223 .and. Asc(cLetra) < 230)
cLetra := "A"
Case (Asc(cLetra) > 199 .and. Asc(cLetra) < 204) .or.;
(Asc(cLetra) > 231 .and. Asc(cLetra) < 236)
cLetra := "E"

Case (Asc(cLetra) > 204 .and. Asc(cLetra) < 207) .or.;


(Asc(cLetra) > 235 .and. Asc(cLetra) < 240)
cLetra := "I"

Case (Asc(cLetra) > 209 .and. Asc(cLetra) < 215) .or.;


(Asc(cLetra) == 240) .or. (Asc(cLetra) > 241 .and. Asc(cLetra) < 247)
cLetra := "O"

Case (Asc(cLetra) > 216 .and. Asc(cLetra) < 221) .or.;


(Asc(cLetra) > 248 .and. Asc(cLetra) < 253)
cLetra := "U"

Case Asc(cLetra) == 199 .or. Asc(cLetra) == 231


cLetra := "C"

EndCase

cRet := cRet+cLetra

Next

Return UPPER(cRet)

Página 208 Introducción a la Programación ADVPL I


AT()

Devuelve a la primera posición de un carácter o string, dentro de otra string


especificada.

; Sintaxis: AT(cCaractere, cString )


; Parámetros:

cCaractere Carácter o string que se desea verificar.


cString String en la cual se verificará la existencia del contenido de
cCaractere.

Ejemplo:

STATIC FUNCTION NOMASCARA(cString,cMascara,nTamanho)

LOCAL cNoMascara := ""


LOCAL nX := 0

IF !Empty(cMascara) .AND. AT(cMascara,cString) > 0


FOR nX := 1 TO Len(cString)
IF !(SUBSTR(cString,nX,1) $ cMascara)
cNoMascara += SUBSTR(cString,nX,1)
ENDIF
NEXT nX

cNoMascara := PADR(ALLTRIM(cNoMascara),nTamanho)
ELSE
cNoMascara := PADR(ALLTRIM(cString),nTamanho)
ENDIF

RETURN cNoMascara

CHR()

Convierte un valor número referente a una información de la tabla ASCII, en el


carácter que esta información representa.

; Sintaxis: CHR(nASCII)
; Parámetros:

nASCII Código ASCII del carácter.

Ejemplo:

Introducción a la Programación ADVPL I Página 209


#DEFINE CRLF CHR(13)+CHR(10) // FINAL DE LÍNEA

LEN()

Devuelve el tamaño de la string especificada en el parámetro.

; Sintaxis: LEN(cString)
; Parámetros:

cString String que se evaluará.

Ejemplo:

cNome := ALLTRIM(SA1->A1_NOME)

MSGINFO(“Datos del campo A1_NOME:”+CRLF


“Tamaño:” + CVALTOCHAR(LEN(SA1->A1_NOME))+CRLF
“Texto:” + CVALTOCHAR(LEN(cNome)))

LOWER()

Devuelve una string con todos los caracteres minúsculos, con base en la string
considerada como parámetro.

; Sintaxis: LOWER(cString)
; Parámetros:

cString String que se convertirá a caracteres minúsculos.

Ejemplo:

cTexto := “ADVPL”

MSGINFO(“Texto:”+LOWER(cTexto))

Página 210 Introducción a la Programación ADVPL I


RAT()

Devuelve la última posición de un carácter o string, dentro de otra string


especificada.

; Sintaxis: RAT(cCaractere, cString )


; Parámetros:

cCaractere Carácter o string que se desea verificar.


cString String en la cual se verificará la existencia del contenido de
cCaractere.

STUFF()

Permite sustituir un contenido carácter en una string existente, especificando


la posición inicial para esta adición y el número de caracteres que se
sustituirán.

; Sintaxis: STUFF(cString, nPosInicial, nExcluir, cAdicao)


; Parámetros:

Ejemplo:

cLin := Space(100)+cEOL // Crea la string base

cCpo := PADR(SA1->A1_FILIAL,02) // Información que se almacenará en la string

cLin := Stuff(cLin,01,02,cCpo) // Sustituye el contenido de cCpo en la string base

SUBSTR()

Devuelve parte del contenido de una string especificada, de acuerdo con la


posición inicial de este contenido en la string e incluso, la cantidad de
caracteres que debe devolverse a partir de aquel punto.

; Sintaxis: SUBSTR(cString, nPosInicial, nCaracteres)


; Parámetros:

cString String que se desea verificar


nPosInicial Posición inicial de la información que se extraerá de la string

Introducción a la Programación ADVPL I Página 211


nCaracteres Cantidad de caracteres que deben devolverse incluso a partir de
aquel punto.

Ejemplo:
cCampo := “A1_NOME”
nPosUnder := AT(cCampo)

cPrefixo := SUBSTR(cCampo,1, nPosUnder) // Æ “A1_”

UPPER()

Devuelve una string con todos los caracteres mayúsculos, con base en la string
considerada como parámetro.

; Sintaxis: UPPER(cString)
; Parámetros:

cString String que se convertirá a caracteres mayúsculos

Ejemplo:

cTexto := “advpl”

MSGINFO(“Texto:”+LOWER(cTexto))

Manipulación de variables numéricas

ABS()

Devuelve un valor absoluto (independientemente del signo) con base en el


valor especificado en el parámetro.

; Sintaxis: ABS(nValor)
; Parámetros:

nValor Valor que se evaluará

Página 212 Introducción a la Programación ADVPL I


Ejemplo:

nPessoas := 20
nLugares := 18

IF nPessoas < nLugares


MSGINFO(“Existen”+CVALTOCHAR(nLugares- nPessoas)+“disponibles”)
ELSE
MSGSTOP(“Existen ”+CVALTOCHAR(ABS(nLugares- nPessoas))+“faltando”)
ENDIF

INT()

Devuelve la parte entera de un valor especificado en el parámetro.

; Sintaxis: INT(nValor)
; Parámetros:

nValor Valor que se evaluará

Ejemplo:

STATIC FUNCTION COMPRAR(nQuantidade)

LOCAL nDinheiro := 0,30


LOCAL nPrcUnit := 0,25

IF nDinheiro >= (nQuantidade*nPrcUnit)


RETURN nQuantidade
ELSEIF nDinheiro > nPrcUnit
nQuantidade := INT(nDinheiro / nPrcUnit)
ELSE
nQuantidade := 0
ENDIF

RETURN nQuantidade

NOROUND()

Devuelve un valor, truncando la parte decimal del valor especificado en el


parámetro de acuerdo con la cantidad de decimales solicitados.

Introducción a la Programación ADVPL I Página 213


; Sintaxis: NOROUND(nValor, nCasas)
; Parámetros:

nValor Valor que se evaluará


nCasas Número de decimales válidos. A partir del decimal especificado no
se considerarán los valores.

Ejemplo:

nBase := 2.985
nValor := NOROUND(nBase,2) Æ 2.98

ROUND()

Devuelve un valor, redondeando la parte decimal del valor especificado en el


parámetro, de acuerdo con las cantidades de decimales solicitados, utilizando
el criterio matemático.

; Sintaxis: ROUND(nValor, nCasas)


; Parámetros:

nValor Valor que se evaluará


nCasas Número de decimales válidos. Los otros decimales sufrirán el
redondeo matemático, donde:

Si nX <= 4 Æ 0, sino +1 para el decimal superior.

Ejemplo:

nBase := 2.985
nValor := ROUND(nBase,2) Æ 2.99

Página 214 Introducción a la Programación ADVPL I


Manipulación de archivos

SELECT()

Determina el número de referencia de un determinado alias en un entorno de


trabajo. Si el alias especificado no estuviera en uso en el entorno, se devolverá
el valor 0 (cero).

; Sintaxis: Select(cArea)
; Parámetros:

cArea Nombre de referencia del área de trabajo que se verificará

Ejemplo:

nArea := Select(“SA1”)

ALERT(“Referencia del alias SA1: ”+STRZERO(nArea,3)) // Æ 10 (propuesto)

DBGOTO()

Mueve el cursor del área de trabajo activa al record number (recno)


especificado, realizando una localización directa, sin necesidad de búsqueda
(seek) previa.

; Sintaxis: DbGoto(nRecno)
; Parámetros:

nRecno Record number del registro que se marcará.

Ejemplo:
DbSelectArea(“SA1”)
DbGoto(100) // Marca en el registro 100

IF !EOF() // Si el área de trabajo no estuviera al final del archivo


MsgInfo(“Está en el cliente:”+A1_NOME)
ENDIF

Introducción a la Programación ADVPL I Página 215


DBGOTOP()

Mueve el cursor del área de trabajo activa al primer registro lógico.

; Sintaxis: DbGoTop()
; Parámetros:

Ninguno .

Ejemplo:

nCount := 0 // Variable para verificar cuántos registros hay en el intervalo


DbSelectArea(“SA1”)
DbSetOrder(1) // A1_FILIAL + A1_COD + A1_LOJA
DbGoTop()

While !BOF() // Mientras no sea el inicio del archivo


nCount++ // Incrementa la variable de control de registros en el intervalo
DbSkip(-1)
End

MsgInfo(“Existen :”+STRZERO(nCount,6)+ “registros en el intervalo”).

// Devolución esperada :000001, pues el DbGoTop se encuentra localizado en el


primer registro.

DBGOBOTTON()

Mueve el cursor del área de trabajo activa al último registro lógico.

; Sintaxis: DbGoBotton()
; Parámetros:

Ninguno .

Página 216 Introducción a la Programación ADVPL I


Ejemplo:

nCount := 0 // Variable para verificar cuántos registros hay en el intervalo


DbSelectArea(“SA1”)
DbSetOrder(1) // A1_FILIAL + A1_COD + A1_LOJA
DbGoBotton()

While !EOF() // Mientras no sea el inicio del archivo


nCount++ // Incrementa la variable de control de registros en el intervalo
DbSkip(1)
End

MsgInfo(“Existen :”+STRZERO(nCount,6)+ “registros en el intervalo”).

// Devolución esperada :000001, pues el DbGoBotton se encuentra localizado en el


último registro.

DBSELECTAREA()

Define el área de trabajo especificada como el área activa. Todas las


operaciones subsiguientes que hagan referencia a un área de trabajo para
utilización, a menos que el área deseada se informe explícitamente.

; Sintaxis: DbSelectArea(nArea | cArea)


; Parámetros:

Valor numérico que representa el área deseada, en función de


nArea todas las áreas abiertas por la aplicación, que puede utilizarse al
contrario del nombre del área.
cArea Nombre de referencia del área de trabajo que se seleccionará.

Ejemplo 01: DbselectArea(nArea)

nArea := Select(“SA1”) // Æ 10 (propuesto)

DbSelectArea(nArea) // De acuerdo con la devolución del comando Select().

ALERT(“Nombre del cliente: ”+A1_NOME) // Como el SA1 es el alias seleccionado,


los comandos
// a partir de la selección del alias consideran que
esté
// está implícito en la expresión, lo que causa el
mismo
// efecto de SA1->A1_NOME.

Introducción a la Programación ADVPL I Página 217


Ejemplo 01: DbselectArea(cArea)

DbSelectArea(“SA1”) // Especificación directa del alias que se desea seleccionar.

ALERT(“Nombre del cliente: ”+A1_NOME) // Como el SA1 es el alias seleccionado,


los comandos
// a partir de la selección del alias consideran que
esté
// está implícito en la expresión, lo que causa el
mismo
// efecto de SA1->A1_NOME.

DBSETORDER()

Define qué índice se utilizará por el área de trabajo activa, es decir, por el área
previamente seleccionada por medio del comando DbSelectArea(). Los
órdenes disponibles en el Entorno Protheus son aquellos definidos en el
SINDEX /SIX, o los órdenes puestos a disposición por medio de índices
temporales.

; Sintaxis: DbSetOrder(nOrdem)
; Parámetros:

Número de referencia del orden que desea definirse como orden


nOrdem
activa para el área de trabajo.

Ejemplo:

DbSelectArea(“SA1”)
DbSetOrder(1) // De acuerdo con el archivo SIX -> A1_FILIAL+A1_COD+A1_LOJA

DBORDERNICKNAME()

Define qué índice creado por el usuario se utilizará. El usuario puede incluir sus
propios índices y en el momento de la inclusión debe crear su NICKNAME.

; Sintaxis: DbOrderNickName(NickName)
; Parámetros:

NickName NickName atribuido al índice creado por el usuario.

Página 218 Introducción a la Programación ADVPL I


Ejemplo:

DbSelectArea(“SA1”)
DbOrderNickName(“Tipo”) // De acuerdo con el archivo SIX -> A1_FILIAL+A1_TIPO
NickName: Tipo

DBSEEK() y MSSEEK()

DbSeek: Con el cursor del área de trabajo activa es posible marcar el registro
con la información especificada en la clave de búsqueda, suministrando una
devolución lógica que indica si la localización se realizó con éxito, es decir, si la
información especificada en la clave de búsqueda se localizó en el área de
trabajo.

; Sintaxis: DbSeek(cChave, lSoftSeek, lLast)


; Parámetros

Datos del registro que se desea localizar, de acuerdo con el orden


de búsqueda previamente especificada por el comando
cChave
DbSetOrder(), es decir, de acuerdo con el índice activo en el
momento para el área de trabajo.
Define si el cursor se quedará en el próximo registro válido, con
relación a la clave de búsqueda especificada, o al final del archivo,
lSoftSeek
si no se encuentra exactamente la información de la clave.
Estándar Æ .F.
Define si el cursor se quedará en el primer o en el último registro
lLast de un intervalo, con la misma información especificada en la
clave. Estándar Æ .F.

Ejemplo 01 – Búsqueda exacta

DbSelectArea(“SA1”)
DbSetOrder(1) // de acuerdo con el archivo SIX -> A1_FILIAL+A1_COD+A1_LOJA

IF DbSeek(“01” + “000001” + “02” ) // Sucursal: 01, Código: 000001, Tienda: 02

MsgInfo(“Cliente localizado”, “Consulta por cliente”)

Else
MsgAlert(“Cliente no encontrado”, “Consulta por cliente”)

Endif

Introducción a la Programación ADVPL I Página 219


Ejemplo 02 – Búsqueda aproximada

DbSelectArea(“SA1”)
DbSetOrder(1) // de acuerdo con el archivo SIX -> A1_FILIAL+A1_COD+A1_LOJA

DbSeek(“01” + “000001” + “02”, .T. ) // Sucursal: 01, Código: 000001, Tienda: 02

// Muestra los datos del cliente localizado, el cual puede no ser el que se especificó
en la clave:

MsgInfo(“Datos del cliente localizado: ”+CRLF +;


“Sucursal:” + A1_FILIAL + CRLF +;
“Código:” + A1_COD + CRLF +;
“Tienda:” + A1_LOJA + CRLF +;
“Nombre:” + A1_NOME + CRLF, “Consulta por cliente”)

MsSeek(): Función desarrollada por el área de Tecnología de Microsiga, la cual tiene


las mismas funcionalidades básicas de la función DbSeek(), con la ventaja de no
necesitar acceder nuevamente a la base de datos para localizar una información
utilizada por la thread (conexión) activa.

De esta manera, la thread mantiene en memoria los datos necesarios para


reposicionar los registros localizados por medio del comando DbSeek (en este caso,
el Recno()), de tal manera que la aplicación puede simplemente realizar el
posicionamiento sin ejecutar la búsqueda nuevamente.

La diferencia entre el DbSeek() y el MsSeek() se nota en aplicaciones con gran


volumen de posicionamientos, como informes, que necesitan referenciar diversas
veces el mismo registro, durante una ejecución.

DBSKIP()

Mueve el cursor del registro marcado al próximo o al anterior, dependiendo


del parámetro, en función del orden activo para el área de trabajo.

; Sintaxis: DbSkip(nRegistros)
; Parámetros:

nRegistros Define en cuántos registros se desplazará el cursor. Estándar Æ 1

Ejemplo 01 – Avanzando registros

DbSelectArea(“SA1”)
DbSetOrder(2) // A1_FILIAL + A1_NOME

Página 220 Introducción a la Programación ADVPL I


DbGotop() // Posiciona el cursor al inicio del área de trabajo activa.

While !EOF() // Mientras el cursor del área de trabajo activa no indica el final del
archivo
MsgInfo(“Está en el cliente:” + A1_NOME)
DbSkip()
End

Ejemplo 02 – Retrocediendo registros

DbSelectArea(“SA1”)
DbSetOrder(2) // A1_FILIAL + A1_NOME
DbGoBotton() // Posiciona el cursor al final del área de trabajo activa.

While !BOF() // Mientras el cursor del área de trabajo activa no indica el inicio del
archivo
MsgInfo(“Está en el cliente:” + A1_NOME)
DbSkip(-1)
End

DBSETFILTER()

Define un filtro para el área de trabajo activa, lo cual puede describirse en la


forma de un bloque de código o por medio de una expresión sencilla

; Sintaxis: DbSetFilter(bCondicao, cCondicao)


; Parámetros:

bCondicao Bloque que expresa la condición de filtro en forma ejecutable


cCondicao Expresión de filtro simple en forma de string

Ejemplo 01 – Filtro con bloque de código

bCondicao := {|| A1_COD >= “000001” .AND. A1_COD <= “001000”}


DbSelectArea(“SA1”)
DbSetOrder(1)
DbSetFilter(bCondicao)
DbGoBotton()

While !EOF()
MsgInfo(“Está en el cliente:”+A1_COD)

Introducción a la Programación ADVPL I Página 221


DbSkip()
End

// El último cliente visualizado debe tener el código menor que “001000”.

Ejemplo 02 – Filtro con expresión simple

cCondicao := “A1_COD >= ‘000001’ .AND. A1_COD <= ‘001000’”


DbSelectArea(“SA1”)
DbSetOrder(1)
DbSetFilter(,cCondicao)
DbGoBotton()

While !EOF()
MsgInfo(“Está en el cliente:”+A1_COD)
DbSkip()
End

// El último cliente visualizado debe tener el código menor que “001000”.

DBSTRUCT()

Devuelve un array que contiene la estructura del área de trabajo (alias) activa.
La estructura será un array bidimensional, de acuerdo con lo siguiente:

ID* Nombre Tipo Tamaño Decimales


campo camp
o

*Índice del array

; Sintaxis: DbStruct()
; Parámetros:

Ninguno .

Ejemplo:

cCampos := “”
DbSelectArea(“SA1”)
aStructSA1 := DbStruct()

Página 222 Introducción a la Programación ADVPL I


FOR nX := 1 to Len(aStructSA1)

cCampos += aStructSA1[nX][1] + “/”

NEXT nX

ALERT(cCampos)

RECLOCK()

Efectúa el trabamiento del registro marcado en el área de trabajo activa,


permitiendo que se incluya o modifique su información.

; Sintaxis: RecLock(cAlias,lInclui)
; Parámetros:

cAlias Alias que identifica el área de trabajo que se manipulará.


Define si la operación será una inclusión (.T.) o una modificación
lInclui
(.F.).

Ejemplo 01 - Inclusión

DbSelectArea(“SA1”)
RecLock(“SA1”,.T.)
SA1->A1_FILIAL := xFilial(“SA1”) // Devuelve la sucursal, de acuerdo con las
configuraciones del ERP.
SA1->A1_COD := “900001”
SA1->A1_LOJA := “01”
MsUnLock() // Confirma y finaliza la operación.
Ejemplo 02 - Modificación

DbSelectArea(“SA1”)
DbSetOrder(1) // A1_FILIAL + A1_COD + A1_LOJA
DbSeek(“01” + “900001” + “01”) // Búsqueda exacta

IF Found() // Evalúa la devolución del último DbSeek realizado


RecLock(“SA1”,.F.)
SA1->A1_NOME := “CLIENTE CURSO ADVPL BÁSICO”
SA1->A1_NREDUZ := “ADVPL BÁSICO”
MsUnLock() // Confirma y finaliza la operación
ENDIF

Introducción a la Programación ADVPL I Página 223


El lenguaje ADVPL tiene variaciones de la función RecLock(), las cuales
son:

; RLOCK()

; DBRLOCK()

La sintaxis y la descripción de estas funciones están disponibles en el


Manual de Referencia Rápido al final de este material.

MSUNLOCK()

Libera el trabamiento (lock) del registro marcado, confirmando las


actualizaciones realizadas en este registro.

; Sintaxis: MsUnLock()
; Parámetros:

Ninguno .

Ejemplo:

DbSelectArea(“SA1”)
DbSetOrder(1) // A1_FILIAL + A1_COD + A1_LOJA
DbSeek(“01” + “900001” + “01”) // Búsqueda exacta

IF Found() // Evalúa la devolución del último DbSeek realizado


RecLock(“SA1”,.F.)
SA1->A1_NOME := “CLIENTE CURSO ADVPL BÁSICO”
SA1->A1_NREDUZ := “ADVPL BÁSICO”
MsUnLock() // Confirma y finaliza la operación
ENDIF

Página 224 Introducción a la Programación ADVPL I


El lenguaje ADVPL tiene variaciones de la función MsUnlock(), las
cuales son:

; UNLOCK()

; DBUNLOCK()

; DBUNLOCKALL()

La sintaxis y la descripción de estas funciones están disponibles en el


Manual de Referencia Rápido al final de este material.

SOFTLOCK()

Permite la reserva del registro marcado en el área de trabajo activa, de tal


manera que otras operaciones, con excepción de la actual, no puedan
actualizar este registro. Difiere de la función RecLock() porque no genera una
obligación de actualización y puede sustituirse por ésta.

En la aplicación ERP Protheus, la opción SoftLock() se utiliza en los browses,


antes de la confirmación de la operación de modificación y borrado, porque
en este momento ésta aún no se hizo efectiva, pero otras conexiones no
pueden acceder a aquel registro porque se encuentra en mantenimiento, lo
cual permite la integridad de la información.

; Sintaxis: SoftLock(cAlias)
; Parámetros:

Alias de referencia del área de trabajo activa, para la cual se


cAlias
trabará el registro marcado.

Ejemplo:

cChave := GetCliente() // Función ilustrativa que devuelve los datos de búsqueda de


un cliente.

DbSelectArea(“SA1”)
DbSetOrder(1)
DbSeek(cChave)

IF Found()
SoftLock() // Reserva el registro localizado

Introducción a la Programación ADVPL I Página 225


lConfirma := AlteraSA1() // Función ilustrativa que muestra los datos del
registro
// marcado y permite su modificación.

IF lConfirma
RecLock(“SA1”,.F.)
GravaSA1() // Función ilustrativa que modifica los datos de acuerdo con
AlertaSA1().
MsUnLock() // Liberado el RecLock() y el SoftLock() del registro.
EndIf
EndIf

DBDELETE()

Efectúa el borrado lógico del registro marcado en el área de trabajo activa.


Para ello, es necesaria su utilización en conjunto con las funciones RecLock() y
MsUnLock().

; Sintaxis: DbDelete()
; Parámetros:

Ninguno .

Ejemplo:
DbSelectArea(“SA1”)
DbSetOrder(1) // A1_FILIAL + A1_COD + A1_LOJA
DbSeek(“01” + “900001” + “01”) // Búsqueda exacta

IF Found()
RecLock(“SA1”,.F.) // Define que se realizará una modificación en el registro
marcado.
DbDelete() // Realiza el borrado lógico del registro marcado.
MsUnLock() // Confirma y finaliza la operación.
ENDIF

DBUSEAREA()

Define un archivo de base de datos como un área de trabajo disponible en la


aplicación.

; Sintaxis: DbUseArea(lNovo, cDriver, cArquivo, cAlias, lComparilhado,;


lSoLeitura)

Página 226 Introducción a la Programación ADVPL I


; Parámetros

Parámetro opcional que permite, si el cAlias especificado


lNovo estuviera en uso, que se cierre antes de la apertura del archivo
de la base de datos.
Driver que permita a la aplicación manipular el archivo de base
de datos especificado. La aplicación ERP tiene la variable
__LOCALDRIVER, definida a partir de las configuraciones del .ini
cDriver
del server de la aplicación.
Algunas claves válidas: “DBFCDX”, “CTREECDX”, “DBFCDXAX”,
“TOPCONN”.
Nombre del archivo de base de datos que se abrirá con el alias
cArquivo
especificado.
Alias para referencia de los archivos de base de datos por la
cAlias
aplicación.
lComparilhado Si el archivo podrá utilizarse para otras conexiones.
Si el archivo podrá modificarse por medio de la conexión
lSoLeitura
activa.

Ejemplo:

DbUserArea(.T., “DBFCDX”, “\SA1010.DBF”, “SA1DBF”, .T., .F.)


DbSelectArea(“SA1DBF”)
MsgInfo(“La tabla SA1010.DBF tiene:” + STRZERO(RecCount(),6) + “ registros.”)
DbCloseArea()

DBCLOSEAREA()

Permite que se cierre un alias presente en la conexión, lo que hace posible que
se utilice nuevamente en otra operación. Este comando sólo tiene efecto en el
alias activo en la conexión, haciéndose necesaria su utilización en conjunto con
el comando DbSelectArea().

; Sintaxis: DbCloseArea()
; Parámetros:

Ninguno .

Ejemplo:

DbUserArea(.T., “DBFCDX”, “\SA1010.DBF”, “SA1DBF”, .T., .F.)


DbSelectArea(“SA1DBF”)
MsgInfo(“La tabla SA1010.DBF tiene:” + STRZERO(RecCount(),6) + “ registros.”)

Introducción a la Programación ADVPL I Página 227


DbCloseArea()

Control de numeración secuencial

GETSXENUM()

Obtiene el número secuencia del alias especificado en el parámetro, por medio


de la referencia a los archivos de sistema SXE/SXF o al servidor de numeración,
cuando esta configuración está habilitada en el entorno Protheus.

; Sintaxis: GETSXENUM(cAlias, cCampo, cAliasSXE, nOrdem)


; Parámetros:

Alias de referencia de la tabla para la cual se realizará el control


cAlias
de la numeración secuencial
Nombre del campo en el cual está implementado el control de la
cCampo
numeración.
Parámetro opcional, cuando el nombre del alias en los archivos
cAliasSXE de control de numeración no es el nombre convencional del alias
para el sistema ERP.
Número del índice para verificar cuál es la próxima ocurrencia
nOrdem
del número.

CONFIRMSXE()

Confirma el número asignado por medio del último comando GETSXENUM().

; Sintaxis: CONFIRMSXE(lVerifica)
; Parámetros:

Verifica si el número confirmado no se modificó y


lVerifica consecuentemente, ya
existe en la base de datos.

Página 228 Introducción a la Programación ADVPL I


ROLLBACKSXE()

Descarta el número suministrado por el último comando GETSXENUM(),


devolviendo la numeración disponible a otras conexiones.

; Sintaxis: ROLLBACKSXE()
; Parámetros:

Ninguno .

Validación

EXISTCHAV()

Devuelve .T. o .F. si el contenido especificado existe en el alias especificado. Si


existiera, se mostrará un help de sistema con un aviso informando la
ocurrencia.

Esta función generalmente se utiliza para verificar si un determinado código


de archivo ya existe en la tabla. en el cual se incluirá la información, como por
ejemplo el Registro Nacional de Persona Jurídica (CNPJ) en el archivo de
clientes o proveedores.

; Sintaxis: ExistChav(cAlias, cConteudo, nIndice)


; Parámetros:

cAlias Alias de referencia para validación de la información


cConteudo Clave que se buscará, sin la sucursal
nIndice Índice de búsqueda para consulta de la clave

EXISTCPO()

Devuelve .T. o .F. si el contenido especificado existe en el alias especificado. Si


no existiera, se mostrará un help de sistema con un aviso informando la
ocurrencia.

Función que generalmente se utiliza para verificar si la información digitada en


un campo, que depende de otra tabla, realmente existe en aquella otra tabla,
como por ejemplo, el código de un cliente en un pedido de venta.

Introducción a la Programación ADVPL I Página 229


; Sintaxis: ExistCpo(cAlias, cConteudo, nIndice)
; Parámetros:

cAlias Alias de referencia para validación de la información


cConteudo Clave que se buscará, sin la sucursal
nIndice Índice de búsqueda para consulta de la clave

NAOVAZIO()

Devuelve .T. o .F. si el contenido del campo marcado en el momento no está


vacío.

; Sintaxis: NaoVazio()
; Parámetros:

Ninguno .

NEGATIVO()

Devuelve .T. o .F. si el contenido digitado para el campo es negativo.

; Sintaxis: Negativo()
; Parámetros:

Ninguno .

PERTENCE()

Devuelve .T. o .F. si el contenido digitado para el campo está incluido en la


string, definida como parámetro de la función. Generalmente se utiliza en
campos con la opción lista de opciones, porque de loo contrario se utilizaría la
función ExistCpo().

; Sintaxis: Pertence(cString)
; Parámetros:

Página 230 Introducción a la Programación ADVPL I


String que contiene la información válida que puede digitarse
cString
para un campo.

POSITIVO()

Devuelve .T. o .F. si el contenido digitado para el campo es positivo.

; Sintaxis: Positivo()
; Parámetros:

Ninguno .

TEXTO()

Devuelve .T. o .F. si el contenido digitado para el campo tiene solamente


números o alfanuméricos.

; Sintaxis: Texto()
; Parámetros:

Ninguno .

VAZIO()

Devuelve .T. o .F. si el contenido del campo marcado en el momento está


vacío.

; Sintaxis: Vazio()
; Parámetros:

Ninguno .

Introducción a la Programación ADVPL I Página 231


Parámetros

GETMV()

Devuelve el contenido del parámetro especificado en el archivo SX6,


considerando la sucursal parametrizada en la conexión. Si el parámetro no
existe, se mostrará un help del sistema informando la ocurrencia.

; Sintaxis: GETMV(cParametro)
; Parámetros:

Nombre del parámetro del sistema en el SX6, sin la especificación


cParametro
de la sucursal de sistema.

GETNEWPAR()

Devuelve el contenido del parámetro especificado en el archivo SX6,


considerando la sucursal parametrizada en la conexión. Si el parámetro no
existe, se mostrará un help del sistema informando la ocurrencia.

Difiere del SuperGetMV() pues considera que el parámetro puede no existir en


la versión actual del sistema y consecuentemente no se mostrará el mensaje
de help.

; Sintaxis: GETNEWPAR(cParametro, cPadrao, cFilial)


; Parámetros:

Nombre del parámetro del sistema en el SX6, sin la especificación


cParametro
de la sucursal de sistema.

Contenido estándar que se utilizará si el parámetro no existe en


cPadrao
el SX6.

Define para qué sucursal se realizará la consulta del parámetro.


cFilial
Estándar Æ sucursal corriente de la conexión.

Página 232 Introducción a la Programación ADVPL I


PUTMV()

Actualiza el contenido del parámetro especificado en el archivo SX6, de


acuerdo con las parametrizaciones informadas.

; Sintaxis: PUTMV(cParametro, cConteudo)


; Parámetros:

Nombre del parámetro del sistema en el SX6, sin la especificación


cParametro
de la sucursal de sistema
cConteudo Contenido que se atribuirá al parámetro en el SX6

SUPERGETMV()

Devuelve el contenido del parámetro especificado en el archivo SX6,


considerando la sucursal parametrizada en la conexión. Si el parámetro no
existe, se mostrará un help del sistema informando la ocurrencia.

Difiere del GetMv() porque los parámetros consultados se agregan en un área


de memoria, que permite que en una nueva consulta no sea necesario acceder
y buscar el parámetro en la base de datos.

; Sintaxis: SUPERGETMV(cParametro , lHelp , cPadrao , cFilial)


; Parámetros:

Nombre del parámetro del sistema en el SX6, sin la especificación


cParametro
de la sucursal de sistema.

Si se mostrará el mensaje de Help, cuando el parámetro no se


lHelp
encuentre en el SX6.

Contenido estándar que se utilizará si el parámetro no existe en


cPadrao
el SX6.

Define para qué sucursal se realizará la consulta del parámetro.


cFilial
Estándar Æ sucursal corriente de la conexión.

Introducción a la Programación ADVPL I Página 233


Componentes de la interfaz visual

MSDIALOG()

Define el componente MSDIALOG(), el cual se utiliza como base para los demás
componentes de la interfaz visual, pues un componente MSDIALOG() es una ventana
de la aplicación.

; Sintaxis:

DEFINE MSDIALOG oObjetoDLG TITLE cTitulo FROM nLinIni,nColIni TO


nLiFim,nColFim OF oObjetoRef UNIDADE

; Parámetros

Posición del objeto Say en función de la ventana en que se


oObjetoDLG
definirá
cTitulo Título de la ventana de diálogo
nLinIni, nColIni Posición inicial en línea / columna de la ventana
nLiFim, nColFim Posición final en línea / columna de la ventana
oObjetoRef Objeto dialog en el cual se definirá la ventana
UNIDAD Unidad de medida de las dimensiones: PIXEL

Ejemplo:

DEFINE MSDIALOG oDlg TITLE cTitulo FROM 000.000 TO 080.300 PIXEL


ACTIVATE MSDIALOG oDlg CENTERED

Página 234 Introducción a la Programación ADVPL I


MSGET()

Define el componente visual MSGET, el cual se utiliza para la captura de la


información digitable en la pantalla de la interfaz.

; Sintaxis:

@ nLinha, nColuna MSGET VARIAVEL SIZE nLargura,nAltura UNIDADE OF


oObjetoRef F3 cF3 VALID VALID WHEN WHEN PICTURE cPicture

; Parámetros

Posición del objeto MsGet en función de la ventana en que


nLinha, nColuna
se definirá
Variable de la aplicación que se vinculará al objeto MsGet,
VARIABLE que definirá sus características y en la cual se almacenará lo
que se informe en el campo
nLargura,nAltura Dimensiones del objeto MsGet para mostrar el texto
UNIDAD Unidad de medida de las dimensiones: PIXEL
oObjetoRef Objeto dialog en el que se definirá el componente
String que define la consulta estándar, la cual se vinculará al
cF3
campo
VALID Función de validación para el campo
Condición para manipulación del campo, la cual puede ser
WHEN directamente .T. o .F., o una variable o una llamada de
función
String que contiene la definición de la Picture de digitación
cPicture
del campo

Ejemplo:

@ 010.050 MSGET cCGC SIZE 55, 11 OF oDlg PIXEL PICTURE "@R 99,999,999/9999-
99";
VALID !Vazio()

Introducción a la Programación ADVPL I Página 235


SAY()

Define el componente visual SAY, el cual se utiliza para mostrar textos en una
pantalla de interfaz.

; Sintaxis:

@ nLinha, nColuna SAY cTexto SIZE nLargura,nAltura UNIDADE OF oObjetoRef

; Parámetros

Posición del objeto Say en función de la ventana en que se


nLinha, nColuna
definirá
cTexto Texto que se mostrará por el objeto Say
nLargura,nAltura Dimensiones del objeto Say para mostrar el texto
UNIDAD Unidad de medida de las dimensiones: PIXEL
oObjetoRef Objeto dialog en el que se definirá el componente

Ejemplo:

@ 010.010 SAY cTexto SIZE 55, 07 OF oDlg PIXEL

BUTTON()

Define el componente visual Button, con el cual es posible incluir botones de


operación en la pantalla de la interfaz, los cuales sólo se visualizarán con un
texto sencillo para su identificación.

; Sintaxis: BUTTON()

@ nLinha,nColuna BUTTON cTexto SIZE nLargura,nAltura UNIDADE OF oObjetoRef


ACTION ACCIÓN

; Parámetros

Posición del objeto Button en función de la ventana en que


nLinha,nColuna
se definirá
cTexto String que contiene el texto que se mostrará en el botón

Página 236 Introducción a la Programación ADVPL I


nLargura,nAltura Dimensiones del objeto Button para mostrar el texto.
UNIDAD Unidad de medida de las dimensiones: PIXEL
oObjetoRef Objeto dialog en el que se definirá el componente
Función o lista de expresiones que define el comportamiento
ACCIÓN
del botón cuando éste se utilice

Ejemplo:

010, 120 BUTTON “Confirmar” SIZE 080, 047 PIXEL OF oDlg;


ACTION (nOpca := 1.oDlg:End())

SBUTTON()

Define el componente visual SButton, el cual permite la inclusión de botones


de operación en la pantalla de la interfaz, los cuales se visualizarán
dependiendo de la interfaz del sistema ERP utilizada solamente con un texto
sencillo para su identificación, o con una imagen (BitMap) definida
previamente.

; Sintaxis: SBUTTON()

DEFINE SBUTTON FROM nLinha, nColuna TYPE N ACTION AÇÃO STATUS OF


oObjetoRet

; Parámetros

Posición del objeto sButton en función de la ventana en que


nLinha, nColuna
se definirá
Número que indica el tipo de botón (imagen) definido
TYPE N
previamente que se utilizará
Función o lista de expresiones que define el comportamiento
ACCIÓN
del botón cuando éste se utilice
ESTATUS Propiedad de uso del botón: ENABLE o DISABLE
oObjetoRet Objeto dialog en el que se definirá el componente

Ejemplo:
DEFINE SBUTTON FROM 020, 120 TYPE 2 ACTION (nOpca := 2.oDlg:End());
ENABLE OF oDlg

; Visual de los diferentes tipos de botón disponibles

Introducción a la Programación ADVPL I Página 237


Interfaces de archivo

AXCADASTRO()

Sintaxis AxCadastro(cAlias, cTitulo, cVldExc, cVldAlt)


El AxCadastro() es una funcionalidad de archivo simple, con
Descripción
pocas opciones de personalización].

MBROWSE()

Sintaxis MBrowse(nLin1, nCol1, nLin2, nCol2, cAlias)


La Mbrowse() es una funcionalidad de archivo que permite la
Descripción utilización de recursos más perfeccionados en la visualización y
manipulación de la información del sistema:

AXPESQUI()

Función de búsqueda estándar en los registros mostrados por los browses del
sistema, la cual posiciona el browse en el registro consultado. Muestra una
pantalla que permite la selección del índice que se utilizará en la búsqueda y la
digitación de la información que conforma la clave de búsqueda.

; Sintaxis: AXPESQUI()
; Parámetros:

Ninguno .

Página 238 Introducción a la Programación ADVPL I


AXVISUAL()

Función de visualización estándar de la información de un registro, en el


formato Enchoice, de acuerdo con lo que se muestra en el tópico sobre la
interfaz AxCadastro().

; Sintaxis: AXVISUAL(cAlias, nReg, nOpc, aAcho, nColMens, cMensagem,


cFunc,; aButtons, lMaximized )

; Parámetros

Tabla registrada en el Diccionario de Tablas (SX2) que se


cAlias
editará
Record number (recno) del registro marcado en el alias
nReg
activo
Número de la línea del aRotina que definirá el tipo de
nOpc
edición (Inclusión, Modificación, Borrado, Visualización)
Vector con el nombre de los campos que se mostrarán. Los
aAcho campos de usuario siempre se mostrarán cuando no exista
en el parámetro un elemento con la expresión "NOUSER"
nColMens Parámetro no utilizado
cMensagem Parámetro no utilizado
Función que debe utilizarse para cargar las variables que la
cFunc Enchoice utilizará. En este caso, el parámetro lVirtual se
define internamente por la AxFunction() ejecutada como .T.
Botones adicionales para la EnchoiceBar, en el formato:
aArray[n][1] -> Imagen del botón
aButtons aArray[n][2] -> bloque de código que contiene la acción del
botón
aArray[n][3] -> título del botón
lMaximized Indica si debe maximizarse la ventana

AXINCLUI()

Función de inclusión estándar de la información de un registro, en el formato


Enchoice, de acuerdo con lo que se muestra en el tópico sobre la interfaz
AxCadastro().

; Sintaxis: AxInclui(cAlias, nReg, nOpc, aAcho, cFunc, aCpos, cTudoOk,


lF3,; cTransact, aButtons, aParam, aAuto, lVirtual, lMaximized)

; Parámetros

Introducción a la Programación ADVPL I Página 239


Tabla registrada en el Diccionario de Tablas (SX2) que se
cAlias
editará
Record number (recno) del registro marcado en el alias
nReg
activo
Número de la línea del aRotina que definirá el tipo de
nOpc
edición (Inclusión, Modificación, Borrado, Visualización)
Vector con el nombre de los campos que se mostrarán. Los
aAcho campos de usuario siempre se mostrarán cuando no exista
en el parámetro un elemento con la expresión "NOUSER"
Función que debe utilizarse para cargar las variables que la
cFunc Enchoice utilizará. En este caso, el parámetro lVirtual se
define internamente por la AxFunction() ejecutada como .T.
aCpos Vector con el nombre de los campos que podrán editarse
Función de validación de confirmación de la pantalla. No
debe pasarse como Bloque de Código, pero puede pasarse
como una lista de expresiones, siempre y cuando la última
cTudoOk acción realice una devolución lógica:

“(Func1(), Func2(), ...,FuncX(), .T. )”

Indica si la enchoice se esta creando en una consulta F3 para


lF3
utilizar variables de memoria
Función que se ejecutará dentro de la transacción de la
cTransact
AxFunction()
Botones adicionales para la EnchoiceBar, en el formato:
aArray[n][1] -> Imagen del botón
aButtons aArray[n][2] -> bloque de código que contiene la acción del
botón
aArray[n][3] -> título del botón
Funciones para la ejecución en puntos definidos
previamente en la AxFunction(), de acuerdo con lo siguiente:
aParam[1] := Bloque de código que se procesará antes de la
exhibición de la interfaz.
aParam[2] := Bloque de código para procesamiento en la
aParam
validación de la confirmación.
aParam[3] := Bloque de código que se ejecutará dentro de la
transacción de la AxFunction().
aParam[4] := Bloque de código que se ejecutará fuera de la
transacción de la AxFunction().
Array en el formato utilizado por la funcionalidad
MsExecAuto(). Si se informa este array, no se mostrará la
pantalla de interfaz y se ejecutará la función EnchAuto().
aAuto aAuto[n][1] := Nombre del campo
aAuto[n][2] := Contenido del campo
aAuto[n][3] := Validación que se utilizará en sustitución de
las validaciones del SX3

Página 240 Introducción a la Programación ADVPL I


Indica si la Enchoice() llamada por la AxFunction() utilizará
lVirtual
variables de memoria o campos de la tabla en la edición
lMaximized Indica si debe maximizarse la ventana

AXALTERA()

Función de modificación de la información de un registro, en el formato


Enchoice, de acuerdo con lo que se muestra en el tópico sobre la interfaz
AxCadastro().

; Sintaxis: AXALTERA(cAlias, nReg, nOpc, aAcho, aCpos, nColMens,


cMensagem,; cTudoOk, cTransact, cFunc, aButtons, aParam, aAuto,
lVirtual, lMaximized)

; Parámetros

¾ Vea la documentación de parámetros de la función AxInclui().

AXDELETA()

Función de borrado de la información de un registro, en el formato Enchoice,


de acuerdo con lo que se muestra en el tópico sobre la interfaz AxCadastro().

; Sintaxis: AXDELETA(cAlias, nReg, nOpc, cTransact, aCpos, aButtons,


aParam,; aAuto, lMaximized)

; Parámetros

Tabla registrada en el Diccionario de Tablas (SX2) que se


cAlias
editará
Record number (recno) del registro marcado en el alias
nReg
activo
Número de la línea del aRotina que definirá el tipo de
nOpc
edición (Inclusión, Modificación, Borrado, Visualización)
Función que se ejecutará dentro de la transacción de la
cTransact
AxFunction()
aCpos Vector con el nombre de los campos que podrán editarse
Botones adicionales para la EnchoiceBar, en el formato:
aArray[n][1] -> Imagen del botón
aButtons aArray[n][2] -> bloque de código que contiene la acción del
botón
aArray[n][3] -> título del botón

Introducción a la Programación ADVPL I Página 241


Funciones para la ejecución en puntos definidos
previamente en la AxFunction(), de acuerdo con lo siguiente:
aParam[1] := Bloque de código que se procesará antes de la
exhibición de la interfaz.
aParam[2] := Bloque de código para procesamiento en la
aParam
validación de la confirmación.
aParam[3] := Bloque de código que se ejecutará dentro de la
transacción de la AxFunction().
aParam[4] := Bloque de código que se ejecutará fuera de la
transacción de la AxFunction().
Array en el formato utilizado por la funcionalidad
MsExecAuto(). Si se informa este array, no se mostrará la
pantalla de interfaz y se ejecutará la función EnchAuto().
aAuto aAuto[n][1] := Nombre del campo
aAuto[n][2] := Contenido del campo
aAuto[n][3] := Validación que se utilizará en sustitución de
las validaciones del SX3
lMaximized Indica si debe maximizarse la ventana

Funciones visuales para aplicaciones

ALERT()

; Sintaxis: AVISO(cTexto)
; Parámetros:

cTexto Texto que se mostrará

AVISO()

; Sintaxis: AVISO(cTitulo, cTexto, aBotoes, nTamanho)


; Devolución: numérico que indica el botón seleccionado.

Página 242 Introducción a la Programación ADVPL I


; Parámetros

cTitulo Título de la ventana


cTexto Texto del aviso
aBotoes Array simple (vector) con los botones de opción
nTamanho Tamaño (1.2 ó 3)

FORMBACTH()

; Sintaxis: FORMBATCH(cTitulo, aTexto, aBotoes, bValid, nAltura,


nLargura )
; Parámetros

cTitulo Título de la ventana


Array simple (vector) que contiene cada una de las líneas de texto que se
aTexto
mostrarán en el cuerpo de la pantalla
Array con los botones del tipo SBUTTON(), con la siguiente estructura:
aBotoes
{nTipo,lEnable,{|| Ação() }}

bValid (opcional) Bloque de validación de la ventana


nAltura (opcional) Altura en pixels de la ventana
nLargura (opcional) Ancho en pixels de la ventana

Introducción a la Programación ADVPL I Página 243


MSGFUNCTIONS()

; Sintaxis: MSGALERT(cTexto, cTitulo)


; Sintaxis: MSGINFO(cTexto, cTitulo)
; Sintaxis: MSGSTOP(cTexto, cTitulo)
; Sintaxis: MSGYESNO(cTexto, cTitulo)
; Parámetros

cTexto Texto que se mostrará como mensaje


cTitulo Título de la ventana de mensaje

MSGALERT

MSGINFO

Página 244 Introducción a la Programación ADVPL I


MSGSTOP

MSGYESNO

Funciones ADVPL para aplicaciones

GETAREA()

Función que se utiliza para proteger el entorno activo en el momento de algún


procesamiento específico. Para grabar otra área de trabajo (alias) que no sea la
que está activa, la función GetArea() debe ejecutarse dentro del alias: ALIAS-
>(GetArea()).

; Sintaxis: GETAREA()
; Retorno: Array que contiene {Alias(),IndexOrd(),Recno()}
; Parámetros

Ninguno .

RESTAREA()

Función que se utiliza para devolver la situación grabada del entorno por
medio del comando GETAREA(). Debe observarse que la última área
restaurada es el área que quedará activa para aplicación.

; Sintaxis: RESTAREA(aArea)
; Parámetros:

Introducción a la Programación ADVPL I Página 245


Array que contiene: {cAlias, nOrdem, nRecno}, generalmente
aArea
generado por el uso de la función GetArea().

Ejemplo:

// ALIAS ACTIVO ANTES DE LA EJECUCIÓN DE LA RUTINA Æ SN3


User Function XATF001()

LOCAL cVar
LOCAL aArea := GetArea()
LOCAL lRet := .T.

cVar := &(ReadVar())

dbSelectArea("SX5")
IF !dbSeek(xFilial()+"Z1"+cVar)

cSTR0001 := "REAV - Tipo de Reevaluación"


cSTR0002 := "Informe un tipo de reevaluación válido"
cSTR0003 := "Continuar"
Aviso(cSTR0001,cSTR0002,{cSTR0003},2)
lRet := .F.

ENDIF

RestArea(aArea)
Return( lRet )

Página 246 Introducción a la Programación ADVPL I


Referencias Bibliográficas
Referencias bibliográficas

Gestão empresarial com ERP


Ernesto Haberkorn, 2006

Lógica de Programação – A Construção de Algoritmos e Estruturas de Dados


Forbellone, André Luiz Villar - MAKRON, 1993

Introdução à Programação - 500 Algoritmos Resolvidos


Anita Lopes, Guto Garcia – CAMPUS / ELSEVIER, 2002

Separata de Capacitación – ADVPL


Educación corporativa

Separata de Capacitación – Introducción a la programación


Educación corporativa

Separata de Capacitación – Buenas Prácticas de Programación


Inteligencia Protheus y Fábrica de Software

Curso Básico de Lógica de Programação


Paulo Sérgio de Moraes – PUC Campinas

TDN– TOTVS Developer Network


Microsiga Software S.A.

Materiales diversos de colaboradores Totvs


Colaboradores Totvs

Introducción a la Programación ADVPL I Página 247

Das könnte Ihnen auch gefallen