Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 47 additions & 8 deletions src/MiniWord/MiniWord.Implment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ private static void Generate(this OpenXmlElement xmlElement, WordprocessingDocum
ReplaceText(xmlElement, docx, tags);
}


/// <summary>
/// 渲染Table
/// </summary>
Expand All @@ -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();
Expand All @@ -124,12 +130,17 @@ 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>();


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;
Expand All @@ -153,16 +164,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));
Comment on lines +170 to +172

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

当前的水平渲染逻辑似乎只支持当占位符渲染为嵌套表格(Table)时的情况。如果占位符被替换为纯文本或其他类型的元素,newTr.Descendants<Table>().FirstOrDefault() 将返回 null,导致 elementList 为空,水平渲染逻辑不会添加任何内容。这使得该功能在处理非表格内容时会失效,是一个比较严重的缺陷。需要将此逻辑通用化,以捕获被渲染单元格内的所有类型内容。


if (index > 0 && (index + 1) % num == 0 && 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 204 to 206

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

在水平渲染模式下(isHorizontaltrue),如果数据列表中的项目总数不是表格列数的整数倍,循环结束后elementList中剩余的项目将会被丢弃,不会被渲染到文档中,这会导致数据丢失。您需要在循环之后添加逻辑来处理这些剩余的项目,为它们生成最后一行。

                        }

                        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();

Expand Down Expand Up @@ -194,6 +232,7 @@ private static void GenerateTable(Table table, WordprocessingDocument docx, Dict
}



/// <summary>
/// 获取Obj对象指定的值
/// </summary>
Expand Down