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