219 lines
8.8 KiB
C#
219 lines
8.8 KiB
C#
namespace QWERTYkez.WordProcessor;
|
|
|
|
/// <summary>
|
|
/// Множественные динамические замены с извлечением параметра из "$key|param$".
|
|
/// Переиспользует движок <see cref="MultiReplaceExt"/>
|
|
/// </summary>
|
|
internal static class DynamicMultiReplaceExt
|
|
{
|
|
// ============================================================
|
|
// ReplaceString (Func<string, IEnumerable<string>>)
|
|
// ============================================================
|
|
|
|
internal static void ReplaceStringMultiInBody(
|
|
Body body,
|
|
string oldValue,
|
|
Func<string, IEnumerable<string>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (body is null || factory is null) return;
|
|
DynamicReplaceExt.ParsePattern(oldValue, out var prefix, out var suffix);
|
|
|
|
var paragraphs = body.Elements<Paragraph>().ToList();
|
|
for (int i = paragraphs.Count - 1; i >= 0; i--)
|
|
ProcessDynamicStringMulti(paragraphs[i], prefix, suffix, factory, comparisonType);
|
|
}
|
|
|
|
internal static void ReplaceStringMultiInTables(
|
|
OpenXmlElement element,
|
|
string oldValue,
|
|
Func<string, IEnumerable<string>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (element is null || factory is null) return;
|
|
DynamicReplaceExt.ParsePattern(oldValue, out var prefix, out var suffix);
|
|
|
|
foreach (var table in TableTextProcessor.GetAllTables(element))
|
|
{
|
|
var paragraphs = TableTextProcessor.GetTableParagraphs(table).ToList();
|
|
for (int i = paragraphs.Count - 1; i >= 0; i--)
|
|
ProcessDynamicStringMulti(paragraphs[i], prefix, suffix, factory, comparisonType);
|
|
}
|
|
}
|
|
|
|
internal static void ReplaceStringMultiInHeadersFooters(
|
|
WordprocessingDocument doc,
|
|
string oldValue,
|
|
Func<string, IEnumerable<string>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (doc is null || factory is null) return;
|
|
DynamicReplaceExt.ParsePattern(oldValue, out var prefix, out var suffix);
|
|
|
|
foreach (var header in HeaderFooterProcessor.GetAllHeaders(doc))
|
|
ProcessStringMultiInElement(header, prefix, suffix, factory, comparisonType);
|
|
foreach (var footer in HeaderFooterProcessor.GetAllFooters(doc))
|
|
ProcessStringMultiInElement(footer, prefix, suffix, factory, comparisonType);
|
|
}
|
|
|
|
private static void ProcessStringMultiInElement(
|
|
OpenXmlElement element,
|
|
string prefix,
|
|
string suffix,
|
|
Func<string, IEnumerable<string>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
var paragraphs = element.Descendants<Paragraph>().ToList();
|
|
var tables = TableTextProcessor.GetAllTables(element).ToList();
|
|
var tableParagraphs = tables.SelectMany(t => TableTextProcessor.GetTableParagraphs(t)).ToList();
|
|
var allParagraphs = paragraphs.Concat(tableParagraphs).Distinct().ToList();
|
|
|
|
for (int i = allParagraphs.Count - 1; i >= 0; i--)
|
|
ProcessDynamicStringMulti(allParagraphs[i], prefix, suffix, factory, comparisonType);
|
|
}
|
|
|
|
private static void ProcessDynamicStringMulti(
|
|
Paragraph paragraph,
|
|
string prefix,
|
|
string suffix,
|
|
Func<string, IEnumerable<string>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (paragraph is null || paragraph.Parent is null) return;
|
|
|
|
var text = paragraph.InnerText;
|
|
if (string.IsNullOrEmpty(text)) return;
|
|
|
|
var matches = DynamicReplaceExt.FindMatches(text, prefix, suffix, comparisonType);
|
|
if (matches.Count == 0) return;
|
|
|
|
// Строим словарь уникальных matchedText -> значения для этого параграфа
|
|
var dict = new Dictionary<string, IEnumerable<string>>();
|
|
for (int i = 0; i < matches.Count; i++)
|
|
{
|
|
var m = matches[i];
|
|
string matchedText = text.Substring(m.Start, m.End - m.Start);
|
|
if (dict.ContainsKey(matchedText)) continue;
|
|
|
|
IEnumerable<string> values;
|
|
try { values = factory(m.Param); }
|
|
catch { continue; }
|
|
if (values is null) continue;
|
|
|
|
var list = values as IList<string> ?? [.. values];
|
|
if (list.Count == 0) continue;
|
|
|
|
dict[matchedText] = list;
|
|
}
|
|
if (dict.Count == 0) return;
|
|
|
|
var newParas = MultiReplaceExt.ProcessParagraphWithMergedBoundaries(paragraph, dict, comparisonType);
|
|
if (newParas is not null && newParas.Count > 0)
|
|
ParagraphReplacer.ReplaceParagraph(paragraph, newParas);
|
|
}
|
|
|
|
// ============================================================
|
|
// ReplaceItem (Func<string, IEnumerable<ReplaceItem>>)
|
|
// ============================================================
|
|
|
|
internal static void ReplaceItemMultiInBody(
|
|
Body body,
|
|
string oldValue,
|
|
Func<string, IEnumerable<ReplaceItem>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (body is null || factory is null) return;
|
|
DynamicReplaceExt.ParsePattern(oldValue, out var prefix, out var suffix);
|
|
|
|
var paragraphs = body.Elements<Paragraph>().ToList();
|
|
for (int i = paragraphs.Count - 1; i >= 0; i--)
|
|
ProcessDynamicItemMulti(paragraphs[i], prefix, suffix, factory, comparisonType);
|
|
}
|
|
|
|
internal static void ReplaceItemMultiInTables(
|
|
OpenXmlElement element,
|
|
string oldValue,
|
|
Func<string, IEnumerable<ReplaceItem>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (element is null || factory is null) return;
|
|
DynamicReplaceExt.ParsePattern(oldValue, out var prefix, out var suffix);
|
|
|
|
foreach (var table in TableTextProcessor.GetAllTables(element))
|
|
{
|
|
var paragraphs = TableTextProcessor.GetTableParagraphs(table).ToList();
|
|
for (int i = paragraphs.Count - 1; i >= 0; i--)
|
|
ProcessDynamicItemMulti(paragraphs[i], prefix, suffix, factory, comparisonType);
|
|
}
|
|
}
|
|
|
|
internal static void ReplaceItemMultiInHeadersFooters(
|
|
WordprocessingDocument doc,
|
|
string oldValue,
|
|
Func<string, IEnumerable<ReplaceItem>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (doc is null || factory is null) return;
|
|
DynamicReplaceExt.ParsePattern(oldValue, out var prefix, out var suffix);
|
|
|
|
foreach (var header in HeaderFooterProcessor.GetAllHeaders(doc))
|
|
ProcessItemMultiInElement(header, prefix, suffix, factory, comparisonType);
|
|
foreach (var footer in HeaderFooterProcessor.GetAllFooters(doc))
|
|
ProcessItemMultiInElement(footer, prefix, suffix, factory, comparisonType);
|
|
}
|
|
|
|
private static void ProcessItemMultiInElement(
|
|
OpenXmlElement element,
|
|
string prefix,
|
|
string suffix,
|
|
Func<string, IEnumerable<ReplaceItem>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
var paragraphs = element.Descendants<Paragraph>().ToList();
|
|
var tables = TableTextProcessor.GetAllTables(element).ToList();
|
|
var tableParagraphs = tables.SelectMany(t => TableTextProcessor.GetTableParagraphs(t)).ToList();
|
|
var allParagraphs = paragraphs.Concat(tableParagraphs).Distinct().ToList();
|
|
|
|
for (int i = allParagraphs.Count - 1; i >= 0; i--)
|
|
ProcessDynamicItemMulti(allParagraphs[i], prefix, suffix, factory, comparisonType);
|
|
}
|
|
|
|
private static void ProcessDynamicItemMulti(
|
|
Paragraph paragraph,
|
|
string prefix,
|
|
string suffix,
|
|
Func<string, IEnumerable<ReplaceItem>> factory,
|
|
StringComparison comparisonType)
|
|
{
|
|
if (paragraph is null || paragraph.Parent is null) return;
|
|
|
|
var text = paragraph.InnerText;
|
|
if (string.IsNullOrEmpty(text)) return;
|
|
|
|
var matches = DynamicReplaceExt.FindMatches(text, prefix, suffix, comparisonType);
|
|
if (matches.Count == 0) return;
|
|
|
|
var dict = new Dictionary<string, IEnumerable<ReplaceItem>>();
|
|
for (int i = 0; i < matches.Count; i++)
|
|
{
|
|
var m = matches[i];
|
|
string matchedText = text.Substring(m.Start, m.End - m.Start);
|
|
if (dict.ContainsKey(matchedText)) continue;
|
|
|
|
IEnumerable<ReplaceItem> values;
|
|
try { values = factory(m.Param); }
|
|
catch { continue; }
|
|
if (values is null) continue;
|
|
|
|
var list = values as IList<ReplaceItem> ?? [.. values];
|
|
if (list.Count == 0) continue;
|
|
|
|
dict[matchedText] = list;
|
|
}
|
|
if (dict.Count == 0) return;
|
|
|
|
var newParas = MultiReplaceExt.ProcessParagraphWithMergedBoundaries(paragraph, dict, comparisonType);
|
|
if (newParas is not null && newParas.Count > 0)
|
|
ParagraphReplacer.ReplaceParagraph(paragraph, newParas);
|
|
}
|
|
} |