При интеграции 1С с офисными приложениями через COM-соединение программисты часто сталкиваются с ситуацией, когда после выполнения кода в диспетчере задач остаются "висеть" процессы winword.exe. Это не только потребляет ресурсы сервера или клиентской станции, но и может привести к блокировкам файлов и непредсказуемому поведению системы. Рассмотрим подробнее, почему это происходит, как оптимизировать работу с Word и какие современные альтернативы существуют для реализации проверки орфографии в управляемых формах.
Разберем ситуацию, которая возникает при использовании COM-объектов в 1С. Основная причина, по которой процесс winword.exe не завершается после вызова метода Quit(), заключается в механизме подсчета ссылок. Когда мы создаем основной объект Word.Application, а затем обращаемся к его дочерним объектам, таким как Documents, Range, Words или Selection, 1С создает внутренние ссылки на эти объекты.
Проанализируем пример: если вы вызвали ОбъектMSWord.Quit(), но при этом переменная, содержащая ссылку на документ (Док) или коллекцию вариантов (Варианты), все еще активна в памяти 1С, операционная система не позволит процессу завершиться. Процесс будет ждать, пока абсолютно все связанные объекты будут освобождены.
Важное правило: для корректного закрытия Word необходимо обнулять все переменные, которые ссылаются на любые подобъекты Word, в обратном порядке их создания, и только после этого вызывать завершение приложения.
Если специфика задачи требует использования именно Microsoft Word, нам необходимо пересмотреть архитектуру взаимодействия. Ошибка автора темы заключалась в создании и уничтожении объекта Word внутри цикла или при каждом вызове функции. Это крайне ресурсоемкая операция. Рассмотрим, как сделать это правильно на управляемых формах.
Выясним оптимальный алгоритм:
1. Создаем переменную на клиенте в модуле формы.
2. Инициализируем COMОбъект только один раз при начале работы (например, при первом нажатии кнопки проверки).
3. Используем этот объект многократно для всех строк табличной части.
4. Уничтожаем объект только при закрытии формы или окончании масштабного процесса обработки.
Разберем пример кода для управления жизненным циклом объекта:
&НаКлиенте
Перем ОбъектMSWord; // Переменная в начале модуля формы
&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
// Обязательно очищаем память при закрытии формы
Если ОбъектMSWord <> Неопределено Тогда
Попытка
ОбъектMSWord.Quit(0); // wdDoNotSaveChanges = 0
Исключение
КонецПопытки;
ОбъектMSWord = Неопределено;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Функция ПолучитьОбъектWord()
Если ОбъектMSWord = Неопределено Тогда
Попытка
ОбъектMSWord = Новый COMОбъект("Word.Application");
ОбъектMSWord.Visible = Ложь;
ОбъектMSWord.DisplayAlerts = 0; // Отключаем все уведомления Word
Исключение
Сообщить("Не удалось запустить Microsoft Word для проверки орфографии.");
Возврат Неопределено;
КонецПопытки;
КонецЕсли;
Возврат ОбъектMSWord;
КонецФункции
Проанализируем текущий подход автора: перебор коллекции Words в цикле 1С — это "узкое горлышко". Каждое обращение к Слово.Text через COM-границу занимает значительное время. Чтобы ускорить процесс, мы можем использовать встроенную коллекцию ошибок Word. Посмотрим на пример оптимизированного кода проверки:
&НаКлиенте
Функция ПроверитьТекстЭффективно(Текст)
WordApp = ПолучитьОбъектWord();
Если WordApp = Неопределено Тогда Возврат Текст; КонецЕсли;
// Создаем временный документ один раз
Документ = WordApp.Documents.Add();
Попытка
Область = Документ.Range(0, 0);
Область.InsertBefore(Текст);
// Вместо перебора всех слов используем коллекцию ошибок
Ошибки = Документ.SpellingErrors;
Для Каждого Ошибка Из Ошибки Цикл
// Обрабатываем только слова с ошибками
СловоСМинусом = Ошибка.Text;
Варианты = Ошибка.GetSpellingSuggestions();
Если Варианты.Count > 0 Тогда
// Выбираем первый вариант замены
Текст = СтрЗаменить(Текст, СловоСМинусом, Варианты.Item(1).Name);
КонецЕсли;
КонецЦикла;
Исключение
Сообщить("Ошибка при проверке: " + ОписаниеОшибки());
КонецПопытки;
// Закрываем документ, но НЕ приложение
Документ.Close(0);
// Обнуляем ссылки на подобъекты!
Ошибки = Неопределено;
Документ = Неопределено;
Возврат Текст;
КонецФункции
Как справедливо заметили участники обсуждения, использование Word для проверки орфографии — это тяжеловесный и морально устаревший метод. Для управляемых форм гораздо эффективнее использовать внешние API, такие как Yandex.Speller. Это позволяет выполнять проверку даже на сервере (где Word ставить нельзя) и не зависеть от установленного ПО на клиенте.
Рассмотрим шаги реализации проверки через HTTP-запрос:
Посмотрим на пример реализации:
&НаСервере
Функция ПроверитьОрфографиюЧерезAPI(ТекстДляПроверки)
Соединение = Новый HTTPСоединение("speller.yandex.net", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL());
Запрос = Новый HTTPЗапрос("/services/spellservice.json/checkText?text=" + КодироватьСтроку(ТекстДляПроверки, СпособКодированияСтроки.КодировкаURL));
Попытка
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
МассивОшибок = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// МассивОшибок содержит структуры с полями "word" (ошибка) и "s" (варианты замены)
Для Каждого Ошибка Из МассивОшибок Цикл
Если Ошибка.s.Количество() > 0 Тогда
ТекстДляПроверки = СтрЗаменить(ТекстДляПроверки, Ошибка.word, Ошибка.s[0]);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("Орфография", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;
Возврат ТекстДляПроверки;
КонецФункции
Если ваша компания придерживается политики безопасности, запрещающей отправку данных во внешние сервисы, можно воспользоваться встроенным в Windows (начиная с Windows 8/10) механизмом проверки орфографии. Он работает значительно быстрее Word и не требует запуска тяжелых процессов. Доступ к нему можно получить через специализированные внешние компоненты или обертки .NET, вызываемые из 1С.
Подводя итог, проанализируем ситуацию: использование Word через COM оправдано только в том случае, если вам критически важно использовать именно пользовательские словари Word или специфические настройки Office. Во всех остальных случаях:
Hunspell (через внешние компоненты 1С).Documents и Range перед вызовом Quit().Помните, что корректная обработка исключений при работе с COM-объектами — это залог стабильности всей системы. Всегда оборачивайте блоки взаимодействия с Word в конструкцию Попытка ... Исключение.