1. 程式人生 > >在Excel中使用WinSock控制元件遠端通訊

在Excel中使用WinSock控制元件遠端通訊

在Excel中使用WinSock控制元件遠端通訊


這是我在實際使用時想要達到的一個目的。感謝萬能的網路。但也損害了我用心去研究而獲得最終成功的快感!
貴州大學計算機軟體與理論研究所 李 元

  本文討論在Excel 電子表格裡使用對WinSock 控制元件的VBA 程式設計,實現電子表格資料在Internet 網路上遠端通訊。具體地說,我們要求在Internet 網路上的兩個Excel 使用者的工作簿啟動後,能夠連線起來,既可互相將自己工作表單元裡已有的資料傳送給對方,也可將在表單文字框裡現場輸入的資料傳送給對方,而且無論哪方都可將接收到的資料傳到工作表指定的單元裡儲存下來。這樣,用Excel 不僅實現了工作表資料在Internet 網路上傳輸的功能,同時也達到了用Excel 實現一個“聊天室”的目的。


  為實現上述要求,可在Excel 中使用微軟的WinSock 控制元件,用UDP 協議(無連線的通訊協議)或TCP 協議進行。下面敘述用UDP 進行的具體做法。

  一、工作簿:Book_A.XLS

  1. 設計工作簿Book_A.XLS 的表單
  執行Excel,將工作簿用Book_A 存檔,選“工具| 巨集| Visual Basic 編輯器”,在出現的Visual Basic 編輯器窗口裡選選單“插入| 新增使用者窗體”,滑鼠右擊窗體選“屬性”在左面的窗體屬性欄裡對窗體做一些設定,例如:設定窗體的名稱為:frmA (預設名為UserForm1),窗體標題(預設名為Caption):Caption="A 聊天室”等。


  設定資訊輸入輸出文字框:從工具箱裡將下列控制元件放到窗體上:兩個文字框:TextBox1(用來輸入要傳送的字串)、TextBox2(用來接受對方傳送來的字串);再放三個命令按鈕:CommandButton1(用來執行傳送文字框TextBox1 裡的資料的過程)、CommandButton2(用來執行傳送工作表Sheet1 單元Cells(1,1) 的資料的過程)、CommandButton3(用來將在TextBox2 裡接收到的資料傳到工作表Sheet1 裡的單元Cells(3,1) 裡儲存的過程)。

  在視窗中新增WINSOCK 控制元件:選選單的“工具| 附加控制元件”,選“Microsoft Winsock Cotrol"(在Win98 中是6.0 版,在\windows\sytem 下的mswinsck.ocx),這時,該控制元件的圖示已在工具箱裡出現,將它放入窗體中後,左面出現“Winsock1 Winsock"屬性欄視窗,這裡Winsock1 是該控制元件的預設名(用於編寫程式碼),可在該屬性欄裡進行下面的設定,也可如下用程式碼進行設定。


  2. 對工作簿Book_A.XLS 的表單進行VBA 程式設計

Private Sub CommandButton1_Click()
  ' 傳送使用者在文字框TextBox1 裡的資料
  Winsock1.SendData TextBox1.Text
End Sub

Private Sub CommandButton2_Click()
  ' 傳送使用者工作表指定單元裡的資料
  Winsock1.SendData Cells(1, 1).Value
End Sub

Private Sub CommandButton3_Click()
  ' 將接收的資料儲存在單元Cells(3,1) 裡
  Cells(3, 1).Value = "接收的資料:" +TextBox2.Text
  ' 將積分結果儲存在當前的活動單元裡
  ActiveCell.Value = "接收的資料:" +TextBox2.Text
End Sub

Private Sub TextBox1_Change()
  ' 傳送使用者輸入
  'Winsock1.SendData TextBox1.Text
End Sub
'
Private Sub UserForm_Initialize()
Winsock1.Protocol = 1
'winsock 通訊協議設為UDP 協議1, TCP:0
  ' 設定網路地址
  Winsock1.LocalPort = 1999
  'Winsock1.RemoteHost = "210.40.7.168"
  Winsock1.RemoteHost = "Localhost" ' 在本機測試
  Winsock1.RemotePort = 1024
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
  Dim rec As String
  ' 接收對方資料並在Text2 中顯示
  Winsock1.GetData rec, vbString
  TextBox2.Text = rec
