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

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

Как изменить тип колонки таблицы значений в 1С 8

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

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

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

Ниже разобраны рабочие способы для серверного кода и управляемых форм, ограничения каждого подхода, а также ошибки, которые чаще всего приводят к потере данных или падению обработки.

Почему тип колонки нельзя изменить напрямую

Колонка таблицы значений описывается объектом КолонкаТаблицыЗначений, у которого есть свойства Имя, Заголовок, Ширина и ТипЗначения. Первые три можно менять в любой момент, а вот ТипЗначения платформа фиксирует при добавлении колонки. Попытка присвоить этому свойству новое значение вызовет ошибку выполнения.

Такое ограничение связано с внутренним устройством таблицы: значения строк хранятся с учётом описания типов колонки, и смена типа «на лету» потребовала бы перестроения всех данных. Платформа перекладывает эту задачу на разработчика, чтобы преобразование было явным и контролируемым.

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

Способ 1: удалить колонку и добавить заново

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

ТЗ.Колонки.Удалить("Сумма");

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

Новый КвалификаторыЧисла(15, 2)));

Обратите внимание на позицию колонки: метод Добавить() вставляет колонку в конец. Если порядок колонок важен (например, таблица выводится на форму или в макет), используйте метод Вставить() с указанием индекса или запомните индекс до удаления:

ИндексКолонки = ТЗ.Колонки.Индекс(ТЗ.Колонки.Найти("Сумма"));

ТЗ.Колонки.Удалить("Сумма");

ТЗ.Колонки.Вставить(ИндексКолонки, "Сумма",

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

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

Способ 2: пересоздать колонку с переносом значений

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

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

Пример переноса строковых значений в числовую колонку:

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

Новый КвалификаторыЧисла(15, 2)));

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

Попытка

СтрокаТЗ.СуммаНов = Число(СтрЗаменить(СтрокаТЗ.Сумма, " ", ""));

Исключение

СтрокаТЗ.СуммаНов = 0;

КонецПопытки;

КонецЦикла;

ТЗ.Колонки.Удалить("Сумма");

ТЗ.Колонки.СуммаНов.Имя = "Сумма";

Ключевой момент — явное преобразование значений. Присвоение строки числовой колонке не вызовет автоматического приведения: платформа запишет Неопределено или значение по умолчанию, если тип не совместим. Поэтому используйте функции Число(), Дата(), Строка() и обработку исключений для «грязных» данных.

Способ 3: пересоздать таблицу целиком

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

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

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

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

