Каждый начинающий разработчик в среде «1С:Предприятие» рано или поздно сталкивается с задачей обхода элементов справочника и проверки заполнения их реквизитов. В этой статье мы подробно разберем, как правильно реализовать эту задачу, исправим типичные ошибки новичков, поговорим о клиент-серверной архитектуре и рассмотрим современные UX/UI-альтернативы привычному выводу сообщений.
Для начала проанализируем попытки автора темы решить задачу самостоятельно. В коде автора присутствуют две критические ошибки:
Справочники.Люди.Элемены ошибочна синтаксически. В платформе 1С у менеджера справочника нет свойства «Элементы» (и тем более «Элемены»). Для получения данных из базы данных всегда следует использовать запросы, а не пытаться перебирать таблицы напрямую через менеджеры объектов на клиенте.Давайте разберем по шагам, как построить правильное, быстрое и архитектурно верное решение.
В современных управляемых формах код жестко разделен на клиентский и серверный контексты. Процедура ПриОткрытии формы списка справочника выполняется на клиенте. Однако объект Запрос, с помощью которого мы будем выбирать данные из базы данных, доступен исключительно на сервере.
Для решения этой задачи мы применим правильную структуру вызовов. Мы инициируем процесс на клиенте при открытии формы, а саму выборку данных перенесем во внеконтекстную серверную процедуру. Это позволит минимизировать объем передаваемых данных между сервером и клиентом.
Разберем шаблон такой структуры кода в модуле формы списка:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Вызываем серверную процедуру для анализа данных
ПроверитьЗаполнениеРеквизитовНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьЗаполнениеРеквизитовНаСервере()
// Здесь будет выполняться запрос к базе данных
КонецПроцедуры
В платформе 1С тип данных Дата всегда содержит и дату, и время. Понятия «пустого» значения даты в привычном понимании (как NULL в SQL или undefined в JavaScript) для заполненных реквизитов типа дата по умолчанию не существует. Вместо этого пустая дата представляется как начало григорианского календаря: 01 января 1 года (01.01.0001 00:00:00).
При составлении запроса важно учитывать следующие особенности:
Люди.ДатаРождения <> "", вызовет ошибку или вернет неверный результат, так как типы данных не совпадают.ДАТАВРЕМЯ(1, 1, 1).NULL. В нашей простой задаче достаточно проверить равенство пустой дате.В процессе обсуждения на форуме был предложен вариант запроса, который выбирает абсолютно все поля справочника (Ссылка, ВерсияДанных, ПометкаУдаления, Родитель и т.д.). С точки зрения производительности это грубая ошибка. Выборка ненужных полей создает лишнюю нагрузку на сервер СУБД и сеть.
Поскольку наша цель — просто вывести имена людей, у которых не заполнена дата рождения, мы должны выбирать только поле Наименование. Рассмотрим оптимизированный текст запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Люди.Наименование КАК ФИО
|ИЗ
| Справочник.Люди КАК Люди
|ГДЕ
| Люди.ДатаРождения = ДАТАВРЕМЯ(1, 1, 1)";
Обратите внимание на условие в секции ГДЕ. Мы выбираем только те записи, у которых реквизит ДатаРождения равен пустой дате ДАТАВРЕМЯ(1, 1, 1).
Теперь объединим полученные знания в готовое решение. Этот код необходимо разместить в Модуле формы списка справочника «Люди»:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Инициируем проверку незаполненных дат на сервере
ПроверитьЗаполнениеДатНаСервере();
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьЗаполнениеДатНаСервере()
// Создаем запрос для поиска элементов с пустой датой
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Люди.Наименование КАК ФИО
|ИЗ
| Справочник.Люди КАК Люди
|ГДЕ
| Люди.ДатаРождения = ДАТАВРЕМЯ(1, 1, 1)";
РезультатЗапроса = Запрос.Выполнить();
// Если результат пустой, прерываем выполнение, чтобы сэкономить ресурсы
Если РезультатЗапроса.Пустой() Тогда
Возврат;
КонецЕсли;
// Обходим результаты запроса в цикле
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Метод Сообщить() доступен на сервере,
// сообщения будут переданы на клиент и показаны пользователю
Сообщить("У сотрудника " + Выборка.ФИО + " не указана дата рождения!");
КонецЦикла;
КонецПроцедуры
Вывод системных предупреждений через метод Сообщить() при каждом открытии формы списка — это устаревший подход, который сильно перегружает интерфейс пользователя. Представьте, что в справочнике окажется 200 человек без заполненной даты. Пользователь получит огромное, нечитаемое окно сообщений, которое перекроет всю рабочую область.
Рассмотрим, как решить эту задачу более элегантно и в соответствии с современными стандартами разработки 1С.
Вместо написания запросов и программного обхода элементов мы можем визуально выделить строки с незаполненной датой прямо в списке. Это делается стандартными средствами платформы в дизайнере формы списка:
ДатаРождения Равно '0001-01-01' (пустая дата).Наименование или ДатаРождения.В результате при открытии формы все пользователи сразу увидят проблемные строки без вывода навязчивых сообщений.
Мы можем вывести на форму кнопку или флажок «Показать незаполненные». При изменении этого флажка динамический список будет мгновенно отфильтрован. Нам не нужно писать тяжелые запросы вручную — платформа сделает это автоматически на уровне СУБД:
&НаКлиенте
Процедура ФлажокПоказатьТолькоБезДатПриИзменении(Элемент)
// Получаем группу отбора динамического списка
ЭлементОтбора = Список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ДатаРождения");
ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ЭлементОтбора.ПравоеЗначение = '00010101'; // Пустая дата
ЭлементОтбора.Использование = ФлажокПоказатьТолькоБезДат;
КонецПроцедуры
Если нам все же необходимо именно уведомить пользователя о наличии пустых реквизитов, то вместо раздражающего метода Сообщить() лучше применить аккуратное всплывающее оповещение, которое автоматически исчезнет через несколько секунд. Для этого используется метод ПоказатьОповещениеПользователя():
// Пример использования вместо Сообщить()
ПоказатьОповещениеПользователя(
"Внимание!",
,
"Обнаружены сотрудники без указанной даты рождения!",
БиблиотекаКартинок.Важно
);
Используя эти методы, мы делаем наши прикладные решения на платформе «1С:Предприятие 8» быстрыми, надежными и удобными для конечного пользователя.