matinal:SAP ABAP 如何在程序里实现动态计算公式

文章介绍了如何使用编程语言对输入的计算公式进行拆分处理,包括按运算符拆分,并执行公式计算,确保公式合法性。

1.计算公式拆分出计算变量

*&---------------------------------------------------------------------*
*& Form FRM_SPLIT_FORMEL
*&---------------------------------------------------------------------*
*& text 按照运算符拆分公式
*&---------------------------------------------------------------------*
*&      --> LT_FORMEL_RESULT[]
*&      --> LV_FORMEL
*&---------------------------------------------------------------------*
FORM frm_split_formel  TABLES   et_formel STRUCTURE t418f
                        USING   iv_formel.
  DATA:BEGIN OF lt_formel OCCURS 0,
         formel TYPE char1024,
       END OF lt_formel.
  DATA: lv_formel  TYPE string.

  CLEAR: lv_formel.
  lv_formel = iv_formel.
  "按照+分割
  SPLIT lv_formel AT '+' INTO TABLE lt_formel.
  CONCATENATE LINES OF lt_formel INTO lv_formel SEPARATED BY space.
  "按照-分割
  SPLIT lv_formel AT '-' INTO TABLE lt_formel.
  CONCATENATE LINES OF lt_formel INTO lv_formel SEPARATED BY space.
  "按照*分割
  SPLIT lv_formel AT '*' INTO TABLE lt_formel.
  CONCATENATE LINES OF lt_formel INTO lv_formel SEPARATED BY space.
  "按照/分割
  SPLIT lv_formel AT '/' INTO TABLE lt_formel.
  CONCATENATE LINES OF lt_formel INTO lv_formel SEPARATED BY space.
  "按照(分割
  SPLIT lv_formel AT '(' INTO TABLE lt_formel.
  CONCATENATE LINES OF lt_formel INTO lv_formel SEPARATED BY space.
  "按照)分割
  SPLIT lv_formel AT ')' INTO TABLE lt_formel.
  CONCATENATE LINES OF lt_formel INTO lv_formel SEPARATED BY space.
  "按照空格分割
  SPLIT lv_formel AT space INTO TABLE lt_formel.

  "赋值
  LOOP AT lt_formel INTO DATA(ls_formel).
    CONDENSE ls_formel-formel NO-GAPS.
    IF ls_formel-formel IS NOT INITIAL.
      CLEAR: et_formel.
      et_formel-formel = ls_formel-formel.
      APPEND et_formel.
    ENDIF.
  ENDLOOP.

ENDFORM.

2.公式计算

*&---------------------------------------------------------------------*
*& Form FRM_EVAL_FORMULA
*&---------------------------------------------------------------------*
*& text 公式计算
*&---------------------------------------------------------------------*
*&      --> LV_FORMEL_CHAR
*&      <-- CV_BETRG
*&---------------------------------------------------------------------*
FORM frm_eval_formula  USING    iv_formel_char
                       CHANGING cv_betrg.
  DATA: lv_formel_char      TYPE string,
        lv_retcode          TYPE sy-subrc,
        lv_funcname(30)     TYPE c,
        lv_message(70)      TYPE c,
        lv_pos              TYPE i,
        lv_eval_formula     TYPE cha_class_data-sollwert,
        lv_eval_formula_out TYPE cha_class_view-sollwert.

  TRY.
*  check formula
      CLEAR: lv_formel_char.
      lv_formel_char = iv_formel_char.
   
     "校验计算公式是否合法
      CLEAR: lv_retcode,lv_funcname,lv_message,lv_pos.
      CALL FUNCTION 'CHECK_FORMULA'
        EXPORTING
          formula           = lv_formel_char
          program           = sy-repid
        IMPORTING
          subrc             = lv_retcode
          funcname          = lv_funcname
          message           = lv_message
          pos               = lv_pos
        EXCEPTIONS
          error_in_formula  = 1
          missing_parameter = 2
          OTHERS            = 3.
      IF sy-subrc EQ 0 AND lv_retcode EQ 0."formula is ok
