jueves, 12 de septiembre de 2013

Crear nuestra propia funcion split en Navision

En más de una ocasión, programando con navision me he lamentado de la falta de funciones para trabajar con variables que facilita el C/AL en general y la falta de funciones para trabajar con cadenas de texto en particular. No voy a hablar en este post la de veces que me toca ir a ver  como se manipulan los Stream en ejemplos porque su manipulacion en mi opinion es enfarragosa.
En este post vamos a tratar algo tan sencillo como es simular la funcion split (Que tantos lenguajes utilizan) en Navision.
El resultado por supuesto no va a ser el mismo pero nos puede ser muy util a la hora de manejar cadenas de texto.
Cuantas veces nos ha tocado tratar de una direccion de un archivo sacar las carpetas, o el archivo en si, por ejemplo:
'C:\CARPETA\ARCHIVOS\PDF\MIPDF.pdf' nos devuelva MIPDF.pdf o 'C:\CARPETA\ARCHIVOS\PDF' o ARCHIVOS

La primera de las funciones la he llamado ExtraeSubcadena. La funcionalidad consiste en pasarla una cadena de texto con unos parámetros y que nos devuelva unaporcion de texto de esta cadena.
A esta funcion le pasaremos:
  1. Un Texto: Sera el texto que deseamos tratar.
  2. Un Caracter Separador: Nos servira de delimitador.
  3. Direccion: Es un indicador que nos informa si deseamos trocear:
    1. '<' desde el principio a la aparicion del texto deseada indicada en el parametro Posicion.
    2. '>' desde la aparicion del texto deseada indicada en el parametro Posicion hasta el final
    3. '<>' desde la aparicion del texto deseada indicada en el parametro Posicion hasta la siguiente aparición
  4. Posición: El número de aparición del texto delimitador
Funcion ExtraeSubcadena()
Parámetros:
NameDataTypeSubtype
Length
txtTextoText1024
txtSeparadorText1
DireccionText2
PosicionInteger

Variables:
NameDataTypeSubtypeTemporary
SeparadoresRecordIntegerYes
iInteger
//Buscamos las apariciones del carácter separador
Separadores.RESET;
Separadores.DELETEALL;
FOR i:=1 TO STRLEN(txtTexto) DO BEGIN
   IF COPYSTR(txtTexto,i,1) = txtSeparador THEN BEGIN
      Separadores.INIT;
      Separadores.Number := i;
      Separadores.INSERT;
   END;
END;

//Ahora tratamos el textoSeparadores.RESET;
IF Separadores.FINDFIRST THEN BEGIN   Separadores.NEXT(Posicion-1);
   IF Direccion = '<>' THEN BEGIN

     //De la posicion deseada hasta la siguiente
      txtTexto := ExtraeSubcadena(txtTexto,txtSeparador,'>',Posicion);
      IF STRPOS(txtTexto,txtSeparador) > 0 THEN BEGIN         txtTexto := ExtraeSubcadena(txtTexto,txtSeparador,'<',1);
      END;
      EXIT(txtTexto);
   END ELSE BEGIN      IF Direccion = '>' THEN BEGIN

         //De la posicion deseada hasta el final         EXIT(COPYSTR(txtTexto,Separadores.Number+1));
      END ELSE BEGIN

         //Del principio a la posicion deseada         EXIT(COPYSTR(txtTexto,1,Separadores.Number-1));
      END;
   END;
END;

EXIT('');

Una vez tenemos esta función, podemos hacer otra que nos indique cuantas veces aparece nuestro separador, la
Funcion ContarApariciones()
Parámetros:
NameDataTypeSubtype
Length
txtTextoText1024
txtSeparadorText1
DireccionText2
PosicionInteger

Variables:
NameDataTypeSubtypeTemporary
SeparadoresRecordIntegerYes
iInteger
//Buscamos las apariciones del carácter separador
Separadores.RESET;
Separadores.DELETEALL;
FOR i:=1 TO STRLEN(txtTexto) DO BEGIN
    IF COPYSTR(txtTexto,i,1) = txtSeparador THEN BEGIN
       Separadores.INIT;
       Separadores.Number := i;
      Separadores.INSERT;
    END;
END;

//Devolvemos las veces que aparece
Separadores.RESET;
IF Separadores.FINDFIRST THEN BEGIN   EXIT(Separadores.COUNT);
END;
EXIT(0);


Ahora, con la conjuncion de ambas funciones podemos de una manera elegante devolver la carpeta y el archivo de contenido en un texto de la sigiente manera:
MESSAGE('El Archivo es: %1',ExtraeSubcadena('C:\ARCHIVO\MI PDF.pdf','\','>',ContarApariciones('C:\ARCHIVO\MI PDF.pdf','\')));
MESSAGE('La carpeta es: %1',ExtraeSubcadena('C:\ARCHIVO\MI PDF.pdf','\','<',ContarApariciones('C:\ARCHIVO\MI PDF.pdf','\')));

En futuros posts veremos como hacer (Con la misma filosofia, es decir, utilizando recursividad y una tabla temporal del sistema) una funcion que sustituya uno o varios caractéres por uno o varios caractéres.

2 comentarios:

  1. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  2. Excelente articulo. Una preguntita ya que apenas estoy empezando con C/AL. ¿Donde coloco el código de la función?¿En que trigger? Mil gracias

    ResponderEliminar