К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как добавить колонку в таблицу значений

Как добавить колонку в таблицу значений в 1С: метод Колонки.Добавить, типы данных, добавление в табличную часть и форму, типичные ошибки и примеры кода.

Таблица значений в 1С — универсальный объект для хранения и обработки данных в памяти: её используют для промежуточных расчётов, загрузки данных из файлов, вывода произвольных списков на форму. Добавление колонки — базовая операция, выполняемая методом Колонки.Добавить(), но у неё есть нюансы: типизация, повторное добавление, работа с таблицами на форме.

В этой статье разобраны все практические сценарии: добавление колонки в программно созданную таблицу значений, в таблицу, полученную запросом, в реквизит формы и в табличную часть объекта. Каждый вариант сопровождается рабочим кодом на встроенном языке 1С.

Базовый синтаксис метода Колонки.Добавить

Метод вызывается у коллекции Колонки таблицы значений и принимает четыре параметра, из которых обязателен только первый — имя колонки:

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Номенклатура");

ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));

ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)), "Цена продажи", 10);

Параметры метода: Имя — строковый идентификатор колонки (только буквы, цифры и подчёркивание, начинаться должно с буквы или подчёркивания); Тип — объект ОписаниеТипов, ограничивающий допустимые значения; Заголовок — текст, который увидит пользователь при выводе таблицы на форму; Ширина — ширина колонки в символах при отображении.

Если тип не указан, колонка принимает значения любого типа. Это удобно на этапе прототипирования, но в рабочем коде тип лучше задавать явно: без типизации сортировка и итоги по колонке могут работать неожиданно, а попытка записать в базу данных нетипизированное значение приведёт к ошибкам преобразования.

Как задать тип колонки через ОписаниеТипов

Объект ОписаниеТипов конструируется из строки с перечислением типов или из массива типов. Для примитивных типов достаточно строки, для уточнения длины и точности используются квалификаторы:

// Строка фиксированной длины 100 символов

ОписаниеСтроки = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(100));

ТЗ.Колонки.Добавить("Наименование", ОписаниеСтроки);

// Дата без времени

ОписаниеДаты = Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата));

ТЗ.Колонки.Добавить("ДатаОтгрузки", ОписаниеДаты);

// Ссылка на конкретный справочник

ОписаниеСсылки = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");

ТЗ.Колонки.Добавить("Товар", ОписаниеСсылки);

// Составной тип: строка или число

МассивТипов = Новый Массив;

МассивТипов.Добавить(Тип("Строка"));

МассивТипов.Добавить(Тип("Число"));

ТЗ.Колонки.Добавить("Значение", Новый ОписаниеТипов(МассивТипов));

Квалификаторы имеют практическое значение: строка без ограничения длины при выгрузке в СУБД может обрабатываться медленнее, а число без указания разрядности дробной части по умолчанию получает до 10 знаков после запятой, что приводит к «мусорным» хвостам в итогах. Задавайте квалификаторы так же, как они заданы у соответствующих реквизитов в метаданных.

Добавление колонки в таблицу, полученную запросом

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

РезультатЗапроса = Запрос.Выполнить();

ТЗ = РезультатЗапроса.Выгрузить();

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

Для Каждого СтрокаТЗ Из ТЗ Цикл

СтрокаТЗ.СуммаСНДС = СтрокаТЗ.Сумма * 1.2;

КонецЦикла;

Новая колонка заполняется значением Неопределено во всех существующих строках, поэтому после добавления её нужно заполнить в цикле. Если колонка добавляется только для того, чтобы потом свернуть таблицу с итогами, заполнять её не обязательно — метод Свернуть() корректно обрабатывает пустые значения, но суммировать можно только числовые колонки.

Альтернатива без добавления колонки — вычисляемое поле прямо в запросе (Сумма * 1.2 КАК СуммаСНДС). Этот вариант предпочтительнее, если значение известно на момент выполнения запроса: расчёт выполнится на сервере СУБД и не потребует обхода таблицы в коде.

Сравнение вариантов

Колонка в тексте запроса

Подходит, когда значение вычисляется из данных запроса. Быстрее, но нельзя менять после выгрузки

Колонки.Добавить после выгрузки

Подходит для данных из внешних источников, расчётов в коде и колонок-флагов. Требует цикла заполнения

ВыгрузитьКолонку + ЗагрузитьКолонку

Подходит для массовой замены значений существующей колонки массивом подготовленных данных

Добавление колонки в таблицу значений на форме

Если таблица значений является реквизитом управляемой формы, простой вызов Колонки.Добавить() на клиенте недоступен, а на сервере изменения структуры реквизита требуют специального механизма. Используется метод формы ИзменитьРеквизиты():

&НаСервере

Процедура ДобавитьКолонкуНаСервере()

Добавляемые = Новый Массив;

Добавляемые.Добавить(Новый РеквизитФормы("Комментарий",

Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(200)),

"ТаблицаДанных", "Комментарий"));

ИзменитьРеквизиты(Добавляемые);

Элемент = Элементы.Добавить("ТаблицаДанныхКомментарий", Тип("ПолеФормы"), Элементы.ТаблицаДанных);

Элемент.ПутьКДанным = "ТаблицаДанных.Комментарий";

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

Здесь "ТаблицаДанных" — имя реквизита формы типа «ТаблицаЗначений». Вызов ИзменитьРеквизиты() меняет состав реквизитов формы, поэтому после него нужно программно создать элемент формы, привязанный к новому пути данных, иначе колонка существует в данных, но не видна пользователю.

Добавление колонки в динамический список невозможно

Реквизит формы типа «ДинамическийСписок» не поддерживает добавление произвольных колонок — его состав определяется запросом. Если нужны дополнительные данные, измените текст запроса динамического списка, добавив вычисляемое поле, либо замените динамический список на таблицу значений.

