Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用C从ObservableCollection创建Word文件#_C#_Ms Word_Openxml_Observablecollection - Fatal编程技术网

C# 使用C从ObservableCollection创建Word文件#

C# 使用C从ObservableCollection创建Word文件#,c#,ms-word,openxml,observablecollection,C#,Ms Word,Openxml,Observablecollection,我有一个可观察的集合,它的类有两个字符串属性:单词和翻译。我想以以下格式创建word文件: word=翻译word=翻译 word=翻译word=翻译 word文档需要分为两列(PageLayout),并且word应为粗体 我首先尝试了Microsoft.Office.Interop.Word。 PageSetup.TextColumns.SetCount(2)设置页面布局。至于文本本身,我使用了foreach循环,在每次迭代中我都这样做: paragraph.Range.Text = Wo

我有一个可观察的集合,它的类有两个字符串属性:单词和翻译。我想以以下格式创建word文件:


word=翻译word=翻译

word=翻译word=翻译


word文档需要分为两列(PageLayout),并且word应为粗体

我首先尝试了Microsoft.Office.Interop.Word。
PageSetup.TextColumns.SetCount(2)
设置页面布局。至于文本本身,我使用了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()这只需要不到一秒钟,但我无法将单词设置为粗体


然后我转而使用OpenXMLSDK2.5,但即使在阅读了msdn文档之后,我仍然不知道如何将文本的一部分加粗,我甚至不知道是否可以设置PageLayout列数。我唯一能做的就是让它看起来和Interop.Word一样,但是只有一列和OpenXML绝对更好,因为它更快,bug更少,运行时更可靠和灵活(特别是在服务器环境中)。了解如何使用OpenXML生成一个或另一个元素并不困难。因为docx文件只是一个包含xml文件的zip文件,所以我打开它并阅读xml来了解word本身是如何制作的。首先,我创建一个文档,然后格式化它(在您的情况下,您可以创建一些包含两列和粗体字的文件),保存它,然后将其重命名为.zip文件。然后打开它,打开里面的“word”目录和目录里面的文件“document.xml”。本文档包含xml的基本部分,看看这一点,不难理解如何在OpenXML中重新创建它。OOXML一开始可能很吓人。有一些很好的例子。每当你感到困惑时,解压docx并浏览内容,看看它是如何完成的

基本思想是打开Word,创建一个模板,使用您想要的样式和一个码字来查找段落,然后将段落相乘,用每个单词替换模板中的文本

您的Word模板如下所示:

假设您已经安装了

    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();
    }
var templateRegex=newregex(\\[templateForWords\\]);
var wordPlacementRegex=新的Regex(“\\[word\\]”);
var translationPlacementRegex=newregex(“\\[translation]\\]”);
使用(var document=WordprocessingDocument.Open(stream,true))
{ 
MainDocumentPart mainPart=document.MainDocumentPart;
//在这里做你的工作。。。
var paragraphTemplate=mainPart.Document.Body
.后代()
.Where(p=>templateRegex.IsMatch(p.InnerText));//pseudo
//…或者不管你怎么看这段文字,我现在没有SDK
foreach(字典中的字符串){
var paraClone=paragraphTemplate.Clone();//pseudo
//您可能需要执行以下操作:
//paraClone.degents().Where(t=>regex.IsMatch(t.Value))
//查找包含模板文本的确切元素的步骤
paraClone.Text=templateRegex.Replace(paraClone.Text,“”;//pseudo
paraClone.Text=wordPlacementRegex.Replace(paraClone.Text,word);
paraClone.Text=translationPlacementRegex.Replace(paraClone.Text,您的字典[word]);
paragraphTemplate.Parent.InsertAfter(paraClone,paragraphTemplate);//pseudo
}
paragraphTemplate.Remove();
//文档应该自动保存
document.Package.Flush();
}

开放式XML是比Office COM更好的选择。但问题是,它是一个低级别的文件格式库,与Office COM不同,它不能在高抽象级别上工作。你可能想走那条路线,但我建议你先考虑一下一个商业图书馆,它会给你一个高级DOM的好处,而不需要在生产机器上安装MSWord。我们公司最近购买了它,允许您使用基于模板的方法以及DOM/编程方法来生成/修改/创建文档。

尽可能避免互操作(在您的情况下也是如此),您可以下载Open XML SDK生产力工具。您可以使用它来查看制作word文档时生成的xml代码,还可以显示需要生成的c#代码it@AlexanderDerck我下载了生产力工具,但还没有安装。在看到你的评论后,我安装了它,制作了一个测试词文档,花了大概1-2分钟在工具中,找到了我需要知道的,并在VS中编写了代码。。。我之前花了5个多小时阅读/学习Interop和OpenXMLSDK,并试图将其编写得恰到好处。当我下载这个工具时,我对它的概念是错误的。感谢您提出的简单但却很好的建议:D@VincentProxy是的,OpenXMLSDK的文档非常糟糕,但至少该工具非常棒:)误导。OOXML有一个SDK,它比结合XML和ZIP SDK更易于使用,验证结构并具有强类型Linqsupport@StenPetrov关于使用xml或zip sdk,我一句话也没说,我的答案是关于使用OpenXML,而你的答案,实际上,重复了我的大部分内容。你答案中唯一相关的信息是docx是一个zip,其余的“不难”@stenportov在答案中,我解释了如何找到OpenXml OP想要构建的理想结构。从他的问题中,我假设他知道这个库的基本知识,所以我不需要向他解释WordprocessingDocument.Open和其他内容。我没有提到任何关于使用纯xml或zip库的内容,我也没有提到