【问题标题】:Having trouble saving an existing word document保存现有 Word 文档时遇到问题
【发布时间】:2015-02-26 07:53:21
【问题描述】:

在我用 C# 自动生成 word 文档后,我试图将现有的 docx 文件保存在桌面上。我正在使用窗口窗体来执行我的应用程序。当桌面上没有相同的文件名时,我可以保存文档。但是,当我再次尝试保存相同的文件名时,它会给我这个错误消息:

当文件正被另一个进程使用时,您无法保存。尝试 用新名称保存文件。 (C:...\Desktop\TempWord.docx)

我在Microsoft website 中读到它,如果存在现有文件名,我可以使用 SaveAs,它会自动覆盖它。

我不太清楚为什么会出现这种消息,因为在运行该程序时我根本没有打开任何其他 Word 文档。

我不太确定如何解决这个问题。也许我做了一些我没有看到的非常愚蠢的事情:(


这是我的代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection; 
using Microsoft.Office;
using Word = Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;


namespace TestWordAutoWithTemplate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void butGenerate_Click(object sender, EventArgs e)
        {


            //OBJECT OF MISSING "NULL VALUE"
            Object oMissing = Missing.Value;

            //OBJECTS OF FALSE AND TRUE
            Object oTrue = true;
            Object oFalse = false;

            //CREATING OBJECTS OF WORD AND DOCUMENT
            Word.Application oWord = new Word.Application();
            Word.Document oWordDoc = new Word.Document();

            //SETTING THE VISIBILITY TO TRUE
            //oWord.Visible = true;

            //THE LOCATION OF THE TEMPLATE FILE ON THE MACHINE
            Object oTemplatePath = @"C:\Documents and Settings\YYC\Desktop\TestTemplate.dotx";

            //ADDING A NEW DOCUMENT FROM A TEMPLATE
            oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
            int iTotalFields = 0; 

            foreach (Word.Field myMergeField in oWordDoc.Fields)
            {
                iTotalFields++;
                Word.Range rngFieldCode = myMergeField.Code;
                String fieldText = rngFieldCode.Text;

                // ONLY GETTING THE MAILMERGE FIELDS
                if (fieldText.StartsWith(" MERGEFIELD"))
                {
                    // THE TEXT COMES IN THE FORMAT OF
                    // MERGEFIELD  MyFieldName  \\* MERGEFORMAT
                    // THIS HAS TO BE EDITED TO GET ONLY THE FIELDNAME "MyFieldName"
                    Int32 endMerge = fieldText.IndexOf("\\");
                    Int32 fieldNameLength = fieldText.Length - endMerge;
                    String fieldName = fieldText.Substring(11, endMerge - 11);

                    // GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dot FILE
                    fieldName = fieldName.Trim();

                    // **** FIELD REPLACEMENT IMPLEMENTATION GOES HERE ****//
                    // THE PROGRAMMER CAN HAVE HIS OWN IMPLEMENTATIONS HERE
                    if (fieldName == "Name")
                    {
                        myMergeField.Select();
                        //Check whether the control text is empty
                        if (txtName.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtName.Text); 
                        }
                    }
                    if (fieldName == "Address")
                    {
                        myMergeField.Select();
                        //Check whether the control text is empty
                        if (txtAddress.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtAddress.Text);
                        }
                    }

                    if (fieldName == "Age")
                    {
                        myMergeField.Select();
                        // check whether the control text is empty
                        if (txtAge.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtAge.Text); 
                        }
                    }

                    if (fieldName == "EAddress")
                    {
                        myMergeField.Select();
                        // check whether the control text is empty
                        if (txtEmail.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtEmail.Text);
                        }
                    }

                    if (fieldName == "Company")
                    {
                        myMergeField.Select();
                        // Check whether the control text is empty
                        if (txtCompany.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtCompany.Text);
                        }
                    }

                    if (fieldName == "TelNo")
                    {
                        myMergeField.Select();
                        // Check whether the control text is empty
                        if (txtTelephone.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtCompany.Text);
                        }
                    }

                    if (fieldName == "ODetails")
                    {
                        myMergeField.Select();
                        // Check whether the control text is empty
                        if (txtOther.Text == "")
                        {
                            oWord.Selection.TypeText(" ");
                        }
                        else
                        {
                            oWord.Selection.TypeText(txtOther.Text);
                        }
                    }

                }
            }

            oWord.Visible = false;

            //Marshal.ReleaseComObject(oWordDoc.Fields);
            //Marshal.ReleaseComObject(oWordDoc);
            //Marshal.;


            // If you want your document to be saved as docx
            Object savePath = @"C:\Documents and Settings\YYC\Desktop\TempWord.doc";
            //oWordDoc.Save();
            oWordDoc.SaveAs(ref savePath
                //, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing, 
                //ref oMissing
               );



            // Close the Word document, but leave the Word application open.
            // doc has to be cast to type _Document so that it will find the 
            // correct Close method. 
            object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
            ((Word._Document)oWordDoc).Close(ref doNotSaveChanges, ref oMissing, ref oMissing);
            oWordDoc = null; 
            // word has to be case to type _Application so that it will find 
            // the correct Quit method. 
            ((Word._Application)oWord).Quit(ref doNotSaveChanges, ref oMissing, ref oMissing);
            oWord = null;
            GC.Collect();


        }
    }
}

我不太确定我在哪里做错了。

编辑:我把原始代码放进去。

