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
CLEAR: gt_persistent_data[], gt_data[].
-          ZMEPOBADIEX _POP
* get dynpro data
  ex_dynp_data 
= zekko.
-          ZMEPOBADIEX _POST
  DATA: ls_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

  DATA: ls_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

  DATA: l_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.

martes, 3 de junio de 2014

Evento DATA_CHANGED en un listado ALV de SAP

En este post os voy a indicar como podeis controlar el evento de modificación en celdas editables dentro de un ALV de FM. Vamos a tener que controlar el evento DATA_CHANGED. Es algo muy sencillo y que nos da mucho juego a la hora de jugar con los listados ALV

Para controlar el evento DATA_CHANGED en un ALV de función tenemos que registrar el evento:
FORM gestionar_eventos .

  
DATA i_listevent TYPE slis_alv_event.

  
CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
    
EXPORTING
      i_list_type 
= 0
    
IMPORTING
      et_events   
= i_events.

  
READ TABLE i_events WITH KEY name = c_topofpage
       
INTO i_listevent.

  
IF sy-subrc = 0.
    
MOVE c_topofpage TO i_listevent-form.
    
MODIFY i_events FROM i_listevent TRANSPORTING form
                                       
WHERE name = c_topofpage.

    
CLEAR i_listevent.
    i_listevent
-name = 'DATA_CHANGED'.
    i_listevent
-form = 'DATA_CHANGED'.
    
APPEND i_listevent TO i_events.

  
ENDIF.

ENDFORM. 
Después el evento se gestionara desde un FORM:
FORM data_changed USING rr_data TYPE REF TO cl_alv_changed_data_protocol.

  
DATA : ls_mod_cell TYPE lvc_s_modi,
        lv_value 
TYPE lvc_value .

  
DATA rs_selfield TYPE slis_selfield.

  
DATA: l_modif TYPE zverde_n_sac_bb.

  
SORT rr_data->mt_mod_cells BY row_id .

* Tratamos la linea modificada
  
LOOP AT rr_data->mt_mod_cells INTO ls_mod_cell.

    
IF ls_mod_cell-fieldname = 'NSC' OR ls_mod_cell-fieldname = 'NUM'.

  
ENDLOOP.

ENDFORM.                    "data_changed

domingo, 1 de junio de 2014

ADOBE FORMS

La tecnología mas reciente para la creación de formularios en SAP, es la solución SAP Interactive  Forms by Adobe. Esto permite crear formularios interactivos y formularios de impresión basados en Adobe PDF para optimizar los procesos de impresión de las aplicaciones.

El punto interesante en el uso de esta tecnologia es su compatibilidad con las personalidades ABAP y JAVA del SAP Netweaver Application Server. Actualmente, el uso de los formularios de impresión basados en PDF, puede reemplazar a los SmartForms, del lado ABAP, y además, potencias las Web Dynpro, tanto del lado Java como ABAP, usando formularios interactivos.
Para tal efecto esta nueva solución SAP Interactive Forms by Adobe (disponible a partir de SAP Netweaver 04) utiliza el Adobe LiveCycle Designer, que es una herramienta de diseño que permite la creación de formularios utilizando UI Elements, de manera muy intuitiva y facil de utilizar, y está totalmente integrado en el ABAP Workbench y en el Netweaver Developer Studio.

Los formularios de impresión basados en Adobe son parte de SAP Interactive Forms by Adobe y son usados para imprimir en los sistemas SAP.

Un formulario de Abobe PDF consta de tres partes, en las que todas son necesarias para la creacion del mismo:

  • Interfase: Contiene los parametros (tablas, estructuras, etc.) que un formulario podra utilizar. Es independiente del formulario.
  • Contexto: Contiene unicamente los parametros de la interfase que son requeridos en un determinado momento.
  • Layout: Es el diseño del formulario

