Как реализовать множественный выбор в одном поле ввода в 1С

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

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

Постановка задачи и выбор стратегии

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

Проанализируем ситуацию: если мы просто добавим на форму реквизит с типом СписокЗначений, он не будет автоматически сохраняться вместе с документом или справочником, так как 1С не умеет напрямую записывать коллекции в одиночные поля таблиц SQL без преобразования.

Решение 1: Реализация интерфейса на обычных формах

Рассмотрим, как заставить обычное поле ввода работать с множественным выбором. Для этого нам понадобится программная обработка события НачалоВыбора. Вместо стандартного окна выбора мы будем вызывать форму списка программно.

Разберем шаги реализации:

  1. Установим у поля ввода на форме тип значения СписокЗначений (или оставим строковым для отображения).
  2. В обработчике события НачалоВыбора пропишем следующий алгоритм (сформировать каркас которого поможет консоль кода + ИИ-помощник):

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

КонецПроцедуры

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

Решение 2: Методы хранения данных в одном реквизите

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

Способ А: Использование ХранилищаЗначений

Это самый мощный способ, позволяющий хранить практически любые объекты 1С в бинарном виде. Для этого в метаданных реквизиту объекта нужно назначить тип ХранилищеЗначений.


// Запись данных в объект
Объект.ПолеДляХранения = Новый ХранилищеЗначений(СписокДляЗаписи);

// Чтение данных при открытии формы
Коллекция = Объект.ПолеДляХранения.Получить();
Если ТипЗнч(Коллекция) = Тип("СписокЗначений") Тогда
    ПолеНаФорме = Коллекция;
КонецЕсли;

Способ Б: Сериализация в XML или JSON. Для визуальной проверки сохраненных данных удобно использовать просмотр JSON с форматированием.

Если мы хотим сохранить читаемость данных (например, для последующего анализа или обмена), лучше использовать текстовые форматы. Разберем пример с JSON, который является современным стандартом.


// Преобразование СпискаЗначений (массива ссылок) в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СписокЗначений.ВыгрузитьЗначения());
СтрокаДляБД = ЗаписьJSON.Закрыть();

// Обратное преобразование
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(СтрокаДляБД);
МассивСсылок = ПрочитатьJSON(ЧтениеJSON);

Способ В: Внутренняя строка 1С (ЗначениеВСтрокуВнутр)

Рассмотрим самый старый метод — использование системной функции ЗначениеВСтрокуВнутр(). Она превращает объект в текстовое представление внутреннего формата 1С. Это быстро, но такие данные невозможно прочитать никакими внешними средствами, а поиск по ним внутри запроса будет невозможен.

Риски и ограничения «неправильного» хранения

Важно понимать, почему опытные разработчики часто советуют использовать «человеческие» способы (табличные части). Проанализируем последствия записи нескольких значений в одну строку или ХранилищеЗначений — своевременно выявлять проблемы поможет инструмент диагностики поврежденных записей и битых ссылок в регистрах:

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

Рекомендации по реализации на Управляемых формах

В современных конфигурациях на управляемых формах задача упрощается. Выясним, какие инструменты предоставляет платформа 8.3 (отлаживать которые можно используя редактор форм в режиме предприятия (поможет редактор форм и кода для отладки в режиме 1С:Предприятие)):

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

← На главную