首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用C#和OpenXml访问Word文档中大纲的编号?

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

Stack Overflow用户
提问于 2013-12-22 10:28:03
回答 2查看 4K关注 0票数 4

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

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

代码语言:javascript
复制
var allParagraphs = new List<Paragraph>();
WordprocessingDocument wordprocessingDocument = WordprocessingDocument.Open(wordDocPath.Text, false);
Body body = wordprocessingDocument.MainDocumentPart.Document.Body;
allParagraphs = body.OfType<Paragraph>().ToList();

但是,我似乎找不到任何东西存储大纲编号,就在段落旁边。我是否需要抓取文件中的段落以外的其他对象,以获得每个段落的大纲编号(如果有的话)?

下面的截图显示了这些标题的左边显示的大纲编号:

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-24 05:18:41

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

首先,我建议您从这里下载工具。一旦您知道了文件的底层xml是什么样子,解决这个问题就变得非常容易了。

代码语言:javascript
复制
<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。每个段落都有相应的<w:numPr>,其中包含<w:numId>

每个word文档包含许多不同的XML文件,它们作为对整个文档正文中使用的样式和值的引用。关于提纲,有Numbering.xml。

这里的每个numId都引用numbering.xml中的AbstractNumId,而后者又引用同一个文件中的abstractNum。你可以从那里得到你的提纲号码。

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

万事如意!

代码语言:javascript
复制
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!");
                }
            }
        }
票数 7
EN

Stack Overflow用户

发布于 2022-09-14 19:11:40

我发现@varun的答案对于今天解决这个问题非常有帮助。然而,我的编号方案非常复杂,我认为通过NumberingLevelReference计算字符串的任务非常艰巨。我能够通过安装以下nuget包来解决这个问题:

https://www.nuget.org/packages/OpenXmlPowerTools

一旦我这样做了,我就能得到如下的编号:

代码语言:javascript
复制
var wordDoc = WordprocessingDocument.Open(doc.InputStream, false);

var mdp = wordDoc.MainDocumentPart;
var xDoc = mdp.GetXDocument();
var paragraphs = xDoc.Descendants(W.p);

foreach (var paragraph in paragraphs)
{
    var listItem = ListItemRetriever.RetrieveListItem(wordDoc, paragraph);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20728408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档