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

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

Как получить количество строк в таблице 1С

Способы узнать количество строк в таблице 1С: функция Количество(), запрос с КОЛИЧЕСТВО, выборка данных. Примеры кода, ошибки и советы для разработчиков.

Подсчёт строк — одна из самых частых задач при работе с 1С. В зависимости от того, где находятся данные, применяются разные методы: для табличной части документа используется метод Количество(), для таблицы значений — тот же метод, а для данных в базе — запрос с агрегатной функцией КОЛИЧЕСТВО.

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

Ниже разобраны все основные сценарии: табличная часть документа, таблица значений, запрос к базе, динамический список и подсчёт с условиями. Для каждого случая приведён рабочий код и указаны ограничения.

Подсчёт строк табличной части документа

Табличная часть документа или справочника — это коллекция строк, у которой есть встроенный метод Количество(). Он возвращает целое число — текущее число строк в табличной части.

ЧислоСтрок = Объект.Товары.Количество();

Если ЧислоСтрок = 0 Тогда

Сообщить("Табличная часть пустая");

КонецЕсли;

Метод работает мгновенно, потому что количество строк хранится в самой коллекции и не требует перебора. Это самый быстрый способ для объектов, уже загруженных в память.

Обратите внимание: метод применяется к табличной части объекта, открытого для чтения или записи. Если у вас есть только ссылка на документ, сначала получите объект через Ссылка.ПолучитьОбъект() — но учитывайте, что это дорогая операция, и для простого подсчёта строк лучше использовать запрос.

Количество строк в таблице значений

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

ТЗ = Новый ТаблицаЗначений;

// ... заполнение таблицы ...

ВсегоСтрок = ТЗ.Количество();

Если нужно посчитать не все строки, а только те, что соответствуют условию, используйте метод НайтиСтроки() с структурой отбора. Метод возвращает массив строк, у которого можно взять количество.

Отбор = Новый Структура("Склад", СкладОтгрузки);

НайденныеСтроки = ТЗ.НайтиСтроки(Отбор);

КоличествоПоСкладу = НайденныеСтроки.Количество();

Для подсчёта строк с непустым значением в конкретной колонке удобно свернуть таблицу методом Свернуть() или перебрать с проверкой ЗначениеЗаполнено(). Выбор зависит от того, нужна ли сама таблица после операции.

Подсчёт через запрос к базе данных

Когда данные находятся в базе, а не в памяти, правильный инструмент — запрос с агрегатной функцией КОЛИЧЕСТВО. Вариант КОЛИЧЕСТВО(*) считает все строки результата, КОЛИЧЕСТВО(Поле) — строки, где поле не NULL, а КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле) — количество уникальных значений.

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

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

"ВЫБРАТЬ

| КОЛИЧЕСТВО(*) КАК ЧислоСтрок

|ИЗ

| Документ.РеализацияТоваровУслуг.Товары КАК Товары

|ГДЕ

| Товары.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ЧислоСтрок = Выборка.ЧислоСтрок;

КонецЕсли;

Такой запрос позволяет узнать количество строк табличной части документа без получения объекта целиком. Это критично при массовой обработке: вместо чтения сотен объектов выполняется один лёгкий запрос.

Различие между вариантами функции важно учитывать при работе с соединениями таблиц. Если левое соединение не нашло пару, поля присоединённой таблицы будут NULL, и КОЛИЧЕСТВО(Поле) их не посчитает, а КОЛИЧЕСТВО(*) — посчитает.

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

КОЛИЧЕСТВО(*)

Считает все строки результата, включая строки с NULL. Подходит для общего подсчёта.

КОЛИЧЕСТВО(Поле)

Считает только строки, где поле заполнено. Осторожно при левых соединениях.

КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле)

Считает уникальные значения. Полезно для подсчёта разных контрагентов, товаров и т.п.

Подсчёт строк в результате запроса и выборке

Если запрос уже выполнен и результат выгружен в таблицу значений, количество строк получают тем же методом Количество():

Результат = Запрос.Выполнить();

ТЗ = Результат.Выгрузить();

ЧислоСтрок = ТЗ.Количество();

У самого результата запроса метода «количество» нет. Если выгружать таблицу не хочется, можно проверить пустоту результата методом Пустой() — он отвечает на вопрос «есть ли хотя бы одна строка» без выгрузки данных.

Выборка данных (объект типа «ВыборкаИзРезультатаЗапроса») также не хранит число строк. Перебор выборки с счётчиком — рабочий, но неоптимальный вариант. Если нужно и количество, и сами данные, выгрузите результат в таблицу значений один раз и работайте с ней.

Количество строк в динамическом списке и на форме

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

