这篇博客将要讨论的是关于:
如何从C#的source以及注释, 生成一份Word格式的关于各个类,函数以及成员变量的说明文档.
他的大背景如下......
最近的一个项目使用C#, 分N个模块,
在项目的里程碑的时候, 日本的总公司要检查我们的成果物.
成果物包括源代码, 概要设计式样书(SD,System Design), 详细设计式样书(PD, Program Design), 自动化测试等等.
源代码必须要符合编码规范(每个函数都要有注释, 方法变量的命名规则等...)
这些检查都很正常, 唯独一个比较辣手,那就是PD(一份Word文档).
PD中主要分两部分, 第一部分是UML图,
要求在UML图中,必须记载每一个变量名,函数名等等, 且必须与source完全一致.
这一点好办到, 只需要使用UML工具的逆向工程从source生成UML图即可.
PD中还需要的另一部分便是: 要为每一个类, 每一个变量, 每一个方法提供一个详细的说明(包括公有的和私有的一切)
以方法为例, 要求大概形如下面这样(类, 变量, 属性等类似):
这些关于方法,变量详细的记载, 同样要求与源代码一致(包括函数名, 参数, 函数注释等等)
在第一次做成这些文档和代码的时候还好些, 我们从一个地方拷贝到另一个地方, 他们初始是一致的,
然而接下来repeat的噩梦就开始了,两边同时维护, 总有漏下的,
而且需要花费很大的时间(尤其是检查),
有些时候, 日本方面的认真程度是我们中国人无法想象的,
比如从一份上百页的文档中, 他们能挑出某一个函数参数的大小写与source不一致这样的问题.
一个check不周,就有可能指摘.
关于问题, 已经介绍了差不多,
总之, 本着DRY原则,
同时也为了保证我们的这份word文档能够忠实于我们的source,
我想做的是: 从Source自动生成这份Word文档
为此要解决两个问题
1. 从Source中拿到相应的数据
2. 将相应的数据写到Word中.
对于第一个问题
,
visual studio中, [右键一个项目 -> property -> Build -> Output]处有一个叫做[XML documentation file]的选项,
勾上他之后, 在build的时候, 就会同时生成一个xml文件, 这个文件中包含各个类的方法,成员变量, 以及他们的xml注释.
关于这个问题, 还可以参考下面两个项目, 他们帮助我们生成MSDN Style的帮助文档.
Sandcastle - Documentation Compiler for Managed Class Libraries
Sandcastle Help File Builder
(我多么希望我们不需要维护这么一份word文件, 就使用上面的工具帮助我们生成MSDN Style的帮助文档就好....)
(然而总会有一些我们搞不定的人, 拥有一些和我们不同的喜好, 还好, 我们可以满足大家, 用程序生成这份文档吧....^-^)
对于第二个问题
,也就是如何用程序生成这份word文档,
在网上搜了一下, 使用word画表格的例子比较少(表格多的操作都用excel去了)
于是结合网上搜索的结果, 我写了下面的demo程序,
能够生成前面贴图效果的word文档(实际上, 前面的那个图, 就是对下面程序的输出做的一个截屏)
下面的代码只有一个函数,
在入口处设置一个断点, 边执行边看word文件的效果, 想了解word automation的,应该可以了解一个大概.
在调查的过程中, 我发现下面的三个连接提供的示例代码比较有用, 贴到下面供大家参考(第一篇讲解的尤为详细).
Word automation using C# @C#Corner
Word automation using C# @social.msdn.microsoft.com
HOW TO:利用 Visual C# .NET 使 Word 自动新建文
档 @MSDN
How to automate Microsoft Word to perform Mail Merge from Visual C# @MSDN
Automating Word Tables for Data Insertion and Extraction @MSDN
如果你使用的是其他语言, 但也需要维护一份这样的word文档的话,
大都可以使用类似的方法解决,
比如如果是java, javadoc同样可以帮助我们生成xml文档(而不仅仅局限于大家熟知的html), 然后我们从这个xml文档转换成我们需要的格式.
过程中要用到JELDoclet
, 详细做法参考这个链接Tip: Javadoc as XML @IBM DeveloperWorks
class WordAuto
{
Word.Application wApp;
Word._Document wDoc;
Object oMissing = System.Reflection.Missing.Value;
Object oFalse = false;
public void CreateFile()
{
Word.Selection wSelection;
Word.MailMerge wMailMerge;
Word.MailMergeFields wMergeFields;
Word.Table wTable;
int rowsNum = 12;
string StrToAdd;
// Create an instance of Word and make it visible.
wApp = new Word.Application();
wApp.Visible = true;
// Add a new document.
wDoc = wApp.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing);
wDoc.Select();
wSelection = wApp.Selection;
wSelection.ClearFormatting();
wSelection.Paragraphs.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
wSelection.Font.Size = 20;
wSelection.Font.ColorIndex = Word.WdColorIndex.wdBlack;
wSelection.Font.Bold = 1;
wSelection.TypeText("my first method");
wApp.Selection.TypeParagraph();
wSelection.Paragraphs.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
wSelection.ClearFormatting();
wSelection.Font.ColorIndex = Word.WdColorIndex.wdBlack;
wSelection.TypeText("content of first......");
wTable = wDoc.Tables.Add(wSelection.Range, rowsNum, 4, ref oMissing, ref oMissing);
wTable.Rows[1].Cells.Shading.BackgroundPatternColorIndex = Word.WdColorIndex.wdGray25;
//wTable.Columns[1].SetWidth(51, Word.WdRulerStyle.wdAdjustNone);
wTable.Columns[1].SetWidth(70, Word.WdRulerStyle.wdAdjustProportional);
wTable.Columns[3].SetWidth(70, Word.WdRulerStyle.wdAdjustProportional);
wTable.Borders.Enable = 1;
wTable.Rows[1].Cells[1].Merge(wTable.Rows[1].Cells[4]);
wTable.Rows[1].Cells[1].Range.InsertAfter("MyNameSpace.MyClass#MyMethod() : MyRetureType");
for (int i = 6; i <= rowsNum; i++)
{
wTable.Rows[i].Cells[2].Merge(wTable.Rows[i].Cells[4]);
}
wTable.Rows[6].Cells[1].Range.InsertAfter("详细定义");
wTable.Rows[7].Cells[1].Range.InsertAfter("事前条件");
wTable.Rows[8].Cells[1].Range.InsertAfter("事后条件");
wTable.Rows[9].Cells[1].Range.InsertAfter("不变制约");
wTable.Rows[10].Cells[1].Range.InsertAfter("非机能制约");
wTable.Rows[11].Cells[1].Range.InsertAfter("备考");
wTable.Rows[12].Cells[1].Range.InsertAfter("异常");
wTable.Rows[2].Cells[1].Range.InsertAfter("函数输入");
wTable.Rows[2].Cells[2].Range.InsertAfter("key::string");
wTable.Rows[2].Cells[3].Range.InsertAfter("概要");
wTable.Rows[2].Cells[4].Range.InsertAfter("my key to....");
wTable.Rows[3].Cells[3].Range.InsertAfter("制约");
wTable.Rows[3].Cells[4].Range.InsertAfter("key != null");
wTable.Rows[4].Cells[1].Range.InsertAfter("函数输出");
wTable.Rows[4].Cells[2].Range.InsertAfter("-");
wTable.Rows[4].Cells[3].Range.InsertAfter("概要");
wTable.Rows[5].Cells[3].Range.InsertAfter("制约");
Cell startCell1 = wTable.Rows[2].Cells[1];
Cell endCell1 = wTable.Rows[3].Cells[1];
Cell startCell2 = wTable.Rows[2].Cells[2];
Cell endCell2 = wTable.Rows[3].Cells[2];
Cell startCell3 = wTable.Rows[4].Cells[1];
Cell endCell3 = wTable.Rows[5].Cells[1];
Cell startCell4 = wTable.Rows[4].Cells[2];
Cell endCell4 = wTable.Rows[5].Cells[2];
startCell1.Merge(endCell1);
startCell2.Merge(endCell2);
startCell3.Merge(endCell3);
startCell4.Merge(endCell4);
// Go to the end of the document.
Object oConst1 = Word.WdGoToItem.wdGoToLine;
Object oConst2 = Word.WdGoToDirection.wdGoToLast;
wApp.Selection.GoTo(ref oConst1, ref oConst2, ref oMissing, ref oMissing);
wSelection.InsertBreak();
wSelection.Paragraphs.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevel2;
wSelection.Font.ColorIndex = Word.WdColorIndex.wdBlack;
wSelection.Font.Size = 20;
wSelection.Font.Bold = 1;
wSelection.TypeText("my second method");
wApp.Selection.TypeParagraph();
wSelection.Paragraphs.OutlineLevel = Word.WdOutlineLevel.wdOutlineLevelBodyText;
wSelection.ClearFormatting();
wSelection.Font.ColorIndex = Word.WdColorIndex.wdBlack;
wSelection.TypeText("content of second......");
//another table
wTable = wDoc.Tables.Add(wSelection.Range, rowsNum, 4, ref oMissing, ref oMissing);
wTable.Borders.Enable = 1;
////............
wDoc.SaveAs("c:\\word_auto.doc");
wDoc.Close(false);
wApp.Quit();
wApp = null;
}
}
---end---
分享到:
相关推荐
主要内容有C#开发环境的使用、C#语言基础应用、字符串处理技术、数组和集合的使用、面向对象编程...文件、C#与Word互操作、高效应用Excel、基本图形绘制、图像处理技术、常用图表应用、动画处理技术、音频与视频控制...
XML文档型注释 357 第14章 用ADO.NET访问数据 360 关系型数据库与SQL 360 ADO.NET对象模型 364 开始使用ADO.NET 366 使用OLE DB托管提供程序 369 使用数据绑定控件 371 第15章 ASP.NET程序与Web Services编程 380 ...
XML文档型注释 357 第14章 用ADO.NET访问数据 360 关系型数据库与SQL 360 ADO.NET对象模型 364 开始使用ADO.NET 366 使用OLE DB托管提供程序 369 使用数据绑定控件 371 第15章 ASP.NET程序与Web Services编程 380 ...
Sun就从来没有将它的Java交给过ECMA,以至于正当Microsoft尽力在Visual J++基础上拓展Java功能,并使之与Windows操作系统紧密结合在一起的时候,Sun公司对Microsoft提出了法律诉讼,控告Microsoft违反了许可证协议中...
XML文档型注释 357 第14章 用ADO.NET访问数据 360 关系型数据库与SQL 360 ADO.NET对象模型 364 开始使用ADO.NET 366 使用OLE DB托管提供程序 369 使用数据绑定控件 371 第15章 ASP.NET程序与Web Services编程 380 ...
在CST,XML和C#,Java和Lua的代码之间进行相互转换。 CountIfInJava:计算if语句以度量圈复杂度 ModifyIfConditionInC:修改所有条件表达式以测量分支覆盖率 ReplaceStatementWithPassInPython:用pass语句替换每...
Asp.Net(C#)利用XPath解析XML文档示例 XSL .Net框架下的XSLT转换技术简介 一个XSLT的简单例子 XSLXSLT板主题整理 xsl入门的好文章 新手学习XSL的好东西 XSL语法介绍 XSL学习心得 - 调用属性值 XSLT与XML转换的详细...
内含各种例子(vc下各种控件的使用方法、标题栏与菜单栏、工具栏与状态栏、图标与光标、程序窗口、程序控制、进程与线程、字符串、文件读写操作、文件与文件夹属性操作、文件与文件夹系统操作、系统控制操作、程序...
它还可通过反射处理汇编源代码,并在代码中使用XML注释生成MSDN形式的文档,这种文档比难以解读的XML更易于理解。 5. Nunit NUnit是一个.NET上的单元测试框架。NUnit 1.x主要是移植JUnit 3.8。从2.0版本开始,NUnit...
它还可通过反射处理汇编源代码,并在代码中使用XML注释生成MSDN形式的文档,这种文档比难以解读的XML更易于理解。 5. Nunit NUnit是一个.NET上的单元测试框架。NUnit 1.x主要是移植JUnit 3.8。从2.0版本开始,NUnit...
在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自绘对话框。 vc编程:自动停靠窗体,吸附窗体 OnMoving事件处理。 vc基于HTTP协议断点续传和多线程下载源代码 VC满屏开满玫瑰花 VC然输入框出现气球提示 调用...
在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自绘对话框。 vc编程:自动停靠窗体,吸附窗体 OnMoving事件处理。 vc基于HTTP协议断点续传和多线程下载源代码 VC满屏开满玫瑰花 VC然输入框出现气球提示 调用...
独立打包,保证可解压,内含大量源码,网上搜集...在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自绘对话框。 vc编程:自动停靠窗体,吸附窗体 OnMoving事件处理。 vc基于HTTP协议断点续传和多线程下载源代码 VC...
独立打包,保证可解压,内含大量源码,网上搜集...在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自绘对话框。 vc编程:自动停靠窗体,吸附窗体 OnMoving事件处理。 vc基于HTTP协议断点续传和多线程下载源代码 VC...
在MFC应用程序中浏览PDF、Word文档文件 vcdialog 自绘对话框。 vc编程:自动停靠窗体,吸附窗体 OnMoving事件处理。 vc基于HTTP协议断点续传和多线程下载源代码 VC满屏开满玫瑰花 VC然输入框...
此次将长期的思考、感悟,多年的系统开发、设计和团队管理经验,以及深入分析众多项目实战的宝贵成果和盘托出,力求将编程思想与具体实践融为一体,提炼出适合于广大读者快速理解和彻底掌握.NET软件开发的最佳学习...