Таблица значений в 1С 8.3: создание, заполнение, сортировка и вывод на управляемую форму

· 9 мин

Содержание

Чтобы отобразить таблицу значений в 1С на управляемой форме, создайте реквизит формы с типом ТаблицаЗначений, перетащите его в дерево элементов и на сервере перенесите данные методом ЗначениеВРеквизитФормы(ТЗ, "ИмяРеквизита"). Колонки реквизита при этом должны совпадать по именам с колонками вашей таблицы. Для быстрого просмотра без формы подойдёт табличный документ или окно вычисления выражения в отладчике.

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

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

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

&НаСервере
Функция НоваяТаблицаОстатков()

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

    Возврат ТЗ;

КонецФункции

Параметры метода Колонки.Добавить() идут в таком порядке:

№ПараметрЧто задаётОбязателен
1ИмяИмя колонки, по нему идёт обращение в кодеда
2ТипОбъект ОписаниеТиповнет
3ЗаголовокТекст в шапке при выводенет
4ШиринаШирина колонки в символахнет

Имя колонки подчиняется тем же правилам, что и имя переменной: без пробелов, не с цифры. Человеческий текст «Сумма, руб.» пишите в заголовок, а не в имя.

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

Как заполнить таблицу значений: запрос и цикл

Из результата запроса

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

&НаСервере
Функция ОстаткиПоСкладам(Дата)

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Остатки.Номенклатура КАК Номенклатура,
    |    Остатки.Склад КАК Склад,
    |    Остатки.КоличествоОстаток КАК Количество
    |ИЗ
    |    РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки";
    Запрос.УстановитьПараметр("Дата", Дата);

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

КонецФункции

Имя регистра здесь условное: подставьте регистр своей конфигурации. Псевдонимы КАК в запросе становятся именами колонок, поэтому давайте их явно.

В цикле

Когда данные приходят не из базы (файл, расчёт, ответ веб-сервиса), строки добавляют вручную:

Стр = ТЗ.Добавить();
Стр.Номенклатура = Товар;
Стр.Количество = 5;
Стр.Сумма = 1250.50;

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

Полезные методы массового заполнения

  • 📥 ЗагрузитьКолонку(Массив, "Сумма") — заливает массив значений в колонку построчно, строк должно хватать.
  • 📤 ВыгрузитьКолонку("Номенклатура") — возвращает массив значений колонки, удобно для параметра запроса В (&Список).
  • 📋 Скопировать() — полная копия; СкопироватьКолонки() — пустая таблица с той же структурой.
  • ➕ ЗаполнитьЗначения(0, "Сумма") — проставить одно значение во все строки колонки.

Типы, заголовки и ограничения колонок

Колонку после создания можно донастроить через её свойства: Имя, Заголовок, Ширина, ТипЗначения. Свойство ТипЗначения только читается, поэтому тип задают сразу при добавлении. Чтобы сменить тип, создают новую колонку, переносят значения и удаляют старую.

Квалификаторы описания типов работают как ограничения:

  • 🔢 КвалификаторыЧисла(15, 2) — 15 знаков всего, 2 после запятой. Число 1250,456 превратится в 1250,46.
  • 🔤 КвалификаторыСтроки(50) — строка обрежется до 50 символов.
  • 📅 КвалификаторыДаты(ЧастиДаты.Дата) — время отбрасывается, остаётся только дата.

Округление и обрезка происходят при присваивании, без ошибки. Это частая причина «потерянных копеек»: колонка объявлена с квалификатором (15, 0), а в неё пишут суммы с копейками.

Составной тип задаётся строкой через запятую:

Тип = Новый ОписаниеТипов("СправочникСсылка.Контрагенты, СправочникСсылка.ФизическиеЛица");
ТЗ.Колонки.Добавить("Получатель", Тип);

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

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

Сортировка

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

По умолчанию порядок возрастающий, Убыв меняет направление для конкретной колонки. Ссылки сортируются по внутреннему представлению, а не по наименованию. Если нужен алфавит по товарам, добавьте в запрос поле Номенклатура.Наименование и сортируйте по нему, либо сортируйте сразу в запросе через УПОРЯДОЧИТЬ ПО.

Отбор

Отдельного «фильтра» у таблицы значений нет, есть три приёма:

