Разработка и Конфигурация · 13 мин
Как изменить тип значения колонки таблицы значений в 1С
Как изменить тип колонки таблицы значений в 1С: методы через ОписаниеТипов, пересоздание колонки, обход строк. Ограничения платформы, примеры кода и типичные ошибки.
Таблица значений в 1С — это несохраняемый объект, структура колонок которого задаётся при добавлении колонки методом ТаблицаЗначений.Колонки.Добавить(). Уже созданной колонке нельзя просто присвоить новый тип: свойство ТипЗначения у объекта «КолонкаТаблицыЗначений» доступно только для чтения. Поэтому изменение типа всегда сводится к одному из обходных приёмов — созданию новой колонки с нужным типом, переносу данных или полному пересозданию таблицы.
Задача возникает регулярно: колонка создана как строка, а нужно хранить числа для сортировки и итогов; колонка с типом «Строка» неограниченной длины не подходит для помещения таблицы в запрос; при загрузке из Excel все значения пришли строками, а дальше требуется типизированная обработка. Ниже разобраны рабочие способы, их ограничения и способы проверки результата.
Почему нельзя просто поменять тип колонки
Коллекция ТаблицаЗначений.Колонки хранит объекты типа «КолонкаТаблицыЗначений». У каждой колонки есть свойства Имя, ТипЗначения, Заголовок, Ширина. Из них программно изменяемы имя, заголовок и ширина, а ТипЗначения — свойство только для чтения. Попытка присвоить ему новое значение вызовет ошибку исполнения.
Это осознанное ограничение платформы: тип колонки участвует в построении индексов, сортировке, свёртке и передаче таблицы в запрос. Если бы тип менялся «на лету» при заполненных данных, платформа должна была бы неявно пересоздавать внутренние структуры, что чревато потерей данных. Поэтому разработчик сам управляет переносом значений и явно решает, как преобразовывать содержимое.
Важно понимать и обратное: тип отдельной ячейки ограничен типом колонки. Если колонка объявлена как «Строка(10)», присвоить ей число можно (оно будет приведено к строке), но получить из ячейки число без явного преобразования не получится.
Способ 1. Добавление новой колонки и перенос данных
Самый универсальный приём: рядом со старой колонкой создаётся новая с требуемым типом, значения переносятся построчно с явным преобразованием, затем старая колонка удаляется, а новой присваивается прежнее имя.
// Исходная колонка "СуммаСтр" имеет тип Строка, нужен Число(15,2)
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(20)));
// ... заполнение ТЗ ...
// 1. Новая колонка с нужным типом
ТЗ.Колонки.Добавить("СуммаНов", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
// 2. Перенос с преобразованием
Для Каждого СтрокаТЗ Из ТЗ Цикл
СтрокаТЗ.СуммаНов = Число(СтрЗаменить(СтрокаТЗ.Сумма, " ", ""));
КонецЦикла;
// 3. Удаляем старую, переименовываем новую
ИндексСтарой = ТЗ.Колонки.Индекс(ТЗ.Колонки.Найти("Сумма"));
ТЗ.Колонки.Удалить("Сумма");
ТЗ.Колонки.СуммаНов.Имя = "Сумма";
ТЗ.Колонки.Сдвинуть("Сумма", ИндексСтарой - ТЗ.Колонки.Индекс(ТЗ.Колонки.Сумма));Обратите внимание на два момента. Во-первых, функция Число() вызовет исключение, если строка содержит непреобразуемые символы (буквы, «р.», неразрывные пробелы). Перед преобразованием строку стоит очистить: убрать пробелы, заменить запятую на точку, отфильтровать лишние символы. Во-вторых, после удаления старой колонки позиция новой меняется — если порядок колонок важен (например, таблица выводится на форму), используйте Колонки.Сдвинуть().
- 1Добавьте новую колонку с требуемым ОписаниеТипов рядом со старой
- 2В цикле по строкам перенесите значения с явным преобразованием типа
- 3Проверьте, что преобразование не дало потерь (пустые или нулевые значения там, где были данные)
- 4Удалите старую колонку методом Колонки.Удалить()
- 5Переименуйте новую колонку в исходное имя и при необходимости сдвиньте её на прежнюю позицию
Способ 2. Пересоздание таблицы целиком
Если меняется тип нескольких колонок или структура таблицы пересматривается полностью, проще создать новую таблицу значений с правильным описанием колонок и скопировать в неё данные. Это особенно удобно, когда таблица строится по произвольному описанию, полученному извне.
Новая таблица создаётся конструктором Новый ТаблицаЗначений, колонки добавляются с нужными типами, затем строки переносятся через НоваяТЗ.Добавить() и ЗаполнитьЗначенияСвойств() с построчной обработкой отличающихся колонок. Метод ТЗ.Скопировать() здесь не поможет: он копирует таблицу вместе с исходными типами колонок.
Плюс подхода — чистый, предсказуемый результат и возможность за один проход переименовать колонки, изменить их порядок и отбросить лишние. Минус — двойной расход памяти на время переноса, что заметно на таблицах в сотни тысяч строк.
Сравнение подходов
Подходит, когда меняется тип одной-двух колонок. Сохраняет остальную структуру и данные без полного копирования таблицы.
Подходит при массовом изменении структуры. Даёт чистый результат, но требует больше памяти и аккуратного переноса всех колонок.
Профилактика проблемы: колонка объявляется с несколькими типами (например, Число и Строка), и смена типа вообще не требуется. Усложняет сортировку и передачу в запрос.
Способ 3. Типизация через запрос и функции преобразования
Когда таблица значений дальше участвует в запросе (помещается во временную таблицу), типизацию можно выполнить прямо в запросе. В тексте запроса доступны функции ВЫРАЗИТЬ(... КАК ЧИСЛО(15,2)), КАК СТРОКА(100), КАК ДАТА, а также оператор ВЫБОР КОГДА ... ТОГДА для условного преобразования.
Типичный сценарий: таблица загружена из внешнего источника, все колонки строковые. Таблица помещается в параметр запроса, а в выборке значения приводятся к нужным типам через ВЫРАЗИТЬ. Результат запроса выгружается методом Выгрузить() — и на выходе получается новая таблица значений, колонки которой уже имеют целевые типы.
У этого способа есть важное ограничение: если строка не может быть приведена к числу, результатом будет NULL, а не ошибка. Это удобно для фильтрации «мусорных» значений, но требует проверки на NULL при дальнейшей обработке.
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТЗ", ТаблицаИзФайла);
Запрос.Текст =
"ВЫБРАТЬ
| ВЫРАЗИТЬ(ТЗ.Код КАК СТРОКА(9)) КАК Код,
| ВЫРАЗИТЬ(ТЗ.Сумма КАК ЧИСЛО(15, 2)) КАК Сумма,
| ВЫРАЗИТЬ(ТЗ.ДатаСтр КАК ДАТА) КАК ДатаДок
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ &ТЗ КАК ТЗ
|;
|ВЫБРАТЬ * ИЗ ВТ_Данные";
ТипизированнаяТЗ = Запрос.Выполнить().Выгрузить();Типичные преобразования и их подводные камни
Строка → Число. Главные проблемы — неразрывные пробелы в качестве разделителя разрядов, запятая вместо точки, валютные символы. Перед Число() выполните СтрЗаменить по всем встречающимся разделителям. Помните о квалификаторах: Число(10,0) обрежет дробную часть при записи в ячейку.
Строка → Дата. Функция Дата() принимает строку строго в формате «ГГГГММДДччммсс» (время можно опустить). Даты вида «31.12.2023» нужно предварительно разобрать через СтрРазделить и собрать в канонический формат, либо использовать ВЫРАЗИТЬ в запросе с предварительной нормализацией.
Число → Строка. Платформа применяет региональные настройки форматирования, поэтому в строку могут попасть разделители групп разрядов. Для контролируемого результата используйте Формат(Значение, "ЧГ="), чтобы отключить группировку разрядов.
Сужение строки. Перевод колонки из «Строка(200)» в «Строка(50)» молча обрезает значения длиннее 50 символов при записи. Если данные ценны, сначала проверьте максимальную фактическую длину значений в колонке.
Ограничения: составные типы, запросы и длина строк
Колонка может иметь составной тип — например, Новый ОписаниеТипов("Число,Строка"). Это законный способ избежать смены типа, но цена решения — неоднозначность при сортировке (строки и числа сравниваются по особым правилам), невозможность корректной свёртки по такой колонке и проблемы при помещении таблицы в запрос: СУБД требует однозначного типа поля.
Отдельное частое ограничение: таблицу значений со строковой колонкой неограниченной длины нельзя поместить в запрос — платформа выдаст ошибку. Если таблица предназначена для запроса, строковые колонки должны иметь квалификатор длины. Это одна из самых частых причин, зачем вообще меняют тип колонки.
Также учтите: если таблица значений связана с реквизитом формы (например, выведена в табличное поле), добавление и удаление колонок на сервере потребует повторного связывания или обновления отображения. В управляемых формах структуру реквизита типа «ТаблицаЗначений» меняют через ИзменитьРеквизиты(), а не прямыми манипуляциями с колонками данных формы.
Проверка результата после смены типа
После переноса данных убедитесь, что тип действительно изменился и данные не пострадали. Минимальная проверка — сравнить количество строк и контрольные итоги до и после. Для числовой колонки сравните сумму старых значений (преобразованных тем же способом) с суммой новой колонки.
Полезно также проверить тип программно: ТЗ.Колонки.Сумма.ТипЗначения.СодержитТип(Тип("Число")) должно вернуть Истина. Для выборочной проверки значений используйте ТипЗнч(ТЗ[0].Сумма) — он покажет фактический тип значения в ячейке.
Как проверить результат
ТипЗначения содержит целевой тип, лишних типов нет
Остался старый тип или нежелательный составной тип
Итог по новой колонке совпадает с итогом по преобразованным старым значениям
Итог меньше — часть значений не преобразовалась или обрезалась
Пусто там, где исходное значение было пустым или нулевым
Нули и пустые строки появились там, где были данные
Таблица помещается в запрос без ошибок, соединения по колонке работают
Ошибка о неограниченной длине строки или несовместимости типов
Практические рекомендации
По возможности решайте проблему на этапе создания таблицы: если данные загружаются из внешнего источника, сразу объявляйте колонки с целевыми типами и преобразуйте значения в момент заполнения, а не после. Это дешевле, чем двойной перенос данных.
Для преобразования строк в числа в цикле используйте безопасную обёртку: попытка преобразования внутри Попытка ... Исключение с записью проблемного значения в журнал или отдельную таблицу ошибок. Так вы не потеряете всю обработку из-за одной некорректной строки.
Если тип колонки приходится менять регулярно в разных местах кода, вынесите операцию в общую функцию вида ИзменитьТипКолонки(ТЗ, ИмяКолонки, НовоеОписаниеТипов). Это уменьшит количество дублирующегося кода и снизит риск забыть переименование или сдвиг колонки.
Частая причина, по которой разработчики ищут способ сменить тип колонки, — загрузка из Excel или CSV, где всё приходит строками. В этом случае эффективнее не менять типы постфактум, а написать функцию преобразования значения по заданному типу и применять её прямо при чтении файла. Таблица сразу получается типизированной, и вся тема замены типов отпадает.
Что важно запомнить
Тип колонки таблицы значений изменить напрямую нельзя — свойство ТипЗначения доступно только для чтения. Рабочие приёмы: новая колонка с нужным ОписаниеТипов и перенос данных, пересоздание таблицы целиком или типизация через ВЫРАЗИТЬ в запросе. Перед удалением старой колонки сохраните копию данных, а после переноса сверьте контрольные итоги.
Частые вопросы
Можно ли изменить тип колонки без потери данных?
Да, если переносить значения в новую колонку с корректным преобразованием. Потери возможны только при сужении типа (обрезание длинных строк, округление чисел) или при непреобразуемых значениях. Сверка контрольных итогов до и после переноса покажет, прошла ли операция без потерь.
Как изменить тип колонки таблицы значений на форме?
Если таблица является реквизитом формы, прямые манипуляции с колонками недостаточны. Структуру реквизита меняют методом формы ИзменитьРеквизиты(): сначала удаляют реквизит-колонку со старым типом, затем добавляют новый с целевым ОписаниеТипов, после чего переносят данные и при необходимости пересоздают связанные элементы формы.
Почему таблица значений не помещается в запрос?
Наиболее частая причина — строковая колонка с неограниченной длиной. СУБД требует конкретного типа поля, поэтому такие колонки нужно пересоздать с квалификатором длины, например Строка(100). Ещё одна причина — составной тип колонки с несовместимыми для запроса типами.
Что делать, если при Число() возникает ошибка преобразования?
Очистите строку перед преобразованием: удалите пробелы (включая неразрывные — символ с кодом 160), замените запятую на точку, уберите валютные обозначения. Оберните преобразование в Попытка/Исключение, чтобы одна некорректная строка не прерывала обработку всей таблицы, и логируйте проблемные значения.
Можно ли сделать колонку, принимающую и числа, и строки?
Да, при добавлении колонки передайте составной тип: Новый ОписаниеТипов("Число,Строка"). Учтите последствия: сортировка по такой колонке даёт неочевидный порядок, свёртка и итоги работают только с числовой частью, а помещение таблицы в запрос может завершиться ошибкой несовместимости типов.
Как изменить тип колонки у дерева значений?
Точно так же, как у таблицы значений: коллекция колонок у дерева значений устроена идентично, свойство ТипЗначения также доступно только для чтения. Применяются те же приёмы — добавление новой колонки с обходом строк дерева (включая вложенные уровни через рекурсию) или пересоздание дерева целиком.