К статье
Практический материал

Разработка и Конфигурация · 12 мин

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

Как проверить заполнение табличной части в 1С: код на встроенном языке, запросы, проверка перед проведением, типичные ошибки и готовые примеры для разработчика.

Табличная часть — один из основных способов хранения строк в документах и справочниках 1С: товары в накладной, сотрудники в приказе, этапы в договоре. Перед проведением документа или записью объекта почти всегда требуется убедиться, что табличная часть заполнена, а её строки содержат корректные данные. Без такой проверки в базе появляются «пустые» документы, которые ломают отчёты, обороты и последующие расчёты.

Проверить заполнение можно несколькими способами: простым сравнением количества строк с нулём, перебором строк в цикле, запросом к базе данных или штатным механизмом проверки заполнения в модуле объекта. Выбор зависит от задачи: нужно ли просто убедиться, что таблица не пуста, или проверить каждое поле каждой строки и выдать пользователю понятное сообщение с номером строки.

Ниже разобраны рабочие примеры кода на встроенном языке 1С 8.3, варианты с запросами, проверка на форме и на сервере, а также типичные ошибки, из-за которых проверка «вроде есть», но документ всё равно проводится с пустой табличной частью.

Что считается «заполненной» табличной частью

Прежде чем писать код, нужно определить критерий. «Заполнена» может означать три разных состояния: в табличной части есть хотя бы одна строка; в каждой строке заполнены обязательные реквизиты (номенклатура, количество, цена); данные строк проходят бизнес-проверки (количество больше нуля, сумма сходится с итогом документа). Это разные уровни проверки, и смешивать их в одну строку кода не стоит.

Простейший случай — документ не должен проводиться без строк. Здесь достаточно проверить количество. Более строгий случай — строки есть, но в них не заполнены ключевые поля: такой документ формально «не пустой», но по смыслу некорректный. Самый строгий уровень — логические проверки: например, не должно быть двух строк с одинаковой номенклатурой или сумма по строкам должна равняться сумме документа.

Проверка наличия строк: простой способ

Метод Количество() возвращает число строк табличной части. Если оно равно нулю — таблица пуста. Это самый быстрый и самый распространённый вариант проверки:

Если Объект.Товары.Количество() = 0 Тогда

Сообщить("Не заполнена табличная часть ""Товары""!");

Отказ = Истина;

КонецЕсли;

Такой код обычно размещают в обработчике ОбработкаПроверкиЗаполнения в модуле объекта. Параметр Отказ = Истина запрещает запись или проведение документа, пока пользователь не добавит хотя бы одну строку. Важно: если проверка находится в этом обработчике, платформа сама вызовет её при интерактивной записи, и дополнительно дёргать её из формы не нужно.

Для коллекции строк также работает метод Найти(): если поиск строки с нужным условием вернул Неопределено, значит подходящих строк нет. Это удобно, когда «пустота» определяется не количеством, а отсутствием строк определённого вида — например, нет ни одной строки с услугой.

Проверка заполнения реквизитов в каждой строке

Когда строки есть, но нужно убедиться, что в них заполнены обязательные поля, используют перебор в цикле Для Каждого. Для каждой строки проверяется значение реквизита через функцию ЗначениеЗаполнено():

Для Каждого СтрокаТовары Из Объект.Товары Цикл

Если Не ЗначениеЗаполнено(СтрокаТовары.Номенклатура) Тогда

Сообщение = Новый СообщениеПользователю;

Сообщение.Текст = "В строке " + СтрокаТовары.НомерСтроки

+ " не заполнена номенклатура";

Сообщение.Поле = "Товары[" + (СтрокаТовары.НомерСтроки - 1) + "].Номенклатура";

Сообщение.УстановитьДанные(Объект);

Сообщение.Сообщить();

Отказ = Истина;

КонецЕсли;

КонецЦикла;

Обратите внимание на привязку сообщения к полю: путь строится как ИмяТаблицы[Индекс].ИмяРеквизита, причём индекс начинается с нуля, а НомерСтроки — с единицы. Это частая причина «съехавших» подсветок: из номера строки нужно вычесть единицу. При правильной привязке пользователь кликает по сообщению и курсор встаёт ровно в проблемную ячейку.

