Чтение таблицы 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_GETDETAILBAPI, он поддерживает 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);
Другие вопросы по тегам