В процессе разработки конфигураций на платформе 1С:Предприятие часто возникает задача ограничить создание документов на основании существующих. Копирование — удобный механизм для пользователя, но он может привести к дублированию ошибок или нарушению бизнес-логики. В этой статье мы подробно рассмотрим, как запретить копирование документов различными способами, а также разберем методы проверки данных в текстовых полях.
Если вы работаете в обычном приложении (толстый клиент), наиболее простым способом будет использование параметра формы ПараметрОбъектКопирования. Рассмотрим ситуацию, когда нам нужно прервать открытие формы нового документа, если он был создан нажатием кнопки «Копировать».
Для этого нам необходимо использовать событие формы ПередОткрытием. Разберем по шагам, как это реализовать:
ПередОткрытием и перейдем в его обработчик в модуле.Проанализируем код, который необходимо вставить в данную процедуру:
Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
// Проверяем, заполнена ли ссылка на объект-источник копирования
Если ЗначениеЗаполнено(ПараметрОбъектКопирования) Тогда
Отказ = Истина; // Отменяем открытие формы
Предупреждение("Копирование данного документа запрещено правилами системы!");
КонецЕсли;
КонецПроцедуры
Важно помнить, что обращение ЭтаФорма.ПараметрОбъектКопирования работает только в контексте формы объекта. Если вы попытаетесь применить этот код в форме списка, система выдаст ошибку «Поле объекта не обнаружено», так как в списке нет конкретного объекта, который копируется.
В управляемых формах (платформа 8.3) механизм передачи данных при копировании изменился. Теперь информация о копировании передается через параметры формы. Для реализации запрета мы используем обработчик ПриСозданииНаСервере.
Выясним причину, почему это работает именно там: при интерактивном копировании в параметры формы передается ключ ЗначениеКопирования, содержащий ссылку на исходный документ. Рассмотрим пример кода:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем наличие параметра ЗначениеКопирования
Если Параметры.ЗначениеЗаполнено("ЗначениеКопирования") Тогда
Отказ = Истина;
// Сообщение пользователю в управляемом интерфейсе лучше выводить через ТекстСообщения
Сообщить("Создание документа путем копирования запрещено.");
КонецЕсли;
КонецПроцедуры
Наиболее надежным методом считается работа на уровне метаданных или модуля объекта. Это гарантирует, что запрет сработает даже в том случае, если документ создается программно, а не только интерактивно через форму.
Рассмотрим использование обработчика ОбработкаЗаполнения в модуле документа. Этот метод вызывается при создании любого нового объекта.
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
// Если ДанныеЗаполнения имеют тип ссылки на этот же документ, значит идет копирование
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ОтчетОПроведенииАудита") Тогда
// Вызов исключения — самый жесткий способ прервать процесс
ВызватьИсключение "Копирование документов этого типа полностью запрещено на уровне ядра системы.";
КонецЕсли;
КонецПроцедуры
Также существует событие ПриКопировании в модуле объекта. Однако стоит учитывать, что у этого события нет параметра Отказ. В нем мы можем либо очистить критически важные поля, чтобы пользователь вводил их заново, либо также вызвать исключение.
Часто вместе с запретом копирования возникает задача проверки корректности введенных данных. Например, запретить сохранение, если поле «Описание» содержит только пробелы, точки или запятые. Это предотвращает ввод «мусорных» данных для обхода проверки на заполненность.
Для этого в модуле формы документа в обработчике ПередЗаписью мы можем реализовать следующую логику. Посмотрим на пример кода:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Очищаем строку от пробелов по краям
ТекстПроверки = СокрЛП(ОписаниеРеакцияРаботника);
// Проверяем, не пустая ли строка после удаления пробелов
Если ТекстПроверки = "" Тогда
Отказ = Истина;
Сообщить("Поле 'Описание' не может быть пустым!");
Возврат;
КонецЕсли;
// Проверяем наличие только запрещенных символов (точки и запятые)
// Используем Найти (или СтрНайти в новых версиях)
Если Найти(ТекстПроверки, ",") > 0 Или Найти(ТекстПроверки, ".") > 0 Тогда
// Дополнительная логика: если в строке ЕСТЬ что-то кроме точек и запятых
// Для простоты примера запретим наличие запятых и точек вообще, если это условие задачи
Отказ = Истина;
Сообщить("Поле 'Описание' содержит недопустимые символы (точки или запятые)!");
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию: если ваша платформа старше 8.3.6, используйте функцию Найти. В более свежих релизах рекомендуется применять СтрНайти, так как она работает быстрее и имеет больше параметров.
Еще один важный аспект разработки — управление состоянием колонок в табличной части. Например, если в строке выбран «Риск легкой травмы», то «Риск тяжелой травмы» должен автоматически сниматься. Если данные хранятся в числовом виде (0 или 1), но на форме отображаются как флажки, используйте обработчик ПриИзменении для соответствующей колонки.
Разберем пример реализации для табличной части:
Процедура ТабличнаяЧастьРискиРискЛегкойТравмыПриИзменении(Элемент)
ТекДанные = Элементы.ТабличнаяЧастьРиски.ТекущиеДанные;
Если ТекДанные.РискЛегкойТравмы = Истина Тогда
// Снимаем другие флажки
ТекДанные.РискТяжелойТравмы = Ложь;
ТекДанные.РискСмертельнойТравмы = Ложь;
КонецЕсли;
КонецПроцедуры
Важный момент: Если ваши реквизиты имеют тип Число, а не Булево, на форме для элемента управления (флажка) нужно установить свойства Значение истины как 1 и Значение лжи как 0. В коде в таком случае вместо Истина/Ложь используйте 1/0.
Подводя итог, мы видим, что ограничение копирования — это комплексная задача. Для быстрой реализации в интерфейсе достаточно модуля формы, но для гарантированного соблюдения правил учета лучше использовать модуль объекта и обработку заполнения.