使用 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 做不到的事情:小数点的一个额外字节。
如果您只是寻找修补小数问题,则无需经历所有考验。
我正在尝试使用 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 做不到的事情:小数点的一个额外字节。
如果您只是寻找修补小数问题,则无需经历所有考验。