lunes, septiembre 15, 2008

Definición de Rango Numérico

La transacción para definir un objeto de tipo rango de números es la SNRO. A continuación se muestra un ejemplo de definición de rango de números:



Para obtener el siguiente valor del objeto desde un programa habrá que utilizar la siguiente función:



Donde la variable "pch_numpre" es del mismo dominio que el objeto numérico y contendrá el valor actual tras incrementar el contador del rango numérico.

Referencias:

viernes, septiembre 12, 2008

Adobe Forms: Incluir logos, imágenes de fondo y datos de varias tablas

En el siguiente artículo se indica cómo crear un Adobe Form (tx:SFP) al que se le añade imágenes y devuelve tablas con datos recopilados de disntintas fuentes a partir de unos parámetros de entrada variables:

Scenario on displaying logo, background image and fetching data from multiple tables

Ficheros con tamaño de línea fijo

Cuando se desea generar un fichero de texto con longitud de línea fija, en muchas ocasiones se utilizan espacios para rellenar el espacio sobrante al final de las mismas por lo que se debe especificar de la siguiente manera que no se ignoren los espacios finales según se vaya a generar el fichero en local o en el servidor:

Local


Cuando se descarga el fichero en local, se deberá indicar que NO se excluyan los espacios en blancos al final de la línea mediante el parámetro TRUNC_TRAILING_BLANKS_EOL vacío:



Servidor


Cuando el fichero se va a generar en el servidor bastará añadir la sentencia LENGTH seguida del tamaño de la línea del fichero y ésto hará que las líneas cuyo contenido sea inferior al indicado se rellenen por el final con espacios en blanco:


viernes, agosto 01, 2008

PhotoRec

Se trata de una gran utilidad para recuperar ficheros tras una gran pérdida, como lo puede ser darse cuenta de que no copiaste las fotos de aquel fabuloso viaje antes de formatear el disco duro... ¿verdad Manolillo ;) ?

