Creating a classlibrary to imitate Excel interface















  1. Imports System.Reflection
  2. Imports System.Runtime.InteropServices
  3. <ComClass(ImitateExcelClass.ClassId, ImitateExcelClass.InterfaceId, ImitateExcelClass.EventsId)>
  4. Public Class ImitateExcelClass : Implements IImitateExcel
  5.     Public Const ClassId As String = "4704E096-9263-48D3-8527-1FB63BD0E1F9"
  6.     Public Const InterfaceId As String = "22937F2C-23C6-4E64-B503-1F3D304657F4"
  7.     Public Const EventsId As String = "1E0B3789-117B-49DC-9EF3-76C43FB9EDCA"
  8.     Public Sub New()
  9.         MyBase.New()
  10.         _Property1 = "readonly Property1"
  11.         _Property2 = "ImitateExcelClass Property2"
  12.     End Sub

  13.     Dim _Property1 As String
  14.     Public ReadOnly Property Property1 As String Implements IImitateExcel.Property1
  15.         Get
  16.             Return _Property1
  17.         End Get
  18.     End Property
  19.     Dim _Property2 As String
  20.     Public Property Property2 As String Implements IImitateExcel.Property2
  21.         Get
  22.             Return _Property2
  23.         End Get
  24.         Set(value As String)
  25.             _Property2 = value
  26.         End Set
  27.     End Property

  28.     Public Event MyEvent(p As Int64) Implements IImitateExcel_Event.MyEvent
  29.     Public Event MyEvent2 As IImitateExcel_Event.MyEvent2_Delegate Implements IImitateExcel_Event.MyEvent2

  30.     Public Function WhoAreYou(ByVal str As String) As String
  31.         Dim Assembly As Assembly = Assembly.GetExecutingAssembly()
  32.         WhoAreYou = $"{str}  
  33.          Hi,I am Mr.Chen. How are you? 
  34.                     This DLL name is {IO.Path.GetFileName(Assembly.CodeBase)}.
  35.                     Its version is {Assembly.GetName().Version}.
  36.          Good bye"
  37.         Call Do_RaiseEvent()
  38.     End Function
  39.     Public Sub Do_RaiseEvent()
  40.         RaiseEvent MyEvent(55667788)
  41.         RaiseEvent MyEvent2("<MyEvent2>")
  42.     End Sub

  43. End Class

  44. <ComImport>
  45. <CoClass(GetType(ImitateExcelClass))>
  46. <Guid(ImitateExcelClass.InterfaceId)>
  47. Public Interface IImitateExcel : Inherits _IImitateExcel, IImitateExcel_Event
  48. End Interface
  49. <ComImport> <TypeLibType(4160S)>
  50. <Guid(ImitateExcelClass.InterfaceId)>
  51. Public Interface _IImitateExcel
  52.     ReadOnly Property Property1 As String
  53.     Property Property2 As String
  54. End Interface
  55. <TypeLibType(16S)>
  56. <ComVisible(False)>
  57. <Guid(ImitateExcelClass.EventsId)>
  58. Public Interface IImitateExcel_Event
  59.     Delegate Sub MyEvent2_Delegate(str As String)
  60.     Event MyEvent(Password As Int64)
  61.     Event MyEvent2 As MyEvent2_Delegate
  62. End Interface












  1. Option Strict On
  2. Imports Microsoft.Office.Interop
  3. Module Module1
  4.     Dim Excel_Application As Excel.Application
  5.     Dim Workbook As Excel.Workbook
  6.         Dim Worksheet As Excel.Worksheet
  7.         Sub Main()
  8.             Try
  9.                 Dim Type_ImitateExcelApp As Type = Type.GetTypeFromCLSID(
  10.                 New Guid(SimpleCom.ImitateExcelClass.ClassId))
  11.                 Dim ImitateExcelApp_obj As Object = Activator.CreateInstance(Type_ImitateExcelApp, nonPublic:=False)

  12.                 Dim Event_MyEvent2 As Reflection.EventInfo =
  13.               Type_ImitateExcelApp.GetEvent("MyEvent2")
  14.                 Dim Event_MyEvent As Reflection.EventInfo =
  15.               Type_ImitateExcelApp.GetEvent("MyEvent")
  16.                 Dim MyEvent2_Delegate As SimpleCom.IImitateExcel_Event.MyEvent2_Delegate =
  17.          CType(AddressOf EventHandler_2_1, SimpleCom.IImitateExcel_Event.MyEvent2_Delegate)
  18.                 Dim MyEventEventHandle As SimpleCom.IImitateExcel_Event.MyEventEventHandler =
  19.          CType(AddressOf EventHandler_1, SimpleCom.IImitateExcel_Event.MyEventEventHandler)
  20.                 Event_MyEvent2.AddEventHandler(ImitateExcelApp_obj, MyEvent2_Delegate)
  21.                 Event_MyEvent.AddEventHandler(ImitateExcelApp_obj, MyEventEventHandle)
  22.                 Dim Method_WhoAreYou As Reflection.MethodInfo =
  23.           Type_ImitateExcelApp.GetMethod("WhoAreYou", New Type() {GetType(String)})
  24.                 Dim Answer As Object = Method_WhoAreYou.Invoke(ImitateExcelApp_obj,
  25.                                  New Object() {"Do you know my password?"})
  26.                 Console.WriteLine($"{CType(Answer, String)}")
  27.                 Console.Write("Press any key to continue") : Console.ReadKey()

  28.                 Dim Property_Property2 As Reflection.PropertyInfo =
  29.           Type_ImitateExcelApp.GetProperty("Property2")
  30.                 Dim Property2_Value As Object = Property_Property2.GetMethod.Invoke(
  31.           ImitateExcelApp_obj, New Object() {})
  32.                 Console.WriteLine($"{CType(Property2_Value, String)}")
  33.                 Property_Property2.SetMethod.Invoke(
  34.           ImitateExcelApp_obj, New Object() {"I can set Property2 to any value "})
  35.                 Property2_Value = Property_Property2.GetMethod.Invoke(
  36.           ImitateExcelApp_obj, New Object() {})
  37.                 Console.WriteLine($"{CType(Property2_Value, String)}")
  38.                 Console.Write("Press any key to continue") : Console.ReadKey()

  39.                 Dim ImitateExcelApp As SimpleCom.ImitateExcelClass = CType(ImitateExcelApp_obj,
  40.                          SimpleCom.ImitateExcelClass)
  41.                 AddHandler ImitateExcelApp.MyEvent, (AddressOf EventHandler_1)
  42.                 AddHandler ImitateExcelApp.MyEvent2, AddressOf EventHandler_2
  43.                 ImitateExcelApp.Do_RaiseEvent()
  44.                 Console.Write("Press any key to continue") : Console.ReadKey()

  45.                 Excel_Application = New Excel.Application
  46.                 Dim TypeData_ImitateExcelApp As New BrowseHtml(ImitateExcelApp.GetType())
  47.                 TypeData_ImitateExcelApp.Show_type()
  48.                 Dim TypeData_ExcelApp As New BrowseHtml(Excel_Application.GetType())
  49.                 TypeData_ExcelApp.Show_type()
  50.                 Console.Write("Press any key to continue") : Console.ReadKey()

  51.                 Workbook = Excel_Application.Workbooks.Add()
  52.                 Worksheet = CType(Workbook.Worksheets(1), Excel.Worksheet)
  53.                 Workbook.Windows(1).Caption = "Imitate Excel interface"
  54.                 Dim R As Excel.Range = Worksheet.Range("B2")
  55.                 Worksheet.Hyperlinks.Add(Anchor:=R, Address:="http://www.google.com", TextToDisplay:="Google")
  56.                 R = R.Offset(2, 2)
  57.                 R.ColumnWidth = 15 * CDbl(R.ColumnWidth)
  58.                 R.Value = Environment.CurrentDirectory
  59.                 With Excel_Application
  60.                     .OnDoubleClick = "MyMacro"
  61.                     .ActiveWindow.WindowState = Excel.XlWindowState.xlMaximized
  62.                     AddHandler .SheetBeforeDoubleClick, AddressOf Module1.SheetBeforeDoubleClick
  63.                     .Visible = True
  64.                     .ActiveWindow.Visible = True
  65.                 End With
  66.                 Console.Write("Press any key to exit    ") : Console.ReadKey()
  67.             Catch ex As Exception
  68.                 Console.WriteLine(ex.Message)
  69.                 Console.Write("Press any key to exit    ") : Console.ReadKey()
  70.             Finally
  71.                 If Excel_Application IsNot Nothing Then
  72.                     Excel_Application.DisplayAlerts = False
  73.                     Excel_Application.Quit()
  74.                 End If
  75.             End Try
  76.         End Sub
  77.         Sub EventHandler_1(p As Int64)
  78.             Console.WriteLine($"{p,40} =====> EventHandler_1")
  79.         End Sub
  80.         Sub EventHandler_2(str As String)
  81.             Console.WriteLine($"{str,40} =====> EventHandler_2")
  82.         End Sub
  83.         Sub EventHandler_2_1(str As String)
  84.             Console.WriteLine($"{str,40} =====> EventHandler_2-1")
  85.         End Sub
  86.         Private Sub SheetBeforeDoubleClick(ByVal Sh As Object, ByVal Target As Excel.Range, ByRef Cancel As Boolean)
  87.             Dim WorkSheet2 As Excel.Worksheet = DirectCast(Sh, Excel.Worksheet)
  88.             If Target.Row = 4 AndAlso Target.Column = 4 Then
  89.                 Dim path As String = TryCast(Target.Value2, String)
  90.                 If String.IsNullOrEmpty(path) Then Exit Sub
  91.                 Dim DirectoryInfo As New IO.DirectoryInfo(path)
  92.                 If DirectoryInfo.Exists Then
  93.                     Dim Explorer As String = $"{Environment.GetEnvironmentVariable("SystemRoot")}\Explorer.exe"
  94.                     Process.Start(Explorer,
  95. $"/n /e,/select,{DirectoryInfo.FullName}\{IO.Path.GetFileName(Reflection.Assembly.GetExecutingAssembly.CodeBase)}")
  96.                 End If
  97.             End If
  98.         End Sub

  99.         Class BrowseHtml
  100.             Public Shared msedge_exe As String =
  101.             IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
  102.                          "Microsoft\Edge\Application\msedge.exe")
  103.             Shared HtmlFilePath1 As String = IO.Path.GetTempFileName
  104.             Shared HtmlFilePath2 As String = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
  105.                                          IO.Path.GetRandomFileName)
  106.             Shared HtmlFilePath As String
  107.             Const Myblog As String = "MyBlog_8", Key As String = "ViewType"

  108.             Public HtmlFilePath1_type As String
  109.             Dim HtmlFilePath2_type As String
  110.             Dim HtmlFilePath_type As String
  111.             ReadOnly For_HtmlFilePath_type As Register_RunTime_data
  112.             Dim type_forShow As Type
  113.             Sub New([type] As Type)
  114.                 HtmlFilePath1_type = IO.Path.GetTempFileName
  115.                 HtmlFilePath2_type = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
  116.                              IO.Path.GetRandomFileName)
  117.                 HtmlFilePath_type = String.Empty
  118.                 type_forShow = [type]
  119.                 For_HtmlFilePath_type = New Register_RunTime_data(Me)
  120.             End Sub
  121.             Protected Overrides Sub finalize()
  122.                 For_HtmlFilePath_type.SaveHtmlFilePath2()
  123.             End Sub
  124.             Class Register_RunTime_data
  125.                 ReadOnly Delegate_Finalize As System.Action
  126.                 ReadOnly Name_Space, Type_Name, Module_Name As String
  127.                 ReadOnly Parent As BrowseHtml
  128.                 Sub New(Optional OldFilePath As Boolean = True)
  129.                     If OldFilePath Then GetHtmlFilePath()
  130.                     If String.IsNullOrEmpty(HtmlFilePath) Then
  131.                         HtmlFilePath = IO.Path.ChangeExtension(HtmlFilePath2, "html")
  132.                     End If
  133.                     Delegate_Finalize = AddressOf SaveHtmlFilePath
  134.                 End Sub
  135.                 Sub New(Parent As BrowseHtml)
  136.                     Name_Space = Parent.type_forShow.Namespace
  137.                     Type_Name = Parent.type_forShow.Name
  138.                     Module_Name = Parent.type_forShow.Module.Name
  139.                     Me.Parent = Parent
  140.                     GetHtmlFilePath2()
  141.                     If String.IsNullOrEmpty(Parent.HtmlFilePath_type) Then
  142.                         Parent.HtmlFilePath_type = IO.Path.ChangeExtension(Parent.HtmlFilePath1_type, "html")
  143.                     End If
  144.                     Delegate_Finalize = AddressOf SaveHtmlFilePath2
  145.                 End Sub
  146.                 Protected Overrides Sub finalize()
  147.                     Delegate_Finalize()
  148.                 End Sub
  149.                 Public Sub GetHtmlFilePath()
  150.                     Try
  151.                         HtmlFilePath =
  152.                   Interaction.GetSetting(Reflection.Assembly.GetExecutingAssembly.GetName.Name,
  153.                         Myblog, Key)
  154.                     Catch ex As Exception

  155.                     End Try
  156.                 End Sub
  157.                 Public Sub GetHtmlFilePath2()
  158.                     Try
  159.                         Parent.HtmlFilePath_type =
  160.                     Interaction.GetSetting(Reflection.Assembly.GetExecutingAssembly.GetName.Name,
  161.                         Name_Space, Type_Name)
  162.                     Catch ex As Exception

  163.                     End Try
  164.                 End Sub
  165.                 Public Sub SaveHtmlFilePath()
  166.                     Try
  167.                         Interaction.SaveSetting(Reflection.Assembly.GetExecutingAssembly.GetName.Name,
  168.                       Myblog, Key, HtmlFilePath)
  169.                     Catch ex As Exception
  170.                         Console.WriteLine(ex.Message)

  171.                     End Try

  172.                 End Sub
  173.                 Public Sub SaveHtmlFilePath2()
  174.                     Try
  175.                         Interaction.SaveSetting(Reflection.Assembly.GetExecutingAssembly.GetName.Name,
  176.                        Name_Space, Type_Name, Parent.HtmlFilePath_type)
  177.                     Catch ex As Exception
  178.                         Console.WriteLine(ex.Message)
  179.                     End Try
  180.                 End Sub
  181.             End Class

  182.             Public Shared Sub Show(Html_content As String)
  183.                 Static For_HtmlFilePath As New Register_RunTime_data()
  184.                 Using HtmlFile As New IO.StreamWriter(HtmlFilePath, False, Text.Encoding.UTF8),
  185.                       BrowserProcess As New Process
  186.                     HtmlFile.Write(Html_content)
  187.                     HtmlFile.Flush()

  188.                     BrowserProcess.StartInfo = New ProcessStartInfo(HtmlFilePath) With {
  189.                       .Verb = "open",
  190.                       .UseShellExecute = True
  191.                     }
  192.                     If Not BrowserProcess.Start() Then Throw New Exception("error in BrowserProcess")
  193.                 End Using
  194.             End Sub
  195.             Public Sub Show_type()
  196.                 Dim class1_Viewer As New Type_viewer(Me.type_forShow)
  197.                 Dim Html_content As String = $"{class1_Viewer:W}"

  198.                 Using HtmlFile As New IO.StreamWriter(HtmlFilePath_type, False, Text.Encoding.UTF8),
  199.                       BrowserProcess As New Process
  200.                     HtmlFile.Write(Html_content)
  201.                     HtmlFile.Flush()

  202.                     BrowserProcess.StartInfo = New ProcessStartInfo(HtmlFilePath_type) With {
  203.                       .Verb = "open",
  204.                       .UseShellExecute = True
  205.                     }
  206.                     If Not BrowserProcess.Start() Then Throw New Exception("error in BrowserProcess")
  207.                 End Using
  208.             End Sub

  209.         End Class
  210.         Class Type_viewer : Implements IFormattable
  211.             Dim type As Type
  212.             Public Sub New(type As Type)
  213.                 Me.type = type
  214.             End Sub

  215.             Shared ReadOnly Color_set() As String = {"", "white", "yellow", "green", "red", "red", "red"}
  216.             Shared depth_table As Int32 = 0
  217.             Shared Function Table_TR(ParamArray ByVal td As String()) As String
  218.                 Return $"<tr style=""color:{Color_set(depth_table)};"">" &
  219.                    String.Concat(td) &
  220.                    "</tr>"
  221.             End Function
  222.             Shared Function Head_TD(str As String) As String
  223.                 Return $"<td>{str}</td>"
  224.             End Function
  225.             Shared Function Middle_TD(mt As Object) As String
  226.                 Dim part() As String = $"{mt}".Split(New Char() {" "c}, 2)
  227.                 Return $"<td>{part(0)}</td><td>{part(1)}</td>"
  228.             End Function
  229.             Shared Function Tail_TR(mt As Object) As String
  230.                 Return $"<td>{mt}</td>"
  231.             End Function
  232.             Public Function Display_WebPage_Table() As String
  233.                 Static PageContent As New Text.StringBuilder
  234.                 Dim peKind As Reflection.PortableExecutableKinds
  235.                 Dim machine As Reflection.ImageFileMachine
  236.                 If depth_table = 0 Then
  237.                     PageContent.Clear()

  238.                     [type].Module.GetPEKind(peKind, machine)
  239.                     Dim title As String = $"<title>{[type].Name}</title>"
  240.                     PageContent.Append(
  241. "<!DOCTYPE html>
  242. <html dir=""ltr"" , lang=""zh-tw"">
  243.     <head>
  244.                     <meta charset=""utf-8"" />")
  245.                     PageContent.Append(title)
  246.                     PageContent.Append(
  247.     "<style>
  248.         table {
  249.               white-space: pre;
  250.               background-color: lightslategrey;
  251.         }
  252.         caption {
  253.             font-family: ""Courier New"";
  254.             background-color: hotpink;
  255.             font-style: italic;
  256.             text-align: left
  257.         }
  258.         tr {
  259.             background-color: black;
  260.         }
  261.         span {
  262.             white-space: pre;
  263.             font-style: italic;
  264.             background-color: black;
  265.         }
  266.         div.mark1 {
  267.             border-bottom: 8px  ridge  red;
  268.             border-top: 8px ridge #f00;
  269.             border-left: 8px ridge #f00;
  270.         }
  271.         div.mark2 {
  272.             white-space: pre;
  273.             font-style: italic;
  274.             background-color: black;
  275.         }
  276.     </style>
  277.    </head>
  278.    <body>" & $"<div><h3>  machine={machine}  peKind={peKind} </h3></div>")
  279.                 End If
  280.                 depth_table += 1
  281.                 PageContent.Append("<table>")
  282.                 PageContent.AppendLine(
  283.              $"<caption style=""color:{Color_set(depth_table)}"">{depth_table}-Namespace:{[type].Namespace} TypeName:{[type].Name} ModuleName:{[type].Module}" &
  284.              $"{vbNewLine}{type.GUID.ToString.ToUpper}</caption>")
  285.                 Dim Constructors() As Reflection.ConstructorInfo = [type].GetConstructors()
  286.                 For Each ctor As Reflection.ConstructorInfo In Constructors
  287.                     PageContent.AppendLine(
  288.                 Table_TR(Head_TD("Constructor"), Middle_TD(ctor), Tail_TR(ctor.DeclaringType)))
  289.                 Next

  290.                 Dim FieldInfos() As Reflection.FieldInfo =
  291.                 [type].GetFields(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)
  292.                 For Each field As Reflection.FieldInfo In FieldInfos
  293.                     PageContent.AppendLine(
  294.                 Table_TR(Head_TD("Field"), Middle_TD(field), Tail_TR(field.DeclaringType)))
  295.                 Next


  296.                 Dim PropertyInfos() As Reflection.PropertyInfo =
  297.                 [type].GetProperties()
  298.                 For Each _property As Reflection.PropertyInfo In PropertyInfos
  299.                     PageContent.AppendLine(
  300.                 Table_TR(Head_TD("Property"), Middle_TD(_property), Tail_TR(_property.DeclaringType)))
  301.                 Next

  302.                 Dim MethodInfos() As Reflection.MethodInfo =
  303.                 [type].GetMethods(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)
  304.                 For Each method As Reflection.MethodInfo In MethodInfos
  305.                     PageContent.AppendLine(
  306.                 Table_TR(Head_TD("Method"), Middle_TD(method), Tail_TR(method.DeclaringType)))
  307.                 Next

  308.                 Dim EventInfos() As Reflection.EventInfo =
  309.                 [type].GetEvents(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)
  310.                 For Each event_ As Reflection.EventInfo In EventInfos
  311.                     PageContent.AppendLine(
  312.                 Table_TR(Head_TD("Event"), Middle_TD(event_), Tail_TR(event_.DeclaringType)))
  313.                 Next


  314.                 Dim FieldInfos_Static() As Reflection.FieldInfo =
  315.                 [type].GetFields(Reflection.BindingFlags.Static Or Reflection.BindingFlags.Public)
  316.                 For Each field As Reflection.FieldInfo In FieldInfos_Static
  317.                     PageContent.AppendLine(Table_TR(Head_TD("Field static"), Middle_TD(field), Tail_TR(field.DeclaringType)))
  318.                 Next

  319.                 Dim MethodInfos_Static() As Reflection.MethodInfo =
  320.                 [type].GetMethods(Reflection.BindingFlags.Static Or Reflection.BindingFlags.Public)
  321.                 For Each method As Reflection.MethodInfo In MethodInfos_Static
  322.                     PageContent.AppendLine(
  323.                 Table_TR(Head_TD("Method static"), Middle_TD(method), Tail_TR(method.DeclaringType)))
  324.                 Next

  325.                 Dim EventInfos_Static() As Reflection.EventInfo =
  326.                 [type].GetEvents(Reflection.BindingFlags.Static Or Reflection.BindingFlags.Public)
  327.                 For Each event_ As Reflection.EventInfo In EventInfos_Static
  328.                     PageContent.AppendLine(
  329.                 Table_TR(Head_TD("Event static"), Middle_TD(event_), Tail_TR(event_.DeclaringType)))
  330.                 Next
  331.                 PageContent.AppendLine("</table>")

  332.                 Dim InterfaceInfos() As Type = [type].GetInterfaces()
  333.                 For Each InterfaceType As Type In InterfaceInfos
  334.                     PageContent.AppendLine("<div class=""mark1"">" &
  335.                 $"<div class=""mark2"" style=""color: {Color_set(depth_table)};""> Interface   {InterfaceType.FullName}" &
  336.                 $"{vbNewLine}{InterfaceType.GUID.ToString.ToUpper} </div>")
  337.                     Dim temp_type As Type = Me.type
  338.                     Me.type = InterfaceType
  339.                     Me.Display_WebPage_Table()
  340.                     PageContent.AppendLine("</div>")
  341.                     Me.type = temp_type
  342.                 Next
  343.                 Dim NestedTypeInfos() As Type =
  344.                 [type].GetNestedTypes(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public)
  345.                 For Each NestedType As Type In NestedTypeInfos
  346.                     PageContent.AppendLine("<div class=""mark1"">" &
  347.                 $"<div class=""mark2"" style=""color:{Color_set(depth_table)};""> NestedType  {NestedType.FullName}  DeclaringType:{NestedType.DeclaringType}</div>")
  348.                     Dim temp_type As Type = Me.type
  349.                     Me.type = NestedType
  350.                     Me.Display_WebPage_Table()
  351.                     PageContent.AppendLine("</div>")
  352.                     Me.type = temp_type
  353.                 Next

  354.                 depth_table -= 1
  355.                 If depth_table = 0 Then
  356.                     PageContent.AppendLine("</body></html>")
  357.                     Return PageContent.ToString()
  358.                 Else
  359.                     Return Nothing
  360.                 End If
  361.             End Function
  362.             Public Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
  363.                 Select Case format.ToUpperInvariant(0)
  364.                     Case "W"c
  365.                         Return Display_WebPage_Table()
  366.                     Case Else
  367.                         Return ""
  368.                 End Select
  369.             End Function
  370.         End Class
  371.     End Module








































留言

這個網誌中的熱門文章

Marshalling

Calling a C# WPF library from C++

Marshalling II