Word Interop: get_AttachedTemplate () возвращает неверный путь - PullRequest
0 голосов
/ 18 февраля 2019

Я пишу приложение на C #, которое просматривает список документов Word и изменяет их прикрепленный шаблон с помощью Interop.Идея состоит в том, что если множество документов Word указывают на шаблоны на несуществующем сервере, мы можем использовать замену строки, чтобы изменить пути шаблонов на правильные.

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

Моя проблема в том, что мой Interop.Word.Document объект не возвращает правильныйприкрепленный шаблон.Когда я открываю документ Word в MS Word и захожу в окно шаблонов, я вижу, что прикрепленный шаблон является шаблоном сетевого файла, который больше не существует.Это путь, который я хочу изменить.Но когда я использую get_AttachedTemplate() в C #, я получаю путь к другому шаблону ...

Кто-нибудь может мне помочь?

Примечание: я использую Microsoft Word 16.0 Object Library.

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 голосов
/ 19 февраля 2019

Это распространенная проблема взаимодействия 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;
        }
}
...