Как правильно создать подчиненный справочник (договор) через OLE в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Работа с базой 1С:Предприятие 7.7 через Automation (OLE) часто преподносит сюрпризы даже опытным разработчикам. Одной из самых распространенных задач является перегрузка данных, где необходимо создать элемент справочника (например, Контрагенты) и сразу же создать для него подчиненный элемент (например, Договоры). В этой статье мы подробно разберем, почему возникает ошибка «Не выбран элемент справочника-хозяина!» и как правильно организовать последовательность действий в коде.

Проблема: Почему договор не создается?

Рассмотрим типичную ситуацию. Программист пытается создать контрагента, заполняет его реквизиты, записывает, а затем сразу переходит к созданию договора. Однако при попытке вызвать метод Записать() для договора система выдает исключительную ситуацию. Основная причина кроется в специфике работы платформы 7.7: для подчиненного справочника недостаточно просто присвоить ссылку на владельца в реквизит. Необходимо явно указать контексту объекта, с каким владельцем он будет работать, еще до момента создания новой записи или в процессе её инициализации.

Разбор типичных ошибок в коде

Проанализируем фрагмент кода, с которым столкнулся автор темы. В первой редакции кода была попытка установить владельца напрямую:


ДогОЛЕ.Владелец = КонтрОЛЕ.ТекущийЭлемент();
ДогОЛЕ.Записать();

В среде 1С 7.7 такой подход часто не срабатывает через OLE, так как объект справочника требует вызова специального метода ИспользоватьВладельца(). Кроме того, часто встречается избыточное использование метода ТекущийЭлемент(). Рассмотрим основные моменты, которые требуют исправления:

  1. Избыточность ТекущийЭлемент(): При работе через OLE прямое обращение КонтрагентОЛЕ.ОсновнойДоговор.ТекущийЭлемент() может привести к ошибке, если ОсновнойДоговор пуст. В 7.7 лучше проверять само значение или использовать Выбран().
  2. Неверная последовательность: Метод Новый() должен вызываться в правильном контексте относительно установленного владельца.
  3. Проверка на пустоту: Использование Неопределено при работе с OLE-объектами 7.7 из внешней среды (например, из 1С 8.3) некорректно, так как OLE-объект всегда является объектом, даже если он не позиционирован на конкретной записи.

Правильный алгоритм создания подчиненного справочника

Разберем по шагам, как должна выглядеть надежная процедура создания связки «Контрагент — Договор».

Шаг 1. Создание и запись владельца. Сначала мы должны создать объект Контрагенты, заполнить его данные и обязательно вызвать Записать(). Без физической записи в базу данных у объекта не появится ссылка (уникальный идентификатор), которую можно передать в качестве владельца договору.

Шаг 2. Позиционирование на созданном объекте. После записи важно убедиться, что КонтрОЛЕ.ТекущийЭлемент() возвращает валидную ссылку.

Шаг 3. Установка связи для подчиненного объекта. Перед вызовом метода Новый() для договора необходимо вызвать метод ИспользоватьВладельца().

Шаг 4. Создание договора и обратная связь. Если в конфигурации предусмотрен реквизит ОсновнойДоговор в справочнике Контрагенты, нам придется записать контрагента второй раз, чтобы зафиксировать в нем ссылку на только что созданный договор.

Пример исправленного кода

Посмотрим на пример кода, который решает поставленную задачу корректно:


// Создаем объекты справочников
КонтрОЛЕ = ОбъектV77.CreateObject("Справочник.Контрагенты");
ДогОЛЕ   = ОбъектV77.CreateObject("Справочник.Договоры");

// Проверяем, существует ли контрагент (например, по ИНН)
Если КонтрОЛЕ.НайтиПоРеквизиту("ИНН", СокрЛП(Контрагент.ИНН), 1) = 0 Тогда
    // Если не нашли, создаем нового
    КонтрОЛЕ.Новый();
    КонтрОЛЕ.Наименование = СокрЛП(Контрагент.Наименование);
    КонтрОЛЕ.ИНН = СокрЛП(Контрагент.ИНН);
    // Записываем, чтобы получить ссылку для владельца
    КонтрОЛЕ.Записать();
КонецЕсли;

// Теперь работаем с договором
// Устанавливаем владельца ПЕРЕД созданием записи
ДогОЛЕ.ИспользоватьВладельца(КонтрОЛЕ.ТекущийЭлемент());

// Проверяем наличие договора (например, по наименованию у этого владельца)
Если ДогОЛЕ.НайтиПоНаименованию(СокрЛП(Договор.Наименование), 0, 1) = 0 Тогда
    ДогОЛЕ.Новый();
    ДогОЛЕ.Наименование = СокрЛП(Договор.Наименование);
    // Если нужно установить валюту
    Если ВалютаОЛЕ <> 0 Тогда
        ДогОЛЕ.Валюта = ВалютаОЛЕ;
    КонецЕсли;
    ДогОЛЕ.Записать();
КонецЕсли;

// Устанавливаем созданный договор основным для контрагента
// Обратите внимание: работаем напрямую через объект справочника Контрагенты
КонтрОЛЕ.ОсновнойДоговор = ДогОЛЕ.ТекущийЭлемент();
КонтрОЛЕ.Записать();

Важные нюансы работы через OLE

Проанализируем несколько технических моментов, которые помогут избежать ошибок в будущем:

1. Метод ТекущийЭлемент()
В 1С 7.7 ТекущийЭлемент() возвращает ссылку на объект. Когда вы работаете внутри самой программы, платформа часто прощает отсутствие этого вызова. Однако при передаче данных через OLE-интерфейс вы передаете COM-объект. Чтобы 1С поняла, что вы хотите передать именно ссылку на конкретную запись в базу данных, использование ТекущийЭлемент() становится обязательным при присваивании значений ссылочным реквизитам.

2. ИспользоватьВладельца()
Этот метод не просто заполняет реквизит Владелец. Он накладывает фильтр на выборку справочника. Если вы не вызовете его, система при попытке записи метода Новый() не будет знать, к кому «прицепить» этот элемент, даже если вы попытаетесь заполнить атрибут Владелец вручную.

3. Проблема «Курицы и яйца»
Ситуация, когда Контрагенту нужен Договор, а Договору — Контрагент, решается только двойной записью владельца.

  1. Первая запись создает GUID (в терминах 7.7 — внутренний ID) для контрагента.
  2. Вторая запись (после создания договора) обновляет поле ссылки на основной договор.

Не бойтесь лишнего вызова Записать(), в данном контексте это единственный надежный способ.

4. Обработка пустых значений
Вместо сравнения с Неопределено, которое характерно для 1С 8.х, при работе с 1С 7.7 рекомендуется использовать проверку через V77.EvalExpr("ПустоеЗначение(Значение)") или проверять Выбран(). Это позволит избежать ложных срабатываний кода в условиях, когда поиск элемента не дал результатов.

Заключение

Мы выяснили причину ошибки при создании договора и рассмотрели правильную архитектуру кода. Главное правило при работе с подчиненными справочниками в 1С 7.7 через OLE: сначала установите владельца методом ИспользоватьВладельца(), и только потом создавайте и записывайте новый элемент. Соблюдение этой последовательности гарантирует стабильную работу ваших интеграционных механизмов.

← На главную