winsock asynchronous receive in Excel - excel

currently wsock.dll is used in Excel 2007 to connect to a TCP server. It is fine that I can send something out. However, regarding receiving, is there any way to make it event driven as I don't know when there is a msg sending to the Excel? And recv call will be blocked until something is arrived.

If you can get your hands on the Winsock ActiveX control then you can used an event-based programming model. I've excerpted this example for Access:
Private Sub axWinsockServer_DataArrival(ByVal bytesTotal As Long)
Dim strClientMsg As String
' The DataArrival event fires on the server when the client sends
' information. Get the data and display it in a text box.
wsServer.GetData strClientMsg, vbString
Me!Text1.Value = strClientMsg
End Sub
Although consider why, exactly, you need a spreadsheet to do network communication.

Related

VB6 - Sending data to Telnet

I've been looking around for some code examples for sending data from a server application in VB6 to Telnet. From what I've seen (Baring in mind these code examples are 15-20 years old), you can only send raw strings?
I'm just playing around with some source code I made, where I have a custom stand-alone client, so I'm sending byte arrays back and forth to handle strings and values. I'm worried that only being able to send raw strings will massively reduce network performance between the server and client.
Are there any other examples?
Currently I send messages like this:
Public Sub SendMsg(ByVal Index As Long, ByVal Msg As String)
Dim Buffer As clsBuffer
Set Buffer = New clsBuffer
Buffer.PreAllocate Len(Msg) + 4
Buffer.WriteInteger SSendMsg
Buffer.WriteString Msg
Call SendDataTo(Index, Buffer.ToArray)
DoEvents
End Sub
The code there is what I currently have to send data to a custom client, not Telnet. My question is, is it possible to send that type of data to Telnet?

Prevent MySQL Connector/ODBC Data Source Configuration window from appearing when connection fails

On Excel I have a table that uses MySQL Connector/ODBC to get external data from a database.
If the connection fails when I refresh it the MySQL Connector/ODBC Data Source Configuration window appears.
Instead of that I want to present the user with a custom error message.
Checking if the refresh was successful after refreshing is too late to prevent the window so I ping the server before refreshing and cancel the refresh if the ping fails.
My question is if there's a more reliable/standard way to not show the window when there's no connection. I don't want to write the password on my code for security reasons (the connection is made with a DSN) and I don't know if the ping trick will always work or if it might rarely give unexpected errors or results.
Also I think it's technically or theoretically possible that the connection status changes between the ping check and the refresh even though that wouldn't be the end of the world (if that was even possible between the fast running code).
Code example for anyone asking:
Sub Table()
Sheets(1).ListObjects.Add(SourceType:=0, Source:="ODBC;DSN=connection_test;", Destination:=Range("A1")).QueryTable.CommandText = Array("SELECT table_test_0.`column _test` FROM db_test.table_test table_test_0")
End Sub
Sub Refresh()
Sheets(1).ListObjects(1).QueryTable.Refresh
End Sub

Force a COM server to remain open

I have a COM automation server hosted by a VB6 exe.
The COM API is used from Excel VBA:
Dim o as MyCOMAPI.MyCOMType
Set o = new MyCOMAPI.MyCOMType
o.DoSomething
When I create objects in VBA the exe is started along with COM automation and VBA can use the API.
But the exe is closed quickly and "randomly" by Excel, I guess when Excel decides it doesn't need the COM API anymore.
This behaviour is causing random errors.
The simple solution is to start the exe before running the VBA code ; in this case all is working fine as the exe won't stop running until closed by the user.
Have you some information/documentation about the way Excel VBA manages calls to hosted APIs?
Is there a way to avoid this behaviour and have the exe kept open until the VBA code decides to stop it?
This would be the default behavior for a COM automation server when the last object is dereferenced, meaning that the variable that points to the server is set to nothing.
Now, if your code looks something like this today:
Sub MyFunction()
...
Dim o as MyCOMAPI.MyCOMType
Set o = new MyCOMAPI.MyCOMType
o.DoSomething
End Sub
Then, the server life is connected to the life of the o variable. That variable gets set to nothing when the function is finished, and then the server will be shut down (unless there are other variables keeping it alive).
To make sure that your COM server is kept alive for a longer time, simply define the variable as a Public variable as in the sample below.
This sample will start and show Excel and keep it open until the ShutdownExcel function is called.
Public o As Excel.Application
Sub MakeSureExcelIsRunning()
If o Is Nothing Then
Set o = New Excel.Application
o.Visible = True
End If
End Sub
Sub ShutdownExcel()
Set o = Nothing
End Sub
From COM docs.
**Component Automation**
Shutting Down Objects
ActiveX objects must shut down in the following way:
If the object's application is visible, the object should shut down only in response to an explicit user command (for example, clicking Exit on the File menu) or the equivalent command from an ActiveX client.
If the object's application is not visible, the object should shut down only when the last external reference is gone.
If the object's application is visible and is controlled by an ActiveX client, it should become invisible when the user shuts it down (for example, clicking Exit on the File menu). This behavior allows the controller to continue to control the object. The controller should shut down only when the last external reference to the object has disappeared.
© Microsoft Corporation. All rights reserved.
When you write an COM server exe the first thing you do it take a reference to yourself when starting as a normal exe else the exe shuts down as soon as initialisation is over.

Socket connection using Excel VBA

I have a VB.NET application that successfully sends a string to the specified IP address and port.
Public Sub BroadcastData(ByVal toSend As String, ByVal PortToSendTo As Long)
Dim s As New Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
Dim sendBUF As Byte() = Encoding.ASCII.GetBytes(toSend)
Dim ep As New IPEndPoint(MainForm.IPToBroadcastTo, PortToSendTo)
s.SendTo(sendBUF, ep)
System.Diagnostics.Debug.WriteLine(s.SendTo(sendBUF, ep))
End Sub
The IPToBroadcstTo is the IPaddress of a remote computer on the local network.
On this remote computer I can receive this string and do what I want with it using VB.NET.
I would to receive the string in Excel and write it to a cell.
The code you posted is VB.NET. Excel uses VBA which although it shares some common syntax is a completely different language with a reduced set of libraries.
For example there is no Socket or IPEndPoint class in VBA.
So in short the answer is that you can't use that code to open a socket in Excel.
Have a look at the Winsock control or
Maybe you could write a .NET assembly and expose it through COM interop to allow this to be used in Excel.

Excel Application.Ready=False When Receiving Data via COM dll

I am delivering external data using the dispatch interface via a COM dll to an Excel plugin. In the VBA sink method, I check that Application.Ready = True before trying to write the data to the appropriate cell like this,
If Application.Ready = True Then
With Workbooks(bookName).Sheets(sheetName).Range(rangeName)
.Value = thisData
End With
Else
Debug.Print "Dropped Payload"
End If
I don't want to just drop the data, so I've tried to do a few things to get it right.
Call Application.OnTime instead of setting the value. Unfortunately, Excel would not let me call Application.OnTime when Application.Ready=False.
Use the technique here to start a Windows timer that then calls OnTime. The problem here was that multiple events were coming in on top of each other and they were all trying to access the AfterUDFRoutine1 simultaneously, causing a crash.
So my latest thought is to put the data into a queue and then drain the queue when Application.Ready=True. To implement this, I need an event to fire when Application.Ready changes state, but I can't find the event in the list. Does anybody know if this exists and how to expose it? Alternatively, if somebody has a better idea of how to make this work I'm very open to it. The only suggestion I can't do is to use RTD instead of the dispatch I have already - I can't change that part.

Resources