Передача данных из SAP в .NET с помощью ERPConnect

ОГЛАВЛЕНИЕ

Описание инструмента программирования интерфейса для объединения SAP и .NET

• Скачать пример 1 (C#) - 7.35 Кб
• Скачать пример 1 (VB.NET) - 12.57 Кб
• Скачать пример 2 (C#) - 15.14 Кб
• Скачать пример 2 (VB.NET) - 16.38 Кб

Введение

В проекте для последнего заказчика пришлось реализовать своего рода "программу быстрого заказа" для компании-производителя машин. Целью этого проекта было дать возможность инженерам-строителям отправлять автоматически сгенерированный список заказов отделу закупок. Отдел строительства использует систему управления данными об изделии на базе SQL Server 2000 с клиентом Access, тогда как отдел закупок и другие экономические отделы используют систему SAP. Главной задачей проекта была реализация интерфейса для этих двух систем, особенно для приема необходимых данных из системы SAP в приложении .NET. После короткого поиска в Интернете был найден ERPConnect от Theobald Software. Данный инструмент позволил напрямую подключаться к нужным данным из BAPI(интерфейс программирования бизнес-приложений) и таблиц в системе SAP.

Было найдено всего несколько статей о Соединителе .NET от SAP, но ни одной статьи касательно ERPConnect, поэтому мы подумали, что другим пользователям будет интересно почитать об использовании, функциях и личном опыте с другим инструментом для программирования интерфейса SAP. По понятным причинам не публикуем код проекта заказчика, поэтому написали два примера, объясняющие использование ERPConnect. Первый пример рассматривает подключение к BAPI, а второй пример касается чтения прямо из таблиц SAP.

Два примера на VB.NET и C# были включены в раздел загрузок выше. Из проектов были убраны данные входа в систему и подключения к SAP; чтобы опробовать примеры, заполните их своими собственными данными подключения и входа в систему.

Краткая информация о SAP

Для тех, кто не имел дела с SAP, объясним самые важные понятия SAP для программирования интерфейса.
Функциональные модули: Функциональный модуль равноценен нормальной функции/процедуре в любом обычном языке программирования. Функциональные модули являются встроенными модулями SAP, написанными на ABAP(программирование передовых бизнес-приложений), и доступны из любой другой программы ABAP в системе. Как функция в любом ином языке программирования, функциональные модули принимают параметры импорта и экспорта. Функциональные модули также позволяют использовать двунаправленные таблицы. Подключиться извне SAP можно только к функциональному модулю с поддержкой RFC (как в нашем случае). Способ подключения к функциональному модулю без поддержки RFC описан далее в статье.

BAPI: BAPI работает как функциональный модуль, единственное отличие состоит в том, что он является интерфейсом программирования (API) для репозитария бизнес-объектов SAP.

IDocs: IDocs используются для обмена данными между двумя системами SAP или системой SAP и подсистемой. Можно представить IDocs как электронный чек, написанный на бумаге. IDoc однозначно определяется по его имени (и по имени его расширения). IDocs хорошо структурированы, они имеют заголовок, содержащий административную информацию, такую как: отправитель, информация о принимающей системе и средство передачи данных. Кроме заголовка, IDoc имеет иерархические сегменты, подобные древовидной структуре. Каждый сегмент имеет одно или больше полей, содержащих экономические данные.

Запросы SAP: Запросы SAP работают так же, как и любой иной запрос. Для однозначной идентификации запроса SAP нужны три части информации: область пользователя (глобальная или локальная); группа пользователей и имя запроса.

Как использовать ERPConnect

После установки ERPConnect на компьютер надо лишь добавить ссылку (ERPConnect.dll используется с .NET Framework 1.1, а ERPConnect20.dll используется .NET Framework 2.0) в проект и добавить оператор using ERPConnect; в заголовок – вот и все.

Пример 1: Чтение данных из BAPI с помощью объекта RFCFunction

В этом коротком примере показано, как получить значение BANK_KEY клиента 0000001172 и отобразить результат на консоли.

После создания объекта R3Connection и открытия соединения создаем объект RFCFunction для соединения, вызывая BAPI. Затем заполняем параметр Exports объекта-функции RFC параметром Import BAPI. То есть отправляем значение Импорт в BAPI. Сделав это, исполняем функцию и извлекаем искомые данные из таблицы с результатами. Вот и все.

class Program
{
static void Main(string[] args)
{
Connect();
}

static void Connect()
{
//получаем лицензию
ERPConnect.LIC.SetLic("licence code");

//создание объекта соединения
R3Connection con = new R3Connection("name of the application server",
"system number",
"user",
"password",
"language",
"client");

//открытие соединения
con.Open();

//создание объекта RFCFunction
RFCFunction func = con.CreateFunction("BAPI_CUSTOMER_GETDETAIL2");

//отправка параметра импорта в BAPI
func.Exports["CUSTOMERNO"].ParamValue = "0000001172";

try
{
//исполняем функцию
func.Execute();
}
catch (ERPException e)
{
Console.WriteLine(e.Message);
}

/*Чтение BANK_KEY из func и сохранение его в строку.
В таблице с результатами есть лишь один ряд, так как
номеру заказчика соответствует только один заказчик,
поэтому выбираем нужный столбец из таблицы с результатами*/
string Bank_Key =
Convert.ToString(func.Tables["CUSTOMERBANKDETAIL"].Rows[0, "BANK_KEY"]);

//в конце не забудьте закрыть соединение
con.Close();

//отображаем данные
Console.WriteLine("Customer: 0000001172");
Console.WriteLine("Bank Key: {0}", Bank_Key);
Console.ReadLine();
}
}

Результат должен выглядеть так:

 

Можно сохранить результат в DataTable, добавив строку...

DataTable dt = func.Tables["CUSTOMERBANKDETAIL"].ToADOTable();

... после блока Try Catch, затем получаем все данные из CUSTOMERBANKDETAIL согласно номеру заказчика 0000001172.
В данном примере было показано базовое использование ERPConnect для связи с функциональными модулями, но есть ряд более интересных функций (описанных далее в статье) обработки взаимодействия RFC и IDoc и даже чтения прямо из таблиц SAP.

Пример 2: Чтение прямо из таблицы SAP с помощью класса ReadTable

На мой взгляд, ReadTable класс является одним из самых полезных специальных классов, потому что он дает возможность непосредственно читать из таблицы SAP. Для проекта моего заказчика это было очень важно для извлечения данных из таблиц SAP в. NET DataSet, так что этот класс был очень полезен для меня.

Данный пример показывает, как использовать класс ReadTable с помощью оператора "где - как", чтобы получить адрес всех заказчиков в таблице KNA1, соответствующих введенному условию имени, и отобразить результат в DataGridView.
Логика примера инкапсулирована в класс по имени SAPConnect. Как в примере выше, оператор using ERPConnect; и using ERPConnect.Utils; для использования класса ReadTable должны быть добавлены в заголовок.

Нужны следующие закрытые свойства:

private string _userName;
private string _password;
private string _client;
private R3Connection _con;

Параметры для конструктора - username, password и client, хранящиеся в локальных свойствах.

public SAPConn(string userName, string password, string client)
{
_userName = userName;
_password = password;
_client = client;
}

Так как адрес сервера приложений, номер системы и язык чаще всего имеют одно и то же значение, можно ввести эти параметры прямо в код или сохранить их в конфигурационном файле. В проекте заказчика было много методов, использующих одинаковую строку подключения, поэтому процедура открытия соединения хранилась в отдельной закрытой функции по имени openConnection:

private void openConnection()
{
ERPConnect.LIC.SetLic("licence code");

R3Connection con = new R3Connection("name of the application server",
"system number",
_userName,
_password,
"language",
_client);
try
{
connection.Open();
}
catch (ERPException e)
{
MessageBox.Show(e.Message);
}

_con = connection;
}
Нужен метод закрытия соединения:
private void closeConnection()
{
_con.Close();
}

Теперь можно реализовать метод для чтения прямо из таблицы SAP и возвращать результат в DataSet. Сначала разберем, как работает эта функция:

Для начала надо создать объект ReadTable и заполнить свойство TableName именем таблицы SAP, из которой надо читать. Затем добавляем нужные поля с помощью метода AddField. Сделав это, заполняем WhereClause строкой Like. В этом примере было задано дополнительное свойство RowCount на 100, чтобы получить только 100 рядов в результате. После выполнения запроса имеем результат Result в виде DataTable.

public DataTable WhereLikeSearch(string sapTable, string nameCriteria)
{
openConnection();

//создание объекта ReadTable
ReadTable table = new ReadTable(_con);

//Задание имени таблицы, из которой надо читать
table.TableName = sapTable;

//добавление полей, отображаемых в DataTable
table.AddField("NAME1");
table.AddField("STRAS");
table.AddField("ORT01");
table.AddField("PSTLZ");
table.AddField("TELF1");
table.AddField("TELFX");

//это есть…
table.WhereClause = string.Format("NAME1 LIKE '%{0}%'", nameCriteria);

//это дополнительное свойство
table.RowCount = 100;

//исполнение запроса
try
{
table.Run();
}
catch(ERPException e)
{
MessageBox.Show(e.Message);
}

DataTable dt = table.Result;

closeConnection();

return dt;

}

Вместо оператора like можно использовать оператор = для поиска результатов, точно совпадающих с nameCriteria, тогда table.WhereClause выглядит так:

table.WhereClause = string.Format("NAME1 = '{0}'", nameCriteria);

В этом операторе важно соблюдать правильный синтаксис, особенно пробелы до и после =, иначе сгенерируется ERPException.

Чтобы отобразить данные в DataGridView, надо добавить следующий код в обработчик события button1_Click. После нажатия кнопки содержимым textBox1 будет nameCriteria.

private void button1_Click(object sender, EventArgs e)
{
string nameCriteria = textBox1.Text;

SAPConn sapConn = new SAPConn("userName", "password", "client");
DataTable dt = sapConn.WhereLikeSearch("KNA1", nameCriteria);

dataGridView1.DataSource = dt;
}

После исполнения программы надо заполнить DataGridView 100 заказчиками, соответствующими условию (например, ввод t в TextBox возвращает всех заказчиков с t в их имени).