* work out formula
        CLEAR: lv_eval_formula.
        CALL FUNCTION 'EVAL_FORMULA'
          EXPORTING
            formula                 = lv_formel_char
            program                 = sy-repid
          IMPORTING
            value                   = lv_eval_formula
          EXCEPTIONS
            division_by_zero        = 1
            exp_error               = 2
            formula_table_not_valid = 3
            invalid_expression      = 4
            invalid_value           = 5
            log_error               = 6
            parameter_error         = 7
            sqrt_error              = 8
            units_not_valid         = 9
            missing_parameter       = 10
            OTHERS                  = 11.
        "将科学计数法数据转为正常数据
        CLEAR: lv_eval_formula_out.
        CALL FUNCTION 'QSS0_FLTP_TO_CHAR_CONVERSION'
          EXPORTING
            i_number_of_digits       = 2
            i_fltp_value             = lv_eval_formula
            i_value_not_initial_flag = 'X'
            i_screen_fieldlength     = 16
          IMPORTING
            e_char_field             = lv_eval_formula_out.
        IF lv_eval_formula_out IS NOT INITIAL.
          REPLACE ALL OCCURRENCES OF ',' IN lv_eval_formula_out WITH space.
          CONDENSE lv_eval_formula_out NO-GAPS.
          cv_betrg = lv_eval_formula_out.
        ENDIF.
      ENDIF.
    CATCH cx_root INTO DATA(lo_ret).
  ENDTRY.
ENDFORM.

