Разработка и поддержка конфигураций на платформе 1С:Предприятие 7.7 имеет множество специфических особенностей, которые могут вызвать затруднения даже у опытных разработчиков, привыкших к более современным версиям 1С 8.х. Одной из наиболее распространенных и коварных ошибок является остановка выполнения кода с системным сообщением «Поле агрегатного объекта не обнаружено». В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем практический пример из реальной практики разработчика и рассмотрим комплексные методы ее решения.
Для начала выясним причину возникновения данной ошибки с точки зрения архитектуры платформы 1С 7.7. Все типы данных в системе делятся на базовые (простые) и агрегатные (сложные). К базовым относятся такие типы, как Число, Строка и Дата. К агрегатным объектам относятся более сложные структуры данных, имеющие собственные свойства, методы и реквизиты. Примерами агрегатных объектов являются: Справочник, Документ, ТаблицаЗначений, СписокЗначений, Запрос и другие.
Ошибка «Поле агрегатного объекта не обнаружено (ИмяПоля)» означает, что программа пытается обратиться к свойству, реквизиту или методу объекта через точку (например, Объект.ИмяПоля), но во внутренней структуре этого конкретного объекта такое имя отсутствует или еще не было инициализировано. Платформа не может сопоставить указанный идентификатор с метаданными или программной структурой и аварийно завершает процедуру.
Рассмотрим по шагам основные причины этой проблемы на примере практической задачи по учету норм обмундирования.
Представим задачу: в конфигурации существуют справочники НормыОбмундирования, СоставНормы (подчиненный первому справочнику) и документ РасчетКомпенсации. Нам потребовалось ограничить действие определенных элементов состава норм периодами их актуальности. Для этого в справочник СоставНормы в конфигураторе были добавлены два новых реквизита: ДатаНачала и ДатаОкончания.
После добавления реквизитов в метаданные мы пытаемся вывести эти данные на форму справочника НормыОбмундирования, где расположена табличная часть. На форме за отображение состава отвечает элемент типа «Таблица значений» с идентификатором СписокНормы. Мы изменяем процедуру заполнения этой таблицы:
Процедура ЗаполнитьСоставНормы()
Если Выбран()=0 Тогда
Возврат;
КонецЕсли;
СписокНормы.УдалитьСтроки();
Состав = СоздатьОбъект("Справочник.СоставНормы");
Состав.ИспользоватьВладельца(ТекущийЭлемент());
Состав.ПорядокНаименований();
Состав.ВыбратьЭлементы();
Пока Состав.ПолучитьЭлемент() = 1 Цикл
Если Состав.ПометкаУдаления() = 1 Тогда
Продолжить;
КонецЕсли;
СписокНормы.НоваяСтрока();
СписокНормы.Ссылка = Состав.ТекущийЭлемент();
СписокНормы.Обмундирование = Состав.Обмундирование;
СписокНормы.ТипОбмундирования = Состав.ТипОбмундирования;
// Попытка записать новые реквизиты вызывает ошибку:
СписокНормы.ДатаНачала = Состав.ДатаНачала;
СписокНормы.ДатаОкончания = Состав.ДатаОкончания;
СписокНормы.Количество = Состав.КоличествоНаОдного;
СписокНормы.СрокНоски = Состав.СрокНоски;
СписокНормы.СуммаКомпенсации = Состав.СуммаКомпенсации.Получить(РабочаяДата());
КонецЦикла;
КонецПроцедуры
При выполнении этого кода система выдает ошибку: Поле агрегатного объекта не обнаружено (ДатаНачала). Проанализируем ситуацию и найдем верные решения.
Самая частая причина подобного поведения при работе с таблицами на форме в 1С 7.7 заключается в том, что Таблица Значений является динамической структурой. В отличие от табличных частей документов, структура колонок которых жестко задается в конфигураторе, Таблица Значений на форме должна быть сконфигурирована программно.
Если мы просто добавили реквизиты в справочник-источник и разместили новые элементы на форме, сама Таблица Значений СписокНормы о них «не знает». При попытке присвоить значение несуществующей колонке СписокНормы.ДатаНачала = ... платформа сообщает об отсутствии этого поля в объекте ТаблицаЗначений.
Чтобы исправить это, нам необходимо найти место инициализации колонок таблицы (обычно это процедура ПриОткрытии формы или модуль инициализации в самом верху модуля формы) и добавить создание новых колонок с помощью метода НоваяКолонка().
Посмотрим на пример правильной инициализации структуры Таблицы Значений:
// В модуле формы справочника при инициализации интерфейса:
СписокНормы.НоваяКолонка("Ссылка", "Справочник.СоставНормы");
СписокНормы.НоваяКолонка("Обмундирование", "Справочник.Обмундирование", , , "Обмундирование");
СписокНормы.НоваяКолонка("ТипОбмундирования", "Перечисление.ТипОбмундирования", 10, 0, "Тип обмундирования");
// Добавляем наши новые колонки, которых не хватало:
СписокНормы.НоваяКолонка("ДатаНачала", "Дата", , , "Дата начала");
СписокНормы.НоваяКолонка("ДатаОкончания", "Дата", , , "Дата окончания");
СписокНормы.НоваяКолонка("Количество", "Число", 8, 0);
СписокНормы.НоваяКолонка("СрокНоски", "Число", 8, 0, "Срок носки");
СписокНормы.НоваяКолонка("СуммаКомпенсации", "Число", 15, 2, "Сумма компенсации");
СписокНормы.ВидимостьКолонки("Ссылка", 0);
После добавления этих строк Таблица Значений получит новые поля в свою структуру данных, и обращение к свойствам СписокНормы.ДатаНачала и СписокНормы.ДатаОкончания перестанет вызывать фатальный сбой.
Вторая вероятная причина возникновения ошибки кроется в типе реквизитов справочника. В 1С 7.7 существует механизм периодических реквизитов (значений, которые изменяются во времени и хранят историю изменений). Если при создании реквизитов ДатаНачала и ДатаОкончания в конфигураторе была случайно установлена галочка «Периодический», то прямое обращение к ним вернет не дату, а специальный агрегатный объект типа Периодический.
Попытка записать объект типа Периодический напрямую в колонку с типом данных Дата приведет к ошибке несовместимости типов или к ошибке отсутствия поля агрегатного объекта.
Выяснить, является ли реквизит периодическим, можно в конфигураторе или программно через объект Метаданные, выполнив в Табло команду:
Метаданные.Справочник("СоставНормы").Реквизит("ДатаНачала").Периодический
Если возвращается значение 1 (Истина), значит, реквизит является периодическим. В таком случае для получения его значения на конкретную дату необходимо использовать встроенный метод Получить(). Напишем правильный вариант обращения:
// Использование метода Получить() для периодического реквизита:
СписокНормы.ДатаНачала = Состав.ДатаНачала.Получить(РабочаяДата());
СписокНормы.ДатаОкончания = Состав.ДатаОкончания.Получить(РабочаяДата());
Если же реквизит не является периодическим (значение свойства метаданных равно 0), использовать метод Получить() категорически нельзя — это также приведет к ошибке «Поле агрегатного объекта не обнаружено», поскольку у обычного реквизита типа Дата нет метода Получить(). В таком случае значение присваивается напрямую:
// Прямое присвоение для обычного (не периодического) реквизита:
СписокНормы.ДатаНачала = Состав.ДатаНачала;
СписокНормы.ДатаОкончания = Состав.ДатаОкончания;
Иногда разработчики сталкиваются со странным поведением кода при заполнении документов. Рассмотрим некорректный фрагмент кода из примера автора темы:
НормаОбмундирования.НоваяСтрока();
НормаОбмундирования.Обмундирование = СоставНормы.Обмундирование;
НормаОбмундирования.ЭтоГруппа = СоставНормы.Обмундирование.ЭтоГруппа();
Разберем архитектурные ошибки в данном коде, которые гарантированно вызовут проблемы в 1С 7.7:
НормаОбмундирования указывает на объект типа «Справочник», то вызов метода НоваяСтрока() недопустим. В версии 7.7 у справочников отсутствуют табличные части (в отличие от версии 8.х). Для создания нового элемента справочника необходимо использовать метод Новый(). Метод НоваяСтрока() поддерживается только у объектов типа Документ (для заполнения его табличной части) и у объекта ТаблицаЗначений.НормаОбмундирования.ЭтоГруппа = ... не имеет смысла. Свойство ЭтоГруппа() является методом (функцией) объекта типа Справочник, которая возвращает статус элемента (1 — если это группа, 0 — если элемент). Записать в это свойство значение напрямую невозможно, так как оно доступно только для чтения и определяется в момент создания объекта методом НоваяГруппа().Для исправления подобных ошибок всегда четко разграничивайте типы объектов, с которыми вы работаете в коде, и используйте отладчик для проверки текущего типа переменной через окно вычисления выражений (Табло).
Модификация метаданных и программного кода в 1С 7.7 в файловом или сетевом режимах часто усложняется тем, что для внесения изменений требуется монопольный доступ к базе данных. Это означает, что программисту приходится просить всех пользователей выйти из программы даже ради исправления одной опечатки. Чтобы избежать этого и сделать процесс разработки комфортным, рекомендуется использовать проверенные инструменты автоматизации:
Использование данных инструментов в связке с регулярным созданием резервных копий базы данных (бэкапов) позволит вам быстро локализовать любые ошибки, включая не обнаруженные поля агрегатных объектов, и поддерживать legacy-системы на высоком профессиональном уровне.