"先对问题进行整体分析规划,确定其做什么,再决定其如何做",当你看到这样的理论的时候,你可能会说这理论太老套了,我早就知道,oo思想。回过头想想以前做的项目,有多少项目你真正按照这种指导思想在做。
在<<Data Structures and Program Design In C++>>开篇介绍了程序设计原理,通过life游戏设计,逐一点明oo思想理念。逐层分析,使得问题逐渐明朗。文笔笨拙,无法言明,有兴趣的话可以看看它的讲述,的确很有意思。
正好手边有个C#对word操作的例子(本例需要word的com组件的支持),抛出一己之见。
对word的操作,我们自然会想到word头处理、word中正文内容的处理、word尾部的处理。有什么问题?我们的跨幅太大了。按照oo思想,创建一个word对象,然后初始化、生成word。
1
WordObj doc;
2
doc.initialize();
3
doc.process();
那么WordObj是什么样的呢?
WordObj code
1
using System;
2
using System.Web;
3
using System.Reflection;
4
using Microsoft.Office.Interop.Word;
5![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class WordObj
{
6
private object miss;
7
private object strTemplate;
8
private object strPostion;
9
private string filename;
10
11![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private ReportDoc()
{//private constructer to void other create instance
12
}
13
14
public void initialize();
15
public process();
16
}
initialize()该做什么。word需要文件名,需要生成后的存储路径。可能想自己提供一个模板。那么就该对它重构一下:
Initialize
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public void initialize(string filefolder,string docTemplate,string filename)
{
2
strTemplate=docTemplate;
3
strPostion=filefolder;
4
miss=System.Reflection.Missing.Value;
5
filename=filename;
6
}
7
8![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public void initialize(string filefolder,string filename)
{
9
strPostion=filefolder;
10
miss=System.Reflection.Missing.Value;
11
strTemplate=@"E:\MyTemplate.dot";
12
filename=filename
13
}
14
15![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public void initialize()
{
16
miss=System.Reflection.Missing.Value;
17
strTemplate=@"E:\MyTemplate.dot";
18
filename=@"test.doc";
19
}
初始化完成。再看看process()的处理过程。
ProcessToWord Code
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
public void ProcessToWord()
{
2
ApplicationClass appc=new ApplicationClass();
3
//设置文件存储路径
4
StrOper strop=new StrOper();
5
string filepath=strop.CreateFolder(strPostion);//创建存储到的目标文件夹,CreateFolder()string folder如果存在这样的文件夹返回folder,否则创建并返回folder
6
strPostion=HttpRuntime.AppDomainAppPath+filepath+"\\"+filename;
7![](/Images/OutliningIndicators/InBlock.gif)
8
//增加文档
9
Document doc=appc.Documents.Add(ref strTemplate,ref miss,ref miss,ref miss);
10
appc.Visible=false;
11
doc.Activate();
12
13
DataTable dt=this.GetData();//取数据
14
if(dt.Rows.Count>0)
15![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
16
//写入内容
17![](/Images/OutliningIndicators/ContractedSubBlock.gif)
#region
18
19
this.addWordTable(ref doc,ref appc,dt,miss);
20![](/Images/OutliningIndicators/InBlock.gif)
21
this.setParagraphTitle(ref appc,"存在问题");
22
this.setParagraphContent(ref appc,this.stringFormat(dt.Rows[0][8]));
23![](/Images/OutliningIndicators/InBlock.gif)
24
//设置页尾
25
this.setDocBottom(ref appc,this.stringFormat(dt.Rows[0]["report_person"]));
26
this.setDocBottom(ref appc,this.stringFormat(dt.Rows[0]["fill_time"]));
27
28
#endregion
29
doc.SaveAs(ref strPostion,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss,ref miss);
30![](/Images/OutliningIndicators/InBlock.gif)
31
doc.Close(ref miss,ref miss,ref miss);
32![](/Images/OutliningIndicators/InBlock.gif)
33
appc.Quit(ref miss,ref miss,ref miss);
34![](/Images/OutliningIndicators/InBlock.gif)
35
}
36
else
37
this.MessageBox("没有数据,不能生成");
38
39
}
对word头、word正文内容、word尾部的处理,放在一起使得程序阅读起来不方便,同时也违背了oo思想。增加三个方法:
Code
1![](/Images/OutliningIndicators/None.gif)
2![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
private void setParagraphTitle(ref ApplicationClass appc,string strTitle)
{//设置word title
3
appc.Selection.TypeParagraph();
4
appc.Selection.Font.Size=14;//4号字体
5
appc.Selection.ParagraphFormat.LeftIndent=appc.CentimetersToPoints(float.Parse("0"));
6
appc.Selection.Font.Bold=(int)WdConstants.wdToggle;//加粗
7
appc.Selection.TypeText(strTitle);
8
appc.Selection.Font.Bold=(int)WdConstants.wdToggle;//加粗结束
9
}
10![](/Images/OutliningIndicators/None.gif)
11![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
private void setParagraphContent(ref ApplicationClass appc,string strContent)
{//设置word paragraph
12
appc.Selection.TypeParagraph();
13
appc.Selection.Font.Size=10.5f;
14
appc.Selection.Font.NameFarEast="宋体";
15
appc.Selection.Font.Bold=0;
16
appc.Selection.ParagraphFormat.LeftIndent=appc.CentimetersToPoints(float.Parse("1"));//设置段落行首缩进2个字符
17
appc.Selection.TypeText(strContent);
18
appc.Selection.Font.Bold=0;
19
}
20![](/Images/OutliningIndicators/None.gif)
21![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
private void setDocBottom(ref ApplicationClass appc,string strContent)
{//设置word落款:签名及日期
22
appc.Selection.TypeParagraph();
23
appc.Selection.Font.Size=10.5f;
24
appc.Selection.Font.NameFarEast="宋体";
25
appc.Selection.Font.Bold=0;
26
appc.Selection.ParagraphFormat.LeftIndent=appc.CentimetersToPoints(float.Parse("10"));
27
appc.Selection.TypeText(strContent);
28
appc.Selection.Font.Bold=0;
29
}
好像还少点什么?还缺少数据源,程序当然是为了简化我们的操作,没有数据源就显得无意义了:)。 本例中取得数据源为:
DataTable dt
=
this
.GetData();
在对正文内容处理中,我们可能会插入其它元素,比如表、图片或者其它对象。在此只给出对插入表格的操作.
Code
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
private void addWordTable(ref Document doc,ref ApplicationClass appc,DataTable dt,object miss)
{
2
//传入参数doc:word document;appc:ApplicationClass的一个实例;dt:数据源;miss:System.Reflection.Missing.Value;
3
//引用传参
4
//不返回值
5
Microsoft.Office.Interop.Word.Table docTable=doc.Tables.Add(appc.Selection.Range,7,3,ref miss,ref miss);//插入了一个7行3列的table到word中
6
7
this.setDocTable(ref docTable,dt);
8![](/Images/OutliningIndicators/InBlock.gif)
9
object count=docTable.Rows.Count+1;
10
object wdline=Microsoft.Office.Interop.Word.WdUnits.wdLine;
11
appc.Selection.MoveDown(ref wdline,ref count,ref miss);//移动appc焦点选区到word table之后
12
}
Code
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
private void setDocTable(ref Microsoft.Office.Interop.Word.Table doctable,DataTable dt)
{//填充表格数据内容
2
//输入参数 WordTable:要填充的word表,DataTable:数据源
3
//引用传参
4
//不返回值
5
this.setDocTableSytle(ref doctable);
6
doctable.Cell(1,1).Range.Text="报告名称";
7
doctable.Cell(1,2).Range.Text=":";
8
9
doctable.Cell(1,3).Range.Text=this.stringFormat(dt.Rows[0][0]);
10![](/Images/OutliningIndicators/InBlock.gif)
11![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
12
fill the data to doc
13
*/
14
}
15![](/Images/OutliningIndicators/None.gif)
16
有了table,还要对其设定成想要的格式,这样看起来才美观
Code
1![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
private void setDocTableSytle(ref Microsoft.Office.Interop.Word.Table doctable)
{//设置word table的样式
2
doctable.Columns[1].Width=100f;
3
doctable.Columns[2].Width=20f;
4
doctable.Columns[3].Width=280f;
5![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(int i=1;i<=doctable.Rows.Count;i++)
{
6
doctable.Cell(i,1).Range.Font.NameFarEast="黑体";
7
doctable.Cell(i,1).Range.Font.Size=15;
8
}
9
}
10
在setParagraphContent()中,因是从数据库取的数据,增加了一个数据格式的处理,处理出现null的列。
在对word的处理中,人为的增添了限制:word模板和word com组件。这些限制使得程序并不很完善,进一步就需要一一摘除这些限制。由于能力有限,去除word com组件还有困难。
通过对word操作,加固自己对这一程序设计理念的印象,努力改变以前"搭棚式程序设计"。