Я пытаюсь манипулировать последовательностями нумерации в документе Word с помощью Open XML SDK. В частности, я работаю над обновлением нумерации абзацев, ссылающихся на NumberingInstance. Однако я сталкиваюсь с проблемами при обновлении NumberID для определенных абзацев.
Описание проблемы. У меня есть набор абзацев в документе Word, и я хочу обновить их свойства нумерации. Каждый абзац имеет NumberingId, который связывает его с определенным экземпляром NumberingInstance. Я пытаюсь обновить NumberID на основе определенных условий, но в некоторых случаях нумерация не обновляется правильно. Числовые списки заменяются на маркированные, а маркированные на числовые.
Я использую следующее подход к обновлению NumberID:
private static List
GetAllNumberingInstancesWithUpdatedSubtaskSummaries(Dictionary rorReportDataContents)
{
List result = new();
foreach (var content in rorReportDataContents)
{
foreach (var item in content.Value.Where(x => x.Numbering is not null))
{
List abstractNumList = item.Numbering.Descendants().ToList();
List numberingInstances = item.Numbering.Descendants().ToList();
List groupedData = (from abstractNum in abstractNumList
join numbering in numberingInstances
on abstractNum.AbstractNumberId equals numbering.AbstractNumId.Val
select (abstractNum, numbering)).ToList();
List paragraphs = item.Paragraphs.Where(x => x.ParagraphProperties is not null).ToList();
foreach (var paragraph in paragraphs)
{
NumberingProperties numberingProperties = paragraph.ParagraphProperties.Descendants().FirstOrDefault();
if (numberingProperties is null) continue;
NumberingId numberingId = numberingProperties.Descendants().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 rorReportDataContents, bool deleteMiscNote, bool deleteAmendmentNote)
{
documentStream.Position = 0L;
using WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentStream, true);
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
List runs = mainPart.Document.Body.Descendants().ToList();
List paragraphs = mainPart.RootElement.Descendants().Where(x => !string.IsNullOrEmpty(x.InnerText)).ToList();
List 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 documentTags = [];
runTexts.ForEach(x =>
{
MatchCollection matches = Regex.Matches(x.Text, "#([^#]*)#");
foreach (Match match in matches.Cast())
{
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 extraDocumentTags = rorReportDataContents.Keys.Except(documentTags.Keys);
List tobeRemovedRuns = runTexts.Where(x => extraDocumentTags.Contains(x.Text)).Select(x => x.Run).ToList();
tobeRemovedRuns.ForEach(run => run.Remove());
DeleteMiscAndAmendmentNoteSection(runs, deleteMiscNote, deleteAmendmentNote);
KeyValuePair miscTag = RoRReportMasterTags.TagNameSyntaxPair.First(x => x.Key == RoRReportMasterTagNameConstants.MiscSection);
IEnumerable parts = wordDoc.GetAllParts();
NumberingDefinitionsPart numberingPart = parts.OfType().FirstOrDefault();
numberingPart ??= wordDoc.MainDocumentPart.AddNewPart();
numberingPart.Numbering ??= new Numbering();
List 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 item in rorReportDataContents)
{
Paragraph originalParagraph = paragraphs.Find(x => x.InnerText.Contains(item.Key.Replace("#", string.Empty)));
List 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().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 paragraphs, Numbering numbering) content in item.Value)
{
foreach (Paragraph paragraph in content.paragraphs)
{
_ = paragraph.Parent?.RemoveChild(paragraph);
NumberingProperties numberingProperties = paragraph.ParagraphProperties?.Descendants().FirstOrDefault();
NumberingId numberingId = numberingProperties?.Descendants().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().First().Descendants().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()
};
}
Подробнее здесь: https://stackoverflow.com/questions/792 ... en-xml-sdk
Проблема с обновлением нумерации и маркировки в документе Word с использованием Open XML SDK (назначение NumberID) ⇐ C#
Место общения программистов C#
1732254058
Anonymous
Я пытаюсь манипулировать последовательностями нумерации в документе Word с помощью Open XML SDK. В частности, я работаю над обновлением нумерации абзацев, ссылающихся на NumberingInstance. Однако я сталкиваюсь с проблемами при обновлении NumberID для определенных абзацев.
Описание проблемы. У меня есть набор абзацев в документе Word, и я хочу обновить их свойства нумерации. Каждый абзац имеет NumberingId, который связывает его с определенным экземпляром NumberingInstance. Я пытаюсь обновить NumberID на основе определенных условий, но в некоторых случаях нумерация не обновляется правильно. Числовые списки заменяются на маркированные, а маркированные на числовые.
Я использую следующее подход к обновлению NumberID:
private static List
GetAllNumberingInstancesWithUpdatedSubtaskSummaries(Dictionary rorReportDataContents)
{
List result = new();
foreach (var content in rorReportDataContents)
{
foreach (var item in content.Value.Where(x => x.Numbering is not null))
{
List abstractNumList = item.Numbering.Descendants().ToList();
List numberingInstances = item.Numbering.Descendants().ToList();
List groupedData = (from abstractNum in abstractNumList
join numbering in numberingInstances
on abstractNum.AbstractNumberId equals numbering.AbstractNumId.Val
select (abstractNum, numbering)).ToList();
List paragraphs = item.Paragraphs.Where(x => x.ParagraphProperties is not null).ToList();
foreach (var paragraph in paragraphs)
{
NumberingProperties numberingProperties = paragraph.ParagraphProperties.Descendants().FirstOrDefault();
if (numberingProperties is null) continue;
NumberingId numberingId = numberingProperties.Descendants().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 rorReportDataContents, bool deleteMiscNote, bool deleteAmendmentNote)
{
documentStream.Position = 0L;
using WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentStream, true);
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
List runs = mainPart.Document.Body.Descendants().ToList();
List paragraphs = mainPart.RootElement.Descendants().Where(x => !string.IsNullOrEmpty(x.InnerText)).ToList();
List 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 documentTags = [];
runTexts.ForEach(x =>
{
MatchCollection matches = Regex.Matches(x.Text, "#([^#]*)#");
foreach (Match match in matches.Cast())
{
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 extraDocumentTags = rorReportDataContents.Keys.Except(documentTags.Keys);
List tobeRemovedRuns = runTexts.Where(x => extraDocumentTags.Contains(x.Text)).Select(x => x.Run).ToList();
tobeRemovedRuns.ForEach(run => run.Remove());
DeleteMiscAndAmendmentNoteSection(runs, deleteMiscNote, deleteAmendmentNote);
KeyValuePair miscTag = RoRReportMasterTags.TagNameSyntaxPair.First(x => x.Key == RoRReportMasterTagNameConstants.MiscSection);
IEnumerable parts = wordDoc.GetAllParts();
NumberingDefinitionsPart numberingPart = parts.OfType().FirstOrDefault();
numberingPart ??= wordDoc.MainDocumentPart.AddNewPart();
numberingPart.Numbering ??= new Numbering();
List 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 item in rorReportDataContents)
{
Paragraph originalParagraph = paragraphs.Find(x => x.InnerText.Contains(item.Key.Replace("#", string.Empty)));
List 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().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 paragraphs, Numbering numbering) content in item.Value)
{
foreach (Paragraph paragraph in content.paragraphs)
{
_ = paragraph.Parent?.RemoveChild(paragraph);
NumberingProperties numberingProperties = paragraph.ParagraphProperties?.Descendants().FirstOrDefault();
NumberingId numberingId = numberingProperties?.Descendants().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().First().Descendants().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()
};
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79213765/issue-with-updating-numbering-and-bulleting-in-word-document-using-open-xml-sdk[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия