Word VSTO加载项:通过其范围更改段落的文本

时间:2018-06-02 12:06:17

标签: c# .net ms-word vsto

我正在编写一个加载项,它使用GroupContentControl(GCC)来写保护使用“标题1”样式的每个段落。一旦受到保护,这些标题只能通过加载项进行更改。为此,我编写了一个简单的方法来删除段落的GCC,为段落的Range.Text属性分配一个新值,再次将样式设置为标题1,然后设置一个新的GCC来保护段落。

我还是Office编程的新手,我的假设是Range对象可以在整个过程中使用。但是,该方法行为异常:它在新段落文本之后插入一个回车符,然后获取文档中的下一段并使其成为标题1段,然后对其进行写保护。

这是我的方法,同时调用日志函数来查看Range如何演变:

void ChangeParagraphText (Word.Paragraph p, string NewText)
{
    Log("Range 1 : " + p.Range.Start + " - " + p.Range.End);
    UnlockTitle(p);     // remove the paragraph's GroupContentControl     
    Log("Range 2 : " + p.Range.Start + " - " + p.Range.End);
    p.Range.Text = NewText;   // change the paragraph's text
    Log("Range 3 : " + p.Range.Start + " - " + p.Range.End);
    p.Range.set_Style(Globals.ThisAddIn.Application.ActiveDocument.Styles[Word.WdBuiltinStyle.wdStyleHeading1]);
    Log("Range 4 : " + p.Range.Start + " - " + p.Range.End);
    LockTitle(p);       // write-protect the paragraph with a GroupContentControl
    Log("Range 5 : " + p.Range.Start + " - " + p.Range.End);
}

运行后,以下是日志文件的内容:

Range 1 : 90 - 99
Range 2 : 90 - 97
Range 3 : 100 - 102
Range 4 : 100 - 102
Range 5 : 100 - 104

这教会了我一些有趣的事情。对于初学者,在移除GCC后,范围的长度减少2,并且在添加GCC时增加2。但重要的是,第三个日志条目:它表明只要我指定段落的Range.Text,Range就会完全改变。这些值与我的测试文档中的 next 段相匹配。

读取Range.Text属性还会显示它以换行符(ASCII 13)结尾。如果我省略它,我最终会在我的标题1段落中附加下一段。如果我把它放入,我最终将第二段视为标题1段。这些行为都不适合我。

我的问题是:如何以编程方式更改段落的文本?我认为它必须是可能的,但如果不是,那么解决方法是什么?我一直在考虑在我想改变之后创建一个新段落,然后删除旧段落,但这似乎不够优雅。

1 个答案:

答案 0 :(得分:1)

首先,快速回答您所陈述的问题:如何在段落本身完整的情况下替换段落的文本。我无法使用您提供的代码,因为它没有显示您如何派生p。所以我采取任意Paragraph对象:

Word.Range rngPara = doc.Paragraphs[1].Range;
object unitCharacter = Word.WdUnits.wdCharacter;
object backOne = -1;
rngPara.MoveEnd(ref unitCharacter, ref backOne);
rngPara.Text = "replacement text";

背景资料

问题最重要的方面是理解Word Range对象。

首先,永远不要依赖StartEnd属性来识别范围。他们可以快照"快照",或者将一个范围的开始或结束点动态设置为秒。但是,只要在文档中进行任何编辑,就可以将它们丢弃。

当您需要使用Ranges时,请在运行代码的持续时间内使用Range个对象(变量)。

是的,在您分析时,Paragraph.Range.Text确实包含了段落结尾标记。这是ANSI 13,不仅仅是一个回车;在封面下,它存储了大量有关段落格式的信息。如果只想处理文本,请将Range缩短一个字符,使段落标记不在Range范围内。这可以使用MoveEnd方法完成。