Почему Word программно открывается в режиме только для чтения и как это исправить в 1С

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

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

Проанализируем причины такого поведения платформы и офисного приложения, а также разберем по шагам надежные способы решения этой проблемы.

Причины блокировки документа в режиме чтения

Выделим основные технические факторы, из-за которых Word блокирует редактирование файла:

  1. Особенности макета типа «Active document». При сохранении макета данного типа методом Записать() платформа 1С в некоторых сценариях создает на диске файл с системным атрибутом «Только для чтения» или оставляет открытый OLE-дескриптор в памяти процесса.
  2. Использование метода Documents.Open без параметров. По умолчанию Word при открытии файла с признаками шаблона или защищенного каталога переводит его в режим чтения, если явно не указано обратное.
  3. Зависшие фоновые процессы WINWORD.EXE. Если предыдущие COM-сессии не были корректно закрыты методами Quit(), невидимые экземпляры Word могут удерживать файловые блокировки.
  4. Режим чтения разметки (Reading Layout). В зависимости от настроек безопасности Word документ может открыться в специальном представлении для чтения, где запрещено прямое позиционирование курсора.

Способ 1. Переход на макет типа «Двоичные данные» (Рекомендуемый)

Наиболее надежным решением является отказ от устаревшего типа макета Active document в пользу обычных двоичных данных. При выгрузке двоичных данных на диск файл сохраняется как чистый байтовый поток без наложения OLE-оболочек и скрытых атрибутов только для чтения.

Рассмотрим, как правильно сохранить и открыть шаблон из макета двоичных данных:


// Получаем макет двоичных данных
ДвоичныеДанныеШаблона = РеквизитФормыВЗначение("Объект").ПолучитьМакет("ПФ_DOCX_Шаблон");

// Формируем уникальный путь во временном каталоге
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
ДвоичныеДанныеШаблона.Записать(ИмяВременногоФайла);

// Инициализируем COM-соединение с Word
Попытка
    Word = Новый COMОбъект("Word.Application");
    Word.Visible = Ложь;
Исключение
    ВызватьИсключение "Не удалось инициализировать Microsoft Word: " + ОписаниеОшибки();
КонецПопытки;

// Открываем документ для редактирования
ДокументВорд = Word.Documents.Open(ИмяВременногоФайла, Ложь, Ложь);

Способ 2. Использование метода Documents.Add вместо Documents.Open

Разберем классический подход к созданию печатных форм. Вместо открытия самого файла шаблона на редактирование правильнее создавать новый документ на базе имеющегося шаблона с помощью метода Documents.Add. Это исключает блокировки исходного файла и гарантирует, что создаваемый документ всегда будет доступен для записи.


// Создаем новый документ на основе файла-шаблона
НовыйДокумент = Word.Documents.Add(ИмяВременногоФайла);

// Заполняем закладку в созданном документе
Если НовыйДокумент.Bookmarks.Exists("ДатаДоговора") Тогда
    Закладка = НовыйДокумент.Bookmarks("ДатаДоговора");
    Закладка.Select();
    Word.Selection.TypeText(Формат(ТекущаяДата(), "ДЛФ=DD"));
КонецЕсли;

// Делаем Word видимым для пользователя или сохраняем результат
Word.Visible = Истина;

Способ 3. Программное снятие атрибута «Только чтение» перед открытием

Если в силу архитектуры конфигурации макет обязательно должен оставаться объектом Active document, перед передачей пути в Word проверим и принудительно снимем системный атрибут файла средствами 1С.

Посмотрим на пример реализации с объектом Файл:


Макет = РеквизитФормыВЗначение("Объект").ПолучитьМакет("ПФ_MXL_МОЛ");
ПолноеИмяФайла = КаталогВременныхФайлов() + "Шаблон.doc";
Макет.Записать(ПолноеИмяФайла);

// Снимаем системный флаг ReadOnly средствами 1С
ФайлНаДиске = Новый Файл(ПолноеИмяФайла);
Если ФайлНаДиске.Существует() И ФайлНаДиске.ПолучитьТолькоЧтение() Тогда
    ФайлНаДиске.УстановитьТолькоЧтение(Ложь);
КонецЕсли;

// Явно передаем параметр ReadOnly = Ложь при открытии в Word
ДокументВорд = Word.Documents.Open(ПолноеИмяФайла, Ложь, Ложь);

// Принудительно включаем режим обычной разметки страницы (wdPrintView = 3)
Word.ActiveWindow.View.Type = 3;

Способ 4. Корректное завершение процессов Word

Проанализируем ситуацию с зависанием процессов: если при возникновении ошибок COM-объект не освобождается, Word остается висеть в диспетчере задач Windows и блокирует повторно создаваемые файлы в папке временных файлов.

Для предотвращения утечек обязательно используем конструкцию Попытка ... Исключение с гарантированным закрытием приложения в блоке очистки:


Word = Неопределено;
Документ = Неопределено;

Попытка
    Word = Новый COMОбъект("Word.Application");
    Документ = Word.Documents.Add(ПолноеИмяФайла);
    
    // Выполняем алгоритм заполнения закладок
    // ...
    
    Word.Visible = Истина;
Исключение
    // В случае ошибки принудительно закрываем Word без сохранения
    Если Документ <> Неопределено Тогда
        Документ.Close(Ложь);
    КонецЕсли;
    Если Word <> Неопределено Тогда
        Word.Quit();
    КонецЕсли;
    
    ВызватьИсключение "Ошибка при формировании документа Word: " + ОписаниеОшибки();
КонецПопытки;

Резюме: для стабильной работы печатных форм Word храните шаблоны как Двоичные данные, создавайте результирующие файлы через Documents.Add и всегда предусматривайте корректное освобождение COM-объектов при исключениях.

← На главную