Функция ЗначениеЗаполнено() корректно обрабатывает пустые ссылки, пустые строки, нулевые числа и пустые даты, поэтому для большинства реквизитов её достаточно. Но для числовых полей иногда нужна отдельная логика: количество равное нулю формально «заполнено», но по смыслу недопустимо — такие случаи проверяйте явным сравнением.

Проверка запросом: когда цикл не подходит

Цикл по строкам работает с данными в памяти — тем, что пользователь видит на форме. Но иногда нужно проверить табличную часть уже записанного объекта или сравнить строки с данными других таблиц (остатками, ценами, дублями в других документах). Здесь помогает запрос.

Например, проверка, что в табличной части нет дублей номенклатуры:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Номенклатура КАК Номенклатура,

| КОЛИЧЕСТВО(Товары.НомерСтроки) КАК ЧислоСтрок

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ &Товары КАК Товары

|

|СГРУППИРОВАТЬ ПО Товары.Номенклатура

|;

|ВЫБРАТЬ * ИЗ ВТ_Товары ГДЕ ЧислоСтрок > 1";

Запрос.УстановитьПараметр("Товары", Объект.Товары.Выгрузить());

Если Не Запрос.Выполнить().Пустой() Тогда

Отказ = Истина;

КонецЕсли;

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

Если же объект уже записан в базу, можно запросить табличную часть напрямую по ссылке: ИЗ Документ.РеализацияТоваровУслуг.Товары ГДЕ Ссылка = &Ссылка. Это пригодится в отчётах и обработках, которые анализируют уже проведённые документы.

Сравнение вариантов

Количество() = 0

Подходит для простой проверки «есть ли строки». Быстро, но не проверяет содержимое.

Цикл Для Каждого

Позволяет проверить каждый реквизит и дать сообщение с номером строки. Неудобен для сложных агрегатных проверок (дубли, суммы).

Запрос с параметром-таблицей

Лучший вариант для дублей, итогов и сверки с данными базы. Требует выгрузки табличной части и чуть больше кода.

Где размещать проверку: форма, модуль объекта, подписка

Правильное место для проверки — обработчик ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) в модуле объекта. Он срабатывает при любой записи: интерактивной, программной, при обмене данными. Проверки, размещённые только на форме, легко обойти — документ запишется через обработку или обмен, и пустая табличная часть попадёт в базу.

На форме проверки размещают только для удобства пользователя: например, подсветить незаполненные строки до нажатия «Провести» или заблокировать кнопку. Но дублирующая серверная проверка в модуле объекта обязательна. Если проверка нужна сразу для группы документов, используют подписку на событие ОбработкаПроверкиЗаполнения — один общий обработчик вместо копирования кода в каждый модуль.

Дополнительный уровень — свойство «Проверка заполнения» у реквизитов табличной части в конфигураторе. Значение «Выдавать ошибку» заставит платформу автоматически контролировать заполнение без единой строки кода. Этого достаточно для простых обязательных полей, а код оставьте для логических проверок.

Порядок внедрения проверки
  1. 1
    Определите критерий: пустая таблица, незаполненные поля или логические ошибки в строках
  2. 2
    Откройте модуль объекта документа и добавьте обработчик ОбработкаПроверкиЗаполнения
  3. 3
    Напишите проверку: Количество() для пустоты, цикл или запрос для содержимого
  4. 4
    Установите Отказ = Истина при нарушении и выведите СообщениеПользователю с привязкой к полю
  5. 5
    Проверьте запись документа интерактивно и программно — проверка должна срабатывать в обоих случаях

Типичные ошибки при проверке табличных частей

Самая распространённая ошибка — проверка только на форме. Пока документ вводят вручную, всё выглядит нормально, но первая же загрузка из обмена приносит пустые строки. Вторая частая проблема — неправильная привязка сообщения: индекс в пути поля считается с нуля, и забытая поправка «минус один» приводит к подсветке не той строки.

Третья группа ошибок связана с моментом проверки. Если код размещён в ПередЗаписью, а не в ОбработкаПроверкиЗаполнения, стандартная кнопка «Проверить заполнение» его не увидит, а сообщения не попадут в общий список ошибок. Ещё одна ловушка — проверять Количество() у табличной части, которая на форме отфильтрована: пользователь видит пустую таблицу, а в объекте строки есть. Проверять нужно данные объекта, а не отображение.

