gifts2017

 Интеграция 1С и C#. Обращение к 1С через COM. Создание номенклатуры и выполнение запроса к 1С из C# на примере интеграции с Союз-PLM (система информационной поддержки жизненного цикла изделий). Обработка «Загрузка заказа на сборку». (ERP) (загрузка через

Опубликовал Олег Молочников (milkers) в раздел Обмен - Загрузка и выгрузка в Excel

Союз-PLM представляет собой полнофункциональный программный комплекс для решения  широкого спектра задач управления инженерной технической информацией наукоемких изделий и сложных инженерных объектов в области машиностроения, приборостроения, архитектуры, строительства. На практике, это управление конструкторской документацией, интегрированное с САПР, бизнес-процессы, файловый архив. Все это работает в SQL и шевелится с помощью скриптов на C#. Скрипты свободно  отлаживаются в MS Visual Studio. Подробнее смотрите на их сайте: http://www.programsoyuz.ru/products/system-soyuz-plm.html  Редактирование, конструирование и использование бизнес-процессов на порядок лучше систем на базе 1С из тех, что я изучил.

Молочников Олег Spb. 2016.

Интеграция 1С и C#. Обращение к 1С через COM. Создание номенклатуры и выполнение запроса к 1С из C# на примере интеграции с Союз-PLM (система информационной поддержки жизненного цикла изделий). Обработка «Загрузка заказа на сборку». (ERP) (загрузка через EXCEL)

Что такое Союз-PLM. Согласно брошюрке это:

Союз-PLM представляет собой полнофункциональный программный комплекс для решения  широкого спектра задач управления инженерной технической информацией наукоемких изделий и сложных инженерных объектов в области машиностроения, приборостроения, архитектуры, строительства.

На практике, это управление конструкторской документацией, интегрированное с САПР, бизнес-процессы, файловый архив. Все это работает в SQL и шевелится с помощью скриптов на C#. Скрипты свободно  отлаживаются в MS Visual Studio. Подробнее смотрите на их сайте: http://www.programsoyuz.ru/products/system-soyuz-plm.html  Редактирование, конструирование и использование бизнес-процессов на порядок лучше систем на базе 1С из тех, что я изучил.

Пример кода выполняющего на стороне C# запрос в 1С:

	public override void Invoke( EntityAttribute attr, IEnumerable<CollectionElement> selectedElements )
	{
	         string connectionString = "srvr='192.168.0.999'; ref='с_copy'; usr='External'; pwd='123456';";
	        Type oType = Type.GetTypeFromProgID("V83.COMConnector");
	        if (oType != null)
	        {
	            //Создаем COMConnector, соединяемся с базой
	            object V8 = Activator.CreateInstance(oType);
	            object connection;
	            try
	            {
	                connection = oType.InvokeMember("Connect", BindingFlags.Public | BindingFlags.InvokeMethod, null, V8, new object[] { connectionString });
	            }
	            catch (Exception e)
	            {
	                Marshal.ReleaseComObject(V8);
	                    Service.UI.ShowMessage(string.Format("Ошибка подключения к 1С \'{0}\'", (e.InnerException.ToString()), e.Message));
	                return;
	            }
 
	            //Создаем и выполняем запрос (получение списка документов в заданном интервале)
	            object query = oType.InvokeMember("NewObject", BindingFlags.Public | BindingFlags.InvokeMethod, null, connection, new object[] { "Query" });
	            oType.InvokeMember("Текст", BindingFlags.Public | BindingFlags.SetProperty, null, query, new object[] { "ВЫБРАТЬ РеализацияТоваровУслуг.Дата, РеализацияТоваровУслуг.Номер, РеализацияТоваровУслуг.СуммаДокумента ИЗ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг ГДЕ РеализацияТоваровУслуг.Дата МЕЖДУ НАЧАЛОПЕРИОДА(&Дата1, ДЕНЬ) И КОНЕЦПЕРИОДА(&Дата2, ДЕНЬ)" });
	            oType.InvokeMember("УстановитьПараметр", BindingFlags.Public | BindingFlags.InvokeMethod, null, query, new object[] { "Дата1", new DateTime(2016, 3, 1, 0, 0, 0) });
	            oType.InvokeMember("УстановитьПараметр", BindingFlags.Public | BindingFlags.InvokeMethod, null, query, new object[] { "Дата2", new DateTime(2016, 10, 1, 0, 0, 0) });
	            object queryResult = oType.InvokeMember("Выполнить", BindingFlags.Public | BindingFlags.InvokeMethod, null, query, new object[] { });
	            object queryResultSelection = oType.InvokeMember("Выбрать", BindingFlags.Public | BindingFlags.InvokeMethod, null, queryResult, new object[] { });
	            StringBuilder sb = new StringBuilder();
                sb.Length = 0;
                 while ((bool)oType.InvokeMember("Следующий", BindingFlags.Public | BindingFlags.InvokeMethod, null, queryResultSelection, new object[] { }))
	            {
	                object field_date = oType.InvokeMember("Дата", BindingFlags.Public | BindingFlags.GetProperty, null, queryResultSelection, new object[] { });
	                object field_num = oType.InvokeMember("Номер", BindingFlags.Public | BindingFlags.GetProperty, null, queryResultSelection, new object[] { });
	                object field_sum = oType.InvokeMember("СуммаДокумента", BindingFlags.Public | BindingFlags.GetProperty, null, queryResultSelection, new object[] { });
	                sb.Append("Дата:");
	                sb.Append(field_date);
	                sb.Append(",\t№ ");
	                sb.Append(field_num);
	                sb.Append("\t - ");
	                sb.Append(field_sum);
                    sb.Append("\n");
	            }
            Service.UI.ShowMessage(sb.ToString());
 
            //Освобождаем память
            Marshal.ReleaseComObject(queryResultSelection);
	            Marshal.ReleaseComObject(queryResult);
	            Marshal.ReleaseComObject(query);
	            Marshal.ReleaseComObject(connection);
	            Marshal.ReleaseComObject(V8);
	        }
     }
  
}

 