End Sub
  最後,為使呼叫工作簿Bokk_A.XLS 時即執行表單,開啟視窗:雙擊“工程——VBAProject"欄裡的“ThisWorkBook",出現程式碼視窗,在Worksheet_Activate 事件裡錄入下列程式碼(這個過程實現當開啟工作簿時,首先顯示名為frmDemo 的窗體):

  Private Sub Workbook_Activate()
    frmA.Show
End Sub

  二、工作簿:Book_B.XLS 

  另一方的工作簿Book_B.XLS 的做法與工作簿Book_A.XLS 幾乎完全一樣,不同的是在表單的初始化事件裡對網路通訊的遠端主機和埠設定:
  Private Sub UserForm_Initialize()
     ' 設定網路協議
    Winsock1.Protocol = 1
    'winsock 通訊協議設為UDP 協議1, TCP:0
    ' 設定網路地址
    Winsock1.LocalPort = 1024      ' 本地埠
    'Winsock1.RemoteHost = "210.40.7.188" ' 遠端主機
    Winsock1.RemoteHost = "Localhost"  ' 遠端主機
    Winsock1.RemotePort = 1999      ' 遠端埠
End Sub

  本文設計在Win98/Excel97/2000 下通過,下面是執行情況(A 接收B 的資料)。



如果系統沒有Winsock控制元件的話,可以下載下面的控制元件MSWINSCK.OCX,然後將該檔案複製到C:\Windows\System32目錄下。

在VBE視窗中,從選單“工具”->“引用”中,點選“瀏覽”按鈕,選擇MSWinSCK.ocx檔案,再從“工具箱”的“附加控制元件”中選擇Microsoft Winsock Control。

此時使用Winsock控制元件的話,將會出現提示不安全的ActiveX控制元件的提示。可以點選同時下載的REG檔案註冊該控制元件即可。

 zudhVJHh.rar (48.41 KB, 下載次數: 693)

一般在Excel的窗體中新增Winsock控制元件。

使用Winsock控制元件的應用程式一般是Client/Server結構,也就是客戶端/伺服器端。

以服務端為例,一般的步驟是:

先設定LocalPort本地埠,然後使用Listen方法偵聽資料請求。然後處理ConnectionRequest和DataArrival事件。使用完後使用Close方法關閉連線。

Private Sub UserForm_Initialize()
    Winsock1.LocalPort = 1999
    Winsock1.Listen
End Sub
Private Sub UserForm_Terminate()
    Winsock1.Close
End Sub
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
    If Winsock1.State <> sckClosed Then Winsock1.Close
    Winsock1.Accept requestID
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Dim Buffer() As Byte
    TransferedBytes = TransferedBytes + bytesTotal
    ReDim Buffer(bytesTotal - 1)
    Winsock1.GetData Buffer, vbArray + vbByte
End Sub
Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
    Debug.Print "Sock Err:" & Description
End Sub

而客戶端的一般步驟如下:

設定遠端伺服器埠RemotePort屬性,然後使用Connect方法連線。處理ConnectionRequest和DataArrival事件。傳送資料就直接使用Send方法就可以了,可以傳送字串或者Byte陣列。

Private Sub UserForm_Initialize()
    Winsock1.RemoteHost = "127.0.0.1"
    Winsock1.RemotePort = 2999
    Winsock1.Connect
End Sub
Private Sub UserForm_Terminate()
    Winsock1.Close
End Sub
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
    If Winsock1.State <> sckClosed Then Winsock1.Close
    Winsock1.Accept requestID
End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    Dim strData As String
    Winsock1.GetData strData, vbString
    If strData = "OK" Then
        Winsock1.Close
        Winsock1.RemotePort = 1999
        Winsock1.Connect
        MsgBox "You can send file now"
    End If
End Sub