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