目录
[配置Office DCOM](#配置Office DCOM)
应用场景
存储或导出个人WORD版简历是招聘应用系统中的常用功能,我们通常会通过应用系统采集用户的个人简历信息到数据库,许多情况下我们会读取数据记录导出到WORD文件中,以便汇总、打印。其中,WORD表格元素是经常会被用到的,比如问卷调查表格、教育经历表格、工作经历表格等等。
设计约定
1、设计WORD模板,在需要输出值的地方绘制表格,表格的数量对应输出的数据表数量。
2、根据条件查询数据表,生成 DataSet ,遍历 Tables ,生成对应的二维数组集合,将数据输出到对应的WORD表格中。
3、按约定,WORD表格的数量应该大于等于 DataSet 里的 Tables 数量。
4、按参数设定对应的WORD表格ID序号,如参数设定为2,则表示输出到WORD文件中的第二个表格中。(注意:WORD表格序号以1为开始)
在输出写入的方式中,我们约定有两种方式:
一为覆盖式写入(即已预知数据输出模式)举例如下图:
二为动态式写入(即未知数据行数量)举例如下图:
范例运行环境
操作系统: Windows Server 2019 DataCenter
操作系统上安装 Office Word 2016
数据库:Microsoft SQL Server 2016
.net版本: .netFramework4.7.1 或以上
开发工具:VS2019 C#
配置Office DCOM
配置方法可参照我的文章《C# 读取Word表格到DataSet》进行处理和配置。
实现代码
组件库引入
核心代码
DataSet转二维数组
public object[,] DataSetToObjectData(DataSet ds,int TableId,bool hastitle),该方法提供3个参数,DataSet数据集、指定表索引、导出是否包含标题列名称。
cs
public object[,] DataSetToObjectData(DataSet ds,int TableId,bool hastitle)
{
ArrayList rowdata = new ArrayList();
int _fieldcount=ds.Tables[TableId].Columns.Count;
Object[] colvalues = new Object[_fieldcount];
for(int i=0;i<_fieldcount;i++)
{
colvalues[i]=ds.Tables[TableId].Columns[i].ColumnName;
}
if(hastitle)
rowdata.Add(colvalues);
for(int i=0;i<ds.Tables[TableId].Rows.Count;i++)
{
Object[] values = new Object[_fieldcount];
values=ds.Tables[TableId].Rows[i].ItemArray;
rowdata.Add(values);
RowsCount++;
}
object[,] rv=new object[rowdata.Count,_fieldcount];
for(int i=0;i<rowdata.Count;i++)
{
for(int j=0;j<_fieldcount;j++)
{
rv[i,j]=((object[])rowdata[i])[j];
}
}
return rv;
}
导出写入WORD表格
public string DataSetToWordTables(string _filename,int[,] _drawtype,object[] _datas),该方法提供3个参数,使用的WORD模板文件路径、写入配置(包括要写入的WORD表格ID,写入方式:0为覆盖;1为从第二行动态追加;3为从第一行动态追加)、对应的二维数组集合。
cs
public string DataSetToWordTables(string _filename,int[,] _drawtype,object[] _datas) {
Object Nothing = System.Reflection.Missing.Value;
object filename = _filename;
//创建一个名为WordApp的组件对象
Word.Application WordApp = new Word.Application();
//创建一个名为WordDoc的文档对象
WordApp.DisplayAlerts = Word.WdAlertLevel.wdAlertsNone;
Word.Document WordDoc = WordApp.Documents.Open(ref filename, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing);
WordDoc.SpellingChecked = false;//关闭拼写检查
WordDoc.ShowSpellingErrors = false;//关闭显示拼写错误提示框
for(int i=_drawtype.GetLength(0)-1;i>=0;i--)
{
int _tableid=_drawtype[i,0];
int _draw=_drawtype[i,1];
object[,] r_datas=(object[,])_datas[i];
int _rowscount=r_datas.GetLength(0);
if (_rowscount == 0)
{
WordDoc.Tables[_tableid].Delete();
continue;
}
int startrowid = 2;
if (_draw == 3)
{
startrowid = 1;
}
if(_draw==1||_draw==3)
{
object _row=(object)WordDoc.Tables[_tableid].Rows[startrowid];
for(int j=0;j<_rowscount-1;j++)
{
WordDoc.Tables[_tableid].Rows.Add(ref _row);
}
}
for (int k = 0; k < r_datas.GetLength(0); k++)
{
for(int m=0;m<r_datas.GetLength(1);m++)
{
WordDoc.Tables[_tableid].Cell(k + startrowid, m + 1).Range.Text = r_datas[k, m].ToString();
}
}
}
WordDoc.Save();
WordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
//关闭WordApp组件对象
WordApp.Quit(ref Nothing, ref Nothing, ref Nothing);
return "";
}
调用举例
如下为示例代码:
cs
string _filename=@"x:\test.docx";
int[,] _drawtype=new int[2,2];
_drawtype[0,0]=1; //写入WORD第一个表格
_drawtype[0,1]=0; //覆盖式写入
_drawtype[1,0]=2; //写入WORD第二个表格
_drawtype[1,1]=1; //动态追加行写入
object[] _datas=new object[2];
DataSet ds=getDataSet(); //获取DataSet对象
_datas[0]=DataSetToObjectData(ds,0,false); //获取DataSet Tables[0]的二维数组数据
_datas[1]=DataSetToObjectData(ds,1,false); //获取DataSet Tables[1]的二维数组数据
string result=DataSetToWordTables(_filename,_drawtype,_datas); //写入Word表格
小结
1、核心代码中对无数据的表格采取了删除WORD表格的操作。
2、预设表格的优点在于所见即所得,样式设计简单化,便于理解输出,我们还可以采用关键字定位并动态添加WORD表格的形式进行输出,来实现更加复杂的样式等。
3、核心代码中输出的起始行为第2行,根据设置也可以为第1行。如果我们设计的表格比较复杂(如包括合并单元格等),则可以对 _drawtype进行改造,增加一个参数,用于指定从第几行开始进行输出。
这些代码我们提供了一些操作WORD相关的关键方法,这里仅作参考,欢迎大家评论指教!