[SAPABAP开发技术总结]数据输入输出转换、小数位单位货币格式化

更新时间:2023-07-26 18:48:09 阅读: 评论:0

[SAPABAP开发技术总结]数据输⼊输出转换、⼩数位单位货币
格式化
15.数据格式化、转换
15.1.数据输⼊输出转换
15.1.1.输出时⾃动转换
如果某个变量参照的数据元素所对应的Domain具有转换规则,那么在输出时(如Write输出、ALV展⽰、⽂本框中显⽰),最后显⽰的结果会⾃动发⽣转换,如参照 ekpo-meins 表字段的变量赋值时就会发⽣转换,因为 ekpo-meins 所对应的元素Doamin设置了转换规则:
所以,在显⽰输出这样的数据时要注意,如果要显⽰原始数据,则不能参照该表字段来定义变量,⽽是⾃⼰定义。
:i_meins LIKE ekpo-meins,
i_meins2 TYPE c LENGTH 3.
START-OF-SELECTION.
SELECT meins meins FROM ekpo INTO (i_meins,i_meins2) WHERE ebeln = '4500012164'.
"输出时, i_meins会⾃动发⽣转换,但 i_meins2 不会
WRITE: i_meins,i_meins2.
ENDSELECT.
SKIP.
DATA: i_meins3 LIKE ekpo-meins.
"注:这⾥只能是内部单位ST,⽽不是PC,因为Write时是输出转换(即内->外的转换)
i_meins3 = 'ST'.
"只要是参考过 ekpo-meins 的变量,Write输出时⾃动转换
WRITE:/ i_meins3.
在调试过程中发现都是原始数据,⾃动转换发⽣在Write输出时:
15.1.2.输⼊时⾃动转换
输出时会发⽣⾃动转换,那么,在输⼊时,如从选择屏幕上录⼊的数据是参照带有规则转换的Domain的数据元素创建的选择屏幕字段时,从界⾯录⼊到ABAP程序中时,会⾃动按照转换规则进⾏转换,如下⾯从界⾯上输⼊的是 PC (外部格式的单位),但录⼊到ABAP程序中时,⾃动转换为ST(内部格式的部位),但再次Write输出时,⼜将 ST转换为PC输出(从内部转换为外部格式):
15.1.3.通过转换规则输⼊输出函数⼿动转换
除了上⾯通过借助于参照带有转换规则的表字段进⾏⾃动转换外,实质上可以通过转换规则对应的输⼊输出函数进⾏⼿动转换,如VBAK-vbeln的转换规则:
:输⼊转换,前⾯补齐零
此函数将字符类型的变量转换成SAP数据库中内部格式数据,如定单号的类型为 Char 10,如果输⼊的vbeln为6位,则会在前⾯补4个零(注:该函数的转换规则为:如果含有其他⾮数字,则不会补零,只有全部是数字时才补,这可以通过VBELN查看到),Number类型的不需要,因为在ABAP程序中N类型不⾜时长度时默认就会在前⾯补零(如 POSNR),⽽且Number类型的默认值就是全为零,⽽C
类型不⾜时会以后⾯全补空格
CONVERSION_EXIT_ALPHA_OUTPUT:输出转换,去掉前导零
DATA: vbeln TYPE vbak-vbeln.
DATA: str TYPE string VALUE '600000'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING input= str
IMPORTING output= vbeln.
"⾃动输出转换,输出最初始数据,但程序内部已发⽣变化
WRITE: / vbeln."600000
15.2.数量⼩位数格式化
WRITE UNIT .
该语句根据Unit <u>来设置<f>的⼩数位数(即保留⼩数点多少位,或精确到⼩数点后多少位),<u>为<f>的单位。<u>必须要在中进⾏过配置,并且<u>的值(单位KEY值)就是T006-MSEHI字段值,⽽T006-DECAN字段值决定<f>显⽰的⼩数位数,如果<u>在表T006中没有找到,将会忽略该UNIT选项
该选项的使⽤限制如下:
<f>类型的
本⾝的⼩数位⽐<u>所配置的⼩数位少时,系统会忽略该选项
如果<f>本⾝的⼩数位⽐<u>所配置的要多时,并且;如果
从上⾯的限制条件来看,该格式化输出只针对的⼩数位超过了其单位设置的⼩数位,且超过的⼩数要全是零才会起作⽤(去掉多余的零),如果<f>的⼩数位短于<u>设置的⼩数位,也不会再补后输出
"必须是P类型
DATA: p1 TYPE p LENGTH 8 DECIMALS 2.
p1 = '1.10'.
"如果<f>本⾝的⼩数位⽐<u>所配置的⼩数位⼩时,系统会忽略该选项
WRITE:/ p1 UNIT 'D10'."1.10
DATA: p3 TYPE p LENGTH 8.
p3 = '1'.
WRITE:/ p3 UNIT 'D10'."1
DATA:p2 TYPE p LENGTH 8 DECIMALS 4.
p2 = '1.1000'.
"多余的⼩数位全部是零时,会被截断
WRITE:/ p2 UNIT 'D10'."1.100
p2 = '1.1001'.
"多余的⼩数部分不是零时,也会直接忽略该选项
WRITE:/ p2 UNIT 'D10'."1.1001
DATA: i_menge LIKE ekpo-menge VALUE '1.000'.
"注:UNIT选项后⾯⼀定要是内部单位ST,⽽不是外部单位PC,因为这⾥是WRITE输出,
"即内部转换外部,将数据库表存储的原数据格式化输出显⽰
WRITE: / i_menge UNIT 'ST'."1
WRITE: / i_menge."1.000
15.2.1.案例
问:通过11 我们可以看到ekpo中menge的数据元素是BSTMG,BSTMG的域是长度13⼩数位3位。在程序中我参照ekpo-menge定义的变量显⽰的时候后⾯都有3位⼩数,⽽我希望输出时与me23n⼀样,即去掉⼩数点后⾯多余的零,请问⼤侠们有没有⽐较好的办法。为什
么me23n中“PO数量”显⽰的时候没有多余的零,⽽他们的数据元素是⼀样的。
答:MENGE实际上是个存储度量衡值的字段,他的基本数据类型是QUAN,他的⼩数位数并不是你
看到的3,⽽是由这个字段关联的度量衡单位决定的,以MENGE为例,你可以在SE11的最右边⼀个Tab页,Currency/Quantity Fields⾥看到,他关联的单位是EKPO-MEINS
: i_menge LIKE ekpo-menge,
i_meins LIKE -,
i_meins2 TYPE c LENGTH 3. "没有参照表字段ekpo-meins,所以Write输出时不会⾃动输出转换
SELECT menge meins meins FROM ekpo INTO(i_menge,i_meins,i_meins2) WHERE ebeln = '4500012164'.
带单位的数量需要根据单位进⾏格式化输出,这样才与ME23N 中显⽰的数据⼀样
WRITE: / i_menge UNIT i_meins,i_meins,  i_menge,i_meins2.
ENDSELECT.
在ALV中显⽰时,如果是⾦额或数量时,需通过Fieldcat设置这样在显⽰时才会正确
也可直接使⽤Domain所配置的转换规则所对应的输⼊输出转换函数CONVERSION_EXIT_CUNIT_IN
PUT、
CONVERSION_EXIT_CUNIT_OUTPUT来⼿动对单位进⾏转换:
15.3.单位换算:UNIT_CONVERSION_SIMPLE
PARAMETERS: p_in TYPE p DECIMALS 3,
unit_in LIKE t006-mhi DEFAULT 'M',"⽶
unit_out LIKE t006-mhi DEFAULT 'MM',"毫⽶
round(1) TYPE c DEFAULT 'X'.
DATA: result TYPE p DECIMALS 3.
CALL FUNCTION ''
EXPORTING
input      = p_in
round_sign = round"舍⼊⽅式(+ up, - down, X comm, SPACE.)
unit_in    = unit_in
unit_out  = unit_out
IMPORTING
output    = result.
WRITE: 'Result: ',result.
15.4.货币格式化
WRITE <f> CURRENCY <c>.
输出⾦额<f>时,会根据该语句设置的货币代码<C>来决定其⼩数位置,如果货币代码<c>在表TCURX(CURRKEY)表中存在,则系统将根据TCURX-CURRDEC字段的值来设置<f>的⼩数点的位置,否则将<f>转换成具有2位⼩数的数字。这就意味着除⾮<f>本⾝就是类型
为P(.2)(即货币的最⼤单位与最⼩单位换算为100时,如CNY⼈民币、USD美元)的⾦额字段,否则
需要在TCURX表中配置所对应币种的⼩数位(因为不配置时会采⽤默认的2位)。
注意:这⾥的<f>⼀般是从数据库⾥读取出来的⾦额数据才需要这样格式化输出的,如果<f>本⾝存储的就是真实的⾦额,则不需要格式再输出,⽽是直接输出;另外,这⾥的格式化只是简单机械的根据TCURX-CURRDEC所配置的⼩数位置来设置⾦额的⼩数点位置(⽽并不是乘以或除以某个转换率),并与⾦额变量<f>类型本⾝的具有多少⼩数位有关:如果<f>的类型为P(6.5),值为<f> = 1.234时,且TCURX表⾥配置的⼩数位为2时,最后输出的是 1234.00 ,⽽不是12.34(如果是根据转换率来除,则结果会正确),因为在格式化前,会将⼩数末
的0(1.23400)也参与处理,并不理会<f>本⾝原来的⼩位数,⽽是将所有的数字位(抛开⼩数点,但包括末尾的0)看作是待格式会的数字字符串:
DATA: p(6) TYPE p DECIMALS 5.
p = '1.234'.
WRITE: p CURRENCY 'aa'."1,234.00
TCURX:货币⼩数位表
TCURC:货币代码表
TCURR:汇率表
SAP表⾥存储的并不是货币的最⼩单位,⼀般是以货币最⼤单位(也是常⽤计量单元)来存储,不过在存储之前会使⽤经过转换:⽐如存储的⾦额是 100,则存储到表之前会除以⼀个转换因⼦后再存⼊数据表中(该转换因⼦是通过函数获得的,如⽐CNY的转换因⼦
为1,JPY为100),所以如果要读取出来⾃已进⾏展⽰,则需要再次乘以这个因⼦才能得到真正的⾦额数。另外,数据库中存储的虽然不是最⼩单位,但取出来后都是放在P类型的变量中的,所以取出来在内存中统计是不会有精度丢失的(P类型相当于Java中的BigDecimal类类型)。
TCURX-CURRDEC中存储的⼩数位实质上是根据同种币种的最⼤单位与最⼩的= 10X来计算得到的,式中的X即TCURX-CURRDEC表字段中的⼩数位,如CNY中的最⼤单位元与最⼩单位分相差100倍,所以100 = 10X,X就为2,最后TCURX-CURRDEC存储的就是2(但如果值为2是可以不需要在TCURX表中配置的,所以查不到CNY的配置数据,因为不配置时默认值也是2);另外,JPY⽇元没有最⼩单位,所以最⼤单位与最⼩单位的换算率就是1(1 = 10X),所以X就为0,所以TCURX-CURRDEC存储的就是0。⽽转换因⼦计算式为:转换因⼦= ,(CNY⼈民币:X=100/102 =1,JPY⽇元:100/10X=100/100 =100),即转换因⼦ = 100/货币的最⼤单位与最⼩单位换算率,⾦额⼊库时需要除以这个转换因⼦,读取出来展⽰前需要乘以这个转换因⼦
数据库中⽤来存储⾦额的字段的类型都是P(.2),即带两位⼩数,因为转换因⼦最⼤也就是100(除以100后,即为⼩数点后2位),有的是零点⼏(在存⼊之前会将真实⾦额除以这个转换因⼦后再存⼊),所以存储类型为两位⼩数的数字类型即可。ABAP程序中⽤来存储从表中读取出来的内部⾦额的变量类型⼀定要具有两位类型的,否则在使⽤诸
气候的英语如CONVERT_TO_LOCAL_CURRENCY、CONVERT_TO_FOREIGN_CURRENCY转换函数或者是格式化输出时,都会有问题,所以
在ABAP程序中定义这些⽤来存储数据库表中所存内部⾦额变量时,最好参照相应词典类型。
15.4.1.从表中读取⽇元并正确的格式化输出
DATA: netpr LIKE vbap-netpr,"实际的类型为p(6.2)
waers LIKE vbap-waerk,
jpy_netpr TYPE i,
netpr1(6) TYPE p DECIMALS 3.
"通过SQL从数据库查询出来的是真实存储在表⾥的数据,没有经过其他转换,⽇元存到数据库中时缩⼩了100倍,所以要还原操作界⾯上输⼊的⽇元⾦额,则需要使⽤后⾯的格式化输出
SELECT SINGLE netpr waerk INTO (netpr,waers) FROM vbap WHERE waerk = 'JPY' AND vbeln = '0500001326'.
WRITE: waers,netpr."数据库中的值,被缩⼩了100倍
"第⼀种还原⽅式
WRITE: / 'Format:', netpr CURRENCY waers.
"第⼆种转换⽅式:也可以通过以下函数先获取JPY货币代码的转换因⼦,再直乘以这个因⼦也可
DATA: isoc_factor TYPE p DECIMALS 3.
CALL FUNCTION ''
EXPORTING
currency = waers
IMPORTING
factor  = isoc_factor.
jpy_netpr = netpr * isoc_factor."乘以100倍,因为在存⼊表中时缩⼩了100倍
WRITE: / 'Calc factor:', jpy_netpr.
"格式化输出实质上是与存储⾦额的变量本⾝的类型⼩数位有关:上⾯将从表中读出的⾦额(⼩数两位)赋值给变量netpr1(⼩数三位),格式化后会扩⼤10倍(因为多了⼀位⼩数位)。所以格式化正确输出的前提是要⽤来接收从表中读取的⾦额变量的类型要与数据表相应⾦额字段类型相同,否则格式化输出会出错
netpr1 = netpr.
WRITE: / netpr1, netpr1 CURRENCY waers."格式化的结果是错误的
15.4.2.SAP 货币转换因⼦
⼀般⽽⾔,币种的⼩数位为2,所以系统默认的位数也是2,但是有⼀些特殊币种如⽇元JPY,没有⼩
数位。只要⼩数位不等于2,需要在系统中特殊处理(通过转换因⼦进⾏转换,具体请参看后⾯SAP提供的函数 currency_converting_factor 实现过程)。在编程中
l List中,当输出CURR字段时,记得指定对应的货币:
如:WRITE: vbap-netwr CURRENCY vbap-waerk.
l Screen中,对于CURR字段,需要设置对应的货币字段:
l ALV中,需要对FIELD CATALOG进⾏设置
如:ls_cfieldname = 'WAERS'. "这⾥的WAERS是内表中的另⼀货币字段,⾥⾯存储了相应⾦额的货币代码
货币的是:fieldcat-cfieldname、fieldcat-ctabname(内表名,可以不设置)
顺便数量也是相似的⽅法来处理的:
数量的是:fieldcat-qfieldname、fieldcat-qtabname(内表名,可以不设置)
下⾯是SAP转换因⼦函数,在⾦额存储与在ALV展⽰时都会⾃动除以与乘以这个转换因⼦:
FUNCTION currency_converting_factor.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*      IMPORTING
*"            VALUE(CURRENCY) LIKE  TCURR-TCURR
*"      EXPORTING
*"            VALUE(FACTOR) TYPE  ISOC_FACTOR
*"      EXCEPTIONS
*"              TOO_MANY_DECIMALS
*"----------------------------------------------------------------------
DATA: cur_factor TYPE isoc_factor.
*- determine Decimal place in currency from  TCURX
CLEAR tcurx.
"⾸先根据币种到db表tcurx中读取相应的⼩数位数currdec
SELECT SINGLE * FROM tcurx WHERE currkey EQ currency.
"如果没有维护相应币别信息则默认currdec = 2
新西游记蜘蛛精
IF sy-subrc NE 0.
tcurx-currdec = 2.
ENDIF.
"如果currdec ⼤于了 5就报错
IF tcurx-currdec GT 5.
*- entry in tcurx with more than 5 decimals not allowed
RAISE too_many_decimals.
ENDIF.
*- compute converting factor respecting currency
"然后默认转换⽐率是100。如果表tcurx中的currdec = 0就默认转换⽐率为100
cur_factor = 100.
IF tcurx-currdec NE 0.
"在currdec不等于0的情况下循环currdec次,每次将转换⽐率除以10
DO tcurx-currdec TIMES.
"当表tcurx中没有找到相应数据时则默认currdec = 2,转换⽐率也就是100 / 10 / 10 = 1。其他
"的⽐如表tcurx中的currdec = 4,则转换⽐率应该为 100 / 10 / 10 / 10 / 10 = 0.01
cur_factor = cur_factor / 10.
ENDDO.
ENDIF.
IF cur_factor = 0.
*- factor 0 not allowed; check data definition of factor
*- entry in tcurx with more than 5 decimals not allowed季龙
RAISE too_many_decimals.
正能量句子ENDIF.
factor = cur_factor.
ENDFUNCTION.
简单的使⽤Function CURRENCY_CONVERTING_FACTOR,输⼊币种,就可以得到相应的转换⽐率了。我们在SE16中看到的货币⾦额基本上都经过了这个转换,如⽇元,都是除以100后存⼊数据库的。所以当我们从数据库中读取⽇元⾦额时也应该作相应的转换,乘以100。
1、如果某货币的⼩数位不是2位,则需要通过OY04设置其⼩数位数,即需在TCURX表中进⾏维护
2、系统中的数据表存放的⽇元JPY、俄卢布RUR等货币⽐前台输⼊的⾦额⼩100倍,因为它们没有⼩数位,所以转换因⼦为100,存⼊表之
秒杀团前SAP会先将⾦额除以这个因⼦后再存⼊
3、系统根据转换因⼦将原⾦额转换成含⼩位⼩数的⾦额后存储(据说根据ISO的什么标准),如⽇元为0位⼩数,转换因⼦为100,120⽇元
除以因⼦100后转换后变成1.20,缩⼩100倍。如为USDN为5位⼩数,其转换因⼦为100/10/10/10/10/10=0.001,12.01230除以0.001后则转换成12012.30,扩⼤1000倍。SAP在⾦额数据存储时会⾃动的转换,其实SAP是有external及internal的数据格式,可以调⽤以下函数实现相互转换。:转换成数据库中内部存储⾦额,BAPI_CURRENCY_CONV_TO_external:转换成外部实际⾦额
4、每次币别的汇率更改在正式⽣产系统中新创建⼀条记录,利⽤函数CONVERT_TO_LOCAL_CURRENCY⾃动会把当前最近的时间的汇
率作为转化的汇率,⽽不是直接在原纪录上更改
5、OB07、OB08,维护各币种之间的汇率。
6、碰到⽐较变态的货币,例如⽇元,它们是没有⼩数点的,系统内存储的和你看到的不同,有个BAPI可以使⽤:BAPI_CURRENCY_CONV_TO_INTERNAL
7、还有两个不同币种之间的转换FM:基本没有区别,功能都是⼀样的,只是转换的源与⽬标相反⽽
已:CONVERT_TO_FOREIGN_CURRENCY是将外币转换为本位币,⽽CONVERT_TO_LOCAL_CURRENCY是将本位币转换为其他外币
15.4.3.货币内外格式转换
"所有⾦额的在数据库⾥(内部格式)都是带两位的⼩数数字类型⽤来存储内部⾦额时,⽤来存储⾦额的变量类型⼀定要与数据库表⾥的类型⼀致,否则使⽤WRITE输出时会不准确
DATA: usd(7) TYPE p DECIMALS 2,
jpy(7) TYPE p DECIMALS 2,
jpy_e(12) TYPE p DECIMALS 4.
DATA: usd_k TYPE waers, jpy_k TYPE waers.
DATA: ret TYPE bapireturn.
"此处为实际⾦额,所以不宜直接格式化(只有对内部表中存储格式的⾦额格式化输出才有意义,否则是错误的输出),不过这⾥为实际的⾦额似乎也有点不对,因为⽇元真实⾦额是不会有⼩数的,所以变量jpy⽤来存储外部实际⾦额是不妥的,jpy应该为整数类型才恰当
jpy = '10000.01'.
usd_k = 'USD'.
jpy_k = 'JPY'.
"使⽤CONVERT_TO_LOCAL_CURRENCY、CONVERT_TO_FOREIGN_CURRENCY函数时,涉及到的⾦额输⼊输出参数都是采⽤内部⾦额,所以在使⽤这些函数时,如果是外部⾦额,应先将它们转换为内部⾦额后再传⼊
CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'"将⼀种货币兑换成另⼀种货币
EXPORTING
date            = sy-datum
foreign_amount  = jpy"该程序中的jpy本⾝为外部⾦额,但在这⾥会将
"它当作是内部⾦额,所以最后相当于外部⾦额1000001
foreign_currency = jpy_k
local_currency  = usd_k
IMPORTING
local_amount    = usd."转换出来的也是内部⾦额
*CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'
*  EXPORTING
*    date            = sy-datum
子宫疼是什么原因
*    foreign_amount  = '1.00'"内部⾦额,美元的外部⾦额也是1.00美元
红楼梦随笔
*    foreign_currency = 'USD'
*    local_currency  = 'JPY'
*  IMPORTING
*    local_amount    = usd."结果为内部⾦额:1.15,相当于外部⾦额为115⽇元
*CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'
鹦鹉为什么会说话
*  EXPORTING
*    date            = sy-datum
*    "如果内部⾦额没有⼩数,也要补上两位⼩数位0,否则实质⾦额不准确,这⾥正是
*    "因为末尾未补两位0,所以这⾥的⾦额实质上为0.01美元,⽽不是1美元
*    foreign_amount  = '1'"内部⾦额,相当于外部0.01美元
*    foreign_currency = 'USD'
*    local_currency  = 'JPY'
*  IMPORTING
*    local_amount    = usd. "结果为:0.01内部⾦额,实质相当于外部⾦额1⽇元
WRITE: jpy, jpy_k,usd, usd_k.
"由于jpy本⾝为实际⾦额,所以不能在这⾥格式输出;但usd为内部
"格式的⾦额,所以需要使⽤格式化输出(但usd本⾝就是带两位⼩数
"的内部⾦额,转换
WRITE:/ jpy CURRENCY jpy_k, jpy_k,
usd CURRENCY usd_k, usd_k.
ULINE.
jpy_e = jpy.
"将外部⾦额转换为内部存储⾦额,实质上过程是将外部⾦额除以转换因⼦即可得到
CALL FUNCTION 'BAPI_CURRENCY_CONV_TO_INTERNAL'
EXPORTING
currency            = jpy_k
amount_external      = jpy_e"外部⾦额
max_number_of_digits = 23"没什么作⽤,⼀般写23即可
IMPORTING
amount_internal      = jpy "转换后的内部存储⾦额
return              = ret.
CALL FUNCTION 'CONVERT_TO_LOCAL_CURRENCY'
EXPORTING
date            = sy-datum
foreign_amount  = jpy "源货币⾦额(内部格式)
foreign_currency = jpy_k"源货币类型

本文发布于:2023-07-26 18:48:09,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1097705.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:转换   输出   数据   类型   货币   数位
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图