使用Visual C#或者Visual Basic .NET建立COM Add-In結(jié)合了Office應(yīng)用程序的豐富的對(duì)象模型和.NET框架組件、Visual C#、Visual Basic .NET的語言特性。組合COM對(duì)象和.NET框架組件對(duì)象是一個(gè)挑戰(zhàn)。本文為建立Office add-in時(shí)組合這些技術(shù)提供了一些指導(dǎo)。
本文假定你了解基本的編程事務(wù)、對(duì)在Visual Basic for Applications中編寫Office宏有一些經(jīng)驗(yàn),可能在以前建立過某些Add-In。本文中的代碼使用Office XP對(duì)象模型。
本文中的事務(wù)假定你已經(jīng)從Visual Studio .NET新建項(xiàng)目對(duì)話框中建立了共享的Add-In。該新項(xiàng)目對(duì)話框?qū)⑹褂孟驅(qū)椭悴⒔⒒镜腁dd-In和安裝項(xiàng)目。
決定應(yīng)用程序類型
如果將建立的Add-In將在一個(gè)以上Office應(yīng)用程序中載入,你可能需要決定Add-In在那種應(yīng)用程序中運(yùn)行。默認(rèn)的Add-In項(xiàng)目有一個(gè)到Office庫的引用,但并不是引用任意的特定應(yīng)用程序庫。在決定運(yùn)行那種應(yīng)用程序前,需要給將載入Add-In的應(yīng)用程序添加一個(gè)引用。使用"添加引用"對(duì)話框的"COM"頁來選擇并給每個(gè)應(yīng)用程序添加引用。
實(shí)現(xiàn)IDTExtensibility2接口的Connect類在OnConnection事件中有一個(gè)application參數(shù)。該參數(shù)表現(xiàn)正在運(yùn)行的Office應(yīng)用程序的實(shí)例,但是該參數(shù)為System.Object類型。為了更有用,需要把該引用轉(zhuǎn)換成應(yīng)用程序類型。該應(yīng)用程序類型將根據(jù)載入Add-In的Office應(yīng)用程序作更改。
下面的SetApplicationFields方法設(shè)置了兩個(gè)類字段。該方法可以從Connect類的OnConnection方法中調(diào)用。
1、使用"添加引用"對(duì)話框的"COM"頁給項(xiàng)目添加Microsoft Excel Object Library和Microsoft Word Object Library引用。
2、給Connect類添加兩個(gè)類字段來表現(xiàn)Word和Excel應(yīng)用程序?qū)嵗?
' Visual Basic
Dim wordApp As Word.Application
Dim excelApp As Excel.Application
// C#
Word.Application wordApp = null;
Excel.Application excelApp = null;
|
3、把下面的方法添加到Connect類,它們用來設(shè)置Word和Excel應(yīng)用程序引用。在應(yīng)用程序載入時(shí)只需要一個(gè)字段不為空。
' Visual Basic
Private Sub SetApplicationFields(ByVal application As Object)
If TypeOf (application) Is Word.Application Then
wordApp = CType(application, Word.Application)
excelApp = Nothing
ElseIf TypeOf (application) Is Excel.Application Then
excelApp = CType(application, Excel.Application)
wordApp = Nothing
End If
End Sub
// C#
private void SetApplicationFields(object application)
{
if (application is Word.Application)
{
wordApp = (Word.Application)application;
excelApp = null;
}
else if (application is Excel.Application)
{
excelApp = (Excel.Application)application;
wordApp = null;
}
}
|
4、添加下面的代碼到OnConnection方法,在add-in載入時(shí)設(shè)置該字段。
' Visual Basic
Public Sub OnConnection(ByVal application As Object, _
ByVal connectMode As Extensibility.ext_ConnectMode, _
ByVal addInInst As Object, ByRef custom As System.Array) _
Implements Extensibility.IDTExtensibility2.OnConnection
' 為add-in 設(shè)置代碼
SetApplicationFields(application)
' 更多代碼
End Sub
// C#
public void OnConnection(object application,
Extensibility.ext_ConnectMode
connectMode, object addInInst, ref System.Array custom)
{
// 為add-in 設(shè)置代碼
SetApplicationFields(application);
// 更多代碼
}
|
添加命令條
通過應(yīng)用程序的CommandBars對(duì)象集合給應(yīng)用程序添加新的命令條。下面的方法給CommandBars集合添加一個(gè)命令條。當(dāng)你調(diào)用該方法時(shí),需要給它傳遞一個(gè)正在運(yùn)行的Office應(yīng)用程序?qū)嵗囊?。在上面一段中,Word應(yīng)用程序引用保持在類字段wordApp中。Missing變量的使用在段"C# Add-in中的可選參數(shù)"中解釋。
在應(yīng)用程序中放置一個(gè)命令條
1、給Connect類添加下面的方法。
' Visual Basic
Private Function AddWordToolbar(ByVal word As Word.Application, _
ByVal toolbarName As String) As Microsoft.Office.Core.CommandBar
Dim toolBar As Microsoft.Office.Core.CommandBar = Nothing
Try
' 為add-in建立一個(gè)命令條
toolBar = CType(word.CommandBars.Add(toolbarName, _
Microsoft.Office.Core.MsoBarPosition.msoBarTop, , True), _
Microsoft.Office.Core.CommandBar)
toolBar.Visible = True
Return toolBar
Catch
' 此處添加異常處理
Return Nothing
End Try
End Function
// C#
private Microsoft.Office.Core.CommandBar AddWordToolbar(
Word.Application word, string toolbarName)
{
Microsoft.Office.Core.CommandBar toolBar = null;
try
{
//為add-in建立一個(gè)命令條
object missing = System.Reflection.Missing.Value;
toolBar = (Microsoft.Office.Core.CommandBar)
wordApp.CommandBars.Add(toolbarName,
Microsoft.Office.Core.MsoBarPosition.msoBarTop,
missing, true );
toolBar.Visible = true;
return toolBar;
}
catch
{
//此處添加異常處理
return null;
}
}
|
2、給OnConnection方法添加下面的代碼來建立add-in載入時(shí)的工具條。
' Visual Basic
Dim toolbar As Microsoft.Office.Core.CommandBar = Nothing
If Not wordApp Is Nothing Then
toolbar = AddWordToolbar(wordApp, "Some useful toolbar.")
End If
// C#
Microsoft.Office.Core.CommandBar toolBar = null;
if (wordApp != null)
{
toolBar = AddWordToolbar(wordApp, "Some useful toolbar.");
}
|
如果你是使用Visual Basic并且Option Strict設(shè)置為Off,能使用遲綁定屬性并跳過把OnConnection方法中的application引用轉(zhuǎn)換為正確應(yīng)用程序類型的步驟。Word和Excel都有CommandBars屬性,你能通過遲綁定直接從application引用中使用它。
調(diào)試Add-in
你能在開發(fā)環(huán)境中建立、安裝、運(yùn)行和調(diào)試add-in。為了實(shí)現(xiàn)這些功能,需要對(duì)add-in項(xiàng)目的一些默認(rèn)設(shè)置作一些修改。
為add-in項(xiàng)目調(diào)整默認(rèn)設(shè)置
1、在解決方法管理器中右擊該add-in項(xiàng)目,選擇"屬性"。
2、在"屬性"對(duì)話框的左側(cè),選擇"配置屬性",接著選擇它下面的"調(diào)試"。把Debug Mode設(shè)置為Program,把Start Application設(shè)置為Word可執(zhí)行文件的目錄。默認(rèn)的啟動(dòng)程序是Visual Studio .NET,但是該add-in不在Visual Studio .NET中運(yùn)行。
3、建立該add-in項(xiàng)目并安裝項(xiàng)目。
4、在解決方案管理器中右擊安裝項(xiàng)目,選擇"安裝"。
5、按F5啟動(dòng)Word并載入該add-in。如果你的操作代碼只有本文給定的代碼,工具條會(huì)顯示在Word中,但是它上面沒有按鈕。
代碼產(chǎn)生的異常將被Office應(yīng)用程序截取并且不會(huì)自動(dòng)返回調(diào)試器。為了改善調(diào)試的行為,你可以在異常處中斷或者大范圍使用try/catch塊。要注意如果你在所有異常處中斷,調(diào)試器可能在與應(yīng)用程序不相關(guān)的異常處中斷。
在異常處中斷
1、從"調(diào)試"菜單中選擇"異常"。
2、選擇"通用語言運(yùn)行時(shí)異常"節(jié)點(diǎn)。
3、在"當(dāng)出現(xiàn)異常時(shí)"組中選擇"中斷進(jìn)入調(diào)試器"。
Office使失敗的add-in不可用,Office把所有可管理add-in解釋成相同的,因?yàn)樗鼈児蚕韒scoree.dll。因此當(dāng)add-in失敗時(shí),需要卸載失敗的add-in。
給命令條添加按鈕
一旦建立了工具條就能給它添加按鈕和其它控件。對(duì)于每個(gè)添加給工具條的按鈕,你需要給Connect類添加一個(gè)引用變量和一個(gè)處理給按鈕點(diǎn)擊事件的方法。把按鈕引用作為類的成員實(shí)現(xiàn)確保了該按鈕的生命周期與應(yīng)用程序的相同,并且載add-in還在載入、按鈕仍然需要時(shí)不會(huì)被無用單元收集程序例行測(cè)試破壞。
對(duì)于每個(gè)新按鈕,你可以指定一個(gè)FaceID,它是一個(gè)整數(shù),映射到Office庫的某個(gè)圖標(biāo)。隨Office分發(fā)、可以被按鈕使用的圖標(biāo)數(shù)以百計(jì)。
因?yàn)榭赡軙?huì)給工具條增加幾個(gè)按鈕,給Connect類添加一個(gè)方法是值得的,該方法實(shí)例化按鈕、把它添加到工具條,并把它與點(diǎn)擊事件處理程序關(guān)聯(lián)。
下面的代碼使用了添加到命令條按鈕點(diǎn)擊事件的委托。你可能使用OnAction屬性設(shè)置按鈕的事件處理程序。
給命令條添加按鈕和建立事件處理程序
1、使用Clipboard對(duì)象添加一個(gè)System.Windows.Forms引用。
2、為建立按鈕添加下面的代碼。該方法建立和返回了新按鈕的引用。它點(diǎn)擊事件的設(shè)置了標(biāo)題、圖標(biāo)(FaceId)和事件處理程序。
' Visual Basic
Private Function MakeANewButton(ByVal commandBar As _
Microsoft.Office.Core.CommandBar, ByVal caption As String, _
ByVal faceID As Integer, ByVal clickHandler As _
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler) _
As Microsoft.Office.Core.CommandBarButton
Try
Dim newButton As Microsoft.Office.Core.CommandBarButton
newButton = CType(commandBar.Controls.Add( _
Microsoft.Office.Core.MsoControlType.msoControlButton), _
Microsoft.Office.Core.CommandBarButton)
newButton.Caption = caption
newButton.FaceId = faceID
AddHandler newButton.Click, clickHandler
Return newButton
Catch ex As System.Exception
' 添加處理異常的代碼
Return Nothing
End Try
End Function
// C#
private Microsoft.Office.Core.CommandBarButton MakeANewButton(
Microsoft.Office.Core.CommandBar commandBar, string caption,
int faceID,
Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler
clickHandler )
{
object missing = System.Reflection.Missing.Value;
try
{
Microsoft.Office.Core.CommandBarButton newButton;
newButton = (Microsoft.Office.Core.CommandBarButton)
commandBar.Controls.Add(
Microsoft.Office.Core.MsoControlType.msoControlButton,
missing, missing, missing, missing);
newButton.Caption = caption;
newButton.FaceId = faceID;
newButton.Click += clickHandler;
return newButton;
}
catch (System.Exception ex)
{
//添加處理異常的代碼
return null;
}
}
|
3、為按鈕引用給Connect類添加下面的聲明。
' Visual Basic
Dim insertText As Microsoft.Office.Core.CommandBarButton
Dim styleText As Microsoft.Office.Core.CommandBarButton
// C#
Microsoft.Office.Core.CommandBarButton insertText;
Microsoft.Office.Core.CommandBarButton styleText;
|
4、給Connect類添加下面的方法。它們將作為按鈕的點(diǎn)擊事件的事件處理程序。這段代碼使用了類字段wordApp和 excelApp。
' Visual Basic
Public Sub insertText_Click(ByVal barButton As _
Microsoft.Office.Core.CommandBarButton, ByRef someBool As Boolean)
Dim text As String = ""
Dim data As System.Windows.Forms.IDataObject = _
System.Windows.Forms.Clipboard.GetDataObject()
If data.GetDataPresent(System.Windows.Forms.DataFormats.Text) Then
text = data.GetData( _
System.Windows.Forms.DataFormats.Text).ToString()
If (Not wordApp Is Nothing) Then
Me.wordApp.ActiveWindow.Selection.InsertBefore(text)
ElseIf (Not excelApp Is Nothing) Then
Me.excelApp.ActiveCell.Value = text
End If
End If
End Sub
Public Sub styleText_Click(ByVal barButton As _
Microsoft.Office.Core.CommandBarButton, ByRef someBool As Boolean)
Dim code As Object = "Code"
If (Not wordApp Is Nothing) Then
Me.wordApp.ActiveWindow.Selection.Style = code
ElseIf (Not excelApp Is Nothing) Then
Me.excelApp.ActiveCell.Style = code
End If
End Sub
// C#
public void insertText_Click(Microsoft.Office.Core.CommandBarButton
barButton, ref bool someBool)
{
string text = "";
System.Windows.Forms.IDataObject data =
System.Windows.Forms.Clipboard.GetDataObject();
if (data.GetDataPresent(System.Windows.Forms.DataFormats.Text))
{
text = data.GetData(System.Windows.Forms.DataFormats.Text).
ToString();
if (wordApp != null)
{
this.wordApp.ActiveWindow.Selection.InsertBefore(text);
}
else if (excelApp != null)
{
this.excelApp.ActiveCell.Value2 = text;
}
}
}
public void styleText_Click(Microsoft.Office.Core.CommandBarButton
barButton, ref bool someBool)
{
object code = "Code";
if (wordApp != null)
{
this.wordApp.ActiveWindow.Selection.set_Style(ref code);
}
else if (excelApp != null)
{
this.excelApp.ActiveCell.Style = code;
}
}
|
5、給OnConnection方法添加下面的代碼來建立add-in載入時(shí)的按鈕。為了調(diào)用這個(gè)方法,必須有一個(gè)到包含按鈕的命令條的引用。在例子中,上面的AddWordToolbar方法用于建立保持按鈕工具條。
' Visual Basic
' 建立工具條
Dim toolbar As Microsoft.Office.Core.CommandBar = Nothing
If Not wordApp Is Nothing Then
toolbar = AddWordToolbar(wordApp, "Some useful toolbar.")
End If
' 建立按鈕添加文本
insertText = MakeANewButton(toolbar, "Insert text", 1044, _
AddressOf insertText_Click)
' 建立按鈕改變選擇的文本
styleText = MakeANewButton(toolbar, "Style text", 1081, _
AddressOf styleText_Click)
// C#
//建立工具條
Microsoft.Office.Core.CommandBar toolBar = null;
if (wordApp != null)
{
toolBar = AddWordToolbar(wordApp, "Some useful toolbar.");
}
//建立按鈕添加文本
insertText = MakeANewButton(toolBar, "Insert text", 1044,
new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler
(insertText_Click));
//建立按鈕改變選擇的文本
styleText = MakeANewButton(toolBar, "Style text", 1081,
new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler
(styleText_Click));
|
用C#獲得或設(shè)置對(duì)象模型屬性
在前面一段中,Visual Basic中的樣式使用了ActiveCell的Style屬性設(shè)置。在C#代碼中樣式使用set_Style方法設(shè)置。當(dāng)需要改變時(shí),Intellisense會(huì)建議使用正確的方法。該方法有一個(gè)引用的System.Object參數(shù)。System.Object類型可以保持任意類型的數(shù)據(jù)。有些對(duì)象模型屬性可以使用System.Type.InvokeMember方法訪問。
給Add-in添加Windows窗體
給add-in添加Windows傳統(tǒng)與給普通.NET應(yīng)用程序沒有什么區(qū)別。Windows應(yīng)用程序所需要的相應(yīng)的項(xiàng)目引用都隨著新窗體一起添加進(jìn)來了。
窗體與Office的交互操作依賴于窗體是否為非模態(tài)的(modeless)。非模態(tài)窗體不能直接與Office對(duì)象模型交互。作為代替,你必須設(shè)計(jì)應(yīng)用程序使非模態(tài)窗體給調(diào)用代碼返回信息。接著調(diào)用代碼可以與對(duì)象模型交互。通常模態(tài)窗體能夠與Office對(duì)象某些交互。
給應(yīng)用程序添加輸入窗體
1、右擊add-in項(xiàng)目,點(diǎn)擊"添加",選擇"添加Windows窗體"。
2、輸入StyleSelection作為窗體的名字。
3、給新窗體添加一個(gè)ListBox控件,使用項(xiàng)集合編輯器添加三個(gè)項(xiàng)(Text、Code和Link)。把ListBox控件的Modifiers屬性設(shè)置為Public。
4、添加兩個(gè)按鈕。按下表設(shè)置屬性。
按鈕 屬性 值
Button1 Name OK
DialogResult OK
Text OK
Button2 Name Cancel
DialogResult Cancel
Text Cancel
5、給Connect類添加下面的方法。該方法建立窗體的一個(gè)實(shí)例,顯示它,檢查DialogResult并相應(yīng)改變當(dāng)前選擇的顏色。
' Visual Basic
Public Sub changeStyle_Click(ByVal barButton As _
Microsoft.Office.Core.CommandBarButton, ByRef someBool As Boolean)
Dim selectionForm As New StyleSelection()
Dim newStyle As Object = ""
If selectionForm.ShowDialog() = _
System.Windows.Forms.DialogResult.OK Then
newStyle = selectionForm.ListBox1.Text
End If
If Not wordApp Is Nothing Then
Me.wordApp.ActiveWindow.Selection.Style = newStyle
ElseIf Not excelApp Is Nothing Then
Me.excelApp.ActiveCell.Style = newStyle
End If
End Sub
// C#
public void changeStyle_Click(Microsoft.Office.Core.CommandBarButton
barButton, ref bool someBool)
{
StyleSelection selectionForm = new StyleSelection();
object newStyle = "";
if (selectionForm.ShowDialog() ==
System.Windows.Forms.DialogResult.OK)
{
newStyle = selectionForm.listBox1.Text;
}
if (wordApp != null)
{
this.wordApp.ActiveWindow.Selection.set_Style(ref newStyle);
}
else if (excelApp != null)
{
this.excelApp.ActiveCell.Style = newStyle;
}
}
|
6、建立一個(gè)類字段來保持某個(gè)按鈕的引用。點(diǎn)擊這個(gè)按鈕將顯示StyleSelection窗體。
</ccid_nobr>
' Visual Basic
Dim changeStyle As Microsoft.Office.Core.CommandBarButton
// C#
Microsoft.Office.Core.CommandBarButton changeStyle;
|
7、給Connect方法添加下面的代碼來給工具條添加changeStyle按鈕。
' Visual Basic
changeStyle = Me.MakeANewButton(toolbar, "Select style", 1082, _
AddressOf changeStyle_Click)
// C#
changeStyle = this.MakeANewButton(toolBar, "Select style", 1082,
new Microsoft.Office.Core._CommandBarButtonEvents_ClickEventHandler
(changeStyle_Click));
|
為Office應(yīng)用程序查找文檔
Office對(duì)象模型的文檔是Office應(yīng)用程序的一部分,而不是Visual Studio的一部分。例子是為了訪問Word的文檔,啟動(dòng)Word,指向工具菜單的"宏"(Macro)命令,接著點(diǎn)擊Visual Basic編輯器。在編輯器中使用"幫助"菜單獲得對(duì)象模型幫助。
C# Add-in中的可選參數(shù)
如果你查看Word對(duì)象模型的文檔,會(huì)發(fā)現(xiàn)在很多方法的參數(shù)列表中有可選參數(shù)。如果你在Visual Basic .NET中開發(fā)應(yīng)用程序,可以在調(diào)用試不管這些參數(shù)。如果是使用Visual C#,必須發(fā)送一個(gè)值表明缺少值。你可以簡(jiǎn)單地傳遞null,因?yàn)榉椒ㄒ笫褂靡脗鬟f值。在.NET框架組件中,該值是System.Reflection.Missing.Value。它的聲明如下:
// C#
object missing = System.Reflection.Missing.Value;
|
安全問題
你可以結(jié)合COM add-in填隙片(shim),關(guān)閉"Trust installed Add-Ins"選項(xiàng)使add-in運(yùn)行在高安全模式下。否則將使Office應(yīng)用程序運(yùn)行在較低安全層次。
結(jié)論
使用Visual Studio .NET建立Office add-in允許你使用Office的豐富的對(duì)象模型和.NET框架組件的新編程體系。本文的技巧可能需要根據(jù)特定情況輕微改變。
|