Добавление колонки в табличную часть объекта

Табличная часть документа или справочника — не таблица значений, и добавить в неё колонку программно нельзя: состав колонок жёстко определён в конфигураторе. Если нужна дополнительная колонка, её добавляют в метаданные объекта через конфигуратор (реквизит табличной части), после чего она становится доступна и в коде, и пользователю.

Когда изменять конфигурацию нельзя (типовая конфигурация на поддержке), используют обходные пути: дополнительные реквизиты и сведения, хранение расширенных данных в отдельном регистре сведений с измерением по строке документа или расширение конфигурации. Расширение — наиболее чистый способ добавить реквизит табличной части, не снимая конфигурацию с поддержки.

Для промежуточных расчётов по строкам табличной части удобно выгрузить её в таблицу значений методом Выгрузить(), добавить нужные колонки, выполнить расчёт и при необходимости загрузить обратно методом Загрузить() — но обратно загрузятся только колонки, существующие в табличной части.

Порядок действий
  1. 1
    Создайте таблицу значений или получите её выгрузкой запроса/табличной части
  2. 2
    Вызовите ТЗ.Колонки.Добавить с именем и описанием типов
  3. 3
    Проверьте отсутствие дубля: ТЗ.Колонки.Найти(Имя) = Неопределено
  4. 4
    Заполните новую колонку в цикле по строкам
  5. 5
    Выведите таблицу на форму или используйте в дальнейших расчётах

Проверка результата и типичные ошибки

После добавления колонки убедитесь, что структура соответствует ожиданиям. Быстрая проверка в отладчике или коде:

Если ТЗ.Колонки.Найти("СуммаСНДС") = Неопределено Тогда

ТЗ.Колонки.Добавить("СуммаСНДС", Новый ОписаниеТипов("Число"));

КонецЕсли;

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

Типичные ошибки
01
Добавление колонки без проверки на дубликат — исключение при повторном вызове процедуры
02
Имя колонки с пробелом или точкой ("Сумма НДС") — ошибка компиляции или выполнения; используйте СуммаНДС, а пробелы оставьте для заголовка
03
Отсутствие типизации — сортировка строк с числами идёт как строковая, итоги считаются неверно
04
Попытка добавить колонку в табличную часть документа кодом — это невозможно, нужен реквизит в конфигураторе
05
Вызов Колонки.Добавить на клиенте для реквизита формы — метод недоступен, требуется ИзменитьРеквизиты на сервере

Ещё одна частая проблема — добавление колонки после того, как по таблице построен индекс или создана схема компоновки данных. Индексы перестраиваются автоматически, но поле схемы компоновки нужно описывать в наборе данных отдельно, иначе отчёт не увидит новую колонку.

Контрольные точки

Как проверить результат

Наличие колонки
Норма

ТЗ.Колонки.Найти(Имя) возвращает объект колонки

Тревожный признак

Возвращается Неопределено — колонка не создана

Тип значений
Норма

Значения в ячейках соответствуют ОписаниюТипов

Тревожный признак

В ячейках Неопределено или значения другого типа

Отображение на форме
Норма

Колонка видна в таблице формы и редактируется

Тревожный признак

Колонка есть в данных, но не выведена — нет элемента формы

Альтернативные операции с колонками

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

Для переименования колонки отдельного метода нет: изменяется свойство Имя объекта колонки напрямую, но только если новое имя не занято. Учтите, что после переименования весь код, обращающийся к старому имени, перестанет работать.

Итог

Что важно запомнить

Колонка добавляется методом ТЗ.Колонки.Добавить с указанием имени и ОписанияТипов. Для реквизитов формы используется ИзменитьРеквизиты на сервере, для табличных частей — изменение метаданных или расширение. Перед добавлением проверяйте отсутствие дубля через Колонки.Найти и всегда задавайте тип колонки.

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

Можно ли добавить колонку в таблицу значений на клиенте?

Для локальной переменной в толстом клиенте — да. В управляемом приложении на тонком и веб-клиенте тип «ТаблицаЗначений» недоступен на клиенте: все операции со структурой выполняются в серверных процедурах, а на клиенте доступны только операции с данными через данные формы.

Как добавить колонку с значением по умолчанию?

Метод Добавить не принимает значение по умолчанию — все существующие строки получают Неопределено. После добавления пройдите по таблице циклом и присвойте нужное значение, либо используйте ТЗ.ЗаполнитьЗначения(Значение, "ИмяКолонки") — это быстрее цикла.

Чем отличается Имя колонки от Заголовка?

Имя — технический идентификатор для обращения в коде (СтрокаТЗ.СуммаНДС), должен соответствовать правилам идентификаторов. Заголовок — произвольный текст для пользователя, может содержать пробелы и любые символы, например «Сумма с НДС, руб.».

Почему сортировка по новой колонке работает неправильно?

Чаще всего колонка создана без типа, и в ней оказались значения разных типов или строки вместо чисел: «10» сортируется раньше «2». Задайте ОписаниеТипов при добавлении колонки и убедитесь, что значения заполняются в соответствующем типе.

Как добавить несколько колонок сразу?

Отдельного метода пакетного добавления у таблицы значений нет — вызывайте Колонки.Добавить в цикле по массиву структур с параметрами. Для реквизитов формы метод ИзменитьРеквизиты принимает массив, поэтому там несколько колонок добавляются одним вызовом.

Можно ли добавить колонку в дерево значений?

Да, дерево значений имеет ту же коллекцию Колонок, и метод Добавить работает идентично. Колонка станет доступна во всех строках дерева независимо от уровня иерархии.