Смекни!
smekni.com

Взаимодействие через OLE (стр. 1 из 3)

Егоров Андрей Викторович, руководитель информационно-технического отдела ООО МФФ "Аконит"

Примечание - большая часть написанного здесь текста с примерами взята по памяти (пару лет назад изучал достаточно подробно, поэтому может что-то в алгоритмах не работать - я ведь их не копировал откуда-то, а прямо тут же и писал, так что за синтаксические ошибки не пинайте) - на данный момент я активно OLE не пользуюсь (не из-за каких-то проблем с самим OLE, а из-за отсутствия надобности в его использовании в текущий момент).

Основные преимущества, благодаря которым OLE активно используется:

Для вызывающей базы "по барабану" - какой тип вызываемой базы (DBF или SQL)

Объектами вызываемой базы можно управлять всеми известными методами работы с объектами в 1С (т.е. со справочниками работают методы ВыбратьЭлементы(), ИспользоватьДату() и т.п., с документами - ВыбратьДокументы() и т.п.), соответственно, можно напрямую решить - стоит отрабатывать конкретные объекты базы OLE или пропустить их.

Пример 1. Присоединение к базе 1С через OLE.

БазаОле=СоздатьОбъект("V77.Application"); // Получаем доступ к OLE объекту 1С
Локальная версия (на одного пользователя): V77L.Application
Сетевая версия: V77.Application
Версия SQL: V77S.Application

Далее вместо термина "вызываемая база" будет написано просто "база OLE", а вместо термина "вызывающая база" - "местная база"

Теперь, мы должны знать несколько параметров для запуска базы OLE: Каталог базы, имя пользователя и пароль. Ну, наверное, еще и желание запустить 1С в монопольном режиме :)

КаталогБазыОЛе = "C:\program files\1cv77\МояБаза\"; ПользовательОле = "Администратор"; ПарольОле = "qwerty"; МонопольныйРежимOLE = " /m"; // для немонопольного запуска указать пустую строку! ЗапускБезЗаставки = 1; // для появления заставки (например, чтобы наблюдать // процесс запуска базы OLE визуально) поставьте здесь "0" РезультатПодключения = БазаОле.Initialize ( БазаОле.RMTrade , "/d" + СокрЛП(КаталогБазыОле) + " /n" + СокрЛП(ПользовательОле)+ " /p" + СокрЛП(ПарольОле) + МонопольныйРежимOLE, ?(ЗапускБезЗаставки = 1, "NO_SPLASH_SHOW", "")); Если РезультатПодключения = 0 Тогда Предупреждение("Не удалось подключится к указанной базе - проверьте вводные!"); КонецЕсли;

Комментарий: функции СокрЛП() стоят в примере на случай, если пользователь захочет указанные выше переменные сделать в форме диалога, а проблема при этом состоит в том, что в алгоритм программа передаст полное значение реквизита (т.е. допишет в конце значения то количество пробелов, которое необходимо для получения полной длины строки (указана в свойствах реквизита диалога)).

Пример 2. Доступ к объектам базы OLE.

Запомните на будущее как непреложный факт:

Из местной базы в базу OLE (и, соответственно, наоборот) напрямую методом присвоения можно перенести только числовые значения, даты и строки ограниченной длины!!! Т.е. местная база поймет прекрасно без дополнительных алгоритмов преобразования полученного значения только указанные типы значений. Кроме того, под ограничением строк подразумевается проблемы с пониманием в местной базе реквизитов объектов базы OLE типа "Строка неограниченной длины". К этому же еще надо добавить и периодические реквизиты. Естественно, под методом присвоения подразумеваются и попытки сравнить объекты разных баз в одном условии (например, в алгоритмах "Если" или "Пока" и т.п.).

Есть проблемы при попытке перенести "пустую" дату - OLE может ее конвертировать, например, в 31.12.1899 года и т.п. Поэтому вам лучше заранее выяснить те значения, которые могут появится в местной базе при переносе "пустых" дат, чтобы предусмотреть условия преобразования их в местной базе.

A) Доступ к константам базы OLE:

ЗначениеКонстантыOLE = БазаОле.Константа.ДатаЗапретаРедактирования;

Б) Доступ к справочникам и документам базы OLE (через функцию "CreateObject"):

СпрOLE = БазаОле.CreateObject("Справочник.Фирмы"); // "СоздатьОбъект" в OLE не работает! ДокOLE = БазаОле.CreateObject("Документ.РасходнаяНакладная");

После создания объекта справочника или документа к ним применимы все методы, касающиеся таких объектов в 1С:

СпрОле.ВыбратьЭлементы(); Пока СпрОле.ПолучитьЭлемент()=1 Цикл Сообщить(Спр.Наименование); КонецЦикла;

Заметьте, что если вместо "Сообщить(Спр.Наименование)" вы укажете "Сообщить(Спр.ТекущийЭлемент())", то вместо строкового/числового представления этого элемента программа выдаст вам в окошке сообщение "OLE". Именно это я и имел в виду, когда говорил, что напрямую мало что можно перенести. Т.е. не будут работать следующие методы (ошибки 1С не будет, но и результат работы будет нулевой). Рассмотрим следующий пример:

