Как программно открыть и сохранить форму элемента справочника в 1С 7.7?

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

В разработке на платформе 1С:Предприятие 7.7 часто возникает ситуация, когда необходимо массово обновить данные в справочнике. Однако начинающие разработчики сталкиваются с проблемой: бизнес-логика (например, создание подчиненных элементов, таких как «Единицы измерения» для «Номенклатуры») прописана в модуле формы, а не в модуле объекта. Из-за этого при обычном программном сохранении через Записать() нужные действия не выполняются. В этой статье мы разберем, как правильно решить эту задачу, избежав типичных ошибок.

Проблема: Почему простое открытие формы не работает?

Рассмотрим ситуацию: нам нужно пройтись по всему справочнику «Номенклатура» и для каждого элемента убедиться, что у него созданы базовые единицы измерения. Часто этот код «зашит» в процедуру ПриЗаписи() или ПриЗакрытии() самой формы элемента. Попытка просто открыть форму программно выглядит так:


Спр = СоздатьОбъект("Справочник.Номенклатура");
Если Спр.НайтиПоКоду("00000003") = 1 Тогда
    ОткрытьФорму(Спр.ТекущийЭлемент(), КонтекстФормы);
КонецЕсли;

Проблема заключается в том, что функция ОткрытьФорму лишь визуально отображает окно пользователю. Она не «нажимает» кнопку «ОК» за вас. Более того, попытка вызвать метод Записать() сразу после открытия формы часто приводит к ошибке «Данная команда не может выполняться в формуле элемента диалога!». Это происходит потому, что система блокирует рекурсивные или конфликтующие вызовы во время обработки событий интерфейса.

Анализируем причину ошибки «Данная команда не может выполняться...»

В 1С 7.7 архитектура разделения интерфейса и данных довольно жесткая. Когда вы вызываете ОткрытьФорму, управление передается интерактивному процессу. Если вы пытаетесь программно «достучаться» до методов записи этой формы, пока она еще находится в стадии инициализации или активного диалога, платформа выдает ошибку.

Важно понимать: форма в 1С 7.7 не является полноценным объектом базы данных, которым можно манипулировать как переменной. Это лишь визуальное представление данных.

Правильный подход: Перенос логики из формы в обработку

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

  1. Создаем объект справочника «Номенклатура» и организуем цикл по его элементам.
  2. Проверяем наличие подчиненных элементов в справочнике «Единицы».
  3. Если единицы отсутствуют, создаем их программно, устанавливая владельцем текущий элемент номенклатуры.
  4. Присваиваем созданную единицу в соответствующий реквизит номенклатуры (например, БазоваяЕдиница).

Посмотрим на пример кода, который реализует эту логику:


Спр = СоздатьОбъект("Справочник.Номенклатура");
СпрЕдиницы = СоздатьОбъект("Справочник.Единицы");
СпрОКЕИ = СоздатьОбъект("Справочник.ОКЕИ");

// Ищем код единицы измерения (например, штуки - 796)
Если СпрОКЕИ.НайтиПоКоду("796") = 0 Тогда
    Сообщить("Классификатор ОКЕИ не заполнен!");
    Возврат;
КонецЕсли;
ЭталонОКЕИ = СпрОКЕИ.ТекущийЭлемент();

Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
    Если Спр.ЭтоГруппа = 1 Тогда
        Продолжить;
    КонецЕсли;

    // Проверяем, создана ли уже единица
    СпрЕдиницы.ИспользоватьВладельца(Спр.ТекущийЭлемент());
    Если СпрЕдиницы.ВыбратьЭлементы() = 0 Тогда
        // Создаем новую единицу измерения
        СпрЕдиницы.Новый();
        СпрЕдиницы.Наименование = "шт";
        СпрЕдиницы.ОКЕИ = ЭталонОКЕИ;
        СпрЕдиницы.Коэффициент = 1;
        
        Попытка
            СпрЕдиницы.Записать();
            
            // Теперь обновляем саму номенклатуру
            Спр.БазоваяЕдиница = СпрЕдиницы.ТекущийЭлемент();
            Спр.Записать();
            Сообщить("Создана единица для: " + Спр.Наименование);
        Исключение
            Сообщить("Ошибка при записи: " + ОписаниеОшибки());
        КонецПопытки;
    КонецЕсли;
КонецЦикла;

Использование контекста при открытии формы

Если вы все же настаиваете на том, что код должен выполниться именно внутри формы (например, там слишком сложная логика, которую трудно перенести), можно использовать второй параметр функции ОткрытьФорму — контекст.

Рассмотрим этот метод подробнее. Мы можем передать в форму специальный параметр, а в модуле формы в процедуре ПриОткрытии() считать его и выполнить необходимые действия автоматически.

В обработке пишем:


Параметр = "АвтоматическоеСозданиеЕдиниц";
ОткрытьФорму(Спр.ТекущийЭлемент(), Параметр);

В модуле формы справочника Номенклатура:


Процедура ПриОткрытии()
    Если Форма.Параметр = "АвтоматическоеСозданиеЕдиниц" Тогда
        // Вызываем существующие в форме процедуры
        Процедура_Создания_Единиц(); 
        // Записываем объект
        Записать();
        // Закрываем форму без вопросов
        СтатусВозврата(0);
        Возврат;
    КонецЕсли;
КонецПроцедуры

Преимущество этого метода: вам не нужно дублировать код. Недостаток: вам придется изменить конфигурацию (модуль справочника), что не всегда возможно или желательно.

Использование внешних инструментов (FormEx и WScript)

Для тех случаев, когда конфигурацию менять нельзя, а программный интерфейс 1С 7.7 не предоставляет нужных возможностей, существуют «хакерские» методы. Проанализируем их применимость:

Выводы и рекомендации

Проанализировав ситуацию, мы можем сделать следующие выводы для эффективной работы в 1С 7.7:

  1. Избегайте привязки логики к формам. Если вы проектируете систему сами, старайтесь выносить расчеты и заполнение реквизитов в модуль объекта или глобальный модуль.
  2. Используйте прямую манипуляцию объектами. Работа через СоздатьОбъект всегда быстрее и надежнее, чем имитация работы пользователя с окнами.
  3. Двухэтапная запись. Помните, что при работе с подчиненными справочниками (как Единицы измерения) сначала нужно записать владельца, затем создать и записать подчиненный элемент, а затем (если нужно) обновить ссылку в основном элементе и записать его снова.

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

← На главную