Application.DoEvents Takes long time - vb.net

i have s Sub() like this, to download HTML page using GeckoWebBrowser
wb1 = Nothing
wb1 = New Gecko.GeckoWebBrowser
wb1.Navigate(v_url)
totalticks = 0
loadtimer.Start()
Do
If m_stop = True Then Exit Do
If wb1.IsBusy = False Then 'wb1.ReadyState = WebBrowserReadyState.Complete Then
If IsNothing(wb1.Document) = False Then
If IsNothing(wb1.Document.Body) = False Then
Exit Do
End If
End If
ElseIf wb1.IsBusy = True And String.IsNullOrEmpty(sucessID) = False Then 'wb1.ReadyState = WebBrowserReadyState.Interactive And String.IsNullOrEmpty(sucessID) = False Then
If IsNothing(wb1.Document) = False Then
If IsNothing(wb1.Document.Body) = False Then
If InStr(wb1.Document.Body.InnerHtml, sucessID, CompareMethod.Text) <> 0 Then
Exit Do
End If
End If
End If
End If
If totalticks = 15 Then
'wb1.Dispose()
wb1.Stop() 'wb1 = New System.Windows.Forms.WebBrowser
wb1.Reload(Gecko.GeckoLoadFlags.IsRefresh)
'wb1.ScriptErrorsSuppressed = True
'wb1.Navigate(v_url)
ElseIf totalticks >= 30 Then
wb1.Stop()
Exit Do
End If
'FreeUpMemory()
Application.DoEvents()
Loop
My problem is that Application.DoEvents takes a long time to process and finish.
P.S i am using STA thread to run this Sub()

Ok people here is how my problem was solved, and thanks for the others who tried to help! much appreciated. Ok here it goes:
Basically this 2 lines where in loop
wb1 = Nothing
wb1 = New Gecko.GeckoWebBrowser
So this for some reason was making the messages queue too crowded therfore the application.doevents was taking too long to process those messages.
So all i did was decalring wb1 as gloabl object (i.e. dim wb1 as New GeckoWebBrowser) this way i didnt need to set it to nothing then initialize the object again. So anyway i removed the above 2 lines and used the instaniated object instead.
Now things running so smooth and fast, even with DoEvents() !!! YAY!!

Try using a BackgroundWorker instead of running the Download on the Main thread. You can pass results from the Backgroundworker back to the Main thread through the Result property that gets passed to the RunWorkerCompleted event handler. You don't need the Application.DoEvents in your loop then and still have the Main thread responsive.
See this link for a tutorial:
http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

Related

Shapes.Visible True and False within Loop VBA

