Колонка таблицы значений: как создать и заполнить кодом
Содержание
Колонку у таблицы значений нельзя «заполнить» саму по себе — значения хранятся в строках. Сначала добавляют колонку методом Колонки.Добавить(), затем создают строки Добавить() и присваивают значение по имени колонки. Если нужно одно и то же значение во всей колонке — есть метод ЗаполнитьЗначения(), а если под рукой массив готовых значений — ЗагрузитьКолонку().
Таблица значений (ТаблицаЗначений) — это объект только в памяти, он не хранится в базе. Живёт, пока на него есть ссылка в коде или в реквизите формы. Ниже — рабочие приёмы: создание, типы, массовая запись, составной тип и вывод результата на экран.
Создаём таблицу и добавляем в неё колонки
Пустая таблица создаётся одной строкой, колонки добавляются методом Колонки.Добавить():
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)), "Кол-во");
ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "Цена, руб.");
У метода Добавить() четыре параметра, и все кроме первого необязательны:
Имя— программное имя колонки, по нему потом обращаются к значению. Только буквы, цифры и подчёркивание, без пробелов.ТипЗначения— объектОписаниеТипов. Если не указать, колонка примет значение любого типа.Заголовок— как колонка подпишется при выводе на форму или в табличный документ.Ширина— ширина колонки в символах при выводе.
Имя и заголовок — разные вещи. В коде вы пишете Строка.Количество, а пользователь видит подпись «Кол-во». Удобно давать короткое имя латиницей и человекочитаемый заголовок.
Если колонка нужна «на всё подряд» (временный буфер, промежуточные расчёты), тип можно не задавать:
ТЗ.Колонки.Добавить("Служебное");
Как задать тип данных колонки
Тип описывается объектом ОписаниеТипов. Для простого типа достаточно строки с именем:
Новый ОписаниеТипов("Строка")
Новый ОписаниеТипов("Дата")
Новый ОписаниеТипов("Булево")
Для числа и строки стоит добавить квалификаторы — иначе платформа возьмёт максимальную точность и зря потратит память:
// число: 15 знаков, из них 2 дробных
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2))
// строка: не длиннее 100 символов
Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100))
Квалификатор числа задаёт общую разрядность и число знаков после запятой. Если колонка хранит количество с точностью до грамма — ставьте три дробных знака, для денег обычно два.
Тип колонки не ограничивает запись «на лету»: при присвоении значение приводится к заданному типу. Запишете строку "12,5" в числовую колонку — получите не 12,5, а 0, потому что приведение строки к числу так не работает. Приводите значения сами через Число().
Добавляем строки и записываем значения в колонки
Колонка без строк пуста. Новая строка создаётся методом Добавить(), он возвращает саму строку — к ней и обращаются:
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.Номенклатура = ВыбраннаяНоменклатура;
НоваяСтрока.Количество = 10;
НоваяСтрока.Цена = 150;
К значению колонки можно обращаться тремя способами — результат одинаковый:
НоваяСтрока.Цена = 150; // по имени
НоваяСтрока["Цена"] = 150; // по имени строкой
НоваяСтрока[2] = 150; // по индексу колонки (с нуля)
Обращение по имени читается лучше всего. По индексу — только когда имя колонки заранее неизвестно (например, вы перебираете колонки в цикле).
Вставить строку в нужное место списка (а не в конец) — метод Вставить() с индексом:
ПерваяСтрока = ТЗ.Вставить(0); // вставит в начало
Перебрать все строки и дописать значение в одну колонку:
Для Каждого Строка Из ТЗ Цикл
Строка.Сумма = Строка.Количество * Строка.Цена;
КонецЦикла;
Если значения колонок совпадают по имени с реквизитами другого объекта (документа, структуры, строки запроса), не переписывайте их по одному — заполните строку целиком методом ЗаполнитьЗначенияСвойств():
НоваяСтрока = ТЗ.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТовара);
Метод перенесёт значения всех колонок, имена которых нашлись в источнике, а остальные оставит нетронутыми. На заполнении таблицы из коллекции однотипных объектов это экономит десятки строк кода.
Заполняем всю колонку одним вызовом
Если во всю колонку нужно записать одно и то же значение, не гоняйте цикл — есть метод ЗаполнитьЗначения(). Первый параметр — значение, второй — имена колонок через запятую:
// обнулить колонку "Количество" во всех строках
ТЗ.ЗаполнитьЗначения(0, "Количество");
// проставить дату сразу в две колонки
ТЗ.ЗаполнитьЗначения(ТекущаяДата(), "ДатаНачала, ДатаОкончания");
Если второй параметр не указать, значение попадёт во все колонки подходящего типа.
Когда готовые значения уже лежат в массиве — грузите колонку целиком методом ЗагрузитьКолонку(). Это быстрее построчного присвоения:
МассивЦен = Новый Массив;
МассивЦен.Добавить(100);
МассивЦен.Добавить(200);
МассивЦен.Добавить(350);
ТЗ.ЗагрузитьКолонку(МассивЦен, "Цена");
Размер массива должен точно совпадать с числом строк таблицы — иначе часть строк останется без значения или метод завершится ошибкой. Обратный метод ВыгрузитьКолонку("Цена") вернёт массив всех значений колонки — удобно, чтобы передать их в другой объект.
Какой способ выбрать под задачу:
| Способ | Когда применять | Что учесть |
|---|---|---|
| Цикл с присвоением | Значение зависит от других колонок строки | Самый гибкий, но медленный на больших объёмах |
ЗаполнитьЗначения() | Одно значение на всю колонку (обнулить, проставить дату) | Второй параметр — имена колонок через запятую |
ЗагрузитьКолонку() | Готовый массив значений по порядку строк | Размер массива = числу строк |
Выгрузить() из запроса | Данные берутся из базы | Колонки создаются сами по полям запроса |
Настраиваем заголовок и ширину колонки
Свойства колонки меняются через коллекцию Колонки по её имени. Самые ходовые — Заголовок и Ширина:
КолонкаЦена = ТЗ.Колонки.Цена;
КолонкаЦена.Заголовок = "Цена за единицу, руб.";
КолонкаЦена.Ширина = 14;
Заголовок — это подпись, которую увидит пользователь при выводе таблицы на форму или в табличный документ. Ширина задаётся в символах и работает так же — при отображении. На хранение данных ни то, ни другое не влияет.
Переименовать саму колонку можно через свойство Имя, но делать это стоит только до того, как в коде появились обращения по старому имени:
ТЗ.Колонки.Количество.Имя = "Кол";
Полезные операции над набором колонок:
- 🔹
ТЗ.Колонки.Количество()— сколько всего колонок. - 🔹
ТЗ.Колонки.Удалить("Служебное")— убрать колонку вместе с данными. - 🔹
ТЗ.Колонки.Найти("Цена")— вернёт колонку илиНеопределено, если такой нет. - 🔹
ТЗ.Колонки.Сдвинуть(ТЗ.Колонки.Цена, -1)— переставить колонку левее.
Колонка с составным типом значения
Иногда в одной колонке нужно хранить значения разных типов — например, и число, и строку. Для этого в ОписаниеТипов передают несколько типов. Короткая запись — строкой через запятую:
ТЗ.Колонки.Добавить("Значение", Новый ОписаниеТипов("Число, Строка, Дата"));
Когда типов много или они собираются динамически, удобнее массив:
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
МассивТипов.Добавить(Тип("Строка"));
МассивТипов.Добавить(Тип("СправочникСсылка.Контрагенты"));
ТЗ.Колонки.Добавить("Значение", Новый ОписаниеТипов(МассивТипов));
При чтении из составной колонки проверяйте фактический тип функцией ТипЗнч(), прежде чем что-то с ним делать:
Для Каждого Строка Из ТЗ Цикл
Если ТипЗнч(Строка.Значение) = Тип("Число") Тогда
ОбщаяСумма = ОбщаяСумма + Строка.Значение;
КонецЕсли;
КонецЦикла;
Составной тип удобен, но тяжелее простого: платформа хранит рядом признак типа. Если в колонке на деле всегда одно число — не делайте её составной «про запас».
Ускоряем заполнение больших таблиц
Когда строк десятки тысяч, разница между аккуратным и небрежным кодом измеряется секундами. Приёмы, которые реально помогают:
1. Берите данные из запроса целиком. Результат запроса выгружается в таблицу значений одним вызовом — это самый быстрый способ наполнить таблицу:
ТЗ = Запрос.Выполнить().Выгрузить();
Колонки при этом создаются автоматически по полям запроса — руками их добавлять не нужно.
2. Загружайте колонку массивом, а не циклом. ЗагрузитьКолонку() работает заметно быстрее построчного присвоения, если значения уже собраны.
3. Добавьте индекс для поиска. Если по таблице часто идёт поиск методом Найти() или НайтиСтроки(), объявите индекс — платформа перестанет перебирать строки подряд:
ТЗ.Индексы.Добавить("Номенклатура");
НужнаяСтрока = ТЗ.Найти(ВыбраннаяНоменклатура, "Номенклатура");
Если НужнаяСтрока <> Неопределено Тогда
НужнаяСтрока.Количество = НужнаяСтрока.Количество + 1;
КонецЕсли;
4. Сворачивайте вместо ручного суммирования. Метод Свернуть() группирует строки по одним колонкам и складывает другие — одной командой вместо вложенных циклов:
// сгруппировать по номенклатуре, сложить количество и сумму
ТЗ.Свернуть("Номенклатура", "Количество, Сумма");
Общий итог по числовой колонке берётся методом Итог():
ВсегоСумма = ТЗ.Итог("Сумма");
Свернуть() меняет исходную таблицу — после него строки схлопнутся, и детализация пропадёт. Если детализация ещё нужна, работайте с копией: метод Скопировать() вернёт независимую таблицу, сворачивать которую можно без риска для оригинала.
Ещё одна частая ошибка на больших объёмах — вызывать Количество() в условии цикла. Платформа пересчитывает его на каждой итерации. Если число строк внутри цикла не меняется, сохраните его в переменную заранее.
Выводим таблицу значений в табличный документ
Готовую таблицу удобно показать пользователю через табличный документ. Быстрый способ без ручного макета — построитель отчёта: он сам построит шапку из заголовков колонок и выведет строки:
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТЗ);
Построитель.Выполнить();
ТабДок = Новый ТабличныйДокумент;
Построитель.Вывести(ТабДок);
ТабДок.Показать();
Именно здесь пригождается свойство Заголовок у колонок: в шапку документа попадут подписи, а не программные имена.
Метод Показать() открывает документ в отдельном окне и работает в клиентском коде. В управляемой форме таблицу чаще выводят иначе: на форму кладут реквизит типа «Табличный документ» (или «Таблица значений») и связывают с ним данные — тогда пользователь видит их прямо в форме.
Для сложного оформления (объединённые ячейки, свои итоги, группировки с отступами) используют собственный макет с областями или систему компоновки данных — но для простого «показать таблицу как есть» построителя достаточно.
Готовый табличный документ выгружается в файл, в том числе в формат Excel:
ТабДок.Записать("C:\Выгрузка\товары.xlsx", ТипФайлаТабличногоДокумента.XLSX);
Так пользователь получает таблицу значений в виде привычного файла без копирования из окна вручную.
Частые ошибки при заполнении колонок
Три промаха, на которые уходит больше всего времени у новичков:
«Поле объекта не обнаружено». Самая частая ошибка. Вы обратились к Строка.Цена, а колонки с именем Цена в таблице нет — либо её не добавили, либо опечатались в имени. Проверьте, что Колонки.Добавить("Цена", ...) вызван раньше первого обращения, и что регистр и написание совпадают.
Пробел или дефис в имени колонки. Имя — это идентификатор, пробелы и знаки в нём недопустимы. Колонки.Добавить("Цена товара") упадёт с ошибкой. Пробелы и любые символы кладите в параметр Заголовок, а имя оставляйте «слитным»: ЦенаТовара.
Удаление строк в прямом цикле по индексу. Если идти Для Сч = 0 По ТЗ.Количество() - 1 и удалять строки, индексы сдвигаются, и часть строк проскакивает мимо проверки. У оператора Для нет шага назад, поэтому обходят с конца через Пока:
Сч = ТЗ.Количество() - 1;
Пока Сч >= 0 Цикл
Если ТЗ[Сч].Количество = 0 Тогда
ТЗ.Удалить(Сч);
КонецЕсли;
Сч = Сч - 1;
КонецЦикла;
Чем таблица значений отличается от дерева значений?
Строки), поэтому оно подходит для иерархии. Колонки добавляются одинаково.Можно ли отсортировать строки по колонке?
Сортировать("Цена Убыв"). Направление указывается словами Возр или Убыв после имени колонки, колонок можно перечислить несколько через запятую.Как очистить таблицу, но оставить колонки?
Очистить() удаляет все строки, структура колонок остаётся. Если нужно убрать и колонки — удаляйте их через Колонки.Удалить() или создавайте таблицу заново.Почему после `ЗагрузитьКолонку()` часть строк пустая?
Массив.Количество() и ТЗ.Количество().Как найти все строки с определённым значением колонки?
НайтиСтроки() с отбором-структурой: ТЗ.НайтиСтроки(Новый Структура("Номенклатура", Ссылка)). Вернётся массив подходящих строк (пустой, если совпадений нет).