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