Ahora voy a explicar los pasos a seguir para crear un formulario con Adobe en SAP:
 
 
 
  1. Acceder a la transacción SFP - Form Builder.
  2. Crear la interfase que utilizará el formulario de la siguiente manera: indicar un nombre y presionar Create, como se ve en la imagen.

  3. Completar la siguiente pantalla con la descripción de la interfase y grabamos.

  4. Una vez creada la interfase, se debe indicar cuales serán los parametros de entrada y salida que manejará la misma. Esta etapa es similar al manejo de parametros de una función. A continuación se muestra la interfase creada anteriormente, con tres parametros de entrada.



    Si se desea modificar la interfase en esta  etapa, los pasos con los siguientes segun corresponda:

    - Hacer doble click sobre  Import y agregar en la parte derecha de la pantalla todos los parametros de entrada que tendrá la interfase.
    - Repetir está operación para los parámetros de Export, las excepciones, datos globales, etc.
    - En Initialization, agregar código ABAP de ser necesario.

    Una vez hechas las modificaciones necesarias se debe grabar y activar.
  5. Una vez grabada la interfase, accedemos de nuevo a la transacción SFP, para crear el formulario. Elegir un nombre para el formulario y presionar Create. 
  6. Completar la descripción del formulario y asociarlo con una interfase. Luego seleccionar Save.

  7. Una vez creado el formulario, se debe asociar un contexto para el mismo. En la solapa Context aparecerán sobre la izquierda todos los parámetros que se declararon en la interfase. De dicha interfase se deberán seleccionar solo los parámetros que se utilizarán en el formulario. Para ello, arrastrar hacia el contexto (parte derecha de la pantalla) los parametros que se deseen, tal como se muestra en la imagén.

  8. Una vez diseñado el contexto del formulario, Grabar y Activar.
  9. Después, diseñar la imagén de salida que tendrá el formulario, a través de la solapa Layout.

    En la solapa Páginas de Trabajo se diseñará el formulario. Las principales herramientas para ellos son las "Paletas", que se pueden ubicar libremente  en la pantalla. De no estar visibles, se las puede agregar desde el menú, yendo a Paletas y seleccionando la deseada:

    - Paleta Jerarquía/Vista de Datos: En la vista de datos aparecerán  todos los parámetros definidos en el contexto y simplemente habrá que arrastrarlos hacia la página de trabajo tal como se muestra en la figura anterior.
    - Paleta Objeto: Se definen algunos atrinbitos del objeto tales como bordes, presentación, si es de solo lectura, obligatorio, etc. Además en dicha paleta se encuentra el enlace del parametro  del contexto, es decir, que parametro del contexto esta a cada campo del formulario.

    - Paleta Fuente/Parrafo: Permite definir la fuente (tipo, color) y el estilo de párrafo (centrado, alineado, etc.) para cada objeto del formulario.

    - Paleta Biblioteca: Contiene todos los elementos (Controles) que se pueden arrastrar al formulario. 
     
     
     

    En el caso de querer mostrar una tabla en el formulario, desde la paleta "Vista de Datos" se debe arrastrar la tabla a la página de trabajo como cualquier otro componente.



    - En la pagian de trabajo seleccionar la tabla e ir a la paleta Objeto completando con los siguientes datos:



    - Por último seleccionar en la página de trabajo el tipo de tabla dentro de la tabla (tener cuidado que la tabla y el tipo de tabla están muy encimados y es dificil distinguirlos) y completar los siguientes datos en la paleta Objeto:



    En la solapa Vista Previa del PDF se puede visualizar el diseño del formulario completo.
  10. Por último, Grabar y Activar.
Es importante tener en cuenta que para poder desplegar el formulario en la vista previa, es necesario la configuración de los Adobe Document Services (ADS) del lado del SAP Netweaver Application Server Java y la conexión desde ABAP con el sistema servidor JAVA que ofrece los Adobe Documents Services.

La configuración de ADS está fuera del alcance de este post, podeis consultar el HELP de SAP y buscar por: Adobe Document Services Configuration Guide.

En el siguiente post veremos como imprimir el formulario a partir de un programa ABAP.

Os dejo también un video donde se ve un ejemplo de uso de un adobe form con web dynpro abap:







¿Qué es OLAP?

En este post voy a introducir el concepto OLAP, muy necesario cuando vamos a movernos dentro del mundo del Businness Intelligence.

Según la Wikipedia, OLAP es:

OLAP es el acrónimo en inglés de procesamiento analítico en línea (On-Line Analytical Processing). Es una solución utilizada en el campo de la llamada inteligencia empresarial (o Business Intelligence) cuyo objetivo es agilizar la consulta de grandes cantidades de datos. Para ello utiliza estructuras multidimensionales (o cubos OLAP) que contienen datos resumidos de grandes bases de datos o Sistemas Transaccionales (OLTP). Se usa en informes de negocios de ventas, marketing, informes de dirección, minería de datos y áreas similares.

¿Te has enterado de algo? ¿No? Pues tal vez te ayude esta imagen:

¿Todavía no? Pues aquí tienes una explicación mucho mejor (via TodoBI). Esto es OLAP:


Porque OLAP no es más que eso: Una manera de acceder a tu información utilizando un “lenguaje natural”. Esta señora selecciona su pizza filtrando todas las pizzas posibles a través de sus características relevantes.
En el mundo corporativo, los analistas acceden a la información filtrando sus indicadores de negocio por regiones, por producto, por tiempo...
A partir de esta definición básica, existen distintas tecnologías que lo implementan (ROLAP, MOLAP,...), pero básicamente todas hacen las mismas acciones básicas sobre la información:
  • Segmentar: Como cuando pides las ventas por producto y por trimestre
  • Filtrar: Como cuando pides el informe de ventas de España en 2011
  • Profundizar (Drill down): Como cuando ves los datos de trimestre 2 y te interesa el desglose de abril, mayo, junio.
  • Sintetizar (Drill up): Cuando deshacesel desglose anterior y vuelves al desglose por trimestre.
  • Rotar (Drill anywhere): Cuando en lugar de pasar de un desglose por trimestres a uno mensual, te interesa un desglose por familia de producto, o por nacionalidad, es decir, por una característica de una jerarquía distinta a la que lo estas viendo actualmente.
Lo relevante es que el análisis OLAP te permite “navegar” fácilmente por la información, solicitándola con el detalle preciso y con los filtros adecuados, y que puedes hacerlo de manera dinámica, fácil, ad hoc, sobre la marcha, sin necesitar asistencia, rápido, y utilizando el lenguaje de negocio. Vamos, como la señora del vídeo.

Integración SAP

Cuando hablamos de SAP como sistema integrado que cubre toda la casuística de nuestro negocio estamos siendo bastante osados. Casi cualquier...