Why UserForm is "Not Responding" During Run Time in VBA Excel? - vba

I'm very new with VBA Excel and i only know the things as far as i need for this report formatting task.
I'm almost done with my task but when i run the program and start the progress, eventhough it works successfully, GUI is not responding for a minute. I share my code here, is something wrong with it? Can you suggest me any best-practice? I don't want it to freeze because it will look bad to my manager.
Just to make it clear, by "not responding" i mean it freezes on the screen and says "Not Responding" on it's windows frame and when i click on it, it gives a message like this:
*ps: the sheet that i get records has 20997 rows and 7 columns and i make some records to another sheet on same file sized and 20997 lines 23 columns. And my GUI is very simple, it has nothing but a CommandButton that starts the progress.
How can i fix this?

You can prevent the freezing of excel window by putting
DoEvents
inside your loop.

This happens because your procedure is very busy working. For example your Sub TheLoop() is accessing 20995 x 16 times a cell to write on them a string. The interaction VBA with Excel is slow.
There is a couple of things you can do to make the procedure faster.
1.Disable events handlers, screen updating and calculations before you run your procedure. At the end of the procedure restore the settings again.
'Disable'
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
'...... Code'
'Enable'
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
2.You can optimize the Sub TheLoop. Instead of writing immediately on the cells, write the values inside an array. After the array is full with the values, assign the values of the array to the range that you need.
for example:
Dim ResultValues() As String
Dim j As Long
ReDim ResultValues(2 To 20997, 1 To 3)
For j = 2 To 20997
ResultValues(j, 1) = "New Defect"
ResultValues(j, 2) = "3"
ResultValues(j, 3) = "2"
Next j
With ThisWorkbook.Worksheets("myWorksheet")
.Range(.Cells(2, 3), .Cells(20997, 5)) = ResultValues
End With
EDIT:
Given that the columns between the ones that you modify are only text or empty cells, you can:
read the whole range into an array.
Then modify the array in the same way you are currently modifying cells.
After the modifications are done, dump the whole matrix in the range again.'
For example:
Sub TheLoop()
Dim arrRangeValues() as Variant
Dim j as Long
arrRangeValues= Range("A2:V20997").Value2
For j = 2 To 20997
arrRangeValues(j, 1) = "Defect" 'Cells(row_index , column_index)'
arrRangeValues(j, 3) = "New Defect"
arrRangeValues(j, 4) = "3" ' this one also might be empty'
arrRangeValues(j, 5) = "2" ' this one also might be empty'
arrRangeValues(j, 7) = "Name Surname"
arrRangeValues(j, 8) = arrRangeValues(j, 7)
arrRangeValues(j, 16) = arrRangeValues(j, 7)
...
arrRangeValues(j, 10) = " http://SERVER_NAME:8888/PROJECT_NAME/ "
Next j
Range("A2:V20997").Value2 = arrRangeValues
End Sub

Alright, i believe i found the best solution for this. (a) :)
Instead of using for loop in TheLoop subroutine, i removed the loop and changed it as in below. That makes it incredibly faster when i compare it with my first code eventhough i didn't disable event properties, and now it's not freezing.
Sub TheLoop()
Cells(2, 1).Resize(20996) = "Defect"
Cells(2, 3).Resize(20996) = "New Defect"
Cells(2, 4).Resize(20996) = "3"
Cells(2, 5).Resize(20996) = "2"
Cells(2, 7).Resize(20996) = "Name Surname"
Cells(2, 8).Resize(20996) = "Name Surname"
Cells(2, 9).Resize(20996) = "FALSE"
Cells(2, 10).Resize(20996) = " http://SERVER_NAME:8888/PROJECT_NAME/ "
Cells(2, 12).Resize(20996) = "Software Quality"
Cells(2, 13).Resize(20996) = "Unsigned"
Cells(2, 14).Resize(20996) = "Software Quality"
Cells(2, 15).Resize(20996) = "1"
Cells(2, 16).Resize(20996) = "Name Surname"
Cells(2, 18).Resize(20996) = "Software Quality"
Cells(2, 20).Resize(20996) = "Development"
Cells(2, 22).Resize(20996) = " TYPE YOUR MODULE'S NAME TO HERE"
End Sub

