admin管理员组文章数量:1333428
I am trying to manipulate numbering sequences in a Word document using the Open XML SDK. Specifically, I am working on updating the numbering for paragraphs that reference a NumberingInstance. However, I am encountering issues when updating the NumberID for specific paragraphs.
Problem Description:I have a set of paragraphs in a Word document, and I want to update their numbering properties. Each paragraph has a NumberingId which links it to a specific NumberingInstance. I am attempting to update the NumberID based on certain conditions, but the numbering is not updating correctly in some cases.It is changing numaric lists to bulleting and bulleting to numaric
I am using the following approach to update the NumberID:
private static List<(int SubTaskId, int OldNumberId, AbstractNum NewAbstractNum, NumberingInstance NewNumberingInstance)>
GetAllNumberingInstancesWithUpdatedSubtaskSummaries(Dictionary<string, List<(int SubtaskId, List<Paragraph> Paragraphs, Numbering Numbering)>> rorReportDataContents)
{
List<(int SubTaskId, int OldNumberId, AbstractNum NewAbstractNum, NumberingInstance NewNumberingInstance)> result = new();
foreach (var content in rorReportDataContents)
{
foreach (var item in content.Value.Where(x => x.Numbering is not null))
{
List<AbstractNum> abstractNumList = item.Numbering.Descendants<AbstractNum>().ToList();
List<NumberingInstance> numberingInstances = item.Numbering.Descendants<NumberingInstance>().ToList();
List<(AbstractNum AbstractNum, NumberingInstance NumberingInstance)> groupedData = (from abstractNum in abstractNumList
join numbering in numberingInstances
on abstractNum.AbstractNumberId equals numbering.AbstractNumId.Val
select (abstractNum, numbering)).ToList();
List<Paragraph> paragraphs = item.Paragraphs.Where(x => x.ParagraphProperties is not null).ToList();
foreach (var paragraph in paragraphs)
{
NumberingProperties numberingProperties = paragraph.ParagraphProperties.Descendants<NumberingProperties>().FirstOrDefault();
if (numberingProperties is null) continue;
NumberingId numberingId = numberingProperties.Descendants<NumberingId>().FirstOrDefault();
if (numberingId is null) continue;
int numberingValue = numberingId.Val;
if (!result.Exists(x => x.SubTaskId == item.SubtaskId && x.OldNumberId == numberingValue))
{
var numbering = groupedData.Find(x => x.NumberingInstance.NumberID == numberingValue);
if (numbering.AbstractNum != null && numbering.NumberingInstance != null)
{
numbering.AbstractNum.AbstractNumberId = result.Count + 1;
numbering.NumberingInstance.AbstractNumId.Val = result.Count + 1;
numbering.NumberingInstance.NumberID = result.Count + 1;
numbering.AbstractNum.Parent?.RemoveAllChildren();
numbering.NumberingInstance.Parent?.RemoveAllChildren();
result.Add((item.SubtaskId, OldNumberId: numberingValue, numbering.AbstractNum, numbering.NumberingInstance));
}
}
}
}
}
return result;
}
public MemoryStream ReplaceRorReportContents(MemoryStream documentStream, Dictionary<string, List<(int subtaskId, List<Paragraph> paragraphs, Numbering numbering)>> rorReportDataContents, bool deleteMiscNote, bool deleteAmendmentNote)
{
documentStream.Position = 0L;
using WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentStream, true);
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
List<Run> runs = mainPart.Document.Body.Descendants<Run>().ToList();
List<Paragraph> paragraphs = mainPart.RootElement.Descendants<Paragraph>().Where(x => !string.IsNullOrEmpty(x.InnerText)).ToList();
List<(Run Run, string Text)> runTexts = runs.Where(x => x.RunProperties is not null
&& x.RunProperties.Bold is not null
&& !string.IsNullOrEmpty(x.InnerText)
&& x.InnerText.Contains('#')).Select(x => (x, x.InnerText)).ToList();
Dictionary<string, string> documentTags = [];
runTexts.ForEach(x =>
{
MatchCollection matches = Regex.Matches(x.Text, "#([^#]*)#");
foreach (Match match in matches.Cast<Match>())
{
string matchValue = match.Groups[0].Value;
if (matchValue.Contains('$'))
{
int startIndex = matchValue.IndexOf('$');
int lastIndex = matchValue.LastIndexOf('#');
string stylingProperties = matchValue[startIndex..lastIndex];
string docTag = matchValue.Replace(stylingProperties, string.Empty);
_ = x.Text.Replace(matchValue, docTag);
_ = documentTags.TryAdd(docTag, stylingProperties.Replace("$", string.Empty));
}
else
{
_ = documentTags.TryAdd(matchValue, string.Empty);
}
}
});
IEnumerable<string> extraDocumentTags = rorReportDataContents.Keys.Except(documentTags.Keys);
List<Run> tobeRemovedRuns = runTexts.Where(x => extraDocumentTags.Contains(x.Text)).Select(x => x.Run).ToList();
tobeRemovedRuns.ForEach(run => run.Remove());
DeleteMiscAndAmendmentNoteSection(runs, deleteMiscNote, deleteAmendmentNote);
KeyValuePair<string, string> miscTag = RoRReportMasterTags.TagNameSyntaxPair.First(x => x.Key == RoRReportMasterTagNameConstants.MiscSection);
IEnumerable<OpenXmlPart> parts = wordDoc.GetAllParts();
NumberingDefinitionsPart numberingPart = parts.OfType<NumberingDefinitionsPart>().FirstOrDefault();
numberingPart ??= wordDoc.MainDocumentPart.AddNewPart<NumberingDefinitionsPart>();
numberingPart.Numbering ??= new Numbering();
List<(int SubTaskId, int oldNumberId, AbstractNum newAbstractNum, NumberingInstance newNumberingInstance)> numberingInstances = GetAllNumberingInstancesWithUpdatedSubtaskSummaries(rorReportDataContents);
foreach (var numberingInstance in numberingInstances)
{
numberingInstance.newAbstractNum.Parent?.RemoveAllChildren();
numberingInstance.newNumberingInstance.Parent?.RemoveAllChildren();
numberingPart.Numbering.Append(numberingInstance.newAbstractNum, numberingInstance.newNumberingInstance);
}
NumberingFormat miscNumberingFormat = GetNumberingFormat(documentTags.GetValueOrDefault(miscTag.Value));
int lastAbstractNumId = numberingInstances.Count != 0 ? numberingInstances.Max(x => x.newAbstractNum.AbstractNumberId) : 0;
int miscAbstractNumId = lastAbstractNumId + 1;
(AbstractNum miscAbstractNum, NumberingInstance miscNumberingInstance) = CreateAbstractNumberingDefinition(miscNumberingFormat, miscAbstractNumId);
numberingPart.Numbering.Append(miscAbstractNum, miscNumberingInstance);
foreach (KeyValuePair<string, List<(int subtaskId, List<Paragraph> paragraphs, Numbering numbering)>> item in rorReportDataContents)
{
Paragraph originalParagraph = paragraphs.Find(x => x.InnerText.Contains(item.Key.Replace("#", string.Empty)));
List<string> texts = paragraphs.Select(x => x.InnerText).ToList();
if (originalParagraph is not null)
{
Paragraph currentElement = originalParagraph;
if (originalParagraph.InnerText.Contains(miscTag.Value.Replace("#", string.Empty)))
{
originalParagraph.RemoveAllChildren();
foreach (Paragraph paragraph in item.Value.SelectMany(x => x.paragraphs))
{
_ = paragraph.Parent?.RemoveChild(paragraph);
ParagraphProperties paragraphProperties = paragraph.Descendants().OfType<ParagraphProperties>().FirstOrDefault();
// Adjust line spacing for paragraphs with bullets
//if (HasBullets(paragraph))
//{
//}
_ = paragraphProperties is null
? paragraph.AddChild(new ParagraphProperties(new NumberingProperties(
new NumberingLevelReference { Val = 0 },
new NumberingId { Val = miscAbstractNumId }
)))
: paragraph.ParagraphProperties.AddChild(new NumberingProperties(
new NumberingLevelReference { Val = 0 },
new NumberingId { Val = miscAbstractNumId }
));
//AdjustLineSpacing(paragraph);
Paragraph insteredElement = currentElement.InsertAfterSelf(paragraph);
currentElement = insteredElement;
}
}
else
{
originalParagraph.RemoveAllChildren();
foreach ((int subtaskId, List<Paragraph> paragraphs, Numbering numbering) content in item.Value)
{
foreach (Paragraph paragraph in content.paragraphs)
{
_ = paragraph.Parent?.RemoveChild(paragraph);
NumberingProperties numberingProperties = paragraph.ParagraphProperties?.Descendants<NumberingProperties>().FirstOrDefault();
NumberingId numberingId = numberingProperties?.Descendants<NumberingId>().FirstOrDefault();
if (numberingId is not null)
{
int numberId = numberingId.Val;
//int newNumberingId = numberingInstances.First(x => x.SubTaskId == content.subtaskId
// && x.oldNumberId == numberId)
// .newNumberingInstance.NumberID;
var matchingInstance = numberingInstances.FirstOrDefault(x => x.SubTaskId == content.subtaskId
&& x.oldNumberId == numberId);
if (matchingInstance.SubTaskId != 0)
{
int newNumberingId = matchingInstance.newNumberingInstance.NumberID;
// Use newNumberingId as needed
paragraph.ParagraphProperties.Descendants<NumberingProperties>().First().Descendants<NumberingId>().First().Val = newNumberingId;
}
//else
//{
//}
}
Paragraph insteredElement = currentElement.InsertAfterSelf(paragraph);
currentElement = insteredElement;
}
}
}
originalParagraph.Remove();
}
mainPart.Document.Save();
}
documentStream.Position = 0L;
return documentStream;
}
private static (AbstractNum abstractNum, NumberingInstance numberingInstance) CreateAbstractNumberingDefinition(NumberingFormat numberingFormat, int abstractNumId)
{
AbstractNum abstractNum = new(
new Level(
// StartNumberingValue indicates the starting value of the numbering
new StartNumberingValue { Val = 1 },
new LevelJustification { Val = LevelJustificationValues.Center },
// NumberingFormat specifies the numbering format (e.g., decimal, lowerLetter)
numberingFormat,
// LevelText defines the level text (e.g., "%1." for decimal numbering)
new LevelText { Val = "%1•" },
//new Indentation { Left = "0"},
new NumberingSymbolRunProperties
{
Bold = new Bold(),
FontSize = new FontSize() { Val = "25" }
//Spacing = new Spacing { Val = 10},
//Position = new Position { Val = "5" },
},
new ParagraphProperties(
new Indentation { Left = "720", Hanging = "360" }
),
new SpacingBetweenLines { LineRule = LineSpacingRuleValues.Exact }
)
{ LevelIndex = 0 }
)
{ AbstractNumberId = abstractNumId };
NumberingInstance numberingInstance = new(
new AbstractNumId { Val = abstractNum.AbstractNumberId }
)
{ NumberID = abstractNum.AbstractNumberId };
return (abstractNum, numberingInstance);
}
private static NumberingFormat GetNumberingFormat(string numberingTypeValue)
{
_ = Enum.TryParse(numberingTypeValue, true, out NumberingType numberingType);
return numberingType switch
{
NumberingType.None => new NumberingFormat { Val = NumberFormatValues.None },
NumberingType.Bullets => new NumberingFormat { Val = NumberFormatValues.Bullet },
NumberingType.Numeric => new NumberingFormat { Val = NumberFormatValues.Decimal },
NumberingType.LowerAlphabetical => new NumberingFormat { Val = NumberFormatValues.LowerLetter },
NumberingType.UpperAlphabetical => new NumberingFormat { Val = NumberFormatValues.UpperLetter },
_ => throw new NotImplementedException()
};
}
本文标签:
版权声明:本文标题:c# - Issue with Updating Numbering and bulleting in Word Document Using Open XML SDK (NumberID Assignment) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742295417a2448627.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论