///
/// 生成表格
///
///
///
///
public Table GetParagraph(OpenxmlTableModel reportTable, Int32Value width)
{
Table table = new Table();
TableProperties tblProp = new TableProperties(
new TableBorders(
new TopBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 },
new BottomBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 },
new LeftBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 },
new RightBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 },
new InsideHorizontalBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 },
new InsideVerticalBorder() { Val = new EnumValue(BorderValues.Single), Size = 4 }
)
)
{
//A4表格 4835左右
TableWidth = new TableWidth() { Width = width.ToString(), Type = TableWidthUnitValues.Pct },
};
table.Append(tblProp);
int cols = reportTable.Column;
int j = 0;
foreach (List strs in reportTable.Value)
{
int merge = 0;
bool startMerge = true;
TableRow row = new TableRow();
for (int i = 0; i < cols; i++)
{
merge = merge > 0 ? merge : strs[i].Merges;
TableCell cell = new TableCell();
//单元格属性
TableCellProperties tableCellProperties = new TableCellProperties();
//段落属性
Paragraph par = new Paragraph();
//边距
TableCellMargin margin = new TableCellMargin
{
LeftMargin = new LeftMargin() { Width = "0", Type = TableWidthUnitValues.Auto },
RightMargin = new RightMargin() { Width = "0", Type = TableWidthUnitValues.Auto }
};
tableCellProperties.Append(margin);
//垂直居中,将属性加入到单元格样式段落样式
tableCellProperties.Append(new TableCellVerticalAlignment { Val = TableVerticalAlignmentValues.Center });
par.Append(new ParagraphProperties(new Justification() { Val = JustificationValues.Center }));
Run run = new Run();
//表头
if (j == 0 && reportTable.IsHaveHeader)
{
RunProperties rPr = new RunProperties();
rPr.Append(new RunFonts() { EastAsia = "微软雅黑" });
rPr.Append(new FontSize() { Val = "28" });
if (reportTable.IsHaveHeaderBold)
rPr.Append(new Bold());
run.Append(rPr);
}
//数据
if (merge > 0)
{
HorizontalMerge verticalMerge = new HorizontalMerge();
//开始合并
if (startMerge)
{
RunProperties rPr = new RunProperties();
//rPr.Append(new Bold());
rPr.Append(new RunFonts() { EastAsia = "微软雅黑" });
rPr.Append(new FontSize() { Val = "26" });
run.Append(rPr);
verticalMerge.Val = MergedCellValues.Restart;
run.Append(CreateText(strs[i].StrValue));
startMerge = false;
}
else
{
verticalMerge.Val = MergedCellValues.Continue;
merge--;
if (merge == 0)
startMerge = true;
}
tableCellProperties.Append(verticalMerge);
}
else
{
RunProperties rPr = new RunProperties();
rPr.Append(new RunFonts() { EastAsia = "微软雅黑" });
rPr.Append(new FontSize() { Val = "26" });
run.Append(rPr);
run.Append(CreateText(strs[i].StrValue));
}
par.Append(run);
cell.Append(tableCellProperties);
cell.Append(par);
row.Append(cell);
}
j++;
table.Append(row);
}
return table;
}
private Text CreateText(string text)
{
if (text == null)
text = string.Empty;
Text t = new Text(text);
if (text.EndsWith(" "))
{
t.Space = new EnumValue(SpaceProcessingModeValues.Preserve);
}
if (text.StartsWith(" "))
{
t.Space = new EnumValue(SpaceProcessingModeValues.Default);
}
return t;
}
经过我计算,表格宽度大概在4835左右适合A4纸张。Model如下
#region Identity
///
/// openxml生成word表格
///
public class OpenxmlTableModel
{
public List> Value { get; set; }
///
/// 表格列
///
public int Column { get; set; }
///
/// 是否有表头
///
public bool IsHaveHeader { get; set; } = false;
///
/// 表头加粗
///
public bool IsHaveHeaderBold { get; set; } = false;
public class StrText
{
///
/// 文本
///
public string StrValue { get; set; }
///
/// 合并行
///
public int Merges { get; set; } = 0;
}
}
#endregion
OpenxmlTableModel一共有几个参,一个List
StrText两个参数,内容(默认占据一个单元格),Merges占据几个单元格(默认0即一个单元格)
TODO:讲一讲GetParagraph这个函数的合并实现(另外一些字体设置参见代码)
在word中生成Table并合并单元格需要使用到HorizontalMerge横向合并或者VerticalMerge纵向合并(命名空间:DocumentFormat.OpenXml.Wordprocessing)不是来自于Excel,请注意。参照官方文档 微软文档 。官方也有一个合并的文档,今天找不到了~
查看MergedCellValues.Restart的注释可以知道“Start/Restart Merged Region.When the item is serialized out as xml, its value is "restart".”设置开始合并的位置或者重新设置。简单点,就是标记从这个单元格开始。MergedCellValues.Continue从上一个点开始继续合并。
我在代码中是这样实现的:该单元格的Merges大于0,开始合并,标记startMerge为true,结束标记为false,同时用一个变量接收合并单元格的数量,依次减1,Merges为0的时候,重启startMerge为true
以下调用例子
//构造数据
//表头
var openxmlModel = new OperationWordHelper.OpenxmlTableModel()
{
Column = 6,
IsHaveHeader = true,
IsHaveHeaderBold = true,
Value = new List>()
{
new List()
{
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="项目"
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="型号"
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="单价(元)"
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="数量"
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="小计(元)"
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="备注"
},
},
}
};
//数据
foreach (var item in quos.Goodss)
{
openxmlModel.Value.Add(new List()
{
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=item.Name
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=item.Spec
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=item.UnitPrice.ToString("f2")
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=item.Quantity.ToString()
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=(item.Quantity*item.UnitPrice).ToString("f2")
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=item.Remarks
},
});
}
//总价
openxmlModel.Value.Add(new List()
{
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="合计",
Merges=3
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="",
Merges=0
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="",
Merges=0
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="",
Merges=0
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=quos.Goodss.Sum(t=>t.UnitPrice*t.Quantity).ToString("f2")
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=""
},
});
//折扣后总价
var goodsCharge = quos.Goodss.Sum(s => s.UnitPrice * s.Quantity); //物品费用合计
var outsourceCharge = quos.Goodss.Where(s => s.Outsource).Sum(s => s.UnitPrice * s.Quantity); //外协费用
var totalCharge = goodsCharge + quos.MaintenanceCharge + quos.ServiceCharge + quos.TravelCharge; //折前费用
var discountedCharge = totalCharge * quos.DiscountRate; //折后费用
openxmlModel.Value.Add(new List()
{
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="折扣后合计",
Merges=3
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue="",
Merges=0
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=""
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue=""
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
//总价减去折扣费用
StrValue = discountedCharge?.ToString("f2")
},
new OperationWordHelper.OpenxmlTableModel.StrText()
{
StrValue = NumToChinese.NumtoChinese((decimal)discountedCharge)
},
});
多列合并如下:
new List()
// {
// new StrText()
// {
// StrValue="合并内容1",
// Merges=1
// },
// new StrText()
// {
// StrValue="",
// Merges=0
// },
// new StrText()
// {
// StrValue="合并内容2",
// Merges=2
// },
// new StrText()
// {
// StrValue="合并内容2",
// Merges=0
// },
// new StrText()
// {
// StrValue="合并内容2",
// Merges=0
// },
// },
将会呈现两列,第一个单元格占据两列,第二个占据三列
参考https://www.cnblogs.com/zhouxin/p/3174936.html