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