VBA userform is "Not Responding" while macro is running - vba

Why my userform shows "Not Responding" when I run the following code? I have been trying to resolve it, but it is not resolved yet.
Actually it works sometimes. I think the problem has something to do with the screen updating.
' The input button in Sheet1
Sub Rectangle1_Click()
'Remember time when macro starts
StartTime = Timer
' To improve speed and performance
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
' Show the userform
UserForm1.Show vbModeless
UserForm1.Label1.Caption = "Calculation in progress ... " & vbNewLine & "Please be patient"
UserForm1.Label1.Font.Size = 12
UserForm1.Top = (Application.Height / 2) - (UserForm1.Height / 2)
UserForm1.Left = (Application.Width / 2) - (UserForm1.Width / 2)
UserForm1.CommandButton1.Visible = False
UserForm1.Repaint
Call Insert_RawData
'Determine how many seconds code took to run
SecondsElapsed = Round(Timer - StartTime, 2)
UserForm1.Label1.Caption = "This code ran successfully in " & SecondsElapsed & " seconds"
UserForm1.CommandButton1.Visible = True
' Return back to the original settings
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.Calculation = xlCalculationSemiautomatic
End Sub

It could be a number of things. If the issue is intermittent like you mention, then in all likelihood the program IS working, and Windows is just labeling it non-responsive because the program is working too hard to respond to the OS.
The likely issue is probably one, or a combination, of the following:
The amount of data being processed by Insert_RawData
The amount of data in the workbook(s) open when the macro is running
Insert_RawData is encountering an error due to a bad/unhandled value in one of the cells it works with (less likely)
Some suggestions to try and narrow the source down:
If there's a way to consistently run so that you get the "Non-Responsive" in the Excel window, insert a break point at the call to Insert_RawData and watch it run to see if it's hitting an error
Alternatively, try to put some error checks into Insert_RawData and break points on the code handling the case that the error check fails
Capture the amount of data processed (bytes, cells, whatever is easiest) during each run of the macro along with the run time & see if there's a threshold your hitting (ex. <= 1 GB runs fine, but >1GB and the application looks frozen)
Unless you are hitting an error in Insert_RawData though, it's likely that the macro WILL complete, it just might take a really long time.

Related

VBA program stops to refresh the worksheet

I'm making my own Conway's Game of Life on VBA where the current state is displayed on a worksheet.
Because I'm not skilled, the implementation is probably not very efficient (I use 2 boolean matrices to model the current state and the next one).
To display the result at each step, I've sub display() that took the matrix_currentand color each cell in black or white. To make the whole process smoother, I've wrapped Application.ScreenUpdating = Falseand Application.ScreenUpdating = True . Short story long, it looks like that :
Private Sub display()
Application.ScreenUpdating = False
For i = 0 To sizeGrid
For j = 0 To sizeGrid
If matrix_curr(i, j) Then
Cells(i + xmin, j + ymin).Interior.ColorIndex = 1
Else
Cells(i + xmin, j + ymin).Interior.ColorIndex = 2
End If
Next
Next
Application.ScreenUpdating = True
End Sub
Before each Call display() I call the method Sleep() to let enought time to watch each step.
So, here is my issue:
The display on the worksheet often stops after a number of steps. However, the programm is still running and finally shows the last state. So basically, I can monitor the beginning, then nothing change until the last step that are displayed.
Everything happen as if the worksheet suddenly stop to be refreshed.
Do you have any idea to solve this issue.
I thank you in advance for your help (and hope that I make myself understood
despite my poor english)
My problem is that after a number of steps, nothing more happen on the screen (as if it was freeze).
That's because Excel is essentially running out of breath - it's basically not keeping up with all the ScreenUpdating toggles.
When you toggle Application.ScreenUpdating back on once, Excel happily responds by repainting itself.
When you're running a busy loop, it's prioritizing execution of the VBA code and the Excel UI goes:
(not responding)
This is normal: there's a lot of things to process, so it's processing them - updating the UI, raising worksheet events, responding to user actions, calculating cells, all these things "drop priority", until the VBA code completes.
Try adding a DoEvents instruction immediately after toggling Application.ScreenUpdating back on; this explicitly tells Excel "okay, go ahead, process whatever other stuff you've got, then come back here when you're ready". I'd warmly recommend leaving Application.EnableEvents off and Application.Calculation set to xlCalculationManual until the code completely executed.

