Word互操作:get_AttachedTemplate()返回错误的路径

时间:2019-02-18 16:26:00

标签: c# ms-word office-interop

我正在编写一个C#应用程序,该应用程序将遍历Word文档列表并使用Interop更改其附加模板。想法是,如果一堆Word文档指向服务器上不存在的模板,我们可以使用字符串替换将模板的路径更改为正确的路径。

请注意,每个文档可能具有几个不同的模板之一,因此我不能仅将所有模板都更改为特定路径-我必须使用字符串替换。

我的问题是我的Interop.Word.Document对象没有返回正确的附加模板。当我在MS Word中打开Word文档并转到模板窗口时,我看到附件模板是不再存在的网络文件模板。那就是我要改变的道路。但是,当我在C#中使用get_AttachedTemplate()时,我会得到另一个模板的路径...

有人可以帮助我吗?

注意:我正在使用Microsoft Word 16.0对象库。

using System;
using System.IO;
using System.Reflection;
using Microsoft.Office.Interop.Word;
using App = Microsoft.Office.Interop.Word.Application;
using Doc = Microsoft.Office.Interop.Word.Document;

namespace OfficeTemplateCleaner
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.Write(@"Enter a string to search (e.g. \\old\path\): ");
            var stringToFind = Console.ReadLine();
            Console.Write($"Enter a string to replace \"{stringToFind}\": ");
            var replaceWith = Console.ReadLine();

            var files = new[]
            {
                @"\\path\to\one\test\document.doc"
            };

            App oWord = new App() { Visible = false };
            foreach (var file in files)
            {
                if (!File.Exists(file))
                {
                    continue;
                }

                // cache file modification times so that we can revert them to what they were originally
                var fileInfo = new FileInfo(file);
                var modifyTime = fileInfo.LastWriteTime;

                //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
                Doc oWordDoc = new Doc();
                //MAKING THE APPLICATION VISIBLE
                oWord.Visible = true;
                //ADDING A NEW DOCUMENT TO THE APPLICATION
                oWordDoc = oWord.Documents.Open(file);

                var templ = (Template) oWordDoc.get_AttachedTemplate();
                var template = templ.FullName;
                if (template.IndexOf(stringToFind) == -1)
                {
                    continue;
                }

                var newTemplate = template.Replace(stringToFind, replaceWith);
                oWordDoc.set_AttachedTemplate(newTemplate);

                oWordDoc.SaveAs(file);
                oWordDoc.Close();

                fileInfo = new FileInfo(file);
                fileInfo.LastWriteTime = modifyTime;
            }
            oWord.Quit();

            Console.WriteLine("Done.");
            Console.ReadLine();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这是Word互操作的常见问题:如果模板位置不可用,则无法访问该值。 Word返回它实际上可以“到达”的模板,如果找不到附加的模板,则默认情况下通常为Normal.dotm。

更可靠的方法是通过Open XML SDK处理关闭的文件(速度也会更快)。这是一些代码,这些代码将访问当前信息并进行更改。当然,您需要添加将要为其设置文件的逻辑作为新的附加模板。

string filePath = @"C:\Test\DocCopyTest.docm"; 

using (WordprocessingDocument pkgDoc = WordprocessingDocument.Open(filePath, true))
{
    //Gets only the file name, not path; included for info purposes, only
    DocumentFormat.OpenXml.ExtendedProperties.Template t = pkgDoc.ExtendedFilePropertiesPart.Properties.Template;
    string tName = t.Text;
    this.txtMessages.Text = tName;

    //The attached template information is stored in the DocumentSettings part
    //as a link to an external resource. So the information is not directly in the XML
   //it's part of the "rels", meaning it has to be accessed indirectly
    MainDocumentPart partMainDoc = pkgDoc.MainDocumentPart;
    ExternalRelationship r = null;
    string exRel_Id = "";
    string exRelType = "";
   //the file location of the new template, as a URI
    Uri rUri = new Uri("file:////C:/Test/DocCopy_Test2.dotm");
    Array exRels = partMainDoc.DocumentSettingsPart.ExternalRelationships.ToArray();
    foreach (ExternalRelationship exRel in exRels)
        if (exRel.RelationshipType.Contains("attachedTemplate"))
        {
            exRel_Id = exRel.Id;
            exRelType = exRel.RelationshipType;
            System.Diagnostics.Debug.Print(exRel_Id + " " + exRelType);
            partMainDoc.DocumentSettingsPart.DeleteExternalRelationship(exRel);
            r = partMainDoc.DocumentSettingsPart.AddExternalRelationship(exRelType, rUri, exRel_Id);
            System.Diagnostics.Debug.Print(r.Uri.ToString());
            break;
        }
}