Разработка и Конфигурация · 11 мин
Как изменить тип колонки таблицы значений в 1С
Как изменить тип колонки таблицы значений в 1С: методы Колонки.Вставить, Добавить, ОписаниеТипов, пересоздание таблицы и типичные ошибки с примерами кода.
Таблица значений в 1С — один из самых используемых объектов для промежуточного хранения и обработки данных. Но у неё есть особенность: тип уже созданной колонки напрямую изменить нельзя. У объекта «КолонкаТаблицыЗначений» свойство «ТипЗначения» доступно только для чтения, поэтому попытка присвоить ему новое описание типов вызовет ошибку.
На практике задача решается обходными путями: созданием новой колонки с нужным типом и переносом данных, полным пересозданием таблицы или загрузкой данных в новую структуру. Выбор способа зависит от того, заполнена ли таблица данными, важен ли порядок колонок и насколько критична производительность при больших объёмах.
Ниже разобраны рабочие приёмы с примерами кода на встроенном языке 1С, ограничения каждого подхода и типичные ошибки, из-за которых данные теряются или обработка падает с исключением.
Почему тип колонки нельзя поменять напрямую
Коллекция колонок таблицы значений формируется на этапе построения структуры, и платформа фиксирует описание типов каждой колонки в момент её создания. Это сделано для контроля целостности: все строки таблицы хранят значения, соответствующие заявленному типу, и механизмы индексирования, сортировки и свёртки опираются на эту гарантию.
Поэтому конструкция вида ТЗ.Колонки.Сумма.ТипЗначения = Новый ОписаниеТипов("Число"); не сработает — свойство только для чтения. Единственные операции, доступные для существующей колонки, — изменение заголовка, ширины и имени (с осторожностью, если на него есть ссылки в коде).
Из этого следует главный принцип: изменение типа — это всегда создание новой колонки (или новой таблицы) и миграция данных. Все приёмы ниже — вариации этого принципа.
Способ 1. Новая колонка с последующим удалением старой
Универсальный приём, когда таблица уже заполнена данными. Последовательность: добавить колонку с нужным типом, пройти циклом по строкам и перенести значения с преобразованием, удалить старую колонку, при необходимости переименовать новую.
// Исходная колонка "СуммаСтр" имеет тип Строка
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число",
Новый КвалификаторыЧисла(15, 2)));
Для Каждого СтрокаТЗ Из ТЗ Цикл
СтрокаТЗ.Сумма = Число(СтрЗаменить(СтрокаТЗ.СуммаСтр, ",", "."));
КонецЦикла;
ТЗ.Колонки.Удалить(ТЗ.Колонки.СуммаСтр);
Обратите внимание на преобразование значений. Функция Число() выбросит исключение, если в строке встретится нечисловое значение или пробелы. Для «грязных» данных безопаснее обернуть преобразование в попытку или предварительно проверять строку.
Новая колонка добавляется в конец таблицы. Если позиция важна (например, таблица потом выводится в табличный документ), используйте метод Вставить() с индексом нужной позиции.
- 1Определите целевой тип и сформируйте ОписаниеТипов с нужными квалификаторами
- 2Добавьте новую колонку через Колонки.Добавить() или Колонки.Вставить() на нужную позицию
- 3Пройдите циклом по строкам и перенесите значения с безопасным преобразованием
- 4Проверьте результат на контрольных строках, затем удалите старую колонку
- 5При необходимости переименуйте новую колонку в исходное имя
Способ 2. Вставка колонки на нужную позицию
Метод Колонки.Вставить(Индекс, Имя, Тип, Заголовок) позволяет разместить новую колонку строго на месте старой. Это удобно, когда порядок колонок зафиксирован в логике выгрузки или отображения.
ИндексСтарой = ТЗ.Колонки.Индекс(ТЗ.Колонки.Количество);
ТЗ.Колонки.Вставить(ИндексСтарой, "КоличествоНов",
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Для Каждого СтрокаТЗ Из ТЗ Цикл
СтрокаТЗ.КоличествоНов = СтрокаТЗ.Количество;
КонецЦикла;
ТЗ.Колонки.Удалить(ТЗ.Колонки.Количество);
ТЗ.Колонки.КоличествоНов.Имя = "Количество";
Переименование колонки через свойство Имя работает, но проверьте, что новое имя не совпадает с уже существующим — иначе получите исключение. Также помните: если в коде дальше есть обращения к колонке по старому имени, их нужно обновить.
Способ 3. Полное пересоздание таблицы
Когда меняется тип сразу нескольких колонок или структура таблицы пересматривается целиком, проще построить новую таблицу значений с нуля и перенести в неё данные. Этот же подход применяется, если исходная таблица получена из запроса или построителя и её структура удобнее переопределить полностью.
НоваяТЗ = Новый ТаблицаЗначений;
НоваяТЗ.Колонки.Добавить("Номенклатура",
Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
НоваяТЗ.Колонки.Добавить("Сумма",
Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
Для Каждого СтрокаТЗ Из СтараяТЗ Цикл
НоваяСтрока = НоваяТЗ.Добавить();
НоваяСтрока.Номенклатура = СтрокаТЗ.Номенклатура;
НоваяСтрока.Сумма = Число(СтрокаТЗ.СуммаСтр);
КонецЦикла;
Минус подхода — двойной расход памяти на время переноса: обе таблицы существуют одновременно. Для таблиц с сотнями тысяч строк это может быть ощутимо, поэтому на больших объёмах предпочтительнее способ с заменой колонки в той же таблице.
Сравнение вариантов
Подходит для 1–2 колонок и больших таблиц; экономит память, но требует аккуратности с порядком колонок и именами
Удобно при массовом изменении структуры; код проще, но на время переноса данные дублируются в памяти
Если данные можно получить заново из запроса с ВЫРАЗИТЬ — самый чистый вариант, но требует повторного обращения к БД
Изменение типа через запрос: ВЫРАЗИТЬ и перезаполнение
Если таблица значений изначально строится запросом к базе данных, тип колонки часто правильнее скорректировать на уровне самого запроса, а не мучиться с последующей переделкой. Оператор ВЫРАЗИТЬ приводит значение к нужному типу ещё на выборке.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВЫРАЗИТЬ(Товары.Сумма КАК ЧИСЛО(15, 2)) КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Товары";
ТЗ = Запрос.Выполнить().Выгрузить();
Такой подход особенно полезен, когда таблица получена выгрузкой результата запроса и колонка унаследовала неудобный составной тип или избыточную разрядность. ВЫРАЗИТЬ также умеет сокращать длину строк и уточнять тип ссылки до конкретного справочника или документа.
Составные типы и квалификаторы
Описание типов может включать несколько типов одновременно — например, колонка, которая хранит либо ссылку на номенклатуру, либо строку. Составной тип задаётся списком через запятую:
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Номенклатура"));
МассивТипов.Добавить(Тип("Строка"));
ОписаниеСоставное = Новый ОписаниеТипов(МассивТипов, ,
Новый КвалификаторыСтроки(150));
ТЗ.Колонки.Добавить("Значение", ОписаниеСоставное);
Квалификаторы (длина строки, разрядность числа, состав даты) влияют на хранение и отображение. Частая ситуация: числовая колонка создана без квалификаторов, и при выгрузке в СКД или табличный документ значения теряют нужную точность либо занимают избыточное место. Исправляется это тем же приёмом замены колонки, но уже с корректными квалификаторами.
Если нужно сузить составной тип до одного, не создавая новую колонку вручную, можно воспользоваться приёмом через копию: НоваяТЗ = ТЗ.СкопироватьКолонки() не поможет (типы скопируются как есть), поэтому структуру всё равно описывают вручную.
Проверка результата и производительность
После замены типа полезно убедиться, что данные перенеслись корректно. Минимальная проверка — сравнить итог по старой и новой колонке до удаления исходной, а также пройтись по нескольким строкам и убедиться, что значения соответствуют ожиданиям.
Для контроля типа в отладчике используйте выражение ТЗ.Колонки.Сумма.ТипЗначения — оно покажет итоговое описание типов. Проверить тип конкретного значения в строке можно функцией ТипЗнч(СтрокаТЗ.Сумма).
По производительности: перенос данных циклом — операция порядка O(n), и для таблиц в десятки тысяч строк она выполняется быстро. Проблемы начинаются на сотнях тысяч строк при работе на клиенте — в таких случаях переносите обработку на сервер и рассмотрите вариант получения данных заново через запрос с ВЫРАЗИТЬ вместо постобработки.
Как проверить результат
ТипЗначения содержит нужный тип и квалификаторы
Тип остался прежним или стал составным без необходимости
Сумма по новой колонке совпадает с контрольным значением
Итог отличается — часть строк не преобразовалась
ТипЗнч() возвращает ожидаемый тип для каждой проверенной строки
Встречаются Неопределено или значения исходного типа
Когда данные нельзя терять: безопасная последовательность
Если таблица содержит результаты длительной обработки или данные, которые дорого получить заново, не удаляйте исходную колонку до полной проверки переноса. Безопасная схема: создать новую колонку, перенести данные, сверить итоги и выборочные значения, только потом удалять старую.
Дополнительная страховка — сохранить копию таблицы через КопияТЗ = ТЗ.Скопировать() перед началом манипуляций. Это удвоит потребление памяти, но позволит откатиться при любой ошибке. После успешного завершения копию можно обнулить.
Частые вопросы
Можно ли изменить тип колонки без цикла по строкам?
Нет, штатного метода массового преобразования значений колонки в таблице значений не существует. Обход циклом — обязательный этап. Альтернатива — получить данные заново запросом с оператором ВЫРАЗИТЬ, если источник данных это позволяет.
Что будет, если присвоить значение несовместимого типа новой колонке?
Платформа попытается привести значение к типу колонки. Если приведение невозможно (например, строка с буквами в числовую колонку), значение станет Неопределено либо возникнет исключение — в зависимости от контекста. Поэтому преобразование лучше выполнять явно с проверкой.
Как изменить тип колонки в табличной части документа?
Никак — состав и типы колонок табличных частей задаются в конфигураторе и в режиме предприятия не меняются. Изменение типа реквизита табличной части делается через конфигуратор с последующим обновлением конфигурации базы данных, при этом платформа выполнит конвертацию хранимых данных.
Работает ли замена колонки для таблицы на форме?
Да, но с оговорками. Если таблица значений является реквизитом формы, динамическое изменение колонок требует программного изменения реквизитов формы (ИзменитьРеквизиты) и пересоздания связанных элементов отображения. Проще пересоздать данные в рамках уже объявленной структуры.
Как поменять тип на составной, не теряя существующие значения?
Добавьте новую колонку с составным описанием типов, включающим исходный тип, и перенесите значения без преобразования — присвоение пройдёт без потерь, так как старый тип входит в новый состав. Затем удалите исходную колонку.
Что важно запомнить
Тип существующей колонки таблицы значений изменить нельзя — только создать новую колонку с нужным ОписаниемТипов, перенести данные с преобразованием и удалить старую. Для данных из запроса эффективнее применять ВЫРАЗИТЬ на этапе выборки. Всегда проверяйте результат до удаления исходной колонки и обрабатывайте ошибки преобразования значений.