Power Query Tables won't download data until VBA finishes executing

I have a spreadsheet with 4 worksheets, each one connected to a power query which connects to an OLEDB database and runs a select to import data into the workbook.
I am trying to automate the refresh of the queries.
I have VBA in the workbook which
- disables background refresh,
- runs Workbook.RefreshAll,
- resets the background refresh to true (as I need this for the automation software to be able to run it in the first place) and
- then waits 30 seconds to give the automation software a bit of time before it starts saving the workbook.
All the software does is call the macro in the workbook and then save following execution.
The queries correctly execute one after the other and I can tell the data in the tables has refreshed.
The power query confirmation that the rows have been downloaded happens after the VBA completes executing, so the automation software saves it before this is done and Excel reports the download as having failed. This isn't a problem when everything works, but we won't know when the download has truly failed, unless I add in some sort of a row count comparison which is really a workaround rather than an actual solution.
I have tried creating two subs in the workbook, one to do the refresh and then another which calls the first sub and then waits 30 seconds, I was hoping the download would complete after the first sub finishes executing, but this doesn't happen. I have tried refreshing one connection at a time instead of using RefreshAll, tried refreshing the actual power query tables instead of the connections and have tried refreshing with background query set to true and then looping until the refresh is marked as complete (which works if you step through it, but crashes if you just run the VBA in full).
I also tried saving the spreadsheet at the end of the VBA, but it still waits until the save is complete to update the power query status.
My latest VBA:
Sub Workbook_RefreshAll()
Application.DisplayAlerts = False
For Each objConnection In ThisWorkbook.Connections
'Temporarily disable background-refresh
objConnection.OLEDBConnection.BackgroundQuery = False
objConnection.OLEDBConnection.MaintainConnection = False
Next
ActiveWorkbook.RefreshAll
For Each objConnection In ThisWorkbook.Connections
'Re-enable background-refresh
objConnection.OLEDBConnection.BackgroundQuery = True
objConnection.OLEDBConnection.MaintainConnection = True
Next
newHour = Hour(Now())
newMinute = Minute(Now())
newSecond = Second(Now()) + 30
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime
End Sub
(I can't remember whether the maintain connection parameter actually helped as I as trying to force the connection to drop after each refresh, but it works so haven't taken it out.)
Instead of Application.Wait try the following:
Do until now() >= waittime
DoEvents
Loop

Run macro automatically via vbscript from timer