【问题讨论】:

  • 你试过只保存吗?
  • @500-InternalServerError 是的,但我需要将其保存为文件名。
  • 错误消息是什么意思.. 同样,当您通过 Microsoft.Office.Interop 处理 ComObjects 时,您需要使用 Marshal.ReleaseComObject(oWord) 处理它们,例如
  • @DJKRAZE 这是错误消息:当文件被另一个进程使用时,您无法保存。尝试使用新名称保存文件。 (C:\...\Desktop\TempWord.docx)
  • 这不是特定于 word 的,而且每次您在磁盘上写入任何文件时都非常普遍:“当文件正在被另一个进程使用时,您无法保存”。这仅仅意味着在必须将其“保存为”(即)复制它之前,以某种方式创建了一个处理程序来“处理”现有文件。这可能是因为您的“另存为”进程正在尝试以写入模式访问文件,即使它只是为了复制它。我想您需要确保您的文件在尝试将其“另存为”之前已从任何资源中释放出来。

标签: c# winforms ms-word office-automation


【解决方案1】:

我为此做了一个方法,所以将这行代码放在按钮生成中去掉它并复制下面的新方法,这样你的新代码应该如下所示

private void butGenerate_Click(object sender, EventArgs e)
{
   SaveWordTemp2WordDoc();      
}

public void SaveWordTemp2WordDoc()
{
    //OBJECT OF MISSING "NULL VALUE"
    object oMissing = System.Reflection.Missing.Value;
    //OBJECTS OF FALSE AND TRUE
    Object oTrue = true;
    Object oFalse = false;

    //CREATING OBJECTS OF WORD AND DOCUMENT
    Word.Application oWord = new Word.Application();
    Word.Document oWordDoc = new Word.Document();

    //SETTING THE VISIBILITY TO TRUE
    //oWord.Visible = true;

    //THE LOCATION OF THE TEMPLATE FILE ON THE MACHINE
    //Change the path to a path like c:\files\docTemps\
    Object oTemplatePath = @"C:\Documents and Settings\YYC\Desktop\TestTemplate.dotx";

    //ADDING A NEW DOCUMENT FROM A TEMPLATE
    oWordDoc = oWord.Documents.Add(ref oTemplatePath, ref oMissing, ref oMissing, ref oMissing);
    int iTotalFields = 0;

    foreach (Word.Field myMergeField in oWordDoc.Fields)
    {
        iTotalFields++;
        Word.Range rngFieldCode = myMergeField.Code;
        String fieldText = rngFieldCode.Text;

        // ONLY GETTING THE MAILMERGE FIELDS
        if (fieldText.StartsWith(" MERGEFIELD"))
        {
            // THE TEXT COMES IN THE FORMAT OF
            // MERGEFIELD  MyFieldName  \\* MERGEFORMAT
            // THIS HAS TO BE EDITED TO GET ONLY THE FIELDNAME "MyFieldName"
            Int32 endMerge = fieldText.IndexOf("\\");
            Int32 fieldNameLength = fieldText.Length - endMerge;
            String fieldName = fieldText.Substring(11, endMerge - 11);

            // GIVES THE FIELDNAMES AS THE USER HAD ENTERED IN .dot FILE
            fieldName = fieldName.Trim();

            // **** FIELD REPLACEMENT IMPLEMENTATION GOES HERE ****//
            // THE PROGRAMMER CAN HAVE HIS OWN IMPLEMENTATIONS HERE
            if (fieldName == "Name")
            {
                myMergeField.Select();
                //Check whether the control text is empty
                if (txtName.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtName.Text);
                }
            }
            if (fieldName == "Address")
            {
                myMergeField.Select();
                //Check whether the control text is empty
                if (txtAddress.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtAddress.Text);
                }
            }

            if (fieldName == "Age")
            {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtAge.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtAge.Text);
                }
            }

            if (fieldName == "EAddress")
            {
                myMergeField.Select();
                // check whether the control text is empty
                if (txtEmail.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtEmail.Text);
                }
            }

            if (fieldName == "Company")
            {
                myMergeField.Select();
                // Check whether the control text is empty
                if (txtCompany.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtCompany.Text);
                }
            }

            if (fieldName == "TelNo")
            {
                myMergeField.Select();
                // Check whether the control text is empty
                if (txtTelephone.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtCompany.Text);
                }
            }

            if (fieldName == "ODetails")
            {
                myMergeField.Select();
                // Check whether the control text is empty
                if (txtOther.Text == "")
                {
                    oWord.Selection.TypeText(" ");
                }
                else
                {
                    oWord.Selection.TypeText(txtOther.Text);
                }
            }

        }
    }

    oWord.Visible = false;

    // If you want your document to be saved as docx
    //Change the file Path here to a path other than your desktop
    Object savePath = @"C:\Documents and Settings\YYC\Desktop\TempWord.doc";
    //oWordDoc.Save();
    oWordDoc.SaveAs(ref savePath,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing,
        ref oMissing
       );

    // Close the Word document, but leave the Word application open.
    // doc has to be cast to type _Document so that it will find the 
    // correct Close method. 
    object doNotSaveChanges = Word.WdSaveOptions.wdDoNotSaveChanges;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oWordDoc);
    // word has to be case to type _Application so that it will find 
    // the correct Quit method. 
    ((Word._Application)oWord).Quit(ref doNotSaveChanges, ref oMissing, ref oMissing);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oWord);
}

【讨论】:

  • 如果代码没有从您的 ForEach 中中断,您可能希望将 foreach 重构为一个 for 循环,并在 count
  • Oups 我忘了取消注释我放入 .SaveAs 代码中的 cmets。我正在测试看看错误是否出现在 .SaveAs
  • 并非如此。我正在尝试以另一种方式进行操作,而根本不访问模板。不使用模板的代码非常难看。 :( 我可能会回到代码并尝试修复错误。
  • 我在没有模板的情况下使用了相同的代码,与您在我的更改中获得的确切代码一样,它工作正常......所以我不确定你哪里出错了......
  • 只要我不将其保存为 docx 格式,您的代码就可以正常工作。
猜你喜欢
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-04
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多