I have this piece of code which I would like to show and hide some Shape objects one by one, in order to make a little animation. However, nothing happens as the code executes, all images are shown by once when the code stops running.
Sub test()
For i = 1 To 4
Sheets("Game").Shapes("North" & i).Visible = True
Sleep 500
'Sheets("Game").Shapes("North" & i).Visible = False
'by setting it to false i'd like to achieve the animation effect
Debug.Print i
DoEvents
Next i
End Sub
DoEvents allows other code (e.g. Excel's own) to run and handle things like user clicking on another worksheet (which invokes any Worksheet.Change or Workbook.WorksheetChange handler)... or just repainting itself.
By invoking DoEvents once per loop, Excel doesn't get a chance to repaint between the visibility toggles: it's already busy running your loop.
So you need to toggle visibility on, let Excel repaint (DoEvents), sleep for your animation delay (500ms seems a tad slow IMO), then toggle visibility off and let Excel repaint again, i.e. invoke DoEvents one more time.
If the Game worksheet is in ThisWorkbook, then I'd warmly recommend you give it a CodeName - select it in the Project Explorer, then look at its properties (F4) and change its (Name) to, say, GameSheet.
This gives you a global-scope object variable so that you don't need to dereference the same worksheet twice per iteration - heck you could even dereference its Shapes collection only once:
Private Const ANIMATION_DELAY As Long = 100
Sub test()
With GameSheet.Shapes
For i = 1 To 4
Dim currentShape As Shape
Set currentShape = .Item("North" & i)
currentShape.Visible = True
DoEvents
Sleep ANIMATION_DELAY
currentShape.Visible = False
DoEvents
Debug.Print i
Next
End With
End Sub
Amended the code by setting DoEvents after toggling True and Falseand now it works:
Sub test()
For i = 1 To 4
Sheets("Game").Shapes("North" & i).Visible = True
DoEvents
Sleep 100
Sheets("Game").Shapes("North" & i).Visible = False
DoEvents
'by setting it to false i'd like to achieve the animation effect
Debug.Print i
Next i
End Sub

Workbook.CheckIn always produces an error the first time it's called?

I have some workbooks stored in a document library on Sharepoint 2007. I want to check out a workbook, modify it, and check it back in.
Using the following code:
Option Explicit
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub test()
Dim bk As Workbook
Dim path As String
path = "http://sharepoint/sites/test/TEST_Relink.xlsm"
If Workbooks.CanCheckOut(path) Then
Application.DisplayAlerts = False
Workbooks.CheckOut path
DoEvents
Set bk = Workbooks.Open(path, False)
bk.Sheets("test").Range("h1").Value = "modified " & Now
DoEvents
Sleep 10000
bk.checkIn True
Application.DisplayAlerts = True
End If
End Sub
The bk.checkIn call always produces the following run-time error:
Method 'CheckIn' of object '_Workbook' failed
After I go into Debug, I press F5 to continue and the check-in always occurs successfully.
I added the 10-second delay with Sleep 10000 because I was thinking that maybe the check-out was taking a while to propagate to the server. But no matter how much time I set for Sleep, this same issue keeps occurring. Any thoughts?
EDIT:
I tried using a looped check of .CanCheckIn as follows:
While Not bk.CanCheckIn
DoEvents
Wend
bk.checkIn True
This gave the same error.
For those finding this like I did, I had
Workbooks(logFileName).CheckIn SaveChanges:=True, Comments:="New row added from " & mainFile
This produced the error message like yours, however on entering debug and pressing f5 would action. So here is my complex solution.....I just split out the code to the following
Workbooks(logFileName).Save
Workbooks(logFileName).CheckIn Comments:="New row added from " & mainFile
Hope this helps others.
Use this:
Dim xl As Excel.Application
Set xl = CreateObject("Excel.Application")
xl.AutomationSecurity = msoAutomationSecurityForceDisable
xl.EnableEvents = False
xl.DisplayAlerts = False
'code to checkin/checkout
xl.EnableEvents = True
xl.DisplayAlerts = True
You probably already figured it out but I thought I'd post it for anyone else who comes here looking for an answer.
If you are setting SaveChanges to True then you MUST also set Comments to be a String (a null value won't do)
So in your example you would need to do this:
bk.CheckIn True, ""

Toggle Buttons in Powerpoint

I am trying to insert toggle buttons into several pages on a powerpoint. I've got the buttons to behave the way I want, but now I can't see to do two things:
A. Run the program!!! I've deleted everything and started from scratch, except for my first code (see below) and have nothing else written. What do I need to fix it. When I click on the shape that is connected to YourName() nothing happens.
B. I'd like to set the buttons' values to 0 at the start. Once this runs, do you think my code will do that?
Thanks
Sub YourName()
Dim userName As String
Dim ToggleButton1 As ToggleButton
Dim ToggleButton2 As ToggleButton
Dim ToggleButton3 As ToggleButton
Dim ToggleButton4 As ToggleButton
Dim done As Boolean
done = False
While Not done
userName = InputBox(Prompt:="My name is", Title:="Input Name")
If userName = "" Then
done = False
Else
done = True
End If
Wend
FeedbackAnswered = False
ActivePresentation.Slides(2).ToggleButton("ToggleButton1").Value = 0
ActivePresentation.Slides(2).ToggleButton("ToggleButton2").Value = 0
ActivePresentation.Slides(2).ToggleButton("ToggleButton3").Value = 0
ActivePresentation.Slides(2).ToggleButton("ToggleButton4").Value = 0
ActivePresentation.SlideShowWindow.View.Next
End Sub
Your code won't compile (open the IDE, open the module the code's in, choose Debug | Compile). When you try to run broken code within a slide show (as it seems you're doing) PPT doesn't issue any error messages, it just won't attempt to run the code at all.
This at least compiles; I didn't have time to create a presentation with the correct shapes but hey, had to leave SOME of the fun for you:
Option Explicit
Sub YourName()
Dim userName As String
' Dim these as Object; there's no such thing as ToggleButton
Dim ToggleButton1 As Object
Dim ToggleButton2 As Object
Dim ToggleButton3 As Object
Dim ToggleButton4 As Object
Dim done As Boolean
' You forgot one:
Dim FeedbackAnswered As Boolean
done = False
While Not done
userName = InputBox(Prompt:="My name is", Title:="Input Name")
If userName = "" Then
done = False
' you might want to add an Exit Sub here, otherwise the poor
' user has no way out
Else
done = True
End If
Wend
FeedbackAnswered = False
' Fixed these too:
ActivePresentation.Slides(2).Shapes("ToggleButton1").OLEFormat.Object.Value = 0
ActivePresentation.Slides(2).Shapes("ToggleButton2").OLEFormat.Object.Value = 0
ActivePresentation.Slides(2).Shapes("ToggleButton3").OLEFormat.Object.Value = 0
ActivePresentation.Slides(2).Shapes("ToggleButton4").OLEFormat.Object.Value = 0
ActivePresentation.SlideShowWindow.View.Next
End Sub

Excel is waiting for another application to complete an OLE action

Before you go for the obvious: Application.DisplayAlerts = False has not solved my problem.
I have written a VBA procedure (initiated in Excel 2010) which loops around an array containing different Excel files. The loop opens the file, refreshes the data, saves and closes the file for each item in the array. I have written an error catch sub routine so I log which excel files have failed to open/refresh/save etc so a user can manually check them.
Some files are quite large and involve a large amount of data moving across the network; sometimes I get a dialog box with: Excel is waiting for another application to complete an OLE action.
I could use Application.DisplayAlerts = False to disable the message but this would presumably disable all alerts so I couldn't catch the errors?
Further I have tested using the line and it doesn't stop the dialog box pop-up. If I press enter it carries on but will likely pop-up again a few minutes later.
Is there a way to stop is message specifically without stopping other alerts?
NB. My process has a control instance of Excel which runs the VBA and opens the workbooks to be refreshed in a separate instance.
Thanks for your help
An extract of my code is below which contains the refresh elements
Sub Refresh_BoardPivots_Standard()
' On Error GoTo Errorhandler
Dim i
Dim errorText As String
Dim x
Dim objXL As Excel.Application
Set objXL = CreateObject("Excel.Application")
GetPivotsToRefresh ' populate array from SQL
For Each i In StandardBoardPiv
DoEvents
'If File_Exists(i) Then
If isFileOpen(i) = True Then
errorText = i
Failed(failedIndex) = errorText
failedIndex = failedIndex + 1
Else
objXL.Visible = True 'False
objXL.Workbooks.Open FileName:=i
If objXL.ActiveWorkbook.ReadOnly = False Then
BackgroundQuery = False
Application.DisplayAlerts = False
objXL.ActiveWorkbook.RefreshAll
objXL.Application.CalculateFull
objXL.Application.DisplayAlerts = False
objXL.ActiveWorkbook.Save
objXL.Application.DisplayAlerts = True
objXL.Quit
Else
errorText = i
Failed(failedIndex) = errorText
failedIndex = failedIndex + 1
objXL.Application.DisplayAlerts = False
objXL.Quit
Application.DisplayAlerts = True
End If
End If
' Else
' errorText = i
' Failed(failedIndex) = errorText
' failedIndex = failedIndex + 1
' End If
DoEvents
If Ref = False Then
Exit For
End If
Next i
Exit Sub
'Errorhandler:
'
'errorText = i
'Failed(failedIndex) = errorText
'failedIndex = failedIndex + 1
'Resume Next
End Sub
"Waiting for another application to complete an OLE action" isn't an alert message you can just turn off and forget, sometimes the macro will be able to continue on after, but in my experience if you are getting that error its only a matter of time until the problem crashes/freezes your whole macro so it should definitely be troubleshot and corrected.
I only get that error when I am using additional Microsoft Office Applications (other than the Excel that is running the code) as objects and one of them has an error- the Excel running the code doesn't know that an error occurred in one of the other applications so it waits and waits and waits and eventually you get the "Waiting for another application to complete an OLE action" message...
So to troubleshoot this sort of problem you got to look for the places you use other MSO apps... In your example, you have an additional instance of Excel and you are pulling data from Access, so its most likely one of those two that is causing the problems...
Below is how I would re-write this code, being more careful with where the code interacts with the other MSO apps, explicitly controlling what is happening in them.. The only piece I couldn't really do much is GetPivotsToRefresh because I cant see what exactly youre doing here, but in my code I just assumed it returned an array with a list of the excel files you want to update. See code below:
Sub Refresh_BoardPivots_Standard()
Dim pivotWB As Workbook
Dim fileList() As Variant
Dim fileCounter As Long
Application.DisplayAlerts = False
fileList = GetPivotsToRefresh 'populate array from SQL
For fileCounter = 1 To UBound(fileList, 1)
Set pivotWB = Workbooks.Open(fileList(fileCounter, 1), False, False)
If pivotWB.ReadOnly = False Then
Call refreshPivotTables(pivotWB)
pivotWB.Close (True)
Else
'... Error handler ...
pivotWB.Close (False)
End If
Next
End Sub
Public Sub refreshPivotTables(targetWB As Workbook)
Dim wsCounter As Long
Dim ptCounter As Long
For wsCounter = 1 To targetWB.Sheets.Count
With targetWB.Sheets(wsCounter)
If .PivotTables.Count > 0 Then
For ptCounter = 1 To .PivotTables.Count
.PivotTables(ptCounter).RefreshDataSourceValues
Next
.Calculate
End If
End With
Next
End Sub
So I created my own 'refreshPivotTables' but you could have embedded that into the master sub, I just thought the loops and loop counters might get a little messy at that point...
Hope this helps,
TheSilkCode

Auto Exit Powerpoint Slide Show at the end of run

Good morning,
I am working on a macro to autorefresh excel links before slideshow, loop through slideshow and then restart over and over again. The issue I am having is the slideshow stops but doesnt exit so the wait timer doesnt have a chance to even kick in.
Can I get a suggestion of how I might fix this?
Sub LoopAllSlides()
Dim i As Integer
For i = 0 To 2000
Dim Endpoint As Single
Endpoint = Timer + 10
Do While Timer < Endpoint 'This loop works dont delete
DoEvents
Loop
ActivePresentation.UpdateLinks
With ActivePresentation.SlideShowSettings
.AdvanceMode = ppSlideShowUseSlideTimings
.LoopUntilStopped = msoFalse
.Run
End With
Next i
End Sub
You can always do this with the Application.Quit function, which will exit out of your current sub. So, something like this:
Sub LoopAllSlides()
Dim i As Integer
For i = 0 To 2000
Dim Endpoint As Single
Endpoint = Timer + 10
Do While Timer < Endpoint 'This loop works dont delete
DoEvents
Loop
ActivePresentation.UpdateLinks
With ActivePresentation.SlideShowSettings
.AdvanceMode = ppSlideShowUseSlideTimings
.LoopUntilStopped = msoFalse
.Run
End With
Next i
'Quit Application Function
IWishICouldQuitYou
End Sub
Function IWishICouldQuitYou()
With Application
For Each w In .Presentations
w.Save
Next w
.Quit
End With
End Function