miércoles, 25 de junio de 2014

F1 Help. Ayuda en SAP

Es este post voy a hablar de una de las herramientas mas útiles y potentes que nos da SAP a los consultores, ya seamos funcionales o técnicos. Para mi es una herramienta vital que debemos, ya no solo conocer, sino dominar a la perfección. Estamos hablando de F1 Help. la ayuda en SAP.

¿Cuantas veces nos hemos encontrado en un transacción y nos hemos preguntado de donde vendrá este dato que me aparece en este campo?¿En que tabla podre encontrarlo?.... Mi respuesta es cientos y cientos, y seguro que la de muchos de vosotros.

Por otro lado, ¿Cuantas veces os habeis preguntado que significa este campo que estoy viendo en determinada transacción?¿Para que sirve?De igual modo, cientos y cientos.

Llegados a este punto, SAP nos da la opción de posicionarnos sobre cualquier campo, celda, botón, etc. y presionar F1. Tras esto se nos abrirá una ventana como la siguiente:

 
Lo primero que nos encontramos es la descripción del nombre del campo y a continuación una definición del mismo. Además a mayores SAP nos da algun ejemplo de la utilización que se le da al mismo, un procedimiento de utilización y si existe algun tipo de dependencia (Esto es importante ya que a veces informar un determinado campo puede tener repercusiones, puede no ser simplemente informativo).


Esto no siempre es tan bonito, hay veces donde nos vamos a encontrar con que la informacion que nos aporte SAP sea bastante escasa e incluso que las explicaciones que nos de nos lleven mas a la confusión que a otra cosa.

Si nos fijamos en la parte superior de la ventana SAP dispone de varios botones:

 
Podemos acudir al portal de SAP en busca de mas ayuda, podemos imprimir el mensaje con la información que nos muestra, etc.
 
Pero de entre todos hay dos botones que merecen especial atención y que son los que mas juego y potencial nos van a dar. Me refiero a los botones de Información técnica y Customizing.
Explicaremos por separado cada uno de ellos:
  • Información técnica: Si pulsamos sobre esta opción SAP nos abrira una nueva ventana donde nos va a mostrar todos los datos técnicos del campo (Programa, dynpro, tabla o estructura, elemento de datos, etc). En este punto cabe reseñar la importancia que tiene el valor que nos muestre en el campo  "Tabla".
    Si nos indica que es una tabla transparente, estaremos de enhorabuena!!!SAP nos dice directamente de que tabla de la base de datos está obteniendo el valor. En el resto de casos tendremos que trabajarnoslo un poco mas para encontrar el origen del dato. Mi recomendación es intentar buscarlo a partir del elemento de datos con ayuda de las referencias de utilización (
    Las referncias de utilización es una herramienta que nos dice donde se está utilizando un determinado objeto).


  • Customazing: Si pulsamos sobre esta otra opción y este campo esta relacionado con el Customazing, SAP nos llevara al punto donde podremos tratarlo.



    

martes, 24 de junio de 2014

Mensajes en SAP (MESSAGE)

En este post vamos a hablar de una utilidad vital dentro de SAP y de cualquier sistema informatico que se precio, LOS MENSAJES.

En SAP los mensajes están agrupados en áreas de mensajes. Para indicar que área de mensajes
vamos a utilizar en un report utilizamos MESSAGE-ID en la instrucción REPORT.



REPORT <report> MESSAGE-ID <area>.
 
 
Podemos ver, crear y modificar áreas de mensajes desde el editor:

Pasar a -> Mensajes.
Para visualizar un mensaje utilizamos la sentencia MESSAGE.

MESSAGE Tnnn.
Donde nnn es el número de mensaje dentro de su respectiva área de mensajes y T es el tipo de mensaje. Tenemos los siguientes tipos de mensaje:

A = Cancelación o ‘Abend ’ del proceso.
E = Error. Es necesaria una corrección de los datos.
I  = Información. Mensaje meramente informativo. El proceso continuará con un ENTER.



S  = Confirmación. Información en la pantalla siguiente.
W = Warning. Nos da un aviso. Podemos cambiar los datos o pulsar ’intro’ para continuar.

