C# : 操作Word文件的API,
這篇博客將要討論的是關於:
如何從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
C#代碼
- 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語言裡面,這個符號(->)是什,怎使用?
這是結構體指針中的一個符號,給你寫個程序解釋一下吧,例如:
#include<stdio.h>
struct STU //定義一個結構體
{
int num;
}stu;
int main()
{
struct STU *p; //定義一個結構體指針
p=stu; //p指向stu這個結構體變量
stu.num=100; //給結構體成員num附個初值
printf("%d",p->num); //輸出stu中的num的值
return;
}
看到了吧,->的作法就是在引用結構體中的變量!!
形式如:p->結構體成員(如p->num)
他的作用相當於stu.num或(*p).num
不知道這樣解釋你明不明白、、、、、不懂了call我,O(∩_∩)O~
望采納。
C語言裡面,這個符號(->)是什,怎使用?
這是結構體指針中的一個符號,給你寫個程序解釋一下吧,例如:
#include<stdio.h>
struct STU //定義一個結構體
{
int num;
}stu;
int main()
{
struct STU *p; //定義一個結構體指針
p=stu; //p指向stu這個結構體變量
stu.num=100; //給結構體成員num附個初值
printf("%d",p->num); //輸出stu中的num的值
return;
}
看到了吧,->的作法就是在引用結構體中的變量!!
形式如:p->結構體成員(如p->num)
他的作用相當於stu.num或(*p).num
不知道這樣解釋你明不明白、、、、、不懂了call我,O(∩_∩)O~
望采納。