Пустой реквизит в 1С 8.3: ищем источник через отладчик, журнал и код

· 10 мин

Содержание

Сообщение «Значение не заполнено» (или «Поле «Контрагент» не заполнено») выдаёт проверка заполнения: у реквизита стоит свойство Проверка заполнения = Выдавать ошибку, либо код в ОбработкаПроверкиЗаполнения или в обработчике записи сам нашёл пустое значение. Чтобы исправить, найдите, какая именно проверка сработала: через Правка → Глобальный поиск в Конфигураторе по тексту сообщения, через отладчик с остановкой по ошибке или через журнал регистрации.

Типичная ситуация: бухгалтер проводит пачку документов после обмена, и на трёх из двадцати выскакивает «не заполнено». В форме поле вроде бы есть, значение в нём видно. Значит, пусто не там, куда смотрят: в табличной части, в скрытом реквизите или в объекте, на который ведёт ссылка. Ниже — как это найти и закрыть, от быстрой проверки до разбора кода.

Как платформа решает, что значение пустое

У платформы 1С 8.3 три источника таких сообщений. От источника зависит, где искать.

  • 🔹 Свойство реквизита. В Конфигураторе у реквизита или колонки табличной части выставлено Проверка заполнения: Выдавать ошибку. Платформа сама формирует текст вида Поле "Организация" не заполнено, а для таблиц — с указанием номера строки и имени табличной части.
  • 🔹 Обработчик ОбработкаПроверкиЗаполнения в модуле объекта. Здесь разработчик добавляет условные проверки и свой текст сообщения.
  • 🔹 Явная проверка в коде. Если Не ЗначениеЗаполнено(...) Тогда ВызватьИсключение ... в ПередЗаписью, ОбработкаПроведения, в обработке или в общем модуле. Текст тут любой, в том числе дословно Значение не заполнено.

Когда проверка запускается автоматически:

ДействиеПроверка заполнения
Запись объекта из формы кнопкой «Записать» или «Провести»выполняется
Проведение документа, в том числе программноевыполняется
Программная запись справочника Объект.Записать()не выполняется
Вызов Объект.ПроверитьЗаполнение()выполняется явно

Отсюда частый сюрприз: обработка загрузки создаёт справочники с пустыми полями без единой ошибки, а падает уже документ, который на них ссылается.

Близкая по смыслу ошибка времени выполнения — Значение не является значением объектного типа (Наименование). Код обратился к реквизиту через точку у переменной, в которой лежит Неопределено. Причина та же — пустое значение, но ищут её отладчиком, а не через проверку заполнения.

Глобальный поиск и отладчик: где именно сработала проверка

Шаг 1. Поиск по тексту сообщения

  1. Откройте базу в Конфигураторе.
  2. Нажмите Правка → Глобальный поиск (Ctrl+Shift+F).
  3. Вставьте кусок текста ошибки без имени поля, например не заполнено, и ищите по всей конфигурации и расширениям.

Если текст сформировал программист, поиск сразу покажет модуль и строку. Если текст платформенный, в коде его не будет. Тогда ищите имя поля в свойствах реквизитов: откройте объект, выберите реквизит и посмотрите свойство «Проверка заполнения».

Шаг 2. Остановка по ошибке

Когда исключение вызывается где-то в глубине общих модулей, быстрее поймать его в момент возникновения.

  1. В Конфигураторе запустите Отладка → Начать отладку и выберите клиент, которым пользуется сотрудник.
  2. Откройте Отладка → Остановка по ошибке и включите остановку. В фильтре можно указать фрагмент текста ошибки, чтобы отладчик не вставал на каждое обработанное исключение.
  3. В клиентском сеансе повторите действие: запись, проведение, загрузку.
  4. Отладчик встанет на строке, где возникло исключение. Откройте Стек вызовов — по нему видно, кто вызвал эту процедуру.
  5. Через Табло или Вычислить выражение (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 табличной части «Товары»». Через полгода вы сами скажете спасибо при отладке.
Перед выпуском доработки с новой проверкой
Выполнено: 0 / 5

Частые вопросы

Можно ли просто снять «Проверка заполнения» у реквизита типовой конфигурации?
Технически можно, но это изменение типовой: при обновлении придётся сравнивать и объединять. Чаще правильнее заполнить данные или убрать реквизит из проверки в расширении.
Почему проверка не срабатывает при загрузке из файла?
Программная запись справочника не вызывает проверку заполнения. Обработка должна вызывать ПроверитьЗаполнение() сама.
Чем отличается `ЗначениеЗаполнено()` от сравнения с пустой ссылкой?
ЗначениеЗаполнено() работает с любым типом и ловит Неопределено и NULL. Сравнение с ПустаяСсылка() годится только для одного ссылочного типа и пропускает Неопределено.
Почему сообщение не показывает, в какой строке ошибка?
Разработчик не заполнил Сообщение.Поле или не указал номер строки в тексте. Номер можно найти отладчиком, остановившись на строке с выводом сообщения.
Ошибка возникает в регламентном задании — где смотреть текст?
В журнале регистрации с отбором по уровню «Ошибка» и по событию регламентных заданий за нужный интервал.