Si se emiten mensajes del tipo W o E en eventos START-OF-SELECTION o ENDOFSELECTION o GET se comportan como si fueran del tipo A.

Podemos acompañar los mensajes de parámetros variables.


MESSAGE Tnnn WITH <var1> <var2>...
En la posición del mensaje que se encuentre el símbolo &, podemos utilizar para visualizar el valor que le pasemos como parámetro a la instrucción MESSAGE.

No podemos utilizar más de 4 parámetros por mensaje.

Los datos sobre mensajes están en la tabla T100. Y si queremos definir o modificar areas de mensajes podemos hacerlo a través de la transacción SE91.


Y accediendo vemos cada uno de losmensajes que contiene el area:


Ejemplo:
Área de mensajes ZZ.
Mensaje: 005 = Entrada &-& incorrecta.

REPORT ZPRUEBA MESSAGE-ID ZZ.
....
IF....
  MESSAGE A005 WITH SKA1 KTOPL.
ENDIF.

El mensaje obtenido será:
A: Entrada SKA1-KTOPL Incorrecta




domingo, 22 de junio de 2014

ADOBE FORMS. Programa de impresión

Es este post vamos a destallar como podemos imprimir un formulario ADOBE en SAP desde código ABAP.

En el anterior post sobre Adobe Forms vimos como diseñarlo, sería conveniente revisar primero este post antes de continuar.

Para poder invocar al formulario desde un programa impresor ABAP se deberán seguir los siguientes pasos:

1) Llenar las tablas, estructuras, etc. que se pasarán cómo parámetros al formulario. En este ejemplo se llenaron la tabla pt_reserv y la estructura pa_header.

2) Abrir el formulario para impresión:

Invocar la siguiente función con los parámetros de impresión, entre ellos: indicar si se desea suprimir el diálogo pop-up de impresión (como en este ejemplo: l_outputparams-nodialog = ‘X’ ) e indicar que el archivo que retorne sea un PDF con el parámetro l_outputparams-getpdf = ‘X’.
DATA: l_outputparams TYPE sfpoutputparams.

* Output parameters and open spool job
l_outputparams-nodialog = ‘X’.
l_outputparams-getpdf = ‘X’.

* Open the form for printing

CALL FUNCTION 'FP_JOB_OPEN'
CHANGING

    ie_outputparams = l_outputparams
EXCEPTIONS
    cancel = 1
    usage_error = 2
    system_error = 3
    internal_error = 4
    OTHERS = 5.

IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
  WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

3) Obtener el nombre dinámico del formulario:

CALL FUNCTION 'FP_FUNCTION_MODULE_NAME'
EXPORTING
    i_name = 'ZFORM_VH'
IMPORTING
    e_funcname = p_func_name.

4) Llamar al formulario con el nombre obtenido, pasándole los parámetros con los datos ya cargados:

DATA: l_docparams TYPE sfpdocparams,
            l_formoutput TYPE fpformoutput.

l_docparams-langu = 'E'.
l_docparams-fillable = c_on.
 
CALL FUNCTION p_func_name
EXPORTING
   /1bcdwb/docparams = l_docparams
    i_gt_reserv = pt_reserv
    ga_header = pa_header

IMPORTING
    /1bcdwb/formoutput = l_formoutput
EXCEPTIONS
    usage_error = 1
    system_error = 2
    internal_error = 3
    OTHERS = 4.


5) Cerrar el procesamiento del formulario:

CALL FUNCTION 'FP_JOB_CLOSE'
EXCEPTIONS
usage_error = 1
system_error = 2
internal_error = 3
OTHERS = 4.
 
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
 

sábado, 21 de junio de 2014

Colores en un ALV de SAP

En este post voy a comentar como podemos utilizar los colores en las celdas de un ALV en SAP. Es un ejemplo muy sencillo pero a la vez muy util, que hará que aumentemos la vistosidad de nuestros listados resoltando aquellas celdas que mas nos interesen.

-          En la tabla interna definimos un atributo COLOR del tipo SLIS_T_SPECIALCOL_ALV.

COLOR TYPE SLIS_T_SPECIALCOL_ALV, " Color Field
-          En la definición del layout debemos indicar que columna de la tabla interna va a definir las características de color de la celda. En campo a rellenar es el COLTAB_FIELDNAME.

