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