При разработке внешних обработок и отчетов в платформе 1С:Предприятие часто возникает задача поиска документов, в которых не заполнены обязательные реквизиты (например, поставщик или покупатель). Полученные ссылки необходимо передать на форму для дальнейшей обработки или отображения пользователю через специальный элемент управления — СписокЗначений.
В этой статье мы подробно проанализируем исходный код, предложенный на форуме, выявим типичные ошибки при работе с запросами и коллекциями 1С, оптимизируем алгоритм и рассмотрим лучшие практики разработки на управляемых формах.
Рассмотрим первоначальный вариант функции, с которым обратился автор темы:
Функция НезаполненныеДокументы() Экспорт
Массив = Новый Массив;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Поступлениетоваров.Поставщик,
| Поступлениетоваров.Дата,
| Поступлениетоваров.Номер,
| Поступлениетоваров.Ссылка
|ИЗ
| Документ.Поступлениетоваров КАК Поступлениетоваров
|ГДЕ
| Поступлениетоваров.Поставщик = &ПустаяСсылка";
ПустаяСсылка = Справочники.Контрагенты.ПустаяСсылка();
Запрос.УстановитьПараметр("ПустаяСсылка", ПустаяСсылка);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выгрузить();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Массив.Добавить(ВыборкаДетальныеЗаписи.Ссылка);
КонецЦикла;
Возврат Массив;
КонецФункции
Разберем основные недочеты и ошибки в данном подходе:
ВЫБРАТЬ запрашиваются поля Поставщик, Дата, Номер и Ссылка. Однако в коде используется исключительно реквизит Ссылка. Выборка ненужных полей увеличивает нагрузку на СУБД, повышает объем передаваемых данных по сети и замедляет выполнение кода.Справочники.Контрагенты.ПустаяСсылка() и передавать ее в параметры запроса. В языке запросов 1С предусмотрена конструкция ЗНАЧЕНИЕ(...).ВыгрузитьКолонку().КонецЦикла; без открывающей конструкции Пока ... Цикл, что приводит к ошибке компиляции.Сообщить() внутри серверных функций обработки данных противоречит стандартам разработки 1С. Вывод сообщений пользователю должен выполняться на клиентской стороне.Посмотрим, как сделать код чистым, быстрым и соответствующим стандартам 1С. Мы заменим обход выборки на метод ВыгрузитьКолонку() и применим прямой загрузчик в СписокЗначений.
Разберем по шагам итоговую серверную функцию:
&НаСервере
Функция ПолучитьНезаполненныеДокументы() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПоступлениеТоваров.Ссылка КАК Ссылка
|ИЗ
| Документ.ПоступлениеТоваров КАК ПоступлениеТоваров
|ГДЕ
| ПоступлениеТоваров.Поставщик = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)";
ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
МассивСсылок = ТаблицаРезультата.ВыгрузитьКолонку("Ссылка");
СписокДокументов = Новый СписокЗначений();
СписокДокументов.ЗагрузитьЗначения(МассивСсылок);
Возврат СписокДокументов;
КонецФункции
Эту функцию можно сократить до лаконичной записи без потери читаемости:
&НаСервере
Функция ПолучитьНезаполненныеДокументы() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПоступлениеТоваров.Ссылка КАК Ссылка
|ИЗ
| Документ.ПоступлениеТоваров КАК ПоступлениеТоваров
|ГДЕ
| ПоступлениеТоваров.Поставщик = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)";
СписокДокументов = Новый СписокЗначений();
СписокДокументов.ЗагрузитьЗначения(Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка"));
Возврат СписокДокументов;
КонецФункции
Обратите внимание: проверка Пустой() перед выгрузкой не требуется. Если запрос ничего не найдет, метод ВыгрузитьКолонку() вернет пустой массив, а ЗагрузитьЗначения() корректно обработает его без возникновения ошибок.
Если задача заключается в том, чтобы просто показать пользователю во внешней обработке документы с незаполненным поставщиком, ручное написание запросов и выгрузка их в СписокЗначений — не единственный и не всегда самый эффективный способ.
В управляемом приложении 1С 8.3 для вывода данных на форму идеально подходит реквизит типа ДинамическийСписок. Это дает пользователю встроенный функционал поиска, сортировки, настройки группировок и открытия документа по двойному клику.
Выполним следующую последовательность действий:
СписокНезаполненных и укажем его тип: ДинамическийСписок.Документ.ПоступлениеТоваров.СписокНезаполненных в левую панель элементов формы. Платформа автоматически создаст таблицу формы.Поставщик Не Заполнено.Если требуется установить отбор программно при создании формы на сервере, используется следующий код:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЭлементОтбора = СписокНезаполненных.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Поставщик");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
ЭлементОтбора.Использование = Истина;
КонецПроцедуры
Если все же необходимо использовать именно СписокЗначений, организуем связывание клиента и сервера корректно:
СписокДокументовФормы с типом СписокЗначений.ДокументСсылка.ПоступлениеТоваров.
&НаКлиенте
Процедура ОбновитьСписок(Команда)
СписокДокументовФормы = ПолучитьНезаполненныеДокументы();
Если СписокДокументовФормы.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Документы с незаполненным поставщиком не найдены.");
КонецЕсли;
КонецПроцедуры
Проанализируем основные рекомендации стандартов 1С, которые следует соблюдать при решении подобных задач:
ПолучитьНезаполненныеДокументы, а не просто НезаполненныеДокументы).Сообщить() или ПоказатьПредупреждение(). Сервер возвращает данные, а клиентский контекст принимает решение об информировании пользователя.ЗНАЧЕНИЕ(Справочник.ИмяСправочника.ПустаяСсылка) прямо в тексте запроса. Это делает код более компактным и избавляет от лишних вызовов на BSL.