I have a macro that downloads some information from the internet and I need to schedule it to run automatically starting at a certain time of day and running repeatedly both at set time intervals although occasionally at specific times output by the macro.
I have approached the problem in two ways, both of which have presented problems that I can't figure out. The first approach is using a timer sub that runs the macro using the Application.OnTime command with the runtime derived from a cell in the workbook that is updated by the macro.
This method works pretty well if I am on the computer doing something else. However, I have noticed that if I leave, even if the computer doesn't go to sleep, the program inevitably stops re-running after 30min or so. Sometimes it also stops re-running even when I'm active on the computer. Why is this? What could be causing this? Also, naturally, I can't schedule the program to open and run automatically from within the macro, so I turned to the VBScript & Task Scheduler method for this part of the solution.
I have, however, encountered two problems with the execution of the VBScript. First, is that it often fails to start when run by Task Scheduler. Second, is that when it does run, the Application.OnTime command within the macro doesn't work. This is a problem because the macro needs to run sometimes at irregular time intervals which are determined during the course of the day as the macro runs through its iterations. Why would the vbscript fail to run when task manager tries, and why would it not initiate the application.ontime command the way the macro does when I run it manually?
VBA Timer Code:
Sub Timer()
Dim Runtime As Date
If Time <= TimeValue("17:45:00") Then
Workbooks("10am_Swing_Report").Sheets("Parameters").Cells(17, 2).Value = 10
ElseIf Time > TimeValue("17:45:00") And Time <= TimeValue("18:15:00") Then
Workbooks("10am_Swing_Report").Sheets("Parameters").Cells(17, 2).Value = 13
ElseIf Time > TimeValue("18:15:00") And Time <= TimeValue("18:45:00") Then
Workbooks("10am_Swing_Report").Sheets("Parameters").Cells(17, 2).Value = 16
ElseIf Time > TimeValue("18:45:00") And Time <= TimeValue("19:15:00") Then
Workbooks("10am_Swing_Report").Sheets("Parameters").Cells(17, 2).Value = 19
End If
Workbooks("10am_Swing_Report").Sheets("Parameters").Range("B16").Calculate
If Time > Workbooks("10am_Swing_Report").Sheets("Parameters").Range("B16").Value Then
Runtime = Time + TimeValue("00:00:30")
Else
Runtime = Workbooks("10am_Swing_Report").Sheets("Parameters").Range("B16").Value
End If
Application.OnTime TimeValue(Runtime), "Swingtimer"
Workbooks("10am_Swing_Report").Sheets("Parameters").Range("C16").Value = Runtime
Workbooks("10am_Swing_Report").Save
End Sub
Thanks!
I've updated the Vbs code to include a validation that the runtime has been passed, but I'm still encountering a problem with Task Scheduler failing to start the task. I'm getting the following error: "Launch request ignored, instance already running" followed by: "Task Start Failed". I was originally thinking this was because the Vbscript was still running from the previous instance, but I'm getting this from the very beginning.
Option Explicit
Dim xlApp
Dim xlBook
Dim runtime
Dim xlSheet
Set xlApp = CreateObject("Excel.Application")
xlApp.DisplayAlerts = False
'xlApp.Application.DisplayAlerts = True
Set xlBook = xlApp.Workbooks.Open("C:\Users\DORIAN\Dropbox\Swing_Report.xlsm",1,False)
Set xlSheet = xlBook.Sheets("Parameters")
'xlBook.application.Visible = True
'MsgBox FormatDateTime(xlSheet.Range("B16").Value,3)
runtime = TimeValue(FormatDateTime(xlSheet.Range("B16").Value,3))
'MsgBox runtime
If Time > runtime Then
xlApp.Run "Swingtimer"
'MsgBox "Running..."
WScript.Sleep 30000
Else
xlApp.Application.OnTime runtime, "Swingtimer"
'MsgBox "Timer Set"
End If
xlbook.close True
WScript.Quit
Could you do it in a different way?
1)
Run vbscript it in Windows Scheduler say every 1 minute or 1 hour or ….
2)
Put some validation inside VBscript
If Condition then
Execute your code
Else
Stop vbscript
End if
Using this you probably can get rid of OnTime event handler
Best regards
Alex
I think you are over complicating things. You just need a Workbook_Open event and Windows Task Scheduler.
Something like this (customize to suit your needs).
Private Sub Workbook_Open()
Msgbox Date
Worksheets("Sheet1").Range("A1").Value = Date
End Sub
Schedule the event using the Windows Task Scheduler.
http://www.sevenforums.com/tutorials/11949-elevated-program-shortcut-without-uac-prompt-create.html

Allow user to kill process during wait in VBA

I have written a program to print multiple .pdfs with varying file extensions off of an Excel spreadsheet list.
The problem is that it takes anywhere from 30 seconds to a minute for the printer to receive the pdf after the line: Application.SendKeys "^p~", False is called.
To get by this I used Application.Wait (Now + TimeValue("0:01:03")) to wait for a minute (plus 3 seconds just to be safe) before closing the file.
To me there seems like there should be a better way than just causing the program to wait, so I looked around a little and found a question about this lovely gem known as Application.OnTime.
I tried a sample of one of the answers:
Sub test2()
ActiveSheet.Cells(1, 1).Value = ActiveSheet.Cells(1, 1).Value + 1
Application.OnTime Now + TimeValue("00:00:5"), "test2"
End Sub
However when I tried to stop the above code it kept going on an infinite loop and I was unable to stop it until I killed excel using the windows task manager.
I would like to be able to add in a little message box or something of the sort so that the user can click in between the wait time.
So that while the program is waiting for a minute, the user can either manually click and start the program on the next pdf, or click another button to exit if they need to stop printing early. Something like this:
Sub pdfPrinter()
'...
'Insert all the other code here
'...
Application.SendKeys "^p~", False
Application.OnTime Now + TimeValue("00:01:02"), "pdfPrinter"
continue= MsgBox("Click Retry to print again, or cancel to stop printer.", vbRetryCancel)
If continue = vbRetry Then
Call pdfPrinter
ElseIf continue = vbCancel Then
Exit Sub
End If
End Sub
Application.OnTime(unlike Application.Wait) is Asynchronous
so code after
Application.OnTime Now + TimeValue("00:01:02"), "pdfPrinter"
Runs Immediately.
If you want to print another PDF you need to call Application.OnTime with a different schedule of the 1st one.
Now, canceling Application.OnTime, when it is already started is a different story:
To do that you need to store that time that the respective function is scheduled to run and then Cancel it using the following code:
Application.OnTime Now + TimeValue("00:00:50"), "test", schedule:=False

