25 junio 2010

macros de selection-screen

archivado en: ABAP/IV

Hola sufridos programadores de ABAP:

Es muy frecuente que, en cualquier report un poco sofisticado, haya que modificar la visibilidad o la actividad de los campos que aparecen en la pantalla de selección, con lo que es necesario hacer un LOOP AT SCREEN y modificar las propiedades de visualización de los parámetros o los rangos. El código resultante es bastante horroroso y, además, es típico tener que repasar qué propiedades eran las que había que tocar.

Algo parecido pasa si nos piden meter un desplegable o listbox. Aunque es posible utilizarlo en una pantalla de selección definida puramente en ABAP, es un auténtico rollo programarlo.

Así que he creado unas macros para llevar todo esto a cabo en un plis. Son las siguientes:

GENERACIÓN DE LISTBOX
Asumen que tenemos un parámetro tipo listbox y se deben utilizar en el evento INITIALIZATION.

  • vc_lbini ‘PARAM’. : Prepara el parámetro PARAM tipo LISTBOX para su carga.
  • vc_lbadd ‘A’ ‘UNO’. : Carga el parámetro anterior con el valor ‘A’, mostrando en pantalla ‘UNO’. Se debe utilizar tantas veces como valores queramos cargar.
  • vc_lbexe. : Finaliza la carga del último parámetro definido con vc_lbini.

CONTROL DE VISIBILIDAD Y ACTIVIDAD EN PARÁMETROS
Hay que utilizarlos dentro de un LOOP AT SCREEN.

  • vc_ssblanco ‘PARAM’. : Hace que el campo sea editable.
  • vc_ssgris ‘PARAM’. : Deja el campo como no editable, sólo de visualización.
  • vc_ssvisible ‘PARAM’. : Provoca que el campo sea visible.
  • vc_ssinvisible ‘PARAM’. : Provoca que el campo no se muestre.

A continuación, el código de las macros con ejemplo incluido.

REPORT z_macros_selection_screen.

*          _                  _ _     _   _
* ___  ___| |___  ___ _ __   | |_)___| |_| |__   _____  __
*/ __|/ _ \ | __|/ __| '__|  | | | __| __| '_ \ / _ \ \/ /
*\__ \  __/ |__ \ (__| |     | | |__ \ |_| |_) | (_) |  <
*|___/\___|_|___/\___|_|     |_|_|___/\__|_.__/ \___/_/\_\
* as seen on http://glob.cranf.net
* ascii art made at http://ascii.cranf.net
*
* automatizan la creación de parámetros desplegables en reports:
*
*PARAMETERS param1 AS LISTBOX VISIBLE LENGTH 15.
*PARAMETERS param2 AS LISTBOX VISIBLE LENGTH 15.
*
*INITIALIZATION. "ESENCIAL QUE ESTÉ DENTRO DE ESTE EVENTO
*  vc_lbini 'PARAM1'.
*  vc_lbadd 'A' 'UNO'.
*  vc_lbadd 'B' 'DOS'.
*  vc_lbadd 'C' 'TRES'.
*  vc_lbexe.
*
*  vc_lbini 'PARAM2'.
*  vc_lbadd 'D' 'UNO2'.
*  vc_lbadd 'E' 'DOS2'.
*  vc_lbadd 'F' 'TRES2'.
*  vc_lbexe.
*
*START-OF-SELECTION.
*  WRITE param1.
*  WRITE param2.
*
***********************************************************************
TYPE-POOLS vrm.
DATA vc_vrmtable TYPE vrm_value OCCURS 0.
DATA vc_vrmheader TYPE vrm_value.
DATA vc_id TYPE vrm_id.
***********************************************************************
* VC_LBINI 'PARAMETRO'.
*
* inicializa el parámetro listbox de selection screen.
*
DEFINE vc_lbini.
  refresh vc_vrmtable.
  vc_id = &1.
END-OF-DEFINITION.
***********************************************************************
* VC_LBADD 'valor' 'texto'.
*
* al parámetro marcado por VC_LBINI le añade valor y texto descriptivo.
*
DEFINE vc_lbadd.
  vc_vrmheader-key = &1.
  vc_vrmheader-text = &2.
  append vc_vrmheader to vc_vrmtable.
END-OF-DEFINITION.
***********************************************************************
* VC_LBEXE.
*
* finaliza la carga del parámetro listbox indicado en VC_LBINI.
*
DEFINE vc_lbexe.
  if vc_id is initial.
    message e208(00) with 'falta id'.
  endif.
  if vc_vrmtable is initial.
    message e208(00) with 'faltan valores'.
  endif.
  call function 'VRM_SET_VALUES'
       exporting
            id              = vc_id
            values          = vc_vrmtable
       exceptions
            id_illegal_name = 1
            others          = 2.
  if sy-subrc = 1.
    message e398(00) with 'id' vc_id 'no existe' space.
  endif.
  if sy-subrc = 1.
    message e398(00) with 'para id' vc_id 'no hay valores' space.
  endif.
END-OF-DEFINITION.
***********************************************************************

*          _
* ___  ___| |___  ___ _ __    ___  ___ _ __ ___  ___ _ __
*/ __|/ _ \ | __|/ __| '__|  / __|/ __| '__| _ \/ _ \ '_ \
*\__ \  __/ |__ \ (__| |     \__ \ (__| | |  __/  __/ | | |
*|___/\___|_|___/\___|_|     |___/\___|_|  \___|\___|_| |_|
* as seen on http://glob.cranf.net
* ascii art made at http://ascii.cranf.net
*
* facilitan la muestra o activación de campos en LOOP AT SCREEN.
*
*AT SELECTION-SCREEN OUTPUT."debe estar dentro de este evento en reports
*
*  LOOP AT SCREEN.
*    IF pchecker = 'X'.
*      vc_ssblanco 'PARAM1'.  "deja el campo como editable
*      vc_ssvisible 'PARAM2'. "deja el campo visible
*    ELSE.
*      vc_ssgris 'PARAM1'.      "deja el campo sólo lectura
*      vc_ssinvisible 'PARAM2'. "oculta el campo
*    ENDIF.
*  ENDLOOP
***********************************************************************
* VC_SSBLANCO 'PARAMETRO'.
*
* pone como editable el parámetro.
*
DEFINE vc_ssblanco.
  if screen-name = &1. screen-input = '1'. modify screen. endif.
END-OF-DEFINITION.
***********************************************************************
* VC_SSGRIS 'PARAMETRO'.
*
* pone como solo lectura el parámetro.
*
DEFINE vc_ssgris.
  if screen-name = &1. screen-input = '0'. modify screen. endif.
