繁体   English   中英

如何在 ASP.net 中使用 Open XML 创建多级有序列表?

[英]How do you create multi-level ordered lists with Open XML in ASP.net?

我花了无数个小时试图理解 Open XML 中的有序列表。 这里是一个多引用。

我发现了一个简单的文档创建者的这种难以置信的帮助例子在这里

另外,如果我可能会抱怨一点,我必须说这是一个痛苦的学习曲线。 创建编号属性并引用正确的abstractNumberId并且该列表不断重复。

有没有人有在代码中创建多级列表的完整示例? 我可以在没有自定义设置的情况下这样做,就像设置NumberFormatValues.Decimal 一旦您想开始控制listType您就会有很多即时开销。

以我开始的上述示例为例,我添加了一个level参数:

public void AddBulletList(List<Run> runList, int level)

我把它合并在这条线上:

var abstractLevel = new Level(new NumberingFormat() {
    Val = NumberFormatValues.Decimal}, new LevelText() {Val = "·"}) {LevelIndex = level};

请注意,我将格式类型更改为十进制……方法名称显示为 bullet 但我只是在此处进行测试。

我还利用它来处理缩进:

var indentation = new Indentation() { Left = (720 * (level + 1)).ToString(), Hanging = "360" };  

因此,在我的测试中,我向传入0表示级别的方法发送了几句话。 然后我再发送一些传入1的级别。

我的结果有两个问题:

1)我不知道如何重置计数器,所以我得到了这个:

1. Sentence 1
2. Sentence 2
3. Sentence 3
    4. Sentence 1
    5. Sentence 2
    6. Sentence 3

我尝试使用levelRestart但这没有用:

abstractLevel.LevelRestart = new LevelRestart(){ Val = 0 } // tried 1 also

我可以让它重新启动的唯一方法是在插入第二个句子列表之前插入一个空白段落,但这有样式问题(间距)。

我遇到的第二个问题是编号出现在 WordDoc 中,但它在 Microsoft Word 中显示为项目符号。 此外,我在 Microsoft Word 中收到兼容模式警告。

有人会过来说:

使用 Open XML Productivity Tools 并创建一个文档并查看生成的代码

好吧,我对此的回应是:

在看了 5,000 行代码后,我的眼睛在流血,这是一个用来测试的小文档。

所以我觉得我非常接近。 我的代码中有很多其他自定义项,这就是为什么我继续引用我开始的地方。 如果有人可以采用该示例或提供现有示例,我只想创建多级列表并控制使用的编号类型(lowerRoman、decimal 等)。

更新 1

我真的只需要硬着头皮做一些认真的学习。 在托马斯的帮助下,我已经能够继续前进,但似乎我还有一个棘手的问题。 我的新有序列表不是从“1”开始的。

请注意在图像中,如果我单击第一个列表的级别,它只会突出显示该列表。 我希望它们是分开的,但显然不是。 下一个列表应该从 1 开始。

新列表没有重新启动

对于每个新的有序列表,我都为它分配了一个新的numberId所以我不知道发生了什么。 这是生成的标记:

<w:numbering xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex" xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex" xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex" xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex" xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex" xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex" xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex" xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex" xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink" xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid" xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid wp14">
      <w:abstractNum w:abstractNumId="1" w15:restartNumberingAfterBreak="1">
        <w:nsid w:val="191025D9" />
        <w:multiLevelType w:val="hybridMultilevel" />
        <w:tmpl w:val="48A2E570" />
        <w:lvl w:ilvl="0" w:tplc="0409000F">
          <w:start w:val="1" />
          <w:numFmt w:val="decimal" />
          <w:lvlText w:val="%1." />
          <w:lvlJc w:val="left" />
          <w:pPr>
            <w:ind w:start="720" w:hanging="360" />
          </w:pPr>
        </w:lvl>
        <w:lvl w:ilvl="1" w:tplc="04090019">
          <w:start w:val="1" />
          <w:numFmt w:val="lowerLetter" />
          <w:lvlText w:val="%2." />
          <w:lvlJc w:val="left" />
          <w:pPr>
            <w:ind w:start="1440" w:hanging="360" />
          </w:pPr>
        </w:lvl>        
      </w:abstractNum>
      <w:abstractNum w:abstractNumId="2" w15:restartNumberingAfterBreak="1">
        <w:nsid w:val="191025D9" />
        <w:multiLevelType w:val="hybridMultilevel" />
        <w:tmpl w:val="48A2E570" />
        <w:lvl w:ilvl="0" w:tplc="0409000F">
          <w:start w:val="1" />
          <w:numFmt w:val="decimal" />
          <w:lvlText w:val="%1." />
          <w:lvlJc w:val="left" />
          <w:pPr>
            <w:ind w:start="720" w:hanging="360" />
          </w:pPr>
        </w:lvl>
        <w:lvl w:ilvl="1" w:tplc="04090019">
          <w:start w:val="1" />
          <w:numFmt w:val="lowerLetter" />
          <w:lvlText w:val="%2." />
          <w:lvlJc w:val="left" />
          <w:pPr>
            <w:ind w:start="1440" w:hanging="360" />
          </w:pPr>
        </w:lvl>        
      </w:abstractNum>
      <w:num w:numId="1">
        <w:abstractNumId w:val="1" />
      </w:num>
      <w:num w:numId="2">
        <w:abstractNumId w:val="2" />
      </w:num>
    </w:numbering>