Para aquellos que les pueda interesar describiré los pasos básicos que seguí para recuperar los archivos deseados. La situación con la que me encontré fue con un equipo portatil recién formateado sin sistema operativo instalado por lo que la probabilidad de recuperar todos o la mayor parte de los archivos es bastante alta. Como es lógico, el programa de recuperación se debe ejecutar a través de un sistema operativo así que hay 3 opciones:
  1. Coger el disco duro afectado y ensamblarlo en otro equipo que disponga de sistema operativo instalado (tedioso en el caso de los portátiles...).
  2. POCO RECOMENDABLE: Instalar un sistema operativo sobre el propio disco duro afectado, esto podría machacar parte o totalidad de los archivos a recuperar...
  3. Utilizar un sistema operativo volátil de tipo LiveCD.

    Yo considero la tercera opción como la más recomendable y menos costosa. A ser posible si ya viene con la utilidad instalada mejor (Knoppix la tiene). Antes de empezar recomiendo disponder de algún dispositivo de almacenamiento externo tipo pendrive para almacenar todos los archivos en él, ya que las versiones Live de los sistemas operativos no permiten almacenar gran cantidad de datos (dependiendo de la memoria del sistema) por lo que cuanto mayor sea la capacidad del dispositivo externo, mejor (dependiendo de los archivos que se deseen recuperar...).

    Hay que destacar que PhotoRec es multiplataforma, en mi caso utilicé una versión LiveCD de Ubuntu, que no la tenía instalada por lo que a continuación describo los pasos que seguí para poder recuperar los archivos:
    1. Me descargué el paquete correspondiente desde aquí (en mi caso: la versión Linux, kernel 2.6.x i386/x86_64, tar.bz).
    2. A través de la consola de comandos descomprimí el archivo: 
      • bunzip2 testdisk-6.10.linux26.tar
      • bz2tar -xvf testdisk-6.10.linux26.tar
    3. Antes de ejecutar el programa, deberemos concectar el/los dispositivos donde deseamos que se almacenen los archivos recuperados (siempre que se llene un dispositivo, el programa pedirá que se le especifique una nueva ubicación para continuar guardando el resto de archivos que encuentre).
    4. Una vez descomprimido, el programa se puede lanzar mediante el siguiente comando. Una recomendación es ejecutar el programa fuera de la interfaz gráfica (Ctrl+Alt+F4 -> Ctrl+Alt+F7 para volver) ya que es un programa que consume muchos recursos (en mi caso para 80GB estuvo 3 horas) y si estás en modo gráfico puede que se cuelgue el sistema.
      • sudo testdisk-6.10/linux/photorec_static

    Con ésto ya estaremos en la aplicación. La interfaz es muy intuitiva (en inglés, claro), con las opciones justas y propone por defecto los valores correctos (si detecta que la partición anterior se trataba de NTFS se marcará esta opción a la hora de elegir el formato en el que estaban grabados los ficheros a recuperar). Mi recomendación es echar un vistazo a estos links antes de utilizar la aplicación:

      Buena suerte.

      jueves, julio 31, 2008

      Crear un fichero de texto comprimido en ZIP

      Existe una clase estándard en SAP, CL_ABAP_ZIP, que permite crear archivos de texto comprimidos en ZIP. Existen varios modos de conseguir dicho fin. Un objeto de la clase CL_ABAP_ZIP puede contener más de un archivo. Todos los archivos que contengan deben estar codificados en binario (XSTRING).

      A continuación se muestra un ejemplo de cómo convertir el contenido de una tabla interna a un fichero ZIP.



      Si lo que se desea es comprimir un archivo que se encuentra en una ubicación determinada, lo que deberemos hacer es, en primer lugar, leer el contenido del archivo en una variable de tipo binaria (xstring) y a continuación pasarle el contenido de esa variable al objeto de la clase CL_ABAP_ZIP que la vaya a contener.


      miércoles, julio 30, 2008

      SAP Netweaver Developer Studio

      Se trata de una herramienta de utilidad para el desarrollo en XI. Se puede descargar, junto a una serie de herramientas complementarias, desde los siguientes enlaces:



      martes, julio 29, 2008

      RFC vs. Proxy

      En el presente post he querido reflejar las ventajas y contras que aparecen al utilizar RFCs y al utilizar ABAP Proxies. Es por ello que antes de decirdir qué método utilizar será recomendable que tengamos en cuenta las siguientes caracteríscitas:

      ABAP Proxies

      Ventajas

      • Permite definir todas las estructuras necesarias a partir de esquemas XSD o ficheros WSDL.
      • Funcionan sin problemas con estructuras anidadas (tablas dentro de otras tablas).

        Inconvenientes

        • Al importar el proxy en el ERP se generan numerosos objetos con nombres muy largos. Si se desea renombrar dichos objetos habrá que tener en cuenta que cada vez que sea necesario importar de nuevo el proxy (debido a cambios) los nombres de los objetos deberán ser cambiados de nuevo.
        • Es necesario configurar la conexión desde el sistema ERP al sistema XI para que la transacción SPROXY pueda importar los proxies correctamente.
        • El acceso a los métodos de las clases y las llamadas a éstos es más tediosa que con las RFCs.

          RFCs

          Ventajas

          • La definición del código es mucho más directa que a través de los proxies.
          • La llamada a las funciones RFCs es más sencilla.
          • La actualización de las estructuras que utiliza es más directa.

            Desventajas

            • Requiere que definamos las estructuras enteras en el sistema ERP a pelo. Si éstas disponen de muchos campos, la cosa se complica.
            • No funciona bien con estructuras de tipo tabla que contienen campos que a la vez son de tipo tabla.

              A continuación muestro 2 enlaces que pueden ser de interés:

                lunes, julio 28, 2008

                Controlar tiempos de ejecución

                Si lo que se desea conocer es cuánto se tarda en ejecutar una porción de código, la sentecia GET RUN TIME FIELD nos vendrá como anillo al dedo. A continuación muestro un ejemplo de utilización:



                Los tiempos t1 y t2 vienen dado en microsegundos por lo que será necesario dividirlos por 1.000 para pasarlos a milisegundos y por 1.000.000 si se desea tener en segundos.

                miércoles, julio 09, 2008

                EAN-128

                A la hora de tratar con códigos EAN-128 existen módulos de funciones estándar que permiten tanto codificar como decodificar de este modo.

                Dentro del grupo de funciones LE_EAN128 se encuentran los módulos:
                • LE_EAN128_ENCODE: Crear un código de barras estándar para ean128
                • LE_EAN128_DECODE: Descodificación de un código de barras estándar para ean128
                • LE_EAN128_LABEL_OUTPUT: EAN128 etiqueta: Edición impresa
                • LE_EAN128_LABEL_READ: EAN128 etiqueta: datos

                  Hay que tener en cuenta que para que el proceso de codificación se realice correctamente será necesario tener parametrizado de forma correcta las secciones comprendidas en el área de customizing (SPRO) Logistics - General --> Handling Unit Management --> Basics --> Define EAN128.

                  Existe otro grupo de funciones que también debe tenerse en cuenta y es el LE_BARCODE. Dentro del cual el módulo de función más significativo es el:
                  • LE_BARCODE_AI_READ: Lee la descripción de códigos de barras
                  Los datos referentes a los códigos AI (longitud, tipo, etc.) definidos en el sistema se encuentran en la tabla T313D, mientras que la tabla T313G recoge los caracteres especiales (prefijos y delimitadores) utilizados en cada tipo de codificación. Por ejemplo, partiendo del siguiente código EAN128 :
                  • (02)08470006043066(17)150400(37)006(10)1022134
                  El código EAN128 tiene definido, por defecto, el código ']C1' como prefijo y el código hexadecimal '1D' (group separator) como separador de campos de longitud variable. Esto quiere decir que para que la función de decodificación reconozca el anterior código, este se debería pasar de habría que pasar el código EAN de la siguiente manera:
                  • ]C102084700060430661715040037006#101022134
                  Donde '#' representa el carácter no imprimible "group separator".

                    Más info: http://www.scribd.com/doc/3262714/EAN128-E

                    jueves, julio 03, 2008

                    ccBPM

                    A través del cross-component BPM se permiten definir procesos de negocios automatizados ampliando así la potencia de componente de integración de procesos de SAP. El ccBPM permite, entre otras cosas, recibir mensajes individuales a través de una determinada interfaz para postermiormente unificarlos en una lista y distribuirlos a las máquinas correspondiente, por ejemplo.

                    Los procesos definidos a través del ccBPM están basados en el estándard BPEL4WS, definido entre otros por SAP, IBM y Microsoft. Es por ello que dichos procesos pueden ser exportados a otros sistemas y, por otra parte, se pueden importar procesos de negocios definidos en otros sistemas, siempre y cuando sigan este estándar.

                    Antes de definir los procesos de integración mediante el ccBPM, se deberá configurar el entorno XI de manera correcta (diseño y configuración), tal como se especifica en éste enlace.

                    Para más información: http://help.sap.com/saphelp_nw04/helpdata/en/3c/831620a4f1044dba38b370f77835cc/frameset.htm

                    Anteponer el signo de los números

                    El siguiente código vuelca el contenido de un número real (negativo) a una variable alfanumérica, poniendo el signo como prefijo de la misma.


                    jueves, junio 05, 2008

                    Obtener el siguiente número secuencial

                    Donde el parámetro NR_RANGE_NR es de tipo INRI-NRRANGENR y el parámetro OBJETO es de tipo INRI-OBJECT.


                    lunes, junio 02, 2008

                    Convertir campos del ALV en totalizables

                    Para que los botones de sumatoria y subtotales se activen en un listado se deberán especificar los campos que se deseen totalizar a partir de referencias a campos de tablas estándar. De este modo SAP conocerá el tipo (decimales, signo, etc.) y podrá realizar las sumas de manera correcta.



                    Si, además, marcamos el campo "DO_SUM", esto hará que se muestra una línea de totales al final del listado.

                    Ocultar campos de pantalla

                    Hay veces en las que se hace necesario ocultar ciertos campos de la pantalla de selección. Sobre todo cuando se utilizan bases de datos lógicas que incluyen campos propios. En estos casos habrá que saber en primer lugar cuál es el nombre de los campos que deseamos ocultar. Ésto se puede lograr visualizando la pantalla de selección estándar del sistema (dynpro nº 1000). Los campos se recogen en la pestaña Lista de elementos y dentro de ésta deberemos ir a la pestaña Grupos modif./Funciones para conocer los grupos a los que están asignados.

                    Supongamos que deseamos ocultar aquellos campos que pertenezcan al GRUPO1 YB1. El lugar donde debemos codificar ésto es en el evento AT SELECTION-SCREEN OUTPUT. Y el código sería el siguiente:



                    Nótese que el campo INPUT puesto a 0 sirve para aquellos campos de entrada salida, ya que si no especificamos este valor, aunque se pongan invisibles se seguirán mostrando.

                    Llamadas a listados con retorno

                    Algunas veces se crean programas que, en función de unas opciones de selección, permiten visualizar un tipo de listado u otro. Lo ideal es que el usuario no tenga salir del programa y volver a cada vez que quiera cambiar de listado, sino volver a la pantalla de selección y desde ahí elegir el nuevo listado que desea visualizar.

                    Esto se consigue mediante la combinación CALL SCREEN + LEAVE TO SCREEN 0. A continuación se muestra un ejemplo.

                    En el programa principal habrá un código del siguiente estilo:



                    Y los módulo PAI de las pantallas deberán contener un código similar a éste:



                    Es importante hacer uso del CALL SCREEN ya que si utilizamos la sentencia LEAVE TO SCREEN 0 con SET SCREEN nos echará del programa.

                    viernes, mayo 23, 2008

                    Delimitaciones dinámicas en LDB_PROCESS

                    Cuando usamos bases de datos lógicas de partidas de FI hay campos que no aparecen directamente en la pantalla de selección, pero sí a través del botón de delimitaciones opcionales. los programas estándar que incluyen la LDB en los atibutos gestionan correctamente estas delimitaciones, pero... ¿cómo las especificaríamos si utilizamos la función LDB_PROCESS? aquí va un ejemplillo.



                    Funciones relacionadas con los días de los períodos

                    PERIOD_DAY_DETERMINE: devuelve primer/último días de período
                    - Entrada: I_GJAHR, I_MONAT, I_PERIV (de sociedad en T001)
                    - Salida: E_FDAY, E_LDAY, E_SPERIOD (indicador período especial)

                    FIRST_DAY_IN_PERIOD_GET / LAST_DAY_IN_PERIOD_GET
                    - Entrada: I_GJAHR, I_PERIV (de sociedad en T001) , I_POPER (período)
                    - Salida: E_DATE (primer / último día)

                    Gracias a Lucas León.

                    Esperar 'n' segundos

                    Si se desea meter un retardo de 'n' segundos en el código se puede utilizar la siguiente instrucción:


                    Opciones del DELETE ADJACENT

                    El motivo de este post es para explicarles unas opciones del DELETE de las tablas internas, que puede resultar de gran ayuda. Supongo que los más experimentados en Abap ya sabrán de ellas, pero el resto puede que no lo hayan visto.

                    Supongamos que nos pasan una tabla con muchísimos registros, de los cuales pueden haber duplicados. Necesitamos tener un solo registro de cada tipo, por lo que nos interesa eliminar de la tabla los duplicados. Para ello, podemos hacer lo siguiente:
                    1. ordenamos la tabla -> SORT tabla_interna.
                    2. eliminamos los duplicados -> DELETE ADJACENT DUPLICATES FROM tabla_interna.

                    Este delete eliminaría los duplicados de los registros, pero sólo aquellos que coincidan en todos los campos. Si cada registro se compone de varios campos, tienen que coincidir en todos para ser eliminados.

                    Si lo que nos interesa es eliminar registros que coincidan sólo en uno, dos, ... n campos, lo especificariamos de la siguiente forma.
                    1. ordenamos la tabla -> SORT tabla_interna.
                    2. eliminamos los duplicados -> DELETE ADJACENT DUPLICATES FROM tabla_interna COMPARING campo1 campo2 ... campoX.

                    dónde cada campo es el nombre del campo en la tabla interna.

                    Por ejemplo.

                    Tenemos la estructura siguiente, formada por tres campos:



                    Ahora queremos aplicar lo explicado antes, pero para que tenga en cuenta sólo el campo MATKL a la hora de eliminar duplicados.
                    1. SORT gt_fich_gr_articulos.
                    2. DELETE ADJACENT DUPLICATES FROM gt_fich_gr_articulos COMPARING MATKL.

                    Se eliminarian todos los registros duplicados excepto uno, el primero de la ordenación, con el mismo campo MATKL, aunque los dos campos siguientes sean diferentes.

                    Gracias a Samuel Artiles.

                    Estructura para CALL TRANSACTIONS

                    Con la estructura CTU_PARAMS podemos definir algunos parámetros del CALL TRANSACTION como modo de ejecución (Sólo errores, Visible, Invisible,...), modo de actualización, tamaño estándar de dynpro,...

                    Para su uso, por ejemplo, podemos definir un parámetro de tipo CTU_PARAMS-XXXXXX en la pantalla de selección y ello nos dará la posibilidad de seleccionar los diferentes aspectos en la ejecución del CALL TRANSACTION.

                    Ejemplo: