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