Как правильно очистить реквизиты формы при создании нового элемента и сохранить множественные значения в 1С:Предприятии 8.3?

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

Разберем типичную ситуацию, с которой сталкиваются разработчики на платформе 1С:Предприятие 8.3. Предположим, вы работаете над справочником, где требуется реализовать возможность множественного выбора для некоторых полей, таких как "Склад", "Помещение", "СкладскаяЯчейка" или "НоменклатурнаяГруппа". Для этого вы используете реквизиты формы типа СписокЗначений. Однако, при создании нового элемента справочника, вы обнаруживаете, что эти реквизиты формы почему-то заполняются значениями, которые были введены в последнем созданном элементе. Кроме того, возникает вопрос о том, как правильно сохранить эти множественные значения в базе данных, если реквизиты объекта метаданных изначально имели тип Строка, и как затем использовать их в запросах или отчетах.

Давайте пошагово проанализируем эту проблему и найдем эффективные решения.

Причина самопроизвольного заполнения реквизитов формы

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

  1. Выясним причину: Откройте форму вашего справочника в конфигураторе. Найдите реквизиты формы, которые ведут себя некорректно (например, Склад, Помещение, СкладскаяЯчейка, НоменклатурнаяГруппа, если они у вас являются реквизитами формы).
  2. Снимем флаг: В свойствах этих реквизитов формы проверьте наличие флага "Сохранять значения". Снимите этот флаг для всех реквизитов, которые должны быть пустыми при создании нового элемента. Это должно решить проблему автоматического подтягивания старых значений.

Корректная очистка реквизитов формы при создании нового элемента

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

Процедура ПриСозданииНаСервере выполняется на сервере только при первом открытии формы для нового объекта. Это идеальное место для инициализации реквизитов объекта и связанных с ними реквизитов формы.

  1. Используем ПриСозданииНаСервере: Откройте модуль формы вашего справочника. Добавьте или модифицируйте процедуру ПриСозданииНаСервере.

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

    Обратите внимание, что мы используем Объект.ЭтоНовый(). Это гарантирует, что очистка произойдет только при создании нового элемента и не затронет уже существующие элементы при их открытии.

Правильное хранение множественных значений в 1С

Теперь рассмотрим вторую ключевую проблему: как правильно хранить множественные значения, полученные из реквизита формы типа СписокЗначений. Изначальное решение хранить их в реквизитах объекта типа Строка является неэффективным и порождает множество проблем, особенно при попытке использовать эти значения в запросах или отчетах. Представьте, что вам нужно найти все документы, связанные с одним из складов, перечисленных в этой строке – это будет крайне сложно и медленно.

Рассмотрим несколько корректных подходов к хранению множественных значений, выбор которых зависит от того, как вы планируете использовать эти данные в дальнейшем:

1. Использование реквизита типа ХранилищеЗначения

Когда использовать: Этот способ наиболее универсален, когда вам нужно сохранить произвольные данные (включая СписокЗначений, структуру, массив и т.д.) в сжатом виде, и вы не планируете использовать эти значения напрямую в запросах для отбора, связи или группировки.

  1. Изменяем тип реквизита объекта: Вместо реквизита объекта типа Строка, создайте новый реквизит объекта (например, ВыбранныеСклады) с типом ХранилищеЗначения.

  2. Сохраняем СписокЗначений: Чтобы сохранить СписокЗначений из реквизита формы в реквизит объекта типа ХранилищеЗначения, вам нужно обернуть его в объект ХранилищеЗначения.

    
    &НаСервере
    Процедура ПередЗаписьюНаСервере(Отказ, ПараметрыЗаписи)
        // Предположим, СписокВыбранныхСкладов - это реквизит формы типа СписокЗначений.
        // Объект.ВыбранныеСклады - это реквизит объекта типа ХранилищеЗначения.
    
        Если СписокВыбранныхСкладов.Количество() > 0 Тогда
            // Сохраняем СписокЗначений в ХранилищеЗначения.
            // Можно добавить сжатие для экономии места.
            Объект.ВыбранныеСклады = Новый ХранилищеЗначения(СписокВыбранныхСкладов, Новый СжатиеДанных(9)); 
        Иначе
            // Если список пуст, очищаем ХранилищеЗначения.
            Объект.ВыбранныеСклады = Неопределено;
        КонецЕсли;
    КонецПроцедуры
    

    Мы используем процедуру ПередЗаписьюНаСервере, которая выполняется перед сохранением объекта в базу данных. Здесь мы берем данные из реквизита формы (СписокВыбранныхСкладов) и сохраняем их в реквизит объекта (Объект.ВыбранныеСклады).

  3. Получаем СписокЗначений: Чтобы загрузить сохраненный СписокЗначений обратно в реквизит формы при открытии элемента, вам нужно извлечь его из ХранилищаЗначения методом Получить().

    
    &НаСервере
    Процедура ПриЧтенииНаСервере(ТекущийОбъект)
        // Предположим, СписокВыбранныхСкладов - это реквизит формы типа СписокЗначений.
        // ТекущийОбъект.ВыбранныеСклады - это реквизит объекта типа ХранилищеЗначения.
    
        Если ТекущийОбъект.ВыбранныеСклады <> Неопределено Тогда
            СписокВыбранныхСкладов = ТекущийОбъект.ВыбранныеСклады.Получить();
        Иначе
            // Если ХранилищеЗначения пусто, инициализируем пустой СписокЗначений.
            СписокВыбранныхСкладов = Новый СписокЗначений();
        КонецЕсли;
    КонецПроцедуры
    

    Процедура ПриЧтенииНаСервере выполняется после прочтения данных объекта из базы данных, но до отображения формы. Это идеальное место для заполнения реквизитов формы на основе данных объекта.

  4. Очистка ХранилищаЗначения: Для очистки реквизита типа ХранилищеЗначения достаточно присвоить ему значение Неопределено.

