При работе в устаревших или кастомных конфигурациях 1С (таких как УПП 1.3 или КА 1.1) часто встречается классическая проблема: файл выгружается из базы во временную папку (Temp), открывается в Microsoft Word, пользователь вносит правки, но забывает нажать кнопку «Загрузить» в 1С. При следующем открытии того же документа старый временный файл затирается новым, и все несохраненные изменения в базе данных безвозвратно теряются. Рассмотрим, как программно заставить Word принудительно спрашивать пользователя о месте сохранения файла, защищая тем самым результаты его труда.
Разберем ситуацию подробнее. Обычно алгоритм работы с файлами в 1С выглядит так: данные из ХранилищеЗначения записываются во временный файл на диске через УстановитьИмяФайла() и Записать(). После этого вызывается метод ЗапуститьПриложение(). Word открывает этот конкретный файл по пути в папке Temp. Когда пользователь нажимает «Сохранить», Word просто обновляет этот временный файл. Если 1С не отслеживает изменения, то при закрытии формы или повторном открытии файла старый файл в Temp будет перезаписан «чистой» копией из базы данных.
Для решения этой задачи нам необходимо изменить поведение самого Word при открытии. Проанализируем несколько способов реализации этой логики.
Это самый изящный и правильный способ с точки зрения объектной модели Microsoft Word. Вместо того чтобы открывать документ методом Open, мы создадим новый документ на основе существующего. В этом случае Word создаст копию документа под названием «Документ 1», которая не имеет привязки к файлу на диске. При попытке сохранения пользователь обязательно увидит диалоговое окно «Сохранить как...».
Рассмотрим пример кода для реализации этого метода:
Попытка
WordПриложение = Новый COMОбъект("Word.Application");
Исключение
Сообщить("Не удалось запустить Microsoft Word. Проверьте, установлена ли программа.");
Возврат;
КонецПопытки;
// ПутьКВременномуФайлу - это путь, куда мы предварительно сохранили данные из базы
Документ = WordПриложение.Documents.Add(ПутьКВременномуФайлу);
WordПриложение.Visible = Истина;
WordПриложение.Activate();
В данном коде мы используем метод Documents.Add(), передавая в качестве параметра путь к нашему файлу. Важно понимать, что Word воспринимает этот путь как путь к шаблону (Template), даже если это обычный .docx. Результат — новый несохраненный документ с полным содержимым исходного файла.
Если по каким-то причинам метод шаблона не подходит, мы можем создать пустой документ и «влить» в него содержимое файла из базы. Выясним, почему этот метод лучше простого копирования через буфер обмена. Использование Selection.InsertFile не затрагивает системный буфер обмена пользователя, что делает работу программы более стабильной.
Разберем по шагам, как это реализовать:
// Создаем объект Word и новый пустой документ
WordApp = Новый COMОбъект("Word.Application");
NewDoc = WordApp.Documents.Add();
// Устанавливаем курсор в начало и вставляем содержимое внешнего файла
WordApp.Selection.InsertFile(ПутьКФайлуИзБазы);
// Делаем окно видимым для пользователя
WordApp.Visible = Истина;
WordApp.Activate();
В этом сценарии NewDoc также не имеет пути сохранения. Если пользователь нажмет «Ctrl+S», Word предложит выбрать папку и имя файла, что исключает риск случайной перезаписи временного файла в папке Temp.
Проанализируем ситуацию: что если мы не хотим использовать сложные COM-объекты, а предпочитаем стандартный запуск приложения? Мы можем программно запретить Word изменять файл в папке Temp. Для этого перед открытием файла средствами 1С установим ему атрибут Только чтение.
Посмотрим на пример реализации:
// Выгружаем файл из Хранилища Значения на диск
ФайлОбъект = Новый Файл(ПолныйПутьКФайлу);
Если ФайлОбъект.Существует() Тогда
// Используем системную команду для установки атрибута ReadOnly
ФайлОбъект.УстановитьТолькоЧтение(Истина);
КонецЕсли;
// Теперь запускаем файл штатным приложением
ЗапуститьПриложение(ПолныйПутьКФайлу);
При таком подходе пользователь сможет редактировать текст в Word, но при попытке сохранить изменения программа выдаст предупреждение: «Файл доступен только для чтения. Сохранить изменения под другим именем?». Это вынудит пользователя осознанно выбрать место для сохранения новой версии документа.
Если вы хотите сохранить возможность редактирования прямо в Temp, но боитесь затирания, можно использовать механизм уникальных имен. Вместо фиксированного имени файла типа Договор.docx, добавим к нему уникальный идентификатор сессии или документа.
Проанализируем, как сформировать уникальный путь:
УникальныйИдентификатор = Новый УникальныйИдентификатор();
ИмяФайла = "Договор_" + СтрЗаменить(Строка(УникальныйИдентификатор), "-", "") + ".docx";
ПолныйПуть = КаталогВременныхФайлов() + ИмяФайла;
// Далее записываем данные из базы по этому пути
ДанныеФайла.Записать(ПолныйПуть);
ЗапуститьПриложение(ПолныйПуть);
В этом случае каждое открытие файла создает новый физический файл на диске. Даже если пользователь откроет один и тот же документ десять раз подряд, в папке Temp появится 10 разных файлов, и ни один не затрет предыдущий. Однако стоит помнить, что это со временем забивает дисковое пространство временными файлами, которые нужно периодически очищать.
Подведем итог. Выбор решения зависит от бизнес-процессов вашей организации:
При использовании COM-объектов всегда помните о необходимости обработки исключений. Если на компьютере пользователя не установлен Microsoft Word или установлена «урезанная» версия, вызов Новый COMОбъект("Word.Application") приведет к аварийному завершению работы кода 1С. Всегда оборачивайте такие блоки в конструкцию Попытка ... Исключение.