i_layout-coltab_fieldname = 'COLOR'.

-          El último paso sería rellenar este campo en la tabla interna. Lo que le vamos a indicar es que columna vamos a dar color y el color que le vamos a dar. El color se indica con un valor entero (1, 2, 3, ….).

DATA
: v_alv_color TYPE slis_specialcol_alv.
CLEAR
: v_alv_color.
v_alv_color-fieldname = 'STATUS'.
v_alv_color-color-col = 6. “Rojo
APPEND v_alv_color TO t_lecturas-color.
Y finalmente podemos conseguir cosas como la que se ve en la siguiente imagen.

 
 
Podemos jugar con esta funcionalidad y conseguir cosas bastante chulas.

lunes, 9 de junio de 2014

Modificar un ALV de forma dinámica

En este post vamos a explicar como podemos modificar uns ALV de FM de manera dinámica, es decir, en tiempo de ejecución. Podemos modificar desde el numero de columnas que aparecen, la ordenacion, las caracteristicas del ALV, etc.

Lo vamos a hacer con un ejemplo de código que como mejor se entiende. En este caso lo que vamos a hacer es añadir nuevas columnas al informe, ademas completaremos los valores que tendrán estás columnas. La funcion que vamos a utilizar para realizar la modificación es REUSE_ALV_GRID_LAYOUT_INFO_SET.


**Modificamos la estructura de salida.
  PERFORM modificar_gt_alv.
  rs_selfield-refresh = 'X'.

*&---------------------------------------------------------------------*
*&      Form  modificar_gt_alv
*&---------------------------------------------------------------------*
*    Modificamos gt_alv
*----------------------------------------------------------------------*
FORM modificar_gt_alv.

  DATA i_field LIKE i_fieldcat WITH HEADER LINE.

  LOOP AT i_fieldcat INTO i_field.

    CASE i_field-fieldname.

      WHEN 'EFFECTIVITY'.
        i_field-no_out = space.
        MODIFY i_field INDEX sy-tabix TRANSPORTING no_out.

      WHEN 'GRUPO_F'.
        i_field-no_out = space.
        MODIFY i_field INDEX sy-tabix TRANSPORTING no_out.

      WHEN 'SUBMOD'.
        i_field-no_out = space.
        MODIFY i_field INDEX sy-tabix TRANSPORTING no_out.

      WHEN 'MSN'.
        i_field-no_out = space.
        MODIFY i_field INDEX sy-tabix TRANSPORTING no_out.

      WHEN 'PNR'.
        i_field-no_out = space.
        MODIFY i_field INDEX sy-tabix TRANSPORTING no_out.

      WHEN 'SN'.
        i_field-no_out = space.
        MODIFY i_field INDEX sy-tabix TRANSPORTING no_out.

    ENDCASE.

    APPEND i_field.

  ENDLOOP.

  CLEAR i_fieldcat.
  REFRESH i_fieldcat.

  LOOP AT i_field.

    APPEND i_field TO i_fieldcat. 

  ENDLOOP.

  LOOP AT i_gt_alv WHERE SEL = 'X'.

    READ TABLE gt_importar WITH KEY DOKNR = i_gt_alv-DOKNR_D.

    IF sy-subrc = 0.

      i_gt_alv-EFFECTIVITY_TYPE = gt_importar-efectividad.
      i_gt_alv-GRUPO_FLOTA = gt_importar-zzcgrupo_flotas.
      i_gt_alv-SUBMODELO = gt_importar-zzcsubmodelo.
      i_gt_alv-MSN = gt_importar-zzcmsn.

      MODIFY i_gt_alv INDEX sy-tabix
          TRANSPORTING EFFECTIVITY_TYPE
                       GRUPO_FLOTA
                       SUBMODELO
                       MSN.
    ENDIF.

  ENDLOOP. 

CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_SET'
  EXPORTING
*   IS_LAYOUT            =
    IT_FIELDCAT          = i_fieldcat
*   IT_SORT              =
*   IT_FILTER            =
*   IS_GRID_SCROLL       =
*   IS_PRINT             =
          .
ENDFORM.

miércoles, 4 de junio de 2014

Añadir pestañas a la transacción ME21N

