Работа с таблицами в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются как разработчики, так и обычные пользователи. Нередко требуется узнать, сколько строк содержится в табличной части документа, динамическом списке или результате запроса. На первый взгляд задача простая, но в зависимости от контекста и типа таблицы подходы могут кардинально отличаться.
В этой статье мы разберём 5 проверенных способов подсчёта строк в 1С 8.3 и 1С 8.2, включая встроенные методы платформы, SQL-запросы, программный код на встроенном языке, а также нюансы работы с фильтрами и группировками. Особое внимание уделим производительности каждого метода — это критично при работе с большими объёмами данных.
Независимо от того, нужно ли вам просто вывести количество строк на форму или автоматизировать обработку данных в фоновом режиме, здесь вы найдёте готовые решения с примерами кода и пояснениями.
1. Встроенные методы платформы: Количество() и Count()
Самый простой и интуитивно понятный способ — использовать стандартные методы 1С, которые доступны для большинства коллекций, включая таблицы значений, табличные части документов и динамические списки. Эти методы оптимизированы платформой и работают максимально быстро.
Для таблицы значений или табличной части документа применяется метод Количество():
КоличествоСтрок = ТаблицаЗначений.Количество();
Если вы работаете с динамическим списком (например, в форме списка справочника), используйте свойство Count коллекции ВыбранныеСтроки:
КоличествоСтрок = ЭлементыФормы.Список.ВыбранныеСтроки.Count();
- ✅ Плюсы: минимальный код, высокая скорость выполнения, не требует прав на изменение данных.
- ⚠️ Ограничения: не учитывает фильтры, применённые к динамическому списку (вернёт общее количество строк, а не отфильтрованных).
- 🔄 Альтернатива: для динамических списков с фильтрами лучше использовать метод
ПолучитьДанные()(см. раздел 3).
Если вам нужно посчитать строки в табличной части документа до его записи, используйте метод Количество() непосредственно перед сохранением. После записи количество строк может измениться из-за обработчиков событий!
2. Подсчёт строк через запрос на языке 1С
Когда требуется гибкость — например, посчитать строки с учётом условий или агрегации — на помощь приходят запросы на встроенном языке. Этот метод универсален и работает с любыми источниками данных: справочниками, документами, регистрами.
Базовый синтаксис для подсчёта всех строк в таблице:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК КоличествоСтрок
|ИЗ
| Документ.ЗаказыПокупателей КАК Заказы";
Результат = Запрос.Выполнить();
КоличествоСтрок = Результат.Выбрать().КоличествоСтрок;
Если нужно посчитать строки с учётом фильтра (например, только оплаченные заказы за текущий месяц), добавьте условие в секцию ГДЕ:
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(*) КАК КоличествоСтрок
|ИЗ
| Документ.ЗаказыПокупателей КАК Заказы
|ГДЕ
| Заказы.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца
| И Заказы.Оплачен = ИСТИНА";
Как ускорить выполнение запроса?
Для больших таблиц (100 000+ строк) используйте индексированные поля в условиях фильтрации. Например, если в запросе есть условие по полю Дата, убедитесь, что оно проиндексировано в конфигураторе. Также избегайте функций в условиях (например, ГОД(Заказы.Дата) = 2023) — они блокируют использование индексов.
| Тип источника данных | Пример запроса | Особенности |
|---|---|---|
| Справочник | ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Справочник.Номенклатура |
Подсчитывает все элементы, включая помеченные на удаление (если не добавлено условие ПометкаУдаления = ЛОЖЬ) |
| Документ | ВЫБРАТЬ КОЛИЧЕСТВО(*) ИЗ Документ.РеализацияТоваровУслуг ГДЕ Дата > &НачалоПериода |
Можно фильтровать по реквизитам шапки и табличных частей |
| Регистр накопления | ВЫБРАТЬ КОЛИЧЕСТВО(RАЗЛИЧНЫЕ Номенклатура) ИЗ РегистрНакопления.ОстаткиТоваров |
Для регистров часто требуется агрегация (например, КОЛИЧЕСТВО(RАЗЛИЧНЫЕ)) |
3. Работа с динамическими списками: метод ПолучитьДанные()
Динамические списки в 1С — это мощный инструмент для отображения данных с возможностью фильтрации, сортировки и группировки. Однако стандартное свойство Count возвращает только количество видимых строк на экране, а не всех данных, соответствующих фильтру.
Чтобы получить точное количество строк с учётом всех применённых фильтров, используйте метод ПолучитьДанные():
ДанныеСписка = ЭлементыФормы.СписокТоваров.ПолучитьДанные();
КоличествоСтрок = ДанныеСписка.Количество();
Этот метод возвращает таблицу значений с данными, отфильтрованными согласно текущим настройкам динамического списка. Важно учитывать, что:
- 🔍 Фильтры применяются: результат будет соответствовать текущим условиям отбора в списке.
- ⚡ Производительность: при большом количестве данных выполнение может занять время (особенно если в списке включены группировки).
- 📊 Группировки: если в динамическом списке настроены группировки, метод вернёт количество групп, а не строк. Чтобы получить детализированные данные, отключите группировку программно:
ЭлементыФормы.СписокТоваров.Группировки.Очистить();
ДанныеСписка = ЭлементыФормы.СписокТоваров.ПолучитьДанные();
4. Программный обход строк: когда стандартные методы не подходят
В некоторых случаях стандартные методы не дают нужного результата. Например, если требуется посчитать строки с учётом условной логики (например, только те, где сумма больше определённого значения) или когда работа ведётся с нетиповыми коллекциями (например, результатом внешней обработки).
В таких ситуациях поможет цикл по строкам с ручным подсчётом. Пример для таблицы значений:
Счётчик = 0;
Для Каждого Строка Из ТаблицаЗначений Цикл
Если Строка.Сумма > 1000 Тогда
Счётчик = Счётчик + 1;
КонецЕсли;
КонецЦикла;
Для динамических списков можно обойти коллекцию ВыбранныеСтроки:
Счётчик = 0;
Для Каждого Строка Из ЭлементыФормы.Список.ВыбранныеСтроки Цикл
Если НЕ Строка.ПометкаУдаления Тогда
Счётчик = Счётчик + 1;
КонецЕсли;
КонецЦикла;
Инициализируйте счётчик до цикла (Счётчик = 0)
Учитывайте пометки удаления, если работаете с справочниками/документами
Для больших таблиц (>10 000 строк) используйте Прервать для оптимизации
Проверьте права доступа к данным-->
Критичный нюанс: при обходе динамического списка через ВыбранныеСтроки учитываются только строки, видимые на текущей странице (если включена постраничная навигация). Чтобы обработать все данные, сначала получите их через ПолучитьДанные().
5. Подсчёт строк в табличных частях документов и справочников
Табличные части — это отдельный случай, так как они могут содержать не только данные, но и пустые строки, а также строки, помеченные на удаление. Рассмотрим нюансы для разных сценариев.
Способ 1. Подсчёт всех строк (включая пустые):
КоличествоСтрок = ДокументОбъект.ТабличнаяЧастьТовары.Количество();
Способ 2. Подсчёт только заполненных строк (игнорируем пустые):
Счётчик = 0;
Для Каждого Строка Из ДокументОбъект.ТабличнаяЧастьТовары Цикл
Если НЕ ЗначениеЗаполнено(Строка.Номенклатура) Тогда
Продолжить;
КонецЕсли;
Счётчик = Счётчик + 1;
КонецЦикла;
Способ 3. Подсчёт с учётом пометок удаления:
КоличествоСтрок = ДокументОбъект.ТабличнаяЧастьТовары.Количество();
КоличествоУдалённых = 0;
Для Каждого Строка Из ДокументОбъект.ТабличнаяЧастьТовары Цикл
Если Строка.ПометкаУдаления Тогда
КоличествоУдалённых = КоличествоУдалённых + 1;
КонецЕсли;
КонецЦикла;
ФактическоеКоличество = КоличествоСтрок - КоличествоУдалённых;
При работе с табличными частями документов всегда проверяйте настройку "Автозаполнение" — если она включена, платформа может автоматически добавлять пустые строки, что исказит результат подсчёта.
⚠️ Внимание: В некоторых конфигурациях (например, 1С:ERP или 1С:УТ 11) табличные части могут иметь сложную структуру с вложенными таблицами. В этом случае для точного подсчёта используйте рекурсивный обход или специализированные функции модуля объекта.
6. Оптимизация производительности: что делать с большими таблицами
Если таблица содержит десятки или сотни тысяч строк, стандартные методы подсчёта могут работать медленно. В таких случаях требуются специальные подходы:
- 🚀 Индексы: Для запросов к базам данных (SQL) убедитесь, что поля, используемые в условиях фильтрации, проиндексированы. В 1С индексы настраиваются в конфигураторе для реквизитов справочников и документов.
- 📊 Агрегация на стороне СУБД: Если вы работаете с внешней базой (например, PostgreSQL или MS SQL), перенесите подсчёт на сторону сервера с помощью конструкции
ВЫБРАТЬ КОЛИЧЕСТВО(*)без выгрузки всех данных. - ⏳ Асинхронные операции: Для фоновых задач используйте механизм
ФоновыеЗадания, чтобы не блокировать интерфейс пользователя:
ФоновоеЗадание = ФоновыеЗадания.Создать("ПодсчётСтрокВФоне");
ФоновоеЗадание.Параметры.Таблица = МояТаблица;
ФоновоеЗадание.Выполнить();
Для динамических списков с большим количеством данных отключите ненужные колонки и группировки перед вызовом ПолучитьДанные():
ЭлементыФормы.Список.Колонки.Очистить(); // Оставляем только необходимые колонки
ЭлементыФормы.Список.Группировки.Очистить();
Данные = ЭлементыФормы.Список.ПолучитьДанные();
⚠️ Внимание: В клиент-серверном варианте работы 1С подсчёт строк в больших таблицах может блокировать другие сеансы. Используйте транзакции с минимальным уровнем изоляции или выполняйте операции в непиковые часы.
FAQ: Частые вопросы о подсчёте строк в 1С
Можно ли посчитать строки в таблице 1С без программирования?
Да, в некоторых случаях. Например, в динамическом списке количество строк отображается в статусной строке формы (внизу окна). Для табличных частей документов можно использовать кнопку "Итоги" на панели инструментов, если она настроена в конфигураторе.
Однако для гибких условий (фильтры, группировки) без программирования не обойтись.
Почему метод Количество() возвращает неверное значение?
Частые причины:
- В таблице есть пустые строки (например, в табличной части документа с включённым автозаполнением).
- Строки помечены на удаление, но ещё не удалены физически.
- Вы работаете с динамическим списком, где метод возвращает только видимые строки (без учёта фильтров).
Решение: используйте программный обход строк с проверкой условий (см. раздел 4).
Как посчитать уникальные значения в колонке таблицы?
Используйте запрос с конструкцией ВЫБРАТЬ РАЗЛИЧНЫЕ:
Запрос.Текст =
"ВЫБРАТЬ
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Номенклатура) КАК КоличествоУникальных
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары";
Для таблицы значений подойдёт такой код:
УникальныеЗначения = Новый Массив;
Для Каждого Строка Из ТаблицаЗначений Цикл
Если НЕ УникальныеЗначения.Найти(Строка.Номенклатура) Тогда
УникальныеЗначения.Добавить(Строка.Номенклатура);
КонецЕсли;
КонецЦикла;
КоличествоУникальных = УникальныеЗначения.Количество();
Можно ли посчитать строки в таблице 1С через SQL-запрос напрямую?
Технически да, но не рекомендуется в большинстве случаев. Платформа 1С абстрагирует работу с базой данных, и прямой SQL может:
- Нарушить целостность данных при некорректных запросах.
- Не учитывать бизнес-логику конфигурации (например, права доступа).
- Сломаться при обновлении платформы (изменении структуры таблиц).
Исключение: если вы разрабатываете внешнюю обработку для администрирования базы и точно знаете структуру таблиц. Пример для MS SQL:
ВЫБРАТЬ COUNT(*) ИЗ _Document83 AS D
WHERE D._Reference83_ID = 'Документ.ЗаказПокупателя';
Для безопасного использования оберните SQL в транзакцию и проверьте права:
Если НЕ Метаданные.Документы.ЗаказыПокупателей.Права.Чтение Тогда
Возврат;
КонецЕсли;
Как посчитать строки в таблице на форме в 1С 8.2 и 8.3: есть ли различия?
Основные различия связаны с динамическими списками:
- 1С 8.2: метод
ПолучитьДанные()может работать медленнее из-за устаревшей архитектуры. - 1С 8.3: добавлена поддержка асинхронного получения данных (метод
ПолучитьДанныеАсинх()), что ускоряет работу с большими объёмами. - 1С 8.3.20+: оптимизирована работа с группировками в динамических списках.
Для остальных методов (Количество(), запросы, программный обход) разницы нет.