Если нужно показать пользователю количество записей, соответствующих отбору списка, выполните отдельный запрос с КОЛИЧЕСТВО(*) по той же таблице и с теми же условиями. Условия отбора можно взять из настроек динамического списка.

Для таблицы формы, связанной с таблицей значений (реквизит формы типа «ТаблицаЗначений»), количество строк доступно напрямую через Объект.ИмяТаблицы.Количество() на сервере или через данные формы на клиенте.

Типичные ошибки
01
Перебор выборки в цикле со счётчиком вместо КОЛИЧЕСТВО(<em>) — лишний код и потеря производительности
02
Вызов ПолучитьОбъект() ради подсчёта строк табличной части — тяжёлая операция, особенно в цикле
03
Ожидание метода Количество() у результата запроса — его там нет, нужна выгрузка в таблицу значений
04
Путаница между КОЛИЧЕСТВО(</em>) и КОЛИЧЕСТВО(Поле) при соединениях — NULL-значения дают разные результаты

Производительность и выбор способа

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

На больших таблицах (миллионы записей регистров) даже КОЛИЧЕСТВО(*) может выполняться заметное время, если наложены сложные условия по неиндексированным полям. В таких случаях проверяйте план запроса и при необходимости добавляйте индексы или пересматривайте условия отбора.

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

Маршрут решения

Как выбрать действие

Данные уже в таблице значений или табличной части объектаИспользуйте метод Количество()
Данные в базе, объект не загруженВыполните запрос с КОЛИЧЕСТВО(*)
Нужно только узнать, есть ли строкиИспользуйте Результат.Пустой() без подсчёта
Нужны строки по условию в таблице значенийПримените НайтиСтроки() и возьмите Количество() у массива
Нужно число записей динамического спискаВыполните отдельный запрос с теми же отборами

Проверка результата и отладка

Убедиться в корректности подсчёта можно несколькими способами. Для табличной части откройте документ в режиме предприятия и сравните число строк визуально. Для запроса — выполните его в консоли запросов и сравните с результатом без группировки.

Полезный приём при отладке: временно замените КОЛИЧЕСТВО(*) на выборку самих строк с ограничением и проверьте, какие данные попадают под условия. Часто расхождения объясняются неправильными параметрами виртуальных таблиц или лишними соединениями, размножающими строки.

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

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

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

Число строк табличной части
Норма

Совпадает с числом строк в форме документа

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

Запрос возвращает больше — проверьте соединения

Запрос с КОЛИЧЕСТВО(*)
Норма

Одна строка результата с числом

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

Несколько строк — в запросе есть лишняя группировка

Подсчёт с условием
Норма

Результат меньше или равен общему числу строк

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

Результат больше общего — ошибка в логике отбора

Итог

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

Метод Количество() — для таблиц значений и табличных частей в памяти, КОЛИЧЕСТВО(*) в запросе — для данных в базе, Пустой() — если нужен только факт наличия строк. Не перебирайте данные циклом ради подсчёта и не получайте объект документа, если достаточно запроса.

Частые вопросы

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

Используйте запрос к табличной части с группировкой по ссылке: ВЫБРАТЬ Ссылка, КОЛИЧЕСТВО(*) ИЗ Документ.Реализация.Товары ГДЕ Ссылка В (&Список) СГРУППИРОВАТЬ ПО Ссылка. Получите по одной строке на каждый документ без получения объектов.

Чем отличается Количество() у таблицы значений от подсчёта в запросе?

Метод Количество() работает с данными, уже загруженными в память, и выполняется мгновенно. Запрос с КОЛИЧЕСТВО обращается к базе данных. Если данные ещё в базе, выгружать их ради подсчёта невыгодно — считайте запросом.

Почему КОЛИЧЕСТВО(Поле) вернуло меньше, чем КОЛИЧЕСТВО()?

Функция КОЛИЧЕСТВО(Поле) не учитывает строки, где поле равно NULL. Такое бывает при левых соединениях, когда для части строк не нашлось пары в присоединяемой таблице. Проверьте соединения или используйте КОЛИЧЕСТВО().

Можно ли узнать количество строк результата запроса без выгрузки?

Нет, у результата запроса нет такого свойства. Либо выгрузите результат в таблицу значений и возьмите Количество(), либо добавьте в сам запрос агрегатную функцию КОЛИЧЕСТВО. Для проверки наличия строк достаточно метода Пустой().

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

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

Тормозит запрос с КОЛИЧЕСТВО(*) по большому регистру. Что делать?

Проверьте условия отбора: фильтрация по неиндексированным полям заставляет СУБД сканировать всю таблицу. Сузьте период, используйте индексированные измерения, а при регулярной потребности в числе записей храните его в отдельном регистре сведений.