Как указать типы данных для колонок таблицы значений в 1С

· 9 мин

Содержание

Тип колонки задаётся третьим параметром метода Колонки.Добавить() в виде объекта ОписаниеТипов. Если параметр не передать, колонка принимает значения любого типа: платформа ничего не проверяет и ничего не приводит. Для быстрых вспомогательных таблиц это допустимо, для всего остального лучше типизировать колонки сразу.

Типизация даёт три вещи. Значение при записи в ячейку приводится к нужному типу. Колонка в отладчике и на форме ведёт себя предсказуемо: числа выравниваются как числа, даты показываются как даты. И наконец, выгрузка такой таблицы в реквизит формы или табличную часть не ломается из-за неожиданного типа.

Создаём таблицу и добавляем колонки с типом

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

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

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

Таблица.Колонки.Добавить("ДатаОтгрузки", Новый ОписаниеТипов("Дата"), "Дата отгрузки", 12);

Нужно вставить колонку не в конец, а на конкретную позицию? Метод Колонки.Вставить(Индекс, Имя, ТипЗначений, Заголовок, Ширина) работает так же, но первым параметром принимает индекс. Нумерация колонок начинается с нуля.

Колонку можно сразу получить в переменную: Колонка = Таблица.Колонки.Добавить("Сумма", ...). Через неё потом читаются Колонка.Имя, Колонка.Заголовок и Колонка.ТипЗначения.

Простые типы: строка, число, дата, булево

В конструктор ОписаниеТипов имена типов передаются строкой. Для простых типов это "Строка", "Число", "Дата", "Булево". Если тип нужно уточнить, вторым и третьим параметрами идут квалификаторы.

ТипКвалификаторЧто задаёт
ЧислоКвалификаторыЧисла(Разрядность, РазрядностьДробнойЧасти, ДопустимыйЗнак)Всего знаков, знаков после запятой, можно ли отрицательные
СтрокаКвалификаторыСтроки(Длина, ДопустимаяДлина)Длину и признак: фиксированная или переменная
ДатаКвалификаторыДаты(ЧастиДаты)Дата, время или дата и время

Число с точностью

Сумма в рублях и копейках: 15 знаков всего, 2 после запятой.

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

Число 1234567.891 в такой колонке превратится в 1234567.89. Это поведение квалификатора: лишние знаки отбрасываются, а не вызывают ошибку.

Строка с ограничением длины

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

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

Обратите внимание на запятые: конструктор принимает параметры в порядке «Типы, ДобавляемыеТипы, ИсключаемыеТипы, КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыДаты». Квалификатор строки стоит на пятой позиции, после квалификатора числа. Лишние запятые легко пропустить, поэтому после написания проверьте тип колонки в отладчике.

Дата без времени

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

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

Составные и ссылочные типы

Составной тип позволяет колонке хранить значения разных типов. Имена перечисляются через запятую в одной строке:

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

Ссылочные типы пишутся так же, по имени типа в метаданных:

Таблица.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Таблица.Колонки.Добавить("Документ", Новый ОписаниеТипов("ДокументСсылка.РеализацияТоваровУслуг"));

Колонка с типом «любая ссылка на справочник» создаётся именем "СправочникСсылка" без точки и конкретного справочника. Для документов — "ДокументСсылка". Этого достаточно для колонки-приёмника, в которую складывают разнородные ссылки.

Имя объекта в строке типа должно существовать в конфигурации точно. Опечатка в "СправочникСсылка.Номенклатуры" не даст ошибки компиляции, она всплывёт только при выполнении метода: платформа сообщит, что тип не найден.

Типы из массива

Когда список типов собирается программно, удобнее передать массив объектов Тип:

МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Строка"));
МассивТипов.Добавить(Тип("Число"));
Описание = Новый ОписаниеТипов(МассивТипов);

Когда составной тип оправдан

