如何使用C#和OpenXml访问Word文档中的大纲编号?

如何使用C#和OpenXml访问Word文档中的大纲编号?,c#,excel,ms-word,openxml,C#,Excel,Ms Word,Openxml,我正在尝试将Microsoft Word 2010中的大纲转换为Microsoft Excel 2010中的电子表格。我正在使用DocumentFormat.OpenXml.Packing和DocumentFormat.OpenXml.Wordprocessing 我获取文档的主体,并使用它获取所有段落对象的列表: var allParagraphs = new List<Paragraph>(); WordprocessingDocument wordprocessingDocum

我正在尝试将
Microsoft Word 2010
中的大纲转换为
Microsoft Excel 2010
中的电子表格。我正在使用
DocumentFormat.OpenXml.Packing
DocumentFormat.OpenXml.Wordprocessing

我获取文档的主体,并使用它获取所有段落对象的列表:

var allParagraphs = new List<Paragraph>();
WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(wordDocPath.Text, false);
Body body = wordprocessingDocument.MainDocumentPart.Document.Body;
allParagraphs = body.OfType<Paragraph>().ToList();
var allparations=new List();
WordprocessingDocument WordprocessingDocument=WordprocessingDocument.Open(wordDocPath.Text,false);
Body Body=wordprocessingDocument.MainDocumentPart.Document.Body;
ALLPRAGES=body.OfType().ToList();
但我似乎找不到任何存储段落旁边的大纲编号的东西。我是否需要抓取文档中段落之外的其他对象来获取每个段落的大纲编号(如果有)

在下面的屏幕截图中,我所说的大纲编号出现在这些标题的左侧:


不幸的是,
ParagraphProperties.OutlineLevel
为空,尽管我知道它是word文档中大纲的一部分。

现在我已经完全理解了您想要什么,下面是您应该如何着手解决问题

首先,我建议您从下载OpenXML生产力工具。一旦知道了文件的底层xml是什么样子,就很容易解决这个问题

<w:p w:rsidR="004265BF" w:rsidP="00AD13B6" w:rsidRDefault="00AD13B6">
 <w:pPr>
  <w:pStyle w:val="ListParagraph" />
  <w:numPr>
   <w:ilvl w:val="0" />
   <w:numId w:val="2" />
  </w:numPr>
 </w:pPr>
 <w:r>
  <w:t>Requirements</w:t>
 </w:r>
</w:p>
<w:p w:rsidR="00AD13B6" w:rsidP="00AD13B6" w:rsidRDefault="00AD13B6">
 <w:pPr>
  <w:pStyle w:val="ListParagraph" />
   <w:numPr>
    <w:ilvl w:val="1" />
    <w:numId w:val="2" />
   </w:numPr>
  </w:pPr>
  <w:r>
   <w:t>Performance</w:t>
  </w:r>
</w:p>

要求
演出
在上面,您可以看到仅几段内容的XML。每个段落都有相应的
,其中包含

每个word文档都包含许多不同的XML文件,这些文件充当对整个文档体中使用的样式和值的引用。对于大纲,有Numbering.xml

这里的每个numId都引用numbering.xml中的一个AbstractNumId,它反过来又引用同一文件中的abstractNum。你可以从那里得到你的大纲编号

我知道这听起来很乏味,但这是唯一可以做到的方法

祝你一切顺利

