Добавление колонки в таблицу значений: код и примеры
Содержание
Колонку в таблицу значений добавляют методом Колонки.Добавить(). В минимальном виде хватает имени: ТЗ.Колонки.Добавить("Сумма"). Если нужно ограничить тип данных, вторым параметром передают ОписаниеТипов, третьим — заголовок для вывода на форме, четвёртым — ширину.
Ниже — рабочие примеры на встроенном языке 1С 8.3: как добавить колонку в таблицу значений с типом и без, как задать длину строки и точность числа, как вставить колонку в нужную позицию, скопировать структуру и заполнить вычисляемую колонку. Весь код — для серверного или клиентского контекста обычной (не формовой) таблицы значений; про таблицу на управляемой форме есть отдельная оговорка.
Как устроена таблица значений и её колонки
ТаблицаЗначений — это универсальная таблица в памяти: набор строк и набор колонок. Колонки живут в коллекции Колонки (тип КоллекцияКолонокТаблицыЗначений), строки — в самой таблице. Каждая колонка — это объект КолонкаТаблицыЗначений со свойствами Имя, ТипЗначения, Заголовок, Ширина.
Создаётся таблица так:
ТЗ = Новый ТаблицаЗначений;
Пока колонок нет, добавить строку не выйдет — некуда писать данные. Поэтому порядок всегда один: сначала создаём колонки, потом строки. Количество колонок читается через ТЗ.Колонки.Количество(), поиск — через ТЗ.Колонки.Найти("Сумма") (вернёт колонку или Неопределено).
У имени колонки те же правила, что у переменной: только буквы, цифры и подчёркивание, первый символ — не цифра, без пробелов. Имя — это программный идентификатор, по нему вы обращаетесь к данным: Строка.Сумма. Для человекочитаемой подписи есть отдельное свойство Заголовок, оно и показывается в шапке, когда таблицу выводят на форму.
Прочитать, какой тип задан у готовой колонки, можно через свойство ТипЗначения — оно возвращает тот самый объект ОписаниеТипов. Это удобно, когда таблица пришла извне и нужно понять её структуру перед обработкой:
Для Каждого Колонка Из ТЗ.Колонки Цикл
Сообщить(Колонка.Имя + " — " + Строка(Колонка.ТипЗначения));
КонецЦикла;
Добавляем колонку методом Колонки.Добавить
Полная сигнатура метода: Добавить(Имя, Тип, Заголовок, Ширина). Все параметры необязательные, но на практике имя задают всегда.
Самый короткий вариант — колонка без ограничения типа. В неё можно писать что угодно:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Контрагент");
ТЗ.Колонки.Добавить("Комментарий");
Добавим строку и заполним:
Строка = ТЗ.Добавить();
Строка.Контрагент = "ООО Ромашка";
Строка.Комментарий = "Первая поставка";
Метод Колонки.Добавить() возвращает саму созданную колонку. Это удобно, когда дальше нужно донастроить её свойства:
Колонка = ТЗ.Колонки.Добавить("Дата");
Колонка.Заголовок = "Дата операции";
Колонка.Ширина = 12;
Если добавить колонку в таблицу, где уже есть строки, в этих строках новая колонка заполнится значением по умолчанию для указанного типа (для числа — 0, для строки — пустая строка, для даты — пустая дата). Когда тип не задан, значение будет Неопределено.
Как задать тип колонки через ОписаниеТипов
Чтобы колонка принимала только числа, строки или ссылки определённого типа, вторым параметром передают объект ОписаниеТипов. Он же задаёт длину, точность и прочие ограничения.
Простые типы — имя передаётся строкой:
ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
ТЗ.Колонки.Добавить("Наименование", Новый ОписаниеТипов("Строка"));
ТЗ.Колонки.Добавить("ДатаДокумента", Новый ОписаниеТипов("Дата"));
Такая запись ограничивает тип, но не задаёт разрядность. Чтобы указать точность числа или длину строки, добавляют квалификаторы:
// Число: 15 знаков всего, 2 после запятой
КвЧисла = Новый КвалификаторыЧисла(15, 2);
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", КвЧисла));
// Строка: до 100 символов
КвСтроки = Новый КвалификаторыСтроки(100);
ТЗ.Колонки.Добавить("Примечание", Новый ОписаниеТипов("Строка", , КвСтроки));
// Дата: только дата, без времени
КвДаты = Новый КвалификаторыДаты(ЧастиДаты.Дата);
ТЗ.Колонки.Добавить("ДатаОтгрузки", Новый ОписаниеТипов("Дата", , , КвДаты));
Обратите внимание на позиции параметров в ОписаниеТипов: первый — типы, затем квалификаторы числа, строки и даты по порядку. Пропущенные параметры отмечают запятыми.
У квалификаторов есть второй параметр, про который часто забывают. У строки это допустимая длина: Новый КвалификаторыСтроки(100, ДопустимаяДлина.Переменная) разрешает строки короче 100 символов, а ДопустимаяДлина.Фиксированная требует ровно 100 (остаток дополняется пробелами). У числа второй управляющий параметр — знак: Новый КвалификаторыЧисла(15, 2, ДопустимыйЗнак.Неотрицательный) запретит отрицательные суммы прямо на уровне типа колонки. Это дешёвая проверка данных без единой строчки валидации.
Для ссылочных типов имя указывают полностью — СправочникСсылка.Контрагенты, ДокументСсылка.РеализацияТоваровУслуг, ПеречислениеСсылка.СтавкиНДС:
ТЗ.Колонки.Добавить("Контрагент",
Новый ОписаниеТипов("СправочникСсылка.Контрагенты"));
Колонке можно разрешить несколько типов сразу — составной тип. Для этого собирают массив типов:
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Контрагенты"));
МассивТипов.Добавить(Тип("СправочникСсылка.ФизическиеЛица"));
Описание = Новый ОписаниеТипов(МассивТипов);
ТЗ.Колонки.Добавить("Получатель", Описание);
Теперь в колонку Получатель можно записать ссылку и на контрагента, и на физлицо. У составной колонки значение по умолчанию в пустых строках — Неопределено: единого «нуля» для разнородных типов не существует.
Коротко, какой способ создания колонок когда применять:
| Способ | Что делает | Когда брать |
|---|---|---|
Колонки.Добавить(Имя, Тип) | Добавляет одну колонку в конец | Основной способ, строите структуру вручную |
Колонки.Вставить(Индекс, Имя, Тип) | То же, но в заданную позицию | Порядок колонок важен (вывод на форму) |
Результат.Выгрузить() | Создаёт колонки по полям запроса | Таблица собирается из запроса |
СкопироватьКолонки() | Повторяет структуру другой таблицы | Нужна пустая копия с теми же колонками |
Позиция, переименование и удаление колонки
По умолчанию Добавить() ставит колонку в конец. Если порядок важен (например, таблица выводится на форму и колонки должны идти как в документе), используют Вставить(Индекс, Имя, Тип, …) — он работает так же, но вставляет по указанному индексу (нумерация с нуля):
// Поставить "Номер" первой колонкой
ТЗ.Колонки.Вставить(0, "Номер", Новый ОписаниеТипов("Число"));
Переименование — через свойство Имя найденной колонки:
Колонка = ТЗ.Колонки.Найти("Сумма");
Если Колонка <> Неопределено Тогда
Колонка.Имя = "СуммаСНДС";
КонецЕсли;
Удаление:
ТЗ.Колонки.Удалить("Комментарий"); // по имени
ТЗ.Колонки.Удалить(ТЗ.Колонки[0]); // по объекту колонки
Сдвинуть колонку на нужную позицию, не пересоздавая её, помогает Сдвинуть(Колонка, Смещение):
ТЗ.Колонки.Сдвинуть(ТЗ.Колонки.Найти("Итого"), -1); // на одну позицию левее
Удаление или переименование колонки не трогает данные в остальных колонках, но ломает весь код, который обращался к старому имени через Строка.СтароеИмя. После переименования пройдитесь по обработчикам, где использовалось прежнее имя.
Копирование структуры и вычисляемые колонки
Частая задача — получить пустую таблицу с теми же колонками, что у исходной. Пересоздавать колонки вручную не нужно, есть метод СкопироватьКолонки():
ПустаяКопия = ТЗ.СкопироватьКолонки(); // та же структура, строк нет
Если нужна копия вместе с данными — метод Скопировать(). Ему можно передать отбор строк и список колонок, тогда в копию попадут только нужные:
ТолькоСуммы = ТЗ.Скопировать(, "Контрагент, Сумма");
Вычисляемая колонка — это обычная колонка, которую вы добавляете, а затем заполняете в цикле на основе других колонок. Шаблон такой: сначала добавляем колонку с типом результата, потом проходим по строкам:
ТЗ.Колонки.Добавить("Итого", Новый ОписаниеТипов("Число"));
Для Каждого Строка Из ТЗ Цикл
Строка.Итого = Строка.Количество * Строка.Цена;
КонецЦикла;
Так же считают НДС, скидки, остатки — любую производную величину. Если значений в колонке много и их нужно выгрузить массивом (например, для передачи в другой метод), пригодятся ТЗ.ВыгрузитьКолонку("Итого") и обратная ТЗ.ЗагрузитьКолонку(Массив, "Итого").
Иногда колонку добавляют не для расчёта, а чтобы заполнить её готовым массивом значений — скажем, результатами, полученными из внешнего источника. Порядок элементов массива должен совпадать с порядком строк таблицы:
ТЗ.Колонки.Добавить("Курс", Новый ОписаниеТипов("Число"));
МассивКурсов = ПолучитьКурсы(); // длина = числу строк ТЗ
ТЗ.ЗагрузитьКолонку(МассивКурсов, "Курс");
Это быстрее, чем присваивать значения строкам поштучно в цикле, и читается нагляднее.
Когда таблица собирается из запроса, отдельно добавлять колонки обычно не требуется — структуру задаёт сам запрос:
Результат = Запрос.Выполнить();
ТЗ = Результат.Выгрузить(); // колонки уже созданы по полям запроса
А вот добавить к такой таблице свою расчётную колонку — как раз типичный случай вычисляемого поля из примера выше.
Ошибки при работе с колонками и как их избежать
Большинство сбоев на этой теме однотипны и легко читаются по тексту исключения.
🔴 «Колонка с таким именем уже существует» — повторный Добавить() с тем же именем. Перед добавлением проверяйте: Если ТЗ.Колонки.Найти("Сумма") = Неопределено Тогда … КонецЕсли.
🔴 «Поле объекта не обнаружено» — обращение Строка.Сумма к колонке, которой нет (опечатка в имени или колонку забыли добавить). Сверьте имя: регистр в именах колонок не важен, но пробел или лишний символ дадут новое имя.
🔴 Ошибка приведения / преобразования типа — запись значения, не подходящего под тип колонки (строку в числовую колонку, ссылку чужого типа в ссылочную). Решение — либо расширить тип до составного, либо приводить значение заранее.
🔴 Недопустимое имя колонки — имя с пробелом или начинающееся с цифры ("Сумма НДС", "1Строка"). Имя должно быть корректным идентификатором; читаемую подпись задавайте через Заголовок.
Удобно диагностировать по симптому:
На управляемой форме всё иначе. Таблицу значений, которая является реквизитом формы, нельзя пополнить колонкой простым Колонки.Добавить() в обработчике — структура реквизита формы фиксируется при открытии. Колонку добавляют через ИзменитьРеквизиты() и Элементы, и обычно это делают не на лету, а в конфигураторе. Код с Колонки.Добавить() из этой статьи работает с обычной таблицей значений в памяти, а не с реквизитом формы.
Производительность и хорошие практики
Добавление самой колонки — дешёвая операция, даже если в таблице миллион строк: меняется только описание структуры. Дорого обходится заполнение в цикле, поэтому оптимизируют именно его.
✅ Задавайте тип сразу. Колонка с конкретным типом занимает меньше памяти и защищает от мусорных данных. Тип без ограничения (Неопределено) оставляйте только там, где значения действительно разнородны.
✅ Не добавляйте колонку внутри цикла по строкам. Структуру формируют один раз до заполнения. Внутри цикла колонку только заполняют.
✅ Для частого поиска по колонке добавьте индекс: ТЗ.Индексы.Добавить("Контрагент"). Тогда Найти() и НайтиСтроки() по этой колонке работают заметно быстрее на больших таблицах.
✅ Группировку и свёртку по колонкам делайте методом Свернуть("Контрагент", "Сумма, Количество") — он быстрее ручного прохода с накоплением.
✅ Заголовок и ширину задавайте только тем колонкам, которые реально выводятся пользователю; для служебных таблиц в памяти это лишняя работа.
Короткий чек перед тем, как считать таблицу готовой:
Частые вопросы
Можно ли добавить колонку в таблицу значений, в которой уже есть строки?
Неопределено, если тип не задан. Дальше при необходимости заполняете колонку в цикле.Чем отличается Имя колонки от Заголовка?
Имя — программный идентификатор, по нему вы обращаетесь к данным (Строка.Сумма); в нём нельзя использовать пробелы. Заголовок — подпись для пользователя, она показывается в шапке таблицы на форме и может быть любой, в том числе с пробелами.Как добавить колонку со ссылкой на справочник или документ?
ОписаниеТипов полное имя типа: Новый ОписаниеТипов("СправочникСсылка.Контрагенты") или "ДокументСсылка.РеализацияТоваровУслуг". Для нескольких допустимых типов соберите массив типов и передайте его в ОписаниеТипов.Как скопировать колонки из одной таблицы в другую без данных?
СкопироватьКолонки() — он возвращает новую таблицу с той же структурой, но без строк. Если нужны и данные — используйте Скопировать(), которому можно передать отбор и список нужных колонок.Почему не получается добавить колонку к таблице на управляемой форме?
Колонки.Добавить() там не сработает — колонки добавляются через ИзменитьРеквизиты() либо заранее в конфигураторе. Метод Добавить() предназначен для обычной таблицы значений в памяти.