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