SAP Connector для Microsoft .Net v3 — отсутствует класс SAPIDocSender

Я использовал SAP Connector для Microsoft .Net v2 для успешной отправки уже отформатированных IDOCS в SAP. Сегодня я обновился до последней версии коннектора. К сожалению, этого SAPIDocSender больше нет. Как мне теперь отправить эти IDOCS в SAP?

Спасибо за вашу помощь!

РЕДАКТИРОВАТЬ: Спасибо! К сожалению, я не хочу создавать IDOC, как это описано в другой теме.

В v2 была возможность отправить всю строку IDOC, включая все сегменты:

private static void SendIdoc()
{     
    SAP.Connector.RfcTID myTid = SAP.Connector.RfcTID.NewTID();  
    string connectionString = "ASHOST=xxxx SYSNR=xx CLIENT=xxx USER=xxx PASSWD=xxx LANG=xx";
    string upperString = connectionString.ToUpper();
    SAP.Connector.SAPIDocSender sapiDocSender = new SAPIDocSender(upperString);
    sapiDocSender.SubmitIDoc(@"C:\Users\xxx\Documents\testidoc.txt", myTid);
    sapiDocSender.ConfirmTID(myTid);
}

person Fabio Lucia    schedule 16.02.2016    source источник
comment
Возможный дубликат Как создать и отправлять Idocs в SAP с помощью SAP .Net Connector 3   -  person Dirk Trilsbeek    schedule 16.02.2016
comment
См. редактирование выше. Спасибо еще раз!   -  person Fabio Lucia    schedule 16.02.2016
comment
это не так уж и сложно. У вас уже есть все данные в файле как для контрольной записи (первая строка вашего файла), так и для записей данных. Это все фиксированная длина, и вам нужно только вручную заполнить первые несколько полей для записей данных и полей для контрольной записи. На мой взгляд, в библиотеке NCo больше нет специального помощника по idoc.   -  person Dirk Trilsbeek    schedule 16.02.2016
comment
Спасибо! Что вы имеете в виду, говоря, что вам нужно вручную заполнить только первые несколько полей для данных? Мне нужно заполнить каждую строчку, верно? У Somoene есть какой-нибудь пример с настоящим IDOC?   -  person Fabio Lucia    schedule 17.02.2016
comment
да, вы должны заполнить каждую строку. Но таблицы, которые вы заполняете, содержат несколько статических полей, общих для всех типов idoc, а данные, специфичные для сегмента idoc, содержатся в одном поле длинных символов, называемом SDATA. Если вы посмотрите на структуру EDI_DD40 (структура для параметра IDOC_DATA_REC_40 в функциональном модуле), вы увидите, что в ней всего 7 полей. Первые 6 должны быть заполнены индивидуально, а остальная часть строки idoc идет в поле SDATA. Так что это просто вопрос чтения 6 подстрок и последующего перемещения остальной части строки в SDATA.   -  person Dirk Trilsbeek    schedule 17.02.2016


Ответы (3)


насколько мне известно, в текущем Net Connector 3 теперь есть помощник по idoc. Но если у вас есть файл, содержащий действительный idoc, у вас уже есть вся необходимая информация.

Основы отправки Idoc в систему SAP уже описаны здесь, поэтому я не буду вдаваться в подробности. в этом ответе. Чтобы отправить файл idoc, вам необходимо вручную заполнить контрольную запись (первая строка вашего idoc) и записи данных.

Контрольный стол требует некоторого ручного труда. К счастью, контрольная запись одинакова для всех idoc, так что вам не нужно учитывать тип idoc, который вы отправляете.

var fileStream = System.IO.File.OpenRead(fullFilepath);
var streamReader = new System.IO.StreamReader(fileStream);
string control = streamReader.ReadLine();

controlTable.Append();
controlTable.CurrentRow.SetValue("TABNAM", control.Substring(0, 10));
controlTable.CurrentRow.SetValue("MANDT", control.Substring(10, 3));
controlTable.CurrentRow.SetValue("DOCNUM", control.Substring(13, 16));
controlTable.CurrentRow.SetValue("DOCREL", control.Substring(29, 4));
controlTable.CurrentRow.SetValue("STATUS", control.Substring(33, 2));
controlTable.CurrentRow.SetValue("DIRECT", control.Substring(35, 1));
controlTable.CurrentRow.SetValue("OUTMOD", control.Substring(36, 1));
controlTable.CurrentRow.SetValue("EXPRSS", control.Substring(37, 1));
controlTable.CurrentRow.SetValue("TEST", control.Substring(38, 1));
controlTable.CurrentRow.SetValue("IDOCTYP", control.Substring(39, 30));
controlTable.CurrentRow.SetValue("CIMTYP", control.Substring(69, 30));
controlTable.CurrentRow.SetValue("MESTYP", control.Substring(99, 30));
controlTable.CurrentRow.SetValue("MESCOD", control.Substring(129, 3));
controlTable.CurrentRow.SetValue("MESFCT", control.Substring(132, 3));
controlTable.CurrentRow.SetValue("STD", control.Substring(135, 1));
controlTable.CurrentRow.SetValue("STDVRS", control.Substring(136, 6));
controlTable.CurrentRow.SetValue("STDMES", control.Substring(142, 6));
controlTable.CurrentRow.SetValue("SNDPOR", control.Substring(148, 10));
controlTable.CurrentRow.SetValue("SNDPRT", control.Substring(158, 2));
controlTable.CurrentRow.SetValue("SNDPFC", control.Substring(160, 2));
controlTable.CurrentRow.SetValue("SNDPRN", control.Substring(162, 10));
controlTable.CurrentRow.SetValue("SNDSAD", control.Substring(172, 21));
controlTable.CurrentRow.SetValue("SNDLAD", control.Substring(193, 70));
controlTable.CurrentRow.SetValue("RCVPOR", control.Substring(263, 10));
controlTable.CurrentRow.SetValue("RCVPRT", control.Substring(273, 2));
controlTable.CurrentRow.SetValue("RCVPFC", control.Substring(275, 2));
controlTable.CurrentRow.SetValue("RCVPRN", control.Substring(277, 10));
controlTable.CurrentRow.SetValue("RCVSAD", control.Substring(287, 21));
controlTable.CurrentRow.SetValue("RCVLAD", control.Substring(308, 70));
controlTable.CurrentRow.SetValue("REFMES", control.Substring(420, 14));