ПриёмЧто возвращаетКогда брать
НайтиСтроки(Новый Структура("Склад", Склад))Массив строк исходной таблицыПрочитать или изменить найденные строки
Скопировать(Новый Структура("Склад", Склад))Новую таблицу только с подходящими строкамиНужна отдельная таблица для вывода
Найти(Значение, "Номенклатура")Первую найденную строку или НеопределеноПроверить, есть ли значение

Отбор структурой работает только на равенство. Условия «больше», «содержит» и подобные проверяйте в цикле или переносите в запрос.

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

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

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

Удаление строк в цикле

При удалении строк обходите таблицу с конца, иначе индексы сдвигаются и часть строк пропускается:

Всего = ТЗ.Количество();
Для Сч = 1 По Всего Цикл
    Стр = ТЗ[Всего - Сч];
    Если Стр.Количество = 0 Тогда
        ТЗ.Удалить(Стр);
    КонецЕсли;
КонецЦикла;

Граница Всего запоминается до цикла, а индекс Всего - Сч пробегает от последней строки к нулевой.

Вывод таблицы значений на управляемую форму

Способ 1. Реквизит формы, созданный в конфигураторе

Подходит, когда набор колонок известен заранее.

  1. Откройте форму в конфигураторе, вкладка Реквизиты, добавьте реквизит, например ТаблицаОстатков, тип ТаблицаЗначений.
  2. Раскройте реквизит и добавьте колонки с теми же именами и типами, что в вашей ТЗ.
  3. Перетащите реквизит мышью в дерево Элементы — платформа создаст элемент «Таблица» с полями.
  4. Напишите серверную процедуру заполнения и вызовите её из клиентской команды.
&НаСервере
Процедура ЗаполнитьНаСервере()
    ТЗ = ОстаткиПоСкладам(ТекущаяДатаСеанса());
    ЗначениеВРеквизитФормы(ТЗ, "ТаблицаОстатков");
КонецПроцедуры

&НаКлиенте
Процедура Заполнить(Команда)
    ЗаполнитьНаСервере();
КонецПроцедуры

На клиенте реквизит виден как ДанныеФормыКоллекция: строки можно читать и менять, но методов Свернуть(), Скопировать() и Сортировать() с параметрами ТЗ там нет. Для обратного превращения на сервере есть РеквизитФормыВЗначение("ТаблицаОстатков").

Если колонки реквизита совпадают с колонками ТЗ не полностью, лишние колонки ТЗ просто не попадут на форму, а пустые колонки реквизита останутся пустыми. Ошибки не будет, поэтому проверяйте имена.

Отбор строк на форме задаётся свойством элемента, а не реквизита:

Элементы.ТаблицаОстатков.ОтборСтрок = Новый ФиксированнаяСтруктура("Склад", Склад);

Сбросить отбор — присвоить Неопределено.

Способ 2. Колонки создаются программно

Нужен, когда структура таблицы заранее не известна: универсальная обработка, выгрузка произвольного запроса. Реквизиты добавляются методом ИзменитьРеквизиты(), элементы — через Элементы.Добавить(). Всё выполняется на сервере.

&НаСервере
Процедура ПоказатьПроизвольнуюТЗ(ТЗ)

    ИмяТаблицы = "ТаблицаДанных";
    НовыеРеквизиты = Новый Массив;
    НовыеРеквизиты.Добавить(Новый РеквизитФормы(ИмяТаблицы, Новый ОписаниеТипов("ТаблицаЗначений")));
    Для Каждого Колонка Из ТЗ.Колонки Цикл
        НовыеРеквизиты.Добавить(Новый РеквизитФормы(Колонка.Имя, Колонка.ТипЗначения, ИмяТаблицы, Колонка.Заголовок));
    КонецЦикла;
    ИзменитьРеквизиты(НовыеРеквизиты);

    ЭлементТаблица = Элементы.Добавить(ИмяТаблицы, Тип("ТаблицаФормы"));
    ЭлементТаблица.ПутьКДанным = ИмяТаблицы;
    Для Каждого Колонка Из ТЗ.Колонки Цикл
        Поле = Элементы.Добавить(ИмяТаблицы + Колонка.Имя, Тип("ПолеФормы"), ЭлементТаблица);
        Поле.Вид = ВидПоляФормы.ПолеВвода;
        Поле.ПутьКДанным = ИмяТаблицы + "." + Колонка.Имя;
    КонецЦикла;

    ЗначениеВРеквизитФормы(ТЗ, ИмяТаблицы);