Наконец, при программной записи документов из обработок разработчики иногда забывают, что проверка заполнения не выполняется при вызове Записать() без проведения в некоторых сценариях, либо отключают проверки ради скорости загрузки. Для загрузочных обработок осознанно решайте: либо гарантировать качество данных на входе, либо вызывать проверку явно.

Типичные ошибки
01
Проверка только на форме — документ записывается пустым через обмен или обработку
02
Индекс строки без поправки: Товары[НомерСтроки] вместо Товары[НомерСтроки - 1] — сообщение указывает не на ту строку
03
Проверка в ПередЗаписью вместо ОбработкаПроверкиЗаполнения — не участвует в штатной проверке заполнения
04
Сравнение с Неопределено вместо ЗначениеЗаполнено() — пустая ссылка проходит проверку
05
Проверка отображаемой (отфильтрованной) таблицы формы вместо данных объекта

Проверка результата и границы самостоятельной работы

После внедрения кода проверьте три сценария. Первый: интерактивное проведение документа с пустой табличной частью — должна появиться ошибка, документ не проводится. Второй: заполните одну строку с пропущенным обязательным полем — сообщение должно указывать на конкретную строку и поле. Третий: запишите документ программно из консоли кода или обработки — проверка из модуля объекта должна сработать и здесь.

Изменения в модуле объекта требуют обновления конфигурации базы данных. Перед обновлением на рабочей базе сделайте резервную копию — особенно если правки затрагивают документы, по которым уже есть движения. Если конфигурация типовая и находится на поддержке, прямая правка модуля снимет её с полной поддержки; в этом случае рассмотрите расширение конфигурации — обработчик ОбработкаПроверкиЗаполнения можно добавить и через расширение.

Контрольные точки

Как проверить результат

Проведение документа без строк
Норма

Ошибка, документ не проводится

Тревожный признак

Документ проводится с пустой табличной частью

Клик по сообщению об ошибке
Норма

Курсор встаёт в нужную ячейку нужной строки

Тревожный признак

Подсвечивается другая строка или ничего не происходит

Программная запись из обработки
Норма

Проверка срабатывает так же, как интерактивно

Тревожный признак

Документ записывается в обход проверки

FAQ

Как проверить табличную часть на форме без записи документа?

Используйте обработчик команды формы: пройдите циклом по Элементы.Товары или по данным Объект.Товары и выведите сообщения через СообщениеПользователю. Для автоматической подсветки пустых ячеек удобно условное оформление формы — оно работает без кода проверки.

Чем отличается Количество() = 0 от проверки через ПустаяСтрока?

Функция ПустаяСтрока() проверяет строковое значение, а не коллекцию, и для табличной части не применяется. Пустоту табличной части определяют только по числу строк — методом Количество().

Как проверить табличную часть у ещё не записанного документа запросом?

Незаписанного объекта в базе нет, поэтому запрос по ссылке невозможен. Выгрузите табличную часть методом Выгрузить() в таблицу значений и передайте её в запрос как параметр — дальше доступны группировки и соединения с реальными таблицами базы.

Можно ли запретить проведение без строк без программирования?

Частично: для отдельных реквизитов табличной части в конфигураторе есть свойство «Проверка заполнения» со значением «Выдавать ошибку». Но запрет на полностью пустую табличную часть штатными свойствами не настраивается — нужен код в ОбработкаПроверкиЗаполнения.

Почему сообщение об ошибке подсвечивает не ту строку?

В пути поля используется индекс с нуля, а свойство НомерСтроки начинается с единицы. Стройте путь как "Товары[" + (НомерСтроки - 1) + "].ИмяРеквизита" и не забудьте вызвать УстановитьДанные(Объект) у сообщения.

Как проверить табличные части сразу нескольких видов документов?

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

Итог

Что важно запомнить

Проверку заполнения табличной части размещайте в ОбработкаПроверкиЗаполнения модуля объекта: Количество() — для пустоты, цикл или запрос — для содержимого строк. Сообщения привязывайте к полю с учётом индекса с нуля, а перед обновлением рабочей базы делайте резервную копию и тестируйте код на копии.