Разработка и Конфигурация · 12 мин
Как проверить заполнение табличной части в 1С
Как проверить заполнение табличной части в 1С: код на встроенном языке, запросы, проверка перед проведением, типичные ошибки и готовые примеры для разработчика.
Табличная часть — один из основных способов хранения строк в документах и справочниках 1С: товары в накладной, сотрудники в приказе, этапы в договоре. Перед проведением документа или записью объекта почти всегда требуется убедиться, что табличная часть заполнена, а её строки содержат корректные данные. Без такой проверки в базе появляются «пустые» документы, которые ломают отчёты, обороты и последующие расчёты.
Проверить заполнение можно несколькими способами: простым сравнением количества строк с нулём, перебором строк в цикле, запросом к базе данных или штатным механизмом проверки заполнения в модуле объекта. Выбор зависит от задачи: нужно ли просто убедиться, что таблица не пуста, или проверить каждое поле каждой строки и выдать пользователю понятное сообщение с номером строки.
Ниже разобраны рабочие примеры кода на встроенном языке 1С 8.3, варианты с запросами, проверка на форме и на сервере, а также типичные ошибки, из-за которых проверка «вроде есть», но документ всё равно проводится с пустой табличной частью.
Что считается «заполненной» табличной частью
Прежде чем писать код, нужно определить критерий. «Заполнена» может означать три разных состояния: в табличной части есть хотя бы одна строка; в каждой строке заполнены обязательные реквизиты (номенклатура, количество, цена); данные строк проходят бизнес-проверки (количество больше нуля, сумма сходится с итогом документа). Это разные уровни проверки, и смешивать их в одну строку кода не стоит.
Простейший случай — документ не должен проводиться без строк. Здесь достаточно проверить количество. Более строгий случай — строки есть, но в них не заполнены ключевые поля: такой документ формально «не пустой», но по смыслу некорректный. Самый строгий уровень — логические проверки: например, не должно быть двух строк с одинаковой номенклатурой или сумма по строкам должна равняться сумме документа.
Проверка наличия строк: простой способ
Метод Количество() возвращает число строк табличной части. Если оно равно нулю — таблица пуста. Это самый быстрый и самый распространённый вариант проверки:
Если Объект.Товары.Количество() = 0 Тогда
Сообщить("Не заполнена табличная часть ""Товары""!");
Отказ = Истина;
КонецЕсли;
Такой код обычно размещают в обработчике ОбработкаПроверкиЗаполнения в модуле объекта. Параметр Отказ = Истина запрещает запись или проведение документа, пока пользователь не добавит хотя бы одну строку. Важно: если проверка находится в этом обработчике, платформа сама вызовет её при интерактивной записи, и дополнительно дёргать её из формы не нужно.
Для коллекции строк также работает метод Найти(): если поиск строки с нужным условием вернул Неопределено, значит подходящих строк нет. Это удобно, когда «пустота» определяется не количеством, а отсутствием строк определённого вида — например, нет ни одной строки с услугой.
Проверка заполнения реквизитов в каждой строке
Когда строки есть, но нужно убедиться, что в них заполнены обязательные поля, используют перебор в цикле Для Каждого. Для каждой строки проверяется значение реквизита через функцию ЗначениеЗаполнено():
Для Каждого СтрокаТовары Из Объект.Товары Цикл
Если Не ЗначениеЗаполнено(СтрокаТовары.Номенклатура) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "В строке " + СтрокаТовары.НомерСтроки
+ " не заполнена номенклатура";
Сообщение.Поле = "Товары[" + (СтрокаТовары.НомерСтроки - 1) + "].Номенклатура";
Сообщение.УстановитьДанные(Объект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецЦикла;
Обратите внимание на привязку сообщения к полю: путь строится как ИмяТаблицы[Индекс].ИмяРеквизита, причём индекс начинается с нуля, а НомерСтроки — с единицы. Это частая причина «съехавших» подсветок: из номера строки нужно вычесть единицу. При правильной привязке пользователь кликает по сообщению и курсор встаёт ровно в проблемную ячейку.
Функция ЗначениеЗаполнено() корректно обрабатывает пустые ссылки, пустые строки, нулевые числа и пустые даты, поэтому для большинства реквизитов её достаточно. Но для числовых полей иногда нужна отдельная логика: количество равное нулю формально «заполнено», но по смыслу недопустимо — такие случаи проверяйте явным сравнением.
Проверка запросом: когда цикл не подходит
Цикл по строкам работает с данными в памяти — тем, что пользователь видит на форме. Но иногда нужно проверить табличную часть уже записанного объекта или сравнить строки с данными других таблиц (остатками, ценами, дублями в других документах). Здесь помогает запрос.
Например, проверка, что в табличной части нет дублей номенклатуры:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| КОЛИЧЕСТВО(Товары.НомерСтроки) КАК ЧислоСтрок
|ПОМЕСТИТЬ ВТ_Товары
|ИЗ &Товары КАК Товары
|
|СГРУППИРОВАТЬ ПО Товары.Номенклатура
|;
|ВЫБРАТЬ * ИЗ ВТ_Товары ГДЕ ЧислоСтрок > 1";
Запрос.УстановитьПараметр("Товары", Объект.Товары.Выгрузить());
Если Не Запрос.Выполнить().Пустой() Тогда
Отказ = Истина;
КонецЕсли;
Табличную часть передают в запрос как параметр через метод Выгрузить(), который превращает её в таблицу значений. Дальше с ней работают обычными средствами языка запросов: группировки, соединения, условия. Такой подход заметно удобнее цикла, когда проверка сложная — например, нужно сопоставить каждую строку с остатком на складе или проверить, что все указанные договоры действуют на дату документа.
Если же объект уже записан в базу, можно запросить табличную часть напрямую по ссылке: ИЗ Документ.РеализацияТоваровУслуг.Товары ГДЕ Ссылка = &Ссылка. Это пригодится в отчётах и обработках, которые анализируют уже проведённые документы.
Сравнение вариантов
Подходит для простой проверки «есть ли строки». Быстро, но не проверяет содержимое.
Позволяет проверить каждый реквизит и дать сообщение с номером строки. Неудобен для сложных агрегатных проверок (дубли, суммы).
Лучший вариант для дублей, итогов и сверки с данными базы. Требует выгрузки табличной части и чуть больше кода.
Где размещать проверку: форма, модуль объекта, подписка
Правильное место для проверки — обработчик ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты) в модуле объекта. Он срабатывает при любой записи: интерактивной, программной, при обмене данными. Проверки, размещённые только на форме, легко обойти — документ запишется через обработку или обмен, и пустая табличная часть попадёт в базу.
На форме проверки размещают только для удобства пользователя: например, подсветить незаполненные строки до нажатия «Провести» или заблокировать кнопку. Но дублирующая серверная проверка в модуле объекта обязательна. Если проверка нужна сразу для группы документов, используют подписку на событие ОбработкаПроверкиЗаполнения — один общий обработчик вместо копирования кода в каждый модуль.
Дополнительный уровень — свойство «Проверка заполнения» у реквизитов табличной части в конфигураторе. Значение «Выдавать ошибку» заставит платформу автоматически контролировать заполнение без единой строки кода. Этого достаточно для простых обязательных полей, а код оставьте для логических проверок.
- 1Определите критерий: пустая таблица, незаполненные поля или логические ошибки в строках
- 2Откройте модуль объекта документа и добавьте обработчик ОбработкаПроверкиЗаполнения
- 3Напишите проверку: Количество() для пустоты, цикл или запрос для содержимого
- 4Установите Отказ = Истина при нарушении и выведите СообщениеПользователю с привязкой к полю
- 5Проверьте запись документа интерактивно и программно — проверка должна срабатывать в обоих случаях
Типичные ошибки при проверке табличных частей
Самая распространённая ошибка — проверка только на форме. Пока документ вводят вручную, всё выглядит нормально, но первая же загрузка из обмена приносит пустые строки. Вторая частая проблема — неправильная привязка сообщения: индекс в пути поля считается с нуля, и забытая поправка «минус один» приводит к подсветке не той строки.
Третья группа ошибок связана с моментом проверки. Если код размещён в ПередЗаписью, а не в ОбработкаПроверкиЗаполнения, стандартная кнопка «Проверить заполнение» его не увидит, а сообщения не попадут в общий список ошибок. Ещё одна ловушка — проверять Количество() у табличной части, которая на форме отфильтрована: пользователь видит пустую таблицу, а в объекте строки есть. Проверять нужно данные объекта, а не отображение.
Наконец, при программной записи документов из обработок разработчики иногда забывают, что проверка заполнения не выполняется при вызове Записать() без проведения в некоторых сценариях, либо отключают проверки ради скорости загрузки. Для загрузочных обработок осознанно решайте: либо гарантировать качество данных на входе, либо вызывать проверку явно.
Проверка результата и границы самостоятельной работы
После внедрения кода проверьте три сценария. Первый: интерактивное проведение документа с пустой табличной частью — должна появиться ошибка, документ не проводится. Второй: заполните одну строку с пропущенным обязательным полем — сообщение должно указывать на конкретную строку и поле. Третий: запишите документ программно из консоли кода или обработки — проверка из модуля объекта должна сработать и здесь.
Изменения в модуле объекта требуют обновления конфигурации базы данных. Перед обновлением на рабочей базе сделайте резервную копию — особенно если правки затрагивают документы, по которым уже есть движения. Если конфигурация типовая и находится на поддержке, прямая правка модуля снимет её с полной поддержки; в этом случае рассмотрите расширение конфигурации — обработчик ОбработкаПроверкиЗаполнения можно добавить и через расширение.
Как проверить результат
Ошибка, документ не проводится
Документ проводится с пустой табличной частью
Курсор встаёт в нужную ячейку нужной строки
Подсвечивается другая строка или ничего не происходит
Проверка срабатывает так же, как интерактивно
Документ записывается в обход проверки
FAQ
Как проверить табличную часть на форме без записи документа?
Используйте обработчик команды формы: пройдите циклом по Элементы.Товары или по данным Объект.Товары и выведите сообщения через СообщениеПользователю. Для автоматической подсветки пустых ячеек удобно условное оформление формы — оно работает без кода проверки.
Чем отличается Количество() = 0 от проверки через ПустаяСтрока?
Функция ПустаяСтрока() проверяет строковое значение, а не коллекцию, и для табличной части не применяется. Пустоту табличной части определяют только по числу строк — методом Количество().
Как проверить табличную часть у ещё не записанного документа запросом?
Незаписанного объекта в базе нет, поэтому запрос по ссылке невозможен. Выгрузите табличную часть методом Выгрузить() в таблицу значений и передайте её в запрос как параметр — дальше доступны группировки и соединения с реальными таблицами базы.
Можно ли запретить проведение без строк без программирования?
Частично: для отдельных реквизитов табличной части в конфигураторе есть свойство «Проверка заполнения» со значением «Выдавать ошибку». Но запрет на полностью пустую табличную часть штатными свойствами не настраивается — нужен код в ОбработкаПроверкиЗаполнения.
Почему сообщение об ошибке подсвечивает не ту строку?
В пути поля используется индекс с нуля, а свойство НомерСтроки начинается с единицы. Стройте путь как "Товары[" + (НомерСтроки - 1) + "].ИмяРеквизита" и не забудьте вызвать УстановитьДанные(Объект) у сообщения.
Как проверить табличные части сразу нескольких видов документов?
Создайте подписку на событие ОбработкаПроверкиЗаполнения, укажите нужные типы документов в источнике и напишите общий обработчик в общем модуле. Имя табличной части и список обязательных полей можно задавать через условия по типу объекта.
Что важно запомнить
Проверку заполнения табличной части размещайте в ОбработкаПроверкиЗаполнения модуля объекта: Количество() — для пустоты, цикл или запрос — для содержимого строк. Сообщения привязывайте к полю с учётом индекса с нуля, а перед обновлением рабочей базы делайте резервную копию и тестируйте код на копии.