jueves, 23 de junio de 2011

Truco con SapScript para simular un Loop en Tx Standard


En ocasiones se me ha presentado el problema de que debo imprimir un reporte en SAP Script que debe mostrar un detalle que no se encuentra en la tabla relacionada al SAP Script y que si llamaramos una funcion para devolver estos datos nos mostraría solo una linea por cada vez que invoca el reporte el programa de control(siempre la misma) y lo que necesitamos es que nos muestre todo el detalle y para ajustar es en una Tx Standard, no se ustedes a mi esto me causo mas de un dolor de cabeza, por eso espero poder ayudarles con esta solución.

Bueno realmente este truco no lo invente, hace algún tiempo lo encontré en un blog, lo copie lo guarde en un archivo y me olvide de el, hace poco tuve el mismo problema y lo revivi, pero no recuedo el autor original, pero sea quien sea MUCHAS gracias.


Esta solucion puede que no sea la mejor, pero personalmente me parecio ingeniosa, en resumen consiste en que en nuestro SapScript debemos crear un llamado a una funcion Z que hallamos creado que reciba los parámetros que necesitamos y devuelva un String con un Texto Standard que se creo en el modulo de funcion, luego lo devolvemos y cuando se imprima se borra el Texto Standard.

Pasos

  1. Creamos la funcion en un programa Z, digamos que nuestro programa se llama ZRUTINAS y la funcion se llama GET_INFO, este lo invocamos desde nuestro SapScript.


    /: PERFORM GET_INFO IN PROGRAM ZRUTINAS
    /:  USING &EKPO-EBELN&
    /:  USING &EKKO-WAERS&
    /:  CHANGING &TEXTADD&
    /: ENDPERFORM


  2. Get Info va a recibir 2 Tables:


    Form  get_info TABLES input   STRUCTURE itcsy                                       
                                             output  STRUCTURE itcsy.

    Digamos que que los datos que recibió la estructura input corresponde a la table EKPO en la Tx ME22N(Pedidos en SAP) y debemos devolver los servicios relacionados en este pedido.

  3. Debemos llevar a variables los datos que nos entra entrando en forma separada, por ejemplo el Numero de pedido, la moneda, etc:


      DATAlv_ebeln    TYPE ekpo-ebeln,
            lv_waers    TYPE ekko-waers.

      DATAti_lines  LIKE tline OCCURS WITH HEADER LINE,
            ti_lines2 LIKE tline OCCURS WITH HEADER LINE,
            ti_data   LIKE bsid  OCCURS WITH HEADER LINE,
            lv_header LIKE thead,
            lv_object LIKE thead-tdobject VALUE 'TEXT',
            lv_id     LIKE thead-tdid VALUE 'ST',
            lv_langu  LIKE thead-tdspras,
            lv_texto  LIKE thead-tdname.

    *&=================================================*
    *& SEPARO LOS DATOS DE ENTRADA
    *&=================================================*
      LOOP AT input.
        CASE input-name.
          WHEN 'EKPO-EBELN'.
            lv_ebeln input-VALUE.
          WHEN 'EKKO-WAERS'.
            lv_waers input-VALUE.
        ENDCASE.
      ENDLOOP.


  4. Ahora vamos a concatenar en una variable el nombre del que sera nuestro texto standard con los datos  que queramos en este ejemplo sera Z_ME22N_(el pedido)_(El usuario)_(La fecha)_(La Hora Actual):

    CONCATENATE 'ZME22N' lv_ebeln sy-uname sy-datum sy-uzeit INTO lv_texto SEPARATED BY '_'.


  5. Luego vamos a buscar si existe un texto standard con ese nombre en caso de que no exista seguimos con nuestro proceso.

      CALL FUNCTION 'READ_TEXT'
        EXPORTING
          object    lv_object
          ID        lv_id
          name      lv_texto
          LANGUAGE  lv_langu
        IMPORTING
          HEADER    lv_header
        TABLES
          LINES     ti_lines
        EXCEPTIONS
          not_found 1
          OTHERS    2.

      CHECK sy-subrc NE 0
    .

      PERFORM GET_INFO_DATA  TABLES ti_lines
                             USING  lv_ebeln.

  6. Si el texto standard no existe llamamos una función que nos busque la información, y nos la lleve linea a linea de detalle a un estructura(ti_lines) que luego nos servirá para crear nuestro texto standard, la función podría ser algo asi:


    FORM DATOS_SERVICIOS_TEMP TABLES p_lines STRUCTURE tline
                              USING  p_ebeln.


      DATALT_SERVICES TYPE TABLE OF BAPIESLL,
            LS_SERVICES LIKE LINE  OF LT_SERVICES,
            LT_SRVACCAS TYPE TABLE OF BAPIESKL,
            LS_SRVACCAS LIKE LINE  OF LT_SRVACCAS,
            LT_RETURN   TYPE TABLE OF BAPIRETURN,
            LS_RETURN   LIKE LINE  OF LT_RETURN,
            LS_HEADER   LIKE BAPIEKKOL,
            LT_ESLH     TYPE TABLE OF ESLH,
            LS_ESLH     LIKE LINE  OF LT_ESLH,
            LT_EKKO     TYPE TABLE OF EKKO,
            LS_EKKO     LIKE LINE  OF LT_EKKO,
            LT_EKPO     TYPE TABLE OF EKPO,
            LS_EKPO     LIKE LINE  OF LT_EKPO,
            LT_KONV     TYPE TABLE OF KONV,
            LS_KONV     LIKE LINE  OF LT_KONV,
            lv_valtx    TYPE char30.

      DATAit_iva TYPE STANDARD TABLE OF ty_iva,
            l_iva  TYPE eine-netpr.


    *&=================================================*
    *& BUSCO DATOS DE LOS SERVICIOS
    *&=================================================*

      CALL FUNCTION 'BAPI_PO_GETDETAIL'
        EXPORTING
          PURCHASEORDER             p_ebeln
          SERVICES                  'X'
        IMPORTING
          PO_HEADER                 LS_HEADER
        TABLES
          PO_ITEM_SERVICES          LT_SERVICES
          PO_ITEM_SRV_ACCASS_VALUES LT_SRVACCAS
          RETURN                    LT_RETURN.


      LOOP AT LT_SERVICES INTO LS_SERVICES WHERE OUTL_IND IS INITIAL.

        SELECT SINGLE INTO LS_ESLH FROM ESLH
        WHERE EBELN  EQ p_ebelN
        AND   PACKNO EQ LS_SERVICES-PCKG_NO.

        IF SY-SUBRC EQ 0.

          CLEAR p_lines.

          MOVE:  'EI' TO  p_lines-tdformat.

    *   CODIGO
          CLEARlv_valtx.
          WRITE LS_SERVICES-SERVICE  TO lv_valtx.
          move lv_valtx  to p_lines-tdline.


    *   SERVICIO
          CLEARlv_valtx.
          WRITE LS_SERVICES-SHORT_TEXT  TO lv_valtx.
          CONDENSE lv_valtx.
          CONCATENATE p_lines-tdline lv_valtx INTO p_lines-tdline SEPARATED BY ',,'.


    *   UN
          CLEARlv_valtx.
          WRITE LS_SERVICES-BASE_UOM TO lv_valtx.
          CONDENSE lv_valtx.
          CONCATENATE p_lines-tdline lv_valtx INTO p_lines-tdline SEPARATED BY ',,'.

    *   QUANTITY
          CLEARlv_valtx.
          WRITE LS_SERVICES-QUANTITY DECIMALS TO lv_valtx.
          CONDENSE lv_valtx.
          CONCATENATE p_lines-tdline lv_valtx INTO p_lines-tdline SEPARATED BY ',,'.

    *   VALOR UNITARIO
          CLEARlv_valtx.
    *      WRITE LS_SERVICES-GR_PRICE CURRENCY LS_HEADER-CURRENCY TO lv_valtx.
          WRITE LS_SERVICES-GR_PRICE DECIMALS TO lv_valtx.
          CONDENSE lv_valtx.
          CONCATENATE p_lines-tdline lv_valtx INTO p_lines-tdline SEPARATED BY ',,,,'.

    *   SUBTOTAL
          CLEARlv_valtx.
          WRITE LS_SERVICES-GROSS_VAL DECIMALS TO lv_valtx.
          CONDENSE lv_valtx.
          CONCATENATE p_lines-tdline lv_valtx INTO p_lines-tdline SEPARATED BY ',,'.

         ENDIF.

      ENDLOOP.

    ENDFORM
    .  



  7. Con esta rutina ya tenemos la tabla con las lineas de detalles, ahora lo que haremos sera crear el texto standard y ya con el texto creado devolvemos el nombre a nuestro SapScript en la tabla OutPut.


    ti_lines2[] ti_lines[].

      CALL FUNCTION 'INIT_TEXT'
        EXPORTING
          ID       lv_id
          LANGUAGE lv_langu
          name     lv_texto
          object   lv_object
        TABLES
          LINES    ti_lines
        EXCEPTIONS
          ID       1
          OTHERS   5.

      CALL FUNCTION 'CREATE_TEXT'
        EXPORTING
          fid       lv_id
          flanguage lv_langu
          fname     lv_texto
          fobject   lv_object
          fformat   ''
        TABLES
          flines    ti_lines2
        EXCEPTIONS
          no_init   1
          no_save   2
          OTHERS    3.

    * Guarda el parámetro de salida

      READ TABLE OUTPUT WITH KEY name 'TEXTADD'.

      IF sy-subrc EQ 0.
        MOVE lv_texto TO OUTPUT-VALUE.
        MODIFY OUTPUT INDEX sy-tabix.
      ENDIF.

  8. Ya en nuestro SapScript debemos incluir el texto stardard e imprimirlo:
    /: INCLUDE &TEXTADD& OBJECT TEXT ID ST

  9. Y por ultimo borramos nuestro texto standard llamando a una función en nuestro programa:

    /: PERFORM BORRAR_TEXTO_SERVICIO IN PROGRAM  ZRUTINAS
    /: USING  &TEXTADD&
    /: CHANGING &CO_RETORNO&
    /: ENDPERFORM.

  10. La rutina BORRAR_TEXTO seria así:

    FORM borrar_texto_servicio TABLES INPUT  STRUCTURE itcsy
                                     OUTPUT  STRUCTURE itcsy.

      DATAlv_object   LIKE thead-tdobject VALUE 'TEXT',
            lv_id       LIKE thead-tdid     VALUE 'ST',
            lv_langu    LIKE thead-tdspras,
            lv_textadd  LIKE thead-tdname.



    * Busca los parámetros de entrada de la rutina

      READ TABLE INPUT WITH KEY name 'TEXTADD'.

      IF sy-subrc EQ 0.
        MOVE INPUT-VALUE TO lv_textadd.
      ENDIF.

    * Procesa la informacion

      MOVE sy-langu TO lv_langu.

      CALL FUNCTION 'DELETE_TEXT'
        EXPORTING
          ID        lv_id
          LANGUAGE  lv_langu
          name      lv_textadd
          object    lv_object
        EXCEPTIONS
          not_found 1
          OTHERS    2.

    * Guarda la informacion

      READ TABLE OUTPUT WITH KEY name 'CO_RETORNO'.

      IF sy-subrc EQ 0.
        MOVE sy-subrc TO OUTPUT-VALUE.
        MODIFY OUTPUT INDEX sy-tabix.
      ENDIF.

    ENDFORM.                    "find_det2_document_f110


Y listo ya eso es todo con esto podremos imprimir nuestro detalle de varias lineas llamando una sola funcion, espero les sirva y hasta la proxima.




    4 comentarios:

    1. Mil gracias por tu ayuda. Aunque no lo usé como lo planteas me sirvió para imprimir el detalle en cheques de pago. Gracias.

      ResponderEliminar
    2. Muchas Gracias me vino de 10 el contenido

      ResponderEliminar

    Es muy importante saber que opinas de este espacio, por eso te agradezco tus aportes.