Skip to content

Commit b2a9377

Browse files
committed
高级替换 <t>abs{</t><t>{</t> 测试文档
1 parent 3335129 commit b2a9377

3 files changed

Lines changed: 181 additions & 0 deletions

File tree

samples/docx/TestDemo04.docx

1.27 KB
Binary file not shown.
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
namespace MiniSoftware.Extensions
2+
{
3+
using DocumentFormat.OpenXml.Wordprocessing;
4+
using System;
5+
using System.Collections;
6+
using System.Collections.Generic;
7+
using System.ComponentModel;
8+
using System.Dynamic;
9+
using System.Linq;
10+
using System.Text;
11+
12+
internal static class OpenXmlExtension
13+
{
14+
/// <summary>
15+
/// 高级搜索:得到段落里面的连续字符串
16+
/// </summary>
17+
/// <param name="paragraph">段落</param>
18+
/// <returns>Item1:连续文本;Item2:块;Item3:块文本</returns>
19+
internal static List<Tuple<string, List<Run>, List<Text>>> GetContinuousString(this Paragraph paragraph)
20+
{
21+
List<Tuple<string, List<Run>, List<Text>>> tuples = new List<Tuple<string, List<Run>, List<Text>>>();
22+
if (paragraph == null)
23+
return tuples;
24+
25+
var sb = new StringBuilder();
26+
var runs = new List<Run>();
27+
var texts = new List<Text>();
28+
29+
//段落:所有子级
30+
foreach (var pChildElement in paragraph.ChildElements)
31+
{
32+
//块
33+
if (pChildElement is Run run)
34+
{
35+
//文本块
36+
if (run.IsText())
37+
{
38+
var text = run.GetFirstChild<Text>();
39+
runs.Add(run);
40+
texts.Add(text);
41+
sb.Append(text.InnerText);
42+
}
43+
else
44+
{
45+
if (runs.Any())
46+
tuples.Add(new Tuple<string, List<Run>, List<Text>>(sb.ToString(), runs, texts));
47+
48+
sb = new StringBuilder();
49+
runs = new List<Run>();
50+
texts = new List<Text>();
51+
}
52+
}
53+
//公式,书签...
54+
else
55+
{
56+
//跳过的类型
57+
if (pChildElement is BookmarkStart || pChildElement is BookmarkEnd)
58+
{
59+
60+
}
61+
else
62+
{
63+
if (runs.Any())
64+
tuples.Add(new Tuple<string, List<Run>, List<Text>>(sb.ToString(), runs, texts));
65+
66+
sb = new StringBuilder();
67+
runs = new List<Run>();
68+
texts = new List<Text>();
69+
}
70+
}
71+
}
72+
73+
if (runs.Any())
74+
tuples.Add(new Tuple<string, List<Run>, List<Text>>(sb.ToString(), runs, texts));
75+
76+
sb = new StringBuilder();
77+
runs = new List<Run>();
78+
texts = new List<Text>();
79+
80+
return tuples;
81+
}
82+
83+
/// <summary>
84+
/// 整理字符串到连续字符串块中
85+
/// </summary>
86+
/// <param name="texts">连续字符串块</param>
87+
/// <param name="text">待整理字符串</param>
88+
internal static void TrimStringToInContinuousString(this IEnumerable<Text> texts, string text)
89+
{
90+
/*
91+
//假如块为:[A][BC][DE][FG][H]
92+
//假如替换:[AB][E][GH]
93+
//优化块为:[AB][C][DE][FGH][]
94+
*/
95+
96+
var index = string.Concat(texts.SelectMany(o => o.Text)).IndexOf(text);
97+
if (index == -1)
98+
return;
99+
100+
int i = -1;
101+
int addLengg = 0;
102+
bool isbr = false;
103+
foreach (var textWord in texts)
104+
{
105+
if (addLengg > 0)
106+
{
107+
isbr = true;
108+
var leng = textWord.Text.Length;
109+
110+
if (addLengg - leng > 0)
111+
{
112+
addLengg -= leng;
113+
textWord.Text = "";
114+
}
115+
else if (addLengg - leng == 0)
116+
{
117+
textWord.Text = "";
118+
break;
119+
}
120+
else
121+
{
122+
textWord.Text = textWord.Text.Substring(addLengg);
123+
}
124+
}
125+
else if (isbr)
126+
{
127+
break;
128+
}
129+
else
130+
{
131+
i += textWord.Text.Length;
132+
//开始包含
133+
if (i >= index)
134+
{
135+
//全部包含
136+
if (textWord.Text.Contains(text))
137+
{
138+
break;
139+
}
140+
//部分包含
141+
else
142+
{
143+
var str1 = textWord.Text.Substring(0, i - index + 1);
144+
if (i == index)
145+
str1 = "";
146+
147+
var str2 = str1 + text;
148+
149+
addLengg = str2.Length - textWord.Text.Length;
150+
textWord.Text = str2;
151+
}
152+
}
153+
}
154+
}
155+
156+
}
157+
158+
159+
internal static bool IsText(this Run run)
160+
{
161+
return run.Elements().All(o => o is Text || o is RunProperties);
162+
}
163+
}
164+
}

src/MiniWord/MiniWord.Implment.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using DocumentFormat.OpenXml;
44
using DocumentFormat.OpenXml.Packaging;
55
using DocumentFormat.OpenXml.Wordprocessing;
6+
using MiniSoftware.Extensions;
67
using MiniSoftware.Utility;
78
using System;
89
using System.Collections;
@@ -43,6 +44,8 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum
4344
{
4445
// avoid {{tag}} like <t>{</t><t>{</t>
4546
AvoidSplitTagText(xmlElement);
47+
// avoid {{tag}} like <t>aa{</t><t>{</t> test in...
48+
//AvoidSplitTagText(xmlElement, tags.Select(o => "{{" + o.Key + "}}"));
4649

4750
//Tables
4851
var tables = xmlElement.Descendants<Table>().ToArray();
@@ -144,6 +147,20 @@ private static void AvoidSplitTagText(OpenXmlElement xmlElement)
144147
}
145148
}
146149

150+
private static void AvoidSplitTagText(OpenXmlElement xmlElement, IEnumerable<string> txt)
151+
{
152+
foreach (var paragraph in xmlElement.Elements<Paragraph>())
153+
{
154+
foreach (var continuousString in paragraph.GetContinuousString())
155+
{
156+
foreach (var text in txt.Where(o => continuousString.Item1.Contains(o)))
157+
{
158+
continuousString.Item3.TrimStringToInContinuousString(text);
159+
}
160+
}
161+
}
162+
}
163+
147164
private static void ReplaceText(OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary<string, object> tags)
148165
{
149166
var paragraphs = xmlElement.Descendants<Paragraph>().ToArray();

0 commit comments

Comments
 (0)