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