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