Колонки таблицы значений в 1С 8.3: добавление, типы, заполнение и форма
Содержание
Колонка в таблицу значений (ТЗ) в 1С добавляется методом коллекции колонок: ТЗ.Колонки.Добавить("Имя", ОписаниеТипов, "Заголовок"). Первый параметр обязателен, остальные можно опустить. Новая колонка появляется в конце, а во всех уже существующих строках получает пустое значение.
Чтобы колонка работала без сюрпризов, с самого начала задайте ей тип через ОписаниеТипов, а латинское или русское имя без пробелов держите отдельно от заголовка, который увидит пользователь. Остальное — порядок колонок, заполнение, форма — решается парой строк кода.
Метод Колонки.Добавить(): синтаксис и первый пример
Таблица значений создаётся конструктором, а колонки живут в её свойстве Колонки — это коллекция КоллекцияКолонокТаблицыЗначений. Добавлять колонки можно и в пустую, и в уже заполненную таблицу.
Полный синтаксис:
Колонки.Добавить(<Имя>, <ТипЗначения>, <Заголовок>, <Ширина>)
| Параметр | Что задаёт | Обязателен |
|---|---|---|
| Имя | Идентификатор колонки, по нему идёт обращение Строка.Имя | Да |
| ТипЗначения | Объект ОписаниеТипов — какие значения допустимы | Нет |
| Заголовок | Текст, который увидит пользователь при выводе | Нет |
| Ширина | Ширина колонки в символах при отображении | Нет |
Минимальный рабочий пример — таблица товаров из трёх колонок:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"), "Товар");
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)), "Кол-во");
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Количество = 2;
НоваяСтрока.Сумма = 1500;
Метод возвращает созданную колонку — объект КолонкаТаблицыЗначений. Его удобно сохранить в переменную, если дальше с колонкой нужно работать: менять заголовок, загружать значения, передавать в другие методы.
КолонкаЦена = ТЗ.Колонки.Добавить("Цена");
КолонкаЦена.Заголовок = "Цена, руб.";
Вставить колонку в нужную позицию
Добавить() всегда ставит колонку последней. Если порядок важен (например, таблицу потом выводят пользователю или выгружают в файл), используйте Вставить() — у него первым параметром идёт индекс. Нумерация начинается с нуля.
// Колонка "Артикул" станет второй по счёту
ТЗ.Колонки.Вставить(1, "Артикул", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(25)));
Уже существующую колонку можно передвинуть методом Колонки.Сдвинуть(Колонка, Смещение): отрицательное смещение двигает её влево, положительное — вправо.
Как добавить колонку в уже заполненную таблицу значений
Типичная задача: таблица получена из запроса через РезультатЗапроса.Выгрузить(), а к ней нужно приклеить ещё одно поле — признак, комментарий, рассчитанную сумму. Колонка добавляется тем же методом, количество строк при этом не меняется.
ТЗ = Запрос.Выполнить().Выгрузить();
ТЗ.Колонки.Добавить("Отметка", Новый ОписаниеТипов("Булево"));
Проверить, что колонки ещё нет
Повторное добавление колонки с тем же именем вызывает ошибку времени выполнения. Если код может сработать дважды (общая процедура, обработчик, который вызывается из нескольких мест), сначала проверьте наличие через Найти():
Если ТЗ.Колонки.Найти("Отметка") = Неопределено Тогда
ТЗ.Колонки.Добавить("Отметка", Новый ОписаниеТипов("Булево"));
КонецЕсли;
Найти() возвращает колонку или Неопределено, если колонки с таким именем нет.
Заполнить новую колонку значениями
Сразу после добавления в старых строках лежат пустые значения. Есть три способа их заполнить:
- 🔹 Одно значение во все строки —
ЗаполнитьЗначения():ТЗ.ЗаполнитьЗначения(Истина, "Отметка"); - 🔹 Значения из массива —
ЗагрузитьКолонку(). Массив должен идти в том же порядке, что и строки:ТЗ.ЗагрузитьКолонку(МассивОтметок, "Отметка"); - 🔹 Значения, зависящие от других колонок, — цикл по строкам (подробно ниже, в разделе о вычисляемых колонках).
Обратный метод ВыгрузитьКолонку("Имя") возвращает массив значений колонки. Связка «выгрузить → обработать массив → загрузить» удобна, когда колонку надо пересчитать по сложному правилу.
Имя колонки задано строкой
Если имя колонки приходит из настроек или параметра, обращайтесь к значению через квадратные скобки: Строка[ИмяКолонки]. Обращение через точку Строка.ИмяКолонки тут не сработает — платформа будет искать колонку с именем «ИмяКолонки».
ИмяКолонки = "Остаток_" + Формат(НомерСклада, "ЧГ=0");
ТЗ.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов("Число"));
Для Каждого Строка Из ТЗ Цикл
Строка[ИмяКолонки] = 0;
КонецЦикла;
Формат(..., "ЧГ=0") убирает разделитель групп разрядов. Без него для числа 1000 получится «1 000» с неразрывным пробелом — а такое имя колонки недопустимо.
Колонка таблицы значений на управляемой форме
На форме таблица значений хранится не как ТаблицаЗначений, а как реквизит формы с типом «ТаблицаЗначений». Колонки такого реквизита задаются отдельно — либо в конфигураторе, либо программно на сервере.
Через редактор формы в конфигураторе
- Откройте форму и перейдите на вкладку реквизитов (правая верхняя панель редактора формы).
- Добавьте реквизит и в его свойствах выберите тип
ТаблицаЗначений. - Выделите этот реквизит и в командной панели над списком реквизитов выберите команду добавления колонки — она появляется, когда выделен реквизит-таблица.
- Задайте колонке имя, тип и заголовок в палитре свойств.
- Перетащите реквизит в дерево элементов формы — получится элемент «Таблица», в котором колонки станут полями.
Если реквизит-таблица уже выведен на форму, а колонку вы добавили позже, перетащите и её в элемент таблицы. Иначе колонка будет в данных, но на экране её не увидят.
Программно на сервере
Когда состав колонок известен только во время работы (например, по числу складов), реквизит формы меняют методом ИзменитьРеквизиты(), а потом создают поле в элементе таблицы. Оба действия выполняются на сервере.
&НаСервере
Процедура ДобавитьКолонкуНаСервере(ИмяКолонки, Заголовок)
Добавляемые = Новый Массив;
Добавляемые.Добавить(Новый РеквизитФормы(ИмяКолонки,
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)),
"ТаблицаДанных", Заголовок));
ИзменитьРеквизиты(Добавляемые);
Поле = Элементы.Добавить("ТаблицаДанных" + ИмяКолонки, Тип("ПолеФормы"), Элементы.ТаблицаДанных);
Поле.Вид = ВидПоляФормы.ПолеВвода;
Поле.ПутьКДанным = "ТаблицаДанных." + ИмяКолонки;
КонецПроцедуры
Третий параметр РеквизитФормы — путь к реквизиту-таблице. Именно он делает новый реквизит колонкой, а не самостоятельным реквизитом формы.
В тонком клиенте тип ТаблицаЗначений недоступен. На клиенте реквизит-таблица — это коллекция данных формы. Чтобы поработать с ней как с обычной ТЗ, на сервере вызовите РеквизитФормыВЗначение("ТаблицаДанных"), а результат верните методом ЗначениеВРеквизитФормы().
Тип колонки: как задать ОписаниеТипов и квалификаторы
Тип можно не указывать — тогда в колонку поместится что угодно. Для черновых расчётов это удобно, но у колонки без типа есть ограничения: такую таблицу нельзя передать в запрос как временную таблицу, а сортировка и итоги по смешанным значениям ведут себя непредсказуемо.
Конструктор ОписаниеТипов принимает тип и квалификаторы, причём у каждого квалификатора своё место в списке параметров. Отсюда лишние запятые в примерах.
| Что нужно | Как записать |
|---|---|
| Число 15 знаков, 2 после запятой | Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)) |
| Строка до 100 символов | Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(100)) |
| Только дата, без времени | Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата)) |
| Булево | Новый ОписаниеТипов("Булево") |
| Ссылка на справочник | Новый ОписаниеТипов("СправочникСсылка.Контрагенты") |
| Составной тип | Новый ОписаниеТипов("Число, Строка") |
Нюансы, на которых спотыкаются:
- 🔸 Квалификатор строки без длины (или с длиной 0) даёт строку неограниченной длины. В запросе по такой колонке нельзя группировать и сравнивать — задайте конкретную длину.
- 🔸 При записи значения в типизированную колонку платформа приводит его к типу колонки. Значение неподходящего типа молча заменяется приведённым — ошибки не будет, поэтому проблема всплывает позже, в итогах или отчёте.
- 🔸 Тип уже созданной колонки поменять нельзя: свойство
ТипЗначениядоступно только для чтения. Нужен другой тип — добавьте новую колонку, перенесите значения черезВыгрузитьКолонку/ЗагрузитьКолонкуи удалите старую. - 🔸 Имя колонки менять можно: свойство
Имядоступно на запись.
// Замена типа колонки "Код" со строки на число
Значения = ТЗ.ВыгрузитьКолонку("Код");
Для Индекс = 0 По Значения.ВГраница() Цикл
Попытка
Значения[Индекс] = Число(Значения[Индекс]);
Исключение
Значения[Индекс] = 0; // строка не является числом
КонецПопытки;
КонецЦикла;
ТЗ.Колонки.Удалить(ТЗ.Колонки.Найти("Код"));
ТЗ.Колонки.Добавить("Код", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0)));
ТЗ.ЗагрузитьКолонку(Значения, "Код");
Строки переводятся в число явно, функцией Число(). Так вы сами решаете, что делать со значениями вроде «А-15», а не полагаетесь на автоматическое приведение.
Вычисляемые колонки: сумма, признак, группировка
Самый частый сценарий: в таблице есть количество и цена, нужна сумма. Добавляем колонку и заполняем её в цикле:
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
Для Каждого Строка Из ТЗ Цикл
Строка.Сумма = Окр(Строка.Количество * Строка.Цена, 2);
КонецЦикла;
Проверка на числах: 3 штуки по 199,90 дают 599,70 — округление до копеек здесь ничего не меняет, но при цене с тремя знаками после запятой оно уже нужно.
Посчитать прямо в запросе
Если таблица приходит из запроса, вычисляемое поле лучше сделать там же. Тогда колонка появится в результате сразу, с правильным типом, без цикла на стороне 1С:
Запрос.Текст =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары.Количество КАК Количество,
| Товары.Цена КАК Цена,
| Товары.Количество * Товары.Цена КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары
|ГДЕ
| Товары.Ссылка = &Ссылка";
Таблица и поля здесь даны для примера — подставьте свой объект метаданных.
Колонка-итог через Свернуть
Когда нужна не построчная величина, а сумма по группам, отдельная колонка не нужна. Метод Свернуть() группирует строки и суммирует указанные колонки:
ТЗ.Свернуть("Номенклатура", "Количество, Сумма");
Колонки, не попавшие ни в один из двух параметров, после свёртки удаляются. Если какая-то колонка нужна дальше, включите её в группировочные.
Колонки в больших таблицах: как не замедлить обработку
На таблице в сотни строк разница между подходами незаметна. На десятках и сотнях тысяч строк — заметна. Что помогает:
- ⚡ Добавляйте колонки до заполнения строк. Таблица, в которую сразу заложена вся структура, проще в сопровождении, и код заполнения пишется одним проходом.
- ⚡ Один цикл вместо нескольких. Если надо рассчитать три новые колонки, считайте все три в одном
Для Каждого, а не тремя проходами. - ⚡ Колонку ищите один раз.
Колонки.Найти()внутри цикла по строкам — лишняя работа на каждой итерации. Найдите колонку до цикла. - ⚡ Пересчёт — в запросе. Арифметика и условия (
ВЫБОР КОГДА) на стороне СУБД обычно работают быстрее цикла по ТЗ. - ⚡ Лишние колонки — долой. Если таблица передаётся с сервера на клиент или сохраняется, удалите служебные колонки или возьмите копию только с нужными:
ТЗ.Скопировать(, "Номенклатура, Сумма"). - ⚡ Индекс — по колонке поиска. Если по новой колонке будете часто искать через
НайтиСтроки(), добавьте индекс:ТЗ.Индексы.Добавить("Отметка").
Для пустой таблицы с той же структурой есть ТЗ.СкопироватьКолонки(). Он копирует колонки с типами и не тратит время на строки — удобно для таблицы-приёмника, которую потом заполняют отфильтрованными данными.
Частые ошибки при добавлении колонок в ТЗ
Ещё одна неприятная ситуация — значения «не те» без всякой ошибки. Обычно это следствие приведения типа: в числовую колонку записали строку, в колонку даты — значение с временем, хотя квалификатор оставляет только дату. Если результат расходится с ожиданием, первым делом откройте свойство ТипЗначения колонки в отладчике.