2010-10-26 104 views
2

我想在我的C#代碼中創建一個函數,它可以從VB調用,就好像它是一個宏。在C#中創建Excel宏定義

即VB代碼應該能夠做到:

sub vb_method 
    csharp_method("some_parameters") 
end sub 

,並有打電話給我的C#方法:

public object csharp_method(String parameter) { 
    ... 
} 

我知道這可以用C++來完成:

LPXLOPER retval; 
LPXLOPER module; // = something 
LPXLOPER parameters[] = { module, 
         "cpp_function", "parameter_type_info", 
         "MacroName", "text", 
         2, 
         ... }; 
Excel4v(xlfRegister, retval, parameter_count, parameters); 

這注冊我的cpp_function,以便它可以名稱MacroName調用。但它使用XLOPER的東西(這是一個令人頭疼的問題),它是用C++編寫的。

魔法2告訴Excel使用我的函數作爲宏。然後我可以從VB調用我的C++代碼,或者使用ExecuteExcel4Macro。我也可以使用它來註冊用戶定義的函數(UDF) - 只需使用一個神奇的1來代替。 (有關xlfRegister的更多詳細信息,請參見:http://msdn.microsoft.com/en-us/library/bb687900.aspx

C#使創建UDF非常容易,但我需要一種方法將函數註冊爲宏而不是公式。

那麼我怎麼能有一個宏調用我的C#代碼?

回答

1

據我所知,在.NET中沒有可用的便利層,允許您在Excel中註冊宏,就像用戶定義的函數一樣。

解決問題的方法是在託管的C++/CLI中創建一個包裝器DLL,該DLL註冊該宏,然後調用託管的C#代碼。

通過反射手段,您甚至應該能夠創建一個通用包裝,加載一個C#程序集,枚舉所有公共方法(或具有特定自定義屬性的所有公共方法),然後動態註冊這些方法。

我還沒有檢查過,但我認爲登記UDF的機制以非常相似的方式工作。

+0

我希望有一個更原生的機制,但我會試試這個。擁有通用包裝器肯定會比硬編碼包裝器更好。 – Tim 2010-10-26 22:21:02

2

首先,您可以使用Excel-Dna(可從http://exceldna.codeplex.com免費獲得)在C#或VB.NET中製作.xlls,而無需處理XLOPER或C++。

所以,你可以做可作爲Excel中的一個功能(通過0xA3執行描述的那種類型的包裝)的C#方法,只需添加一個屬性

[ExcelFunction(Name="MacroName")] 
public object csharp_method(String parameter) 
{...} 

其次,你可以從VBA調用函數和宏使用Application.Run。所以你可以說

Dim result As Variant 
    result = Application.Run("MacroName", mystring) 
+0

但我有一些宏,我不想公開作爲函數。即,我不希望用戶能夠將「= MacroName()」放入單元格中。那會很糟糕。在C++中用XLOPERs顯式註冊我的方法使我可以將一些註冊爲UDF,還有一些註冊爲宏。 XLW似乎只能讓你做UDF,我認爲Excel-Dna也是一樣。 – Tim 2010-11-05 00:16:48

+0

在Excel-Dna中,您可以將函數標記爲隱藏:ExcelFunction(Name =「MacroName」,IsHidden = true)]。這將函數註冊爲pxMacroType = 0,所以它不會顯示在函數嚮導中。這會有幫助嗎? – Govert 2010-11-05 12:41:45

+0

(用戶仍然可以從工作表中調用該函數,但是他們必須知道該名稱,可以使名稱變得模糊,並添加'?'等) – Govert 2010-11-05 12:53:24