При разработке документов в системе 1С часто возникает задача автоматического (программного) добавления строк в табличную часть. Типичный пример — продажа комплекта (например, мебельного стеллажа), при выборе которого в документе «Расходная накладная» наряду с основным товаром должен автоматически появиться весь список его комплектующих (полок, крепежей, стоек). При этом бизнес-логика требует, чтобы пользователь не мог вручную редактировать, изменять количество или удалять эти автоматически добавленные строки-комплектующие, так как они жестко привязаны к спецификации основного изделия.
В этой статье мы подробно разберем, как реализовать надежный запрет на редактирование программно добавленных строк в табличной части документа на управляемых формах 1С 8.3. Мы рассмотрим как визуальную блокировку с помощью условного оформления, так и жесткое ограничение интерактивных действий пользователя через обработку событий формы.
Если мы установим свойство ТолькоПросмотр для элемента формы «Таблица», то заблокируется абсолютно вся табличная часть. Нам же необходимо действовать избирательно: строки, которые пользователь ввел вручную (например, сам стеллаж или другие отдельные товары), должны оставаться доступными для редактирования, а строки, добавленные программно (детали комплекта), должны быть заблокированы.
Для решения этой задачи мы применим комплексный подход, состоящий из трех основных шагов:
---
Прежде всего, платформа должна уметь отличать строки, которые ввел пользователь, от строк, которые были добавлены алгоритмом. Для этого добавим в табличную часть нашего документа служебный реквизит.
Рассмотрим порядок действий по шагам:
РасходнаяНакладная).СписокНоменклатуры).Автодобавление (или СлужебнаяСтрока) и типом данных Булево.Видимость элемента формы. Этот реквизит будет использоваться исключительно в кодовой логике.---
Теперь доработаем процедуру заполнения табличной части комплектующими на сервере. При добавлении подчиненных строк мы будем устанавливать нашему служебному реквизиту значение Истина. Проанализируем пример кода:
&НаСервере
Процедура ДобавитьКомплектующиеНаСервере(НаименованиеКомплекта)
// Запрос для получения состава комплекта из регистра сведений
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Комплектация.Материал КАК Материал,
| Комплектация.Количество КАК Количество
|ИЗ
| РегистрСведений.Комплектация КАК Комплектация
|ГДЕ
| Комплектация.Товар = &Товар";
Запрос.УстановитьПараметр("Товар", НаименованиеКомплекта);
Выборка = Запрос.Выполнить().Выбрать();
// В цикле обходим комплектующие и добавляем их в табличную часть документа
Пока Выборка.Следующий() Цикл
НоваяСтрока = Объект.СписокНоменклатуры.Добавить();
НоваяСтрока.Номенклатура = Выборка.Material;
НоваяСтрока.Количество = Выборка.Количество;
// Получаем цену (например, среднюю по складу)
НоваяСтрока.Цена = Серверный.СредняяПоСкладу(Выборка.Материал, Объект.Склад);
НоваяСтрока.Сумма = НоваяСтрока.Количество * НоваяСтрока.Цена;
// Устанавливаем признак программно добавленной строки
НоваяСтрока.Автодобавление = Истина;
КонецЦикла;
// Пересчитываем итог документа
Объект.СуммаПоДокументу = Объект.СписокНоменклатуры.Итог("Сумма");
КонецПроцедуры
---
Самым простым и элегантным способом визуально запретить редактирование конкретных строк на управляемой форме является использование механизма Условного оформления. Многие разработчики ошибочно полагают, что условное оформление доступно только в интерактивном режиме настройки формы. На самом деле мы можем легко настроить его программно на стороне сервера при создании формы.
Давайте разберем по шагам, как написать код программной настройки условного оформления в обработчике события формы ПриСозданииНаСервере:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
НастроитьБлокировкуСтрокТаблицы();
КонецПроцедуры
&НаСервере
Процедура НастроитьБлокировкуСтрокТаблицы()
// 1. Создаем новый элемент условного оформления
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
// 2. Указываем свойство, которое хотим применить. В нашем случае это "ТолькоПросмотр"
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ТолькоПросмотр", Истина);
// 3. Задаем условие (отбор), при котором оформление будет срабатывать
// Нам нужно оформлять строки, у которых реквизит "Автодобавление" равен Истина
ЭлементОтбора = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.СписокНоменклатуры.Автодобавление");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = Истина;
// 4. Указываем, какие именно поля (колонки) таблицы подлежат блокировке.
// Если мы хотим заблокировать всю строку, добавляем все видимые колонки ТЧ.
МассивКолонок = Новый Массив;
МассивКолонок.Добавить("СписокНоменклатурыНоменклатура");
МассивКолонок.Добавить("СписокНоменклатурыКоличество");
МассивКолонок.Добавить("СписокНоменклатурыЦена");
МассивКолонок.Добавить("СписокНоменклатурыСумма");
Для Каждого ИмяКолонки Из МассивКолонок Цикл
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных(ИмяКолонки);
КонецЦикла;
КонецПроцедуры
Благодаря этому коду платформа автоматически сделает все ячейки строки недоступными для ввода и изменения, если в скрытом поле Автодобавление стоит флаг Истина. Визуально эти поля станут недоступными для фокуса ввода, что защитит их от случайной модификации пользователем.
---
Хотя условное оформление отлично справляется с визуальной блокировкой ячеек для ввода данных, оно имеет существенную брешь в безопасности: пользователь все еще может выделить заблокированную строку в интерфейсе и нажать клавишу Del на клавиатуре (или выбрать пункт контекстного меню «Удалить»). Строка удалится, что нарушит комплектность накладной.
Чтобы закрыть эту уязвимость и обеспечить стопроцентную защиту данных, мы должны задействовать клиентские события таблицы формы. Перейдем на форму документа, выберем элемент таблицы СписокНоменклатуры и создадим обработчики событий ПередНачаломИзменения и ПередУдалением.
Рассмотрим код клиентских обработчиков:
&НаКлиенте
Процедура СписокНоменклатурыПередНачаломИзменения(Элемент, Отказ, ВходВРежимРедактирования, НоваяСтрока, Копирование)
// Получаем данные текущей строки таблицы
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Если строка добавлена автоматически, запрещаем любое изменение или копирование
Если ТекущиеДанные.Автодобавление Тогда
Отказ = Истина;
// Если пользователь пытался скопировать строку
Если Копирование Тогда
ПоказатьПредупреждение(, "Копирование автоматически добавленных строк комплектующих запрещено!");
Иначе
ПоказатьПредупреждение(, "Эта строка заблокирована, так как является частью комплекта!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СписокНоменклатурыПередУдалением(Элемент, Отказ)
// Запрещаем удаление отдельных комплектующих
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
Если ТекущиеДанные.Автодобавление Тогда
Отказ = Истина;
ПоказатьПредупреждение(, "Нельзя удалить комплектующую деталь отдельно от основного комплекта!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
С помощью этой несложной надстройки мы полностью исключаем любую возможность обойти запрет на редактирование. Попытка удалить или скопировать системную строку вызовет информационное предупреждение, а само действие будет отменено платформой (параметр Отказ = Истина).
---
В реальных бизнес-сценариях просто заблокировать строки комплектующих бывает недостаточно. Возникает закономерный вопрос: а что делать, если пользователь решит изменить количество основного товара (например, заказать не 1 стеллаж, а 3) или вовсе удалить сам стеллаж из документа?
Для решения этой проблемы в профессиональной разработке используется концепция Ключа связи:
КлючСвязи.1). Он записывается в поле КлючСвязи основного товара.КлючСвязи записывается этот же номер 1.ПриИзменении, находит в табличной части все строки с аналогичным КлючомСвязи и пропорционально пересчитывает их количество.ПередУдалением) система автоматически находит все строки с его ключом связи и программно удаляет их вместе с ним.Такой подход делает табличную часть интерактивной, защищенной и интуитивно понятной для пользователя, исключая появление «осиротевших» заблокированных строк в документе.