Как реализовать обход табличной части и настроить контроль заполнения реквизитов в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки в среде 1С:Предприятие 8 одной из самых частотных задач является работа с табличными частями (ТЧ). Это могут быть списки товаров в накладной, перечень уроков в учебном плане или список дисциплин. Рассмотрим подробно, как правильно взаимодействовать с этими коллекциями, вычислять их параметры и внедрять логические проверки при записи документов.

Методы вычисления количества строк в табличной части

Прежде чем приступать к перебору строк, выясним, как быстро получить общее количество элементов в коллекции. Рассмотрим самый простой и эффективный способ — использование встроенного метода Количество(). Проанализируем пример, где Уроки — это имя нашей табличной части:


// Получение числа строк напрямую из объекта
КолСтрок = Уроки.Количество();

Важно понимать разницу в контексте обращения. Если мы работаем в модуле объекта, мы обращаемся к ТЧ напрямую по имени. Если же код исполняется в модуле формы, нам необходимо обращаться через основной реквизит формы, обычно это Объект:


// Обращение в модуле формы
КолСтрок = Объект.Уроки.Количество();

Разберем типичную ошибку начинающих разработчиков: попытку вызвать метод Количество() как глобальную функцию. Помните, что это метод конкретного объекта (табличной части), поэтому вызов всегда идет через точку от имени переменной коллекции.

Способы обхода табличной части: выбираем оптимальный цикл

Рассмотрим различные варианты итерации по строкам табличной части. В 1С существует несколько конструкций, позволяющих решить эту задачу, и выбор конкретной зависит от ваших целей.

1. Цикл "Для каждого" (наиболее предпочтительный)

Этот вариант является самым быстрым и читаемым. Мы не заботимся об индексах, а просто получаем по очереди каждую строку (объект типа ДанныеФормыЭлементКоллекции или СтрокаТабличнойЧасти).


Для каждого ТекущаяСтрока Из Объект.Уроки Цикл
    // Работаем с реквизитами строки
    Если ТекущаяСтрока.Специальность = Справочники.Специальности.ПустаяСсылка() Тогда
        // Выполняем действия
    КонецЕсли;
КонецЦикла;

2. Обход по индексу (через счетчик)

Этот метод полезен, когда нам нужно знать порядковый номер строки или обращаться к соседним элементам. Проанализируем синтаксис:


ВсегоСтрок = Объект.Уроки.Количество();
Для Индекс = 0 По ВсегоСтрок - 1 Цикл
    ТекущаяСтрока = Объект.Уроки[Индекс];
    // Логика обработки строки
КонецЦикла;

3. Использование счетчика в цикле (ручной подсчет)

В некоторых учебных задачах требуется реализовать подсчет количества строк вручную через перебор. Посмотрим, как это выглядит:


Счетчик = 0;
Для каждого Стр Из Объект.Дисциплины Цикл
    Счетчик = Счетчик + 1;
КонецЦикла;
// Теперь в переменной Счетчик хранится количество итераций

Реализация контроля заполнения реквизитов по условию

Разберем практическую задачу: необходимо включить проверку заполнения реквизита Специальность (в шапке документа) и колонки Урок (в табличной части Уроки). При этом проверка должна срабатывать только в том случае, если количество строк в табличной части меньше двух или если дата документа меньше текущей даты.

Наиболее правильным местом для реализации такой логики является обработчик события ОбработкаПроверкиЗаполнения в модуле объекта. Выясним причину: это событие специально предназначено для валидации данных перед сохранением. Рассмотрим пример реализации:


Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    
    // Вычисляем количество строк
    КолСтрок = Уроки.Количество();
    
    // Проверяем условие: строк меньше 2 ИЛИ дата в прошлом
    Если КолСтрок < 2 Или Дата < ТекущаяДата() Тогда
        
        // Добавляем реквизит шапки в список обязательных
        ПроверяемыеРеквизиты.Добавить("Специальность");
        
        // Добавляем реквизит табличной части (указывается через точку)
        ПроверяемыеРеквизиты.Добавить("Уроки.Урок");
        
    КонецЕсли;

КонецПроцедуры

Важный нюанс при сравнении дат: Функция ТекущаяДата() возвращает значение с точностью до секунды. Если вы хотите сравнивать только календарные дни (например, чтобы документ за сегодня не считался "прошлым"), рекомендуем использовать функцию НачалоДня():

Если НачалоДня(Дата) < НачалоДня(ТекущаяДата()) Тогда ...

Анализ проблем контекста: Клиент и Сервер

Часто новички сталкиваются с ошибками вида "Переменная не определена (Объект)" при попытке реализовать проверку в модуле формы. Разберем ситуацию подробнее.

Если вы создаете процедуру с директивой &НаСервереБезКонтекста, форма не передает данные объекта на сервер для экономии трафика. Следовательно, обратиться к табличной части через Объект.Уроки не получится. У вас есть два пути:

  1. Использовать директиву &НаСервере. В этом случае контекст формы передается полностью, и вы можете работать с данными привычным образом.
  2. Передавать необходимые данные в процедуру как параметры. Рассмотрим этот вариант:

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    // Вызываем серверную функцию, передавая количество строк
    Если Не ПроверитьДанныеНаСервере(Объект.Уроки.Количество()) Тогда
        Отказ = Истина;
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПроверитьДанныеНаСервере(КоличествоСтрок)
    Если КоличествоСтрок < 2 Тогда
        Возврат Ложь;
    КонецЕсли;
    Возврат Истина;
КонецФункции

Дополнительные инструменты для работы с табличными частями

Рассмотрим еще несколько полезных методов, которые помогут вам писать более чистый код:

Помните, что для успешной сдачи диплома или выполнения рабочих задач важно не только написать работающий код, но и понимать, в каком модуле и в каком обработчике он должен располагаться. Использование стандартных методов платформы, таких как Количество() и ОбработкаПроверкиЗаполнения, является признаком профессионального подхода к разработке.

← На главную