Егоров Андрей Викторович, руководитель информационно-технического отдела ООО МФФ "Аконит"
Примечание - большая часть написанного здесь текста с примерами взята по памяти (пару лет назад изучал достаточно подробно, поэтому может что-то в алгоритмах не работать - я ведь их не копировал откуда-то, а прямо тут же и писал, так что за синтаксические ошибки не пинайте) - на данный момент я активно 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!