Примечание - большая часть написанного здесь текста с примерами взята по памяти (пару лет назад изучал достаточно подробно, поэтому может что-то в алгоритмах не работать - я ведь их не копировал откуда-то, а прямо тут же и писал, так что за синтаксические ошибки не пинайте) - на данный момент я активно 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 files1cv77МояБаза"; ПользовательОле = "Администратор"; ПарольОле = "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!
Как же я про это забыл-то, а? Поскольку при запуске базы автоматически компилируется глобальный модуль, то нам становятся доступны функции и процедуры глобального модуля (поправлюсь - только те, у которых стоит признак "Экспорт"). Плюс к ним еще и различные системные функции 1С. А доступны они нам через функцию 1С OLE - EvalExpr(). Приведем примеры работы с базой OLE:
ДатаАктуальностиОле = БазаОле.EvalExpr("ПолучитьДатуТА()"); // Возвращает дату актуальности ИмяПользователяОле = БазаОле.EvalExpr("ИмяПользователя()"); // возвращает строку // // попробуем теперь получить числовое значение НДС у элемента номенклатуры // через функцию глобального модуля ПроцентНДС(СтавкаНДС) Экспорт! ТовОле = БазаОле.CreateObject("Справочник.Номенклатура"); ТовОле.ВыбратьЭлементы(); // Найдем элемент справочника (не группа!) Пока ТовОле.ПолучитьЭлемент()=1 Цикл Если ТовОле.ЭтоГруппа()=0 Тогда Прервать; КонецЕсли; КонецЦикла; ЧисловоеЗначениеПроцентаНДСТовараОле = БазаОле.EvalExpr("ПроцентНДС(Перечисление.ЗначенияНДС." + ТовОле.СтавкаНДС.Идентификатор()+")"); |
На самом деле, в последней строке примера я исхитрился и забежал немного вперед. Дело в том, что как и запрос (см. отдельную главу), так и EvalExpr() выполняются внутри базы OLE, причем команды передавается им обычной строкой, и поэтому надо долго думать, как передать необходимые ссылки на объекты базы OLE в строке текста местной базы. Так что, всегда есть возможность поломать голову над этим…
Алгоритмы преобразования объектов в "удобоваримый вид" между базами.
Ясно, что алгоритмы преобразования нужны не только для переноса объектов между и базами, но и для такой простой задачи, как попытки сравнить их между собой.
И еще раз обращу внимание: ОБЪЕКТЫ ОДНОЙ БАЗЫ ПРЕКРАСНО ПОНИМАЮТ ДРУГ ДРУГА, ПРОБЛЕМЫ ВОЗНИКАЮТ ТОЛЬКО ТОГДА, КОГДА ВЫ НАЧИНАЕТЕ СВЯЗЫВАТЬ МЕЖДУ СОБОЙ ОБЪЕКТЫ РАЗНЫХ БАЗ, т.е. команда
ДокОле.Фирма=СпрОле.ТекущийЭлемент();
// где ДокОле - документ базы OLE, а СпрОле - справочник "Фирмы" базы OLE
будет прекрасно работать без ошибок. Не забывайте это, чтобы не перемудрить с алгоритмами!
Итак, повторяюсь, что напрямую перенести, да и просто сравнить можно только даты (причем не "пустые"), числа и строки ограниченной длины. Итак, как же нам сравнить объекты разных баз (не числа, не даты, не строки), т.е. как их преобразовать в эту самую строку/число/дату.
Егоров Андрей Викторович
Mista.Ru
Начать дискуссию