最近在做兼职的时候,客户需要做一个导出导入word的功能。导出word很常见,但是导入word却很少,经过两天的摸索总算折腾出来了。
用的是第三方框架Aspose,不知道为什么在Nuget里下载的时候一直没反应,就在网上找了个dll,点击下载
1. 导出Word:
如果是简单的数据绑定可以用 域 or书签 的方式
微软的word添加域: 点击“插入→文档部件→域”找到MergeField,添加即可.
Wps的word:如图
添加完成后用代码绑定相对应数据
域绑定如下:
string tempPath = Server.MapPath("~/Docs/Temp/Template.doc");
string outputPath = Server.MapPath("~/Docs/Output/Template.doc");
//载入模板
var doc = new Document(tempPath);
//提供数据源
String[] fieldNames = new String[] {"UserName", "Gender", "BirthDay", "Address"};
Object[] fieldValues = new Object[] {"张三", "男", "1988-09-02", "陕西咸阳"};
//合并模版,相当于页面的渲染
doc.MailMerge.Execute(fieldNames, fieldValues);
//保存合并后的文档
doc.Save(outputPath);//在MVC中采用,保存文档到流中,使用base.File输出该文件
var docStream = new MemoryStream();
doc.Save(docStream, SaveOptions.CreateSaveOptions(SaveFormat.Doc));
return base.File(docStream.ToArray(), "application/msword","Template.doc");
书签绑定如下:
var tempPath = Server.MapPath("~/Temp/Doc/Template/Template.doc");
//载入模板
var doc = new Document(tempPath);
#region 书签绑定值,用于单个字段
//书签绑定值,用于单个字段
Dictionary<string, string> dictBookMark = new Dictionary<string, string>();
dictBookMark.Add("MedicinalName", "品名-山药");
dictBookMark.Add("MaterieBatchNumber", "物料代码- 000001");
dictBookMark.Add("ProdcutBatchNumber", "产品批号- 20152123456");
dictBookMark.Add("PlanDate", "执行日期- 2017年5月9号");
foreach (string name in dictBookMark.Keys)
{
var bookmark = doc.Range.Bookmarks[name];
if (bookmark != null)
{
bookmark.Text = dictBookMark[name];
}
}
//在MVC中采用,保存文档到流中,使用base.File输出该文件
var docStream = new MemoryStream();
doc.Save(docStream, SaveOptions.CreateSaveOptions(SaveFormat.Doc));
return base.File(docStream.ToArray(), "application/msword", "Template.doc");
如果是列表的绑定则如下:
设计如下模板,在循环的列表下添加列表的起始和结束域 : <<TableStart:RawMaterialList>> 和 <<TableEnd:RawMaterialList>> 以及列表中的各项域.
代码操作如下
var rawMaterialList = new List<RawMaterialModel>
{
new RawMaterialModel
{
RawMaterialIndex = 1,
RawMaterialName="测试物料1",
RawMaterialCode="test1",
UnitName = "KG",
ShouldUseCount = 123,
DestoryCost = "5.3%",
NeedUseCount = 150,
Remark = "test1111"
},
new RawMaterialModel
{
RawMaterialIndex = 2,
RawMaterialName="测试物料2",
RawMaterialCode="test2",
UnitName = "KG",
ShouldUseCount = 444,
DestoryCost ="-",
NeedUseCount = 555,
Remark = "test222"
},
new RawMaterialModel
{
RawMaterialIndex = 3,
RawMaterialName="测试物料3",
RawMaterialCode="test3",
UnitName = "KG",
ShouldUseCount = 654,
DestoryCost = "-",
NeedUseCount = 800,
Remark = "test333"
},
};
var packageMaterialList = new List<RawMaterialModel>
{
new RawMaterialModel
{
RawMaterialIndex = 1,
RawMaterialName="包材1",
RawMaterialCode="test1",
UnitName = "KG",
ShouldUseCount = 123,
DestoryCost = "5.3",
NeedUseCount = 150,
Remark = "test1111"
},
new RawMaterialModel
{
RawMaterialIndex = 2,
RawMaterialName="包材2",
RawMaterialCode="test2",
UnitName = "KG",
ShouldUseCount = 444,
DestoryCost = "9",
NeedUseCount = 555,
Remark = "test222"
}
};
var dt = CommonHelper.ListToTable(rawMaterialList);
dt.TableName = "RawMaterialList";
var dt2 = CommonHelper.ListToTable(packageMaterialList);
dt2.TableName = "PackageMaterialList";
var ds = new DataSet();
ds.Tables.Add(dt);
ds.Tables.Add(dt2);
doc.MailMerge.ExecuteWithRegions(ds);
2. 导入Word:
导入一个模板如下的word,导入word相对比较麻烦,因为我这里主要是一个表格,所以找到第一个table对象就可以,这里表格格式是固定的,所以部分代码采用硬编码的形式。
代码操作如下:
Document doc = new Document(filePathAndName);
Section section = (Section)doc.ChildNodes[0];
Body body = section.Body;
var importDocModel = new ImportDocModel();
Aspose.Words.Tables.Table table = null;
//找到第一个tabel
foreach (var node in body.ChildNodes)
{
if (node is Aspose.Words.Tables.Table)
{
table = (Aspose.Words.Tables.Table)node;
break;
}
}
//原辅料起始索引
var OldRawMaterialStartIndex = 5;
//原辅料结束索引
var OldRawMaterialEndIndex = 5;
//包材列表起始索引
var baoCaiStartIndex = table.Rows.Count - 1 - 7;
//包材列表结束索引
var baoCaiEndIndex = table.Rows.Count - 1 - 7;
//计算原辅料和包材的起始、结束索引
for (var i = 0; i < table.Rows.Count; i++)
{
if (table.Rows[i].Cells[0].Paragraphs[0] != null && table.Rows[i].Cells[0].Paragraphs[0].Runs[0].Text == "包材")
{
OldRawMaterialEndIndex = i - 1;
baoCaiStartIndex = i + 2;
break;
}
}
//循环表的每一行
for (var i = 0; i < table.Rows.Count; i++)
{
var row = table.Rows[i];
//1-3行数据处理
if (i <= 2)
{
#region 循环每行的每一列, 截取“:”:后面的内容
for (var j = 0; j < row.Cells.Count; j++)
{
var cell = row.Cells[j];
if (cell.Paragraphs[0] != null && cell.Paragraphs[0].Runs.Count > 0)
{
var cellText = string.Empty;
for (int x = 0; x < cell.Paragraphs[0].Runs.Count; x++)
{
cellText += cell.Paragraphs[0].Runs[x].Text;
}
if (!string.IsNullOrEmpty(cellText))
{
var index = cellText.IndexOf(":");
var useText = cellText;
if (index >= 0)
{
useText = cellText.Substring(index + 1, cellText.Length - index - 1);
}
if (i == 0 && j == 0)
{
importDocModel.Headr.MedicinalName = useText;
}
else if (i == 0 && j == 1)
{
importDocModel.Headr.Size = useText;
}
else if (i == 1 && j == 0)
{
importDocModel.Headr.MaterialCode = useText;
}
else if (i == 1 && j == 1)
{
importDocModel.Headr.ShoulUseCount = useText;
}
else if (i == 2 && j == 0)
{
importDocModel.Headr.ProductNumber = useText;
}
else if (i == 2 && j == 1)
{
importDocModel.Headr.DoDate = useText;
}
}
}
}
#endregion
}
//原辅料列表处理
else if (i >= OldRawMaterialStartIndex && i <= OldRawMaterialEndIndex)
{
if (row.Cells[0].Paragraphs[0] != null && row.Cells[0].Paragraphs[0].Runs.Count > 0)
{
var model1 = GetRawMaterialByRow(row);
importDocModel.RawMaterialModelList1.Add(model1);
}
}
//包材列表处理
else if (i >= baoCaiStartIndex && i <= baoCaiEndIndex)
{
if (row.Cells[0].Paragraphs[0] != null && row.Cells[0].Paragraphs[0].Runs.Count > 0)
{
var model2 = GetRawMaterialByRow(row);
importDocModel.RawMaterialModelList2.Add(model2);
}
}
}