Странное исключение при попытке автоматизировать MS Word с vb.net - PullRequest
0 голосов
/ 03 мая 2011

Я использую следующую функцию vb.net для чистого сохранения документов Word (никакого ввода текста вообще, на данный момент меня интересует только массовое создание пустых документов Word):

Sub createDoc(ByVal cname As String, ByVal acctype As String)
    counter += 1
    wordDoc = wordApp.Documents.Add
    wordDoc.SaveAs(OFDD.SelectedPath & "\" & cname & "_" & acctype & ".docx")
    wordDoc.Close()
End Sub

Переменная OFDD - это имя компонента vb обозревателя папок, а его свойство SelectedPath в сочетании с параметрами cname и acctype предоставляют мне имя документа Word, который я хочу создать и сохранить. Вот объявления переменных counter, wordDoc и wordApp:

 Private Shared counter As Integer = 0
 Private wordApp As New Word.Application
 Private wordDoc As Word.Document

Переменная wordDoc назначается объекту Document путем использования второй строки кода в подпрограмме createDoc. Однако, похоже, что в 83-й раз, когда я пытаюсь извлечь объект документа и назначить его wordDoc, я получаю исключение, в котором говорится, что «Команда завершилась неудачно». Я могу сказать, что это 83-й раз, когда я вхожу в функцию, потому что в своем контрольном блоке я печатаю значение счетчика в окне сообщения сразу после печати сведений о полученном исключении и прямо перед тем, как освободить использованные ресурсы и завершить процесс.

Обеспокоенный тем, есть ли в моей системе ограничения, связанные с автоматизацией MS Word, я создал другой проект Visual Studio (на этот раз проект Console), сослался на пространство имен Microsoft.Interop.Office.Word и написал следующий простой модуль:

Imports Word = Microsoft.Office.Interop.Word
Module Module1

Sub Main()
    Dim wordApp As New Word.Application
    Try
        For i As Integer = 0 To 150
            Dim document As Word.Document = wordApp.Documents.Add()
            document.SaveAs("C:\WordTester\" & i & ".docx")
            document.Close()
        Next
    Catch
        wordApp.Quit()
    End Try
    Console.WriteLine("Document objects left in memory: " & _ 
                       wordApp.Documents.Count) ' zero
    Console.Read()
    wordApp.Quit()
End Sub

End Module

Который работает отлично. Проверяя мою файловую систему, я вижу файлы из 150 слов, созданные в «C: \ WordTester». Учитывая все мои усилия, я действительно сбит с толку тем, почему первый написанный мной код застрял на 83-й попытке создать и сохранить документ, и любая помощь будет чрезвычайно признательна.

Спасибо за ваше время,

Jason

Редактировать: вот отредактированная версия createDoc, на которую я ссылаюсь в комментарии ниже:

Sub createDoc(ByVal cname As String, ByVal acctype As String)
    counter += 1
    wordApp = New Word.Application
    wordDoc = New Word.Document
    wordDoc = wordApp.Documents.Add
    wordDoc.SaveAs(OFDD.SelectedPath & "\" & cname & "_" & acctype & ".docx")
    wordDoc.Close()
    wordApp.Quit()
End Sub

Ответы [ 4 ]

2 голосов
/ 03 мая 2011

Попробуйте что-нибудь подобное. Очевидно, мне пришлось вставить немного предполагаемого кода, но это почти то, что вы должны делать:

Imports Word = Microsoft.Office.Interop.Word

Public Class Class1

Private pWordApp As Word.Application
Private pintCounter As Integer = 0

Public Sub CreateWordDocuments()

    '--instanciate word:
    pWordApp = New Word.Application

    Dim dt As DataTable = GetYourDataEtc    'replace with however you get the data you loop around
    Dim OFDD As Object = GetYourFolderPathEtc   'replace Object and folder path call and 

    Try

        For Each dr In dt.Rows
            Dim cName As String = dr("cname")  'for example
            Dim acctype As String = dr("acctype") #for example

            CreateDoc(OFDD, cName, acctype)
        Next

    Catch ex As Exception
        '--some error code
    Finally
        pWordApp.Quit()
        System.Runtime.InteropServices.Marshal.ReleaseComObject(pWordApp)
    End Try

End Sub

Private Sub CreateDoc(ByVal OFDD As Object, ByVal cname As String, ByVal accType As String)

    Dim document As Word.Document = pWordApp.Documents.Add()
    document.SaveAs(OFDD.SelectedPath & "\" & cname & "_" & accType & ".docx")
    document.Close()

End Sub


End Class
0 голосов
/ 04 мая 2011

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

Спасибо за ваше время и интерес.

0 голосов
/ 04 мая 2011

Вместо создания нового экземпляра Word каждый раз, когда вы создаете документ, я бы предпочел создать ОДИН экземпляр перед циклом для создания отдельного документа и использовать этот объект приложения во время цикла - это подход, предложенный Дунк.1001 *

ПРИМЕЧАНИЕ. После цикла вы освобождаете COM-объект с помощью Marshal.ReleaseCOMObject.Я бы назвал эту функцию также в подпрограмме CreateDoc для объекта doc.Пожалуйста, посмотрите на это обсуждение о выпуске COM-объектов в автоматизации Office.

0 голосов
/ 03 мая 2011

Похоже на проблему сбора мусора - CLR удерживает много ссылок на объект слова и является словом, исчерпывающим некоторый ресурс, прежде чем начнется сбор мусора. Вторая функция работает, потому что все ограничено локально.Вы можете изменить код, чтобы охватить вещи локально;Также поможет вызов dispose для объекта worddoc.

Похоже, что dispose не существует.Правильный способ - вызвать метод ReleaseComObject

http://msdn.microsoft.com/en-us/library/aa159887(office.11).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...