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

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

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

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

Таблица значений — универсальная структура данных встроенного языка 1С, которая хранит строки и колонки в оперативной памяти и не привязана к базе данных. Разработчик использует её для промежуточной обработки данных: выгрузки результата запроса, подготовки табличных частей, консолидации показателей из разных источников, передачи данных между процедурами.

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

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

Создание таблицы и описание колонок

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

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

ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));

ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));

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

Проверить, что колонка существует, можно через ТЗ.Колонки.Найти("Цена"): метод вернёт объект колонки или Неопределено. Это полезно в универсальных процедурах, которые получают таблицу извне и не могут гарантировать её структуру.

Добавление и изменение строк

Строки добавляются методом Добавить(), который возвращает ссылку на новую строку. Дальше значения присваиваются по именам колонок через точку. Обращение к несуществующей колонке вызовет ошибку «Поле объекта не обнаружено», поэтому имена в коде должны точно совпадать с именами при создании.

НоваяСтрока = ТЗ.Добавить();

НоваяСтрока.Номенклатура = ТекущийТовар;

НоваяСтрока.Количество = 5;

НоваяСтрока.Цена = 1200;

Если данные приходят из другой таблицы с аналогичной структурой, используйте ЗаполнитьЗначенияСвойств(НоваяСтрока, ИсходнаяСтрока) — совпадающие по именам свойства заполнятся автоматически. Для копирования всей таблицы есть метод ТЗ.Скопировать(), а для выборочного копирования — Скопировать(МассивСтрок, "Колонка1,Колонка2").

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

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

Обход строк и поиск данных

Стандартный способ обхода — цикл Для Каждого Строка Из ТЗ Цикл. Внутри цикла доступны все колонки текущей строки. Если нужен индекс, используйте классический цикл Для Сч = 0 По ТЗ.Количество() - 1 Цикл и обращайтесь к строке через ТЗ[Сч].

Для поиска одной строки подходит метод Найти(Значение, "ИмяКолонки") — он вернёт первую найденную строку или Неопределено. Когда нужны все совпадения, используйте НайтиСтроки(ПараметрыОтбора), где параметры отбора — структура с парами «колонка — значение». Этот метод возвращает массив строк, который может быть пустым.

Отбор = Новый Структура("Номенклатура", ТекущийТовар);

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

Для Каждого Строка Из НайденныеСтроки Цикл

Строка.Количество = Строка.Количество + 1;

КонецЦикла;

Поиск выполняется линейным перебором, поэтому в больших таблицах (десятки тысяч строк и больше) многократные вызовы Найти в цикле заметно тормозят код. В таких случаях добавьте индекс: ТЗ.Индексы.Добавить("Номенклатура") — поиск по проиндексированной колонке ускорится многократно.

Сортировка, итоги и свёртка

Сортировка выполняется методом Сортировать("Колонка1 Возр, Колонка2 Убыв") — направление задаётся словами Возр и Убыв, несколько колонок перечисляются через запятую. Сортировка меняет саму таблицу, а не создаёт копию.

Итог по числовой колонке считается одной строкой: СуммаИтог = ТЗ.Итог("Количество"). Для группировки с агрегацией предназначен метод Свернуть("Номенклатура", "Количество,Сумма"): он объединяет строки с одинаковыми значениями группировочных колонок и суммирует указанные числовые колонки. Остальные колонки после свёртки удаляются.

ТЗ.Свернуть("Номенклатура", "Количество,Сумма");

ТЗ.Сортировать("Сумма Убыв");

Если нужно убрать только дубликаты без суммирования, вызовите Свернуть("Номенклатура") без второго параметра. Учтите: свёртка необратимо меняет таблицу, поэтому при необходимости сохранить исходные данные сначала сделайте копию методом Скопировать().

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

Свернуть()

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

Запрос с СГРУППИРОВАТЬ ПО

Гибкая агрегация (сумма, среднее, минимум, максимум, количество) с фильтрацией. Требует передачи таблицы как параметра.

Сводная таблица через СводныеДиаграммы

Подходит для интерактивного анализа пользователем, но избыточна для программной обработки.

Передача таблицы в запрос

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

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

Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

Запрос.УстановитьПараметр("ТЗ", ТЗ);

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

"ВЫБРАТЬ

| ТЗ.Номенклатура КАК Номенклатура,

| ТЗ.Количество КАК Количество

|ПОМЕСТИТЬ ВТ_Данные

|ИЗ &ТЗ КАК ТЗ";

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

После помещения во временную таблицу данные можно соединять с регистрами и справочниками обычными соединениями запроса. Обратная операция — выгрузка результата в таблицу значений — выполняется методом Результат.Выгрузить(). Это стандартный приём, когда отчёт строится программно без схемы компоновки.

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

Типовой порядок работы с таблицей
  1. 1
    Создайте таблицу и опишите типизированные колонки
  2. 2
    Заполните строки в цикле или выгрузите результат запроса
  3. 3
    Добавьте индексы по колонкам, используемым в поиске
  4. 4
    Выполните обработку: поиск, сортировку, свёртку
  5. 5
    Передайте таблицу в запрос или в табличную часть документа
  6. 6
    Проверьте результат: количество строк и итоги по числовым колонкам

Клиент-серверные особенности и производительность

Таблица значений доступна и на клиенте, и на сервере, но передача между ними в тонком клиенте ограничена: таблицу нельзя напрямую вернуть с сервера на клиент вне контекста формы. Рабочие варианты — хранить таблицу в реквизите формы с соответствующим типом, передавать через временное хранилище (ПоместитьВоВременноеХранилище) или конвертировать в массив структур.

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

Для отладки структуры удобно вывести таблицу в табличный документ или временно добавить её как реквизит формы. Простая проверка после обработки — сравнить ТЗ.Количество() и ТЗ.Итог("Сумма") с ожидаемыми значениями: расхождение сразу укажет на потерю строк при свёртке или копировании.

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

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

Количество строк после обработки
Норма

Совпадает с ожидаемым числом записей

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

Строк меньше — вероятна лишняя свёртка или удаление в цикле

Итог по числовой колонке
Норма

Сумма соответствует контрольному значению из источника

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

Итог расходится — потеряны или продублированы строки

Типы значений в колонках
Норма

Все значения соответствуют описанию типов колонки

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

Смешение типов — поиск и сортировка будут работать некорректно

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

Чем таблица значений отличается от табличной части документа?

Табличная часть хранится в базе данных вместе с документом и сохраняется при записи. Таблица значений существует только в памяти во время выполнения кода. Часто таблицу значений используют как промежуточный буфер: обработали данные — загрузили в табличную часть методом Загрузить().

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

Используйте НайтиСтроки с параметром отбора, где значение — пустая ссылка, Неопределено или пустая строка в зависимости от типа колонки. Для составных проверок удобнее пройти таблицу циклом и проверять функцией ЗначениеЗаполнено().

Можно ли отсортировать таблицу по колонке со смешанными типами?

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

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

Напрямую передать нельзя. Поместите таблицу во временное хранилище методом ПоместитьВоВременноеХранилище и передайте адрес, либо преобразуйте таблицу в массив структур, который сериализуется свободно. В форме проще всего хранить данные в реквизите типа ТаблицаЗначений.

Почему Свернуть удалил нужные колонки?

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

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

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

Итог

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

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