最新消息

[公告2014/05/30] 如有需要將部落格中,任何一篇文章的程式碼使用在商業用途,請與我聯繫。

[公告2015/04/26] Line版的 iInfo程式與投資應用 群組已上線想加入的朋友們,請先查看 "入群須知" 再與我聯繫 Line : aminwhite5168,加入請告知身分與回答 "入群須知" 的問題。

[公告2018/04/22] 台北 Python + Excel VBA 金融資訊爬蟲課程,課程如網頁內容 金融資訊爬蟲班:台北班 Python 金融資訊爬蟲、EXCEL VBA 金融資訊爬蟲

[公告2019/01/08] 請注意:我再次重申,部落格文章的程式碼,是要提供各位參考與學習,一旦網頁改版請自行修改,別要求東要求西要我主動修改,你們用我寫東西賺錢了、交差了,請問有分我一杯羹嗎?既然賺錢沒分我,請問有什麼理由要求我修改,如果沒能力改,就花錢來找我上課。

[公告2019/12/01] 若各位有 Excel VBA 案子開發需求,歡迎與我聯繫,可接案處理。

[公告2020/05/22] 頁面載入速度慢,起因為部分JS來源(alexgorbatchev.com)失效導致頁面載入變慢,目前已做調整,請多見諒。

2017年2月4日 星期六

.NET C# 建立 COM元件 (3) --- 再談 Excel VBA 後期綁定元件

從 .NET C# 建立 COM元件 (2) --- 製作 Excel VBA 後期綁定元件 介紹製作 Excel VBA 後期綁定元件,操作過程中 DLL元件需要跟系統註冊後才能使用,這裡就來看看在登錄檔中到底註冊了什麼內容,以及當屬性修改後會造成什麼影響。
還記得以下程式碼內容嗎?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TestVBA
{
    [Guid("6EE994BA-95B5-4548-98CB-B87663557880"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IVBAFunc
    {
        //[DispId(1)]
        int Multiply(int a, int b);
    }

    [ComVisible(true)]
    [Guid("A4F15491-8F1B-49C3-B626-589ECBCC60E7")]
    [ClassInterface(ClassInterfaceType.None)]
    public class VBAFunc : IVBAFunc
    {        
        public int Multiply(int a, int b)
        {
            return a * b;
        }
    }
}
第9行:在登錄檔以下的路徑可以找到 {6EE994BA-95B5-4548-98CB-B87663557880} 機碼。
(1) HKEY_CLASSES_ROOT\Interface\

(2) HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\

點選 HKEY_CLASSES_ROOT\Interface\{6EE994BA-95B5-4548-98CB-B87663557880} 路徑下的 「TypeLib」會見系統幫我們產生一組新GUID。

用這組新的GUID:{BA353C64-FFD5-439D-8C0C-1DBEEE5B8CA6} 再搜尋一次登錄檔,會在HKEY_CLASSES_ROOT\TypeLib\{BA353C64-FFD5-439D-8C0C-1DBEEE5B8CA6} 下見到關於 TestVBA專案相關內容。



第18行:在登錄檔以下的路徑可以找到 {A4F15491-8F1B-49C3-B626-589ECBCC60E7} 機碼。
(1) HKEY_CLASSES_ROOT\CLSID\,並且在該路徑下會找到TestVBA專案相關內容。




(2) HKEY_CLASSES_ROOT\TestVBA.VBAFunc\CLSID\

(3) HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\

以上介紹到這裡大家心裡應該有個底了,在C#程式碼中添加的GUID屬性內容,透過Regasm.exe 註冊,就會被寫入到登錄檔中,如果沒有使用GUID屬性,Regasm.exe會自動隨機產生一組GUID來填 入到登錄檔中
把 .NET C# 建立 COM元件 (2) --- 製作 Excel VBA 後期綁定元件  Excel VBA程式碼拿來修改,透過GUID來執行,看看會有什麼變化?
Sub TestVBA()
    Dim tool As Object
    Set tool = CreateObject("new:{A4F15491-8F1B-49C3-B626-589ECBCC60E7}")
    MsgBox tool.Multiply(2, 3)
    Set tool = Nothing
End Sub
執行結果:

有沒有發現 CreateObject 使用 GUID去建立物件,一樣可物件呼叫到Multiply函數執行,所以得到一個結論,COM元件的函數或模組可由指定 GUID來呼叫。

接著來看看在 HKEY_CLASSES_ROOT\CLSID\{A4F15491-8F1B-49C3-B626-589ECBCC60E7} 路徑下有多了一個「Progid」機碼內容,這內容也是DLL透過 Regasm.exe 註冊時被寫進去,預設內容為專案「命名空間.類別名稱」「namespace.class」,這個屬性影響 CreateObject 建立物件。我們可以試著在C#中添加 「Progid("iInfo.Amin")」 屬性,來看看 CreateObject 其中的變化。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TestVBA
{
    [Guid("6EE994BA-95B5-4548-98CB-B87663557880"),
    InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IVBAFunc
    {
        //[DispId(1)]
        int Multiply(int a, int b);
    }

    [ComVisible(true)]
    [Guid("A4F15491-8F1B-49C3-B626-589ECBCC60E7")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ProgId("iInfo.Amin")]
    public class VBAFunc : IVBAFunc
    {
        public int Multiply(int a, int b)
        {
            return a * b;
        }
    }
}
添加「 Progid 」屬性後重建DLL,記得先移除註冊系統中前一次註冊的DLL,再重新註冊新建好的DLL,這樣才看得出修改效果。

以下修改Excel VBA 程式碼中 CreateObject 的內容。
Sub TestVBA()
    Dim tool As Object
    Set tool = CreateObject("iInfo.Amin")
    MsgBox tool.Multiply(2, 3)
    Set tool = Nothing
End Sub

執行結果:

有聰明的讀者有發現什麼了嗎?
沒錯,在指定「Progid」屬性內容後,會直接影響 Excel VBA 程式碼中 CreateObject 的內容。如果沒有添加「Progid」屬性,則 CreateObject  呼叫的方法就是以「namespace.class」即「TestVBA.VBAFunc」。
以上介紹完C# COM DLL屬性添加的介紹,後續就交由讀者自行發想了。

相關文章:
參考資料: