[SAPABAP开发技术总结]数据输⼊输出转换、⼩数位单位货币
格式化
15.数据格式化、转换
15.1.数据输⼊输出转换
15.1.1.输出时⾃动转换
如果某个变量参照的数据元素所对应的Domain具有转换规则,那么在输出时(如Write输出、ALV展⽰、⽂本框中显⽰),最后显⽰的结果会⾃动发⽣转换,如参照ekpo-meins 表字段的变量赋值时就会发⽣转换,因为ekpo-meins 所对应的元素Doamin设置了转换规则:
所以,在显⽰输出这样的数据时要注意,如果要显⽰原始数据,则不能参照该表字段来定义变量,⽽是⾃⼰定义。
DATA: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的转换规则:
CONVERSION_EXIT_ALPHA_INPUT:输⼊转换,前⾯补齐零
此函数将字符类型的变量转换成SAP数据库中内部格式数据,如定单号vbeln的类型为 Char 10,如果输⼊的vbeln为6位,则会在前⾯补4个零(注:该函数的转换规则为:如果含有其他⾮数字,则不会补零,只有全部是数字时才补,这可以通过VBELN查看到),Number类型的不需要,因为在ABAP程序中N类型不⾜时长度时默认就会在前⾯补零(如 POSNR),⽽且Number类型的默认值就是全为零,
⽽C类型不⾜时会以后⾯全补空格
CONVERSION_EXIT_ALPHA_OUTPUT:输出转换,去掉前导零
DATA: str TYPE string VALUE '600000'.
CALL FUNCTION 'CONVERSION_EXIT_ALPHA_INPUT'
EXPORTING input= str
IMPORTING output= vbeln.
"⾃动输出转换,输出最初始数据,但程序内部已发⽣变化
WRITE: / vbeln."600000
15.2.数量⼩位数格式化
WRITE <f> UNIT <u>.
该语句根据Unit <u>来设置<f>的⼩数位数(即保留⼩数点多少位,或精确到⼩数点后多少位),<u>
为<f>的单位。<u>必须要在T006中进⾏过配置,并且<u>的值(单位KEY值)就是T006-MSEHI字段值,⽽T006-DECAN字段值决定<f>显⽰的⼩数位数,如果<u>在表T006中没有到,将会忽略该UNIT选项
该选项的使⽤限制如下:
<f>必须是P类型的
如果<f>本⾝的⼩数位⽐<u>所配置的⼩数位少时,系统会忽略该选项
如果<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
bigdecimal格式化两位小数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.案例
问:通过se11 我们可以看到ekpo中menge的数据元素是BSTMG,BSTMG的域是长度13⼩数位3位。在程序中我参照ekpo-menge定义的变量显⽰的时候后⾯都有3位⼩数,⽽我希望输出时与me23n⼀样,即去掉⼩数点后⾯多余的零,请问⼤侠们有没有⽐较好的办法。为什
么me23n中“PO数量”显⽰的时候没有多余的零,⽽他们的数据元素是⼀样的。
答:MENGE实际上是个存储度量衡值的字段,他的基本数据类型是QUAN,他的⼩数位数并不是你看到的3,⽽是由这个字段关联的度量衡单位决定的,以MENGE为例,你可以在SE11的最右边⼀个Tab页,Currency/Quantity Fields⾥看到,他关联的单位是EKPO-MEINS
i_meins LIKE ekpo-meins,
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设置cfieldname 、ctabname ;qfieldname、qtabname这样在显⽰时才会正确
也可直接使⽤Domain所配置的转换规则所对应的输⼊输出转换函数CONVERSION_EXIT_CUNIT_INPUT、
CONVERSION_EXIT_CUNIT_OUTPUT来⼿动对单位进⾏转换:
15.3.单位换算:UNIT_CONVERSION_SIMPLE
PARAMETERS: p_in TYPE p DECIMALS 3,
unit_in LIKE t006-msehi DEFAULT 'M',"⽶
unit_out LIKE t006-msehi DEFAULT 'MM',"毫⽶
round(1) TYPE c DEFAULT 'X'.
DATA: result TYPE p DECIMALS 3.
CALL FUNCTION 'UNIT_CONVERSION_SIMPLE'
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,则存储到表之前会除以⼀个转换因⼦后再存⼊数据表中(该转换因⼦是通过CURRENCY_CONVERTING_FACTOR函数获得的,如⽐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。⽽转换因⼦计
算式为:转换因⼦ = 100/10X,(CNY⼈民币:100/10X=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 'CURRENCY_CONVERTING_FACTOR'
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 实现过程)。在编程中
List中,当输出CURR字段时,记得指定对应的货币:
如:WRITE: vbap-netwr CURRENCY vbap-waerk.
Screen中,对于CURR字段,需要设置对应的货币字段:
ALV中,需要对FIELD CATALOG进⾏设置
如:ls_cfieldname = 'WAERS'. "这⾥的WAERS是内表中的另⼀货币字段,⾥⾯存储了相应⾦额的货币代码货币的是:fieldcat-cfieldname、fieldcat-ctabname(内表名,可以不设置)
顺便数量也是相似的⽅法来处理的:
数量的是:fieldcat-qfieldname、fieldcat-qtabname(内表名,可以不设置)
下⾯是SAP转换因⼦函数,在⾦额存储与在ALV展⽰时都会⾃动除以与乘以这个转换因⼦:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论