При программной работе с Microsoft Word через COM-объект разработчики 1С часто сталкиваются с задачей сохранения созданного или заполненного документа. Если передать методу SaveAs только путь и имя файла без явного расширения, текстовый процессор обычно автоматически сохраняет его в формате, установленном в параметрах программы по умолчанию (например, .docx).
Однако если имя файла задается пользователем или формируется динамически и содержит в себе символы точки (например, "Акт сверки от 12.02.2025"), логика парсера Microsoft Word дает сбой: строка после крайней правой точки автоматически воспринимается приложением как расширение файла. В итоге файл сохраняется с расширением .2025 или вовсе без валидного расширения, хотя его внутреннее содержимое формируется в заданном формате.
Разберем детально, почему это происходит, как программно узнать формат по умолчанию и как правильно сохранять такие файлы.
Проанализируем работу метода SaveAs (и его версии SaveAs2) объектной модели Microsoft Word. Поведение приложения устроено следующим образом:
FileFormat.Чтобы избежать порчи расширения, необходимо явно передавать методу SaveAs как полное имя с правильным расширением, так и числовой код формата во втором параметре (FileFormat).
Рассмотрим, как из 1С получить формат, который выбран у пользователя по умолчанию в параметрах Word (меню Файл — Параметры — Сохранение — Сохранять файлы в следующем формате).
У объекта Word.Application доступно свойство DefaultSaveFormat. Оно возвращает строковый идентификатор конвертера формата:
"" — стандартный формат документов текущей версии Office (расширение .docx, числовой код формата 16)."Doc" — формат документов Word 97–2003 (расширение .doc, числовой код формата 0)."Docm" или "MacroEnabledDocument" — документ с поддержкой макросов (расширение .docm, числовой код формата 13)."RTF" — формат Rich Text Format (расширение .rtf, числовой код формата 6)."HTML" или "MHTML" — веб-страницы (расширение .htm / .mht).Посмотрим на пример функции в 1С, которая определяет расширение и соответствующий код формата WdSaveFormat по значению DefaultSaveFormat:
Функция ПолучитьПараметрыФорматаWordПоУмолчанию(WordApp) Экспорт
СтруктураФормата = Новый Структура("Расширение, КодФормата", ".docx", 16);
ФорматПоУмолчанию = ВРег(СокрЛП(WordApp.DefaultSaveFormat));
Если ФорматПоУмолчанию = "" Тогда
// Стандартный формат docx
СтруктураФормата.Расширение = ".docx";
СтруктураФормата.КодФормата = 16;
ИначеЕсли ФорматПоУмолчанию = "DOC" Тогда
// Word 97-2003
СтруктураФормата.Расширение = ".doc";
СтруктураФормата.КодФормата = 0;
ИначеЕсли ФорматПоУмолчанию = "DOCM" Или ФорматПоУмолчанию = "MACROENABLEDDOCUMENT" Тогда
// Документ с макросами
СтруктураФормата.Расширение = ".docm";
СтруктураФормата.КодФормата = 13;
ИначеЕсли ФорматПоУмолчанию = "RTF" Тогда
// Текст в формате RTF
СтруктураФормата.Расширение = ".rtf";
СтруктураФормата.КодФормата = 6;
КонецЕсли;
Возврат СтруктураФормата;
КонецФункции
В объектной модели Word также присутствует коллекция FileConverters, которая содержит информацию обо всех зарегистрированных конвертерах файлов. У каждого элемента коллекции есть свойства ClassName, Extensions и SaveFormat.
Разберем процедуру перебора коллекции конвертеров для сопоставления с DefaultSaveFormat:
Функция НайтиПараметрыФорматаЧерезКонвертеры(WordApp) Экспорт
ИмяКлассаПоУмолчанию = СокрЛП(WordApp.DefaultSaveFormat);
// Если пустая строка - это базовый docx
Если ПустаяСтрока(ИмяКлассаПоУмолчанию) Тогда
Возврат Новый Структура("Расширение, КодФормата", ".docx", 16);
КонецЕсли;
Конвертеры = WordApp.FileConverters;
Количество = Конвертеры.Count;
Для Индекс = 1 По Количество Цикл
Конвертер = Конвертеры.Item(Индекс);
Если ВРег(СокрЛП(Конвертер.ClassName)) = ВРег(ИмяКлассаПоУмолчанию) Тогда
СписокРасширений = СокрЛП(Конвертер.Extensions);
ПервоеРасширение = ?(Найти(СписокРасширений, " ") > 0,
Лев(СписокРасширений, Найти(СписокРасширений, " ") - 1),
СписокРасширений);
Если Не ПустаяСтрока(ПервоеРасширение) И Лев(ПервоеРасширение, 1) <> "." Тогда
ПервоеРасширение = "." + ПервоеРасширение;
КонецЕсли;
Возврат Новый Структура("Расширение, КодФормата", ПервоеРасширение, Конвертер.SaveFormat);
КонецЕсли;
КонецЦикла;
// Значение по умолчанию, если класс не найден
Возврат Новый Структура("Расширение, КодФормата", ".docx", 16);
КонецФункции
Объединим полученные знания и разберем полный алгоритм создания и сохранения документа Word из 1С, когда в имени файла содержатся произвольные пользовательские точки:
Процедура СохранитьДокументWordСТочкамиВИмени(КаталогСохранения, ИмяФайлаОтПользователя) Экспорт
WordApp = Новый COMОбъект("Word.Application");
WordApp.Visible = Ложь;
WordApp.DisplayAlerts = 0; // Отключаем диалоговые окна
Попытка
// Создаем новый документ
Документ = WordApp.Documents.Add();
// Заполняем документ текстом
Параграф = Документ.Paragraphs.Add();
Параграф.Range.Text = "Тестовый документ, сформированный из 1С:Предприятия.";
// Определяем параметры формата по умолчанию
ПараметрыФормата = ПолучитьПараметрыФорматаWordПоУмолчанию(WordApp);
// Очищаем имя файла от недопустимых символов Windows
ИмяФайлаБезЗапрещенныхСимволов = ИмяФайлаОтПользователя;
ЗапрещенныеСимволы = "\/:*?""<>|";
Для Сч = 1 По СтрДлина(ЗапрещенныеСимволы) Цикл
Символ = Сред(ЗапрещенныеСимволы, Сч, 1);
ИмяФайлаБезЗапрещенныхСимволов = СтрЗаменить(ИмяФайлаБезЗапрещенныхСимволов, Символ, "_");
КонецЦикла;
// Формируем полный путь с принудительным добавлением корректного расширения
ПолныйПуть = КаталогСохранения + "\" + ИмяФайлаБезЗапрещенныхСимволов + ПараметрыФормата.Расширение;
// Выполняем сохранение с явным указанием пути и формата
Документ.SaveAs(ПолныйПуть, ПараметрыФормата.КодФормата);
Документ.Close(0); // wdDoNotSaveChanges
WordApp.Quit(0);
Исключение
WordApp.Quit(0);
ВызватьИсключение "Ошибка при сохранении документа Word: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
При реализации выгрузки документов важно учитывать ограничения COM-технологии:
Word.Application функционирует только в среде Windows при установленном Microsoft Office.WINWORD.EXE в сеансах сервера 1С или регламентных заданиях не рекомендуется разработчиками Microsoft из-за риска зависания фоновых процессов.В качестве альтернативы на платформах 1С 8.3 можно использовать штатный объект ТабличныйДокумент и его метод Записать с параметром ТипФайлаТабличногоДокумента.DOCX. Это позволяет формировать документы формата .docx на стороне сервера под любой операционной системой без использования COM-соединений.