Сохранение результатов и настроек обработки в 1С 8.3
Содержание
Закрыли обработку — и отбор, период и заполненная таблица исчезли. При следующем открытии приходится настраивать всё заново. Чтобы значения обработки сохранялись, их нужно куда-то положить: в настройки формы, во внешний файл, в саму информационную базу или во временное хранилище на время сеанса.
Выбор зависит от того, что именно вы сохраняете. Галочки и отбор на форме — это настройки интерфейса, им место в хранилище настроек. Готовый отчёт — это файл. Результат расчёта, который нужен другим документам, — это данные базы. Ниже разобраны все способы с рабочим кодом на встроенном языке 1С 8.3.
Чтобы не ошибиться с выбором, сверьтесь с таблицей — каждый способ решает свою задачу:
| Способ | Что хранит | Где живёт | Когда выбрать |
|---|---|---|---|
| Настройки формы | Отбор, период, галочки | Хранилище настроек, у пользователя | Запомнить интерфейс формы |
ХранилищеОбщихНастроек | Структуры, таблицы параметров | Хранилище настроек, по ключу | Общие настройки обработки |
| Внешний файл | Табличный документ, таблица | Диск, вне базы | Отчёт для отправки или архива |
| Регистр/справочник | Числа, итоги, карточки | Информационная база | Данные для других документов |
ХранилищеЗначения | Документ, картинка целиком | Реквизит базы | Сохранить объект без разбора |
| Временное хранилище | Промежуточные данные | Память сервера, на время формы | Не гонять данные между вызовами |
ХранилищеОбщихНастроек или включите автосохранение реквизитов формы.Запоминаем настройки формы между сеансами
Самый частый случай — чтобы при повторном открытии форма помнила отбор, период и переключатели. Для этого у реквизитов формы есть свойство «Сохранение данных в настройках».
Откройте форму в конфигураторе, выделите реквизит (например, поле периода или отбора) и в палитре свойств найдите СохранениеДанныхВНастройках. Доступны три значения:
- 🔹 Не использовать — значение не сохраняется (по умолчанию).
- 🔹 Использовать список — платформа запоминает несколько последних введённых значений и предлагает их списком.
- 🔹 Использовать — значение сохраняется и восстанавливается автоматически при открытии формы.
Этого хватает для большинства полей. Платформа сама пишет данные в хранилище настроек данных форм под ключом формы и конкретного пользователя — отдельный код не нужен.
Когда нужно управлять сохранением вручную (сохранить не реквизит, а произвольное значение), используйте глобальные методы:
// Сохранить значение по строковому ключу
СохранитьЗначение("ПутьВыгрузки", ПутьВыгрузки);
// Восстановить при открытии формы
ПутьВыгрузки = ВосстановитьЗначение("ПутьВыгрузки");
СохранитьЗначение и ВосстановитьЗначение кладут данные в хранилище настроек данных форм текущего пользователя. Значение переживает перезапуск программы, но привязано к пользователю: у коллеги будут свои настройки.
В веб-клиенте эти настройки хранятся на сервере, а не на компьютере пользователя. Поэтому обработка «вспомнит» отбор даже при входе с другого устройства под тем же логином.
Храним общие настройки через ХранилищеОбщихНастроек
Когда настройки обработки должны быть доступны по понятному ключу и, при необходимости, всем пользователям, подойдёт стандартное хранилище общих настроек. Оно удобнее тем, что вы сами задаёте ключ объекта и ключ настройки.
// Сохранить структуру с параметрами обработки
НастройкиОбработки = Новый Структура;
НастройкиОбработки.Вставить("Период", Период);
НастройкиОбработки.Вставить("Организация", Организация);
НастройкиОбработки.Вставить("ТолькоПроведённые", ТолькоПроведённые);
ХранилищеОбщихНастроек.Сохранить("ОбработкаЗагрузки", "ПоследнийЗапуск", НастройкиОбработки);
// Загрузить при открытии
Настройки = ХранилищеОбщихНастроек.Загрузить("ОбработкаЗагрузки", "ПоследнийЗапуск");
Если Настройки <> Неопределено Тогда
Период = Настройки.Период;
Организация = Настройки.Организация;
ТолькоПроведённые = Настройки.ТолькоПроведённые;
КонецЕсли;
Первый параметр — ключ объекта (обычно имя обработки), второй — ключ настройки. В одно хранилище можно класть структуру, таблицу значений, массив — любое сериализуемое значение. Если под ключом ничего нет, метод вернёт Неопределено — эту проверку делайте всегда.
Не кладите в настройки гигабайты данных. Хранилище настроек не рассчитано на большие объёмы — для результатов расчёта используйте регистр или файл (ниже).
Выгружаем результат во внешний файл
Если результат обработки — табличный документ (отчёт, печатная форма), его сохраняют в файл. Метод Записать табличного документа умеет отдавать несколько форматов:
// XLSX для Excel
ТабДок.Записать("C:\Выгрузка\Итог.xlsx", ТипФайлаТабличногоДокумента.XLSX);
// PDF — неизменяемый вид для отправки
ТабДок.Записать("C:\Выгрузка\Итог.pdf", ТипФайлаТабличногоДокумента.PDF);
// MXL — родной формат 1С, открывается внутри программы
ТабДок.Записать("C:\Выгрузка\Итог.mxl", ТипФайлаТабличногоДокумента.MXL);
Такой код работает только в толстом клиенте, где серверу доступна файловая система рабочего места. В тонком и веб-клиенте путь на диске пользователя из серверного кода недоступен — файл сначала готовят на сервере во временном хранилище, а потом отдают клиенту:
// &НаСервере: записать во временный файл и положить в хранилище
ВременныйФайл = ПолучитьИмяВременногоФайла("xlsx");
ТабДок.Записать(ВременныйФайл, ТипФайлаТабличногоДокумента.XLSX);
ДвоичныеДанные = Новый ДвоичныеДанные(ВременныйФайл);
УдалитьФайлы(ВременныйФайл);
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
// &НаКлиенте: предложить сохранить файл пользователю
ПолучитьФайл(Адрес, "Итог.xlsx", Истина);
Последний параметр Истина в ПолучитьФайл означает интерактивный режим: пользователь сам выберет папку. Для произвольного значения (не табличного документа) подойдёт пара ЗначениеВФайл / ЗначениеИзФайла — она сериализует таблицу значений, структуру или дерево в файл и читает обратно.
Если нужен простой текст или выгрузка в CSV, вместо табличного документа используйте текстовый:
Текст = Новый ТекстовыйДокумент;
Для Каждого Строка Из ТаблицаЗначений Цикл
Текст.ДобавитьСтроку(Строка.Код + ";" + Строка.Наименование);
КонецЦикла;
Текст.Записать("C:\Выгрузка\Список.csv", КодировкаТекста.UTF8);
Такой формат открывается в Excel и в любом текстовом редакторе, его удобно передавать во внешние системы.
Жёсткие пути вида C:\Выгрузка\ в коде — плохая практика. Папку выгрузки выносите в настройку обработки, иначе на другом компьютере код упадёт с ошибкой «каталог не найден».
Записываем итоги прямо в информационную базу
Когда результат обработки нужен не однократно, а дальше — другим документам, отчётам, другому пользователю, — его сохраняют в самой базе. Есть три рабочих варианта.
Регистр сведений — лучший выбор для табличных итогов (дата, организация, показатель). Создаёте менеджер записи и записываете:
Запись = РегистрыСведений.РезультатыРасчёта.СоздатьМенеджерЗаписи();
Запись.Период = ТекущаяДата();
Запись.Организация = Организация;
Запись.Сумма = ИтоговаяСумма;
Запись.Записать();
Справочник подойдёт, когда у результата должна быть карточка с реквизитами и своё имя:
Элемент = Справочники.СохранённыеРасчёты.СоздатьЭлемент();
Элемент.Наименование = "Расчёт от " + Формат(ТекущаяДата(), "ДЛФ=DD");
Элемент.Записать();
Реквизит типа ХранилищеЗначения нужен, когда в базе надо сохранить целиком табличный документ, картинку или произвольную структуру. Такой реквизит умеет хранить любое значение в сжатом виде:
Запись.ДанныеОтчёта = Новый ХранилищеЗначения(ТабДок);
Обратно значение достают методом Получить:
ТабДок = Запись.ДанныеОтчёта.Получить();
Конструктор ХранилищеЗначения принимает вторым параметром степень сжатия — для крупных таблиц это ощутимо экономит место в базе.
Регистр сведений индексируется и быстро отбирается по периоду и измерениям. ХранилищеЗначения — наоборот, «чёрный ящик»: по его содержимому нельзя построить запрос. Храните в нём то, что нужно достать целиком, а не искать по частям.
Временное хранилище: держим значение на время работы формы
Пока форма обработки открыта, промежуточные данные (большая таблица, подготовленный файл) незачем гонять туда-сюда между клиентом и сервером. Их кладут во временное хранилище — область памяти на сервере, привязанную к форме.
// &НаСервере: положить таблицу и получить адрес
АдресТаблицы = ПоместитьВоВременноеХранилище(ТаблицаЗначений, УникальныйИдентификатор);
// Позже, при следующем обращении к серверу — достать по адресу
ТаблицаЗначений = ПолучитьИзВременногоХранилища(АдресТаблицы);
Если вторым параметром передать УникальныйИдентификатор формы, значение живёт, пока форма открыта, и удаляется автоматически при её закрытии. Если передать уникальный идентификатор без привязки — значение очистится в конце серверного вызова.
Для ускорения повторяющихся вычислений есть другой механизм — общие модули с флагом «Повторное использование возвращаемых значений» (на время сеанса или вызова). Платформа кэширует результат функции по набору параметров и при повторном вызове с теми же аргументами не выполняет код заново, а отдаёт запомненное значение. Это снимает нагрузку, когда обработка многократно дёргает одну и ту же справочную функцию.
Ведём историю запусков и протокол в журнале
Чтобы видеть, когда и с каким результатом отрабатывала обработка, пишите протокол. Два проверенных приёма.
Журнал регистрации — встроенный механизм платформы, отдельных объектов создавать не нужно:
ЗаписьЖурналаРегистрации("ОбработкаЗагрузки.Итог",
УровеньЖурналаРегистрации.Информация, , ,
"Загружено строк: " + Формат(КоличествоСтрок, "ЧГ=0"));
Запись найдётся в разделе НСИ и администрирование → Журнал регистрации (в типовых конфигурациях на БСП) с отбором по вашему событию ОбработкаЗагрузки.Итог. Это удобно, когда историю смотрит администратор, а не пользователь.
Отдельный регистр сведений нужен, когда историю должны видеть пользователи прямо в интерфейсе. Заводите регистр с измерениями «Дата», «Пользователь», «Статус» и ресурсом «Комментарий» — и записываете в него по итогам каждого запуска. По такому регистру легко построить отчёт «кто и когда запускал обработку».
Для числа обработанных строк всегда выводите значение через Формат(Число, "ЧГ=0") — иначе при склейке числа со строкой получите разделители групп разрядов в сообщении.
Запускаем сохранение по расписанию
Если итоги надо сохранять регулярно без участия человека (например, каждую ночь выгружать остатки в файл), подойдут регламентные задания.
Порядок настройки:
- Вынесите код сохранения в процедуру общего модуля с установленным флагом «Сервер» (вызов с клиента для регламента недоступен).
- Создайте объект метаданных «Регламентное задание» и укажите в нём имя этой процедуры как метод.
- Задайте расписание в свойстве
Расписание(типРасписаниеРегламентногоЗадания) — периодичность, время, дни недели.
Параметры расписания можно задать и программно:
Задание = РегламентныеЗадания.НайтиПоИмени("ЕжедневнаяВыгрузка");
Расписание = Новый РасписаниеРегламентногоЗадания;
Расписание.ВремяНачала = Дата(1, 1, 1, 2, 0, 0); // 02:00
Расписание.ДнямиНедели = Новый Массив; // пусто = каждый день
Задание.Расписание = Расписание;
Задание.Записать();
Как это работает в зависимости от варианта базы:
- 🔹 Клиент-серверная база — регламентные задания выполняет планировщик кластера автоматически, даже когда пользователи не в сети.
- 🔹 Файловая база — планировщика нет. Задания отрабатывают только пока открыт сеанс, запустивший их выполнение. Для регулярной работы выделяют отдельную постоянно открытую «техническую» сессию или переносят базу в клиент-серверный режим.
В регламентном задании нет интерактива: нельзя показать вопрос, выбрать файл вручную, обратиться к диску клиента. Все пути и параметры задавайте заранее в константах или настройках, а результат пишите в файл на сервере либо в базу.
Проверить, отработало ли задание и без ошибок ли, можно там же, в журнале регистрации, — платформа фиксирует старт и завершение фоновых заданий.
Отдельная задача — запустить длительное сохранение однократно и в фоне, не блокируя пользователя за формой. Для этого есть фоновые задания: процедура выполнится на сервере параллельно, а пользователь продолжит работу.
Параметры = Новый Массив;
Параметры.Добавить(Организация);
ФоновыеЗадания.Выполнить("ОбщийМодуль.СохранитьИтоги", Параметры, ,
"Фоновое сохранение итогов");
Пользователю в этом случае показывают индикатор ожидания, а по завершении — результат. В типовых конфигурациях на БСП для этого есть готовая обёртка «Длительные операции», которая сама следит за состоянием фонового задания и возвращает результат на форму.
Частые вопросы
Чем `ХранилищеОбщихНастроек` отличается от `СохранитьЗначение`?
СохранитьЗначение пишет в хранилище настроек данных форм по строковому ключу и привязано к текущему пользователю. ХранилищеОбщихНастроек — отдельное хранилище с парой «ключ объекта + ключ настройки», и в него можно писать настройки для других пользователей (если есть права). Для настроек всей обработки удобнее второе.Почему после обновления конфигурации пропали сохранённые настройки формы?
Можно ли сохранить табличный документ прямо в базу, а не в файл?
ХранилищеЗначения и положите в него документ: Новый ХранилищеЗначения(ТабДок). Обратно достанете методом Получить. По содержимому такого поля нельзя строить запросы — оно хранится как единый упакованный объект.Сохранятся ли настройки обработки у другого пользователя?
СохранитьЗначение) — у каждого свои значения. Чтобы настройки были общими, пишите их в ХранилищеОбщихНастроек с явным ключом либо храните в константе или регистре сведений.Куда сохраняются значения в веб-клиенте — на сервер или на диск?
ПолучитьФайл: браузер сам предложит сохранить файл на компьютер пользователя.