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