var dataLine = streamReader.ReadLine();
while (dataLine != null) {

    dataTable.Append();
    dataTable.CurrentRow.SetValue("SEGNAM", dataLine.SubString(0, 30));
    dataTable.CurrentRow.SetValue("MANDT", dataLine.SubString(30, 3));
    dataTable.CurrentRow.SetValue("DOCNUM", dataLine.SubString(33, 16));
    dataTable.CurrentRow.SetValue("SEGNUM", dataLine.SubString(49, 6));
    dataTable.CurrentRow.SetValue("PSGNUM", dataLine.SubString(55, 6));
    dataTable.CurrentRow.SetValue("HLEVEL", dataLine.SubString(61, 2));
    dataTable.CurrentRow.SetValue("SDATA", dataLine.SubString(63, dataLine.Length - 63));

    dataLine = streamReader.ReadLine();
}

этот фрагмент ожидает один idoc в файле. Если у вас есть несколько idoc в одном файле, вам нужно разделить их, выполнив поиск контрольной записи (строка контрольной записи обычно начинается с «EDI_DC40»).

person Dirk Trilsbeek    schedule 17.02.2016
comment
Привет Дирк! В то же время я только что попробовал почти то же самое. Кажется, работает нормально. Спасибо еще раз! Опубликует фрагмент, содержащий код для динамического получения метаданных из таблицы. - person Fabio Lucia; 17.02.2016

Основываясь на ответе Дирка, я только что создал 2 метода для динамического заполнения таблиц управления и данных с использованием доступных метаданных:

    private static void AddControlToIdocTable(ref IRfcTable control, string controlLine)
    {
        var lineType = control.Metadata.LineType;

        //Append a new Control Row
        control.Append();

        //Creates an empty array with the Count of the different fields the RfcTable consists of
        string[] columns = new string[control.Metadata.LineType.FieldCount];

        for (int i = 0; i < columns.Length; i++)
        {
            //Get the Type containg the structure of the field
            var type = lineType[i];

            //If NucOffset + NucLength is not bigger then the length of the current control line
            //we append the substring of the control line using those values (Offset + Length)
            if(controlLine.Length >= (type.NucOffset + type.NucLength))
                control.CurrentRow.SetValue(type.Name, controlLine.Substring(type.NucOffset, type.NucLength));
        }
    }

    private static void AddDataToIdocTable(ref IRfcTable records, List<string> dataLines)
    {
        var lineType = records.Metadata.LineType;

        //Creates an empty array with the Count of the different fields the RfcTable consists of
        string[] columns = new string[records.Metadata.LineType.FieldCount];

        foreach (string dataLine in dataLines)
        {
            //Append a new Data Row for every data line
            records.Append();
            for (int i = 0; i < columns.Length; i++)
            {
                //Get the Type containg the structure of the field
                var type = lineType[i];

                //If NucOffset + NucLength is not bigger then the length of the current control line
                //we append the substring of the control line using those values (Offset + Length)
                if (dataLine.Length >= (type.NucOffset + type.NucLength))
                    records.CurrentRow.SetValue(type.Name, dataLine.Substring(type.NucOffset, type.NucLength));
            }
        }
    }

Подробности опубликую после тестирования. Спасибо!

person Fabio Lucia    schedule 17.02.2016

Я несколько минут работал с кодом Фабио, читал документацию SAP и придумал этот метод заполнения таблиц. (Таблицы управления и данных одного класса)

    private void AppendRecordToTable(IRfcTable idocTable, string textRecord)
    {
        var structure = idocTable.Metadata.LineType.CreateStructure();
        foreach (var field in structure)
        {
            var fieldMeta = field.Metadata;
            var fieldValue = CreateFieldValue(fieldMeta, textRecord);
            structure.SetValue(fieldMeta.Name, fieldValue);
        }
        idocTable.Append(structure);
    }

    private string CreateFieldValue(RfcFieldMetadata fieldMeta, string record)
    {
        if (record.Length < fieldMeta.NucOffset)
            return new string(' ', fieldMeta.NucLength);
        if (record.Length < fieldMeta.NucOffset + fieldMeta.NucLength)
            return record.Substring(fieldMeta.NucOffset).PadRight(fieldMeta.NucLength);
        return record.Substring(fieldMeta.NucOffset, fieldMeta.NucLength);
    }
person Bob Hodge    schedule 14.02.2018