using (WordprocessingDocument doc = WordprocessingDocument.Open("word-wrP.docx", true))
        {
            Body body = doc.MainDocumentPart.Document.Body;

            //Documents' numbering definition
            Numbering num = doc.MainDocumentPart.NumberingDefinitionsPart.Numbering;

            //Get all paragraphs in the document
            IEnumerable<Paragraph> paragraphs = doc.MainDocumentPart.Document.Body.OfType<Paragraph>();
            foreach (Paragraph paragraph in paragraphs)
            {
                int tempLevel = 0; 
             
                //Each paragraph has a reference to a numbering definition that is defined by the numbering ID
                NumberingId numId = paragraph.ParagraphProperties.NumberingProperties.NumberingId;

                //NumberingLevelReference defines the outline level or the "indent" of Numbering, index starts at Zero.
                NumberingLevelReference iLevel =
                    paragraph.ParagraphProperties.NumberingProperties.NumberingLevelReference;

                //From the numbering reference we get the actual numbering definition to get start value of the outline etc etc.
                var firstOrDefault =
                    num.Descendants<NumberingInstance>().FirstOrDefault(tag => tag.NumberID == (int)numId.Val);
                if (firstOrDefault != null)
                {
                    var absNumId =
                        firstOrDefault.GetFirstChild<AbstractNumId>();
                    AbstractNum absNum =
                        num.OfType<AbstractNum>().FirstOrDefault(tag => tag.AbstractNumberId == (int)absNumId.Val);
                    if (absNum != null)
                    {
                        StartNumberingValue start = absNum.OfType<StartNumberingValue>().FirstOrDefault();
                        // once you have the start value its just a matter of counting the paragraphs that have the same numberingId and from the Number
                        //ingLevel you can calculate the actual values that correspond to each paragraph.
                        if (start != null) startValue = start.Val;
                    }
                }
                else
                {
                    Console.WriteLine("Failed!");
                }
            }
        }
使用(WordprocessingDocument=WordprocessingDocument.Open(“word wrP.docx”,true))
{
Body Body=doc.main documentpart.Document.Body;
//文件编号定义
编号编号=doc.main documentpart.Numbering定义spart.Numbering;
//获取文档中的所有段落
IEnumerable段落=doc.MainDocumentPart.Document.Body.OfType();
foreach(段落中的段落)
{
int-tempLevel=0;
//每个段落都引用由编号ID定义的编号定义
NumberingId numId=段落.ParagraphProperties.NumberingProperties.NumberingId;
//NumberingLevelReference定义编号的大纲级别或“缩进”,索引从零开始。
编号级别参考I级别=
段落.ParagraphProperties.NumberingProperties.NumberingLevelReference;
//从编号参考中,我们得到实际的编号定义,以获得轮廓的起始值等。
var firstOrDefault=
num.subjects().FirstOrDefault(tag=>tag.NumberID==(int)numId.Val);
if(firstOrDefault!=null)
{
absNumId变种=
GetFirstChild();
抽象数=
num.OfType().FirstOrDefault(tag=>tag.AbstractNumberId==(int)absNumId.Val);
如果(absNum!=null)
{
StartNumberingValue start=absNum.OfType().FirstOrDefault();
//一旦有了起始值,只需从数字开始计算具有相同numberingId的段落
//ingLevel您可以计算每个段落对应的实际值。
如果(start!=null)startValue=start.Val;
}
}
其他的
{
Console.WriteLine(“失败!”);
}
}
}

我不确定你通过大纲编号推断出什么,你能发布一个屏幕截图突出显示它是什么吗,然后也许我可以帮你。@VarunRathore,我已经添加了一个我所说的屏幕截图。我的目标是让它成为一个处理所有这些问题的windows应用程序,但我相信OpenXml可能没有我想要的功能。现在我已经在Word文档中使用了vba,但我更愿意使用C#路线。哇,这个工具太棒了!它也会用C语言为您生成代码??!!你应该得到+1。我很可能也会给你答案,只要我多用一点,看看这是否对我有用。看起来会的…我很高兴我能帮上忙:)再次感谢你的帮助。如果你不介意的话,你能给我举个例子来帮助我吗。我一直在尝试编写针对上述示例的C代码,其中大纲与标题样式相关联。我很难找到不同部分(或.xml)文件之间的相关性。如果您有这方面的经验,您是否介意告诉我如何获得我提供的屏幕截图示例中每个段落的大纲编号?此工具的许可证是什么,是否免费用于商业用途?@SaadA您可以在这里找到问题的答案