I been tried with the Application.ScreenUpdating, Application.EnableEvents, Application.Calculation, DoEvents and Application.Wait (Now + TimeValue("0:00:10")), and unfortunately the lasted options can not to resolve that problem, looking at the Microsoft WebPage say me if a program say me "Not Responding" is
For Security reasons and
Because is too heavy or complicated
Because the program don´t sent any FeedBack to user about to do.
In my case I tried showing and MsgBox to user with the finality to provide a FeedBack for the Win10 operative system and the customer, but is so boring that the user click yes, yes, yes, yes, ok, ok, ok, ok and viewing on others forums about VBA for MsgBox (automatly close), they suggest me that code CreateObject("WScript.Shell").PopUp "Please Wait", 1 and tada!! I going to stop see the "Not Responding Message", and if the user don´t to press any click or button for disable the message don´t worry the program going to execute after the message close after 1 second in my case this solve me a lot of problems, i hope to help you, good lucky.

Related

How to fix Excel-2016 not running Excel-2010 VBA code for printing correctly?

This loop runs typically 4 to 8 times. It updates 30+ textboxes and prints. Has been working great. But we updated from office 2010 to 2016 (and to Office 365), so now it runs but all the textboxes on the printed pages have the same value from iteration 1. Happens on all printers including PDFcreator. But afterwards the sheet is in the state I expect for the last iteration. It's like the code outruns the printer. But adding a delay of even 10 sec does not help. Oddly, as I try different things I see on the first iter that the textboxes update (from the previous runs last iter). Seems like it should update every iter.
Sub printParamSheets()
On Error GoTo errHandler
Dim Bin1_Matl, Bin1_Parts 'Declaring types won't help or speed up
Dim iCond, conditions
Application.EnableEvents = True 'Is not helping with issue
For iCond = 1 To conditions
With Sheet2
'Assign from sheet2 to variables
Bin1_Matl = .Range("A64").Offset(0, iCond * 2).Value2
Bin1_Parts = .Range("B64").Offset(0, iCond * 2).Value2
'about 30 more of these
End With
With Sheet8 'Assign Sheet8 named ranges from variables above.
'Could skip intermed vars but nice for debugging.
'ALL LINKED TO ACTIVEX TEXT BOXES on Sheet8, atop an image.
.Range("Bin1Matl").Value2 = Bin1_Matl
.Range("Bin1Parts").Value2 = Bin1_Parts
'about 30 more of them
.Calculate 'Is not helping with issue
Dim ctrl As OLEObject 'Is not helping with issue
For Each ctrl In .OLEObjects
If TypeName(ctrl.Object) = "TextBox" Then
'ctrl.Update 'error, but was not in 2010 anyway
End If
Next ctrl
Application.Wait (Now + TimeValue("00:00:05")) 'Is not helping
Application.ScreenUpdating = True 'Never toggled off , no help
DoEvents 'Is not helping with issue
.PrintOut from:=1, To:=1, Copies:=1, Collate:=True
End With
Next iCond
Exit Sub
errHandler:
Application.EnableEvents = True 'Don't need but cannot hurt
Resume Next
End Sub
I will try skipping the extra intermediate assignments, going straight from sheet2 to the textboxes. But I'd like to know the cause because I have other code 'in the wild' that doesn't necessarily use any activex objects that may be affected. Hoping the symptom is not unique to our site and so others may benefit from an answer.

VBA - range.sort script unexpectedly runs other script it shouldn't run

