В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача автоматизации ввода данных. Типичный сценарий: пользователь выбирает объект (например, «Оборудование»), и система должна мгновенно подтянуть связанные с ним данные (например, «Заменяемый картридж») из истории, хранящейся в регистре сведений. Несмотря на кажущуюся простоту, здесь есть несколько «подводных камней», связанных с типами данных, контекстом исполнения кода и особенностями работы с временными отметками.
Разберем подробно, как правильно организовать этот процесс, проанализируем типичные ошибки начинающих разработчиков и рассмотрим наиболее эффективные методы получения данных.
Самый простой и быстрый в написании способ получить данные из периодического регистра сведений — использование метода менеджера регистра ПолучитьПоследнее(). Рассмотрим пример реализации, который часто применяется в общих модулях.
Предположим, у нас есть периодический регистр РасходныеМатериалыВОборудовании с измерением Оборудование и ресурсом ЗаменяемыйКартридж. Наша задача — получить значение ресурса на определенную дату.
Проанализируем программный код в общем модуле:
// Функция в общем модуле (должны быть установлены флаги "Сервер" и "Вызов сервера")
Функция ПолучитьАктуальныйКартридж(АктуальнаяДата, ВыбранноеОборудование) Экспорт
// Создаем структуру отбора.
// ВАЖНО: Отбор всегда идет по ИЗМЕРЕНИЯМ регистра.
Отбор = Новый Структура();
Отбор.Вставить("Оборудование", ВыбранноеОборудование);
// Получаем структуру последних значений ресурсов
ЗначенияРесурсов = РегистрыСведений.РасходныеМатериалыВОборудовании.ПолучитьПоследнее(АктуальнаяДата, Отбор);
// Возвращаем конкретный ресурс.
// Если запись не найдена, структура будет содержать пустые значения соответствующих типов.
Возврат ЗначенияРесурсов.ЗаменяемыйКартридж;
КонецФункции
Важные замечания по этому методу:
ПолучитьПоследнее принимает в отбор только измерения.ВыбранноеОборудование имеет тот же тип, что и измерение в регистре (например, СправочникСсылка.Номенклатура). Если вы передадите строку вместо ссылки, поиск не даст результатов.АктуальнаяДата передать пустую дату, система вернет самую последнюю запись в регистре за всю историю.Рассмотрим ситуацию, которую часто обсуждают на форумах: код написан верно, данные в регистре есть, но поле на форме остается пустым. Выясним причину, проанализировав работу платформы с временем.
Метод ПолучитьПоследнее(Дата, Отбор) ищет запись, период которой меньше или равен переданной дате. Если в документе реквизит Объект.Дата равен 15.10.2023 00:00:00 (начало дня), а запись в регистре была сделана тем же числом, но позже (например, в 12:00:00), то метод её «не увидит».
Для решения этой проблемы при вызове функции из формы рекомендуется использовать либо текущую дату сеанса, либо конец дня документа:
&НаКлиенте
Процедура ОборудованиеПриИзменении(Элемент)
// Используем КонецДня, чтобы захватить все записи, сделанные в течение дня документа
ДатаДляПоиска = КонецДня(Объект.Дата);
// Вызываем серверную функцию для получения данных
Объект.СтарыйКартридж = ОбщийМодульСервер.ПолучитьАктуальныйКартридж(ДатаДляПоиска, Объект.Оборудование);
КонецПроцедуры
Более профессиональным и гибким подходом считается использование запроса к виртуальной таблице СрезПоследних. Это позволяет избежать проблем с производительностью на больших объемах данных и дает возможность накладывать сложные условия.
Рассмотрим пример запроса:
&НаСервереБезКонтекста
Функция ПолучитьКартриджЗапросом(АктуальнаяДата, ОборудованиеСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РМ.ЗаменяемыйКартридж КАК Картридж
|ИЗ
| РегистрСведений.РасходныеМатериалыВОборудовании.СрезПоследних(&Период, Оборудование = &Оборудование) КАК РМ";
Запрос.УстановитьПараметр("Период", АктуальнаяДата);
Запрос.УстановитьПараметр("Оборудование", ОборудованиеСсылка);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Картридж;
КонецЕсли;
Возврат Справочники.Номенклатура.ПустаяСсылка();
КонецФункции
Преимущества использования запроса:
ГДЕ или параметры виртуальной таблицы).NULL или пустых ссылок).Чтобы подстановка работала корректно в управляемом интерфейсе, необходимо соблюдать правила контекстных вызовов. Выполним настройку по шагам:
&НаСервереБезКонтекста, так как это работает быстрее (не передается вся форма на сервер).Посмотрим на итоговую структуру модуля формы:
&НаКлиенте
Процедура ОборудованиеПриИзменении(Элемент)
Если ЗначениеЗаполнено(Объект.Оборудование) Тогда
// Передаем дату документа и ссылку на оборудование
Объект.ЗаменяемыйКартридж = ПолучитьДанныеИзРегистра(Объект.Дата, Объект.Оборудование);
Иначе
// Очищаем зависимое поле, если основное пустое
Объект.ЗаменяемыйКартридж = ПредопределенноеЗначение("Справочник.Номенклатура.ПустаяСсылка");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьДанныеИзРегистра(ДатаДокумента, СсылкаОборудование)
// Здесь может быть либо логика с ПолучитьПоследнее(), либо Запрос
// Для надежности используем границу времени или текущий момент
СтруктураДанных = РегистрыСведений.РасходныеМатериалыВОборудовании.ПолучитьПоследнее(КонецДня(ДатаДокумента), Новый Структура("Оборудование", СсылкаОборудование));
Возврат СтруктураДанных.ЗаменяемыйКартридж;
КонецФункции
Проанализировав ситуацию, можно выделить основные правила безопасной подстановки данных:
Во-первых, всегда проверяйте структуру регистра сведений. Отборы в методах ПолучитьПоследнее или параметрах СрезПоследних работают только по измерениям. Если вам нужно найти данные по значению ресурса, используйте обычный запрос к физической таблице регистра с условием в секции ГДЕ.
Во-вторых, помните о времени. В 1С 00:00:00 — это самое начало дня. Если записи вносятся оперативно в течение дня, поиск на начало дня их не найдет. Используйте КонецДня() или Неопределено (для получения самого последнего значения вне зависимости от даты).
В-третьих, следите за контекстом. В управляемых формах обращение к объекту РегистрыСведений напрямую на клиенте невозможно. Всегда выносите логику получения данных на сервер.
Соблюдение этих простых правил позволит вам создавать отзывчивые и надежные интерфейсы, которые экономят время пользователей и минимизируют ошибки ручного ввода.