这是身体:

    <w:body xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:p>
    <w:pPr>
      <w:pStyle w:val="ListParagraph" />
      <w:numPr>
        <w:ilvl w:val="0" />
        <w:numId w:val="1" />
      </w:numPr>
    </w:pPr>
    <w:r>
      <w:t>List one item 1</w:t>
    </w:r>
  </w:p>
  <w:p>
    <w:pPr>
      <w:pStyle w:val="ListParagraph" />
      <w:numPr>
        <w:ilvl w:val="0" />
        <w:numId w:val="1" />
      </w:numPr>
    </w:pPr>
    <w:r>
      <w:t>List one item 2</w:t>
    </w:r>
  </w:p>
  <w:p>
    <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>List two item 1</w:t>
    </w:r>
  </w:p>
  <w:p>
    <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>List two item 2</w:t>
    </w:r>
  </w:p>
</w:body>

虽然我从未使用过 Open XML Productivity Tools,但我经常使用并推荐Open XML Package Editor for Modern Visual Studios 使用该包编辑器,您可以查看 Microsoft Word 创建的 Open XML 标记以从中学习。

因此,为了回答您的问题,我已经这样做了,使用包含多个多级列表的 Word 模板,这些列表的行为与您希望它们的行为完全相同(我希望)。

(a)  First paragraph, on outline level 0 (shown as 1 in Word)
(b)  Second paragraph, on outline level 0
     (1) Third paragraph, on outline level 1 (shown as 2 in Word)
     (2) Fourth paragraph, on outline level 1

请注意,您的多级列表的不同级别通常会有不同的编号格式(例如,小写字母、大写字母、小写罗马字母、大写罗马字母、十进制)。

接下来,这是主文档部分对应的 Open XML 标记:

  <w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
      <w:p>
        <w:pPr>
          <w:pStyle w:val="ListLowerLetter0"/>
        </w:pPr>
        <w:r>
          <w:t>First paragraph, on outline level 0 (shown as 1 in Word)</w:t>
        </w:r>
      </w:p>
      <w:p>
        <w:pPr>
          <w:pStyle w:val="ListLowerLetter0"/>
        </w:pPr>
        <w:r>
          <w:t>Second paragraph, on outline level 0</w:t>
        </w:r>
      </w:p>
      <w:p>
        <w:pPr>
          <w:pStyle w:val="ListLowerLetter0"/>
          <w:numPr>
            <w:ilvl w:val="1"/>    <!-- This overrides the numbering level -->
            <w:numId w:val="43"/>  <!-- This references the w:numbering/w:num -->
          </w:numPr>
        </w:pPr>
        <w:r>
          <w:t>Third paragraph, on outline level 1 (shown as 2 in Word)</w:t>
        </w:r>
      </w:p>
      <w:p>
        <w:pPr>
          <w:pStyle w:val="ListLowerLetter0"/>
          <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="43"/>
          </w:numPr>
        </w:pPr>
        <w:r>
          <w:t>Fourth paragraph, on outline level 1</w:t>
        </w:r>
      </w:p>
    </w:body>
  </w:document>

请注意w:pStylew:numPr元素,它们指定要使用的编号段落样式,并且在也使用w:numPr情况下,会覆盖样式中指定的编号默认值。

接下来,这是样式定义部分的 Open XML 标记:

  <w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

    <!-- This is the paragraph style used in the main document part (w:document) -->
    <w:style w:type="paragraph" w:customStyle="1" w:styleId="ListLowerLetter0">
      <w:name w:val="List Lower Letter 0"/>
      <w:basedOn w:val="Normal"/>
      <w:pPr>
        <w:numPr>
          <w:numId w:val="43"/>   <!-- This references the w:numbering/w:num -->
        </w:numPr>
      </w:pPr>
    </w:style>

    <!-- This is the list style referenced in the numbering definitions part (w:numbering).
         This is optional but helps if you want to use the list in Word. -->
    <w:style w:type="numbering" w:customStyle="1" w:styleId="ListLowerLetter0List">
      <w:name w:val="List Lower Letter 0 List"/>
      <w:basedOn w:val="NoList"/>
      <w:pPr>
        <w:numPr>
          <w:numId w:val="43"/>   <!-- This references the w:numbering/w:num -->
        </w:numPr>
      </w:pPr>
    </w:style>


    <!-- I've included this for completeness because it is referenced by our
         paragraph style below -->
    <w:style w:type="paragraph" w:default="1" w:styleId="Normal">
      <w:name w:val="Normal"/>
      <w:rPr>
        <w:kern w:val="16"/>
      </w:rPr>
    </w:style>

    <!-- I've included this for completeness because it is referenced by our
         list style below -->
    <w:style w:type="numbering" w:default="1" w:styleId="NoList">
      <w:name w:val="No List"/>
      <w:semiHidden/>
      <w:unhideWhenUsed/>
    </w:style>
  </w:styles>

