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