777
This commit is contained in:
@@ -180,7 +180,6 @@ internal static class MultiReplaceExt
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Клонирует параграф, удаляя все SectionProperties и PageBreakBefore.</summary>
|
||||
private static Paragraph CloneParagraphWithoutSection(Paragraph original)
|
||||
{
|
||||
var newPara = new Paragraph();
|
||||
@@ -367,13 +366,12 @@ internal static class MultiReplaceExt
|
||||
if (!(sourceIsLandscape && sectionChangeInsideGroup && lastIsPortrait))
|
||||
return;
|
||||
|
||||
foreach (var bodySec in body.Elements<SectionProperties>())
|
||||
{
|
||||
var ps = bodySec.GetFirstChild<PageSize>();
|
||||
if (ps is not null && ps.Orient?.Value == PageOrientationValues.Landscape)
|
||||
return;
|
||||
}
|
||||
// Удаляем все существующие секции из Body
|
||||
var existingSections = body.Elements<SectionProperties>().ToList();
|
||||
foreach (var sec in existingSections)
|
||||
sec.Remove();
|
||||
|
||||
// Создаём новую landscape секцию для Body
|
||||
var bodySection = new SectionProperties();
|
||||
var pageSizeClone = (PageSize)sourcePageSize.CloneNode(true);
|
||||
if (pageSizeClone.Orient?.Value != PageOrientationValues.Landscape)
|
||||
@@ -404,7 +402,6 @@ internal static class MultiReplaceExt
|
||||
|
||||
// ---------- ОСНОВНОЙ АЛГОРИТМ ----------
|
||||
|
||||
/// <summary>Основной алгоритм множественной замены с поддержкой разрывов и смены ориентации.</summary>
|
||||
private static List<Paragraph>? ProcessMultiReplacements(
|
||||
Paragraph original,
|
||||
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? stringReplacements,
|
||||
@@ -424,6 +421,22 @@ internal static class MultiReplaceExt
|
||||
prevPara = prevPara.PreviousSibling<Paragraph>();
|
||||
}
|
||||
|
||||
// Определяем секцию, которая следует за original (если у original нет секции)
|
||||
SectionProperties? followingSection = null;
|
||||
if (original.ParagraphProperties?.GetFirstChild<SectionProperties>()?.CloneNode(true) is not SectionProperties sourceSection)
|
||||
{
|
||||
var nextPara = original.NextSibling<Paragraph>();
|
||||
if (nextPara is not null)
|
||||
{
|
||||
followingSection = nextPara.ParagraphProperties?.GetFirstChild<SectionProperties>()?.CloneNode(true) as SectionProperties;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
followingSection = sourceSection;
|
||||
}
|
||||
followingSection ??= new SectionProperties();
|
||||
|
||||
// 1. Сбор определений
|
||||
var definitions = new List<MatchDefinition>();
|
||||
if (stringReplacements is not null)
|
||||
@@ -471,14 +484,7 @@ internal static class MultiReplaceExt
|
||||
if (matches.Count == 0) return null;
|
||||
matches.Sort((a, b) => a.Start.CompareTo(b.Start));
|
||||
|
||||
// 4. Получаем исходную секцию для копирования (из original или из документа)
|
||||
SectionProperties? sourceSection = original.ParagraphProperties?.GetFirstChild<SectionProperties>()?.CloneNode(true) as SectionProperties;
|
||||
if (sourceSection is null && body is not null)
|
||||
{
|
||||
sourceSection = body.Elements<SectionProperties>().LastOrDefault()?.CloneNode(true) as SectionProperties;
|
||||
}
|
||||
sourceSection ??= new SectionProperties();
|
||||
|
||||
// 4. Получаем книжную секцию для копирования полей (из документа)
|
||||
SectionProperties? portraitSection = null;
|
||||
if (body is not null)
|
||||
{
|
||||
@@ -539,6 +545,29 @@ internal static class MultiReplaceExt
|
||||
var values = match.Definition.Values.ToList();
|
||||
if (values.Count == 0) continue;
|
||||
|
||||
// Если это простая замена текста (один элемент и это текст без маркеров),
|
||||
// заменяем текст внутри параграфа, сохраняя все остальные элементы
|
||||
if (values.Count == 1 && !string.IsNullOrEmpty(values[0].Text) && !values[0].BreakValue.HasValue)
|
||||
{
|
||||
// Простая замена текста в текущем параграфе
|
||||
var newText = values[0].Text;
|
||||
// Находим сегмент с совпадением
|
||||
var matchSeg = structure.Segments.FirstOrDefault(s => s.Start >= match.Start && s.End <= match.End);
|
||||
if (matchSeg is not null)
|
||||
{
|
||||
// Заменяем текст в Run
|
||||
var run = matchSeg.Run;
|
||||
// Удаляем все Text элементы
|
||||
foreach (var textElem in run.Elements<Text>().ToList())
|
||||
textElem.Remove();
|
||||
// Добавляем новый Text
|
||||
run.AppendChild(new Text(newText));
|
||||
// Возвращаем null, чтобы не заменять параграф
|
||||
return null;
|
||||
}
|
||||
// Если не нашли сегмент, продолжаем обычную обработку
|
||||
}
|
||||
|
||||
// Сбрасываем флаги для новой группы
|
||||
pageBreakBeforeNext = false;
|
||||
pendingOrientation = null;
|
||||
@@ -563,7 +592,7 @@ internal static class MultiReplaceExt
|
||||
original,
|
||||
structure,
|
||||
match.Start,
|
||||
sourceSection,
|
||||
followingSection,
|
||||
portraitSection,
|
||||
resultParas);
|
||||
}
|
||||
@@ -582,7 +611,7 @@ internal static class MultiReplaceExt
|
||||
ref emptyParagraphCreated,
|
||||
hasEmptyParagraphsBefore,
|
||||
original,
|
||||
sourceSection,
|
||||
followingSection,
|
||||
portraitSection,
|
||||
resultParas);
|
||||
}
|
||||
@@ -594,26 +623,26 @@ internal static class MultiReplaceExt
|
||||
if (currentPara.ParagraphProperties?.GetFirstChild<SectionProperties>() is null)
|
||||
{
|
||||
bool addPageSize = (lastOrientation.Value == BreakType.NewLandscapeSection);
|
||||
AddSectionProperties(currentPara, lastOrientation.Value, addPageSize, sourceSection, portraitSection);
|
||||
AddSectionProperties(currentPara, lastOrientation.Value, addPageSize, followingSection, portraitSection);
|
||||
}
|
||||
}
|
||||
|
||||
// Если внутри группы не было смены, но есть sourceSection с PageSize,
|
||||
// Если внутри группы не было смены, но есть followingSection с PageSize,
|
||||
// копируем её в последний параграф группы (если он не имеет секции)
|
||||
if (!sectionChangeInsideGroup && currentPara is not null)
|
||||
{
|
||||
var sourcePageSize = sourceSection.GetFirstChild<PageSize>();
|
||||
var sourcePageSize = followingSection.GetFirstChild<PageSize>();
|
||||
if (sourcePageSize is not null)
|
||||
{
|
||||
if (currentPara.ParagraphProperties?.GetFirstChild<SectionProperties>() is null)
|
||||
{
|
||||
currentPara.ParagraphProperties ??= new ParagraphProperties();
|
||||
currentPara.ParagraphProperties.AppendChild(sourceSection.CloneNode(true));
|
||||
currentPara.ParagraphProperties.AppendChild(followingSection.CloneNode(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EnsureBodyLandscapeSection(body!, sourceSection, sectionChangeInsideGroup, lastOrientation);
|
||||
EnsureBodyLandscapeSection(body!, followingSection, sectionChangeInsideGroup, lastOrientation);
|
||||
|
||||
currentPos = match.End;
|
||||
}
|
||||
@@ -630,7 +659,7 @@ internal static class MultiReplaceExt
|
||||
var breakRun = new Run(new Break { Type = BreakValues.Page });
|
||||
remainderPara.InsertAt(breakRun, 0);
|
||||
bool addPageSize = (pendingOrientation.Value == BreakType.NewLandscapeSection);
|
||||
AddSectionProperties(remainderPara, pendingOrientation.Value, addPageSize, sourceSection, portraitSection);
|
||||
AddSectionProperties(remainderPara, pendingOrientation.Value, addPageSize, followingSection, portraitSection);
|
||||
pendingOrientation = null;
|
||||
}
|
||||
else if (sectionChangeInsideGroup && lastOrientation.HasValue)
|
||||
@@ -638,16 +667,16 @@ internal static class MultiReplaceExt
|
||||
var breakRun = new Run(new Break { Type = BreakValues.Page });
|
||||
remainderPara.InsertAt(breakRun, 0);
|
||||
bool addPageSize = (lastOrientation.Value == BreakType.NewLandscapeSection);
|
||||
AddSectionProperties(remainderPara, lastOrientation.Value, addPageSize, sourceSection, portraitSection);
|
||||
AddSectionProperties(remainderPara, lastOrientation.Value, addPageSize, followingSection, portraitSection);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Если нет смены, но есть sourceSection с PageSize, копируем её в остаток
|
||||
var sourcePageSize = sourceSection.GetFirstChild<PageSize>();
|
||||
// Если нет смены, но есть followingSection с PageSize, копируем её в остаток
|
||||
var sourcePageSize = followingSection.GetFirstChild<PageSize>();
|
||||
if (sourcePageSize is not null)
|
||||
{
|
||||
remainderPara.ParagraphProperties ??= new ParagraphProperties();
|
||||
remainderPara.ParagraphProperties.AppendChild(sourceSection.CloneNode(true));
|
||||
remainderPara.ParagraphProperties.AppendChild(followingSection.CloneNode(true));
|
||||
}
|
||||
}
|
||||
resultParas.Add(remainderPara);
|
||||
@@ -679,7 +708,7 @@ internal static class MultiReplaceExt
|
||||
Paragraph original,
|
||||
ParagraphStructure structure,
|
||||
int position,
|
||||
SectionProperties sourceSection,
|
||||
SectionProperties followingSection,
|
||||
SectionProperties portraitSection,
|
||||
List<Paragraph> resultParas)
|
||||
{
|
||||
@@ -690,7 +719,7 @@ internal static class MultiReplaceExt
|
||||
currentPara = newPara;
|
||||
|
||||
bool addPageSize = (pendingOrientation.Value == BreakType.NewLandscapeSection);
|
||||
AddSectionProperties(currentPara, pendingOrientation.Value, addPageSize, sourceSection, portraitSection);
|
||||
AddSectionProperties(currentPara, pendingOrientation.Value, addPageSize, followingSection, portraitSection);
|
||||
lastOrientation = pendingOrientation;
|
||||
sectionChangeInsideGroup = true;
|
||||
pendingOrientation = null;
|
||||
@@ -738,7 +767,7 @@ internal static class MultiReplaceExt
|
||||
ref bool emptyParagraphCreated,
|
||||
bool hasEmptyParagraphsBefore,
|
||||
Paragraph original,
|
||||
SectionProperties sourceSection,
|
||||
SectionProperties followingSection,
|
||||
SectionProperties portraitSection,
|
||||
List<Paragraph> resultParas)
|
||||
{
|
||||
@@ -764,7 +793,7 @@ internal static class MultiReplaceExt
|
||||
var newPara = CloneParagraphWithoutSection(original);
|
||||
resultParas.Add(newPara);
|
||||
currentPara = newPara;
|
||||
AddSectionProperties(currentPara, breakType, false, sourceSection, portraitSection);
|
||||
AddSectionProperties(currentPara, breakType, false, followingSection, portraitSection);
|
||||
lastOrientation = breakType;
|
||||
sectionChangeInsideGroup = true;
|
||||
firstSplitMarkerHandled = true;
|
||||
@@ -788,14 +817,14 @@ internal static class MultiReplaceExt
|
||||
{
|
||||
lastTextPara.ParagraphProperties ??= new ParagraphProperties();
|
||||
|
||||
var sourcePageSize = sourceSection.GetFirstChild<PageSize>();
|
||||
var sourcePageSize = followingSection.GetFirstChild<PageSize>();
|
||||
if (sourcePageSize is not null)
|
||||
{
|
||||
lastTextPara.ParagraphProperties.AppendChild(sourceSection.CloneNode(true));
|
||||
lastTextPara.ParagraphProperties.AppendChild(followingSection.CloneNode(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
AddSectionProperties(lastTextPara, breakType, false, sourceSection, portraitSection);
|
||||
AddSectionProperties(lastTextPara, breakType, false, followingSection, portraitSection);
|
||||
}
|
||||
lastOrientation = breakType;
|
||||
sectionChangeInsideGroup = true;
|
||||
@@ -805,7 +834,7 @@ internal static class MultiReplaceExt
|
||||
}
|
||||
else
|
||||
{
|
||||
AddSectionProperties(currentPara, breakType, false, sourceSection, portraitSection);
|
||||
AddSectionProperties(currentPara, breakType, false, followingSection, portraitSection);
|
||||
lastOrientation = breakType;
|
||||
sectionChangeInsideGroup = true;
|
||||
firstSplitMarkerHandled = true;
|
||||
|
||||
Reference in New Issue
Block a user