Чтение таблицы TCURR с RFC_READ_TABLE обрезает значение скорости
Я пытаюсь прочитать данные из SAP ECC с помощью Microsoft .NET. Для этого я использую SAP Connector для 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);
Значения следующие:
Как получить полную стоимость без усечения?
4 ответа
Вы просто столкнулись с худшим ограничением RFC_READ_TABLE
.
Его ошибка состоит в том, чтобы возвращать значения полей на основе внутренней длины и усекать остальные, а не использовать длину вывода. TCURR-UKURS
представляет собой десятичное упакованное поле длины в формате BCD 9,5
(9 байтов = 17 цифр, включая 5 цифр после десятичной точки) и длина вывода 12. К сожалению, RFC_READ_TABLE
выводит результат в виде 9 символов, поэтому значение 105.48000-
занимает 10 символов слишком долго, поэтому логика ABAP по умолчанию - установить *
символ переполнения на крайнем левом символе (*5.48000-
).
Либо вы создаете другой функциональный модуль с поддержкой RFC на стороне SAP/ABAP, либо вы получаете прямой доступ к базе данных SAP (классическая СУБД, подключенная к серверу SAP).
Просто дополнение к Сандре прекрасное объяснение по этому поводу. Да, единственным решением здесь было бы написать собственный модуль для получения удаленных записей.
Если вы не хотите переписывать его с нуля, самым простым решением было бы скопировать RFC_READ_TABLE
в модуль Z и измените строку 137
FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-LENG.
к
FIELDS_INT-LENGTH_DST = TABLE_STRUCTURE-OUTPUTLEN.
Это решает проблему.
ОБНОВЛЕНИЕ: попробуйте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.
Используйте BBP_RFC_READ_TABLE. Это все еще не лучший вариант, но он делает одну вещь правильной, чего не сделал RFC_READ_TABLE: один дополнительный байт для десятичного знака.
Нет необходимости проходить через все испытания, если вы ищете исправление только проблемы с десятичным числом.
Это образец кода, который используется с соединителем SAP для.NET, пусть он будет полезен тем, кто ищет то же самое. Спасибо всем, кто помогал.
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);