END-OF-DEFINITION.
***********************************************************************
* VC_SSVISIBLE 'PARAMETRO'.
*
* hace visible el parámetro.
*
DEFINE vc_ssvisible.
  if screen-name = &1. screen-active = '1'. modify screen. endif.
END-OF-DEFINITION.
***********************************************************************
* VC_SSINVISIBLE 'PARAMETRO'.
*
* oculta el parámetro.
*
DEFINE vc_ssinvisible.
  if screen-name = &1. screen-active = '0'. modify screen. endif.
END-OF-DEFINITION.
***********************************************************************

***********************************************************************
***********************************************************************
***********************************************************************
*       _                      _
*  ___ (_) ___ _ __ ___  _ __ | | ___
* / _ \| |/ _ \ '_ ` _ \| '_ \| |/ _ \
*|  __/| |  __/ | | | | | |_) | | (_) |
* \___|/ |\___|_| |_| |_| .__/|_|\___/
*    |__/               |_|

PARAMETERS param1 AS LISTBOX VISIBLE LENGTH 15.
PARAMETERS param2 AS LISTBOX VISIBLE LENGTH 15.
PARAMETERS pchecker AS CHECKBOX USER-COMMAND zin.

INITIALIZATION. "ESENCIAL QUE ESTÉ DENTRO DE ESTE EVENTO
  vc_lbini 'PARAM1'.
  vc_lbadd 'A' 'UNO'.
  vc_lbadd 'B' 'DOS'.
  vc_lbadd 'C' 'TRES'.
  vc_lbexe.

  vc_lbini 'PARAM2'.
  vc_lbadd 'D' 'UNO2'.
  vc_lbadd 'E' 'DOS2'.
  vc_lbadd 'F' 'TRES2'.
  vc_lbexe.

AT SELECTION-SCREEN OUTPUT."debe estar dentro de este evento en reports

  LOOP AT SCREEN.
    IF pchecker = 'X'.
      vc_ssblanco 'PARAM1'.  "deja el campo como editable
      vc_ssvisible 'PARAM2'. "deja el campo visible
    ELSE.
      vc_ssgris 'PARAM1'.      "deja el campo sólo lectura
      vc_ssinvisible 'PARAM2'. "oculta el campo
    ENDIF.
  ENDLOOP.

START-OF-SELECTION.

  WRITE param1.
  WRITE param2.
  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV

27 abril 2010

zvcExcel 0.9beta

archivado en: ABAP/IV Inventos

Hola sufridos programadores de ABAP:

Es difícil tener la ocasión de escribir “SAP” y “glamour” en la misma frase, a pesar de esta misma.

Esto es especialmente cierto a la hora de exportar ALVs como excel, sobretodo desde versiones antiguas de R/3, pues los resultados son horrorosos a la vista. Y aunque tampoco es la única manera que existe de generar hojas de cálculo desde R/3, ya que tenemos clases ABAP dedicadas, en este caso tenemos que hablar de fealdad a la hora de programarlas.

Si además queremos construir excels un tanto complejos con fórmulas, diversidad de titulares, disposiciones no estrictamente tabulares, etc…, etc… entonces estamos en un auténtico aprieto.

ejemplo elemental de uso de la librería
Para resolver todo esto presento la librería zvcExcel que, aunque no está todo lo acabada que me gustaría, en su forma actual ofrece muchas posibilidades, siendo su mejor baza el enfoque de programación que soporta, muy cercano, en el fondo, al del usuario de Office.

Un humano, a la hora de generar hojas de cálculo, se dedica a mover el cursor e ir rellenando allí donde le apetece o le parece más adecuado, gozando de mucha libertad a la hora de hacer el diseño. Un programa, sin embargo, por lo general sólo se limita a rellenar filas y columnas de datos con una línea de cabecera y gracias.

zvcExcel utiliza una especie de cursor que podemos “mover” libremente (utilizando un lenguaje de macros) rellenando las casillas que nos interesan, dotándolas así de diferente estética, contenidos… y ¡hasta de fórmulas!

Mientras que lo habitual a la hora de totalizar o realizar cálculos en la exportación de éxceles es incrustarlos a piñon en el resultado, zvcExcel permite que introduzcas auténticas fórmulas de excel para que el usuario final, si lo desea, pueda modificar valores en la hoja resultante sin que las cifras se descuadren.

Lo mejor para entender cómo funciona la librería es leer este código de ejemplo, que es el que genera el gráfico de arriba y está ampliamente comentado. Lo único que precisa para funcionar es el include que al final de este artículo adjunto, junto con este mismo programa, en un zip:

REPORT zvcexcel_ejemplo.

INCLUDE zvcexcel.

DATA it_excel TYPE TABLE OF vcxt_excel.
DATA it_ekpo TYPE TABLE OF ekpo WITH HEADER LINE.

START-OF-SELECTION.

  SELECT *
  FROM ekpo
  INTO TABLE it_ekpo
  UP TO 10 ROWS
  WHERE netpr NE 0
    AND menge NE 0
    AND txz01 NE space.

* COMIENZA LA GENERACIÓN DEL EXCEL
* refrescamos nuestra tabla it_excel, que hemos definido nosotros.
  REFRESH it_excel.

* este macro borra las definiciones anteriores y establece un estilo
* de texto por defecto para toda la hoja, y sitúa el cursor en A1
  vcx_initialize.

* este macro hace que cada vez que ejecutemos VCX_CELLVAL, el cursor
* avance una casilla en horizontal. con VCX_AUTOXINC_OFF desactivamos.
  vcx_autoxinc_on.

* empezamos a definir la estética. es necesario saber CSS
* en algunos casos, como ciertas fórmulas, deberemos investigar
* los CSS propios de microsoft, que comienzan por mso-
  vcx_classcss 'titulo' 'font-family:impact;font-size:24px'.
  vcx_classcss 'cabeza' 'font-weight:bolder;font-size:14px;' &
  'background-color:#660000;color:#ffffff'.
  vcx_classcss 'numero' 'color:#ff9900;font-size:12px;' &
  'font-weight:bolder'.
  vcx_classcss 'total' 'font-size:14px;border-top:1px #000000 solid'.
* definimos la clase fecha, para campos tipo datum, utilizando
* un valor por defecto de la librería
  vcx_classcss 'fecha' vcxdefaultdateformat.

* vamos a cargar la primera celda de título.
* le asignamos una estética ANTES de dar valor
  vcx_cellclass 'titulo'.
* fusionamos 6 celdas en horizontal para que quepa bien el título
  vcx_cellspan 6.
