我正在编写一个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();
}
}
}
答案 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;
}
}