I needed exactly the same solution and here is what I did (it's already working):
I created a local http server and an local websocket server on different ports (8080 and 3000) with Node.js (using Node Webkit, but you can use pure Node.js).
On http server I set http://localhost:8080/write/ to receive a GET request with the params I wanted and to broadcast a message to the websocket server with those params.
I wrote a VBA code to push data to the local http server, using Worksheet_Calculate sub (it's an event fired every time the worksheet refresh its content).
Finnaly I made Python to listen to the websocket server (ws://localhost:3000/), waiting for the server signal.
Diving into coding details:
To create local server I used Express and ws modules. The first one to create http server and the second to create websocket server:
Express details:
var express = require('express');
var app = express();
app.get('/', function (req, res) { res.send('Hello World!') }) // to see if server is on
// broadcast data on q GET variable: http://localhost:8080/write/?q=32,34,23
app.get('/write/', function (req, res) {
wss.broadcast(req.query.q); // this line uses the variable created below
res.send();
});
var server = app.listen(8080, function () {});
ws details:
var WebSocketServer = require('ws').Server;
wss = new WebSocketServer({port: 3000});
wss.on('connection', function(ws) {
// you can use this event to perform some action when python get connected
ws.send("you're connected");
// use this event if you need websocket to receive message
ws.on('message', function(message) {
ws.send(message);
});
});
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
client.send(data);
});
};
To send data from Excel to the http server (I tried to use websocket, but I couldn't figure out how Excel connects to a websocket):
Function postServer(url, data)
Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP")
objHTTP.Open "GET", url & data, False ' true para asynchronous calls
objHTTP.send '(dados)
postServer = 1 'It's a good idea to get the responseHTML from server and verifies if the everything is all right
End Function
Use this function inside Worksheet_Calculate() to send data:
Private Sub Worksheet_Calculate()
server = "http://localhost:8080/write/?q="
'data = <something> 'catch your data with vba code
postServer(server,data)
End sub
The trick detail here is how to know when some data is already sent so you can avoid send it twice or more. You'll have to create your method based on how your data is organized on the sheet. For me, a have a number column, ordered and a cell registering the last number I sent.
Ok! Now you have to prepare Python to receive this data:
I downloaded the websocket-client 0.25.0 module. And here is the python code to listen to the websocket server:
import sys
import websocket
import thread
import time
wsAddress = "ws://localhost:3000/"
def on_message(ws, message):
print message # you got it!
def on_error(ws, error):
print error
def on_close(ws):
print "### closed ###"
def on_open(ws):
print "conectado"
if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp(wsAddress,
on_message = on_message,
on_error = on_error,
on_close = on_close)
ws.on_open = on_open
ws.run_forever()
If you're on a local network, you can use IP (or machine names) to post and listen to the server (it's awesome). Here is the code to discover the id with node.js:
var os = require('os');
var ifaces=os.networkInterfaces();
for (var dev in ifaces) {
var alias=0;
ifaces[dev].forEach(function(details){
if ((details.family=='IPv4')&&(details.address!="127.0.0.1")&&(details.internal === false)) {
console.log(details.address);
++alias;
}
});
}
I hope I've helped. If you let some questions, just let me know.