СпрOLE = БазаОле.CreateObject("Справочник.Фирмы"); // это справочник в базе OLE Док = СоздатьОбъект("Документ.РасходнаяНакладная"); // а это документ в местной базе Док.Новый(); // создаем новый документ в местной базе СпрOLE.НайтиПоКоду(1, 0); // спозиционируем в базе OLE // на фирме с кодом "1". Док.Фирма = СпрOLE.ТекущийЭлемент(); // такой метод не сработает, т.к. справа от "=" стоит // объект не местной базы, и местная база 1С его не понимает!

Однако, сработает следующий метод:

Спр = СоздатьОбъект("Справочник.Фирмы"); // создаем объект справочника местной базы Спр.НайтиПоНаименованию(СпрОле.Наименование, 0, 0); // Или Спр.найтиПоКоду(СпрОле.Код, 0); // т.е. СпрОле.Код и Спр.наименование // являются обычными числовыми/строковыми // значениями, которые понимает местная база! Док.Фирма = Спр.ТекущийЭлемент(); // Вот теперь все в порядке, т.к. с обоих сторон метода // стоят объекты только местной базы!

Отсюда вывод: возможность доступа к объектам базы 1С через OLE требуется, в основном, только для определенной задачи - получить доступ к реквизитам определенного элемента справочника или документа. Однако, не забываем, что объекты базы OLE поддерживают все методы работы с ними, в т.ч. и "Новый()", т.е. приведем пример противоположный предыдущему:

ДокОле = CreateObject("Документ.РасходнаяНакладная"); // Создаем документ в базе OLE ДокОле.Новый(); Спр = СоздатьОбъект("Справочник.Фирмы"); // В местной базе получаем доступ к справочнику Спр.НайтиПоКоду(1, 0); // Находим в местной базе фирму с кодом 1 (если есть) ДокОле.Фирма = Спр.ТекущийЭлемент(); // такой метод не сработает

Однако, сработает следующий метод:

СпрОле = БазаОле.CreateObject("Справочник.Фирмы"); // создаем объект справочника базы OLE СпрОле.НайтиПоНаименованию(Спр.Наименование, 0, 0); // Или СпрОле.найтиПоКоду(Спр.Код, 0); // т.е. Спр.Код и Спр.Наименование являются обычными числовыми/строковыми значениями, // которые понимает база OLE! ДокОле.Фирма = СпрОле.ТекущийЭлемент(); // Вот теперь все в порядке, т.к. с обоих сторон // метода стоят объекты базы OLE! ДокОле.Записать(); // запишем документ в базе OLE Если ДокОле.Провести()=0 тогда Сообщить("Не смогли провести документ!"); КонецЕсли;

В) Доступ к регистрам базы OLE (Не сложнее справочников и документов):

РегОле=БазаOLE.CreateObject("Регистр.ОстаткиТоваров"); РегОле.ВыбратьИтоги(); Пока РегОле.ПолучитьИтог()=1 Цикл // Не забываем, что надо указывать наименование! Сообщить("Остаток для " + РегОле.Товар.Наименование+ " на складе " + РегОле.Склад.Наименование + " равен " + РегОле.ОстатокТовара); КонецЦикла;

Г) Доступ к перечислениям базы OLE (аналогичен константе):

ЗначениеПеречисленияOLE = БазаОле.Перечисление.Булево.НеЗнаю; // :)

Заметьте, что пользы для местной базы от переменной "ЗначениеПеречисленияOLE" особо-то и нет, ведь подобно справочнику и документу перечисление также напрямую недоступно для местной базы. Пожалуй, пример работы с ними может быть следующим (в качестве параметра условия):

СмотретьТолькоВозвратыПоставщикам = 1; // предположим, что это - флажок в форме диалога, // который мы либо устанавливаем, либо снимаем ДокОле = БазаОле.CreateObject("Документ.РасходнаяНакладная"); ДокОле.ВыбратьДокументы(НачДата, КонДата); // НачДата и КонДата - также реквизиты формы // диалога, но база OLE прекрасно их понимает - // ведь это же даты! Пока ДокОле.ПолучитьДокумент()=1 Цикл Если СмотретьТолькоВозвратыПоставщикам = 1 Тогда Если ДокОле.ПризнакНакладной <> БазаОле.Перечисление.ПризнРасхНакл.ВозвратПоставщику Тогда Продолжить; КонецЕсли; Иначе Если ДокОле.ПризнакНакладной = БазаОле.Перечисление.ПризнРасхНакл.ВозвратПоставщику Тогда Продолжить; КонецЕсли; КонецЕсли; Сообщить(ДокОле.Вид() + " № "+ДокОле.НомерДок + " от " + ДокОле.датаДок); КонецЦикла;

Д) Доступ к счетам базы OLE:

СчтОле=БазаОле.CreateObject("Счет"); СчтОле.НайтиПоКоду("10.5"); // нашли в базе OLE счет 10.5

Е) Доступ к ВидамСубконто базы OLE (аналогичен перечислению):

ВидСубконтоКонтрагентыОле = БазаОле.ВидыСубконто.Контрагенты;

По аналогии со справочниками и документами работает объект "Периодический", план счетов работает по аналогии с ВидомСубконто, ну и далее в том же духе… Отдельную главу посвятим запросу, а сейчас… стоп. Еще пункт забыл!

Ж) Доступ к функциям и процедурам глобального модуля базы OLE!