Insert text before a list using Word Interop

纵然是瞬间 提交于 2019-12-11 04:18:45

问题


I'm trying to insert text before a list. I have the Microsoft.Office.Interop.Word.Range of the list, and get the previous Range before the list. I then try to add my paragraph text to the previous range, however, the paragraph is added as the first item in the list instead of before the list.

// rangeObj is the Range object for the list
var previousRange = rangeObj.Previous(MSWord.WdUnits.wdCharacter, 1);

Paragraph paragraph;
if (previousRange == null)
{
  var rangeCopy = rangeObj.Duplicate;
  rangeCopy.InsertParagraphBefore();
  paragraph = rangeCopy.Paragraphs[1];
}
else 
{
  paragraph = previousRange.Paragraphs[1];  
}

Range range = paragraph.Range;
range.Text = String.Format("{0} {1}", "My list", range.Text);

E.g. Before:

  1. Item 1
  2. Item 2

After (What I want):

My list

  1. Item 1
  2. Item 2

After (What I'm currently getting):

  1. My list
  2. Item 1
  3. Item 2

Edit: Per Lasse's answer and my comment, I'm getting everything to work except for the following edge case. Note: The 2nd list is not a sub list of the first one and there's no empty lines in-between each list.

if (previousRange.ListParagraphs.Count > 0)

Before:

  1. Item 1
  2. Item 2

    1. Item 3
    2. Item 4

After (what I want):

  1. Item 1
  2. Item 2

    Another list:

    1. Item 3
    2. Item 4

回答1:


In this code:

else 
{
  paragraph = previousRange.Paragraphs[1];  
}

.. you are risking overwriting anything before the list (including empty lines with only \r in it), and when I run it on a sample, it makes good sense that things gets overwritten and occur weird in the end.

In this code:

if (previousRange == null)
{
  var rangeCopy = rangeObj.Duplicate;
  rangeCopy.InsertParagraphBefore();
  paragraph = rangeCopy.Paragraphs[1];
}

.. you insert a new paragraph before the list (which is fine - even though, I cannot see why it would be necessary to clone the range, as the range automatically expands to include the newly inserted paragraph) and then stores the range of the new paragraph in your local variable paragraph. At this point, the content of paragraph = '\r' - (this is seen if you step through your application with a debugger while keeping word visible during the debugging phase). So, at this point the cursor is positioned just before the list, which is where you want it to be - but then you do the following:

Range range = paragraph.Range;
range.Text = "My paragraph";

... meaning that instead of pre-pending text to the paragraph, you simply overwrite everything including the \r, which causes Word to insert the text in the list instead of before it.

To bypass this, I have made an alternative implementation that seems to work. It is based on your idea of using the range before the list to insert text. I have added comments for most of the lines, so it should be straight forward to follow what is going on :)

using System;
using System.Linq;
using Microsoft.Office.Interop.Word;
using Application = Microsoft.Office.Interop.Word.Application;

namespace WordDocStats
{
    internal class Program
    {
        private static void Main()
        {
            var wordApplication = new Application() { Visible = true };

            // Open document A
            var documentA = wordApplication.Documents.Open(@"C:\Users\MyUser\Documents\documentA.docx", Visible: true);

            // This inserts text in front of each list found in the document
            const string myText = "My Text Before The List";
            foreach (List list in documentA.Lists)
            {
                // Range of the current list
                var listRange = list.Range;

                // Range of character before the list
                var prevRange = listRange.Previous(WdUnits.wdCharacter);

                // If null, the list might be located in the very beginning of the doc
                if (prevRange == null)
                {
                    // Insert new paragraph
                    listRange.InsertParagraphBefore();
                    // Insert the text
                    listRange.InsertBefore(myText);
                }
                else
                {
                    if (prevRange.Text.Any())
                    {
                        // Dont't append the list text to any lines that might already be just before the list
                        // Instead, make sure the text gets its own line
                        prevRange.InsertBefore("\r\n" + myText);
                    }
                    else
                    {
                        // Insert the list text
                        prevRange.InsertBefore(myText);
                    }
                }
            }

            // Save, quit, dones
            Console.WriteLine("Dones");
            Console.ReadLine();
            documentA.Save();
            wordApplication.Quit();
        }
    }
}

In short, the code inserts a string before each list in the given document. If there is already text on the line before the list, the implementation makes sure to insert the list description text before the list and after the text that was already on the line before the list.

Hope this helps :)

--- UPDATE to answer to edited question:

A way to accomplish what you are asking here in the second round is doing something like:

...
// The paragraph before the current list is also a list -> so in order to insert text, we must do "some magic"
else if(prevRange.ListParagraphs.Count > 0)
{
    // First, insert a new line -> this causes a new item to be inserted into the above list
    prevRange.InsertAfter("\r");

    // Modify current range to be on the line of the new list item
    prevRange.Start = prevRange.Start + 1;
    prevRange.End = prevRange.Start;

    // Convert the list item line into a paragraph by removing its numbers
    prevRange.ListFormat.RemoveNumbers();

    // Insert the text
    prevRange.InsertBefore(myText);
}
...

Just add that code to the if-else block inside the foreach loop of the sample code I have provided above and you should be good to go :) I have tested it on my machine with MS Word 2013, and it seems to work.



来源:https://stackoverflow.com/questions/13311310/insert-text-before-a-list-using-word-interop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!