使用C#从ObservableCollection创建Word文件

时间:2016-01-04 19:04:24

标签: c# ms-word openxml observablecollection

我有一个可观察的集合,其中一个类有2个字符串属性:Word和Translation。我想以格式创建一个word文件:

=翻译 =翻译

=翻译 =翻译...

word文档需要在2列(PageLayout)中,Word应以粗体显示。

我首先尝试过Microsoft.Office.Interop.Word。 PageSetup.TextColumns.SetCount(2)设置PageLayout。至于文本本身,我使用了foreach循环,在每次迭代中我都这样做了:

paragraph.Range.Text = Word + " = " + Translation;
object boldStart = paragraph.Range.Start;
object boldEnd = paragraph.Range.Start + Word.Length;
Word.Range boldPart = document.Range(boldStart, boldEnd);
boldPart.Bold = 1;

paragraph.Range.InsertParagraphAfter();

这正是我想要的,但如果集合中有1000个项目需要大约10秒,如果数量是10k +则要多得多。然后我使用了一个StringBuilder并设置了document.Content.Text = sb.ToString();并且花了不到一秒钟,但我不能将这个单词设置为粗体。

然后我转而使用Open XML SDK 2.5,但即使阅读了msdn文档,我仍然不知道如何只将文本的一部分变为粗体,我不知道是否甚至可以设置PageLayout Columns计数。我唯一能做的就是让它看起来与Interop.Word相同,但只有1列和<1秒的创建时间。

我应该使用Interop.Word还是Open XML(或者可能合并)?并且有人可以告诉我如何正确地写这个,所以如果集合相对较大,它不会永远存在吗?任何帮助表示赞赏。 :)

3 个答案:

答案 0 :(得分:0)

OpenXML绝对更好,因为它在运行时(特别是在服务器环境中)速度更快,错误更少,更可靠和更灵活。并且要找出如何使用OpenXML创建一个或另一个元素并不是很困难。由于docx文件只是一个包含xml文件的zip文件,我打开它并阅读xml以获取想法,word本身是如何实现的。首先,我创建一个文档,然后对其进行格式化(在您的情况下,您可以创建一个包含两列和内部粗体字的文件),保存它,将其重命名为.zip文件。然后打开它,打开里面的“word”目录和目录里面的文件“document.xml”。本文档包含xml的基本部分,看看这个并不难解决如何在OpenXML中重新创建它

答案 1 :(得分:0)

OOXML最初可能会令人生畏。 http://officeopenxml.com/anatomyofOOXML.php有一些很好的例子。每当你感到困惑时,解压缩docx并浏览内容以查看它是如何完成的。

基本的想法是你打开Word,用你想要的样式创建一个模板,然后用代码字找到段落,然后将段落相乘,用每个单词替换该模板中的文本。

您的Word模板如下所示:

Word template

这里有一些代码可以帮助您入门,假设您安装了SDK

    var templateRegex = new Regex("\\[templateForWords\\]");
    var wordPlacementRegex = new Regex("\\[word\\]");
    var translationPlacementRegex = new Regex("\\[translation]\\]");

    using (var document = WordprocessingDocument.Open(stream, true))
    { 
      MainDocumentPart mainPart = document.MainDocumentPart;

      // do your work here...
      var paragraphTemplate = mainPart.Document.Body
       .Descendants<Paragraph>()
       .Where(p=>templateRegex.IsMatch(p.InnerText)); //pseudo 
       //... or whatever gives you the text of the Para, I don't have the SDK right now

      foreach (string word in YourDictionary){
        var paraClone = paragraphTemplate.Clone(); // pseudo 

// you may need to do something like 
// paraClone.Descendents<Text>().Where(t=>regex.IsMatch(t.Value))
// to find the exact element containing template text
        paraClone.Text = templateRegex.Replace(paraClone.Text,"");// pseudo 
        paraClone.Text = wordPlacementRegex.Replace(paraClone.Text,word);
        paraClone.Text = translationPlacementRegex.Replace(paraClone.Text,YourDictionary[word]);

        paragraphTemplate.Parent.InsertAfter(paraClone,ParagraphTemplate); // pseudo
      }

      paragraphTemplate.Remove();

      // document should auto-save 
      document.Package.Flush();
    }

答案 2 :(得分:0)

Open XML是比Office COM更好的选择。但问题是它是一个低级文件格式库,与Office COM不同,它不能在高抽象级别上运行。您可能希望走这条路线,但我建议您首先考虑查看一个商业库,它将为您提供高级DOM的好处,而无需在生产计算机上安装MS Word。我们公司最近购买了this toolkit,它允许您使用基于模板的方法以及DOM /程序化方法来生成/修改/创建文档。