Пример кода создающего на стороне C# номенклатуру в 1С:

   public override void Invoke(EntityAttribute attr, IEnumerable<CollectionElement> selectedElements)
    {
        string connectionString = "srvr='192.168.0.999'; ref='с_copy'; usr='External'; pwd='External';";
        Type oType = Type.GetTypeFromProgID("V83.COMConnector");
        if (oType != null)
        {
            //Создаем COMConnector, соединяемся с базой
            object V8 = Activator.CreateInstance(oType);
            object connection;
            try
            {
                connection = oType.InvokeMember("Connect", BindingFlags.Public | BindingFlags.InvokeMethod, null, V8, new object[] { connectionString });
            }
            catch (Exception e)
            {
                Marshal.ReleaseComObject(V8);
                Service.UI.ShowMessage(string.Format("Ошибка подключения к 1С  \'{0}\'", (e.InnerException.ToString()), e.Message));
                return;
            }
            string NameOfItem1C = "Тест создания номенклатуры из C#3";
 
            object Items1C = oType.InvokeMember("NewObject", BindingFlags.Public | BindingFlags.InvokeMethod, null, connection, new object[] { "СправочникМенеджер.Номенклатура" });
            object FindItem1C = oType.InvokeMember("НайтиПоНаименованию", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, Items1C, new object[] { NameOfItem1C });
            bool IfItem1CExist = Convert.ToBoolean(oType.InvokeMember("ЗначениеЗаполнено", BindingFlags.Public | BindingFlags.InvokeMethod, null, connection, new object[] { FindItem1C }));
            if (IfItem1CExist==false) {
                object NewItem1C = oType.InvokeMember("СоздатьЭлемент", BindingFlags.Public | BindingFlags.InvokeMethod, null, Items1C, new object[] { });
                object SpeciesOfItems1C = oType.InvokeMember("NewObject", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, connection, new object[] { "СправочникМенеджер.ВидыНоменклатуры" });
                object Material_SpeciesOfItems1C = oType.InvokeMember("НайтиПоНаименованию", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, SpeciesOfItems1C, new object[] { "Материал" });
                NewItem1C.GetType().InvokeMember("ВидНоменклатуры", BindingFlags.PutDispProperty | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, NewItem1C, new object[] { Material_SpeciesOfItems1C });
                oType.InvokeMember("ЗаполнитьРеквизитыПоВидуНоменклатуры", BindingFlags.Public | BindingFlags.InvokeMethod, null, Items1C, new object[] { NewItem1C });
                NewItem1C.GetType().InvokeMember("Наименование", BindingFlags.PutDispProperty | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, NewItem1C, new object[] { NameOfItem1C });
                NewItem1C.GetType().InvokeMember("НаименованиеПолное", BindingFlags.PutDispProperty | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, null, NewItem1C, new object[] { NameOfItem1C });
                try
                {
                    NewItem1C.GetType().InvokeMember("Записать", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static, null, NewItem1C, new object[] { });
                }
                catch (Exception e)
                {
                    Marshal.ReleaseComObject(Items1C);
                    Marshal.ReleaseComObject(connection);
                    Marshal.ReleaseComObject(V8);
                    Service.UI.ShowMessage(string.Format("Ошибка записи номенклатуры  \'{0}\'", (e.InnerException.ToString()), e.Message));
                    return;
                }
            }
         //Освобождаем память 
            Marshal.ReleaseComObject(Items1C);
            Marshal.ReleaseComObject(connection);
            Marshal.ReleaseComObject(V8);
 } }    }
 

