关于Word中InsertXML的说明(Word ML)

【前言】从Word2007刚出来的时候,就发现这个问题了,但是修改的不是很细致,也不深入。
今天优化代码的时候(2013年11月),又研究了下这个问题,在我所查找到的资料中,只有这一个有参考性的帖子。

【问题】wrod通过InsertXML的方法插入Word ML的时候,word2003和2007-2013的版本效果不一样。
对于一个简单的Word ML来说,2007-2013的版本比word2003多一个换行符。
就一个简单的换行符,对一个要在行内插入内容的使用场景来说,真是糟糕透了。

更有外国朋友贴出了总结的规律:
in Word 2003:
- ending without para mark: inserted as is.
- ending with para mark: inserted without para mark.
- ending with double para mark: inserted without last para mark.
- ending with para mark + single space: inserted without para mark and without the space.
- ending with para mark + double space: inserted as is.
- ending with para mark + any printable char(s) other than space: inserted as is.
in Word 2010:
- ending without para mark: inserted with para mark added at the end.
- ending with para mark: inserted as is.
- ending with double para mark: inserted as is.
- ending with para mark + single space: inserted without space.
- ending with para mark + double space: inserted with para mark added at the end.
- ending with para mark + any printable char(s) other than space: inserted with para mark added at the end.

【解决方案】
我以前的解决方案是:插入Word ML,然后判断版本,非2003删除后面的回车。
帖子里的解决方案是:先添加个回车,然后再回车前插入代码,然后删除回车。
因为我遇到的情况更复杂一些,涉及到插入域和修改域(Word Field),所以暂时坚持我原来的方案。

【相关链接】
http://social.msdn.microsoft.com/Forums/en-US/62c41f9e-9037-4805-85e7-be7483367835/rangeinsertxml-bug-in-word-2010?forum=worddev

帖子里的相关链接:
OpenXMLDeveloper.org
http://social.msdn.microsoft.com/forums/en-US/oxmlsdk/threads/
http://social.msdn.microsoft.com/Forums/en-US/os_openXML-ecma/threads

【链接中的代码】(好像是他们项目用的,不通用):

 internal static void InsertXML_W14_mimic_W11(this Word.Range range, string text)
    {
      // W11:
      // 1. Last paragraph is inserted with no ending '\r' and target paragraph formatting is retained.
      // 2. Any preceding paragraphs are inserted with ending '\r' and source paragraph formatting is used.
      // W14:
      // All paragraphs are inserted with ending '\r' and source paragraph formatting is used.
      // With W14 range stopped including the inserted text after InsertXML is called.
      // The range of range is now a point before the inserted text.
      //
      // We want to keep W11 behaviour.

      // range.End would move with rng if range includes end of header/footer or body
      Word.Range max_range = range.Duplicate;
      max_range.MoveEnd(Word.WdUnits.wdStory, 1); // End is moved as far as it goes (be it in header/footer or body)
      if (range.End == max_range.End) range.End--;

      Word.Range rng = range.Duplicate;
      rng.InsertAfter("\r#"); // Needed to work out end of range after range.InsertXML()

      // Get hold of target paragraph format.
      // Ie last paragraph in target range or following paragraph if target range ends with '\r'.
      Word.ParagraphFormat pf = rng.Paragraphs.Last.Format.Duplicate;
      
      range.InsertXML(text);
      // range.End is now equal range.Start (W14 bug, in W11 range.End would be after inserted text).
      // rng is now range.Start + inserted text + "\r" + "#".
      // Due to trailing \r paragraph format for last inserted paragraph is from source instead of target (as it would be with W11).

      // Work out if last paragraph before "#" is not empty (ie not '\r').
      // If so we will apply target paragraph markup to "last" paragraph.
      bool use_target_p_markup_for_last_para
        = rng.Paragraphs.Count > 1
        && (rng.Paragraphs[rng.Paragraphs.Count - 1].Range.Text != "\r" || rng.Paragraphs[rng.Paragraphs.Count - 1].Range.Fields.Count > 0);

      // Remove "\r#" and set range as it would be using W11.
      rng.Start = rng.End - 2;
      rng.Delete();
      range.End = rng.End;
      // Now we should have same range as if W11 had been used with the simple Range.InsertXML only.

      if (use_target_p_markup_for_last_para) range.Paragraphs.Last.Range.ParagraphFormat = pf;
    }
    





你可能感兴趣的:(关于Word中InsertXML的说明(Word ML))