Vamos a explicar como añadir pestañas a las transacciones de creación/modificación del pedidos de compra (ME21N, ME22N, ME23N).

Para implementar una nueva pestaña debemos de crearnos una copia del grupo de funciones  MEPOBADIEX. En el grupo de funciones que nos creemos debemos declarar la dynpro que vamos a utilizar para la nueva pestaña. Además utilizaremos las funciones de este grupo para introducir toda la lógica necesario para tratar los datos que se muevan en esta nueva pestaña.
La dynpro la debemos declarar como subscreen:
 
 
Además los campos que añadamos en la subscreen los tomaremos de la estructura que hemos utilizado para el APPEND a la tabla EKKO o EKPO.
Además deberemos implementar la BADI ME_GUI_PO_CUST. En los métodos de esta BADI definiremos la nueva pestaña y utilizaremos sus métodos para tratar el flujo de datos para la nueva pestaña.
A continuación se muestra un ejemplo del código utilizado en el grupo de funciones ZMEPOBADIEX.
-          ZMEPOBADIEX_GET_DATA
  CLEAR ex_data.

  
CHECK NOT im_ebeln IS INITIAL.

* Recuperamos los registros de la tabla EKKO
  
SELECT SINGLE zekko1 zekko2 zekko3 zekko4 zekko5   INTO CORRESPONDING FIELDS OF ex_data
  
FROM ekko
  
WHERE ebeln im_ebeln.

  
INSERT ex_data INTO TABLE gt_data.
-          ZMEPOBADIEX_INIT
CLEARgt_persistent_data[]gt_data[].
-          ZMEPOBADIEX _POP
* get dynpro data
  ex_dynp_data 
zekko.
-          ZMEPOBADIEX _POST
  DATAls_data LIKE LINE OF gt_data,
        lt_data_new 
TYPE STANDARD TABLE OF zekko,
        lt_data_old 
TYPE STANDARD TABLE OF zekko.

* prepare customers data for posting

  
CHECK NOT im_ebeln IS INITIAL.

  lt_data_new[] 
gt_data.
  lt_data_old[] 
gt_persistent_data.
-          ZMEPOBADIEX _ PUSH
zekko im_dynp_data.
A continuación se muestra un ejemplo del código utilizado la clase ZCL_IM_ME_GUI_PO_CUST. Se han modificado los siguientes métodos:
-          IF_EX_ME_GUI_PO_CUST~SUBSCRIBE

  DATAls_subscribe LIKE LINE OF re_subscribers.

  
CHECK im_application 'PO'.
  
CHECK im_element     'HEADER'.

  
CLEAR re_subscribers[].

  ls_subscribe
-name 'SCREEN_V'.
  ls_subscribe
-dynpro '0001'.
  ls_subscribe
-program 'SAPLZMEPOBADIEX'.
  ls_subscribe
-struct_name 'ZEKKO'.
  ls_subscribe
-label 'Nueva Pestaña'.
  ls_subscribe
-position 10.
  ls_subscribe
-height 7.
  
APPEND ls_subscribe TO re_subscribers.

-          IF_EX_ME_GUI_PO_CUST~MAP_DYNPRO_FIELDS

  FIELD-SYMBOLS<mapping> LIKE LINE OF ch_mapping.

  
LOOP AT ch_mapping ASSIGNING <mapping>.
    
CASE <mapping>-fieldname.
      
WHEN 'ZEKKO1'.
        <mapping>
-metafield 1.
      
WHEN 'ZEKKO2'.
        <mapping>
-metafield 2.
      
WHEN 'ZEKKO3'.
        <mapping>
-metafield 3.
      
WHEN 'ZEKKO4'.
        <mapping>
-metafield 4.
      
WHEN 'ZEKKO5'.
        <mapping>
-metafield 5.
    
ENDCASE.
  
ENDLOOP.
-          IF_EX_ME_GUI_PO_CUST~TRANSPORT_FROM_MODEL

  DATAl_item       TYPE REF TO if_purchase_order_item_mm,
        ls_mepoitem  
TYPE mepoitem,
        pedido 
TYPE ebeln,
        modelo 
TYPE REF TO cl_po_header_handle_mm,
        ex_data 
