I am creating a Word document using Open XML, and cannot understand how to make numbering reset.
What I want is this:
1. Top index line A
2. Top index line B
1. Top index line C
But what I'm getting is this:
1. Top index line A
2. Top index line B
3. Top index line C
In my Open Xml I have two AbstractNum objects that define the layout of the numbering. Both AbstractNums are identical, except that one has an abstractNumId of 200 and the other has an abstractNumId of 201.
I have shown only the first level definition for brevity.
<w:abstractNum
xmlns:w15=";
w:abstractNumId="200"
w15:restartNumberingAfterBreak="0"
xmlns:w=";>
<w:multiLevelType w:val="multilevel" />
<w:lvl w:ilvl="0">
<w:start w:val="1" />
<w:numFmt w:val="decimal" />
<w:suff w:val="space" />
<w:lvlText w:val="%1." />
<w:lvlJc w:val="left" />
<w:pPr>
<w:ind w:left="360" w:hanging="360" />
</w:pPr>
<w:rPr>
<w:b />
</w:rPr>
</w:lvl>
</w:abstractNum>
I also have two NumberingInstance objects. One has a numbering instance Id of 100 and an AbstractNumId of 200. The other has a numbering instance Id of 101 and an AbstractNumId of 201.
And in the document body, I have three paragraphs, the first two have a numbering instance id of 100, and the last one, 101.
<w:body xmlns:w=";>
<w:sectPr>
<w:pgSz w:w="11932" w:h="16875" w:orient="portrait" />
<w:pgMar w:top="1443" w:right="1443" w:bottom="1443" w:left="1443" w:header="710" w:footer="710" w:gutter="568" />
</w:sectPr>
<w:p>
<w:pPr>
<w:pStyle w:val="legalPara" />
<w:numPr>
<w:ilvl w:val="0" />
<w:numId w:val="100" />
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="default">Top index line A</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="legalPara" />
<w:numPr>
<w:ilvl w:val="0" />
<w:numId w:val="100" />
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="default">Top index line B</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="legalPara" />
<w:numPr>
<w:ilvl w:val="0" />
<w:numId w:val="101" />
</w:numPr>
</w:pPr>
<w:r>
<w:t xml:space="default">Top index line C</w:t>
</w:r>
</w:p>
</w:body>
From what I understand, switching the number id on the last paragraph from 100 to 101 should start the numbering again at 1, but it does not.
I have tried correcting my Open XML in Word and identifying the difference in the OpenXML Productivity tool, but Word seems to be doing what I am doing - switching to a different number Id. I am omitting to do something.
Thanks for reading.
-
-
- UPDATE * * *
-
Here is a code example that runs in a C# console app.
using System.Text;
using OpenXml = DocumentFormat.OpenXml;
using OpenXmlPackaging = DocumentFormat.OpenXml.Packaging;
using OpenXmlWordProc = DocumentFormat.OpenXml.Wordprocessing;
Console.WriteLine("Application: Started");
//
using (MemoryStream ms = new MemoryStream())
{
//
using (OpenXmlPackaging.WordprocessingDocument wordDocument = OpenXmlPackaging.WordprocessingDocument.Create(ms, OpenXml.WordprocessingDocumentType.Document, true))
{
// Set up main docjment part
OpenXmlPackaging.MainDocumentPart mainPart = wordDocument.AddMainDocumentPart();
{
// Setup the numbering
{
//
OpenXmlPackaging.NumberingDefinitionsPart numberingDefinitionsPart = mainPart.NumberingDefinitionsPart != null ? mainPart.NumberingDefinitionsPart : mainPart.AddNewPart<OpenXmlPackaging.NumberingDefinitionsPart>();
//
if (numberingDefinitionsPart.Numbering is null)
numberingDefinitionsPart.Numbering = new OpenXmlWordProc.Numbering();
ArgumentNullException.ThrowIfNull(numberingDefinitionsPart.Numbering);
}
}
// Set up document
mainPart.Document = new OpenXmlWordProc.Document();
// Set up body
OpenXmlWordProc.Body body = mainPart.Document.AppendChild(new OpenXmlWordProc.Body());
///////////////////////////////////////////////////////////////////
// Add the content
// For some reason, Word inserts an abstract-numbering with id 0
//_addAbstractNumbering(mainPart, 0);
// Create a numbering (id:100) based on an abstract-numbering (id:200)
_addAbstractNumbering(mainPart, 200);
_addNumbering(mainPart, iNumberId: 100, iAbstractNumberingId: 200); // <-- Remove these lines and it works!!!
// Line A
OpenXmlWordProc.Paragraph P = new OpenXmlWordProc.Paragraph(
new OpenXmlWordProc.ParagraphProperties()
{
NumberingProperties = new OpenXmlWordProc.NumberingProperties()
{
NumberingLevelReference = new OpenXmlWordProc.NumberingLevelReference() { Val = 0 },
NumberingId = new OpenXmlWordProc.NumberingId() { Val = 100 }
}
},
new OpenXmlWordProc.Run(
new OpenXmlWordProc.Text("This is line A")
)
);
body.Append(P);
// Line B
P = new OpenXmlWordProc.Paragraph(
new OpenXmlWordProc.ParagraphProperties()
{
NumberingProperties = new OpenXmlWordProc.NumberingProperties()
{
NumberingLevelReference = new OpenXmlWordProc.NumberingLevelReference() { Val = 0 },
NumberingId = new OpenXmlWordProc.NumberingId() { Val = 100 }
}
},
new OpenXmlWordProc.Run(
new OpenXmlWordProc.Text("This is line B")
)
);
body.Append(P);
// Create a numbering (id:101) based on an abstract-numbering (id:201)
_addAbstractNumbering(mainPart, 201);
_addNumbering(mainPart, iNumberId: 101, iAbstractNumberingId: 201); // <-- Remove these lines and it works!!!
// Line C
P = new OpenXmlWordProc.Paragraph(
new OpenXmlWordProc.ParagraphProperties()
{
NumberingProperties = new OpenXmlWordProc.NumberingProperties()
{
NumberingLevelReference = new OpenXmlWordProc.NumberingLevelReference() { Val = 0 },
NumberingId = new OpenXmlWordProc.NumberingId() { Val = 101 }
}
},
new OpenXmlWordProc.Run(
new OpenXmlWordProc.Text("This is line C")
)
);
body.Append(P);
}
//
File.WriteAllBytes("E:\\test-word.docx", ms.ToArray());
}
//
Console.WriteLine("Application: Exit");
/////////////////////////////////////////////////////////////////////
// Functions
void _addAbstractNumbering(OpenXmlPackaging.MainDocumentPart mainPart, int iAbstractNumberingId)
{
//
OpenXmlWordProc.Level ___buildLevel(int iLevel)
{
//
int[] IndentationLefts = { 360, 792, 1224, 1728, 2232, 2736 };
int[] IndentationHangings = { 360, 432, 504, 648, 792, 936 };
//
StringBuilder sbFormat = new StringBuilder();
for (int i1 = 0; i1 <= iLevel; i1++)
sbFormat.Append($"%{i1 + 1}.");
//
OpenXmlWordProc.Level level = new OpenXmlWordProc.Level()
{
LevelIndex = iLevel,
NumberingFormat = new OpenXmlWordProc.NumberingFormat { Val = OpenXmlWordProc.NumberFormatValues.Decimal },
LevelText = new OpenXmlWordProc.LevelText() { Val = sbFormat.ToString() },
LevelJustification = new OpenXmlWordProc.LevelJustification() { Val = OpenXmlWordProc.LevelJustificationValues.Left },
StartNumberingValue = new OpenXmlWordProc.StartNumberingValue() { Val = 1 },
LevelSuffix = new OpenXmlWordProc.LevelSuffix() { Val = OpenXmlWordProc.LevelSuffixValues.Space },
PreviousParagraphProperties = new OpenXmlWordProc.PreviousParagraphProperties()
{
Indentation = new OpenXmlWordProc.Indentation() { Left = IndentationLefts[iLevel].ToString(), Hanging = IndentationHangings[iLevel].ToString() }
}
};
//
if (iLevel == 0)
{
// Make the top level bold
level.NumberingSymbolRunProperties = new OpenXmlWordProc.NumberingSymbolRunProperties()
{
Bold = new OpenXmlWordProc.Bold()
};
}
//
return level;
}
//
ArgumentNullException.ThrowIfNull(mainPart.NumberingDefinitionsPart);
ArgumentNullException.ThrowIfNull(mainPart.NumberingDefinitionsPart.Numbering);
//
OpenXmlWordProc.AbstractNum abstractNum = new OpenXmlWordProc.AbstractNum()
{
AbstractNumberId = iAbstractNumberingId,
MultiLevelType = new OpenXmlWordProc.MultiLevelType { Val = OpenXmlWordProc.MultiLevelValues.Multilevel }
};
for (int iLevel = 0; iLevel <= 5; iLevel++)
abstractNum.Append(___buildLevel(iLevel));
// This line does not seem to make any difference
//abstractNum.SetAttribute(new OpenXml.OpenXmlAttribute("w15", "restartNumberingAfterBreak", ";, "0"));
//
mainPart.NumberingDefinitionsPart.Numbering.Append(abstractNum);
//
Console.WriteLine($"Created AbstractNum with AbstractNumId:{abstractNum.AbstractNumberId}");
}
void _addNumbering(OpenXmlPackaging.MainDocumentPart mainPart, int iNumberId, int iAbstractNumberingId)
{
//
ArgumentNullException.ThrowIfNull(mainPart.NumberingDefinitionsPart);
ArgumentNullException.ThrowIfNull(mainPart.NumberingDefinitionsPart.Numbering);
//
OpenXmlWordProc.NumberingInstance numberingInstance = new OpenXmlWordProc.NumberingInstance
{
NumberID = iNumberId,
AbstractNumId = new OpenXmlWordProc.AbstractNumId { Val = iAbstractNumberingId }
};
mainPart.NumberingDefinitionsPart.Numbering.Append(numberingInstance);
//
#if DEBUG
System.Diagnostics.Trace.WriteLine($"Created NumberingInstance with NumberId:{numberingInstance.NumberID} and AbstractNumId:{numberingInstance.AbstractNumId.Val}");
#endif // #if DEBUG
}
If you want to run this code, you will need to install Microsoft's DocumentFormat.OpenXml in the NuGet package manager.
This code creates a Word document with three lines, all three are numbered. For the last of the three lines, the numbering is changed to force a reset of the numbering, but this does not work.
If I comment out the calls to _addNumbering, the numbering does reset, just not with the numbering layout defined in the abstract numbering.