Skip to content

Commit efa324d

Browse files
committed
解决常见问题中模版字串没有生效问题 格式:<t>abs{</t><t>{</t>
1 parent 3ae759f commit efa324d

3 files changed

Lines changed: 180 additions & 2 deletions

File tree

samples/docx/TestDemo04.docx

-637 Bytes
Binary file not shown.
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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 > 0)
98+
{
99+
int i = -1;
100+
int addLengg = 0;
101+
bool isbr = false;
102+
foreach (var textWord in texts)
103+
{
104+
if (addLengg > 0)
105+
{
106+
isbr = true;
107+
var leng = textWord.Text.Length;
108+
109+
if (addLengg - leng > 0)
110+
{
111+
addLengg -= leng;
112+
textWord.Text = "";
113+
}
114+
else if (addLengg - leng == 0)
115+
{
116+
textWord.Text = "";
117+
break;
118+
}
119+
else
120+
{
121+
textWord.Text = textWord.Text.Substring(addLengg);
122+
}
123+
}
124+
else if (isbr)
125+
{
126+
break;
127+
}
128+
else
129+
{
130+
i += textWord.Text.Length;
131+
//开始包含
132+
if (i >= index)
133+
{
134+
//全部包含
135+
if (textWord.Text.Contains(text))
136+
{
137+
break;
138+
}
139+
//部分包含
140+
else
141+
{
142+
var str1 = textWord.Text.Substring(0, i - index + 1);
143+
if (i == index)
144+
str1 = "";
145+
146+
var str2 = str1 + text;
147+
148+
addLengg = str2.Length - textWord.Text.Length;
149+
textWord.Text = str2;
150+
}
151+
}
152+
}
153+
}
154+
}
155+
}
156+
157+
158+
internal static bool IsText(this Run run)
159+
{
160+
return run.Elements().All(o => o is Text || o is RunProperties);
161+
}
162+
}
163+
}

src/MiniWord/MiniWord.Implment.cs

Lines changed: 17 additions & 2 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;
@@ -41,8 +42,8 @@ private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Diction
4142
}
4243
private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary<string, object> tags)
4344
{
44-
// avoid {{tag}} like <t>{</t><t>{</t>
45-
AvoidSplitTagText(xmlElement);
45+
// avoid {{tag}} like <t>abs{</t><t>{</t>
46+
AvoidSplitTagText(xmlElement, tags.Select(o => "{{" + o.Key + "}}"));
4647

4748
//Tables
4849
var tables = xmlElement.Descendants<Table>().ToArray();
@@ -144,6 +145,20 @@ private static void AvoidSplitTagText(OpenXmlElement xmlElement)
144145
}
145146
}
146147

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

0 commit comments

Comments
 (0)