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