КонецПроцедуры

Повторный вызов с тем же именем упадёт: реквизит уже есть. Перед повторным построением удалите старый реквизит, передав его имя во второй параметр ИзменитьРеквизиты() (массив удаляемых), и удалите элемент через Элементы.Удалить().

Способ 3. Табличный документ

Когда таблицу надо показать «только посмотреть» или распечатать, проще собрать табличный документ на сервере и открыть его на клиенте:

&НаСервере
Функция ТЗВТабличныйДокумент(ТЗ)

    ТабДок = Новый ТабличныйДокумент;
    НомКол = 0;
    Для Каждого Колонка Из ТЗ.Колонки Цикл
        НомКол = НомКол + 1;
        ТабДок.Область(1, НомКол, 1, НомКол).Текст = ?(ЗначениеЗаполнено(Колонка.Заголовок), Колонка.Заголовок, Колонка.Имя);
    КонецЦикла;

    НомСтр = 1;
    Для Каждого Стр Из ТЗ Цикл
        НомСтр = НомСтр + 1;
        НомКол = 0;
        Для Каждого Колонка Из ТЗ.Колонки Цикл
            НомКол = НомКол + 1;
            ТабДок.Область(НомСтр, НомКол, НомСтр, НомКол).Текст = Строка(Стр[Колонка.Имя]);
        КонецЦикла;
    КонецЦикла;

    Возврат ТабДок;

КонецФункции

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

Какой способ выбрать

СпособКогдаМинус
Реквизит из конфигуратораКолонки известны, нужна правка пользователемИзменение структуры — правка формы
Программные реквизитыПроизвольный набор колонокБольше кода, сложнее отлаживать
Табличный документПросмотр, печать, выгрузка в ExcelДанные нельзя редактировать как строки

Для отчётов с группировками и отборами пользователем есть ещё один путь — система компоновки данных с набором «Объект», куда ТЗ передаётся через внешние наборы данных. Это отдельная большая тема; для простого вывода хватает трёх способов выше.

Отладка: как посмотреть содержимое таблицы

В тонком клиенте нет быстрого «открыть значение» для таблицы значений, поэтому смотрят её в отладчике:

  1. Поставьте точку останова (F9) на строке после заполнения ТЗ.
  2. Запустите отладку (F5), дождитесь остановки.
  3. Выделите имя переменной и откройте окно вычисления выражения (Shift+F9).
  4. Раскройте переменную: отладчик покажет колонки и строки, для таблицы доступен табличный просмотр.

В выражении можно писать код: ТЗ.Количество(), ТЗ.Итог("Сумма"), ТЗ.ВыгрузитьКолонку("Склад"). Так за секунду проверяется, на каком шаге «потерялись» строки.

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

Если отладчик недоступен, временно выведите количество строк сообщением: Сообщить("Строк: " + Формат(ТЗ.Количество(), "ЧН=0; ЧГ=0")). Формат здесь нужен, чтобы 1500 не превратилось в «1 500» и чтобы ноль не стал пустой строкой.

Типичные ошибки при работе с таблицей значений

Диагностика: выберите симптом

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

Можно ли передать таблицу значений на клиент?
Напрямую нет: в тонком и веб-клиенте этого типа не существует. Передают реквизит формы, массив структур или табличный документ.
Чем таблица значений отличается от табличной части?
Табличная часть принадлежит объекту и записывается в базу вместе с ним. Таблица значений живёт только в памяти и пропадает после завершения процедуры, если её не сохранить в реквизит.
Как выгрузить таблицу значений в Excel?
Соберите табличный документ, как в способе 3, и запишите его методом Записать() с типом ТипФайлаТабличногоДокумента.XLSX, либо пользователь сохранит его из открытого окна.
Можно ли хранить таблицу значений в реквизите справочника?
Через тип ХранилищеЗначения: Новый ХранилищеЗначения(ТЗ) при записи и Получить() при чтении. Искать и отбирать по содержимому такого реквизита в запросе нельзя.
Сколько строк выдержит таблица значений?
Жёсткого лимита нет, ограничение — память сервера. Сотни тысяч строк работают, но такие объёмы лучше обрабатывать запросом с временными таблицами.