-
-
Notifications
You must be signed in to change notification settings - Fork 100
扩展渲染table支持单元格渲染,单元格模板{{}}只有一个的时list数据渲染每个单元格,超过一个时渲染行 #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dazhu6666
wants to merge
5
commits into
mini-software:main
Choose a base branch
from
dazhu6666:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+314
−24
Open
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
b01e2aa
扩展渲染table支持单元格渲染,单元格模板{{}}只有一个的时list数据渲染每个单元格,超过一个时渲染行
dazhu6666 aae9d7c
修复 当渲染table时使用 Descendants 会自动提取所有的tableRow,包括嵌套的tableRow,改用Elements,…
dazhu6666 83afbe8
修复cell数量计算错误
dazhu6666 e3f758f
1
dazhu6666 2b87e97
修复渲染table不满行时漏行bug
dazhu6666 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,7 @@ public static partial class MiniWord | |
| { | ||
| private static void SaveAsByTemplateImpl(Stream stream, byte[] template, Dictionary<string, object> data) | ||
| { | ||
| SaveAsByTemplateImplAsync(stream,template,data).GetAwaiter().GetResult(); | ||
| SaveAsByTemplateImplAsync(stream, template, data).GetAwaiter().GetResult(); | ||
| } | ||
|
|
||
| private static async Task SaveAsByTemplateImplAsync(Stream stream, byte[] template, Dictionary<string, object> data, CancellationToken token = default(CancellationToken)) | ||
|
|
@@ -81,6 +81,7 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum | |
| ReplaceText(xmlElement, docx, tags); | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// 渲染Table | ||
| /// </summary> | ||
|
|
@@ -90,16 +91,21 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum | |
| /// <exception cref="NotSupportedException"></exception> | ||
| private static void GenerateTable(Table table, WordprocessingDocument docx, Dictionary<string, object> tags) | ||
| { | ||
| var trs = table.Descendants<TableRow>().ToArray(); // remember toarray or system will loop OOM; | ||
| var trs = table.Elements<TableRow>().ToArray(); // remember toarray or system will loop OOM; | ||
| var regexStr = "(?<={{).*?\\..*?(?=}})"; | ||
| //计算是否只有一个cell存在指令,如果超过1个则纵向渲染,否则横向渲染。 | ||
| var cellList = table.Elements<TableRow>().SelectMany(s => s.Elements<TableCell>()).ToList(); | ||
| bool isHorizontal = cellList.Count > 1 && cellList.Count(w => Regex.Matches(w.InnerText, regexStr).Count > 0) <= 1; | ||
|
|
||
| foreach (var tr in trs) | ||
| { | ||
| var innerText = tr.InnerText.Replace("{{foreach", "").Replace("endforeach}}", "") | ||
| .Replace("{{if(", "").Replace(")if", "").Replace("endif}}", ""); | ||
|
|
||
| // 匹配list数据,格式“Items.PropName” | ||
| var matchs = (Regex.Matches(innerText, "(?<={{).*?\\..*?(?=}})") | ||
| var matchs = (Regex.Matches(innerText, regexStr) | ||
| .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(); | ||
|
|
@@ -124,12 +130,18 @@ private static void GenerateTable(Table table, WordprocessingDocument docx, Dict | |
| var attributeKey = matchs[0].Split('.')[0]; | ||
| var list = tagObj as IEnumerable; | ||
|
|
||
| int num = tr.Elements<TableCell>().Count(); | ||
| int index = 0; | ||
| List<OpenXmlElement> elementList = new List<OpenXmlElement>(); | ||
| int totalCount = list.Cast<object>().Count(); | ||
| //int rowCount = (totalCount + num - 1) / (num == 0 ? 1 : num); // 计算总行数 | ||
|
|
||
| foreach (var item in list) | ||
| { | ||
| var dic = new Dictionary<string, object>(); //TODO: optimize | ||
|
|
||
|
|
||
|
|
||
| var newTr = tr.CloneNode(true); | ||
|
|
||
| if (item is IDictionary) | ||
| { | ||
| var es = (Dictionary<string, object>)item; | ||
|
|
@@ -153,16 +165,43 @@ private static void GenerateTable(Table table, WordprocessingDocument docx, Dict | |
| ReplaceIfStatements(newTr, tags: dic); | ||
|
|
||
| ReplaceText(newTr, docx, tags: dic); | ||
| //Fix #47 The table should be inserted at the template tag position instead of the last row | ||
| if (table.Contains(tr)) | ||
|
|
||
| if (isHorizontal) | ||
| { | ||
| table.InsertBefore(newTr, tr); | ||
| var newTable = newTr.Descendants<Table>().FirstOrDefault(); | ||
| if (newTable != null) | ||
| elementList.Add(newTable.CloneNode(true)); | ||
|
|
||
| if (index > 0 && ((index + 1) % num == 0 || (index == totalCount - 1)) && elementList.Count > 0) | ||
| { | ||
| var templateTr = tr.CloneNode(true); | ||
| for (var i = 0; i < elementList.Count; i++) | ||
| { | ||
| var tCell = templateTr.Elements<TableCell>().ToList()[i]; | ||
|
|
||
| tCell.RemoveAllChildren(); | ||
| tCell.Append(elementList[i]); | ||
| } | ||
| newTr = templateTr; | ||
| elementList = new List<OpenXmlElement>(); | ||
|
|
||
| table.Append(newTr); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| // If it is a nested table, temporarily append it to the end according to the original plan. | ||
| table.Append(newTr); | ||
| //Fix #47 The table should be inserted at the template tag position instead of the last row | ||
| if (table.Contains(tr)) | ||
| { | ||
| table.InsertBefore(newTr, tr); | ||
| } | ||
| else | ||
| { | ||
| // If it is a nested table, temporarily append it to the end according to the original plan. | ||
| table.Append(newTr); | ||
| } | ||
| } | ||
| index++; | ||
| } | ||
|
|
||
| tr.Remove(); | ||
|
Comment on lines
205
to
207
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 在水平渲染模式下( }
if (isHorizontal && elementList.Any())
{
var templateTr = tr.CloneNode(true);
var cells = templateTr.Elements<TableCell>().ToList();
for (int i = 0; i < cells.Count; i++)
{
var tCell = cells[i];
tCell.RemoveAllChildren();
if (i < elementList.Count)
{
tCell.Append(elementList[i]);
}
}
table.Append(templateTr);
}
tr.Remove(); |
||
|
|
@@ -194,6 +233,7 @@ private static void GenerateTable(Table table, WordprocessingDocument docx, Dict | |
| } | ||
|
|
||
|
|
||
|
|
||
| /// <summary> | ||
| /// 获取Obj对象指定的值 | ||
| /// </summary> | ||
|
|
@@ -648,7 +688,7 @@ private static void ReplaceText(Paragraph p, WordprocessingDocument docx, Dictio | |
| { | ||
| AddPicture(run, mainPart.GetIdOfPart(imagePart), pic); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| t.Remove(); | ||
|
|
@@ -1023,9 +1063,9 @@ private static void AddPicture(OpenXmlElement appendElement, string relationship | |
| new A.PresetGeometry( | ||
| new A.AdjustValueList() | ||
| ) | ||
| { Preset = A.ShapeTypeValues.Rectangle })) | ||
| { Preset = A.ShapeTypeValues.Rectangle })) | ||
| ) | ||
| { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) | ||
| { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }) | ||
| ) | ||
| { | ||
| DistanceFromTop = (UInt32Value)0U, | ||
|
|
@@ -1043,22 +1083,30 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati | |
|
|
||
| DW.Anchor anchor3 = new DW.Anchor() | ||
| { | ||
| DistanceFromTop = (UInt32Value)0U, DistanceFromBottom = (UInt32Value)0U, | ||
| DistanceFromLeft = (UInt32Value)114300U, DistanceFromRight = (UInt32Value)114300U, | ||
| SimplePos = false, RelativeHeight = (UInt32Value)0U, BehindDoc = pic.BehindDoc, Locked = false, | ||
| LayoutInCell = true, AllowOverlap = pic.AllowOverlap, EditId = "1EACBECC", AnchorId = "5AF073F3" | ||
| DistanceFromTop = (UInt32Value)0U, | ||
| DistanceFromBottom = (UInt32Value)0U, | ||
| DistanceFromLeft = (UInt32Value)114300U, | ||
| DistanceFromRight = (UInt32Value)114300U, | ||
| SimplePos = false, | ||
| RelativeHeight = (UInt32Value)0U, | ||
| BehindDoc = pic.BehindDoc, | ||
| Locked = false, | ||
| LayoutInCell = true, | ||
| AllowOverlap = pic.AllowOverlap, | ||
| EditId = "1EACBECC", | ||
| AnchorId = "5AF073F3" | ||
| }; | ||
| DW.SimplePosition simplePosition3 = new DW.SimplePosition() { X = 0L, Y = 0L }; | ||
|
|
||
| DW.HorizontalPosition horizontalPosition3 = new DW.HorizontalPosition() | ||
| { RelativeFrom = DW.HorizontalRelativePositionValues.Column }; | ||
| { RelativeFrom = DW.HorizontalRelativePositionValues.Column }; | ||
| DW.PositionOffset positionOffset5 = new DW.PositionOffset(); | ||
| positionOffset5.Text = $"{pic.HorizontalPositionOffset * 9525}"; | ||
|
|
||
| horizontalPosition3.Append(positionOffset5); | ||
|
|
||
| DW.VerticalPosition verticalPosition3 = new DW.VerticalPosition() | ||
| { RelativeFrom = DW.VerticalRelativePositionValues.Paragraph }; | ||
| { RelativeFrom = DW.VerticalRelativePositionValues.Paragraph }; | ||
| DW.PositionOffset positionOffset6 = new DW.PositionOffset(); | ||
| positionOffset6.Text = $"{pic.VerticalPositionOffset * 9525}"; | ||
|
|
||
|
|
@@ -1067,12 +1115,12 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati | |
|
|
||
|
|
||
| DW.EffectExtent effectExtent13 = new DW.EffectExtent() | ||
| { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }; | ||
| { LeftEdge = 0L, TopEdge = 0L, RightEdge = 0L, BottomEdge = 0L }; | ||
| DW.WrapNone wrapNone3 = new DW.WrapNone(); | ||
|
|
||
|
|
||
| DW.DocProperties docProperties13 = new DW.DocProperties() | ||
| { Id = (UInt32Value)774829591U, Name = $"Picture {Guid.NewGuid().ToString()}" }; | ||
| { Id = (UInt32Value)774829591U, Name = $"Picture {Guid.NewGuid().ToString()}" }; | ||
|
|
||
| DW.NonVisualGraphicFrameDrawingProperties nonVisualGraphicFrameDrawingProperties13 = | ||
| new DW.NonVisualGraphicFrameDrawingProperties(); | ||
|
|
@@ -1087,14 +1135,14 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati | |
| graphic13.AddNamespaceDeclaration("a", "http://schemas.openxmlformats.org/drawingml/2006/main"); | ||
|
|
||
| A.GraphicData graphicData13 = new A.GraphicData() | ||
| { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }; | ||
| { Uri = "http://schemas.openxmlformats.org/drawingml/2006/picture" }; | ||
|
|
||
| PIC.Picture picture13 = new PIC.Picture(); | ||
| picture13.AddNamespaceDeclaration("pic", "http://schemas.openxmlformats.org/drawingml/2006/picture"); | ||
|
|
||
| PIC.NonVisualPictureProperties nonVisualPictureProperties13 = new PIC.NonVisualPictureProperties(); | ||
| PIC.NonVisualDrawingProperties nonVisualDrawingProperties13 = new PIC.NonVisualDrawingProperties() | ||
| { Id = (UInt32Value)0U, Name = $"Image {Guid.NewGuid().ToString()}.{pic.Extension}" }; | ||
| { Id = (UInt32Value)0U, Name = $"Image {Guid.NewGuid().ToString()}.{pic.Extension}" }; | ||
| PIC.NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties13 = | ||
| new PIC.NonVisualPictureDrawingProperties(); | ||
|
|
||
|
|
@@ -1104,7 +1152,7 @@ private static void AddPictureAnchor(OpenXmlElement appendElement, string relati | |
| PIC.BlipFill blipFill13 = new PIC.BlipFill(); | ||
|
|
||
| A.Blip blip13 = new A.Blip() | ||
| { Embed = relationshipId, CompressionState = A.BlipCompressionValues.Print }; | ||
| { Embed = relationshipId, CompressionState = A.BlipCompressionValues.Print }; | ||
|
|
||
| A.BlipExtensionList blipExtensionList11 = new A.BlipExtensionList(); | ||
| A.BlipExtension blipExtension11 = new A.BlipExtension() { Uri = $"{{{Guid.NewGuid().ToString("n")}}}" }; | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
当前的水平渲染逻辑似乎只支持当占位符渲染为嵌套表格(
Table)时的情况。如果占位符被替换为纯文本或其他类型的元素,newTr.Descendants<Table>().FirstOrDefault()将返回null,导致elementList为空,水平渲染逻辑不会添加任何内容。这使得该功能在处理非表格内容时会失效,是一个比较严重的缺陷。需要将此逻辑通用化,以捕获被渲染单元格内的所有类型内容。