Как закрыть документ Word из 1С с сохранением изменений и без лишних диалоговых окон?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации документооборота в 1С программисты часто сталкиваются с проблемой: при попытке закрыть Microsoft Word программно, приложение «зависает» или выводит окно с вопросом «Сохранить изменения в файле?». Это делает невозможной потоковую обработку файлов на сервере или в фоновых заданиях. В этой статье мы подробно разберем, как заставить Word работать «молча», сохранять данные автоматически и корректно завершать процессы в памяти.

Разбираем причину появления диалоговых окон

Прежде всего, проанализируем ситуацию: почему Word вообще задает вопросы? Это происходит в трех случаях: когда свойство DisplayAlerts включено, когда документ был изменен, но метод Save не был вызван, или когда документ создан на основе шаблона и еще не имеет пути в файловой системе. Наша задача — программно имитировать действия пользователя так, чтобы у приложения не осталось поводов для сомнений.

Шаг 1. Отключение системных уведомлений через DisplayAlerts

Первым делом нам необходимо настроить само приложение Word. У объекта Application есть свойство DisplayAlerts, которое отвечает за вывод предупреждений. Рассмотрим, какие значения оно может принимать:

Посмотрим на пример правильной инициализации объекта в 1С:


Word = Новый COMОбъект("Word.Application");
Word.Visible = Ложь; // Скрываем окно приложения
Word.Application.DisplayAlerts = 0; // Отключаем все диалоги

Шаг 2. Корректное сохранение документа

Существует несколько способов записи изменений. Выбор метода зависит от того, работаете ли вы с уже существующим файлом или создаете новый на основании шаблона. Проанализируем основные подходы.

Метод Save(). Используется для сохранения изменений в уже открытом файле, который имеет физический путь на диске. Если файл новый (создан через Documents.Add), этот метод все равно может вызвать окно «Сохранить как», поэтому его лучше использовать с осторожностью.

Метод SaveAs() или SaveAs2(). Это наиболее надежный способ для работы в 1С. Мы явно указываем путь, куда нужно поместить файл. Рассмотрим фрагмент кода:


// ПутьКФайлу — полный путь к новому или существующему файлу
DocWord = Word.Documents.Add(ПутьКШаблону);
// ... тут идет код заполнения документа ...
DocWord.SaveAs(ПутьКФайлу);

Если вы работаете с современными версиями Office (начиная с 2010), рекомендуется использовать SaveAs2, так как он лучше поддерживает формат .docx и параметры совместимости.

Шаг 3. Сохранение в формате PDF

Часто бизнес-задача требует не просто изменить Word-файл, а сохранить его в неизменяемом виде. Выясним, как сделать это без лишних окон. Для этого используется метод ExportAsFixedFormat. Рассмотрим пример:


ИмяФайлаPDF = "C:\Docs\Договор.pdf";
wdExportFormatPDF = 17; // Константа формата PDF
ОбъектШаблон.ExportAsFixedFormat(ИмяФайлаPDF, wdExportFormatPDF);

Важно помнить, что после экспорта сам документ Word всё еще считается «измененным». Поэтому при закрытии он снова может спросить о сохранении уже в формате .docx. Чтобы этого избежать, используйте параметры метода Quit, о которых мы поговорим далее.

Шаг 4. Закрытие приложения без вопросов

Самый ответственный момент — вызов метода Quit. У этого метода есть параметры, которые позволяют управлять финальным поведением. В языке VBA Word константа wdSaveChanges имеет значение -1, а wdDoNotSaveChanges значение 0.

Разберем, как это применить в 1С:

  1. Закрыть с принудительным сохранением: Word.Quit(-1);
  2. Закрыть без сохранения (все изменения будут потеряны): Word.Quit(0);

Посмотрим на комплексный пример, который объединяет сохранение и закрытие:


// Сначала сохраняем конкретный документ
DocWord.Save(); 
// Затем закрываем приложение, указывая, что сохранять больше ничего не нужно
Word.Quit(0); 

Шаг 5. Очистка памяти и борьба с «зависшими» процессами

Многие разработчики замечают, что даже после выполнения команды Quit в диспетчере задач остаются процессы winword.exe. Это происходит из-за того, что COM-объект в 1С удерживается ссылкой в переменной. Проанализируем, как правильно «убирать за собой».

Правило «одной переменной»: если вы создали COMОбъект, в конце работы обязательно присвойте всем переменным, ссылающимся на Word и его документы, значение Неопределено.


// Правильный порядок завершения:
DocWord.Close(0); // Закрываем документ без сохранения (если уже сохранили ранее)
Word.Quit(0);     // Закрываем само приложение
DocWord = Неопределено; // Очищаем ссылку на документ
Word = Неопределено;    // Очищаем ссылку на приложение

Если вы работаете в цикле, категорически не рекомендуется создавать новый объект Word.Application на каждой итерации. Это крайне ресурсозатратно. Лучше создать один объект до начала цикла, открывать/закрывать в нем документы, и вызвать Quit один раз после завершения всех операций.

Шаг 6. Особенности работы на сервере (фоновые задания)

Если ваш код выполняется на стороне сервера (например, в регламентном задании), Word может вести себя нестабильно. Выясним причину: Word — это десктопное приложение, ему требуются определенные папки профиля пользователя для временных файлов. Даже если Visible = Ложь, он ищет папку Desktop.

Решение: убедитесь, что на сервере созданы следующие системные папки (зависит от разрядности системы):

Без этих папок Word может игнорировать команды Save и Quit, просто «зависая» в ожидании окружения.

Итоговый надежный алгоритм

Подведем итог и составим шаблон функции, которая будет работать стабильно и «тихо»:


&НаКлиенте
Процедура ОбработатьДокументБезДиалогов(ПутьКФайлу)
    Попытка
        Word = Новый COMОбъект("Word.Application");
        Word.Visible = Ложь;
        Word.DisplayAlerts = 0;
    Исключение
        Сообщить("Не удалось запустить Word: " + ОписаниеОшибки());
        Возврат;
    КонецПопытки;

    Попытка
        // Открываем документ
        Документ = Word.Documents.Open(ПутьКФайлу);
        
        // Выполняем полезную работу, например, меняем колонтитулы
        Документ.Sections.Item(1).Footers.Item(1).Range.Text = "Автоматическая обработка 1С";
        
        // Сохраняем изменения
        Документ.Save();
        
        // Закрываем документ (0 - wdDoNotSaveChanges, т.к. уже сохранили)
        Документ.Close(0);
    Исключение
        Сообщить("Ошибка при обработке файла: " + ОписаниеОшибки());
    КонецПопытки;

    // Завершаем работу приложения
    Word.Quit(0);
    
    // Очистка памяти
    Документ = Неопределено;
    Word = Неопределено;
КонецПроцедуры

Используя этот подход, мы гарантируем, что пользователь не увидит никаких всплывающих окон, а серверная часть 1С не будет перегружена «зомби-процессами» офисных приложений. Важно помнить: всегда используйте блоки Попытка...Исключение, так как работа с внешними компонентами через COM всегда сопряжена с риском возникновения непредсказуемых ошибок окружения.

← На главную