Часто в работе с 1С возникает задача, когда нужно выполнить длительную или ресурсоемкую операцию с файлом (например, конвертацию, подписание, архивацию) и затем обновить интерфейс пользователя, чтобы он увидел результат. Классический пример: в форме есть список прикрепленных файлов, пользователь выбирает один из них, нажимает кнопку, файл на сервере конвертируется из .txt в .pdf, и теперь в списке должен отображаться новый .pdf файл вместо старого .txt.
Основная сложность здесь кроется в архитектуре платформы 1С: форма и ее элементы существуют на клиенте, а все операции с файлами и базой данных происходят на сервере. Прямой вызов клиентской процедуры обновления формы из серверного кода невозможен. Разберем, как правильно организовать такое взаимодействие.
Проанализируем ситуацию. У нас есть клиентская форма, где пользователь видит список файлов. По нажатию кнопки мы вызываем серверную процедуру, которая выполняет конвертацию. После того как на сервере появился новый файл, серверный код "ничего не знает" о клиентской форме, с которой его вызвали. Он не может напрямую сказать форме: "Эй, форма, обнови свой список!".
Это фундаментальный принцип разделения контекста в 1С. Сервер обрабатывает запросы от множества клиентов и работает только с данными. Клиент отвечает за взаимодействие с пользователем и отображение этих данных. Связь между ними всегда инициируется клиентом.
Таким образом, наша задача — построить правильную цепочку вызовов: Клиент → Сервер → Клиент.
Рассмотрим по шагам, как реализовать необходимый функционал, чтобы он работал корректно и соответствовал архитектуре платформы.
Ключевой момент — с клиента нужно вызывать не процедуру, а именно функцию. Процедура просто выполняет действия на сервере и ничего не возвращает. Функция же может выполнить действия и вернуть на клиент результат своей работы, что нам и нужно.
В обработчике нажатия кнопки на клиентской форме получаем данные о выбранном файле и вызываем серверную функцию, передавая ей эту информацию.
Серверная функция, получив данные о файле, выполняет всю "тяжелую" работу:
jar-конвертор)..pdf.РаботаСФайлами. С помощью его функций нужно создать новый элемент справочника "Присоединенные файлы" (или аналога), связав его с тем же объектом-владельцем, что и у исходного файла.Истина/Ложь) или, что более удобно, структура, содержащая статус и сообщение об ошибке в случае неудачи.После того как серверная функция завершила свою работу и вернула результат, управление возвращается в ту же клиентскую процедуру, откуда был сделан вызов. Теперь у нас есть результат, и мы можем действовать.
Получив от сервера подтверждение успешной конвертации, клиентский код должен инициировать обновление списка файлов. Есть несколько способов это сделать:
ОбновитьОтображениеДанных(). Этот метод заставит форму перечитать свои данные с сервера и обновить все элементы, связанные с ними.Этот подход гарантирует, что форма запросит с сервера уже актуальные данные, и пользователь увидит в списке новый, сконвертированный файл вместо старого.
Посмотрим, как это может выглядеть в коде. Представим, что у нас есть форма с табличной частью СписокФайлов.
// Клиентский обработчик команды "Конвертировать"
&НаКлиенте
Процедура КонвертироватьФайл(Команда)
// Получаем данные о текущем выбранном файле
ТекущиеДанные = Элементы.СписокФайлов.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Сообщить("Файл не выбран!");
Возврат;
КонецЕсли;
// Вызываем серверную функцию для выполнения конвертации
// Передаем ссылку на объект присоединенного файла
РезультатВыполнения = ВыполнитьКонвертациюНаСервере(ТекущиеДанные.СсылкаНаФайл);
// После возврата управления с сервера анализируем результат
Если РезультатВыполнения.Успешно Тогда
// Если все прошло хорошо, обновляем отображение данных на форме
ОбновитьОтображениеДанных();
Сообщить("Файл успешно сконвертирован!");
Иначе
// Если произошла ошибка, выводим сообщение
ПоказатьПредупреждение(Неопределено, РезультатВыполнения.ТекстОшибки);
КонецЕсли;
КонецПроцедуры
// Серверная функция, выполняющая основную логику
&НаСервере
Функция ВыполнитьКонвертациюНаСервере(СсылкаНаСтарыйФайл)
Результат = Новый Структура("Успешно, ТекстОшибки");
Результат.Успешно = Ложь;
// Шаг 1: Получаем данные старого файла
// ... здесь код для получения двоичных данных, имени, расширения из объекта СсылкаНаСтарыйФайл
// Шаг 2: Запускаем внешний конвертор
// ... код для вызова КомандаСистемы() или ЗапуститьПриложение() для jar-конвертора
// Предположим, получили путь к новому файлу
ПутьКНовомуФайлу = "C:\temp\converted_file.pdf";
// Шаг 3: Добавляем новый файл в систему через API конфигурации
// В 1С:Документооборот это может быть функция из общего модуля РаботаСФайлами
// Например: РаботаСФайлами.ДобавитьФайл(ВладелецФайла, ПутьКНовомуФайлу, ...);
// ...
// Шаг 4: Помечаем на удаление старый файл
ОбъектСтарогоФайла = СсылкаНаСтарыйФайл.ПолучитьОбъект();
ОбъектСтарогоФайла.ПометкаУдаления = Истина;
ОбъектСтарогоФайла.Записать();
// Если все шаги прошли без ошибок
Результат.Успешно = Истина;
// Возвращаем структуру с результатом на клиент
Возврат Результат;
// Здесь также должна быть обработка исключений с помощью Попытка...Исключение
КонецФункции
Для более сложных сценариев, когда изменение данных на сервере должно отразиться не в одной, а сразу в нескольких открытых формах, можно использовать другие механизмы платформы:
ОповеститьОбИзменении(Ссылка): После изменения данных на сервере (например, записи нового файла) можно вызвать этот метод. Все открытые формы, отображающие данные по этой ссылке, получат событие и смогут автоматически обновиться.ПодключитьОбработчикОжидания) будет периодически проверять статус задания и обновит интерфейс по его завершении.Однако для простой задачи замены одного файла в текущей форме описанный выше алгоритм "вызов серверной функции и обновление по результату" является самым простым, надежным и правильным решением.