Составная колонка нужна не так часто, как кажется. Типичные случаи:

  • 🔹 Универсальная таблица настроек, где значение бывает строкой, числом или датой в зависимости от строки.
  • 🔹 Колонка «Основание» со ссылками на разные виды документов.
  • 🔹 Временная таблица обмена, куда складывают данные из внешнего источника до разбора.

Если значения однородны, составной тип только усложняет код: придётся проверять ТипЗнч(Значение) перед каждым действием. Для колонки со ссылками на разные документы проще один раз задать "ДокументСсылка" и дальше работать со свойством Метаданные() самой ссылки.

Когда в составной колонке нужен контроль, пользуйтесь связкой «описание типов плюс проверка»:

Допустимо = Описание.Типы().Найти(ТипЗнч(Значение)) <> Неопределено;
Если Не Допустимо Тогда
	ВызватьИсключение "Недопустимый тип значения: " + Строка(ТипЗнч(Значение));
КонецЕсли;

Так ошибка проявляется там, где допущена, а не через десять шагов в отчёте с неверными итогами.

ОписаниеТипов как инструмент гибкой настройки

Один и тот же объект ОписаниеТипов можно использовать для нескольких колонок и достраивать от готового. Второй и третий параметры конструктора позволяют добавить или исключить типы из уже существующего описания.

// Взять описание у реквизита и добавить к нему «Неопределено»
Исходное = Метаданные.Справочники.Номенклатура.Реквизиты.Артикул.Тип;
Расширенное = Новый ОписаниеТипов(Исходное, "Неопределено");
Таблица.Колонки.Добавить("Артикул", Расширенное);

Так колонка получает ровно тот же тип, что и реквизит в метаданных, включая квалификаторы длины. Не придётся вручную дублировать «Строка, 25 символов»: если разработчик позже изменит длину реквизита, в новой таблице она подтянется сама.

Описание типов можно взять и у реквизита формы, и у уже существующей колонки:

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

Проверка и приведение значения

У ОписаниеТипов есть метод ПривестиЗначение. Он возвращает значение, приведённое к типу описания, а если привести нельзя, то пустое значение первого типа. Это удобно для проверки перед записью в таблицу:

ОписаниеЧисла = Новый ОписаниеТипов("Число");
Результат = ОписаниеЧисла.ПривестиЗначение("125");   // 125
Результат = ОписаниеЧисла.ПривестиЗначение("abc");   // 0

Проверить, входит ли тип значения в описание, можно через Описание.Типы().Найти(ТипЗнч(Значение)) <> Неопределено.

Заполнение таблицы и преобразование типов

При записи значения в ячейку платформа приводит его к типу колонки. Строка «15» в числовой колонке станет числом 15, а строка «текст» превратится в 0. Исключения не будет, и это самая коварная особенность: ошибка тихо превращается в ноль.

Строка = Таблица.Добавить();
Строка.Наименование = "Болт М8";
Строка.Количество = "12";        // в ячейке будет число 12
Строка.ДатаОтгрузки = '20261015'; // литерал даты

Лучше приводить значения явно в тех местах, где источник ненадёжен: чтение файла, ввод пользователя, разбор XML. Тогда видно, что и откуда берётся.

Как изменить тип существующей колонки

Свойство ТипЗначения у колонки доступно только для чтения. Поменять тип напрямую нельзя. Рабочая схема из четырёх действий:

  1. Добавить новую колонку с нужным типом и временным именем.
  2. Скопировать данные из старой колонки: в цикле по строкам или методами ВыгрузитьКолонку и ЗагрузитьКолонку.
  3. Удалить старую колонку командой Таблица.Колонки.Удалить("Старая").
  4. Переименовать новую: свойство Имя у колонки доступно на запись.
Таблица.Колонки.Добавить("КоличествоЧисло", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 3)));
Для Каждого Стр Из Таблица Цикл
	Стр.КоличествоЧисло = Стр.Количество;
