При переходе от разработки интерфейсных механизмов к серверным процессам, таким как регламентные задания, разработчики часто сталкиваются с ограничением: в метаданных объекта (например, в табличной части обработки или реквизите типа ТаблицаЗначений) невозможно выбрать тип СписокЗначений для колонки. Это происходит потому, что тип СписокЗначений является динамическим объектом и предназначен для работы в оперативной памяти или интерфейсе, но не для прямого хранения в физических таблицах базы данных SQL.
В этой статье мы подробно разберем, как обойти это ограничение, проанализируем различные подходы к архитектуре данных и выясним, как эффективно работать с таблицами, содержащими более 40 колонок, в фоновых процессах.
Разберем ситуацию: когда вы создаете таблицу на форме, платформа позволяет использовать СписокЗначений, так как данные формы существуют только в контексте текущего сеанса пользователя. Однако, как только вы пытаетесь добавить аналогичную колонку в реквизиты обработки в конфигураторе, этот тип пропадает из списка доступных. Причина заключается в типизации СУБД. База данных должна четко понимать, какой объем памяти выделить под поле. СписокЗначений — это сложный объект, который может содержать неограниченное количество элементов разных типов, и платформа не может «уложить» его в одну стандартную ячейку таблицы БД без дополнительных инструментов преобразования.
Если ваша задача — выполнить расчет в регламентном задании, вам не обязательно привязываться к жестко заданным реквизитам обработки в метаданных. Самый гибкий и правильный путь — создание таблицы значений непосредственно в коде модуля. В этом случае ограничений на типы колонок нет.
Рассмотрим ситуацию, когда у вас более 40 колонок. Чтобы не описывать каждую из них вручную, мы можем автоматизировать процесс. Проанализируем пример кода, который создает структуру таблицы динамически:
// Создаем таблицу в оперативной памяти сервера
ТЗ_Расчет = Новый ТаблицаЗначений;
// Вместо ручного добавления 40 колонок, используем массив имен
МассивИменКолонок = Новый Массив;
МассивИменКолонок.Добавить("Номенклатура");
МассивИменКолонок.Добавить("Склад");
// ... добавляем остальные колонки
Для Каждого ИмяКолонки Из МассивИменКолонок Цикл
Если ИмяКолонки = "СписокАналогов" Тогда
// Здесь мы спокойно назначаем нужный нам тип
ТЗ_Расчет.Колонки.Добавить(ИмяКолонки, Новый ОписаниеТипов("СписокЗначений"));
Иначе
ТЗ_Расчет.Колонки.Добавить(ИмяКолонки);
КонецЕсли;
КонецЦикла;
Этот подход идеален для регламентных заданий, так как ТаблицаЗначений, созданная программно, живет ровно столько, сколько выполняется процедура расчета, и не нагружает базу данных лишними структурами.
Если вам все же необходимо сохранить таблицу со списками значений в базе данных (например, чтобы одно регламентное задание подготовило данные, а другое позже их обработало), используйте тип ХранилищеЗначений. Это специальный тип данных, который позволяет упаковать («сериализовать») любой объект 1С в двоичные данные.
Выясним, как это реализовать по шагам:
ХранилищеЗначений.Получить().Пример упаковки данных:
// Предположим, ОбъектБД - это наша обработка или документ
СписокДляХранения = Новый СписокЗначений;
СписокДляХранения.Добавить("Значение 1");
// Помещаем список в хранилище
ОбъектБД.ДанныеСписка = Новый ХранилищеЗначений(СписокДляХранения);
ОбъектБД.Записать();
Проанализируем ситуацию, когда данных много и они должны быть читаемы или передаваемы между разными системами. Вместо сложных структур с УИДами (уникальными идентификаторами) и вспомогательными таблицами, можно использовать строковую сериализацию. Список значений легко преобразуется в строку JSON.
Рассмотрим преимущества этого метода: Во-первых, данные хранятся в обычном текстовом поле неограниченной длины в метаданных. Во-вторых, структуру JSON легко отлаживать, просто просмотрев текст строки.
Пример преобразования:
// Превращаем СписокЗначений в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
СериализаторXDTO.ЗаписатьJSON(ЗаписьJSON, МойСписокЗначений);
СтрокаДляБД = ЗаписьJSON.Закрыть();
// И наоборот, при чтении в регламентном задании
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаДляБД);
МойСписокЗначений = СериализаторXDTO.ПрочитатьJSON(ЧтениеJSON, Тип("СписокЗначений"));
Если расчет в регламентном задании предполагает оперирование огромными массивами данных (миллионы строк), то ТаблицаЗначений в памяти может вызвать переполнение стека или нехватку оперативной памяти. В этом случае целесообразно рассмотреть Регистр Сведений.
Разберем нюансы создания такого регистра с 40+ колонками:
ХранилищеЗначений внутри ресурса регистра.Посмотрим на проблему с точки зрения контекста. Регламентное задание всегда выполняется на Сервере. У него нет доступа к Экспортным процедурам модулей форм. Если ваш расчет ранее находился в модуле формы, его необходимо вынести в Модуль Менеджера обработки или в Общий модуль с включенным признаком «Сервер».
Рассмотрим типичную ошибку: попытка передать в фоновое задание ссылку на форму или элементы управления. Помните, что передавать в параметры фонового задания можно только сериализуемые типы данных. ТаблицаЗначений и СписокЗначений являются сериализуемыми, поэтому вы можете подготовить их заранее и передать как параметры функции запуска фонового задания.
Подведем итог. Отсутствие типа СписокЗначений в конфигураторе — это не ошибка, а особенность проектирования баз данных. Для решения задачи в регламентном задании мы рекомендуем:
Выбор конкретного метода зависит от объема данных и необходимости их последующего анализа средствами запросов 1С.