Работа с таблицами в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются как разработчики, так и опытные пользователи. Нередко требуется узнать количество строк в табличной части документа, справочника или результата запроса — будь то для отчетности, проверки данных или оптимизации кода. На первый взгляд задача кажется тривиальной, но в зависимости от контекста (версия платформы, тип таблицы, наличие отборов) подходы могут кардинально отличаться.
В этой статье мы разберем 5 основных способов получения количества строк — от элементарных методов для новичков до продвинутых техник с использованием Запросов и объектной модели. Особое внимание уделим нюансам: почему Количество() иногда возвращает неверное значение, как учитывать отборы и группировки, и какие методы работают быстрее на больших объемах данных. Если вы когда-либо сталкивались с тем, что количество строк в таблице на форме не совпадает с реальным числом записей в базе, эта инструкция поможет разобраться в причинах и найти решение.
1. Простейший способ: метод Количество() для таблиц на форме
Начнем с самого очевидного варианта — использования встроенного метода Количество(). Он подходит для таблиц, которые отображаются на формах (например, табличные части документов или справочников). Этот метод возвращает количество видимых строк, учитывая текущие отборы и фильтры, примененные пользователем.
Пример кода для таблицы на форме документа:
КоличествоСтрок = ЭлементыФормы.ТабличнаяЧастьТовары.Количество();
Важно понимать ограничения этого метода:
- 🔹 Работает только с таблицами, привязанными к элементам формы. Для программных таблиц (
ТаблицаЗначенийилиТаблицаДокумента) нужен другой подход. - 🔹 Учитывает только те строки, которые прошли клиентские отборы. Если на сервере данные фильтруются иначе, результат может отличаться.
- 🔹 Не работает с динамическими списками — для них требуется отдельная логика (см. раздел 3).
⚠️ Внимание: Если таблица на форме имеет иерархический вид (например, с группировками по складам), методКоличество()вернет количество визуальных строк, включая заголовки групп. Чтобы получить только данные, используйтеЭлементыФормы.Таблица.Данные.Количество().
2. Работа с ТаблицаЗначений и ТаблицаДокумента
Если вам нужно посчитать строки в программной таблице (например, ТаблицаЗначений или ТаблицаДокумента), используйте одноименный метод этих объектов. В отличие от таблиц на форме, здесь нет привязки к визуальному представлению — метод всегда возвращает фактическое количество строк в коллекции.
Примеры:
// Для ТаблицыЗначений
ТаблицаТоваров = Новый ТаблицаЗначений;
ТаблицаТоваров.Колонки.Добавить("Наименование");
ТаблицаТоваров.Колонки.Добавить("Количество");
ТаблицаТоваров.Добавить();
ТаблицаТоваров.Добавить();
КоличествоСтрок = ТаблицаТоваров.Количество(); // Вернет 2
// Для табличной части документа (серверный контекст)
КоличествоСтрок = Документ.Товары.Количество();
Особенности работы с этими объектами:
- 📌
ТаблицаЗначений.Количество()— самый быстрый метод для программных таблиц, так как не требует обращения к базе данных. - 📌 Для
ТаблицаДокумента(например,Документ.Товары) результат зависит от прав пользователя: если у него нет прав на чтение некоторых строк, они не будут учтены. - 📌 Если таблица пустая, метод вернет
0, а неНеопределено.
Чтобы ускорить работу с большими таблицами (10 000+ строк), предварительно отключите автоматический расчет итогов с помощью ТаблицаЗначений.Итоги.Очистить(). Это сократит время выполнения Количество() на 20-30%.
3. Подсчет строк в динамических списках
Динамические списки — это особый тип таблиц в 1С, который подгружает данные порциями (пагинация) и поддерживает серверные отборы. Здесь метод Количество() работать не будет, так как на клиенте отображается только часть данных. Чтобы получить полное количество строк, нужно использовать свойство ВыбратьКоличество().
Пример для динамического списка на форме:
ДинамическийСписок = ЭлементыФормы.СписокТоваров.Список;
КоличествоСтрок = ДинамическийСписок.ВыбратьКоличество();
Ключевые моменты:
| Метод | Описание | Пример результата |
|---|---|---|
ВыбратьКоличество() |
Возвращает общее количество строк с учетом всех отборов, даже если они не загружены на клиент. | 150 (если в базе 150 строк, соответствующих отбору) |
Количество() |
Возвращает количество строк, загруженных на клиент в текущей порции. | 20 (если на странице отображается 20 строк) |
ПолучитьЭлементы() |
Возвращает массив всех элементов списка (ресурсоемко!). | Массив из 150 элементов |
⚠️ Внимание: МетодВыбратьКоличество()выполняет дополнительный запрос к базе данных. Если динамический список уже имеет отборы, они будут учтены автоматически. Однако если отборы меняются динамически (например, при изменении фильтров пользователем), результат может устареть. В таких случаях используйте событиеПриИзмененииОтборадля пересчета.
4. Использование запросов для подсчета строк
Когда нужно посчитать строки в реальной таблице базы данных (например, в регистре накопления или документе), самый надежный способ — использовать Запрос. Этот метод универсален, работает на сервере и учитывает все возможные отборы, включая права доступа.
Базовый пример:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК КоличествоСтрок
|ИЗ
| Документ.ЗаказПокупателя КАК Заказ
|ГДЕ
| Заказ.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ТекущаяДата()));
Результат = Запрос.Выполнить();
КоличествоСтрок = Результат.Выбрать().КоличествоСтрок();
Преимущества этого подхода:
- 🛠️ Работает с любыми таблицами базы: документы, справочники, регистры, последовательности.
- 🛠️ Поддерживает сложные отборы, включая вложенные запросы и объединения (
ОБЪЕДИНИТЬ). - 🛠️ Учитывает права доступа текущего пользователя (в отличие от прямых обращений к таблицам).
Для ускорения запросов на больших объемах данных используйте:
Использовать индексированные поля в условиях (например, Ссылка вместо Наименование)
Заменять КОЛИЧЕСТВО(*) на КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Поле), если нужны уникальные значения
Избегать ПОМЕСТИТЬ и ВРЕМЕННЫЕ ТАБЛИЦЫ без необходимости
Применять ИНДЕКСИРОВАТЬ ПО для часто используемых полей-->
⚠️ Внимание: Если в запросе используются виртуальные таблицы (например,РегистрНакопления.ОстаткиИОбороты), результатКОЛИЧЕСТВО(*)может отличаться от ожидаемого из-за особенностей хранения данных в 1С. Например, для регистра накопления с периодичностью "По дням" количество строк будет равно числу уникальных комбинаций измерений, а не физических записей.
Что делать, если запрос выполняется слишком долго?
Если запрос на подсчет строк (КОЛИЧЕСТВО(*)) выполняется более 5 секунд, попробуйте следующие шаги:
1. Разбейте запрос на части: сначала получите идентификаторы документов, затем посчитайте их количество.
2. Используйте временные таблицы для промежуточных результатов:
ВЫБРАТЬ РАЗРЕШЕННЫЕ Документ.ЗаказПокупателя.Ссылка КАК Ссылка ПОМЕСТИТЬ ВТДокументы
ВЫБРАТЬ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Ссылка) ИЗ ВТДокументы
3. Проверьте план выполнения запроса в конфигураторе (меню Администрирование → Тестирование и исправление → План запроса). Часто проблема кроется в отсутствии индексов на полях, используемых в условиях ГДЕ.
5. Альтернативные методы: обход коллекций и рефлексия
В редких случаях стандартные методы недоступны или не подходят. Тогда можно воспользоваться альтернативными подходами, такими как обход коллекций в цикле или использование рефлексии (для опытных разработчиков).
Способ 1: Обход в цикле
Если таблица небольшая, можно просто перебрать ее элементы:
Счетчик = 0;
Для Каждого Строка Из ТаблицаЗначений Цикл
Счетчик = Счетчик + 1;
КонецЦикла;
Этот метод неэффективен для больших таблиц (10 000+ строк), но полезен, если нужно одновременно проверять условия для каждой строки.
Способ 2: Рефлексия (только для опытных)
С помощью механизма рефлексии можно получить доступ к внутренним свойствам объектов. Например, так можно узнать количество строк в ДинамическомСписке без вызова ВыбратьКоличество():
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
ДанныеСписка = ЭлементыФормы.СписокТоваров.Список.ПолучитьДанные(МенеджерВременныхТаблиц);
КоличествоСтрок = ДанныеСписка.Выбрать().Количество();
⚠️ Внимание: Использование рефлексии и недокументированных методов (например, ПолучитьДанные()) может привести к нестабильной работе при обновлении платформы. Такой код следует тщательно тестировать и документировать. В большинстве случаев лучше обойтись стандартными методами.
6. Частые ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с неожиданными результатами при подсчете строк. Рассмотрим типичные ошибки и способы их решения.
Ошибка 1: Несовпадение количества строк в таблице на форме и в базе
Если ЭлементыФормы.Таблица.Количество() возвращает одно значение, а запрос к базе — другое, причины могут быть следующими:
- 🔍 На форму выгружаются не все строки (например, из-за отбора по дате или статусу).
- 🔍 Пользователь применил клиентский фильтр (например, по наименованию товара).
- 🔍 В таблице есть скрытые строки (группировки, итоги).
Решение: используйте ЭлементыФормы.Таблица.Данные.Количество() для получения данных без учета визуальных эффектов.
Ошибка 2: Запрос возвращает 0 строк при явном наличии данных
Частая причина — неверные параметры или права доступа. Проверьте:
- 🔐 У пользователя есть права на чтение данных (меню
Администрирование → Пользователи). - 📅 Параметры запроса (например, даты) корректны. Используйте
Сообщить(Запрос.ТекстЗапроса)для отладки. - 🔄 Если используете виртуальные таблицы, убедитесь, что период актуален (например, для
ОстаткиИОбороты).
Ошибка 3: Медленная работа КОЛИЧЕСТВО(*) на больших таблицах
Если запрос выполняется более 1-2 секунд, оптимизируйте его:
- ⚡ Замените
КОЛИЧЕСТВО(*)наКОЛИЧЕСТВО(Поле), если не нужны все строки. - ⚡ Добавьте
ИНДЕКСИРОВАТЬ ПОдля полей в условияхГДЕ. - ⚡ Разбейте запрос на части (например, сначала получите ссылки, затем посчитайте их).
FAQ: Ответы на частые вопросы
Как посчитать строки в таблице с группировкой?
Если таблица на форме сгруппирована (например, по складам), метод Количество() вернет количество визуальных строк, включая заголовки групп. Чтобы получить только данные:
- Используйте
ЭлементыФормы.Таблица.Данные.Количество(). - Или обнулите группировку перед подсчетом:
ЭлементыФормы.Таблица.Группировки.Очистить().
Для запросов с ГРУППИРОВКА ПО количество строк будет равно числу уникальных групп.
Почему ТаблицаЗначений.Количество() работает быстрее, чем запрос?
ТаблицаЗначений.Количество() оперирует данными, уже загруженными в память, тогда как запрос обращается к базе данных. Если таблица содержит 10 000 строк, метод вернет результат мгновенно, а запрос может выполняться дольше из-за:
- Сетевых задержек (если база на сервере).
- Блокировок таблиц другими пользователями.
- Отсутствия индексов на полях в условиях
ГДЕ.
Можно ли получить количество строк в таблице без прав на чтение?
Нет. В 1С:Предприятие права доступа проверяются на уровне данных. Если у пользователя нет прав на чтение хотя бы одной строки, результатом будет 0 (для запросов) или пустая коллекция (для ТаблицаЗначений). Обойти это ограничение можно только через привилегированный режим или изменение ролей.
Как посчитать строки в таблице с учетом отборов на СКД?
Если используете Систему компоновки данных (СКД), количество строк можно получить через настройки компоновщика:
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
КомпоновщикМакета.Инициализировать(СхемаКомпоновкиДанных);
Настройки = КомпоновщикМакета.ПолучитьНастройкиПоУмолчанию();
// Примените отборы через Настройки.Отбор
Результат = КомпоновщикМакета.Выполнить(Настройки);
КоличествоСтрок = Результат.Вывод.КоличествоСтрок();
Обратите внимание: этот метод учитывает все настройки СКД, включая отборы, условное оформление и группировки.
Есть ли разница между Количество() и ВГруппах()?
Да, эти методы возвращают разные значения:
Количество()— общее число строк, включая заголовки групп.ВГруппах()— количество групп верхнего уровня (только для иерархических таблиц).
Пример: если в таблице 3 группы по 5 строк каждая, то Количество() вернет 18 (3 заголовка + 15 строк), а ВГруппах() — 3.