VBA和C#之间的远程集成(使用JSON)

我试图find一个简单的方法发送一个string(在我的情况下JSON)从VBA数据提供程序到C#服务器。

我的服务器已经有一个服务器和客户端之间的高层次通信。 在我的情况下,我使用CORBA IIOP.NET,但我可以轻松地将其更改为WCF。

我的问题是:如何发送一个string到我的C#服务器?

从我的C#服务器,我从代码项目的代码(未testing)

public void Server() { //start server TcpListener tcpServerListener = new TcpListener(6666); tcpServerListener.Start(); //block tcplistener to accept incoming connection Socket serverSocket = tcpServerListener.AcceptSocket(); //open network stream on accepted socket NetworkStream serverSockStream = new NetworkStream(serverSocket); StreamReader serverStreamReader = new StreamReader(serverSockStream); Console.writeLine(serverStreamReader.ReadeLine()); } 

我很难通过VBA发送string。 任何人都可以帮助我。

PS:在C#中parsingJSON我正在使用JSON.NET和VBA我正在使用VB JSON

现在我看到,我们不能要求良好的实践和意识来帮助VBA,Excel-VBA标签。 所以我做了我的研究,并做出了我的select。 让我知道,如果有人有一个更好的理念做这个远程集成。

  1. 首先,我select了JSON,因为我觉得在不使用CORBA的情况下发送包是一个很好的理想。 所以我find了C#实现和VBA实现的JSON。
  2. 然后我没有find比TCP更好的协议。

我的例子有三个testing。 一个服务器(C#)和两个客户端(C#和VBA)可以在下面看到。

我使用Store和Company的理念来举例说明JSON for .NET在inheritance方面效果很好。 这是我的课程:

 public class Company { public string Name { get; set; } } public class Store : Company { public string Country { get; set; } public Dictionary<String, Double> Salaries { get; set; } } 

我的C#客户端只是创build两个Stores序列化并发送到服务器使用TcpClient

码:

 static void Main(string[] args) { Store storeUSA = new Store { Country = "USA", Name = "Amazon.com", Salaries = new Dictionary<string, double>{ {"Jones", 100000}, {"Deborah",200000} } }; Store storeBR = new Store { Country = "Brazil", Name = "Amazon.com", Salaries = new Dictionary<string, double>{ {"Ricardo", 500000}, {"Math", 800000} } }; TcpClient tcpClient = new TcpClient("192.168.1.63", 6666); Console.WriteLine("Connected to Server"); using (NetworkStream clientSockStream = tcpClient.GetStream()) { using (StreamWriter sw = new StreamWriter(clientSockStream)) { string output = JsonConvert.SerializeObject(storeUSA, Formatting.None); sw.WriteLine(output); sw.Flush(); System.Threading.Thread.Sleep(2000); output = JsonConvert.SerializeObject(storeBR, Formatting.None); sw.WriteLine(output); sw.Flush(); Console.WriteLine("Closing"); } } Console.WriteLine("Done"); Console.ReadLine(); } 

我的VBA客户端略有不同。 但它是一样的理想

码:

 Sub main() Dim tcp As New TCPClient Dim ok As Boolean ok = tcp.Connect("192.168.1.63", 6666) If Not ok Then Debug.Print "Error Connecting" Exit Sub End If tcp.Send "{""Country"":""France"",""Salaries"":{""Peyton Manning"":800.0,""Blaine Gabbert"":200000.0},""Name"":""Amazon.net""}" tcp.CloseConnection End Sub 

最后我的服务器真的很简单。 它只是听一个端口,当一个消息来了它反序列化JSON:

 static void Main(string[] args){ IPAddress ip = IPAddress.Parse("192.168.1.63"); TcpListener tcp = new TcpListener(ip, 6666); tcp.Start(); Console.WriteLine("[DEBUG] End point is: " + tcp.LocalEndpoint); Stopwatch time = new Stopwatch(); time.Start(); while (time.Elapsed < TimeSpan.FromSeconds(10)){ TcpClient client = tcp.AcceptTcpClient(); Console.WriteLine("Receiving message ... "); using (NetworkStream networkStream = client.GetStream()){ using (StreamReader streamReader = new StreamReader(networkStream)){ while (!streamReader.EndOfStream){ var json = streamReader.ReadLine(); Console.WriteLine("JSON:" + json); Store store = JsonConvert.DeserializeObject<Store>(json); Console.WriteLine("Data:"); Console.WriteLine(store.ToString()); } } } client.Close(); Console.WriteLine("... Message received"); } tcp.Stop(); time.Stop(); Console.WriteLine("Server no longer working"); Console.ReadKey(); } public class Company{ public string Name { get; set; } } public class Store : Company{ public string Country { get; set; } public Dictionary<String, Double> Salaries { get; set; } public override string ToString() { StringBuilder str = new StringBuilder(); str.Append(String.Format("Name= {0}; Country={1};\n Salaries:\n", Name, Country)); if (Salaries != null) { foreach (var salary in Salaries) { str.Append(String.Format(" '{0}' = {1}\n", salary.Key, salary.Value)); } } return str.ToString(); } } 

请注意,我使用VBA的TcpClient 。 感谢rory – code bellow:

 Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Const sckClosed = 0 ' Default. Closed Const sckOpen = 1 ' Open Const sckListening = 2 ' Listening Const sckConnectionPending = 3 ' Connection pending Const sckResolvingHost = 4 ' Resolving host Const sckHostResolved = 5 ' Host resolved Const sckConnecting = 6 ' Connecting Const sckConnected = 7 ' Connected Const sckClosing = 8 ' Peer is closing the connection Const sckError = 9 ' Error Const TIMEOUT_MAX As Integer = 10 Private host As String Private port As String Private socket As winsock Function Connect(ByVal fhost As String, ByVal fport As Integer) As Boolean Dim secs As Integer host = fhost port = fport Debug.Print Now & " - Client Started" Connect = False 'Create WinSock On Error Resume Next Set socket = CreateObject("MSWINSOCK.Winsock") If Err.Number <> 0 Then MsgBox "You need to add MsWinSock reference:" & vbCrLf & "Tools -> References -> Browse -> %SYSEM%\MSWINSCK.OCX" Debug.Print Now & " - Winsock Object Error." Exit Function End If On Error GoTo 0 'Connect socket.RemoteHost = host socket.RemotePort = port socket.Connect 'Wait for connected state (or TIMEOUT_MAX) While socket.State <> sckConnected And secs < TIMEOUT_MAX DoEvents secs = secs + 1 Debug.Print Now & " - Waitting for server [" & secs & "/" & TIMEOUT_MAX; "]." Sleep 1000 Wend If secs >= TIMEOUT_MAX Then Debug.Print Now & " - Client Timed Out" CloseConnection End If Connect = True End Function Sub Send(ByVal str As String) If socket Is Nothing Then Call Err.Raise(3222, "TCPClient::Send", "Socket not Initialized") End If If socket.State <> sckConnected Then Call Err.Raise(3222, "TCPClient::Send", "Not connected") End If socket.SendData str DoEvents End Sub Sub CloseConnection() If socket.State <> sckClosed Then socket.Close End If Set socket = Nothing Debug.Print Now & " - Client Closed." End Sub ' WINSOCK DATA ARRIVES Sub winsock_dataArrival(bytesTotal) Dim strData winsock.GetData strData, vbString RecieveData = strData WriteData Now & " - Client Recieved: " & RecieveData winsock.SendData "Test" Wscript.Sleep 1000 WriteData Now & " - Client Sent Data" Call ClientClose End Sub ' WINSOCK ERROR Sub winsock_Error(Number, Description, SCode, Source, HelpFile, HelpContext, CancelDisplay) MsgBox "Cient Error: " & Number & vbCrLf & Description WriteData Now & " - Cient Error: " & Number & ". " & Description Call ClientClose End Sub 

我希望对某人有用。