仅向 CDS 中的数字字段添加前导零?
Add leading zeros only to numeric field in CDS?
在我的 AS ABAP 7.50 系统中,我有一个 table,其中 material 长度为 18,我需要通过 CDS 公开它,就好像 material 长度是 40 一样在 S/4。系统中的 material ID 可以是数字(带前导零)或字母数字。 material 字段需要转换为 MATNR40,如果 ID 是数字,则需要将前导零添加到 40 个字符。
首先,我尝试了`lpad。但当然,它还会将前导零添加到字母数字值中:
lpad( cast(matnr as matnr40), 40, '0' ) as material_long,
然后我添加了一个 case
但我无法使条件按预期工作。正如康斯坦丁在评论中确认的那样,我尝试在此处使用正则表达式是不可能的:
case when matnr like '%[^0-9.]%'
then lpad( cast(matnr as matnr40), 40, '0' )
else cast(matnr as matnr40)
end as material_long,
CDS 本身是否有针对此问题的解决方案?
来源table:
MATNR18
Description
000000000000000142
Numeric ID material
MATERIAL_2
Alphanumeric ID
预期结果:
MATNR40
Description
0000000000000000000000000000000000000142
Numeric ID material
MATERIAL_2
Alphanumeric ID
由于 CDS 语法中的功能有限,我看到的唯一方法是嵌套 10 个 REPLACE
函数来删除数字并将结果与初始字符串进行比较。如果它是初始的,那么你只有数字,所以你可以 LPAD
他们用零。如果不是 - 使用原始值。
这是我的代码:
@AbapCatalog.sqlViewName: 'Z_V_TEST'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Test'
define view Z_TEST as select from /bi0/mmaterial {
cast(
case replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(material,
'0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', '')
when ''
then lpad(material, 40, '0')
else material
end as abap.char(40)
) as MATERIAL_ALPHA,
material
}
结果是:
REPORT Z_TEST.
select *
from Z_V_TEST
where material in ('LAMP', '000000000000454445')
into table @data(lt_res)
.
cl_demo_output=>display( lt_res ).
MATERIAL_ALPHA | MATERIAL
-----------------------------------------+-------------------
0000000000000000000000000000000000454445 | 000000000000454445
LAMP | LAMP
这是 7.55 的做法,当 custom entities 被引入时:
创建自定义实体
@EndUserText.label: 'Material List'
@ObjectModel.query.implementedBy: 'ABAP:ZCL_MATERIAL_ZEROED'
@Search.searchable: false
define custom entity zcds_mat {
key matnr : abap.char( 40 );
maktx : abap.char( 40 );
}
为其创建实现class
CLASS ZCL_MATERIAL_ZEROED DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_rap_query_provider.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS ZCL_MATERIAL_ZEROED IMPLEMENTATION.
METHOD if_rap_query_provider~select.
DATA: it_result TYPE TABLE OF zcustomer_zero. "Internal table to be returned , easier to handle return if internal table is as same type of our data definition
DATA: lv_param TYPE string."Local variable to fetch and save parameter value
TRY.
TRY.
IF io_request->is_data_requested( ). "Fetching incoming data
io_request->get_paging( ).
SELECT matnr maktx FROM makt INTO TABLE @it_result.
LOOP AT it_result ASSIGNING FIELD-SYMBOL(<fldsym>).
<fldsym>-matnr = | { <fldsym>-matnr ALPHA = OUT } |.
ENDLOOP.
io_response->set_total_number_of_records( lines( it_result ) ). "setting the total number of records which will be sent
io_response->set_data( it_result ). "returning the data as internal table
ENDIF.
CATCH cx_a4c_rap_query_provider INTO DATA(lx_exc). "CX_A4C_RAP_QUERY_PROVIDER is now deprecated so use CX_RAP_QUERY_PROVIDER
ENDTRY.
CATCH cx_rfc_dest_provider_error INTO DATA(lx_dest).
ENDTRY.
ENDMETHOD.
ENDCLASS.
这里我们通过 string templates
添加前导零
您不能直接使用自定义实体,但您可以在 OData service 中使用它,以防您有此意图。
在我的 AS ABAP 7.50 系统中,我有一个 table,其中 material 长度为 18,我需要通过 CDS 公开它,就好像 material 长度是 40 一样在 S/4。系统中的 material ID 可以是数字(带前导零)或字母数字。 material 字段需要转换为 MATNR40,如果 ID 是数字,则需要将前导零添加到 40 个字符。
首先,我尝试了`lpad。但当然,它还会将前导零添加到字母数字值中:
lpad( cast(matnr as matnr40), 40, '0' ) as material_long,
然后我添加了一个 case
但我无法使条件按预期工作。正如康斯坦丁在评论中确认的那样,我尝试在此处使用正则表达式是不可能的:
case when matnr like '%[^0-9.]%'
then lpad( cast(matnr as matnr40), 40, '0' )
else cast(matnr as matnr40)
end as material_long,
CDS 本身是否有针对此问题的解决方案?
来源table:
MATNR18 | Description |
---|---|
000000000000000142 | Numeric ID material |
MATERIAL_2 | Alphanumeric ID |
预期结果:
MATNR40 | Description |
---|---|
0000000000000000000000000000000000000142 | Numeric ID material |
MATERIAL_2 | Alphanumeric ID |
由于 CDS 语法中的功能有限,我看到的唯一方法是嵌套 10 个 REPLACE
函数来删除数字并将结果与初始字符串进行比较。如果它是初始的,那么你只有数字,所以你可以 LPAD
他们用零。如果不是 - 使用原始值。
这是我的代码:
@AbapCatalog.sqlViewName: 'Z_V_TEST'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Test'
define view Z_TEST as select from /bi0/mmaterial {
cast(
case replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(material,
'0', ''), '1', ''), '2', ''), '3', ''), '4', ''), '5', ''), '6', ''), '7', ''), '8', ''), '9', '')
when ''
then lpad(material, 40, '0')
else material
end as abap.char(40)
) as MATERIAL_ALPHA,
material
}
结果是:
REPORT Z_TEST.
select *
from Z_V_TEST
where material in ('LAMP', '000000000000454445')
into table @data(lt_res)
.
cl_demo_output=>display( lt_res ).
MATERIAL_ALPHA | MATERIAL
-----------------------------------------+-------------------
0000000000000000000000000000000000454445 | 000000000000454445
LAMP | LAMP
这是 7.55 的做法,当 custom entities 被引入时:
创建自定义实体
@EndUserText.label: 'Material List' @ObjectModel.query.implementedBy: 'ABAP:ZCL_MATERIAL_ZEROED' @Search.searchable: false define custom entity zcds_mat { key matnr : abap.char( 40 ); maktx : abap.char( 40 ); }
为其创建实现class
CLASS ZCL_MATERIAL_ZEROED DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_rap_query_provider. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS ZCL_MATERIAL_ZEROED IMPLEMENTATION. METHOD if_rap_query_provider~select. DATA: it_result TYPE TABLE OF zcustomer_zero. "Internal table to be returned , easier to handle return if internal table is as same type of our data definition DATA: lv_param TYPE string."Local variable to fetch and save parameter value TRY. TRY. IF io_request->is_data_requested( ). "Fetching incoming data io_request->get_paging( ). SELECT matnr maktx FROM makt INTO TABLE @it_result. LOOP AT it_result ASSIGNING FIELD-SYMBOL(<fldsym>). <fldsym>-matnr = | { <fldsym>-matnr ALPHA = OUT } |. ENDLOOP. io_response->set_total_number_of_records( lines( it_result ) ). "setting the total number of records which will be sent io_response->set_data( it_result ). "returning the data as internal table ENDIF. CATCH cx_a4c_rap_query_provider INTO DATA(lx_exc). "CX_A4C_RAP_QUERY_PROVIDER is now deprecated so use CX_RAP_QUERY_PROVIDER ENDTRY. CATCH cx_rfc_dest_provider_error INTO DATA(lx_dest). ENDTRY. ENDMETHOD. ENDCLASS.
这里我们通过 string templates
添加前导零您不能直接使用自定义实体,但您可以在 OData service 中使用它,以防您有此意图。