<think> 我们正在解决SAP RAP List Report中Filter字段的检索帮助出现重复值的问题。检索帮助(Value Help)在Fiori Elements List Report中通常通过CDS视图的注解来定义。重复值可能源于以下几个原因: 1. **数据源本身存在重复**:如果检索帮助直接关联的CDS视图或实体返回了重复的值,那么下拉列表中自然会显示重复项。 2. **注解配置不当**:在定义`@Consumption.valueHelpDefinition`或`@UI.selectionField`时,如果没有正确设置去重属性,可能导致重复。 3. **多个值帮助叠加**:可能为同一个字段配置了多个值帮助,且这些值帮助返回的结果合并时未去重。 4. **模型设计问题**:在自定义实体的计算字段中,如果逻辑未去重,也会导致重复。 ### 解决方法 #### 方法1:确保数据源去重 检查为检索帮助提供数据源的CDS视图或自定义实体。在定义该数据源时,使用`DISTINCT`关键字或分组确保返回唯一值。 例如,在定义值帮助的CDS视图中: ```sql @AbapCatalog.sqlViewName: 'ZVDH_MATERIAL' @AbapCatalog.compiler.compareFilter: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'Material Value Help' define view ZVDH_MATERIAL as select distinct from matinal { key matnr as Material, maktx as MaterialText } ``` #### 方法2:在注解中指定去重 在字段的`@UI.selectionField`或`@Consumption.valueHelpDefinition`注解中,确保指定了正确的去重属性。 例如,在CDS视图的字段上: ```abap @UI.selectionField: [ { position: 10, mandatory: true, valueHelp: '_MATERIAL' // 指向一个去重的值帮助实体 } ] Matnr; ``` 然后,在值帮助实体定义中,确保数据是唯一的。 #### 方法3:使用自定义值帮助 如果标准值帮助无法满足去重需求,可以创建自定义值帮助。在自定义值帮助的实现中,可以控制返回的数据,包括去重。 在ABAP RAP中,可以通过实现一个自定义的`DETERMINE_VALUE_HELP`方法来实现。具体步骤: 1. **在行为定义中声明值帮助方法**: ```abap define behavior for ZCE_MyEntity { value help Material for _Material on action valueHelp; } ``` 2. **在行为实现类中编写方法**: ```abap CLASS lhc_entity IMPLEMENTATION. METHOD valueHelp. " 在这里编写获取值帮助并去重的逻辑 DATA: lt_values TYPE TABLE OF zsh_material. SELECT DISTINCT matnr, maktx INTO TABLE @lt_values FROM matinal. " 将lt_values填充到返回参数中 ENDMETHOD. ENDCLASS. ``` #### 方法4:检查是否多个值帮助叠加 如果为同一个字段配置了多个值帮助,需要检查并移除多余的配置。通常,一个字段应该只关联一个值帮助。 ### 总结步骤 1. **检查数据源**:确保提供值帮助的CDS视图或自定义实体返回的数据是唯一的(使用`DISTINCT`或`GROUP BY`)。 2. **检查注解配置**:确保在`@UI.selectionField`中正确引用了值帮助实体,并且该实体已去重。 3. **考虑自定义值帮助**:如果上述方法无效,实现自定义值帮助并在其中控制返回唯一值。 4. **调试**:使用SAP Gateway Client或Fiori应用测试值帮助,查看返回的数据,确认重复值的来源。 ### 额外提示 在Fiori Elements应用中,还可以通过前端扩展来调整值帮助,但建议优先在后端解决数据重复问题,确保数据一致性。 ### 相关问题 1. 在SAP RAP中如何为List Report的过滤器字段添加自定义值帮助? 2. 如何调试SAP Fiori Elements应用中的值帮助问题? 3. 在CDS视图中使用`DISTINCT`关键字有哪些性能影响?如何优化? 4. 如何为SAP RAP自定义实体中的字段添加值帮助? 通过以上方法,应该能够解决List Report过滤器字段检索帮助中的重复值问题。 [^1]: [SAP Help Portal: Value Help in Fiori Elements](https://help.sap.com) [^2]: [SAP Community: How to avoid duplicate values in Value Help](https://community.sap.com) </think> ### SAP RAP List Report 过滤器检索帮助重复值问题解决方案 在 SAP RAP List Report 中,过滤器字段检索帮助出现重复值通常由以下原因导致: --- ### 根本原因分析 1. **数据源重复** - CDS 视图或底层数据库表本身包含重复记录 - 未使用 `DISTINCT` 或 `GROUP BY` 去重处理 ```sql -- 问题示例:未去重的CDS视图 define view ZMY_VIEW { select from matnr -- 可能返回重复物料号 } ``` 2. **注解配置错误** - `@UI.selectionField` 注解未正确关联值帮助实体 - 值帮助实体未配置去重逻辑([引用3]) 3. **自定义逻辑缺陷** - 自定义值帮助的 ABAP 实现类未处理重复值 - 多个值帮助源合并时未去重 --- ### 解决方案步骤 #### 方案1:CDS 源头去重(推荐) ```sql -- 修正后的CDS视图 (ABAP CDS) @AbapCatalog.sqlViewName: 'ZMAT_DISTINCT' define view ZMATERIAL_DISTINCT as select distinct _mat.matnr as Material, _text.maktx as Description from mara as _mat left join makt as _text on _mat.matnr = _text.matnr and _text.spras = $session.system_language ``` #### 方案2:值帮助注解显式去重 ```abap // 在目标CDS视图中配置值帮助注解 @UI: { selectionField: [ { position: 10, valueHelp: 'ZMATERIAL_DISTINCT', // 指向去重视图 valueListParameter: 'Material' // 指定关联字段 } ] } entity ZMY_ENTITY { key Material : matnr; ... } ``` #### 方案3:自定义值帮助类实现去重 ```abap CLASS zcl_my_value_help IMPLEMENTATION. METHOD get_value_help_items. SELECT DISTINCT matnr, maktx INTO TABLE @DATA(lt_items) FROM makt WHERE spras = @sy-langu. " 填充结果集 result = VALUE #( FOR ls IN lt_items ( key = ls-matnr, description = ls-maktx ) ). ENDMETHOD. ENDCLASS. ``` #### 方案4:前端过滤器配置调整([引用1]) ```json // 在manifest.json中配置过滤器去重 "filterFields": { "Material": { "valueHelp": "ZMATERIAL_DISTINCT", "distinctValues": true, // 显式启用去重 "displayMode": "DescriptionValue" } } ``` --- ### 验证与调试技巧 1. **检查值帮助实体数据** 使用事务 `SE16N` 直接查询值帮助实体 `ZMATERIAL_DISTINCT`,确认数据是否去重 2. **注解一致性检查** 使用 ADT 的 **Annotation Propagation** 功能确保注解正确传播到 OData 元数据 3. **Fiori 调试工具** - 浏览器开发者工具查看 `/sap/opu/odata4/sap/zmy_srv/$metadata` 响应 - 检查 `ValueList` 注解指向的实体: ```xml <Annotation Term="UI.ValueList"> <Record><PropertyValue Property="CollectionPath" String="ZMATERIAL_DISTINCT"/></Record> </Annotation> ``` 4. **清除缓存** 删除浏览器缓存并重启 `/IWFND/MAINT_SERVICE` 中的 OData 服务 --- ### 最佳实践 1. **始终在值帮助源头去重** 优先使用 CDS 视图的 `DISTINCT` 而非前端处理([引用3]) 2. **统一值帮助复用** 为常用字段(如物料、公司代码)创建共享去重视图 3. **性能优化** 对大数据量表添加 `@EndUserText.label: 'MANDT'` 客户端过滤条件 4. **测试规范** 使用 `CL_OSQL_REPLACE` 工具模拟测试数据重复场景 > **关键原则**:值帮助数据管理责任链 > ```mermaid > graph LR > A[数据库表] --> B(CDS值帮助视图) > B --> C(注解关联) > C --> D(UI渲染) > style B stroke:#ff9900,stroke-width:3px -- 去重核心节点 > ``` --- ### 配置效果验证 成功修复后,过滤器下拉列表将显示: ``` | Material | Description | |----------|------------------| | MAT001 | Raw Material A | | MAT002 | Component B | | MAT003 | Packaging C | ``` 替代原先可能出现的重复条目。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值