使用 RFC_READ_TABLE 读取 TCURR table 会截断速率值

Reading TCURR table with RFC_READ_TABLE truncates the rate value

我正在尝试使用 Microsoft .NET 从 SAP ECC 读取数据。为此,我使用 SAP Connector for Microsoft .NET 3.0 下面是检索数据的代码,我也得到了结果。但是,我发现如果超过7个字符,汇率值就会有一个*。

        ECCDestinationConfig cfg = new ECCDestinationConfig();

        RfcDestinationManager.RegisterDestinationConfiguration(cfg);

        RfcDestination dest = RfcDestinationManager.GetDestination("mySAPdestination");

        RfcRepository repo = dest.Repository;


        IRfcFunction testfn = repo.CreateFunction("RFC_READ_TABLE");
        testfn.SetValue("QUERY_TABLE", "TCURR");

        // fields will be separated by semicolon
        testfn.SetValue("DELIMITER", ";");

        // Parameter table FIELDS contains the columns you want to receive
        // here we query 3 fields, FCURR, TCURR and UKURS
        IRfcTable fieldsTable = testfn.GetTable("FIELDS");
        fieldsTable.Append();
        fieldsTable.SetValue("FIELDNAME", "FCURR");
        fieldsTable.Append();
        fieldsTable.SetValue("FIELDNAME", "TCURR");
        fieldsTable.Append();
        fieldsTable.SetValue("FIELDNAME", "UKURS");
        fieldsTable.Append();
        fieldsTable.SetValue("FIELDNAME", "GDATU");

        // the table OPTIONS contains the WHERE condition(s) of your query           
        // several conditions have to be concatenated in ABAP syntax, for instance with AND or OR
        IRfcTable optsTable = testfn.GetTable("OPTIONS");

        var dateVal = 99999999 - 20190701;
        optsTable.Append();
        optsTable.SetValue("TEXT", "gdatu = '" + dateVal + "' and KURST = 'EURX'");

        testfn.Invoke(dest);

数值如下:

如何在不截断的情况下获取完整值?

你刚刚运行进入了RFC_READ_TABLE的最差限制。

它的错误是 return 字段值基于内部长度并截断其余部分,而不是使用输出长度。 TCURR-UKURS是一个BCD十进制压缩字段,长度为9,5(9字节=17位,包括小数点后5位),输出长度为12,可惜RFC_READ_TABLE输出结果在 9 个字符上,所以 105.48000- 的值需要 10 个字符太长,所以 ABAP 默认逻辑是在最左边的字符 (*5.48000-) 上设置 * 溢出字符。

要么在 SAP/ABAP 端创建另一个支持 RFC 的功能模块,要么直接访问 SAP 数据库(连接到 SAP 服务器的经典 RDBMS)。

只是 Sandra 对这个问题的完美解释的补充。是的,这里唯一的解决方案是编写一个自定义模块来获取远程记录。

如果您不想从头开始重写它,最简单的解决方案是将 RFC_READ_TABLE 复制到 Z 模块并更改第 137 行

FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-LENG.

FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-OUTPUTLEN.

这解决了问题。

UPDATE:尝试 BAPI_EXCHANGERATE_GETDETAIL BAPI,它支持 RFC 并正确读取速率。界面是不言自明的,唯一的区别是日期应该是原生格式,而不是倒置:

CALL FUNCTION 'BAPI_EXCHANGERATE_GETDETAIL'
  EXPORTING
    rate_type  = 'EURO'
    from_curr  = 'USD'
    to_currncy = 'EUR'
    date       = '20190101'
  IMPORTING
    exch_rate  = rates
    return     = return.

这是与适用于 .NET 的 SAP 连接器一起使用的示例代码,希望它对寻找相同内容的人有所帮助。感谢所有帮助过的人。

        var RateForDate = 20190701;

        ECCDestinationConfig cfg = new ECCDestinationConfig();
        RfcDestinationManager.RegisterDestinationConfiguration(cfg);
        RfcDestination dest = RfcDestinationManager.GetDestination("mySAPdestination");
        RfcRepository repo = dest.Repository;


        IRfcFunction sapFunction = repo.CreateFunction("RFC_READ_TABLE");
        sapFunction.SetValue("QUERY_TABLE", "TCURR");
        // fields will be separated by semicolon
        sapFunction.SetValue("DELIMITER", ";");

        // Parameter table FIELDS contains the columns you want to receive
        // here we query 3 fields, FCURR, TCURR and UKURS
        IRfcTable fieldsTable = sapFunction.GetTable("FIELDS");
        fieldsTable.Append();
        fieldsTable.SetValue("FIELDNAME", "FCURR");
        //fieldsTable.Append();
        //fieldsTable.SetValue("FIELDNAME", "TCURR");
        //fieldsTable.Append();
        //fieldsTable.SetValue("FIELDNAME", "UKURS");


        // the table OPTIONS contains the WHERE condition(s) of your query
        // here a single condition, KUNNR is to be 0012345600
        // several conditions have to be concatenated in ABAP syntax, for instance with AND or OR
        IRfcTable optsTable = sapFunction.GetTable("OPTIONS");

        var dateVal = 99999999 - RateForDate;
        optsTable.Append();
        optsTable.SetValue("TEXT", "gdatu = '" + dateVal + "' and KURST = 'EURX'");

        sapFunction.Invoke(dest);

        var companyCodeList = sapFunction.GetTable("DATA");
        DataTable Currencies = companyCodeList.ToDataTable("DATA");

        //Add additional column for rates
        Currencies.Columns.Add("Rate", typeof(double));

        //------------------
        sapFunction = repo.CreateFunction("BAPI_EXCHANGERATE_GETDETAIL");
        //rate type of your system
        sapFunction.SetValue("rate_type", "EURX");
        sapFunction.SetValue("date", RateForDate.ToString());
        //Main currency of your system
        sapFunction.SetValue("to_currncy", "EUR");

        foreach (DataRow item in Currencies.Rows)
        {
            sapFunction.SetValue("from_curr", item[0].ToString());
            sapFunction.Invoke(dest);
            IRfcStructure impStruct = sapFunction.GetStructure("EXCH_RATE");
            item["Rate"] = impStruct.GetDouble("EXCH_RATE_V");
        }


        dtCompanies.DataContext = Currencies;     
        RfcDestinationManager.UnregisterDestinationConfiguration(cfg);

使用BBP_RFC_READ_TABLE。它仍然不是最好的,但它做了一件 RFC_READ_TABLE 做不到的事情:小数点的一个额外字节。

如果您只是寻找修补小数问题,则无需经历所有考验。