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