6

テンプレートを使用してドキュメントを作成し、データベースに保存するために Word Automation を使用している WinForms アプリケーションがあります。ドキュメントが作成されたら、データベースからドキュメントを取得し、それをファイル システムの一時ディレクトリに書き込み、Word Interop サービスを使用してドキュメントを開きます。

読み込まれたドキュメントのリストがあり、ユーザーは各ドキュメントの 1 つのインスタンスしか開くことができませんが、複数の異なるドキュメントを同時に開くことができます。1 つのドキュメントを開くときは、開いたり、保存したり、閉じたりするのに問題はありませんが、複数のドキュメントを同時に開くと、Word のインスタンスを閉じるときに次のエラーが表示されます。

The file is in use by another application or user. (C:\...\Templates\Normal.dotm) 
This error is commonly encountered when a read lock is set on the file that you are attempting to open.

次のコードを使用してドキュメントを開き、BeforeDocumentClosed イベントを処理しています。

public void OpenDocument(string filePath, Protocol protocol, string docTitle, byte[] document)
{
    _protocol = protocol;
    documentTitle = docTitle;
    _path = filePath;

    if (!_wordDocuments.ContainsKey(_path))
    {
        FileUtility.WriteToFileSystem(filePath, document);

        Word.Application wordApplication = new Word.Application();
        wordApplication.DocumentBeforeClose += WordApplicationDocumentBeforeClose;

        wordApplication.Documents.Open(_path);

        _wordDocuments.Add(_path, wordApplication);
    }
    _wordApplication = _wordDocuments[_path];
    _currentWordDocument = _wordApplication.ActiveDocument;

    ShowWordApplication();
}

public void ShowWordApplication()
{
    if (_wordApplication != null)
    {
        _wordApplication.Visible = true;
        _wordApplication.Activate();
        _wordApplication.ActiveWindow.SetFocus();
    }
}

private void WordApplicationDocumentBeforeClose(Document doc, ref bool cancel)
{
    if (!_currentWordDocument.Saved)
    {
        DialogResult dr = MessageHandler.ShowConfirmationYnc(String.Format(Strings.DocumentNotSavedMsg, _documentTitle), Strings.DocumentNotSavedCaption);

        switch (dr)
        {
            case DialogResult.Yes:
                SaveDocument(_path);
                break;
            case DialogResult.Cancel:
                cancel = true;
                return;
        }
    }

    try
    {
        if (_currentWordDocument != null)
            _currentWordDocument.Close();
    }
    finally
    {
        Cleanup();
    }
}

public void Cleanup()
{
    if (_currentWordDocument != null)
        while(Marshal.ReleaseComObject(_currentWordDocument) > 0);

    if (_wordApplication != null)
    {
        _wordApplication.Quit();
        while (Marshal.ReleaseComObject(_wordApplication) > 0);
        _wordDocuments.Remove(_path);
    }
}

複数のドキュメントを同時に開くことを許可するために私が行っていることを誰かが間違っていると思いますか? 私は Word Automation と Word Interop サービスにまったく慣れていないので、アドバイスをいただければ幸いです。ありがとう。

4

4 に答える 4

9

この MSDN 記事で解決策を見つけました: http://support.microsoft.com/kb/285885

Application.Quit(); を呼び出す前にこれを行う必要があります。

_wordApplication.NormalTemplate.Saved = true;

これにより、Word は Normal.dotm テンプレートを保存しようとしなくなります。これが他の誰かに役立つことを願っています。

于 2010-12-06T14:41:50.193 に答える
2

C# doc2pdf アプリケーションで Word を使用しました。ドキュメントを閉じる前に、保存オプションを次のように設定します。

object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
oDoc.Close(ref saveOption, ref oMissing, ref oMissing);
oWord.Quit(ref saveOption, ref oMissing, ref oMissing);
于 2012-06-29T02:16:38.030 に答える
1

アプリケーションにヘルプ リンクがあり、特定の単語ドキュメントを特定のブックマークで開きたいと考えていました。ドキュメントが既に開いている場合は、再度開くべきではありません。Word が既に開いている場合、Word の新しいインスタンスを開く必要はありません。

このコードは私のために働いた:

object filename = @"C:\Documents and Settings\blah\My Documents\chapters.docx";
object confirmConversions = false;
object readOnly = true;
object visible = true;
object missing = Type.Missing;
Application wordApp;

object word;
try
{
    word = System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
}
catch (COMException)
{
    Type type = Type.GetTypeFromProgID("Word.Application");
    word = System.Activator.CreateInstance(type);
}

wordApp = (Application) word;
wordApp.Visible = true;
Console.WriteLine("There are {0} documents open.", wordApp.Documents.Count);
var wordDoc = wordApp.Documents.Open(ref filename, ref confirmConversions, ref readOnly, ref missing,
                                        ref missing, ref missing, ref missing, ref missing,
                                        ref missing, ref missing, ref missing, ref visible,
                                        ref missing, ref missing, ref missing, ref missing);
wordApp.Activate(); 
object bookmarkName = "Chapter2";
if (wordDoc.Bookmarks.Exists(bookmarkName.ToString()))
{
    var bookmark = wordDoc.Bookmarks.get_Item(bookmarkName);
    bookmark.Select();
}
于 2013-08-16T05:11:57.183 に答える
0

コードは次のことに注意してください。

Word.Application wordApplication = new Word.Application();

インスタンスが既に読み込まれている場合でも、Word の新しいインスタンスが常に起動されます。

通常、(GETOBJECT を介して) ロードされたインスタンスをチェックし、存在する場合はそれを使用し、必要な場合にのみ新しいインスタンスをスピンアップすることをお勧めします。

于 2010-12-06T20:52:47.717 に答える