* y al final le damos valor. debido a VCX_AUTOXINC_ON avanza el cursor
  vcx_cellval 'ejemplo de excel generado con zvcExcel'.
* salto de línea
  vcx_crlf.
* la celda de abajo la usaremos de comentario y tomará estética defecto
  vcx_cellval 'un tanto elemental'.
  vcx_crlf.

* esta instrucción hace que TODAS las celdas definidas a partir de ahora
* tengan estética tipo 'cabeza'.
  vcx_autoclass 'cabeza'.
  vcx_cellval 'Pedido'.
  vcx_cellval 'Pos.'.
  vcx_cellval 'Concepto'.
  vcx_cellval 'Fecha'.
  vcx_cellval 'Cant.'.
  vcx_cellval 'Un.'.
  vcx_cellval 'Precio'.
* con space desactivamos la clase 'cabeza'.
  vcx_autoclass space.
  vcx_crlf.

* internamente no se trabaja en formato A1 típico excel, sino con
* coordenadas x,y type i. vcx_x y vcx_y recogen en todo momento las
* coordenadas actuales del cursor.

* filainicio y filafin nos servirá para delimitar el rango de una suma
  DATA filainicio TYPE i.
  DATA filafin TYPE i.

  filainicio = vcx_y.

* un vulgar loop nos permite rellenar la hoja rápidamente
  LOOP AT it_ekpo.
    vcx_cellclass 'numero'.
    vcx_cellval it_ekpo-ebeln.
    vcx_cellval it_ekpo-ebelp.
    vcx_cellval it_ekpo-txz01.
    vcx_cellclass 'fecha'.
    vcx_cellval it_ekpo-aedat.
    vcx_cellval it_ekpo-menge.
    vcx_cellval it_ekpo-meins.
    vcx_cellval it_ekpo-netpr.
    vcx_crlf.
  ENDLOOP.

* como al final hay un salto de línea, restamos uno para rango de suma
  filafin = vcx_y - 1.

* vamos a poner la fila de totales con una raya encima
  vcx_autoclass 'total'.
* desplazamos el cursor a la derecha hasta la columna F
  DO 5 TIMES.
    vcx_cellval ''.
  ENDDO.
* también podríamos haber utilizado VCX_XINC que mueve cursor a derecha

* escribimos la leyenda para el total.
  vcx_cellval 'SUMA:'.

* la siguiente instrucción nos va a meter en la celda la fórmula
* =SUMA(G4:G53)
* aunque nosotros lo hacemos como si dijeramos (7,4):(7,53) y no G4:G53
  vcx_cellsum 7 filainicio 7 filafin.
  vcx_cellval space.

* en este ejemplo VCX_CELLFORMULA, más complicado: permite introducir
* cualquier fórmula siempre que sea en el formato interno de excel, en
* el que el nombre de las funciones no es el español. también debemos
* utilizar coordenadas alfanuméricas y no numéricas. no es problema:

* si queremos convertir una coordenada x en letras,
* lo haremos con VCX_NUMBER2ALFA. no hay límite más allá que
* el del propio excel.

* del mismo modo, VCX_COORDS2ALFA convierte (x,y) en formato A1. si uno
* de los valores es 0, lo transforma en totalidad de fila o columna
* ejemplo: ncoords2alfa 4 3 valor. hace valor = 'D3'.
* ejemplo: ncoords2alfa 4 0 valor. hace valor = 'D'.

* aunque aquí ya no haría falta, desactivamos la clase 'total'.
  vcx_autoclass ''.

* generamos el excel dentro de la tabla
  vcx_excelgenerate it_excel.

* y lo descargamos localmente.
  vcx_exceldownload it_excel 'c:prueba.xls'.

* importante: si excel ya tiene abierto el fichero, no lo podremos
* descargar.

* otros macros están descritos dentro de la librería y no
* necesitan mucha explicación

Lo único que lamento de esta librería es el hecho de que todavía no está lo suficientemente completa para mi gusto, puesto que las posibilidades de ampliación son enormes. Pero no dudo que lo iré haciendo a medida que necesite funcionalidades.

Como siempre, recomiendo el uso de esta librería siempre que se respete la autoría, el link a este glob, etc… y animando a aquellas personas que decidan ampliarla a compartir su trabajo tras hacerlo.

Podéis descargar el include zvcExcel y el programa de ejemplo aquí.

  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV Inventos

20 abril 2010

voet’s ALV template

archivado en: ABAP/IV

Hola sufridos programadores de ABAP:

Este es mi template para cada vez que tengo que hacer una ALV. Es bastante completo, lo justo para que en el 95% de los casos lo único que tenga que hacer es cambiar la definición de campos y programar la interacción del usuario. Quizás te merezca la pena echarle un vistazo a mi post sobre el tratamiento de colores en ALV.

A disfrutar.

REPORT z_alv_template.

DATA it_alv TYPE STANDARD TABLE OF ekko.

SELECT * FROM ekko INTO TABLE it_alv
    UP TO 137 ROWS.

PERFORM alv_display.

