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