C# 在OpenXML中创建具有可变列的表
我有一个每个对象结构的列表,如下所示C# 在OpenXML中创建具有可变列的表,c#,openxml,C#,Openxml,我有一个每个对象结构的列表,如下所示 { "regionName": "(R1)", "physicalRules": [ { "region": "(R1)", "Group": "Strip_10", "ClassGroup": "DKC", &quo
{
"regionName": "(R1)",
"physicalRules": [
{
"region": "(R1)",
"Group": "Strip_10",
"ClassGroup": "DKC",
"properties": [
{
"name": "N1",
"value": "200"
},
{
"name": "N2",
"value": "14"
}
]
}
]
}
-----------------------------------------------------
(R1) (R2) (R3)
N1 N2 N3 N4 N5 N6
200 14 5 10 15 500
我想创建一个表结构,如下所示
{
"regionName": "(R1)",
"physicalRules": [
{
"region": "(R1)",
"Group": "Strip_10",
"ClassGroup": "DKC",
"properties": [
{
"name": "N1",
"value": "200"
},
{
"name": "N2",
"value": "14"
}
]
}
]
}
-----------------------------------------------------
(R1) (R2) (R3)
N1 N2 N3 N4 N5 N6
200 14 5 10 15 500
其中,R1、R2和R3数据中的每一个都是具有如上定义的结构的对象形式。只有R1可以避免重复,因为R2和R3具有类似的结构。这实际上意味着表的列数由列表中的对象数定义。我不知道如何在OpenXML表中动态创建列。我看到的所有示例都是在OpenXML表中添加固定数量的列。。我应该为每个对象创建一个单独的表,并通过列垂直连接它们吗?我也不知道该怎么做
private void AddTable(Body body, MyVM data)
{
Table tbl = new();
// Set the style and width for the table.
TableProperties tableProp = new();
TableStyle tableStyle = new() { Val = "TableGrid" };
// Make the table width 100% of the page width.
TableWidth tableWidth = new() { Width = "5000", Type = TableWidthUnitValues.Pct };
// Apply
tableProp.Append(tableStyle, tableWidth);
tbl.AppendChild(tableProp);
// Add 3 columns to the table.
TableGrid tg = new(new GridColumn(), new GridColumn(), new GridColumn());
tbl.AppendChild(tg);
foreach (var item in data)
{
TableRow tr1 = new();
TableCell tc1 = new(new Paragraph(new Run(new Text(item.FirstName))));
TableCell tc2 = new(new Paragraph(new Run(new Text(item.LastName))));
TableCell tc3 = new(new Paragraph(new Run(new Text($"{item.Age}"))));
tr1.Append(tc1, tc2, tc3);
tbl.AppendChild(tr1);
}
body.AppendChild(tbl);
}
基于示例JSON,我假设您的模型类如下所示:
public class Item
{
public string RegionName { get; set; }
public List<PhysicalRule> PhysicalRules { get; set; }
}
public class PhysicalRule
{
public string Region { get; set; }
public string Group { get; set; }
public string ClassGroup { get; set; }
public List<Property> Properties { get; set; }
}
public class Property
{
public string Name { get; set; }
public string Value { get; set; }
}
公共类项目
{
公共字符串RegionName{get;set;}
公共列表物理规则{get;set;}
}
公共类物理规则
{
公共字符串区域{get;set;}
公共字符串组{get;set;}
公共字符串类组{get;set;}
公共列表属性{get;set;}
}
公共类财产
{
公共字符串名称{get;set;}
公共字符串值{get;set;}
}
您可以使用以下方法生成表:
private static void AddTable(Body body, List<Item> data)
{
Table tbl = new();
// Set the style and width for the table.
TableProperties tableProp = new();
TableStyle tableStyle = new() { Val = "TableGrid" };
// Make the table width 100% of the page width.
TableWidth tableWidth = new() { Width = "5000", Type = TableWidthUnitValues.Pct };
tableProp.Append(tableStyle, tableWidth);
TableGrid tableGrid = new(); // we will fill this as we go
// We will create three rows simultaneously, with a variable number of columns in them
TableRow regionsRow = new();
TableRow propertyNamesRow = new();
TableRow propertyValuesRow = new();
tbl.Append(tableProp, tableGrid, regionsRow, propertyNamesRow, propertyValuesRow);
int colsAdded = 0;
foreach (var rule in data.SelectMany(i => i.PhysicalRules))
{
var count = rule.Properties.Count;
if (count > 0)
{
TableCell regionCell = new();
// If there's more than one property in the rule,
// make the region cell span across those columns
if (count > 1)
{
TableCellProperties cellProperties = new();
cellProperties.Append(new GridSpan { Val = count });
regionCell.Append(cellProperties);
}
regionCell.Append(new Paragraph(new Run(new Text(rule.Region))));
regionsRow.Append(regionCell);
// Create one column for each property and add
// the name and value to the the respective rows
foreach (var prop in rule.Properties)
{
tableGrid.Append(new GridColumn());
colsAdded++;
TableCell nameCell = new();
nameCell.Append(new Paragraph(new Run(new Text(prop.Name))));
propertyNamesRow.Append(nameCell);
TableCell valueCell = new();
valueCell.Append(new Paragraph(new Run(new Text(prop.Value))));
propertyValuesRow.Append(valueCell);
}
}
}
// Don't add the table unless there's something in it
if (colsAdded > 0) body.AppendChild(tbl);
}
private static void AddTable(主体,列表数据)
{
表tbl=new();
//设置表格的样式和宽度。
TableProperties tableProp=new();
TableStyle TableStyle=new(){Val=“TableGrid”};
//使表格宽度为页面宽度的100%。
TableWidth TableWidth=new(){Width=“5000”,Type=TableWidthUnitValues.Pct};
tableProp.Append(tableStyle,tableWidth);
TableGrid TableGrid=new();//我们将边走边填充
//我们将同时创建三行,其中列数可变
TableRow RegionRow=new();
TableRow propertyNamesRow=new();
TableRow propertyValuesRow=new();
tbl.Append(tableProp、tableGrid、RegionRow、propertyNamesRow、propertyValuesRow);
int colsAdded=0;
foreach(data.SelectMany中的var规则(i=>i.PhysicalRules))
{
var count=rule.Properties.count;
如果(计数>0)
{
TableCell regionCell=new();
//如果规则中有多个属性,
//使区域单元跨越这些列
如果(计数>1)
{
TableCellProperties cellProperties=new();
Append(新的GridSpan{Val=count});
regionCell.Append(cellProperties);
}
Append(新段落(新运行(新文本(rule.Region)));
regionsRow.Append(regionCell);
//为每个属性创建一列并添加
//将名称和值添加到相应的行中
foreach(rule.Properties中的var prop)
{
Append(newgridcolumn());
colsAdded++;
TableCell nameCell=new();
追加(新段落(新运行(新文本(prop.Name)));
propertyNamesRow.Append(nameCell);
TableCell valueCell=new();
Append(新段落(新运行(新文本(prop.Value)));
propertyValuesRow.Append(valueCell);
}
}
}
//除非表中有什么内容,否则不要添加表
如果(colsAdded>0)body.AppendChild(tbl);
}
这是我用来测试上面的程序。我从一个空白文档开始,它被保存到“blank.docx”。程序将此文件复制到不同的名称,然后使用OpenXml对其进行修改。我相信这和你说的一样
using System.Collections.Generic;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
public class Program
{
public static void Main(string[] args)
{
string filename = "Output.docx";
File.Copy("Blank.docx", filename, true);
using (WordprocessingDocument doc = WordprocessingDocument.Open(filename, true))
{
var body = doc.MainDocumentPart.Document.Body;
var items = GetItems();
AddTable(body, items);
doc.Save();
doc.Close();
}
}
private static List<Item> GetItems()
{
var items = new List<Item>
{
new Item
{
RegionName = "(R1)",
PhysicalRules = new List<PhysicalRule>
{
new PhysicalRule
{
Region = "(R1)",
Group = "Strip_10",
ClassGroup = "DKC",
Properties = new List<Property>
{
new Property { Name = "N1", Value = "200" },
new Property { Name = "N2", Value = "14" }
}
}
}
},
new Item
{
RegionName = "(R2)",
PhysicalRules = new List<PhysicalRule>
{
new PhysicalRule
{
Region = "(R2)",
Group = "Strip_10",
ClassGroup = "DKC",
Properties = new List<Property>
{
new Property { Name = "N3", Value = "5" },
new Property { Name = "N4", Value = "10" },
new Property { Name = "N5", Value = "15" }
}
}
}
},
new Item
{
RegionName = "(R3)",
PhysicalRules = new List<PhysicalRule>
{
new PhysicalRule
{
Region = "(R3)",
Group = "Strip_10",
ClassGroup = "DKC",
Properties = new List<Property>
{
new Property { Name = "N6", Value = "500" }
}
}
}
}
};
return items;
}
private static void AddTable(Body body, List<Item> data)
{
// code as shown earlier in my answer
}
}
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用DocumentFormat.OpenXml.Packaging;
使用DocumentFormat.OpenXml.Wordprocessing;
公共课程
{
公共静态void Main(字符串[]args)
{
字符串filename=“Output.docx”;
File.Copy(“Blank.docx”,文件名,true);
使用(WordprocessingDocument doc=WordprocessingDocument.Open(文件名,true))
{
var body=doc.main documentpart.Document.body;
var items=GetItems();
添加表(正文、项目);
doc.Save();
doc.Close();
}
}
私有静态列表GetItems()
{
var items=新列表
{
新项目
{
RegionName=“(R1)”,
PhysicalRules=新列表
{
新物理规则
{
Region=“(R1)”,
Group=“Strip_10”,
ClassGroup=“DKC”,
属性=新列表
{
新属性{Name=“N1”,Value=“200”},
新属性{Name=“N2”,Value=“14”}
}
}
}
},
新项目
{
RegionName=“(R2)”,
PhysicalRules=新列表
{
新物理规则
{
Region=“(R2)”,
Group=“Strip_10”,
ClassGroup=“DKC”,
属性=新列表
{
新属性{Name=“N3”,Value=“5”},
新属性{Name=“N4”,Value=“10”},
新属性{Name=“N5”,Value=“15”}
}
}
}
},
新项目
{
RegionName=“(R3)”,
PhysicalRules=新列表
{
新物理规则
{
Region=“(R3)”,