我只需要ListLowerLetter0样式。 ListLowerLetter0List是可选的列表样式。 我总是在我的模板中使用它们。 其他两种风格只是为了完整性和一致性。 显然,现实生活中的样式定义部分包含更多样式和其他元素。

最后,我们有编号定义部分的 Open XML 标记(同样带有解释相关元素作用的注释):

  <w:numbering xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
               xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
               xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
               xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
               mc:Ignorable="w14 w15">

    <!-- Here's an example multi-level list -->
    <w:abstractNum w:abstractNumId="67" w15:restartNumberingAfterBreak="0">
      <w:nsid w:val="3E434843" />
      <w:multiLevelType w:val="multilevel" />
      <w:tmpl w:val="1146F302" />

      <!-- The w:styleLink references our list style. This is optional (but I use
           it as a best practice in Word) -->
      <w:styleLink w:val="ListLowerLetter0List" />

      <!-- This defines the first outline level, i.e., 0 in Open XML lingo or 1
           when you look at it in Word -->
      <w:lvl w:ilvl="0">
        <!-- This starts the level at the ordinal number 1, i.e., "a" on this level -->
        <w:start w:val="1" />

        <!-- This defines the number format on this level -->
        <w:numFmt w:val="lowerLetter" />

        <!-- This references our paragraph style, which will be the same on each level -->
        <w:pStyle w:val="ListLowerLetter0" />

        <!-- This defines the level text, e.g., (a), (b), (c), ... -->
        <w:lvlText w:val="(%1)" />

        <!-- The next elements define alignment, indentation, and color -->
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="851" w:hanging="851" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>

      <!-- This and the following w:lvl elements define levels 1 to 8 (i.e., 2 to 9 in Word) -->
      <w:lvl w:ilvl="1">
        <w:start w:val="1" />
        <w:numFmt w:val="decimal" />
        <w:lvlText w:val="(%2)" />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="1418" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="2">
        <w:start w:val="1" />
        <w:numFmt w:val="upperLetter" />
        <w:lvlText w:val="(%3)" />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="1985" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="3">
        <w:start w:val="1" />
        <w:numFmt w:val="lowerRoman" />
        <w:lvlText w:val="(%4)" />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="2552" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="4">
        <w:start w:val="1" />
        <w:numFmt w:val="lowerLetter" />
        <w:lvlText w:val="%5." />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="3119" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="5">
        <w:start w:val="1" />
        <w:numFmt w:val="decimal" />
        <w:lvlText w:val="%6." />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="3686" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="6">
        <w:start w:val="1" />
        <w:numFmt w:val="lowerLetter" />
        <w:lvlText w:val="%7." />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="4253" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="7">
        <w:start w:val="1" />
        <w:numFmt w:val="lowerRoman" />
        <w:lvlText w:val="%8." />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="4820" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
      <w:lvl w:ilvl="8">
        <w:start w:val="1" />
        <w:numFmt w:val="lowerLetter" />
        <w:lvlText w:val="%9)" />
        <w:lvlJc w:val="left" />
        <w:pPr>
          <w:ind w:left="5387" w:hanging="567" />
        </w:pPr>
        <w:rPr>
          <w:color w:val="auto" />
        </w:rPr>
      </w:lvl>
    </w:abstractNum>

    <!-- This is the w:num referenced from our main document part (w:document) -->
    <w:num w:numId="43">
      <w:abstractNumId w:val="67" />
    </w:num>
  </w:numbering>

现在,基于对创建所需效果所需的标记的理解,使用以下任一方法手写生成该标记的 C# 代码实际上非常容易:

让我为这两个选项提供非常简短的示例,生成以下标记:

    <w:num w:numId="43">
      <w:abstractNumId w:val="67" />
    </w:num>

下面是使用Open XML SDK的强类型类的代码:

var num = new NumberingInstance
{
    NumberID = 43,
    AbstractNumId = new AbstractNumId { Val = 67 }
};

这是使用Open-XML-PowerTools的代码:

var num =
    new XElement(W.num, new XAttribute(W.numId, 43),
        new XElement(W.abstractNumId, new XAttribute(W.val, 67)));

在这种情况下,Open-XML-PowerTools 的美妙之处在于您可以逐字复制标签名称。 此外,Linq to XML 类的构造函数(例如XElement )比 Open XML SDK 的构造函数灵活得多,并且 C# 代码看起来很像 Open XML 标记。 因此,对于像这样的用例,我对 Open-XML-PowerTools 略有偏好。 但是,我也非常成功地将 Open XML SDK 用于此类情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM