OLE в 1С-Предприятии

Опубликовал Андрей Пастухов (Minotavrik) в раздел Программирование - Теория программирования

Небольшая инструкция с примерами - как работать с OLE

Краткая справка по использованию OLE в 1С-Предприятии.

Для запуска системы 1С-Предприятия в качестве OLE Automation сервера из внешнего приложения выполняется следующая последовательность действий:

  1. Создается объект с OLE идентификатором (регистр символов непринципиален):
    • V1CEnterprise.Application - версия независимый ключ;
    • V77.Application - версия зависимый ключ;
    • V77S.Application - версия зависимый ключ, SQL версия;
    • V77L.Application - версия зависимый ключ, локальная версия;
    • V77M.Application - версия зависимый ключ, сетевая версия.
  2. Выполняется инициализация системы 1С-Предприятие методом Initialize().
  3. Вызываются атрибуты и методы системы 1С-Предприятия как OLE Automation сервера.

1С-Предприятие в качестве OLE Automation сервера имеет 4 метода:

  • Initialize() - выполнить инициализацию системы 1С-Предприятие.
  • CreateObject() - Создает объект агрегатного типа данных 1С-Предприятия и возвращает ссылку на него.
  • EvalExpr() - Вычислить выражение системы 1С-Предприятие.
  • ExecuteBatch() - Выполнить последовательность операторов системы 1С-Предприятие.

Методы:

1. Initialize() - открыть базу.

Синтаксис метода такой:

Initialize(<Имя объекта>.RMTrade, <Командная строка>, <Пустая строка>)

где:

<Имя объекта>.RMTrade - имя переменной и ключевое слово RMTrade.
<Командная строка> - командная строка, в которой можно прописать путь к базе, имф пользователя и пароль.
<Пустая строка>) - либо пустая строка, либо "NO_SPLASH_SHOW" - чтобы не показывать заставку при загрузке.

Для того, чтобы открыть базу через OLE - необходимо создать объект с идентификатором OLE, выполнить инициализацию базы и проверить успешность выполнения инициализации. В своем примере я не указываю никаких дополнительных параметров, поэтому открывается квадратное окошко выбора базы, предлагается выбрать пользователя и ввести пароль.

ДругаяБаза=СоздатьОбъект("V77.Application");
Открыта=ДругаяБаза.Initialize(ДругаяБаза.RMTrade,,);
Если Открыта=0 Тогда
    // True=-1, False=0. Для всех OLE команд.
    Сообщить("База не была открыта.");
    Возврат;
КонецЕсли; 

2. CreateObject() - создать объект агрегатного типа.

Этот метод создает объект агрегатного типа данных системы 1С-Предприятия и возвращает ссылку на него.

Синтаксис метода такой:

CreateObject(<ИмяАгрегатногоТипа>)

где:

<ИмяАгрегатногоТипа> - строковое выражение, значение которого содержит имя агрегатного типа данных, заданного в конфигураторе. Например: "Справочник.Номенклатура", "Документ.ПриходнаяНакладная".

3. EvalExpr() - вычислить выражение.

Синтаксис метода такой:

EvalExpr(<СтрокаВыражения>)

где:

<СтрокаВыражения> - строковое выражение, записанное на встроенном языке 1С-Предприятия.

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

4. ExecuteBatch() - выполнить последовательность операторов.

Синтаксис метода такой:

ExecuteBatch(<СтрокаОператоров>)

где:

<СтрокаОператоров> - строковое выражение, текст программы на встроенном языке 1С-предприятия.

Возвращает значение логического типа: TRUE, если последовательность операторов выполнена успешно, FALSE, если нет. В OLE Automation TRUE и FALSE имеют соответственно значения -1 (минус единица) и 0.

Пример: создание документа в другой базе, открытой через OLE.

Выгрузка происходит из обработки. ВыбДокумент - документ, выбранный пользователем для выгрузки в другую базу.

ДругаяБаза=СоздатьОбъект("v77.application");
Открыта=ДругаяБаза.Initialize(ДругаяБаза.RMTrade,,);
Если Открыта=0 Тогда
    Сообщить("База не была открыта.");
    Возврат;
КонецЕсли;
дДок=ДругаяБаза.CreateObject("Документ.ПриходнаяНакладная");
дТовар=ДругаяБаза.CreateObject("Справочник.Номенклатура");
дДок.Новый();
дДок.ДатаДок=ВыбДокумент.ДатаДок;
дДок.Фирма=ДругаяБаза.evalexpr("Константа.ОсновнаяФирма");
дДок.Склад=ДругаяБаза.evalexpr("Константа.ОсновнойСклад");
дДок.КатегорияЦен=ДругаяБаза.evalexpr("Константа.ПриходнаяКатегорияЦен");
дДок.ВариантРасчетаНалогов=ДругаяБаза.evalexpr("Константа.ОсновнойВариантРасчетаНалогов");
дДок.Валюта=ДругаяБаза.evalexpr("Константа.БазоваяВалюта");//рубли
дДок.Дата_курса=дДок.ДатаДок;
дДок.ТипУчета=1;
дДок.Автор=ДругаяБаза.evalexpr("глПользователь");
дДок.ПризнакНакладной=ДругаяБаза.evalexpr("Перечисление.ПризнПрихНакл.Закупка");
дДок.Курс=1;//рубли
дДок.Комментарий=ВыбДОкумент.Комментарий;
ВыбДОкумент.ВыбратьСтроки();
Пока ВыбДокумент.ПолучитьСтроку()=1 Цикл
    дДок.НоваяСтрока();
    ТовКод=СокрЛП(ВыбДОкумент.Товар.Код);
    Если дТовар.НайтиПоКоду(ТовКод)=0 Тогда
        Сообщить("Не найден товар с кодом "+ТовКод);
        Возврат;
    КонецЕсли;
    дТовар.ИспользоватьДату(дДок.ДатаДок);
    дДок.Товар=дТовар.ТекущийЭлемент();
    дДок.Количество=ВыбДокумент.Количество;
    дДок.Единица=дТовар.ЕдиницаПоУмолчанию;
    дДок.Цена=ВыбДОкумент.Цена;
    дДок.Коэффициент=1;
    дДок.Всего=ВыбДОкумент.Сумма;
    дДок.Сумма=ВыбДОкумент.Сумма-ВыбДокумент.НП;
    дДок.СтавкаНДС=дТовар.СтавкаНДС;
    дДок.НДС=ВыбДокумент.НДС;
    дДок.СтавкаНП=дТовар.СтавкаНП;
    дДок.СуммаНП=ВыбДокумент.НП;
КонецЦикла;
дДок.УстановитьНовыйНомер(ДругаяБаза.evalexpr("Константа.ПрефиксНомеровДокументовУпрУчета"));
Сообщить(""+дДок.НомерДок);
дДок.Записать();

Этот пример на 100% рабочий. Используется у меня для выгрузки документов из одной конфигурации в другую.

Сравнение в базе OLE. Константы, перечисления, элементы справочников.

Для сравнения значений агрегатных типов данных в базе, открытой через Оле, использовать стандартный алгоритм с использование знаков равно и неравно (=,<>) не получается. Выход простой. Необходимо перейти от сравнения агрегатных типов данных к простым типам данных - дата, строка и число.

Отсюда вывод: мы сравниваем не сами элементы, а их уникальные атрибуты. Например, для элементов справочника - это код (если он есть), либо наименование. Для перечисления используется метод Идентификатор(). Вот два примера:

//Сравнение реквизита номенклатуры с Константой БазоваяВалюта
Если дТовар.ВалютаУчета.Код<>Другая.Константа.БазоваяВалюта.Код Тогда
    дТовар.ВалютаУчета=Другая.Константа.БазоваяВалюта;
КонецЕсли;
//Сравнение реквизита номенклатуры с перечислением
Если дТовар.ТипТовара.Идентификатор()<>Другая.Перечисление.ТипыТоваров.Штучный.Идентификатор() Тогда
    дТовар.ТипТовара=Другая.Перечисление.ТипыТоваров.Штучный;
КонецЕсли;

См. также

Комментарии
1. Ludmila Ludmila (recommend) 49 13.08.08 11:05 Сейчас в теме
А что изменится если вместо
дДок.Фирма=ДругаяБаза.evalexpr("Константа.ОсновнаяФирма");
написать
дДок.Фирма=ДругаяБаза.Константа.ОсновнаяФирма;
?
2. Valerasv (valerasv) 13.08.08 11:15 Сейчас в теме
****А что изменится если****
Не прокатит
3. Ludmila Ludmila (recommend) 49 13.08.08 11:31 Сейчас в теме
Сдается мне, что "покатит "
да и выполняться быстрее будет
4. g789 (g789) 13.08.08 16:04 Сейчас в теме
100% - "покатит", у меня работает
ОлдДата = База.Константа.ДатаЗапретаРедактирования;
5. Андрей Пастухов (Minotavrik) 1447 14.08.08 07:20 Сейчас в теме
В итоге получишь тоже самое, единственное может чуть медленнее, т.к функция EvalExpr() является COM т.е. храниться по сути в dll, которая подгружается в память скорее всего при загрузке компа и является голимым кодом для исполнения :))
6. Сергей Зенюков (Sanario) 15 03.09.16 09:15 Сейчас в теме
Курс же периодический реквизит - будет 0 равен, если установить, как установлено в коде про создание нового документа
7. white mount (white-mount) 03.09.16 11:37 Сейчас в теме
дДок=ДругаяБаза.CreateObject("Документ.ПриходнаяНакладная");
дТовар=ДругаяБаза.CreateObject("Справочник.Номенклатура");
дДок.Новый();
...

На мой взгляд основная ошибка данного метода в манипулировании открываемой базой.
Создавать объекты необходимо в базе-приёмнике.
источник это только источник данных.

Необходимость открытия ИБ для перепроверки это не самое главное.
Возможные ошибки при таком переносе потом дольше вылавливать.
Сбой целостности это тот ещё подарок.