Для работы этого кода вам придется в свойствах конфигурации в окне "Заголовок для скриптов" дописать:

using System.Reflection;
using System.Runtime.InteropServices;

В случае, если у вас возникает ошибка несоответсвия версий , рекомедую поискать comcntr.dll в regedit  и поправить пути.
В случае, если у вас возникает ошибка 800700c1 не является приложением Win32то весьма рекомендую статью http://infostart.ru/public/197627/  ("Ошибка V82.COMConnector на сервере 64. Решение проблемы")

По дополнительному запросу Союз-PLM  высылает шаблон документа “Сводная спецификация”.  Мы слегка модифицируем этот документ, добавив в шаблон в табличную часть поле “Покупной / IsPurchased” (Bool). Этот атрибут нам нужен, для того что бы мы знали какие детали мы купим в  виде готового узла, а какие подузлы будем собирать сами из комплектующих, которые, в свою очередь, тоже  надо обеспечить (купить или сделать) для сборки.

В скрипте формирования табличной части в процедуре public void ParseItem( ) меняем одну строку для заполнения нового атрибута.

                    // Однотипно заполняемые атрибуты
                    Line[ "IsPurchased" ] = IsPurchased;  // Эту строку мы добавили
                    Line[ "Order" ] = attr.CollectionElements.Count;

 Больше ничего менять не надо, нам вполне подойдет штатная выгрузка в Excel, прямо в документе, для передачи данных в 1С.

Подключаем обработку в ERP (НСИ и администрирование -> Печатные формы -> Дополнительные отчеты и обработки.) В документе “Заказ на сборку” в меню заполнение появится кнопка “Загрузить заказ на сборку из файла”.

 

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

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

Если для узла есть соответствие в ERP, то по сочетанию Обозначение+” ”+Наименование подбирается номенклатура из ERP.  Производится визуальный контроль заполнения колонки “Номенклатура ERP”. Если есть  номенклатура, которая названа по другому чем в PLM, но которую надо привести к стандарту, она выбирается в этой колонке вручную. 

После нажатия кнопки “Создать/обновить номенклатуру в ERP” будет создана недостающая номенклатура, а указанная приведена к стандарту.  В созданной номенклатуре артикул будет заполнен Обозначением.   

Нажатие кнопки “Добавить в документ” выгружает данные в документ. Количество комплектующих умножается на количество изделий, которые надо собрать в заказе на сборку. Если для узла стоит флаг “Покупной”, то он выгружается без подузлов.

К статье прилагается скрипт на C# для выгрузки  всех актуальных чертежей в форматах “tiff” и “pdf” для шаблона “исполнение изделия в версии (ЭСИ ГОСТ 2.053)”.   К теме имеет отношение слабое, но вдруг кому пригодиться.

Обработка гарантированно работает на платформе 8.3 (тестировано на релизе 8.3.8.1652) с конфигурациями 1С:ERP Управление предприятием 2 (тестировано на релизе 2.1.3.136)  только на управляемых формах.

P.S.: Надеюсь, вам понравится эта и другие мои статьи и разработки на http://infostart.ru/profile/48714/.

Очень жду ваших комментариев  и пожеланий.

Молочников Олег Spb. 2016.

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Пример скрипта выгруки изображений
.txt 11,19Kb
25.07.16
0
.txt 11,19Kb 0 Скачать
Пример экспорта спецификации
.xlsx 8,87Kb
25.07.16
0
.xlsx 8,87Kb 0 Скачать
Обработка загрузки заказа на сборку
.epf 15,42Kb
25.07.16
0
.epf 15,42Kb 0 Скачать

См. также

Подписаться Добавить вознаграждение
В этой теме еще нет сообщений.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа