Skip to content

Commit

Permalink
Merge pull request #74 from isdaniel/implement-async
Browse files Browse the repository at this point in the history
Implement async
  • Loading branch information
shps951023 authored Mar 24, 2024
2 parents 5f006a1 + 649a49c commit e6e2248
Show file tree
Hide file tree
Showing 8 changed files with 1,239 additions and 43 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.x
dotnet-version: 6.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
Expand Down
30 changes: 15 additions & 15 deletions src/MiniWord/Extensions/OpenXmlExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace MiniSoftware.Extensions
namespace MiniSoftware.Extensions
{
using DocumentFormat.OpenXml.Wordprocessing;
using System;
Expand All @@ -12,10 +12,10 @@ namespace MiniSoftware.Extensions
internal static class OpenXmlExtension
{
/// <summary>
/// 高级搜索:得到段落里面的连续字符串
/// 高级搜索:得到段落里面的连续字符串
/// </summary>
/// <param name="paragraph">段落</param>
/// <returns>Item1:连续文本;Item2:块;Item3:块文本</returns>
/// <param name="paragraph">段落</param>
/// <returns>Item1:连续文本;Item2:块;Item3:块文本</returns>
internal static List<Tuple<string, List<Run>, List<Text>>> GetContinuousString(this Paragraph paragraph)
{
List<Tuple<string, List<Run>, List<Text>>> tuples = new List<Tuple<string, List<Run>, List<Text>>>();
Expand All @@ -26,13 +26,13 @@ internal static List<Tuple<string, List<Run>, List<Text>>> GetContinuousString(t
var runs = new List<Run>();
var texts = new List<Text>();

//段落:所有子级
//段落:所有子级
foreach (var pChildElement in paragraph.ChildElements)
{
//块
//块
if (pChildElement is Run run)
{
//文本块
//文本块
if (run.IsText())
{
var text = run.GetFirstChild<Text>();
Expand All @@ -50,10 +50,10 @@ internal static List<Tuple<string, List<Run>, List<Text>>> GetContinuousString(t
texts = new List<Text>();
}
}
//公式,书签...
//公式,书签...
else
{
//跳过的类型
//跳过的类型
if (pChildElement is BookmarkStart || pChildElement is BookmarkEnd)
{

Expand Down Expand Up @@ -81,16 +81,16 @@ internal static List<Tuple<string, List<Run>, List<Text>>> GetContinuousString(t
}

/// <summary>
/// 整理字符串到连续字符串块中
/// 整理字符串到连续字符串块中
/// </summary>
/// <param name="texts">连续字符串块</param>
/// <param name="text">待整理字符串</param>
/// <param name="texts">连续字符串块</param>
/// <param name="text">待整理字符串</param>
internal static void TrimStringToInContinuousString(this IEnumerable<Text> texts, string text)
{
/*
//假如块为:[A][BC][DE][FG][H]
//假如替换:[AB][E][GH]
//优化块为:[AB][C][DE][FGH][]
//假如块为:[A][BC][DE][FG][H]
//假如替换:[AB][E][GH]
//优化块为:[AB][C][DE][FGH][]
*/

var allTxtx = string.Concat(texts.SelectMany(o => o.Text));
Expand Down
73 changes: 47 additions & 26 deletions src/MiniWord/MiniWord.Implment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ namespace MiniSoftware
using A = DocumentFormat.OpenXml.Drawing;
using DW = DocumentFormat.OpenXml.Drawing.Wordprocessing;
using PIC = DocumentFormat.OpenXml.Drawing.Pictures;
using System.Threading.Tasks;
using System.Threading;

public static partial class MiniWord
{
Expand All @@ -25,22 +27,39 @@ private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Diction
using (var ms = new MemoryStream())
{
ms.Write(template, 0, template.Length);
ms.Position = 0;
using (var docx = WordprocessingDocument.Open(ms, true))
{
var hc = docx.MainDocumentPart.HeaderParts.Count();
var fc = docx.MainDocumentPart.FooterParts.Count();
for (int i = 0; i < hc; i++)
docx.MainDocumentPart.HeaderParts.ElementAt(i).Header.Generate(docx, value);
for (int i = 0; i < fc; i++)
docx.MainDocumentPart.FooterParts.ElementAt(i).Footer.Generate(docx, value);
docx.MainDocumentPart.Document.Body.Generate(docx, value);
docx.Save();
}
bytes = ms.ToArray();
bytes = WriteToByte(data, ms);
}
stream.Write(bytes, 0, bytes.Length);
}

private static async Task SaveAsByTemplateImplAsync(Stream stream, byte[] template, Dictionary<string, object> data,CancellationToken token)
{
byte[] bytes = null;
using (var ms = new MemoryStream())
{
await ms.WriteAsync(template, 0, template.Length, token);
bytes = WriteToByte(data, ms);
}
await stream.WriteAsync(bytes, 0, bytes.Length,token);
}

private static byte[] WriteToByte(Dictionary<string, object> value, MemoryStream ms)
{
ms.Position = 0;
using (var docx = WordprocessingDocument.Open(ms, true))
{
var hc = docx.MainDocumentPart.HeaderParts.Count();
var fc = docx.MainDocumentPart.FooterParts.Count();
for (int i = 0; i < hc; i++)
docx.MainDocumentPart.HeaderParts.ElementAt(i).Header.Generate(docx, value);
for (int i = 0; i < fc; i++)
docx.MainDocumentPart.FooterParts.ElementAt(i).Footer.Generate(docx, value);
docx.MainDocumentPart.Document.Body.Generate(docx, value);
docx.Save();
}
return ms.ToArray();
}

private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocument docx, Dictionary<string, object> tags)
{
// avoid {{tag}} like <t>{</t><t>{</t>
Expand All @@ -53,14 +72,14 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum
{
foreach (var table in tables)
{
var trs = table.Descendants<TableRow>().ToArray(); // remember toarray or system will loop OOM;
var trs = table.Descendants<TableRow>().ToArray(); // remember toarray otherwise system will loop OOM;

foreach (var tr in trs)
{
var innerText = tr.InnerText.Replace("{{foreach", "").Replace("endforeach}}", "")
.Replace("{{if(", "").Replace(")if", "").Replace("endif}}", "");
var matchs = (Regex.Matches(innerText, "(?<={{).*?\\..*?(?=}})")
.Cast<Match>().GroupBy(x => x.Value).Select(varGroup => varGroup.First().Value)).ToArray();
var matchs = Regex.Matches(innerText, "(?<={{).*?\\..*?(?=}})")
.Cast<Match>().GroupBy(x => x.Value).Select(varGroup => varGroup.First().Value).ToArray();
if (matchs.Length > 0)
{
var listKeys = matchs.Select(s => s.Split('.')[0]).Distinct().ToArray();
Expand All @@ -76,15 +95,8 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum

foreach (Dictionary<string, object> es in list)
{
var dic = new Dictionary<string, object>(); //TODO: optimize

var dic = es.ToDictionary(e => $"{listKey}.{e.Key}", e => e.Value);
var newTr = tr.CloneNode(true);
foreach (var e in es)
{
var dicKey = $"{listKey}.{e.Key}";
dic.Add(dicKey, e.Value);
}

ReplaceStatements(newTr, tags: dic);

ReplaceText(newTr, docx, tags: dic);
Expand Down Expand Up @@ -356,8 +368,7 @@ private static void ReplaceText(OpenXmlElement xmlElement, WordprocessingDocumen
{
if (forTags.Any(forTag => forTag.Value.Keys.Any(dictKey =>
{
var innerTag = "{{" + tag.Key + "." + dictKey + "}}";
return t.Text.Contains(innerTag);
return t.Text.Contains($@"{{{{{tag.Key}.{dictKey}}}}}");
})))
{
isMatch = true;
Expand Down Expand Up @@ -700,5 +711,15 @@ private static byte[] GetBytes(string path)
return ms.ToArray();
}
}

private static async Task<byte[]> GetByteAsync(string path)
{
using (var st = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true))
using (var ms = new MemoryStream())
{
await st.CopyToAsync(ms);
return ms.ToArray();
}
}
}
}
26 changes: 26 additions & 0 deletions src/MiniWord/MiniWord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ namespace MiniSoftware
{
using DocumentFormat.OpenXml.Office2013.Excel;
using MiniSoftware.Extensions;
using MiniSoftware.Utility;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.IO;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;

public static partial class MiniWord
{
Expand All @@ -31,5 +35,27 @@ public static void SaveAsByTemplate(this Stream stream, byte[] templateBytes, ob
{
SaveAsByTemplateImpl(stream, templateBytes, value.ToDictionary());
}

public static async Task SaveAsByTemplateAsync(this Stream stream, byte[] templateBytes, object value,CancellationToken token = default(CancellationToken))
{
await SaveAsByTemplateImplAsync(stream, templateBytes, value.ToDictionary(),token).ConfigureAwait(false);
}

public static async Task SaveAsByTemplateAsync(this Stream stream, string templatePath, object value,CancellationToken token = default(CancellationToken))
{
await SaveAsByTemplateImplAsync(stream, await GetByteAsync(templatePath), value.ToDictionary(),token).ConfigureAwait(false);
}

public static async Task SaveAsByTemplateAsync(string path, string templatePath, object value,CancellationToken token = default(CancellationToken))
{
using (var stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true))
await SaveAsByTemplateImplAsync(stream, await GetByteAsync(templatePath), value.ToDictionary(),token);
}

public static async Task SaveAsByTemplateAsync(string path, byte[] templateBytes, object value,CancellationToken token = default(CancellationToken))
{
using (var stream = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true))
await SaveAsByTemplateImplAsync(stream, templateBytes, value.ToDictionary(),token);
}
}
}
1 change: 1 addition & 0 deletions src/MiniWord/Utility/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.ComponentModel;
using System.Dynamic;
using System.IO;
using System.Threading.Tasks;

internal static partial class Helpers
{
Expand Down
Loading

0 comments on commit e6e2248

Please sign in to comment.