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