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