В разработке на платформе 1С:Предприятие 7.7 часто возникает ситуация, когда необходимо массово обновить данные в справочнике. Однако начинающие разработчики сталкиваются с проблемой: бизнес-логика (например, создание подчиненных элементов, таких как «Единицы измерения» для «Номенклатуры») прописана в модуле формы, а не в модуле объекта. Из-за этого при обычном программном сохранении через Записать() нужные действия не выполняются. В этой статье мы разберем, как правильно решить эту задачу, избежав типичных ошибок.
Рассмотрим ситуацию: нам нужно пройтись по всему справочнику «Номенклатура» и для каждого элемента убедиться, что у него созданы базовые единицы измерения. Часто этот код «зашит» в процедуру ПриЗаписи() или ПриЗакрытии() самой формы элемента. Попытка просто открыть форму программно выглядит так:
Спр = СоздатьОбъект("Справочник.Номенклатура");
Если Спр.НайтиПоКоду("00000003") = 1 Тогда
ОткрытьФорму(Спр.ТекущийЭлемент(), КонтекстФормы);
КонецЕсли;
Проблема заключается в том, что функция ОткрытьФорму лишь визуально отображает окно пользователю. Она не «нажимает» кнопку «ОК» за вас. Более того, попытка вызвать метод Записать() сразу после открытия формы часто приводит к ошибке «Данная команда не может выполняться в формуле элемента диалога!». Это происходит потому, что система блокирует рекурсивные или конфликтующие вызовы во время обработки событий интерфейса.
В 1С 7.7 архитектура разделения интерфейса и данных довольно жесткая. Когда вы вызываете ОткрытьФорму, управление передается интерактивному процессу. Если вы пытаетесь программно «достучаться» до методов записи этой формы, пока она еще находится в стадии инициализации или активного диалога, платформа выдает ошибку.
Важно понимать: форма в 1С 7.7 не является полноценным объектом базы данных, которым можно манипулировать как переменной. Это лишь визуальное представление данных.
Вместо того чтобы пытаться имитировать действия пользователя (нажатие кнопок, открытие окон), мы должны проанализировать код модуля формы справочника «Номенклатура», найти там фрагмент, отвечающий за создание единиц измерения, и реализовать его непосредственно в нашей обработке. Рассмотрим, как это сделать по шагам.
БазоваяЕдиница).Посмотрим на пример кода, который реализует эту логику:
Спр = СоздатьОбъект("Справочник.Номенклатура");
СпрЕдиницы = СоздатьОбъект("Справочник.Единицы");
СпрОКЕИ = СоздатьОбъект("Справочник.ОКЕИ");
// Ищем код единицы измерения (например, штуки - 796)
Если СпрОКЕИ.НайтиПоКоду("796") = 0 Тогда
Сообщить("Классификатор ОКЕИ не заполнен!");
Возврат;
КонецЕсли;
ЭталонОКЕИ = СпрОКЕИ.ТекущийЭлемент();
Спр.ВыбратьЭлементы();
Пока Спр.ПолучитьЭлемент() = 1 Цикл
Если Спр.ЭтоГруппа = 1 Тогда
Продолжить;
КонецЕсли;
// Проверяем, создана ли уже единица
СпрЕдиницы.ИспользоватьВладельца(Спр.ТекущийЭлемент());
Если СпрЕдиницы.ВыбратьЭлементы() = 0 Тогда
// Создаем новую единицу измерения
СпрЕдиницы.Новый();
СпрЕдиницы.Наименование = "шт";
СпрЕдиницы.ОКЕИ = ЭталонОКЕИ;
СпрЕдиницы.Коэффициент = 1;
Попытка
СпрЕдиницы.Записать();
// Теперь обновляем саму номенклатуру
Спр.БазоваяЕдиница = СпрЕдиницы.ТекущийЭлемент();
Спр.Записать();
Сообщить("Создана единица для: " + Спр.Наименование);
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Если вы все же настаиваете на том, что код должен выполниться именно внутри формы (например, там слишком сложная логика, которую трудно перенести), можно использовать второй параметр функции ОткрытьФорму — контекст.
Рассмотрим этот метод подробнее. Мы можем передать в форму специальный параметр, а в модуле формы в процедуре ПриОткрытии() считать его и выполнить необходимые действия автоматически.
В обработке пишем:
Параметр = "АвтоматическоеСозданиеЕдиниц";
ОткрытьФорму(Спр.ТекущийЭлемент(), Параметр);
В модуле формы справочника Номенклатура:
Процедура ПриОткрытии()
Если Форма.Параметр = "АвтоматическоеСозданиеЕдиниц" Тогда
// Вызываем существующие в форме процедуры
Процедура_Создания_Единиц();
// Записываем объект
Записать();
// Закрываем форму без вопросов
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецПроцедуры
Преимущество этого метода: вам не нужно дублировать код. Недостаток: вам придется изменить конфигурацию (модуль справочника), что не всегда возможно или желательно.
Для тех случаев, когда конфигурацию менять нельзя, а программный интерфейс 1С 7.7 не предоставляет нужных возможностей, существуют «хакерские» методы. Проанализируем их применимость:
Enter или Esc. Мы открываем форму модально, а затем через скрипт посылаем сигнал нажатия клавиши. Однако этот метод крайне нестабилен, так как фокус окна может переключиться в самый неподходящий момент.Проанализировав ситуацию, мы можем сделать следующие выводы для эффективной работы в 1С 7.7:
СоздатьОбъект всегда быстрее и надежнее, чем имитация работы пользователя с окнами.Рассмотренные подходы позволят вам автоматизировать рутинные операции в старых версиях 1С, сохраняя стабильность базы данных и чистоту кода.