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

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

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

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

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

Выбор способа зависит от того, есть ли в таблице данные, сколько строк нужно обработать и где используется таблица — только внутри процедуры или она связана с элементом формы, реквизитом объекта, запросом. Ниже разобраны рабочие приёмы с готовым кодом, ограничения каждого подхода и способы проверить, что преобразование прошло корректно.

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

Коллекция ТаблицаЗначений.Колонки предоставляет методы Добавить(), Удалить(), Вставить(), Сдвинуть(), Найти(), но у объекта КолонкаТаблицыЗначений свойство ТипЗначения доступно только для чтения. Попытка присвоить ему новое значение вызовет ошибку времени выполнения.

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

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

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

Самый простой вариант, когда таблица пустая или данные в колонке можно потерять. Колонка удаляется через Колонки.Удалить(), затем добавляется с тем же именем, но с новым описанием типов.

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

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

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

ИндексНужнойПозиции = 2;

Таблица.Колонки.Сдвинуть("Сумма", ИндексНужнойПозиции - Таблица.Колонки.Индекс(Таблица.Колонки.Найти("Сумма")));

Если таблица связана с реквизитом формы типа «ТаблицаЗначений», после изменения структуры колонок программно нужно пересоздать элементы формы, отображающие колонки, иначе визуальная часть будет показывать старую структуру или возникнет ошибка при обращении к удалённой колонке.

Способ 2: новая колонка с переносом и преобразованием данных

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

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

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

СтрокаТаблицы.СуммаНовая = СтроковыеФункцииКлиентСервер.СтрокаВЧисло(СтрокаТаблицы.Сумма);

КонецЦикла;

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

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

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

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

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

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

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

НоваяТаблица = Таблица.СкопироватьКолонки();

НоваяТаблица.Колонки.Удалить("ДатаСтрокой");

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

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

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

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТаблицы);

НоваяСтрока.ДатаСтрокой = Дата(СтрокаТаблицы.ДатаСтрокой);

КонецЦикла;

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

Для больших таблиц рассмотрите альтернативу через запрос: выгрузите таблицу во временную таблицу запроса и выполните преобразование функциями языка запросов (ВЫРАЗИТЬ, ПОДСТРОКА, ДАТАВРЕМЯ). Результат запроса — уже новая таблица с нужными типами колонок.

Если таблица значений формируется из запроса, часто проще не менять типы после выгрузки, а сразу задать нужный тип в тексте запроса через ВЫРАЗИТЬ(Поле КАК Число(15,2)). Тогда таблица придёт с корректными типами колонок, и никакой постобработки не потребуется.
ПЗ
Практическое замечание

Как задать составной тип и квалификаторы

Колонка может хранить значения нескольких типов — для этого в конструктор ОписаниеТипов передаётся массив типов или строка с перечислением типов через запятую:

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

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

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

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

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

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

Для ссылочных типов указывайте конкретный тип, например Новый ОписаниеТипов("СправочникСсылка.Номенклатура"). Если в колонке могут быть ссылки на разные справочники, перечислите их все в массиве типов — это корректнее, чем хранить строковое представление ссылки.

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

После изменения структуры убедитесь, что тип колонки соответствует ожиданиям. Программно это делается через свойство ТипЗначения:

ОписаниеКолонки = Таблица.Колонки.Найти("Сумма").ТипЗначения;

Сообщить(ОписаниеКолонки.СодержитТип(Тип("Число"))); // Истина, если тип задан верно

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

Типичные ошибки
01
Попытка присвоить значение свойству ТипЗначения колонки — свойство доступно только для чтения, возникнет ошибка времени выполнения
02
Удаление колонки до переноса данных — значения теряются безвозвратно
03
Сужение типа без контроля: строка длиной 200 заменяется на 50, и часть данных обрезается при записи
04
Переименование новой колонки до удаления старой с тем же именем — ошибка дублирования имени колонки
05
Забытый Сдвинуть() после пересоздания колонки — колонка оказывается в конце, ломая вывод в табличное поле или печатную форму
Контрольные точки

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

Тип колонки
Норма

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

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

Тип остался прежним или состав типов шире, чем требуется

Данные в строках
Норма

Значения перенесены, дробные части и длины строк сохранены

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

Пустые значения, обрезанные строки, потерянная точность чисел

Порядок колонок
Норма

Колонка на исходной позиции

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

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

Когда какой способ выбрать

Единых правил нет, но ориентиры помогают не потратить время на неподходящий вариант. Для пустой таблицы или таблицы, которая ещё только строится, всегда проще удалить и пересоздать колонку. Для заполненной таблицы с одной-двумя изменяемыми колонками достаточно новой колонки с переносом. При массовом изменении структуры или необходимости сохранить исходные данные до конца обработки — пересоздание таблицы или запрос с ВЫРАЗИТЬ.

Маршрут решения

Как выбрать действие

Таблица пустая или данные колонки не нужныУдалите колонку и добавьте заново с новым ОписаниеТипов
Таблица заполнена, меняется тип одной колонкиДобавьте новую колонку, перенесите значения в цикле, удалите старую, переименуйте
Меняется несколько колонок или нужна страховка исходных данныхПостройте новую таблицу через СкопироватьКолонки() и скопируйте строки
Таблица формируется запросомЗадайте тип прямо в запросе через ВЫРАЗИТЬ и не меняйте структуру после выгрузки
Итог

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

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

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

Можно ли изменить только длину строки у строковой колонки?

Напрямую — нет, это тоже изменение типа. Создайте новую колонку с нужными КвалификаторыСтроки, перенесите значения и удалите старую. Учтите, что при уменьшении длины длинные значения будут обрезаны.

Почему после пересоздания колонки она оказалась в конце таблицы?

Метод Добавить() всегда помещает колонку в конец коллекции. Восстановите позицию методом Колонки.Сдвинуть(), вычислив смещение от текущего индекса к нужному.

Как сделать колонку, которая хранит и числа, и строки?

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

Что будет, если записать в числовую колонку строку?

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

Можно ли изменить тип колонки таблицы значений на форме?

Можно программно: изменить структуру реквизита формы через ИзменитьРеквизиты() с новым описанием типов, а затем пересоздать связанные элементы формы. Сами данные при этом нужно перенести отдельно, так как изменение реквизитов очищает изменяемую колонку.

Как изменить тип колонки, если таблица получена из запроса?

Проще всего не менять после выгрузки, а задать тип в тексте запроса функцией ВЫРАЗИТЬ(Поле КАК Число(15,2)). Тогда результат запроса сразу будет содержать колонку с нужным типом и квалификаторами.