Почему в расширении 1С нельзя выбрать тип ТаблицаЗначений для реквизита и как это обойти

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

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

Причина отсутствия ТаблицыЗначений в типах реквизитов

Для начала проанализируем ситуацию: тип ТаблицаЗначений является исключительно программным объектом. Он существует только в оперативной памяти сервера (или толстого клиента) в момент выполнения кода. У этого типа нет физического представления в таблицах базы данных SQL. Реквизит любого объекта метаданных (будь то справочник, документ или задача) должен иметь тип, который платформа может однозначно преобразовать в поле или набор полей в СУБД для постоянного хранения.

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

Различие между реквизитом объекта и реквизитом формы

Важно различать, где именно мы пытаемся добавить данные. Рассмотрим два варианта:

  1. Реквизит объекта (в дереве метаданных): Здесь ТаблицаЗначений недоступна по описанным выше причинам. Это касается и основной конфигурации, и расширений.
  2. Реквизит формы: Здесь ситуация иная. На форме можно создать реквизит и программно назначить ему тип ТаблицаЗначений. Однако при интерактивном добавлении реквизита в редакторе формы платформа чаще предлагает использовать ДанныеФормыКоллекция — это специальный тип-обертка, который позволяет отображать табличные данные в интерфейсе и передавать их между клиентом и сервером.

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

Решение 1: Использование Табличной части

Это самый правильный и стандартный способ хранения структурированных данных в 1С. Если вам нужно хранить таблицу в объекте расширения, мы создаем новую Табличную часть (ТЧ).

Проанализируем преимущества этого подхода:

Разберем по шагам процесс добавления ТЧ в расширение:

  1. Добавьте объект (например, Документ) в расширение.
  2. В дереве расширения перейдите к ветке «Табличные части» и нажмите «Добавить».
  3. Создайте необходимые колонки (Реквизиты ТЧ), указав нужные типы.
  4. Теперь вы можете работать с этими данными через стандартные механизмы: Объект.ИмяВашейТЧ.Добавить().

Решение 2: ХранилищеЗначений для сложных структур

Иногда структура таблицы заранее неизвестна или она слишком сложна для стандартной табличной части. В этом случае мы можем использовать реквизит с типом ХранилищеЗначений. В него можно «упаковать» (сериализовать) практически любой объект, включая ТаблицуЗначений, Массив или Структуру.

Посмотрим на пример кода для записи таблицы в реквизит объекта:


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

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

// Помещаем таблицу в реквизит типа ХранилищеЗначений
ОбъектХранилище = Новый ХранилищеЗначений(НоваяТаблица);
Объект.РеквизитХранилище = ОбъектХранилище;
Объект.Записать();

Для получения данных обратно используйте метод Получить():


Если ТипЗнч(Объект.РеквизитХранилище) = Тип("ХранилищеЗначений") Тогда
    ВосстановленнаяТаблица = Объект.РеквизитХранилище.Получить();
    Если ТипЗнч(ВосстановленнаяТаблица) = Тип("ТаблицаЗначений") Тогда
        // Работаем с таблицей
    КонецЕсли;
КонецЕсли;

Важный нюанс: Данные внутри ХранилищаЗначений невозможно прочитать обычным SQL-запросом. Платформа хранит их в бинарном виде. Используйте этот метод только тогда, когда поиск по этим данным внутри запросов не требуется.

Решение 3: Сериализация в JSON или XML (строковый реквизит)

Современный и очень гибкий метод — хранение таблицы в виде строки неограниченной длины. Проанализируем ситуацию: если мы преобразуем таблицу в формат JSON, мы получаем текстовую строку, которую легко хранить, передавать через API и даже просматривать глазами при отладке.

Разберем пример реализации через JSON:


// Сериализация таблицы в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МояТаблицаЗначений);
СтрокаДляХранения = ЗаписьJSON.Закрыть();

// Записываем в реквизит объекта (тип Строка неограниченной длины)
Объект.ДанныеТаблицыСтрокой = СтрокаДляХранения;

Этот метод удобен тем, что строку можно прочитать в консоли запросов, в отличие от ХранилищаЗначений. Однако, как и в предыдущем случае, полноценный поиск по колонкам внутри такой строки в запросе будет затруднен.

Особенности работы в расширениях

При работе в расширении помните о свойстве «Используемые типы». Если вы создаете колонку в табличной части и хотите назначить ей тип ссылки на объект из основной конфигурации, этот объект обязательно должен быть добавлен в расширение. В противном случае платформа просто не «увидит» этот тип в списке доступных.

Также учитывайте ограничение передачи данных между клиентом и сервером. Тип ТаблицаЗначений не существует на клиенте (в тонком клиенте или веб-клиенте). Если вам нужно передать данные из кода сервера на форму, используйте метод ЗначениеВРеквизитФормы(), который преобразует вашу таблицу в коллекцию данных формы.

Выводы и рекомендации

Подведем итог нашему анализу:

  1. Если нужны отчеты и поиск по данным — создавайте Табличную часть в расширении.
  2. Если нужно хранить произвольные данные «кучей», которые не нужны в запросах — используйте ХранилищеЗначений.
  3. Если важна гибкость и возможность просмотра данных в текстовом виде — используйте строковый реквизит и JSON.
  4. Никогда не путайте реквизиты метаданных (хранятся в БД) и программные объекты (живут только в коде).

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

← На главную