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