Как устранить зависание процесса MS Word при проверке орфографии в 1С и какие есть альтернативные способы?

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

При интеграции 1С с офисными приложениями через COM-соединение программисты часто сталкиваются с ситуацией, когда после выполнения кода в диспетчере задач остаются "висеть" процессы winword.exe. Это не только потребляет ресурсы сервера или клиентской станции, но и может привести к блокировкам файлов и непредсказуемому поведению системы. Рассмотрим подробнее, почему это происходит, как оптимизировать работу с Word и какие современные альтернативы существуют для реализации проверки орфографии в управляемых формах.

Причина зависания процесса Word: счетчик ссылок

Разберем ситуацию, которая возникает при использовании COM-объектов в 1С. Основная причина, по которой процесс winword.exe не завершается после вызова метода Quit(), заключается в механизме подсчета ссылок. Когда мы создаем основной объект Word.Application, а затем обращаемся к его дочерним объектам, таким как Documents, Range, Words или Selection, 1С создает внутренние ссылки на эти объекты.

Проанализируем пример: если вы вызвали ОбъектMSWord.Quit(), но при этом переменная, содержащая ссылку на документ (Док) или коллекцию вариантов (Варианты), все еще активна в памяти 1С, операционная система не позволит процессу завершиться. Процесс будет ждать, пока абсолютно все связанные объекты будут освобождены.

Важное правило: для корректного закрытия Word необходимо обнулять все переменные, которые ссылаются на любые подобъекты Word, в обратном порядке их создания, и только после этого вызывать завершение приложения.

Оптимизация работы с COM-объектом 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);
    // Обнуляем ссылки на подобъекты!
    Ошибки = Неопределено;
    Документ = Неопределено;
    
    Возврат Текст;
КонецФункции

Современная альтернатива №1: Веб-сервисы (Yandex.Speller API)

Как справедливо заметили участники обсуждения, использование Word для проверки орфографии — это тяжеловесный и морально устаревший метод. Для управляемых форм гораздо эффективнее использовать внешние API, такие как Yandex.Speller. Это позволяет выполнять проверку даже на сервере (где Word ставить нельзя) и не зависеть от установленного ПО на клиенте.

Рассмотрим шаги реализации проверки через HTTP-запрос:

  1. Формируем текст для проверки.
  2. Отправляем GET или POST запрос к сервису Яндекса.
  3. Получаем JSON с массивом ошибок и вариантами замен.
  4. Обрабатываем результат в 1С.

Посмотрим на пример реализации:


&НаСервере
Функция ПроверитьОрфографиюЧерез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]);
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    Исключение
        ЗаписьЖурналаРегистрации("Орфография", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
    КонецПопытки;
    
    Возврат ТекстДляПроверки;
КонецФункции

Альтернатива №2: Встроенный Spell Checking API Windows

Если ваша компания придерживается политики безопасности, запрещающей отправку данных во внешние сервисы, можно воспользоваться встроенным в Windows (начиная с Windows 8/10) механизмом проверки орфографии. Он работает значительно быстрее Word и не требует запуска тяжелых процессов. Доступ к нему можно получить через специализированные внешние компоненты или обертки .NET, вызываемые из 1С.

Выводы и рекомендации

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

Помните, что корректная обработка исключений при работе с COM-объектами — это залог стабильности всей системы. Всегда оборачивайте блоки взаимодействия с Word в конструкцию Попытка ... Исключение.

← На главную