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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача создания универсального интерфейса для редактирования различных данных. Типичный пример: мы считываем реквизиты документа (организацию, дату, склад, сумму) и выводим их в интерфейс, где каждая строка соответствует отдельному реквизиту. Возникает вопрос: как сделать так, чтобы в строке «Организация» пользователь выбирал именно организацию, а в строке «Склад» — склад, если вся колонка имеет тип Произвольный?

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

Понимание структуры: Колонка против Строки

Прежде всего, проанализируем архитектуру объекта ТаблицаЗначений. В 1С тип данных задается для колонки в целом при ее создании. Мы не можем программно сказать, что «строка №5 имеет тип Число», если вся колонка определена как СправочникСсылка.Организации.

Однако мы можем использовать тип Произвольный (или не указывать тип вовсе). В этом случае в каждой ячейке этой колонки может храниться значение любого типа. Проблема здесь чисто интерфейсная: как объяснить платформе, какой именно тип данных предлагать пользователю для выбора при нажатии на кнопку выбора в конкретной строке?

Решение 1: Использование программного ограничения типа на форме

Это самый гибкий и современный способ для управляемых форм, позволяющий реализовать программное ограничение типа в конкретной ячейке. Рассмотрим ситуацию, когда у нас есть таблица на форме с колонками ИмяРеквизита и Значение. Тип колонки Значение — Произвольный.

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

  1. При заполнении таблицы получаем метаданные реквизитов документа.
  2. Сохраняем ОписаниеТипов каждого реквизита в служебную колонку.
  3. Используем событие элемента формы ПриАктивизацииСтроки или ПриНачалеРедактирования.

Рассмотрим пример кода для инициализации такой таблицы:


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

// Заполняем на основании метаданных документа "РеализацияТоваровУслуг"
МетаданныеДока = Метаданные.Документы.РеализацияТоваровУслуг;
Для Каждого Реквизит Из МетаданныеДока.Реквизиты Цикл
    НоваяСтрока = ТЗ.Добавить();
    НоваяСтрока.ИмяРеквизита = Реквизит.Имя;
    НоваяСтрока.ТипДляОграничения = Реквизит.Тип;
    // Устанавливаем пустое значение нужного типа, чтобы платформа понимала контекст
    НоваяСтрока.Значение = Реквизит.Тип.ПривестиЗначение(Неопределено);
КонецЦикла;

Теперь самое важное: управление вводом на форме. В обработчике события ПриАктивизацииСтроки для таблицы формы мы можем динамически менять свойства элемента управления:


&НаКлиенте
Процедура ТаблицаРеквизитовПриАктивизацииСтроки(Элемент)
    ТекущиеДанные = Элементы.ТаблицаРеквизитов.ТекущиеДанные;
    Если ТекущиеДанные <> Неопределено Тогда
        // Устанавливаем ограничение типа для поля ввода в текущей ячейке
        Элементы.ТаблицаРеквизитовЗначение.ОграничениеТипа = ТекущиеДанные.ТипДляОграничения;
    КонецЕсли;
КонецПроцедуры

Решение 2: Приведение типов и работа с пустыми ссылками

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

Выясним, как это работает. Если мы запишем в ячейку Справочники.Организации.ПустаяСсылка(), то при нажатии на кнопку выбора 1С сразу откроет справочник «Организации», так как текущее значение уже имеет этот тип. Для этого удобно использовать метод ПривестиЗначение() объекта ОписаниеТипов. Он преобразует переданное значение к наиболее подходящему типу из описания.

Решение 3: Типизация для передачи в запрос

Рассмотрим более сложную задачу. Если вам нужно передать такую «разношерстную» таблицу значений в запрос для создания временной таблицы, Произвольный тип колонки станет препятствием. СУБД требует жесткого определения типов для передачи в запрос. Для отладки таких механизмов и проверки данных во временных таблицах отлично подойдут консоль запросов УФ или bm Консоль запросов — для этого есть универсальные инструменты разработчика с консолью запросов.

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


// Собираем все типы, которые встречаются в нашей колонке "Значение"
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Организации"));
МассивТипов.Добавить(Тип("СправочникСсылка.Склады"));
МассивТипов.Добавить(Тип("Дата"));

ОписаниеСоставногоТипа = Новый ОписаниеТипов(МассивТипов);

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

// Заполняем данными...

Решение 4: Связь по типу (декларативный метод)

Посмотрим на возможности свойств элементов формы. У поля ввода существует свойство СвязьПоТипу. Обычно оно используется в связке с реквизитами, зависящими от владельца (например, цена за единицу зависит от номенклатуры). Однако этот механизм можно адаптировать. Если в строке таблицы есть колонка, содержащая ссылку на характеристику или другой объект, определяющий тип, СвязьПоТипу позволит автоматически фильтровать доступные типы данных в ячейке без написания лишнего кода в ПриАктивизацииСтроки.

Решение 5: Использование «Инструментов разработчика» (ИР)

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

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

← На главную