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