在 ABAP 中,负数值的显示一直是个很让大家头疼的问题,虽然有一个系统函数可以把数字转换成字符后把负号提前,却失去了千位分隔符。网上还能找到用转换例程实现的负号提前方法,我没有验证过,不知道能否输出千位分隔符。
我这个函数也是把数值类型转换为字符串输出,改进之处在于可以通过输入参数设置输出的小数位数和输出字符串的对齐方式,在输出中也同时包含了带千位分隔符和不带千位分隔符的两种形式。
在 ABAP 中,负数值的显示一直是个很让大家头疼的问题,虽然有一个系统函数可以把数字转换成字符后把负号提前,却失去了千位分隔符。网上还能找到用转换例程实现的负号提前方法,我没有验证过,不知道能否输出千位分隔符。
下面是一些相关方法的链接:
http://hi.baidu.com/zhangjigang/blog/item/bfeb9d2f8a7bd23b1e308968.html
http://blog.csdn.net/CompassButton/archive/2007/01/31/1499218.aspx
http://hi.baidu.com/festsoft/blog/item/2cb6b713a8d3cad5f6039e31.html
我这个函数也是把数值类型转换为字符串输出,改进之处在于可以通过输入参数设置输出的小数位数和输出字符串的对齐方式,在输出中也同时包含了带千位分隔符和不带千位分隔符的两种形式。
现在的输入值只允许 i 和 p,没有对浮点小数 f 类型做测试,各位如果感兴趣的话可以自行添加相应的处理。
Code
FUNCTION z_sign_to_front.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" VALUE(INPNUMERIC) 输入的数值,i 或 p 类型
*" VALUE(INPDECIMALS) TYPE I DEFAULT -1 小数位数,默认 -1 取输入值的位数
*" VALUE(INPRIGHTJUST) TYPE C DEFAULT 'X' 默认X,自动右对齐,否则左对齐。
*" EXPORTING
*" VALUE(WITHTHSEP) TYPE C 输出值,带千位分隔符
*" VALUE(WITHTHSEPLEN) TYPE I 输出值长度
*" VALUE(WITHOUTTHSEP) TYPE C 输出值,不带千位分隔符
*" VALUE(WITHOUTTHSEPLEN) TYPE I 输出值长度
*" EXCEPTIONS
*" NOTNUMERIC 输入的类型不正确
*" DECIMALSOVERFLOW 输入的小数位不在 -1 到 8 之间
*"----------------------------------------------------------------------
DATA: ntyp TYPE c,
nlen TYPE i,
ndec TYPE i.
DATA: cstring(50) TYPE c, "中间字符串,P类型最长32个数字,加上11个千位分隔符或小数点,最多43位。
cmask(50) TYPE c. "掩码。
DATA: ioff TYPE i,
ilen TYPE i.
DATA: decprefix(50) TYPE c, "整数部分
decsuffix(10) TYPE c. "小数部分
* 检测输入值的数据类型
DESCRIBE FIELD inpnumeric TYPE ntyp DECIMALS ndec.
* 如果不是 p 或 i 就触发例外
IF ( ntyp EQ 'P' ) OR ( ntyp EQ 'i' ).
ELSE.
RAISE notnumeric.
ENDIF.
* 如果小数位超过值域就触发例外
IF ( inpdecimals LT -1 ) OR ( inpdecimals GT 8 ).
RAISE decimalsoverflow.
ENDIF.
* 填写掩码
DO 50 TIMES.
ioff = sy-index - 1.
cmask+ioff(1) = '_'.
ENDDO.
* 设置掩码的小数位
IF ndec EQ 0.
ioff = 50.
ELSE.
ioff = 50 - ndec - 1.
cmask+ioff(1) = '.'.
ENDIF.
ioff = ioff - 4.
* 设置掩码的千位分隔符
WHILE ioff GE 0.
cmask+ioff(1) = ','.
ioff = ioff - 4.
ENDWHILE.
* 设置输出格式掩码
cmask(3) = 'RRV'.
* 按照编辑掩码赋值
WRITE inpnumeric TO cstring RIGHT-JUSTIFIED USING EDIT MASK cmask.
* 压缩多余空格和千位分隔符
CONDENSE cstring NO-GAPS.
REPLACE FIRST OCCURRENCE OF ',,,,,,,,' IN cstring WITH space.
REPLACE FIRST OCCURRENCE OF ',,,,' IN cstring WITH space.
REPLACE FIRST OCCURRENCE OF ',,' IN cstring WITH space.
FIND ',' IN cstring IN CHARACTER MODE MATCH OFFSET ioff.
IF ioff EQ 0.
REPLACE FIRST OCCURRENCE OF ',' IN cstring WITH space.
ENDIF.
REPLACE FIRST OCCURRENCE OF '-,' IN cstring WITH '-'.
* 如果指定了小数位数,就用指定的小数位
IF inpdecimals NE -1.
SPLIT cstring AT '.' INTO decprefix decsuffix.
* 指定的小数位为 0,截断小数点以后的位置。否则按位补齐。
IF inpdecimals EQ 0.
cstring = decprefix.
ELSE.
* 原来的小数位长度
ioff = STRLEN( decsuffix ).
* 如果大于要求位数,就截断
IF ioff GT inpdecimals.
decsuffix = decsuffix+0(inpdecimals).
ENDIF.
* 如果小于要求位数,就在末尾补 0
IF ioff LT inpdecimals.
ilen = inpdecimals - ioff.
DO ilen TIMES.
CONCATENATE decsuffix '0' INTO decsuffix.
ENDDO.
ENDIF.
* 组合结果
CONCATENATE decprefix '.' decsuffix INTO cstring.
ENDIF.
ENDIF.
* 填写输出值
withthsep = cstring.
withthseplen = STRLEN( withthsep ).
REPLACE ALL OCCURRENCES OF ',' IN cstring WITH space.
withoutthsep = cstring.
withoutthseplen = STRLEN( withoutthsep ).
* 右对齐
IF inprightjust EQ 'X'.
WRITE withthsep TO withthsep RIGHT-JUSTIFIED.
WRITE withoutthsep TO withoutthsep RIGHT-JUSTIFIED.
ENDIF.
ENDFUNCTION.