Skip to content

Commit 9b8ed0c

Browse files
authored
Merge pull request #46 from ping9719/main
高级替换 <t>abs{</t><t>{</t> 测试文档
2 parents 5153720 + 00f90ff commit 9b8ed0c

3 files changed

Lines changed: 160 additions & 1 deletion

File tree

samples/docx/TestDemo04.docx

1.27 KB
Binary file not shown.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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.Text);
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 = null;
77+
runs = null;
78+
texts = null;
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 allTxtx = string.Concat(texts.SelectMany(o => o.Text));
97+
var indexState = allTxtx.IndexOf(text);
98+
if (indexState == -1)
99+
return;
100+
101+
int indexEnd = indexState + text.Length - 1;
102+
List<Tuple<int, char>> yl = new List<Tuple<int, char>>(allTxtx.Length);
103+
int iRun = 0;
104+
int iIndex = 0;
105+
int iRunOf = -1;
106+
foreach (var item in texts)
107+
{
108+
foreach (var item2 in item.Text)
109+
{
110+
if (indexState <= iIndex && iIndex <= indexEnd)
111+
{
112+
if (iRunOf == -1)
113+
iRunOf = iRun;
114+
115+
yl.Add(new Tuple<int, char>(iRunOf, item2));
116+
}
117+
else
118+
{
119+
yl.Add(new Tuple<int, char>(iRun, item2));
120+
}
121+
122+
iIndex++;
123+
}
124+
iRun++;
125+
}
126+
127+
int i = 0;
128+
foreach (var item in texts)
129+
{
130+
item.Text = string.Concat(yl.Where(o => o.Item1 == i).Select(o => o.Item2));
131+
i++;
132+
}
133+
134+
}
135+
136+
137+
internal static bool IsText(this Run run)
138+
{
139+
return run.Elements().All(o => o is Text || o is RunProperties);
140+
}
141+
}
142+
}

src/MiniWord/MiniWord.Implment.cs

Lines changed: 18 additions & 1 deletion
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;
@@ -42,7 +43,9 @@ private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Diction
4243
private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary<string, object> tags)
4344
{
4445
// avoid {{tag}} like <t>{</t><t>{</t>
45-
AvoidSplitTagText(xmlElement);
46+
//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)