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