*       _          _ _           _
*  __ _| |_   ____| |_)___ _ __ | | __ _ _   _
* / _` | | \ / / _` | | __| '_ \| |/ _` | | | |
*| (_| | |\ V / (_| | |__ \ |_) | | (_| | |_| |
* \__,_|_| \_/ \__,_|_|___/ .__/|_|\__,_|\__, |
*           FORM PRINCIPAL|_|            |___/
* necesaria tener definida globalmente IT_ALV con
*               los campos y contenidos a mostrar
* as seen on http://glob.cranf.net
* ascii art made at http://ascii.cranf.net
***********************************************************************
FORM alv_display.

** VARIABLES NECESARIAS                       *no es necesario tocar
**------------------------------------------------------------------
  TYPE-POOLS slis.
  DATA alv_fieldcat TYPE slis_t_fieldcat_alv.
  DATA alv_layout   TYPE slis_layout_alv.
  DATA alv_sort     TYPE slis_t_sortinfo_alv.
  DATA ls_sort      TYPE slis_sortinfo_alv.
  DATA alv_events   TYPE slis_t_event.
  DATA ls_events    TYPE slis_alv_event.
  DATA lsyrepid LIKE sy-repid. lsyrepid = sy-repid.
  CLEAR alv_fieldcat. REFRESH alv_fieldcat.
  CLEAR alv_layout.

** definición de LAYOUT                                 *recomendado
**------------------------------------------------------------------
  alv_layout-colwidth_optimize = 'X'. "optimización de ancho columna
  alv_layout-cell_merge = 'X'.        "fusión de celdas
  alv_layout-no_vline = 'X'.          "sin línea separadora vertical
  alv_layout-zebra = ' '.             "franjas alternas de color

** campo de COLOR DE LÍNEA                                 *opcional
**------------------------------------------------------------------
* alv_layout-info_fieldname = 'COLOR'. "campo it_alv color de línea

** campo de COLOR DE CELDAS                                *opcional
**------------------------------------------------------------------
* alv_layout-coltab_fieldname = 'COLOR'  "campo it_alv color celdas

** campo de SELECCIÓN DE LÍNEA                             *opcional
** el campo puesto aquí no necesita ir en el fieldcat
**------------------------------------------------------------------
* alv_layout-box_fieldname = 'LOEKZ'.

** SORTING                                                 *opcional
** necesario si queremos que cell_merge funcione la primera vez
**------------------------------------------------------------------
*  ls_sort-fieldname = 'EBELN'.
*  ls_sort-up = 'X'. "contrario es ls_sort-down = 'X'
*  APPEND ls_sort TO alv_sort.

** definición de EVENTS                                    *opcional
**------------------------------------------------------------------
*  ls_events-name = 'TOP_OF_PAGE'.
*  ls_events-form = 'ALV_TOP_OF_PAGE'.
*  APPEND ls_events TO alv_events.

** definición de FIELDCAT       *obligatorio si no se usa estructura
**------------------------------------------------------------------
  PERFORM alv_fields USING alv_fieldcat[].

**                                             *llamada a la función
**------------------------------------------------------------------
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
       EXPORTING
            is_layout                = alv_layout
            it_fieldcat              = alv_fieldcat
            it_sort                  = alv_sort
            it_events                = alv_events
            i_callback_program       = lsyrepid
            i_callback_pf_status_set = 'ALV_SET_STATUS'
            i_callback_user_command  = 'ALV_COMMAND'
*           I_STRUCTURE_NAME         = 'TABLADICCIONARIO'
*                   en este caso no usaríamos it_fieldcat
       TABLES
            t_outtab                 = it_alv.
*-------------------------------------------------------------------
ENDFORM.                    "alv_display
***********************************************************************
*       _                _
*  __ _| |_   _____ ___ | | ___  _ __
* / _` | | \ / / __| _ \| |/ _ \| '__|
*| (_| | |\ V / (__ (_) | | (_) | |
* \__,_|_| \_/ \___|___/|_|\___/|_|
DEFINE alv_color.
* MACRO para convertir color humano en código color Cxyz
* uso: alv_color campo 'texto en español'

* en EMPHASIZE o en el campo COLOR usamos char(4)
* con la forma Cxyz, x€[0,7]; y,z€[0,1] / y+z<2
* valores de x:
*            0 COL_BACKGROUND fondo (gris)
*            1 COL_HEADING    azul oscuro
*            2 COL_NORMAL     azul claro
*            3 COL_TOTAL      amarillo
*            4 COL_KEY        azul
*            5 COL_POSITIVE   verde
*            6 COL_NEGATIVE   rojo
*            7 COL_GROUP      naranja
* valores de y: 0 = normal, 1 = intenso
* valores de z: 0 = xy afecta fondo, 1 = x invertido

*          OJO: ls_fieldcat-key = 'X' invalida lo anterior

  &1 = 'C000'. "gris fondo por definición
  find 'azul' in &2 ignoring case.
  if sy-subrc = 0.
    &1+1(1) = '4'.
    find 'claro' in &2 ignoring case.
    if sy-subrc = 0. &1+1(1) = '2'. endif.
    find 'oscuro' in &2 ignoring case.
    if sy-subrc = 0. &1+1(1) = '1'. endif.
  endif.
  find 'amar' in &2 ignoring case.
  if sy-subrc = 0. &1+1(1) = '3'. endif.
  find 'verd' in &2 ignoring case.
  if sy-subrc = 0. &1+1(1) = '5'. endif.
  find 'rojo' in &2 ignoring case.
  if sy-subrc = 0. &1+1(1) = '6'. endif.
  find 'nara' in &2 ignoring case.
  if sy-subrc = 0. &1+1(1) = '7'. endif.
  find 'ntens' in &2 ignoring case.
  if sy-subrc = 0. &1+2(2) = '10'. endif.
  find 'nver' in &2 ignoring case.
  if sy-subrc = 0. &1+2(2) = '01'. endif.
END-OF-DEFINITION.
***********************************************************************
* COLOR para su uso dentro del FORM ALV_FIELDS
DEFINE fld_color.
  alv_color ls_fieldcat-emphasize &1.
END-OF-DEFINITION.
***********************************************************************
* TEXTO para su uso dentro del FORM ALV_FIELDS
DEFINE fld_texto.
  ls_fieldcat-seltext_s   = &1.
  ls_fieldcat-seltext_m   = &1.
  ls_fieldcat-seltext_l   = &1.
END-OF-DEFINITION.
***********************************************************************
*       _        __ _      _     _
*  __ _| |_   __/ _|_) ___| | __| |___
* / _` | | \ / / |_| |/ _ \ |/ _` | __|
*| (_| | |\ V /|  _| |  __/ | (_| |__ \
* \__,_|_| \_/ |_| |_|\___|_|\__,_|___/DEFINICIÓN DE CAMPOS
*
FORM alv_fields USING pfieldcat TYPE slis_t_fieldcat_alv..
  DATA ls_fieldcat  TYPE slis_fieldcat_alv.
  REFRESH pfieldcat.

  CLEAR ls_fieldcat.
  ls_fieldcat-fieldname   = 'EBELN'.
  ls_fieldcat-ref_tabname = 'EKKO'.
  ls_fieldcat-key         = ''.
  ls_fieldcat-icon        = ''.
  ls_fieldcat-checkbox    = ''.
  ls_fieldcat-no_out      = ''.
  fld_color 'amarillo'.
  APPEND ls_fieldcat TO pfieldcat.

** TEMPLATE PARA CAMPOS DE DICCIONARIO
*  CLEAR ls_fieldcat.
*  ls_fieldcat-fieldname   = ''.
*  ls_fieldcat-ref_tabname = ''.
*  ls_fieldcat-key         = ''.
*  ls_fieldcat-no_out      = ''.
*  fld_color ''.
*  APPEND ls_fieldcat TO pfieldcat.

** TEMPLATE PARA TEXTOS S/M/L IGUALES
*  CLEAR ls_fieldcat.
*  ls_fieldcat-fieldname   = ''.
*  ls_fieldcat-key         = ''.
*  ls_fieldcat-icon        = ''.
*  ls_fieldcat-checkbox    = ''.
*  ls_fieldcat-no_out      = ''.
*  fld_texto ''.
*  fld_color ''.
*  APPEND ls_fieldcat TO pfieldcat.

** TEMPLATE PARA TEXTOS S/M/L DISTINTOS
*  CLEAR ls_fieldcat.
*  ls_fieldcat-fieldname   = ''.
*  ls_fieldcat-key         = ''.
*  ls_fieldcat-icon        = ''.
*  ls_fieldcat-checkbox    = ''.
*  ls_fieldcat-no_out      = ''.
*  ls_fieldcat-seltext_s   = ''.
*  ls_fieldcat-seltext_m   = ''.
*  ls_fieldcat-seltext_l   = ''.
*  fld_color ''.
*  APPEND ls_fieldcat TO pfieldcat.

ENDFORM.                    "alv_fields
*
* FORMS DE LLAMADA DINÁMICA DESDE LA ALV
***********************************************************************
*       _                _       _        _
*  __ _| |_   _____  ___| |_ ___| |_ __ _| |_ _   _ ___
* / _` | | \ / / __|/ _ \ __| __| __| _` | __| | | | __|
*| (_| | |\ V /\__ \  __/ |_\__ \ |_ (_| | |_| |_| |__ \
* \__,_|_| \_/ |___/\___|\__|___/\__|__,_|\__|\__,_|___/
*  DEFINICIÓN DE STATUS BAR
FORM alv_set_status USING prt_extab TYPE slis_t_extab.
* barra de status de referencia
**--------------------------------------------------------------------
  SET PF-STATUS 'STANDARD_FULLSCREEN' OF PROGRAM 'SAPLKKBL'.
ENDFORM.                    "alv_set_status
***********************************************************************
*       _       _                     __
*  __ _| |_   __ |_ ___  _ __   ___  / _|_ __   __ _  __ _  ___
* / _` | | \ / / __| _ \| '_ \ / _ \| |_| '_ \ / _` |/ _` |/ _ \
*| (_| | |\ V /| |_ (_) | |_) | (_) |  _| |_) | (_| | (_| |  __/
* \__,_|_| \_/  \__|___/| .__/ \___/|_| | .__/ \__,_|\__, |\___|
* CABECERA DE LISTA     |_|             |_|          |___/
FORM alv_top_of_page.

  DATA: lls_list TYPE slis_listheader.
  DATA: lalv_list TYPE slis_t_listheader.

**definición de cada línea de la cabecera
**el typ puede tener valores: H = header, S = selection, A = action
**--------------------------------------------------------------------
  lls_list-typ = 'H'.
  lls_list-info = 'TÍTULO DEL LISTADO'.
  APPEND lls_list TO lalv_list.

*---------------------------------------------------------------------
  CALL FUNCTION 'REUSE_ALV_COMMENTARY_WRITE'
    EXPORTING
      it_list_commentary = lalv_list.
*---------------------------------------------------------------------
ENDFORM.                    "alv_top_of_page
***********************************************************************
*       _                                                    _
*  __ _| |_   _____ ___  _ __ ___  _ __ ___   __ _ _ __   __| |
* / _` | | \ / / __| _ \| '_ ` _ \| '_ ` _ \ / _` | '_ \ / _` |
*| (_| | |\ V / (__ (_) | | | | | | | | | | | (_| | | | | (_| |
* \__,_|_| \_/ \___|___/|_| |_| |_|_| |_| |_|\__,_|_| |_|\__,_|
*  RESPUESTA A COMANDOS
FORM alv_command USING
    r_ucomm LIKE sy-ucomm
    rs_selfield TYPE slis_selfield.

** actualiza celdas editadas en modo edición
**--------------------------------------------------------------------
*  DATA p_ref1 TYPE REF TO cl_gui_alv_grid.
*  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
*    IMPORTING
*      e_grid = p_ref1.
*  CALL METHOD p_ref1->check_changed_data.

** toma de decisiones en función de UCOMM
**--------------------------------------------------------------------
  CASE r_ucomm.
********* doble click [rs_selfield-tabindex = línea seleccionada]
    WHEN '&IC1'.
********* otros comandos
    WHEN OTHERS.
  ENDCASE.

** cambiamos el field catalog si es necesario hacerlo sobre la marcha
**--------------------------------------------------------------------
*  DATA lfieldcat TYPE slis_t_fieldcat_alv.
*  CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_GET'
*    IMPORTING
*      et_fieldcat = lfieldcat[].
*
** podemos escoger el form original o utilizar otro que nos convenga
*  PERFORM alv_fields USING lfieldcat[].
*
*  CALL FUNCTION 'REUSE_ALV_GRID_LAYOUT_INFO_SET'
*    EXPORTING
*      it_fieldcat = lfieldcat[].

* conservamos la posición del click
  rs_selfield-row_stable = 'X'.
  rs_selfield-col_stable = 'X'.

* esencial para que redibuje: NUNCA se debe rellamar a la función
**--------------------------------------------------------------------
  rs_selfield-refresh = 'X'.

ENDFORM.                    "alv_command
***********************************************************************
  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV

18 abril 2010

reloj de avance para tablas internas

archivado en: ABAP/IV


Hola sufridos programadores de ABAP:

A veces es frustrante, tanto para el usuario como para nosotros mismos, no saber cuándo un programa acabará de ejecutarse. Para ello he creado una minilibrería con tres macros, muy sencilla de utilizar, que, convenientemente utilizada en cualquier LOOP, nos mostrará:

  1. lo que está haciendo (que se lo especificaremos nosotros como texto opcional)
  2. el porcentaje de avance de recorrido de la tabla
  3. el tiempo total estimado
  4. el tiempo faltante para acabar
  5. línea procesada y total de líneas de la tabla interna

Las macros son las siguientes:

  • vc_clocktimer texto: Se sitúa dentro del LOOP que nos interesa especificándole un texto corto descriptivo. No hace falta nada más ya que el cálculo se hace a partir de la variable de sistema sy-tabix. Fuera de un LOOP no funcionará.
  • vc_clockreset tabla: se sitúa antes del LOOP para poner el contador de tiempo a cero y analizar la tabla interna en la que vamos a meter el reloj.

  • vc_seconds2hms: de uso interno, convierte segundos a formato HH:MM:SS indicando “+100h” en caso de que el tiempo resultante sea superior a 100 horas. También es utilizable de manera independiente

Al final del código de ejemplo que pongo más abajo, en negrita, se puede ver lo sencilla que es su inserción. El gráfico superior, que muestra el reloj en funcionamiento, corresponde a este mismo programa.

Es importante señalar que asume que la resolución temporal de la sentencia GET RUN TIME está afinada al microsegundo; la opción por defecto de los sistemas SAP. De otro modo dará resultados absurdos.

Más importante aún es avisar de que en conexiones lentas la actualización del reloj en el SAPgui puede afectar negativamente al rendimiento. En ese caso convendrá llamar a la macro vc_clocktimer sólo cada n pasos.

REPORT  z_percentage_clock.
* _  __        _            _
*(_)/ /    ___| | ___   ___| | __
*  / /    / __| |/ _ \ / __| |/ /
* / /_   | (__| | (_) | (__|   <
*/_/(_)   \___|_|\___/ \___|_|\_\
* as seen in http://glob.cranf.net
* ASCII art made using http://ascii.cranf.net
*
***********************************************************************
DATA vc_clocktlines TYPE i.
DATA vc_time0 TYPE f.
***********************************************************************
DEFINE vc_seconds2hms.
  perform vc_seconds2hms using &1 changing &2.
END-OF-DEFINITION.
*
FORM vc_seconds2hms USING pseconds CHANGING phms.
  DATA vc_segundos TYPE uzeit.
  DATA vc_segundosi TYPE i.
  vc_segundosi = pseconds.
  IF vc_segundosi < 360000.
    vc_segundos = vc_segundosi.
    WRITE vc_segundos TO phms.
  ELSE.
    phms = '+100h'.
  ENDIF.
ENDFORM.                    "vc_seconds2hms
***********************************************************************
DEFINE vc_clockreset.
  vc_clocktlines = 0.
  describe table &1 lines vc_clocktlines.
  get run time field vc_time0.
END-OF-DEFINITION.
***********************************************************************
DEFINE vc_clocktimer.
  perform vc_clocktimer using &1.
END-OF-DEFINITION.
*
FORM vc_clocktimer USING vc_ptexto.

  DATA vc_porcentaje TYPE i.
  DATA vc_porcentajet(4).
  DATA vc_pend TYPE f.
  DATA vc_tabixt(8).
  DATA vc_tfillt(8).
  DATA vc_linest(20).

  DATA vc_time TYPE f.
  DATA vc_timetotal TYPE f.
  DATA vc_timetotalt(8).
  DATA vc_timefalta TYPE f.
  DATA vc_timefaltat(8).
  DATA vc_timefin TYPE uzeit.
  DATA vc_timefint(8).
  DATA vc_mensaje(100).

  CHECK vc_clocktlines > 0.
  CHECK sy-tabix > 0.

  GET RUN TIME FIELD vc_time.

  vc_pend = ( vc_time - vc_time0 ) / sy-tabix .
  vc_timetotal = vc_pend * vc_clocktlines / 1000000.
  vc_timefalta = vc_pend * ( vc_clocktlines - sy-tabix ) / 1000000 + 1.
  vc_porcentaje = sy-tabix * 100 / vc_clocktlines.

  WRITE vc_porcentaje TO vc_porcentajet.
  CONCATENATE vc_porcentajet '%' INTO vc_porcentajet.
  CONDENSE vc_porcentajet NO-GAPS.
  WRITE sy-tabix TO vc_tabixt.
  WRITE vc_clocktlines TO vc_tfillt.
  CONCATENATE '[' vc_tabixt '/' vc_tfillt ']' INTO vc_linest.
  CONDENSE vc_linest NO-GAPS.
  vc_seconds2hms vc_timetotal vc_timetotalt.
  vc_seconds2hms vc_timefalta vc_timefaltat.
  vc_timefin = sy-uzeit + vc_timefalta.
  WRITE vc_timefin TO vc_timefint.

  CONCATENATE
    vc_ptexto
    vc_porcentajet
    'Total'
    vc_timetotalt
    'Resta'
    vc_timefaltat
    'Final'
    vc_timefint
    vc_linest
  INTO vc_mensaje SEPARATED BY space.
  CONDENSE vc_mensaje.

  CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
       EXPORTING
            percentage = vc_porcentaje
            text       = vc_mensaje.
ENDFORM.                    "vc_clocktimer
***********************************************************************

*       _                      _
*  ___ (_) ___ _ __ ___  _ __ | | ___
* / _ \| |/ _ \ '_ ` _ \| '_ \| |/ _ \
*|  __/| |  __/ | | | | | |_) | | (_) |
* \___|/ |\___|_| |_| |_| .__/|_|\___/
*    |__/               |_|
*______________________________________________________________________

DATA it_dd02l TYPE TABLE OF dd02l WITH HEADER LINE.

START-OF-SELECTION.

  SELECT *
  FROM dd02l
  INTO TABLE it_dd02l
  UP TO 10 ROWS.

* pone a cero el reloj
  vc_clockreset it_dd02l.

* recorremos la tabla
  LOOP AT it_dd02l.

*   dibuja el reloj con el texto elegido
    vc_clocktimer 'Proceso'.

*   retraso temporal de un segundo por ciclo
    CALL FUNCTION 'RZL_SLEEP'
         EXPORTING
              seconds        = 1
         EXCEPTIONS
              argument_error = 1
              OTHERS         = 2.
  ENDLOOP.
  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV

9 marzo 2010

enviar mails desde R/3

archivado en: ABAP/IV

Hola sufridos programadores de ABAP:

Enviar correos electrónicos desde R/3 es una tarea sencilla… si sabes cómo. Si no, puede ser algo muy lioso.

El requisito básico es configurar, en la transacción SCOT, un servidor SMTP. Debemos añadir al árbol INT (internet) un objeto SMTP y posteriormente configurarlo: basta con darle un nombre, activar la casilla “Nodo en operación” y especificar en Host y Puerta el nombre o IP del servidor SMTP y el puerto (normalmente el 25).

Pon también, en los tipos de dirección soportados, un * dentro del botón adyacente a la casilla “Internet”. Nada de esto servirá si en el menú de la SCOT > Opciones > Dominio por defecto no ponemos el nombre del dominio desde donde queremos que figure el remitente.

El servidor de correo, por otra parte, deberá estar correctamente configurado y con una adecuada política de permisos, que en ocasiones, dentro de las empresas, es muy restrictivo. De hecho, no me detengo mucho en esto porque esto es responsabilidad de Sistemas y no nuestra, meros picacódigos.

El proceso de enviar el mail en sí admite un montón de parámetros: pero, en aras de la simplicidad, he creado una función que debería funcionar en prácticamente cualquier sistema y que tiene sólo 3 parámetros: destinatario, título y contenido. Control de errores y demás están reducidos al mínimo, pero se pueden añadir a voluntad del programador.

He aquí el código de la función:

FUNCTION z_send_text_mail.
*"----------------------------------------------------------------------
*"*"Interfase local
*"  IMPORTING
*"     VALUE(EMAIL) TYPE  STRING
*"     VALUE(SUBJECT) TYPE  STRING
*"     VALUE(TEXT) TYPE  STRING
*"----------------------------------------------------------------------
  "as seen on http://glob.cranf.net

  DATA it_packing_list TYPE TABLE OF sopcklsti1 WITH HEADER LINE.
  DATA it_receivers TYPE TABLE OF somlreci1 WITH HEADER LINE.
  DATA it_contents_txt TYPE TABLE OF solisti1 WITH HEADER LINE.
  DATA document_data TYPE sodocchgi1.
  DATA sent_to_all.

  "pasamos el string a tabla
  PERFORM string2table TABLES it_contents_txt USING text.

  "atributos del mensaje
  document_data-obj_langu = sy-langu.
  document_data-obj_name = 'SAPRPT'.
  document_data-obj_descr = subject.
  document_data-sensitivty = 'S'.
  document_data-no_change = space.

  " descripción del body
  CLEAR it_packing_list.
  REFRESH it_packing_list.
  it_packing_list-transf_bin = space.
  it_packing_list-head_start = 1.
  it_packing_list-head_num = 0.
  it_packing_list-body_start = 1.
  DESCRIBE TABLE it_contents_txt LINES it_packing_list-body_num.
  it_packing_list-doc_type = 'TXT'.
  APPEND it_packing_list.

  " destinatario
  CLEAR it_receivers.
  REFRESH it_receivers.
  it_receivers-receiver = email.
  it_receivers-rec_type = 'U'.
  it_receivers-com_type = 'INT'.
  APPEND it_receivers.

  CALL FUNCTION 'SO_NEW_DOCUMENT_ATT_SEND_API1'
    EXPORTING
      document_data              = document_data
      put_in_outbox              = 'X'
      commit_work                = 'X'
    IMPORTING
      sent_to_all                = sent_to_all
    TABLES
      packing_list               = it_packing_list
      contents_txt               = it_contents_txt
      receivers                  = it_receivers
    EXCEPTIONS
      too_many_receivers         = 1
      document_not_sent          = 2
      document_type_not_exist    = 3
      operation_no_authorization = 4
      parameter_error            = 5
      x_error                    = 6
      enqueue_error              = 7
      OTHERS                     = 8.

ENDFUNCTION.

*     _        _             ____  _        _     _
* ___| |_ _ __(_)_ __   __ _|___ \| |_ __ _| |__ | | ___
*/ __| __| '__| | '_ \ / _` | __) | __| _` | '_ \| |/ _ \
*\__ \ |_| |  | | | | | (_| |/ __/| |_ (_| | |_) | |  __/
*|___/\__|_|  |_|_| |_|\__, |_____|\__|__,_|_.__/|_|\___|
*       ASCII Art made |___/ at http://ascii.cranf.net
FORM string2table TABLES ptable USING pstring TYPE string.
  DATA lstring TYPE string.
  DATA loffset TYPE i.
  DATA lofflen TYPE i.
  DATA llimlen TYPE i.
  DATA lchunks TYPE i.
  DATA ltablength TYPE i.
  DATA lstrlength TYPE i.

  lstring = pstring.
  lstrlength = STRLEN( lstring ).

  DESCRIBE FIELD ptable LENGTH ltablength IN CHARACTER MODE.
  lofflen = ltablength.

  lchunks = lstrlength / ltablength.

  WHILE loffset < lstrlength.
    llimlen = ltablength + loffset.
    IF llimlen > lstrlength.
      lofflen = lstrlength - loffset.
    ENDIF.
    ptable = lstring+loffset(lofflen).
    APPEND ptable.
    loffset = loffset + ltablength.
  ENDWHILE.
  CLEAR ptable.

ENDFORM.                    "string2table

El texto puede incluir saltos de línea siempre que se haga uso de saltos de línea adecuados.

Es importante tener en cuenta que la función por sí sola no manda el mail. Debemos invocar un report estándar que se encarga de liberar la cola de correo. En principio esto está, o debería estar configurado, como job periódico. Pero podemos dar un empujoncito creando la siguiente función, que no tiene parámetros, para que los mails se hagan efectivos.

FUNCTION z_mail_launch.

  SUBMIT rsconn01 WITH mode = 'INT' WITH output = '' AND RETURN.

ENDFUNCTION.
  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV

17 febrero 2010

macros para mensajes de batch-input y bapi

archivado en: ABAP/IV

Hola y autocompasión para nosotros, sufridos programadores de ABAP.

La gestión de mensajes en Batch-Input y BAPI es bastante horrorosa, teniendo en cuenta además que utilizan dos estructuras muy similares pero con nombres de campos muy parecidos, lo que suele llevar a confusiones frustrantes cuando intentamos analizar el resultado.

Estas macros permiten gestionar los mensajes de ambos tipo de llamadas unificando criterios y simplificando al máximo el código a utilizar.

  • vc_messtab2bapiret messtab bapiret2: mueve una estructura bdcmsgcoll a bapiret2.
  • vc_bapiret2messtab bapiret2 messtab: mueve una estructura bapiret2 a bdcmsgcoll.
  • vc_messtab2mensaje messtab cadenadetexto: construye un mensaje como texto a partir de una estructura bdcmsgcoll.
  • vc_bapiret2mensaje bapiret2 cadenadetexto: construye un mensaje como texto a partir de una estructura bapiret2.
* _     _    ___                 _
*| |__ (_)  / / |__   __ _ _ __ (_)   _ __ ___   ___ ___ ___  __ _  __ _  ___ ___
*| '_ \| | / /| '_ \ / _` | '_ \| |  | '_ ` _ \ / _ \ __| __|/ _` |/ _` |/ _ \ __|
*| |_) | |/ / | |_) | (_| | |_) | |  | | | | | |  __/__ \__ \ (_| | (_| |  __/__ \
*|_.__/|_|_/  |_.__/ \__,_| .__/|_|  |_| |_| |_|\___|___/___/\__,_|\__, |\___|___/
*                         |_|                                      |___/
* as seen in http://glob.cranf.net
* ASCII art made using http://ascii.cranf.net
*
***********************************************************************
DEFINE vc_messtab2bapiret."convierte estructura messtab de BI a bapiret2
  "vc_messtab2bapiret messtab bapiret2.
  "lo hace de línea en línea, no usando tablas
  perform vc_messtab2bapiret using &1 changing &2.
END-OF-DEFINITION.
*
FORM vc_messtab2bapiret USING pbi TYPE bdcmsgcoll
                      CHANGING pbapi TYPE bapiret2.
  pbapi-type = pbi-msgtyp.
  pbapi-id = pbi-msgid.
  pbapi-number = pbi-msgnr.
  pbapi-message_v1 = pbi-msgv1.
  pbapi-message_v2 = pbi-msgv2.
  pbapi-message_v3 = pbi-msgv3.
  pbapi-message_v4 = pbi-msgv4.
ENDFORM.                    "vc_messtab2bapiret
***********************************************************************
DEFINE vc_bapiret2messtab. "convierte estructura bapiret2 a messtab de BI
  "vc_bapiret2messtab bapiret2 messtab.
  "lo hace de línea en línea, no usando tablas
  perform vc_bapiret2messtab using &1 changing &2.
END-OF-DEFINITION.
*
FORM vc_bapiret2messtab USING pbapi TYPE bapiret2
                     CHANGING pbi TYPE bdcmsgcoll.
  pbi-msgtyp = pbapi-type.
  pbi-msgid = pbapi-id.
  pbi-msgnr = pbapi-number.
  pbi-msgv1 = pbapi-message_v1.
  pbi-msgv2 = pbapi-message_v2.
  pbi-msgv3 = pbapi-message_v3.
  pbi-msgv4 = pbapi-message_v4.
ENDFORM.                    "vc_bapiret2messtab
***********************************************************************
DEFINE vc_messtab2mensaje. "convierte estructura messtab en mensaje verbal
  "vc_messtab2mensaje messtab cadenadetexto
  perform vc_messtab2mensaje using &1 changing &2.
END-OF-DEFINITION.
*
FORM vc_messtab2mensaje USING pbi TYPE bdcmsgcoll
                     CHANGING pmensaje.

  DATA lmsgid LIKE sy-msgid.
  DATA lmsgnr LIKE sy-msgno.
  DATA lmensaje LIKE sy-lisel.
  DATA lmsgv1 TYPE symsgv.
  DATA lmsgv2 TYPE symsgv.
  DATA lmsgv3 TYPE symsgv.
  DATA lmsgv4 TYPE symsgv.

  lmsgid = pbi-msgid.
  lmsgnr = pbi-msgnr.
  lmsgv1 = pbi-msgv1.
  lmsgv2 = pbi-msgv2.
  lmsgv3 = pbi-msgv3.
  lmsgv4 = pbi-msgv4.

  CALL FUNCTION 'RPY_MESSAGE_COMPOSE'
    EXPORTING
      language          = sy-langu
      message_id        = lmsgid
      message_number    = lmsgnr
      message_var1      = lmsgv1
      message_var2      = lmsgv2
      message_var3      = lmsgv3
      message_var4      = lmsgv4
    IMPORTING
      message_text      = lmensaje
    EXCEPTIONS
      message_not_found = 1
      OTHERS            = 2.
  IF sy-subrc <> 0.
    CLEAR lmensaje.
  ENDIF.
  pmensaje = lmensaje.
ENDFORM.                    "vc_messtab2mensaje
***********************************************************************
DEFINE vc_bapiret2mensaje."convierte estructura bapiret2 en mensaje verbal
  perform vc_bapiret2mensaje using &1 changing &2.
END-OF-DEFINITION.
*
FORM vc_bapiret2mensaje USING pbapi TYPE bapiret2
                     CHANGING pmensaje.
  DATA lbi TYPE bdcmsgcoll.
  vc_bapiret2messtab pbapi lbi.
  vc_messtab2mensaje lbi pmensaje.
ENDFORM.                    "vc_bapiret2mensaje
***********************************************************************

Self-Promotion: Tengo unas estupendas macros para hacer Batch-Input en mi compactador de código BI. Échales un vistazo.

  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV

porcentaje de iva a partir del indicador

archivado en: ABAP/IV

Buenas, sufridos programadores de ABAP.

Los que estamos curtidos sabemos que, a veces, los caminos de SAP son inexcrutables inescrutables; pero más por retorcidos que porque no se puedan deducir. Es el caso de los porcentajes que corresponden a los tipos de IVA recogidos en campos MWSKZ. En vez de ser almacenados en una tabla al efecto, pues no. Se marea al programador.

La siguiente rutina deduce el porcentaje correspondiente a un indicador de IVA simplemente conociendo este y el país. Si sy-subrc no vale 0, es que no lo ha encontrado; esto se deberá controlar.

Una advertencia: los valores son devueltos como porcentajes literales, de 0 a 100. Cualquier operación que se realice con ellos deberá ser dividida a su vez por 100 para que el resultado sea correcto.

*     _          _                   _  __   _
*  __| | ___  __| |_   _  ___ ___   (_)/ /  (_)_   ____ _
* / _` |/ _ \/ _` | | | |/ __| _ \    / /   | | \ / / _` |
*| (_| |  __/ (_| | |_| | (__  __/   / /_   | |\ V / (_| |
* \__,_|\___|\__,_|\__,_|\___|___|  /_/(_)  |_| \_/ \__,_|
* as seen on http://glob.cranf.net
* ASCII art made at http://ascii.cranf.net
*
FORM deduce_porcentaje_iva USING pland1 pmwskz CHANGING pkbetr LIKE konp-kbetr.

  DATA lvakey LIKE konh-vakey.
  DATA lknumh LIKE konh-knumh.
  CLEAR pkbetr.

  CONCATENATE pland1 pmwskz INTO lvakey SEPARATED BY space.

  SELECT SINGLE knumh
    INTO lknumh
    FROM konh
   WHERE vakey = lvakey.

  IF sy-subrc = 0.
    SELECT SINGLE kbetr INTO pkbetr
      FROM konp
     WHERE knumh = lknumh.
    IF sy-subrc = 0.
      pkbetr = pkbetr / 10.
    ELSE.
      sy-subrc = 2.
    ENDIF.
  ELSE.
    sy-subrc = 1.
  ENDIF.
ENDFORM.
  • RSS
  • Facebook
  • Meneame
  • Twitter
  • MySpace
  • Digg
  • del.icio.us
  • BarraPunto
  • Bitacoras.com
  • Slashdot
  • StumbleUpon
  • Technorati
  • Wikio
  • Google Bookmarks
archivado en: ABAP/IV
índice   cranf.net   wordnadapress
123