Application.ScreenUpdating stops macro execution in VBA

I am not experienced VBA programmer, and I need community to find a problem with the Excel.
My problem is that in Excel, code stops execution immediatly after following line:
Application.ScreenUpdating = True
I use following example code from msdn website:
Dim elapsedTime(2)
Application.ScreenUpdating = True
For i = 1 To 2
If i = 2 Then Application.ScreenUpdating = False
startTime = Time
Worksheets("Sheet1").Activate
For Each c In ActiveSheet.Columns
If c.Column Mod 2 = 0 Then
c.Hidden = True
End If
Next c
stopTime = Time
elapsedTime(i) = (stopTime - startTime) * 24 * 60 * 60
Next i
Application.ScreenUpdating = True
MsgBox "Elapsed time, screen updating on: " & elapsedTime(1) & _
" sec." & Chr(13) & _
"Elapsed time, screen updating off: " & elapsedTime(2) & _
" sec."
Source: http://msdn.microsoft.com/en-us/library/office/ff193498.aspx
However, Msgbox never get executed, nor VBA shows any error - it just silently fails.
Anyidea why this is happening and how to fix that ?
This is not an answer; like earlier posters I am unable to get this routine to fail.
Firstly, I will say this is a dreadful piece of code. I cannot understand why Microsoft posted something this bad. For example:
elapsedTime is not typed. (It should be Dim elapsedTime(2) As Double)
i, startTime and stopTime are not defined.
The Activate is within the timed block for the first loop so, if Sheet1 is not the active sheet at the beginning, the time to activate it is added to the first loop's duration.
The columns are not unhidden between the two loops so the second loop has nothing to do. If you run the routine a second time, the two loops have the same duration.
There is a bug in Excel which I encounter very infrequently and not for a couple of years. When I do encounter it, it takes me so long to discover the cause that I am behind schedule and forget to record the details for next time. There are certain errors for which Excel does not stop and report the fault; instead it terminates the current function and continues with the next statement in the calling routine. This subroutine has been called directly, so it would just stop without finishing.
My only suggestion is that there is something about this code on your Sheet1 on your computer that causes this error.
You seem to think the Application.ScreenUpdating = True statement is failing. This is possible but unlikely. From your description, all you know is that the routine does not reach the MsgBox statement.
I suspect c.Hidden = True. I have seen a question asking about a maximum number of hidden columns but no one knew of a maximum. One answer was you cannot hide part of a merged area but I cannot duplicate that error. Look at your Sheet1: are some even columns hidden but not all? Unhide the columns and try again. Does the routine fail at a consistent column? Does it fail after hiding something like 1,024 columns?
I wish you luck with any investigation. However, I suggest you abandon this deadful code and accept that Application.ScreenUpdating = False will reduce the run time of any routine that updates the active worksheet.
In this situation, there was following problem, that didn't immediatly found at first glance:
There is auto-validation rules in the Sheet
Auto-validation rules are based on user-space function, i.e. code rule for matching is formula: =NOT(IsValidCell(INDIRECT("RC";FALSE)))
there is a problem with this function.
Example of baqd code:
Function IsValidCell(ByVal CellValue As String) As Boolean
IsValidCell = False
If CellValue Like "#####" Then
IsValidColumn = True ' Notice bug
Else ' Notice second bug
End Function
Result is that code in completely unseparated routine fails when excel tries to recalculate rules.