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