VBA-tools / VBA-Web

VBA-Web: Connect VBA, Excel, Access, and Office for Windows and Mac to web services and the web
http://vba-tools.github.io/VBA-Web/
MIT License
2k stars 493 forks source link

VBA-Web in Outlook #199

Open Sophist-UK opened 8 years ago

Sophist-UK commented 8 years ago

I am trying to make VBA-Web work in Outlook (to do automatic web services calls when particular emails arrive). Since these will be in the background and emails could come in in a bunch, I want these to run in the background. I am making progress towards making VBA-Web work in Outlook, but there is one issue I need some advice on...

In module WebAsyncWrapper subroutine web_StartTimeoutTimer it uses Application.OnTime to set an asynchronous timeout timer for the web call. Application.OnTime is an Excel specific method, so this doesn't work in Outlook.

I have though about replacing this with an Outlook Task Reminder - but before I start coding this I thought I would ask why WebAsyncWrapper uses its own timeout timer, rather than using the WinHttpRequest.SetTimeouts and the OnError event?

It seems to me that:

  1. We should have an OnError event handler in any case to handle other errors
  2. Using SetTimeouts and OnError would be simpler and more compatible than Application.OnTime - and would have greater granularity (millisecs rather than secs).

If you agree with the principle, I am happy to code, test and submit as a PR.

Sophist-UK commented 8 years ago

A second similar issue has arisen,this time with Application.Run. It seems to me that we can replace much of Application.Run with the CallByName function.

Application.Run works only with Modules, and CallByName only with objects, but in most cases we use Application.Run to call a routine in WebHelpers which then runs the object method. So this change might simplify the code.

Again if you agree with the principle, I am happy to code and test and submit as a PR.

Note: WebAsyncWrapper uses this to call a handler for the WebResponse - is there a particular reason that you do not use an Event to call an Event Method instead?

timhall commented 8 years ago

The timeout code was from the pre-WinHttp implementation so I'm definitely open to new approaches. If you don't mind attempting the OnError approach in a PR, I'll be happy to review it. Sounds good!

As for the CallByName change, I'm currently using callbacks in modules for my code and I'd like to avoid a breaking change by removing it. As an alternative, I added the EnableCustomFormatting flag (in #103) to deal with cases where Application.Run is missing for WebHelpers, so there may be room to bypass it similarly in WebAsyncWrapper and add a CallByName alternative. That plus switching to the OnError event seems like it would make it compatible with Windows in general (rather than just Excel).

As far as the evented approach, I looked into it, but didn't have much experience with events in VBA so I skipped it. I'm open to suggestions though.

Sophist-UK commented 8 years ago

I think I can resolve the timer issues without creating any compatibility issues in WebAsyncWrapper by using the WinHttpRequest timeout functionality and catching its OnError event.

It might be possible to add functionality to use an event as a callback alongside the use of method name string - but I am not sure it is worth it because...

I am planning a WebClientAsync class which properly wraps the WebClient class and merges in the WebAsyncWrapper code – the idea being that you can use this as an almost drop in replacement for WebClient - just replacing WebClient.Execute with WebClientAsync.ExecuteAsync and sending back the results via an Event. This would be Windows only, and you have to call it from a Class rather than a normal Module, but if you are wanting Async you are probably going to be doing something complicated enough to be using classes anyway.

I will try to replace Application.Run for everything except WebAsyncWrapper (which needs it), which would then make everything except this work in Outlook etc.

However, I will wait until you have accepted / rejected all my existing PRs before I do any of the above because it will get too complicated to manage the code unless I have a new base to work from.

dlong500 commented 8 years ago

What is the status of this? I'd also like to use this library in Outlook, but I can't tell if anything has been resolved on that front.

timhall commented 8 years ago

Hi @dlong500 this issue is particular to WebAsyncWrapper (an optional class). I know a few people that have used VBA-Web successfully with Outlook, so I'd say give it a try. Let me know if you run into any other Outlook-specific issues.

dlong500 commented 8 years ago

Ok. Are there any special things that need to be done to get it set up in Outlook? The install instructions only mention using an xlsm file.

timhall commented 8 years ago

Sorry, been meaning to add some details on that.

  1. Download the latest release (and unzip)
  2. Import all of the files from the src/ folder (except WebAsyncWrapper) to your project

That should do it!

gtdr5g commented 6 years ago

Hi, I tried to use VBA-Web in Outlook, but I get a compile error on WebResponse : "Private object modules cannot be used in public object modules as parameters or return types for public procedures, as public data members, or as fields of public user defined types".... The same works ok for Excel, so is it possible that Outlook has a different type for WebResponse compared to Excel? I have very little experience in VBA and do not know how to deal with this error. Problem seems to be that the Outlook object-explorer shows WebResponse as Private Class