Пустой реквизит в 1С 8.3: ищем источник через отладчик, журнал и код
Содержание
Сообщение «Значение не заполнено» (или «Поле «Контрагент» не заполнено») выдаёт проверка заполнения: у реквизита стоит свойство Проверка заполнения = Выдавать ошибку, либо код в ОбработкаПроверкиЗаполнения или в обработчике записи сам нашёл пустое значение. Чтобы исправить, найдите, какая именно проверка сработала: через Правка → Глобальный поиск в Конфигураторе по тексту сообщения, через отладчик с остановкой по ошибке или через журнал регистрации.
Типичная ситуация: бухгалтер проводит пачку документов после обмена, и на трёх из двадцати выскакивает «не заполнено». В форме поле вроде бы есть, значение в нём видно. Значит, пусто не там, куда смотрят: в табличной части, в скрытом реквизите или в объекте, на который ведёт ссылка. Ниже — как это найти и закрыть, от быстрой проверки до разбора кода.
Как платформа решает, что значение пустое
У платформы 1С 8.3 три источника таких сообщений. От источника зависит, где искать.
- 🔹 Свойство реквизита. В Конфигураторе у реквизита или колонки табличной части выставлено
Проверка заполнения: Выдавать ошибку. Платформа сама формирует текст видаПоле "Организация" не заполнено, а для таблиц — с указанием номера строки и имени табличной части. - 🔹 Обработчик
ОбработкаПроверкиЗаполненияв модуле объекта. Здесь разработчик добавляет условные проверки и свой текст сообщения. - 🔹 Явная проверка в коде.
Если Не ЗначениеЗаполнено(...) Тогда ВызватьИсключение ...вПередЗаписью,ОбработкаПроведения, в обработке или в общем модуле. Текст тут любой, в том числе дословноЗначение не заполнено.
Когда проверка запускается автоматически:
| Действие | Проверка заполнения |
|---|---|
| Запись объекта из формы кнопкой «Записать» или «Провести» | выполняется |
| Проведение документа, в том числе программное | выполняется |
Программная запись справочника Объект.Записать() | не выполняется |
Вызов Объект.ПроверитьЗаполнение() | выполняется явно |
Отсюда частый сюрприз: обработка загрузки создаёт справочники с пустыми полями без единой ошибки, а падает уже документ, который на них ссылается.
Близкая по смыслу ошибка времени выполнения — Значение не является значением объектного типа (Наименование). Код обратился к реквизиту через точку у переменной, в которой лежит Неопределено. Причина та же — пустое значение, но ищут её отладчиком, а не через проверку заполнения.
Глобальный поиск и отладчик: где именно сработала проверка
Шаг 1. Поиск по тексту сообщения
- Откройте базу в Конфигураторе.
- Нажмите
Правка → Глобальный поиск(Ctrl+Shift+F). - Вставьте кусок текста ошибки без имени поля, например
не заполнено, и ищите по всей конфигурации и расширениям.
Если текст сформировал программист, поиск сразу покажет модуль и строку. Если текст платформенный, в коде его не будет. Тогда ищите имя поля в свойствах реквизитов: откройте объект, выберите реквизит и посмотрите свойство «Проверка заполнения».
Шаг 2. Остановка по ошибке
Когда исключение вызывается где-то в глубине общих модулей, быстрее поймать его в момент возникновения.
- В Конфигураторе запустите
Отладка → Начать отладкуи выберите клиент, которым пользуется сотрудник. - Откройте
Отладка → Остановка по ошибкеи включите остановку. В фильтре можно указать фрагмент текста ошибки, чтобы отладчик не вставал на каждое обработанное исключение. - В клиентском сеансе повторите действие: запись, проведение, загрузку.
- Отладчик встанет на строке, где возникло исключение. Откройте
Стек вызовов— по нему видно, кто вызвал эту процедуру. - Через
ТаблоилиВычислить выражение(Shift+F9) посмотрите значения переменных. Пустое значение покажется какНеопределено, пустая ссылка — как пустая строка с типом.
Шаг 3. Если код выполняется на сервере
В файловой базе серверный код отлаживается сразу. В клиент-серверной служба сервера 1С должна быть запущена с ключом -debug, иначе отладчик не подключится к серверным вызовам. Проверить, какие процессы доступны, можно в Отладка → Подключение.
Перезапуск службы агента сервера 1С обрывает все сеансы пользователей в кластере. Включайте отладку на рабочем сервере только вне рабочего времени или на копии базы.
Журнал регистрации и технологический журнал
Отладчик неудобен, когда ошибка плавающая: появилась у пользователя ночью в регламентном задании или раз в неделю при обмене. Тогда смотрите журналы.
Журнал регистрации
- В режиме Предприятия в БП 3.0, ЗУП 3.1 и УТ 11:
Администрирование → Обслуживание → Журнал регистрации. - В Конфигураторе:
Администрирование → Журнал регистрации.
Поставьте отбор по уровню «Ошибка», по пользователю и интервалу времени. В подробностях записи будет текст исключения и, как правило, имя модуля со строкой.
Учтите ограничение: сообщения из СообщениеПользователю, которыми оформлена обычная проверка заполнения, в журнал не попадают. Там видно исключения и неудачные записи, а не каждое «поле не заполнено» в форме.
Технологический журнал: поймать все исключения
Если журнал регистрации молчит, включите сбор событий EXCP (исключения) в технологическом журнале. Файл logcfg.xml кладётся в каталог conf установленной платформы на сервере, например C:\Program Files\1cv8\conf\.
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
<log location="D:\v8logs" history="24">
<event>
<eq property="name" value="EXCP"/>
</event>
<property name="all"/>
</log>
</config>
Платформа подхватывает файл без перезапуска, через минуту-две. Воспроизведите ошибку, затем найдите в логах строку с текстом исключения: рядом будет контекст — модуль и строка кода.
Техжурнал быстро растёт и нагружает диск. Держите его включённым не дольше, чем нужно для поимки ошибки, затем удалите или переименуйте logcfg.xml. Каталог логов размещайте не на системном диске.
Перехват в своём коде
Если ошибка возникает в вашей обработке, оберните опасный участок и запишите подробности сами:
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Инфо = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Загрузка.Проведение", УровеньЖурналаРегистрации.Ошибка,
ДокументОбъект.Метаданные(), ДокументОбъект.Ссылка, ПодробноеПредставлениеОшибки(Инфо));
КонецПопытки;
ПодробноеПредставлениеОшибки даёт текст с модулем и номером строки — именно то, чего не хватает в кратком сообщении пользователю.
Как проверить заполненность значения в коде
Что считает пустым ЗначениеЗаполнено()
| Значение | Результат |
|---|---|
Неопределено, NULL | Ложь |
| Пустая ссылка любого справочника или документа | Ложь |
Число 0 | Ложь |
Пустая строка "" | Ложь |
Пустая дата '00010101' | Ложь |
Ссылка на удалённый объект (<Объект не найден>) | Истина |
Две строки таблицы ломают логику чаще остальных:
- 🔸 Ноль считается незаполненным. Если у реквизита «Количество» стоит проверка заполнения, документ с нулевым количеством не запишется. Когда ноль — нормальное значение, снимайте свойство и проверяйте кодом.
- 🔸 Битая ссылка считается заполненной. Проверка пройдёт, а дальше код упадёт при обращении к реквизитам. Битую ссылку выявляет
Ссылка.ПолучитьОбъект() = Неопределено.
Условная проверка в ОбработкаПроверкиЗаполнения
Частая доработка: поле обязательно только при определённом условии. Свойство «Проверка заполнения» оставьте, а лишний реквизит уберите из массива проверяемых.
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если Не ТребуетсяДоставка Тогда
Индекс = ПроверяемыеРеквизиты.Найти("АдресДоставки");
Если Индекс <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(Индекс);
КонецЕсли;
КонецЕсли;
Для Каждого СтрокаТЧ Из Товары Цикл
Если СтрокаТЧ.Количество <= 0 Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = СтрШаблон("В строке %1 не заполнено количество", СтрокаТЧ.НомерСтроки);
Сообщение.Поле = "Товары[" + Формат(СтрокаТЧ.НомерСтроки - 1, "ЧГ=0") + "].Количество";
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Индекс в Сообщение.Поле считается с нуля, а НомерСтроки — с единицы, поэтому вычитаем 1. Тогда по двойному щелчку на сообщении курсор встанет в нужную ячейку.
В типовых конфигурациях на БСП вместо ручного СообщениеПользователю используют ОбщегоНазначения.СообщитьПользователю. Если дорабатываете типовую, пишите в том же стиле — так проще пройти обновление.
Проверка при программной записи
Обработка загрузки или групповой правки должна сама вызвать проверку перед записью справочника:
Если ЭлементОбъект.ПроверитьЗаполнение() Тогда
ЭлементОбъект.Записать();
Иначе
// сообщения уже выведены, объект пропускаем
КонецЕсли;
Запросы и выборки: откуда берутся NULL и пустые ссылки
Значительная часть пустых значений рождается не в форме, а в запросе, результат которого потом пишется в реквизит.
NULL после левого соединения
Если в ЛЕВОЕ СОЕДИНЕНИЕ справа не нашлось пары, поле придёт как NULL. Записать NULL в реквизит ссылочного типа нельзя, а сравнение = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) такую строку не поймает.
ВЫБРАТЬ
Товары.Ссылка КАК Номенклатура,
ЕСТЬNULL(Цены.Цена, 0) КАК Цена,
ЕСТЬNULL(Настройки.ОсновнойСклад, ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)) КАК Склад
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ПО Товары.Ссылка = Цены.Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НастройкиНоменклатуры КАК Настройки
ПО Товары.Ссылка = Настройки.Номенклатура
Имена регистров здесь условные: подставьте свои. Суть приёма — ЕСТЬNULL на каждом поле, пришедшем из правой таблицы.
Как искать в запросе пустые значения
Чтобы найти документы с незаполненным полем, проверяйте оба варианта пустоты:
ГДЕ
Док.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
ИЛИ Док.Контрагент ЕСТЬ NULL
У реквизитов составного типа пустым бывает и НЕОПРЕДЕЛЕНО. Для проверки конкретного типа используйте ССЫЛКА Справочник.Контрагенты или ТИПЗНАЧЕНИЯ().
Пустая выборка
Код вида Выборка.Следующий(); Объект.Склад = Выборка.Склад; без проверки результата — классический источник пустот. Если запрос ничего не вернул, обращение к полю выборки вызовет ошибку. Всегда пишите Если Выборка.Следующий() Тогда … КонецЕсли и решайте, что делать в ветке «не нашли».
Типичные сценарии и их устранение
Ниже — ситуации, после которых чаще всего появляется сообщение о незаполненном значении, и что делать в каждой.
Массовое исправление пустых реквизитов
Когда документов сотни, открывать каждый неудобно. В типовых конфигурациях на БСП есть обработка группового изменения реквизитов: откройте список документов, выделите нужные строки и найдите в меню «Ещё» команду изменения выделенных. Через отбор задайте условие «поле не заполнено» и укажите новое значение.
Групповое изменение проведённых документов перепроводит их. Сделайте резервную копию базы и выполняйте операцию, когда в базе никто не работает с этими документами, иначе можно получить конфликт блокировок и расхождение в отчётах.
Битые ссылки
Если причина — ссылки на удалённые объекты, поможет Тестирование и исправление в Конфигураторе (Администрирование → Тестирование и исправление) с вариантом «создавать объекты» или «очищать ссылки» для битых ссылок. Этот режим требует монопольного доступа: все пользователи должны выйти из базы, а копия должна быть сделана заранее.
Профилактика: как не допускать незаполненных реквизитов
- ✅ Заполняйте по умолчанию. Обработчик
ОбработкаЗаполненияв модуле объекта подставляет значения при создании нового элемента — так поле не останется пустым по забывчивости. - ✅ Выбирайте способ проверки осознанно. Безусловная обязательность — свойство реквизита. Условная — код в
ОбработкаПроверкиЗаполнения. Не дублируйте одно и то же в двух местах: пользователь получит два сообщения на одно поле. - ✅ Не доверяйте данным извне. В загрузках и обменах вызывайте
ПроверитьЗаполнение()перед записью справочников и логируйте отказ. - ✅ Оборачивайте запросы в
ЕСТЬNULLпри каждом левом соединении, результат которого куда-то пишется. - ✅ Указывайте поле в сообщении.
Сообщение.Полес путём к реквизиту экономит пользователю поиск: двойной щелчок ведёт прямо в ячейку. - ✅ Пишите тексты с контекстом. Не «Значение не заполнено», а «Не заполнен склад в строке 3 табличной части «Товары»». Через полгода вы сами скажете спасибо при отладке.
Частые вопросы
Можно ли просто снять «Проверка заполнения» у реквизита типовой конфигурации?
Почему проверка не срабатывает при загрузке из файла?
ПроверитьЗаполнение() сама.Чем отличается `ЗначениеЗаполнено()` от сравнения с пустой ссылкой?
ЗначениеЗаполнено() работает с любым типом и ловит Неопределено и NULL. Сравнение с ПустаяСсылка() годится только для одного ссылочного типа и пропускает Неопределено.Почему сообщение не показывает, в какой строке ошибка?
Сообщение.Поле или не указал номер строки в тексте. Номер можно найти отладчиком, остановившись на строке с выводом сообщения.