TYPE zekko.

  
FIELD-SYMBOLS<zekko1>   TYPE ekko-zekko1,
                 <zekko2>   
TYPE ekko-zekko2,
                 <zekko3>   
TYPE ekko-zekko3,
                 <zekko4>   
TYPE ekko-zekko4,
                 <zekko5>   
TYPE ekko-zekko5.

  
CASE im_name.

    
WHEN 'SCREEN_V'.

      modelo ?= im_model
.
      pedido 
modelo->po_number.

      
IF pedido IS NOT INITIAL AND dynp_data_pai IS INITIAL.

        
CALL FUNCTION 'ZMEPOBADIEX_GET_DATA'
          
EXPORTING
            im_ebeln 
pedido
          
IMPORTING
            ex_data  
ex_data.

        
MOVE-CORRESPONDING ex_data TO dynp_data_pbo.

      
ELSEIF dynp_data_pai IS NOT INITIAL.

        dynp_data_pbo 
dynp_data_pai.

      
ENDIF.

      
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO1')  TO <zekko1>.
      
IF sy-subrc 0.
        <zekko1> 
dynp_data_pbo-zekko1.
      
ENDIF.
      
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO2')  TO <zekko2>.
      
IF sy-subrc 0.
        <zekko2> 
dynp_data_pbo-zekko2.
      
ENDIF.
      
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO3')  TO <zekko3>.
      
IF sy-subrc 0.
        <zekko3> 
dynp_data_pbo-zekko3.
      
ENDIF.
      
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO4')  TO <zekko4>.
      
IF sy-subrc 0.
        <zekko4> 
dynp_data_pbo-zekko4.
      
ENDIF.
      
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO5')  TO <zekko5>.
      
IF sy-subrc 0.
        <zekko5> 
dynp_data_pbo-zekko5.
      
ENDIF.

  
ENDCASE.
-          IF_EX_ME_GUI_PO_CUST~TRANSPORT_TO_DYNP

  CASE im_name.

    
WHEN 'SCREEN_V'.

      
CALL FUNCTION 'ZMEPOBADIEX_PUSH'
        
EXPORTING
          im_dynp_data 
dynp_data_pbo.

    
WHEN OTHERS.

  
ENDCASE.
-          IF_EX_ME_GUI_PO_CUST~TRANSPORT_FROM_DYNP
  FIELD-SYMBOLS<zekko1>   TYPE ekko-zekko1,
                 <zekko2>   
TYPE ekko-zekko2,
                 <zekko3>   
TYPE ekko-zekko3,
                 <zekko4>   
TYPE ekko-zekko4,
                 <zekko5>   
TYPE ekko-zekko5.

  
CASE im_name.

    
WHEN 'SCREEN_V'.

      
IF sy-ucomm 'MECHOB'.

        
CLEAR dynp_data_pai.

      
ELSE.

        
CALL FUNCTION 'ZMEPOBADIEX_POP'
          
IMPORTING
            ex_dynp_data 
dynp_data_pai.

        
IF dynp_data_pai NE dynp_data_pbo.
* something has changed therefor we have to notify the framework
* to transport data to the model
          re_changed 
mmpur_yes.

          
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO1')  TO <zekko1>.
          
IF sy-subrc 0.
            <zekko1> 
dynp_data_pai-zekko1.
          
ENDIF.
          
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO2')  TO <zekko2>.
          
IF sy-subrc 0.
            <zekko2> 
dynp_data_pai-zekko2.
          
ENDIF.
          
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO3')  TO <zekko3>.
          
IF sy-subrc 0.
            <zekko3> 
dynp_data_pai-zekko3.
          
ENDIF.
          
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO4')  TO <zekko4>.
          
IF sy-subrc 0.
            <zekko4> 
dynp_data_pai-zekko4.
          
ENDIF.
          
ASSIGN ('(SAPLMEPO)EKKO-ZEKKO5')  TO <zekko5>.
          
IF sy-subrc 0.
            <zekko5> 
dynp_data_pai-zekko5.
          
ENDIF.

        
ENDIF.

      
ENDIF.

  
ENDCASE.

Finalmente si ejecutamos alguna de las tres transacciones veremos que la nueva pestaña ya aparece.