Как реализовать выбор одного или нескольких документов в отчете или обработке 1С 8.3

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

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

Организация интерфейса и начальный выбор

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

Рассмотрим процедуру ПриОткрытии, где мы задаем начальное состояние формы. По умолчанию мы скрываем список объектов:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Устанавливаем начальное состояние видимости
    Элементы.СписокОбъектов.Видимость = Ложь;
    Элементы.СсылкаНаОбъект.Видимость = Истина;
КонецПроцедуры

Чтобы предоставить пользователю возможность множественного выбора в стандартной форме выбора документа, необходимо программно перехватить событие начала выбора. Разберем, как это сделать с помощью метода ОткрытьФорму и параметров выбора.


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

Обработка результата выбора и управление видимостью

Теперь выясним причину, по которой интерфейс может вести себя некорректно. Основная логика должна быть сосредоточена в процедуре обратного вызова ПриЗакрытииФормыВыбора. Здесь мы должны проанализировать, сколько объектов выбрал пользователь, и в зависимости от этого переключить видимость элементов формы.

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


&НаКлиенте
Процедура ПриЗакрытииФормыВыбора(Значение, ДопПараметры) Экспорт
    // Если пользователь закрыл форму без выбора, значение будет Неопределено
    Если Значение = Неопределено Тогда 
        Возврат; 
    КонецЕсли;

    Если ТипЗнч(Значение) = Тип("Массив") Тогда
        Если Значение.Количество() = 1 Тогда
            // Выбран один документ
            Объект.СсылкаНаОбъект = Значение[0];
            СписокОбъектов.Очистить();
            
            Элементы.СсылкаНаОбъект.Видимость = Истина;
            Элементы.СписокОбъектов.Видимость = Ложь;
        ИначеЕсли Значение.Количество() > 1 Тогда
            // Выбрано несколько документов
            Объект.СсылкаНаОбъект = ПредопределенноеЗначение("Документ.ОтчетПроизводстваЗаСмену.ПустаяСсылка");
            СписокОбъектов.ЗагрузитьЗначения(Значение);
            
            Элементы.СсылкаНаОбъект.Видимость = Ложь;
            Элементы.СписокОбъектов.Видимость = Истина;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Проанализируем этот код: если выбран один элемент, мы заполняем реквизит СсылкаНаОбъект. Если выбрано несколько — мы заполняем СписокОбъектов, а одиночный реквизит обнуляем, чтобы он не мешал логике печати.

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

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


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

    Если МассивОбъектов.Количество() = 0 Тогда
        Сообщить("Документы не выбраны!");
        Возврат Неопределено;
    КонецЕсли;

    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    Возврат ОбработкаОбъект.СформироватьПечать(МассивОбъектов);
КонецФункции

Исправление ошибок в запросах

Одной из самых частых проблем является ошибка "Неверные параметры в операции сравнения". Это происходит, когда в запросе используется оператор сравнения = (равно), а в качестве параметра передается массив объектов. Для того чтобы запрос корректно отрабатывал и для одного документа, и для списка, всегда используйте оператор В.

Рассмотрим правильное построение запроса в модуле объекта:


Запрос = Новый Запрос;
// МассивОбъектов может содержать 1 или более ссылок
Запрос.УстановитьПараметр("МассивОбъектов", МассивОбъектов);

Запрос.Текст = 
    "ВЫБРАТЬ
    |   Отчет.Ссылка КАК Документ,
    |   Отчет.Организация,
    |   Отчет.Номер,
    |   Отчет.Дата
    |ИЗ
    |   Документ.ОтчетПроизводстваЗаСмену КАК Отчет
    |ГДЕ
    |   Отчет.Ссылка В (&МассивОбъектов)";

РезультатЗапроса = Запрос.Выполнить();

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

  1. Всегда проверяйте тип возвращаемого значения в ОписаниеОповещения. При множественном выборе это всегда будет Массив.
  2. Для проверки на пустоту ссылки на стороне клиента используйте ПредопределенноеЗначение("Документ.ИмяДокумента.ПустаяСсылка").
  3. В запросах используйте оператор В вместо =, если параметр может принимать коллекцию значений.
  4. Если вы используете БСП (Библиотеку стандартных подсистем), для формирования печатных форм рекомендуется использовать стандартные механизмы передачи коллекции ссылок в команду печати.

Разберем еще один момент: передача параметра в запрос. Ошибка "Поле объекта не обнаружено (Ссылка)" часто возникает, когда разработчик пытается обратиться к свойству МассивОбъектов.Ссылка. Помните, что у массива нет свойства Ссылка — сам массив уже является набором ссылок. В метод УстановитьПараметр нужно передавать сам массив целиком.

Следуя этой структуре, мы создали надежный механизм выбора, который интуитивно понятен пользователю и устойчив к ошибкам типов данных в коде 1С.

← На главную