При работе с платформой 1С:Предприятие 7.7 начинающие разработчики часто сталкиваются с трудностями при попытке изменить значение периодического реквизита справочника. Типичная ошибка заключается в попытке обращения к свойствам Значение или ДатаЗнач напрямую через реквизит найденного элемента справочника. Система в таких случаях выдает сообщение о том, что атрибут не найден. В этой статье мы подробно разберем, почему это происходит, и изучим три надежных способа записи периодических данных.
Рассмотрим ситуацию, с которой столкнулся автор темы. В программном коде предпринималась попытка записать цену акции следующим образом:
xs = СоздатьОбъект("Справочник.Shares");
Если xs.НайтиЭлемент(BuyDoc.Ticker) = 1 Тогда
xs.ClPrice.Значение = NewPrice; // Ошибка: Атрибут не найден
xs.ClPrice.ДатаЗнач = ReportDate;
xs.Записать();
КонецЕсли;
Проанализируем причину неудачи. В 1С 7.7 периодический реквизит справочника при прямом обращении через точку (xs.ClPrice) ведет себя по-разному в зависимости от контекста. Если мы просто читаем его, система возвращает значение на текущую рабочую дату или дату, установленную методом ИспользоватьДату(). Однако свойства Значение и ДатаЗнач не являются атрибутами самого реквизита внутри справочника — они принадлежат специальному системному объекту Периодический. Для прямой записи без создания вспомогательных объектов необходимо использовать встроенные методы работы с реквизитом.
Это самый простой и быстрый способ записи. Метод Установить() позволяет передать дату и новое значение непосредственно в периодический реквизит объекта справочника. Выясним важную особенность: при использовании этого метода изменения фиксируются в базе данных немедленно, поэтому вызывать метод Записать() для самого справочника не требуется (если только вы не меняли другие, непериодические реквизиты).
Разберем правильный пример кода для нашей задачи:
xs = СоздатьОбъект("Справочник.Shares");
Если xs.НайтиЭлемент(BuyDoc.Ticker) = 1 Тогда
// Используем метод Установить(Дата, Значение)
xs.ClPrice.Установить(ReportDate, NewPrice);
// Метод Записать() здесь не обязателен для сохранения ClPrice
КонецЕсли;
Этот подход идеален, когда нам нужно обновить или создать запись на конкретную дату «в одно действие».
Иногда простой записи на дату недостаточно. Например, если нам нужно проанализировать историю изменений, удалить запись или найти значение на предыдущую дату. В таких случаях мы используем объект Периодический. Рассмотрим этот механизм подробнее.
Алгоритм работы выглядит следующим образом:
ИспользоватьОбъект().ДатаЗнач и Значение.Записать() для объекта Периодический.Посмотрим на пример реализации:
ОбъектПериод = СоздатьОбъект("Периодический");
xs = СоздатьОбъект("Справочник.Shares");
Если xs.НайтиЭлемент(BuyDoc.Ticker) = 1 Тогда
// Связываем объект с реквизитом ClPrice конкретного элемента xs
ОбъектПериод.ИспользоватьОбъект("ClPrice", xs.ТекущийЭлемент());
// Устанавливаем параметры записи
ОбъектПериод.ДатаЗнач = ReportDate;
ОбъектПериод.Значение = NewPrice;
// Сохраняем изменение в истории
ОбъектПериод.Записать();
КонецЕсли;
Этот метод более громоздкий, но он незаменим при выполнении сложных манипуляций с историей значений.
Проанализируем еще одну интересную возможность платформы 7.7. Если вызвать для объекта справочника метод ИспользоватьДату(), то система начинает воспринимать периодический реквизит как обычный. При выполнении метода Записать() справочник автоматически создаст (или обновит) запись в истории на указанную дату.
Пример реализации:
xs = СоздатьОбъект("Справочник.Shares");
Если xs.НайтиЭлемент(BuyDoc.Ticker) = 1 Тогда
// Указываем дату, на которую будут вноситься изменения
xs.ИспользоватьДату(ReportDate);
// Теперь обращаемся к реквизиту как к обычному полю
xs.ClPrice = NewPrice;
// Обязательно вызываем Записать(), чтобы изменения вступили в силу
xs.Записать();
КонецЕсли;
Этот способ очень удобен, если вам нужно одновременно обновить несколько периодических реквизитов на одну и ту же дату.
Прежде чем программный код заработает, необходимо убедиться, что реквизит правильно настроен в Конфигураторе. Разберем влияние ключевых флагов:
Мы рассмотрели различные подходы к решению проблемы. Если ваша задача — просто обновить цену из документа или обработки, используйте метод xs.ИмяРеквизита.Установить(Дата, Значение). Это наиболее компактный и читаемый код. Если же вы строите сложную систему учета с анализом прошлых периодов, осваивайте объект Периодический.
Также не забывайте о возможности использования англоязычного синтаксиса, как советовали участники форума. Например, CreateObject("Reference.Shares") вместо СоздатьОбъект("Справочник.Shares"). Это не влияет на функциональность, но может быть полезно при использовании сторонних инструментов разработки или переводчиков кода.