КонецЦикла;
Таблица.Колонки.Удалить("Количество");
Таблица.Колонки.КоличествоЧисло.Имя = "Количество";

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

Таблица из запроса

Когда таблица получена через Результат.Выгрузить(), типы колонок определяются запросом. Чтобы задать тип поля явно, в тексте запроса используйте ВЫРАЗИТЬ(Поле КАК Число(15, 2)) или ВЫРАЗИТЬ(Поле КАК Строка(100)). Это особенно важно для полей, полученных конструкцией ВЫБОР: без приведения тип бывает составным, а строка получается неограниченной длины.

Обход колонок и проверка структуры

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

Для Каждого Колонка Из Таблица.Колонки Цикл
	Типы = Колонка.ТипЗначения.Типы();
	Сообщить(Колонка.Имя + ": типов " + Типы.Количество());
КонецЦикла;

Колонку по имени ищет Таблица.Колонки.Найти("Количество"). Если такой нет, вернётся Неопределено, так что проверяйте результат перед обращением к свойствам. Прямое обращение Таблица.Колонки.Количество при отсутствии колонки вызовет ошибку.

Копирование структуры без данных

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

Индексы и производительность

Таблица значений умеет строить индексы. Они ускоряют метод Найти, НайтиСтроки и отборы по колонкам. Индексы задаются на таблице, а не на колонке:

Таблица.Индексы.Добавить("Номенклатура, Склад");

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

Несколько практических приёмов для больших таблиц:

  • 🔹 Выбирайте узкий тип. Колонка с типом «Число(10,0)» экономичнее колонки без типа.
  • 🔹 Избегайте составных типов там, где значения однородны. Для составного типа платформе приходится хранить признак типа в каждой ячейке.
  • 🔹 Ссылочные колонки индексируются эффективнее строковых: сравниваются ссылки, а не тексты.
  • 🔹 Если нужно сгруппировать и просуммировать, используйте Свернуть("Колонка1", "Сумма"). Колонки измерений и ресурсов должны существовать заранее.

Индекс по колонке с типом без ограничений работает, но сравнение разных типов в одной колонке замедляет поиск. Это ещё один довод за конкретный тип.

Перед тем как типизировать колонку
Выполнено: 0 / 4

Типичные ошибки и как их исправить

Большинство проблем с типами колонок повторяется от проекта к проекту. Ниже самые частые, с признаком и способом проверки.

Диагностика: выберите симптом

Ещё один частый случай: попытка присвоить значение свойству ТипЗначения у колонки. Свойство только для чтения, ошибка возникнет сразу, и решать задачу нужно через новую колонку (см. выше).

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

Можно ли добавить колонку без типа?
Да. Достаточно передать только имя: Таблица.Колонки.Добавить("Поле"). Такая колонка принимает любые значения без приведения. Это быстро, но проверок типа нет.
Как узнать типы колонок уже готовой таблицы?
Обойдите Таблица.Колонки циклом и прочитайте Колонка.ТипЗначения. Список конкретных типов вернёт метод Типы() у описания.
Чем «Строка» без длины отличается от строки с длиной?
Без квалификатора длина не ограничена. С квалификатором фиксированной длины значение дополняется пробелами до нужной длины, с переменной ограничивается сверху.
Можно ли указать несколько типов сразу?
Да, перечислите их через запятую в одной строке: "Строка, Число". Получится составной тип.
Нужен ли тип колонки, если таблицу выгружают в табличную часть?
Желательно. Если типы совпадают с реквизитами табличной части, загрузка проходит без приведений и потерь точности.
Как задать тип колонки, если таблица на форме, а не в коде?
Реквизит формы типа «ТаблицаЗначений» настраивается в конфигураторе: в списке колонок реквизита для каждой колонки выбирается тип. Программно колонки такого реквизита меняют через ДобавитьРеквизиты и ИзменитьРеквизиты формы.