Особый случай: Хранение ОтбораКомпоновкиДанных в ХранилищеЗначения

Если ваши "множественные значения" представляют собой не просто список ссылок, а сложный отбор, который может включать группы, условия "И/ИЛИ", сравнения по полям и т.д., тогда ОтборКомпоновкиДанных является более мощным инструментом. Вы можете создать объект ОтборКомпоновкиДанных, заполнить его нужными условиями (включая множественные значения) и сохранить его целиком в реквизит типа ХранилищеЗначения. Затем, при необходимости, вы сможете извлечь этот ОтборКомпоновкиДанных и применить его к любому отчету или запросу, основанному на Системе Компоновки Данных (СКД).

Это дает огромную гибкость, но требует более глубокого понимания работы с СКД. Для сохранения и получения логика будет аналогична работе со СписокЗначений, просто вместо СписокЗначений вы будете сериализовать и десериализовать ОтборКомпоновкиДанных.

2. Использование Табличных частей

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

  1. Создаем табличную часть: В структуре вашего справочника (метаданных) создайте новую табличную часть, например, "ВыбранныеСклады".

  2. Добавляем реквизит в табличную часть: В эту табличную часть добавьте реквизит, например, "Склад", с типом "СправочникСсылка.Склады". Аналогично для "Помещение", "СкладскаяЯчейка" и т.д. Каждый выбранный элемент будет занимать отдельную строку в этой табличной части.

  3. Размещаем на форме: На форму вашего справочника добавьте элемент типа "Таблица" (Табличное поле), связанный с этой новой табличной частью (например, Объект.ВыбранныеСклады).

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

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

    На сервере, при записи объекта, данные табличной части будут автоматически сохраняться вместе с основным объектом. При чтении они также будут загружаться.

Отображение множественных значений в форме списка справочника

Отображение множественных значений в форме списка справочника (не в форме элемента, а именно в списке) представляет собой отдельную задачу. Если вы храните данные в ХранилищеЗначения, вы не сможете напрямую отобразить их содержимое в колонке списка без дополнительных усилий. Если используете табличную часть, то тем более напрямую отобразить все значения в одной колонке списка не получится.

Для отображения в списке обычно используют следующие подходы:

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

  2. Первый/несколько элементов + "и другие": Можно отобразить представление первого (или нескольких) выбранных элементов, а затем добавить текст "и другие". Это потребует написания функции, которая будет формировать такую строку.

  3. Поле типа Строка (только для вывода): Можно создать дополнительный реквизит объекта типа Строка, который не будет использоваться для хранения данных, а будет служить лишь для формирования текстового представления выбранных элементов. При записи объекта (в ПередЗаписьюНаСервере) вы будете формировать эту строку, например, "Склад 1, Склад 2, ...". Этот строковый реквизит уже можно будет отобразить в форме списка.

Итоги и рекомендации

Чтобы эффективно решить поставленные задачи, мы рекомендуем следующие шаги:

  1. Очистка реквизитов формы:

    1. Убедитесь, что для соответствующих реквизитов формы снят флаг "Сохранять значения".
    2. Реализуйте или скорректируйте процедуру ПриСозданииНаСервере в модуле формы с использованием Объект.ЭтоНовый() для инициализации реквизитов формы (СписокЗначений.Очистить()) и реквизитов объекта ("" для строк, Неопределено для ХранилищеЗначения).
  2. Хранение множественных значений:

    1. Если значения не нужны в запросах: Используйте реквизит объекта типа ХранилищеЗначения. В ПередЗаписьюНаСервере сохраняйте СписокЗначений из формы в ХранилищеЗначения, а в ПриЧтенииНаСервере извлекайте его обратно в реквизит формы. Это подойдет для большинства случаев, где значения нужны только для программной обработки.
    2. Если значения нужны в запросах: Используйте табличную часть. Создайте новую табличную часть с реквизитом типа СправочникСсылка. Разместите табличное поле на форме и реализуйте механизм множественного подбора. Это обеспечит возможность эффективного связывания и фильтрации по этим значениям в запросах и отчетах.
    3. Если нужны сложные отборы: Используйте ОтборКомпоновкиДанных, сохраняя его в ХранилищеЗначения. Это гибкий подход для хранения комплексных условий отбора.
  3. Отображение в списке: Для формы списка справочника рассмотрите варианты отображения количества выбранных элементов или формирования краткой текстовой строки из значений для вывода.

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

← На главную