Как исключить конкретный документ из внешнего отчета 1С и исправить ошибку «Поле объекта не обнаружено»

Программист 1С v8.3 (Управляемые формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

В процессе разработки или доработки внешних отчетов в системе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью тонкой настройки фильтрации данных. Типичная ситуация: отчет выводит общие суммы начислений, но по требованию руководства необходимо исключить конкретный документ (например, счет на оплату с определенным номером) за конкретный период, чтобы не искажать итоговые показатели. При попытке реализовать такую логику «в лоб» новички часто получают ошибку Поле объекта не обнаружено. В этой статье мы разберем, почему возникает эта ошибка и как правильно реализовать исключение данных несколькими способами.

Анализ причины ошибки: Менеджеры vs Ссылки

Разберем ситуацию, когда при написании кода вида Документы.СчетНаОплату.ДоговорКонтрагента или Документы.СчетНаОплату.Номер система выдает ошибку. Выясним причину: в 1С объект Документы.СчетНаОплату является менеджером объекта. Менеджер предназначен для управления всем классом документов данного типа: создания новых экземпляров, поиска существующих в базе по номеру или ссылке, получения форм. Однако менеджер не содержит данных конкретного счета (его номера, даты или суммы).

Чтобы обратиться к реквизитам, нам необходимо работать с конкретной ссылкой на объект или с результатом запроса. Попытка вызвать метод НайтиПоКоду() у менеджера документа также обречена на провал, так как этот метод относится к справочникам, а не к документам. Для документов используются методы НайтиПоНомеру() или получение ссылки через запрос.

Способ №1: Использование Системы компоновки данных (СКД)

Если ваш внешний отчет построен на базе СКД (что является стандартом для современной платформы 8.3), то программный код для фильтрации может вообще не понадобиться. Рассмотрим, как настроить исключение документа через пользовательские настройки или схему компоновки.

  1. Откроем схему компоновки данных нашего отчета.
  2. Перейдем на вкладку «Настройки», затем на вкладку «Отбор».
  3. Добавим новый элемент отбора. В качестве поля выберем Документ (или Ссылка, в зависимости от структуры набора данных).
  4. Установим вид сравнения «Не равно».
  5. В значении выберем конкретный документ «Счет на оплату №12275».

Проанализируем ситуацию, если исключение должно работать только в определенном периоде (например, в январе). В этом случае в настройках СКД мы можем сгруппировать условия. Создадим группу условий «ИЛИ», в которой укажем, что либо дата документа не попадает в январь, либо его номер не равен искомому. Это позволит сохранить гибкость отчета без внесения правок в конфигуратор.

Способ №2: Корректировка текста запроса

Если отчет формируется на основе запроса, наиболее производительным решением будет ограничение выборки на уровне сервера базы данных. Рассмотрим пример добавления условия в блок ГДЕ.

Предположим, наш запрос выбирает данные из регистра накопления или таблицы документов. Нам нужно исключить документ с номером "12275" за январь 2021 года. Проанализируем пример кода запроса:


ВЫБРАТЬ
    Продажи.Контрагент,
    Продажи.СуммаОбороти
ИЗ
    РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, , ) КАК Продажи
ГДЕ
    НЕ (Продажи.Регистратор.Номер = "12275" 
        И Продажи.Регистратор.Дата МЕЖДУ ДАТАВРЕМЯ(2021, 1, 1) И ДАТАВРЕМЯ(2021, 1, 31, 23, 59, 59))

Важный момент: использование отрицания НЕ вместе с логическим И позволяет четко отсечь только одно конкретное совпадение, не затрагивая другие документы этого же контрагента или этого же периода. Этот метод эффективнее программного перебора, так как данные не передаются с сервера на клиент.

Способ №3: Программный фильтр при обходе результата

Рассмотрим ситуацию, когда отчет формируется программно через выборку из запроса или объектную модель. В этом случае мы можем использовать оператор Продолжить внутри цикла обхода данных. Разберем, как это сделать правильно, избегая ошибки доступа к полям.

Допустим, у нас есть переменная Выборка, полученная из результата запроса. Мы должны проверить условия перед тем, как выводить строку в табличный документ:


Пока Выборка.Следующий() Цикл
    // Проверяем условие исключения
    Если Выборка.НомерДокумента = "12275" 
       И Выборка.ДатаДокумента >= '20210101' 
       И Выборка.ДатаДокумента <= '20210131235959' Тогда
        
        Продолжить; // Пропускаем итерацию, данные не попадут в отчет
        
    КонецЕсли;
    
    // Дальнейшая логика вывода данных в отчет
    ОбластьМакета.Параметры.Заполнить(Выборка);
    ТабДок.Вывести(ОбластьМакета);
КонецЦикла;

Обратите внимание на формат даты 'YYYYMMDD' — это стандартный литерал даты в 1С, который позволяет избежать ошибок при сравнении периодов.

Почему не стоит искать по коду договора «на лету»

Посмотрим на типичную ошибку из практики: попытку использовать НайтиПоКоду("КодДоговора"). В справочнике ДоговорыКонтрагентов коды уникальны только в разрезе Владельца (Контрагента). Если вы попытаетесь найти договор просто по коду, система может вернуть ссылку на договор совершенно другого клиента или пустую ссылку.

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


СсылкаНаКонтрагента = Справочники.Контрагенты.НайтиПоНаименованию("ГБУЗ ЛО Гатчинская КМБ");
СсылкаНаДоговор = Справочники.ДоговорыКонтрагентов.НайтиПоКоду("12275", СсылкаНаКонтрагента);

Если СсылкаНаДоговор.Пустая() Тогда
    Сообщить("Договор не найден, проверьте код!");
КонецЕсли;

Рекомендации по учету в ЖКХ и коммунальных услугах

Поскольку рассматриваемая проблема возникла в отчете по коммунальным услугам, важно учитывать специфику регистров начислений. Часто данные в такие отчеты попадают не из самих счетов, а из регистров накопления (например, «Взаиморасчеты» или «Начисления по услугам»).

Проанализируем ситуацию: если сумма «зависла» в январе, хотя начисление было в декабре, это может быть следствием использования даты регистрации (периода записи в регистр), которая отличается от даты самого документа. В таком случае фильтровать нужно не по Документ.Дата, а по полю Период регистра.

Вместо жесткого кодирования исключений в тексте модуля («зашития» номера счета в код), мы рекомендуем использовать Дополнительные реквизиты или Свойства. Вы можете пометить нужный счет специальным флагом «Исключить из отчетов», и тогда программный код будет универсальным: он просто будет проверять наличие этого флага, что избавит вас от необходимости переписывать отчет при возникновении аналогичной просьбы от руководства в будущем.

Подведение итогов

Для успешного решения задачи и устранения ошибки Поле объекта не обнаружено мы рекомендуем придерживаться следующего алгоритма:

  1. Убедиться, что обращение идет к ссылке документа в выборке или запросе, а не к менеджеру Документы.СчетНаОплату.
  2. Проверить возможность реализации фильтра через стандартные настройки СКД — это самый безопасный и быстрый способ.
  3. Если используется запрос — добавить условие ГДЕ НЕ (...) для фильтрации данных на стороне сервера.
  4. При использовании поиска объектов в коде всегда учитывать владельца (для подчиненных справочников) и проверять результат на Пустая().

Следуя этим правилам, вы сможете создавать стабильные и гибкие отчеты, корректно обрабатывающие исключительные ситуации в учете.

← На главную