Word Interop .InsertFile приводит к потере стилей - PullRequest
0 голосов
/ 04 мая 2018

У меня есть код C #, который объединяет один файл в другой. Это довольно простой процесс:

//open the files
Microsoft.Office.Interop.Word.Document file1 = winWord.Documents.Open(ref
    file1address, ReadOnly: true, Visible: false);

Microsoft.Office.Interop.Word.Document insertfile = 
     winWord.Documents.Open(ref insertfileaddress, ReadOnly: true, 
     Visible: false);

//activate file1
file1.Activate();

// insert a page break
 file1.Words.Last.
    InsertBreak(Microsoft.Office.Interop.Word.
    WdBreakType.wdPageBreak);

//move to end and insert insertfile 
Microsoft.Office.Interop.Word.Selection selection = winWord.Selection;
selection = winWord.Selection;

selection.
    EndOf(Microsoft.Office.Interop.Word.WdUnits.wdStory, 
    Microsoft.Office.Interop.Word.WdMovementType.wdMove);

selection.InsertFile(insertfileaddress.ToString(), missing, 
     missing, missing, missing);

// save under a new name
file1.SaveAs2(NewFileName);

В моем проекте я использую этот код дважды. В первый раз, когда я генерирую файл длиной около 300 страниц, он отлично работает.

Второй раз намного больше - размер получаемого файла превышает 15 000 страниц - и в этом случае возникает проблема. Стилизация абзаца потеряна - все абзацы отображаются как нормальные. (Что меня волнует, так это заголовки абзацев, сохраняющие обозначения «Заголовок 1», «Заголовок 2» или «Заголовок 3».

В обоих случаях file1 одинаков, а файл вставки генерируется в другом месте с использованием взаимодействия слов - и код, который генерирует этот файл, совпадает с кодом в уменьшенной и увеличенной версиях. Характеристики файла и характеристики содержимого одинаковы, но в большей версии я теряю стили «Заголовок».

Единственное решение, которое я могу придумать, - это просмотреть новый файл и снова применить стили.

Если у кого-то есть идея, почему это происходит, и как это исправить, пожалуйста, помогите.

1 Ответ

0 голосов
/ 08 мая 2018

Как вы увидите в комментариях выше, я попробовал несколько вещей. Рабочим решением было перебрать все абзацы и заменить стили на основе подстановочного совпадения. Для этого нужно было убедиться, что документ остался активным (я сделал это, добавив строку активации в цикл). Но это заняло более 6 часов, что было неоправданно.

Исходя из комментария от C. Meister выше, я попробовал OpenXML, и это было здорово. Единственная проблема заключалась в том, что OpenXML не запускает функции слов, такие как «обновление оглавления». Таким образом, я закончил с 2 методами. Один, чтобы добавить один файл в другой и сохранить полученный файл (с неповрежденными стилями!) - используя OpenXML. А вторая открывает документ в режиме Word Interop, обновляет оглавление и устанавливает некоторые параметры так, как я хочу, и сохраняет файл.

Вот мой код:

{
string targetFile = "c:\\users\\me\\desktop\\targetFile.docx";
string appendThisFile = "c:\\users\\me\\desktop\\appendThisFile.docx";
string newFile = "c:\\users\\me\\desktop\\newFile.docx";

object newFileObj = newfile;  // will need this later to save file

AppendFileToEnd(targetFile, appendThisFile, newFile);

UpdateTOCplusSettings(newFile, ref winWord);
}

// This method appends  puts a page break at the end of "targetFile" and 
then appends "appendThisFile."
// This method requires adding the WordOpenXML SDK - add using nuget
internal void AppendFileToEnd(string targetFile, string appendThisFile, 
string newFile)
    {
        File.Delete(newFile);
        File.Copy(targetFile, newFile);

        using (WordprocessingDocument myDoc =
            WordprocessingDocument.Open(newFile, true))
        {
            string altChunkId = "AltChunkId1";

            MainDocumentPart mainPart = myDoc.MainDocumentPart;

            DocumentFormat.OpenXml.Wordprocessing.Paragraph para = new 
              DocumentFormat.OpenXml.Wordprocessing.Paragraph(new 
              DocumentFormat
                .OpenXml.Wordprocessing
                .Run((new DocumentFormat.OpenXml.Wordprocessing.Break() { 
                  Type = BreakValues.Page })));

            mainPart.Document.Body.InsertAfter(para, 
               mainPart.Document.Body.LastChild);

            AlternativeFormatImportPart chunk =
                mainPart.AddAlternativeFormatImportPart(
                AlternativeFormatImportPartType.WordprocessingML, 
                altChunkId);

            using (FileStream fileStream = File.Open(appendThisFile, 
                 FileMode.Open))
                 chunk.FeedData(fileStream);

            AltChunk altChunk = new AltChunk();
            altChunk.Id = altChunkId;
            mainPart.Document
                .Body
                .InsertAfter(altChunk, mainPart.Document.Body
                .Elements<DocumentFormat.OpenXml.Wordprocessing
                   .Paragraph>().Last());
           mainPart.Document.Save();
        }
    }

 // This method opens a document and updates the first Table of Contents.
 // Note that my project already has a Word Interop object, so I pass it in 
       // and use it.  If you don't have an Word object then you need to 
       // create one before opening the doc file)
 // I also turn off grammar and spelling error - which is a choice of mine      
 internal void UpdateTOCplusSettings(string filename, ref 
     Microsoft.Office.Interop.Word.Application winword)
 {
        Microsoft.Office.Interop.Word.Document wordDocument = 
            winword.Documents.Open(filename);
        wordDocument.ShowGrammaticalErrors = false;
        wordDocument.ShowSpellingErrors = false;
        wordDocument.TablesOfContents[1].Update();
        wordDocument.Save();
  }

Вместо 6 часов (плюс) этот процесс занимает чуть более 6 минут. Добавление метода занимает менее секунды, а обновление TOC занимает 6 минут. Сохранение занимает около секунды.

...