I'm working on a workbook and I'm getting an error which is driving me crazy. I really have no idea what's going wrong here.
On the main worksheet (Bestandsübersicht) I have a combobox named ddBestand. On the change event of that combobox it runs a script that checks if certain buttons should be enabled or disabled. The code for this is:
Private Sub ddBestand_Change()
On Error GoTo ExitSub
Dim i As Integer
i = 3
Dim WS As Worksheet
Set WS = Sheets("Bestandsübersicht")
If ddBestand.Value = "" Then GoTo ExitSub
Do Until WS.Cells(i, 1).Value = ddBestand.Value
i = i + 1
Loop
If WS.Cells(i, 13).Value = 0 Or _
Right(Sheets("Bestandsübersicht").Range("AL1").Value, 3) <> "yes" Then
btnNetwork.Enabled = False
Else
btnNetwork.Enabled = True
End If
btnChange.Enabled = True
btnSpecifics.Enabled = True
btnCopy.Enabled = True
Exit Sub
ExitSub:
btnChange.Enabled = False
btnSpecifics.Enabled = False
btnNetwork.Enabled = False
btnCopy.Enabled = False
End Sub
This works totally fine when I use ddBestand. But sometimes when I run other scripts this script unexpectedly starts to run, even though those scripts do not relate to eachother. For example, when I run the initialize even for a userform (which is launched from another worksheet) it starts to run at this range.sort method:
Sheets("DB_Network").Columns("A:C").Sort key1:=Sheets("DB_Network").Range("A2"), _
order1:=xlAscending, Header:=xlNo
it gives the error 1004 (Unable to set the Enabled propert of the OLEObject class (which is logica, because as we're on another worksheet, the property for those buttons is wrong). As I didn't know how to stop the first script from running, I fixed the script by changing the OLEObjects to this:
Sheets("Bestandsübersicht").OLEObjects("btnChange").Object.Enabled = True
Solving the symptoms might not be the prettiest solution, but as I couldn't find out what the problem really was, I decided this was a suitable solution. But it got crazier. I'm still using another version of this document as I need it for my work. Somehow the same sort method started running the same script in the other document, which made the same error occur. Now I really want to solve this problem, as I don't want it to unexpectedly run scripts in other documents. Is there anybody out here who can help? Would be much appreciated!
I would guess that your combobox is directly linked to a range using the ListFillRange and/or LinkedCell properties. That is not a good idea for precisely this reason. I suggest you use code to populate the control using its .List property instead, which is easier and faster than .AddItem:
Sheets("Bestandsübersicht").OLEObjects("ddBestand").Object.List = Sheets("blah").Range("A2:A100").Value
for example.

VBA compiler not breaking / trapping on errors and no error message, when using UDF in conditional formatting

See new development.
I have a strange problem in Excel. I've got a Worksheet_Change event that I'm using and I'm trying to debug it. I save the program and open it back up and all of a sudden the compiler is not breaking on an error. In fact, it's not breaking at all!! I'll put a break at the head of the sub (and the next three lines for good measure) and it just does not happen. I thought maybe the events weren't enabled... So, I've put a message box as one of the first lines of code. The message box pops up.... even with the break on it's line.
This happened once before on a particular line of another macro and I tried copying everything into a .txt file and pasting it back into an earlier version of my program. This worked for months, but the problem now came back.
The coding isn't really important but I'll paste it below for kicks and giggles. It's aborting without an error wether I remove all the "on error"'s or not. I've cut and pasted the code into a new sub and it works fine. I've also checked the options and checked "break on all errors." nothing, even an undefined call won't throw an error, will stop the program from aborting.
Private Sub Worksheet_Change(ByVal target As Range)
Application.EnableEvents = False
Dim aVar() As String
Dim iVar As Integer
On Error GoTo 0
MsgBox "you changed something" 'this is a msgbox that does pop up during execution, verifying that the sub did in fact, run.
Call iRandomNonsense 'this is a sub that does not exist which the compiler does not tell me about any more.
If target.Columns.Count = 1 Then
Select Case target.Column
Case 2
If target.Count = 1 And Cells(target.Row, 1) = "" Then _
Cells(target.Row, 1) = Now
Case 8
On Error GoTo ExitSub
aVar = Split(target.Value)
For Each sVar In aVar
If IsNumeric(sVar) And Len(sVar) = 5 Then
If sVar > 30000 Then
aVar(iVar) = "ALN-" & sVar
Else
aVar(iVar) = "DEV-" & sVar
End If
End If
iVar = iVar + 1
Next
target.Value = Join(aVar, " ")
End Select
Else
On Error GoTo ExitSub
target.Resize(target.Rows.Count, Cells(target.Row, target.Columns.Count).End(xlToLeft).Column + 1 - target.Column).Select
Select Case Selection.Columns.Count
Case 18, 21 'Paste from Scrap report
Debug.Print "Paste from Scrap report" & Now
Call purgeCheckboxes
With Selection
.Copy
.PasteSpecial (xlValues)
End With
OnSelRow(4, 8).Select
Selection.Copy Destination:=OnSelRow(1)
'desc
OnSelRow(6) = OnSelRow(10)
OnSelRow(4) = OnSelRow(15)
With Range(Cells(Selection.Row, 10), Cells(Selection.Row + Selection.Rows.Count - 1, 10))
.FormulaR1C1 = _
"=RC[2]&"" ""&RC[3]&"" ""&RC[-3]&"" ""&RC[4]&"" ""&RC[7]&"" ""&RC[11]"
.Copy
.PasteSpecial (xlValues)
End With
Application.CutCopyMode = False
Range(Cells(Selection.Row, 7), Cells(Selection.Row + Selection.Rows.Count - 1, 7)).FormulaR1C1 = "TRUE"
Range(Cells(Selection.Row, 8), Cells(Selection.Row + Selection.Rows.Count - 1, 8)).FormulaR1C1 = "T D Q 9 A Wav DMR"
Range(Cells(Selection.Row, 9), Cells(Selection.Row + Selection.Rows.Count - 1, 9)).FormulaR1C1 = "2"
Range(Cells(Selection.Row, 11), Cells(Selection.Row + Selection.Rows.Count - 1, 11)).Select
Range(Selection, Cells(Selection.Row, UsedRange.Columns.Count)).Select
Selection.ClearContents
ActiveWindow.ScrollColumn = 1
End Select
Call RefreshCondFormats
End If
ExitSub:
On Error GoTo 0
Application.EnableEvents = True
End Sub
A new development:
I followed the advice in one of the comments. "Long shot: do you have any conditional formatting that uses UDFs? – Rory yesterday" It resolved the breaking error when I deleted the User Formula in my conditional formatting. Now the compiler stops like its supposed to and when I comment out "iRandomNonsense" it breaks on my command. When I put the formatting back it screws up again.
Rory, put your comment down as an answer (with a little more description as to how you figured this out) and I'll check it off to you.
If anyone's willing, I'd really like to know a way around this glitch in excel. It seems like a utility I might use in the future, and it really bothers me I can't use a user function in a conditional format. Also, this code has been very useful to me and I don't see any other way to do what I've done without either a user formula in conditional formatting, or a hairy autocorrect code.
If you are using UDFs in conditional formatting, this kind of problem can occur. It is most likely if you don't have error handling, or if you try and access any properties other than .Value or .Formula. It is often possible to work around the issue - e.g. using an alternative calculation, or putting the UDF in a cell - but occasionally you may just be out of luck.
I suggest using Rob Bovey's Code Cleaner to get rid of the accumulated p-code that can cause errors like this. When Excel VBA starts behaving strangely cleaning the code often fixes the problem.
http://www.appspro.com/Utilities/CodeCleaner.htm

VBA - Compile Error - Method or Data member not Found [duplicate]

This question already has answers here:
Microsoft Excel ActiveX Controls Disabled?
(11 answers)
Closed 8 years ago.
I have been using this excel program for several months without issues. suddenly a couple days ago it started to throw this error. On sheet named "Input" I will double click a cell in column "A" which will create a drop down box that will fill with data from the "Data" sheet. I start typing and then I select the data to add to the cell. Now when I click the cell and get an error message "Compile Error - Method or data member not found". Here is my block of code and the error is showing near the bottom highlighting "Me.TempCombo.Activate".
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim str As String
Dim cboTemp As OLEObject
Dim ws As Worksheet
Set ws = ActiveSheet
If Target.Column = 1 And Target.Row > 12 And Target.Row <> HRRow And Target.Row <> HRRow - 1 Then
lRow = Sheets("Data").Range("A65536").End(xlUp).Row
Set cboTemp = ws.OLEObjects("TempCombo")
On Error Resume Next
With cboTemp
'clear and hide the combo box
.ListFillRange = ""
.LinkedCell = ""
.Visible = False
End With
On Error GoTo errHandler
'If Target.Validation.Type = 3 Then
'if the cell contains a data validation list
Cancel = True
Application.EnableEvents = False
'get the data validation formula
'str = Target.Validation.Formula1
'str = Right(str, Len(str) - 1)
str = "=Data!A2:A" & lRow
With cboTemp
'show the combobox with the list
.Visible = True
.Left = Target.Left
.Top = Target.Top
.Width = Target.Width + 5
.Height = Target.Height + 5
.ListFillRange = str
.LinkedCell = Target.Address
End With
'cboTemp.Activate
Me.TempCombo.Activate
'open the drop down list automatically
Me.TempCombo.DropDown
End If
errHandler:
Application.EnableEvents = True
Exit Sub
End Sub
I tried several things and for the life of me I cannot figure out what changed.
Any help will be appreciated. Thank you.
I ran into the same error and was able to solve it as Rory suggested. I searched my machine for *.exd files and found a few. The issue was solved for me after removing C:\Users\<username>\AppData\Local\Temp\Excel8.0\MSForms.exd...the others seemed to be unrelated to the ActiveX controls in Excel.
Looks like the code came from an example like this: http://www.contextures.com/xlDataVal10.html
except your code has commented out the line which activates the cboTemp combobox. Your code is attempting to access the TempCombo attribute of the worksheet (which I don't think exists). Uncomment 'cboTemp.Activate on the line above the highlighted error line.
I had the same problem, my code broke this morning. Fortunately, I recalled that I ran Windows Update this weekend. I performend a system restore (earliest available restore point was 8th of december), and now the problem is gone.
I never did understand the panicy server guys who were always making backups and spending a whole lot of time testing before/after system updates, in all my years I never experienced any problems. Now I sure figured out what they were talking about. Lesson learnt. I'll try running win update again in a few months, hopefully MS has solved the problem by then.
Best of luck

Excel headers/footers won't change via VBA unless blank

Disclaimer: It's been a few years since I worked (a lot) with VBA, so this might be an issue caused by confusing myself with what is essentially a very different language from what I usually deal with.
So; I've got a workbook (Excel 2010) with multiple sheets (20+), most of whom are multi-page. To make things easier when printing everything, I want to add some sheet-specific headers with amongst others the name of the sheet, number of pages and so on.
I've written a tiny function that should (in theory) do this for me by iterating over all the sheets setting the header. However, for some reason it only works if the header is empty; if it already has a value it refuses to overwrite for some unknown reason.
Dim sheetIndex, numsheets As Integer
sheetIndex = 1
numsheets = Sheets.Count
' Loop through each sheet, but don't set any of them to active
While sheetIndex <= numsheets
Dim sheetname, role, labeltext As String
sheetname = Sheets(sheetIndex).name
role = GetRole(mode)
labeltext = "Some text - " & sheetname & " - " & role
With Sheets(sheetIndex).PageSetup
.LeftHeader = labeltext
.CenterHeader = ""
.RightHeader = "Page &[Page] / &[Pages]"
.LeftFooter = "&[Date] - &[Time]"
.CenterFooter = ""
.RightFooter = "Page &P / &N"
End With
sheetIndex = sheetIndex + 1
Wend
I found a solution that seems to work for replacing text. For whatever reason, in the macro, you need to include the header/footer format character codes in order for it to work properly.
This code worked to replace existing header text with new information:
Sub test()
Dim sht As Worksheet
Set sht = Worksheets(1)
sht.PageSetup.LeftHeader = "&L left text"
sht.PageSetup.CenterHeader = "&C center Text"
sht.PageSetup.RightHeader = "&R right text"
End Sub
Without the &L, &C, and &R codes before the text, I could not get it to work.
Some interesting behavior I found is that if you use the following code:
.CenterHeader = "&L some text"
it will actually put the some text in the LeftHeader position. This led me to believe that the formatting codes were very important.
The line Application.PrintCommunication = False (which is added by the macro recorder) before doing PageSetup screws up the formating via VBA.
If your code has got this line in it, try removing it. That solved my problem with setting the header and footer via VBA.
I've read StackOverflow for years and this is the first time I've actually been able to post a solution ... hope it helps someone!! Also, you need to remember, I am a CPA not a programmer ;-)
I am reading some values from the ActiveSheet to populate the header. The application is a tax election that will be sent with a tax return so it must have the taxpayer's name and social security number at the top.
Sub PrintElection()
' Print preview the MTM Election
If Range("Tax_Year").Value = Range("First_MTM_year").Value Then
ActiveSheet.PageSetup.LeftHeader = Format(Worksheets("Election").Range("Taxpayer_Name").Value)
ActiveSheet.PageSetup.RightHeader = Format(Worksheets("Election").Range("Taxpayer_SSN").Value)
ActiveWindow.SelectedSheets.PrintPreview
Else
MsgBox "The 'Effective For Tax Year' date must EQUAL the 'First MTM year' date", vbOKOnly, "Check Years"
Sheets("Roadmap").Select
Range("First_MTM_year").Select
End If
End Sub
It checks to see if the Mark-to-Market election year is the same as the election form then formats the election page.
I split the sheet print setup into 2 loops. First loop with Application.PrintCommunication = False I run the non-header/footer setup. I then set Application.PrintCommunication = True and run the header/footer setup in a second loop. Appears to run faster than in XL2003, and applies the header/footer correctly. Until MS fixes this bug, that works fine for me.