НоваяТЗ.Колонки.Добавить("Количество",

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

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

НоваяСтрока = НоваяТЗ.Добавить();

НоваяСтрока.Номенклатура = СтрокаТЗ.Номенклатура;

НоваяСтрока.Количество = Число(СтрокаТЗ.Количество);

КонецЦикла;

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

Ещё один вариант — получить структуру через запрос: выгрузить таблицу во временную таблицу запроса и применить функции ВЫРАЗИТЬ() для приведения типов. Это удобно для больших таблиц, так как обработка идёт на уровне СУБД.

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

Удалить и добавить колонку

Подходит для пустой таблицы. Быстро, но уничтожает данные и сбрасывает позицию колонки.

Временная колонка с переносом

Универсальный способ для заполненной таблицы. Требует кода преобразования, но сохраняет остальные данные и порядок строк.

Пересоздание всей таблицы

Удобно при смене типов нескольких колонок. Требует больше памяти на время копирования.

Запрос с ВЫРАЗИТЬ

Эффективен для больших таблиц и сложных приведений, но требует помещения таблицы в запрос и навыков языка запросов.

Изменение типа колонки реквизита формы

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

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

МассивДобавляемых.Добавить(Новый РеквизитФормы("Сумма",

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

"ТаблицаДанных"));

МассивУдаляемых = Новый Массив;

МассивУдаляемых.Добавить("ТаблицаДанных.Сумма");

ИзменитьРеквизиты(МассивДобавляемых, МассивУдаляемых);

После вызова ИзменитьРеквизиты() данные удалённого реквизита теряются, а элементы формы, связанные со старой колонкой, нужно пересоздать или перепривязать — иначе получите ошибку «Поле не найдено» при открытии или обновлении формы.

Учтите, что ИзменитьРеквизиты() — ресурсоёмкая операция: форма фактически пересоздаётся. Не вызывайте её в цикле; собирайте все изменения в массивы и применяйте одним вызовом.

Составной тип и тип NULL как альтернатива

Иногда вместо смены типа правильнее расширить его. Если в колонке могут встречаться и строки, и числа, задайте составной тип: Новый ОписаниеТипов("Строка,Число", ...). Это избавляет от переноса данных, но усложняет сортировку, итоги и сравнения — платформа сравнивает значения разных типов по особым правилам, которые не всегда совпадают с ожиданиями.

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

Типичные ошибки
01
Попытка присвоить значение свойству ТипЗначения — ошибка выполнения, свойство только для чтения
02
Удаление колонки с данными без предварительного сохранения — значения теряются во всех строках
03
Присвоение строки числовой колонке без Число() — в ячейке окажется Неопределено или 0
04
Добавление колонки заново без Вставить() — колонка уезжает в конец и ломает макет вывода
05
Изменение реквизита формы в цикле по одному — многократное пересоздание формы и заметные тормоза
06
Ожидание автоматического приведения типов при ЗагрузитьКолонку() — метод копирует значения как есть

Проверка результата и отладка

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

Для Каждого Колонка Из ТЗ.Колонки Цикл

Сообщить(Колонка.Имя + ": " + Колонка.ТипЗначения);

КонецЦикла;

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

Если ТипЗнч(СтрокаТЗ.Сумма) <> Тип("Число") Тогда

Сообщить("Некорректное значение в строке " + ТЗ.Индекс(СтрокаТЗ));

КонецЕсли;

КонецЦикла;

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

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

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

Тип колонки после пересоздания
Норма

ТипЗначения содержит нужный тип и квалификаторы

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

Тип старый или составной без необходимости

Значения в строках
Норма

Все значения нужного типа, итоги совпадают с контрольными

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

Встречаются Неопределено или значения по умолчанию

Позиция колонки
Норма

Индекс колонки соответствует исходному

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

Колонка оказалась в конце таблицы

Форма после ИзменитьРеквизиты
Норма

Элементы отображают данные без ошибок

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

Ошибка привязки поля или пустая колонка на форме

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

Можно ли изменить тип колонки без удаления, через свойство ТипЗначения?

Нет. Свойство ТипЗначения у колонки таблицы значений доступно только для чтения, попытка присвоения вызовет ошибку. Единственные рабочие пути — пересоздание колонки или всей таблицы с переносом данных.

Что произойдёт со значениями строк при удалении колонки?

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

Как изменить длину строковой колонки, например с 50 на 200 символов?

Так же, как и смену типа: удалите колонку и добавьте заново с новым описанием — Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(200)). При переносе данных учтите, что строки длиннее старого ограничения в исходной таблице уже быть не могли, поэтому потерь не будет.

Почему после переноса в числовую колонку значения стали нулями?

Скорее всего, присваивалась строка без явного преобразования, и платформа подставила значение по умолчанию. Используйте функцию Число() с предварительной очисткой строки от пробелов и неразрывных пробелов, а неконвертируемые значения обрабатывайте через Попытка/Исключение.

Как изменить тип колонки таблицы на управляемой форме?

Через метод ИзменитьРеквизиты(): сформируйте массив добавляемых реквизитов с новым типом и массив удаляемых с полным путём вида «ИмяТаблицы.ИмяКолонки». После вызова перепривяжите элементы формы, так как старые связи с удалённым реквизитом перестанут работать.

Можно ли сменить тип колонки запросом?

Да, если поместить таблицу во временную таблицу запроса и применить ВЫРАЗИТЬ к нужным полям — результат будет новой таблицей с приведёнными типами. Способ эффективен для больших объёмов, но требует аккуратности: ВЫРАЗИТЬ не всегда справляется с «грязными» строками, и такие значения могут отбрасываться.

Итог

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

Тип колонки таблицы значений меняется только пересозданием: удалите колонку и добавьте с новым ОписаниеТипов, предварительно сохранив данные. Значения переносите с явным преобразованием через Число(), Дату() или Строку(). На управляемой форме используйте ИзменитьРеквизиты() одним вызовом. После изменения проверьте типы, контрольные итоги и позицию колонки.