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