Excel - Screen flicker on screen update - excel

I've got yet another question from the long serries of 'Stop excel screen from flickering', but I think this one is a bit more tricky.
I've got a client who requires a 'progress' bar on his spreadsheet during macro execution.
What I've done, is I've a pie chart linked to 2 cells which I adjust based on the progress. For performance, I've disabled events, ScreenUpdating and changed calculation to manual.
Then, once in a while I quickly toggle ScreenUpdating on and off to actually update the progress chart. This works like a charm every time I use it (more than 30 projects now).
Recently, the client came back to me with a 'big' problem. Whenever I do the quick toggle to refresh the progress chart, the entire excel screen (including all the items on it)flickers, which drives the guy crazy.
Has anyone got any idea on what could be done with this to keep the chart updating while keeping the front page constantly displayed (the macro jumps between pages) without screen flickering? Something like double buffering or so...
SOLUTION
Believe it or not, but I just found a solution. This was so so so easy. In VBA, it's possible to refresh just a specific object, while the remaining screen remains 'locked'. For example:
ThisWorkbook.Worksheets("Welcome").ChartObjects(1).Chart.Refresh
Thank you everyone for your input.

You may be able to rewrite the macro so that it doesn't "jump between pages" (since it's usually not necessary to activate worksheets in order to manipulate their data. Otherwise, either a user form or the application's StatusBar could be used to display a progress bar:
Sub StatusBar()
Dim pct As Double
Dim msg as String
Application.ScreenUpdating = False
For i = 10000 To 1 Step -1
pct = (10000 - i) / 10000
msg = Format(pct, "0.0%") & " complete"
Application.StatusBar = msg
Next
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub
Here is a revised example with UserForm. Note that you will need to add the UserForm module, and at least one Label to it in order to present the information:
Sub StatusBar()
Dim pct As Variant
DoEvents
UserForm1.Show vbModeless
Application.ScreenUpdating = False
For i = 10000 To 1 Step -1
pct = (10000 - i) / 10000
If Int((i / 10000) * 100) = (i / 10000) * 100 Then
msg = Format(pct, "0%")
UserForm1.Label1 = msg & " complete"
End If
Next
UserForm1.Label1 = "Finished!"
Application.ScreenUpdating = True
End Sub
Problem might be that, depending on how quickly your macro(s) execute, the progress indicator may appear to jump from 0 to 100%. You can do graphical progress bars, too, but the basic idea behind it would be the same, just instead of updating a label value, you'd be changing the size of a textbox with a differing background color, etc.
Revised per OP comments
This is how you can "copy" a range from one sheet to another sheet without "copy/paste":
Set rng1 = Sheets(1).Rows(12)
Set rng2 = Sheets(2).Rows(1)
rng2.Value = rng1.Value
So, you can just define your ranges, and assign the second range to = the first range.

Related

Pause VBA until #GETTING DATA Power Pivot is complete

I've found a lot of questions and answers about issues that feel very close to what I'm working on, but not quite. I have an Excel workbook with a large Data Model connected to two slicers. I need to cycle through every entry in the slicer, allow the workbook to catch up on loading a large number of cube formulas, then copy one particular worksheet over into another.
I've written VBA which does all of this, but I can't for the life of me get the VBA to wait for the workbook to finish uploading before it continues with the rest of the script. I can rule out background refresh-based solutions, which don't apply to OLAP. Various solutions I've found online which recommend waiting for calculations to be complete don't seem to work, the script just barrels right through those lines. The only solution I've seen which seems to apply here involved identifying every cell which would be updated as a result of the slicer change and looping through them until they no longer say #GETTING DATA. For my workbook, this would be hundreds of cells to identify and check and feels very unsustainable.
Even telling the script to Applcation.Wait seems to wait for the selected amount of time during which the workbook pauses getting data.
Setting different values of a slicer connected to a Data Model and automating some output feels like it should be such a common task that we have a solution for it. Any help would be much appreciated.
Running Office 365
Sub generate_all_forecasts()
'Cycle through all products and push forecast values to fcst_output'
Application.ScreenUpdating = True
Dim SC_products As SlicerCache
Dim selection, product_array As Variant
Dim push As Boolean
Set SC_products = ThisWorkbook.SlicerCaches("Slicer_PRODUCT_GROUPING_WRITTEN") 'The product slicer on the Inputs worksheet'
product_array = Range("product_array") 'Named range product_array on Tbl_Codes worksheet'
For Each p In product_array 'For each product'
push = WorksheetFunction.Index(Range("fcst_push_array"), WorksheetFunction.Match(p, product_array, 0)) 'Check if the product has been selected for this run'
If push = True Then
If p = "Major Medical Plan" Then 'If "Major Medical" '
selection = Array("[Query1 1].[PRODUCT_GROUPING_WRITTEN].&[Major Medical Plan - CMM]", _
"[Query1 1].[PRODUCT_GROUPING_WRITTEN].&[Major Medical Plan - GMM]") 'selection will be both CMM and GMM'
Else
selection = Array("[Query1 1].[PRODUCT_GROUPING_WRITTEN].&[" & p & "]") 'Otherwse selection is the single product'
End If
SC_products.VisibleSlicerItemsList = selection 'Change slicer to current selection'
'This is where the script needs to pause until #GETTING DATA is complete'
Application.Run "push_to_output" 'Run the forecast update macro'
End If
Next p
Worksheets("Fcst_Output").Range("B2:B1381").Value = "" 'Clear prior month's comments'
Application.ScreenUpdating = True
End Sub
Solutions which have not worked: Wait time after change slicer in
power pivot, Getting vba to wait before proceeding, Wait
until Application.Calculate has finished
The "solution" I really don't want to use: Force VBA to wait until
power pivot finishes refreshing
Thanks to Tragamor for linking to a thread where they already had a working answer. I included the following immediately after the slicer selection in my VBA and it appears to properly wait until all data fetching is complete:
Dim CalculationState As Long
With Application
CalculationState = .Calculation
.Calculation = xlCalculationAutomatic
.CalculateUntilAsyncQueriesDone
Do Until .CalculationState = xlDone
DoEvents
Loop
.Calculation = CalculationState
End With
Find your Query Properties, and set 'Enable background refresh' to False (Microsoft use True as default).
Then in your code you need to call for RefreshAll and wait for the data to load with the DoEvents. If you want your update of data to run on open you can use this in 'ThisWorkbook' Object.
Private Sub Workbook_Open()
For Each q In ThisWorkbook.Connections
q.Refresh
DoEvents
Next
End Sub

Application.ScreenUpdate and Shapes

I have a sheet that I have a bunch of shapes (rectangle = button) that have marcos assigned to. I am using the shapes as a userform. There is one button that toggles between forms (essentially hiding all the visible shapes then showing all the shapes for another setup). The issue that I am having is that during the switch over to the other setup the shapes from the first setup still appear throughout the transition even though I am using:
Application.ScreenUpdate=False
I am trying to have a clean transition / clean switch over. Any thoughts? If my question is not clear, please let me know.
Sample Code
Sub Toggle_Form
Application.ScreenUpdating = False
Call Form1_ShowHide(False)
Call Form2_ShowHide(True)
Application.ScreenUpdating = True
Sub Form1_ShowHide(VisibleState as boolean)
For CoUnTer = 1 To 10
WS.Shapes("Shape1_" & CoUnTer).Visible = VisibleState
Next CoUnTer
End Sub
Sub Form2_ShowHide(VisibleState as boolean)
For CoUnTer = 1 To 20
WS.Shapes("Shape2_" & CoUnTer).Visible = VisibleState
Next CoUnTer
End Sub
I am using Excel 2016. Do not think it is a computer processing issue (got a pretty good laptop).

VBA - Combo Box scroll down bar broken

I am working on a client management utility for my workplace, with various note entry / viewer system + dropdown for convenience and efficiency.
Right now I am having an issue where on a userform, after clicking a combobox, the user cannot click on the scroll bar to drag down. They can click the arrow to scroll down, but not the bar itself for faster scrolling.
What is weird is that the file I sent, "7.8", was a direct copy of my file but with my colleagues clients info inserted. On my version, made 5 minutes before, the click on scroll down bar works perfectly. I took screenshots of the combo box properties and couldn't find what if anything had changed.
This also occurs on a userform which I made ZERO changes to today, again not working on his but working on mine. Are there common issues that can occur when having multiple workbooks open? All of my userform code targets this workbook & identifties the sheet by codename. All of the other features are working, including much more complex things then whether or not a scroll bar is draggable...
a bit puzzled. Anyone have any ideas?
So I put an example of the code below: I successfully use the same code at several points with small shifts to identify if a given account owner is selected, and if so, load the matching clients, and if a client is selected, to load the timestamp for a note.
What is weird is that the code identified has been the exact opposite of reproducible. I had workbook 7.8, copy-pasted it, changed the client data (which in no way affected the underlying code), and sent to my colleague, whose then experience of the userforms was that the scroll bars can have the button down click but not drag on the bar itself. The only thing I can think of is somehow if having multiple workbooks caused an issue, but out of all of the > 1000 lines of code, there isnt even a single line of code of mine which does anything to the scroll bar. And somehow in the 5 minutes from emailing to him, the scroll bar lost partial functionality?
Sub noteOwnerClients()
Dim wsFound As Worksheet
Dim mainBook As Workbook
Set mainBook = ThisWorkbook
Dim rangeFinder As Range
Dim rangeInt As Integer
Dim rangePull As String
Dim selectedString As String
For Each ws In ThisWorkbook.Worksheets
If StrComp(ws.CodeName, "sheetDatabase", vbTextCompare) = 0 Then
Set wsFound = ws
End If
Next ws
noteClientCombo.Clear
selectedString = noteOwnerCombo.Text
If selectedString <> "" Then
rangeInt = 2
For Each rangeFinder In wsFound.Range("E2:E200")
If selectedString = rangeFinder.Value Then
rangePull = "A" & rangeInt
noteClientCombo.AddItem wsFound.Range(rangePull)
End If
rangeInt = rangeInt + 1
Next
End If
End Sub

Launch a different sheet by Spin button

want to use a Spin button (ActiveX Control) to show a previous or next sheet. When the button is clicked the event is successfully triggered and the desired sheet is activated but it holds some elements (commands, graphs, etc.,) from the original sheet and shows these as an appending picture.
Sample code for Down button event :
Private Sub SpinButton_JumpToWeek_SpinDown()
Dim sh_num As String
Dim tmp_num As Integer
Application.ScreenUpdating = False
Application.EnableEvents = False
SpinButton_JumpToWeek.Value = Range("B27").Value - 1
tmp_num = SpinButton_JumpToWeek.Value
' Activate desired KTx sheet
sh_num = "KT" & tmp_num
Range("F27").Value = "" 'reset to blank
Sheets(sh_num).Activate
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
To override this effect I have to manually select (activate) another sheet and then again select the desired sheet. I tried also to automatize this workaround with a macro, but unfortunately it does not work.
It is interesting that this problem do not occur if I execute code in Debug mode (using breakpoint and the stepping line by line).
Surprisingly, I do not have such problem if I try to show the previous/next sheet by writing a value (sheet name index) into a defined cell (i.e. using the Worksheet_Change event). The desired page is correctly shown. See photos.
Sample code for this evententer image description here:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim sh_num As String
Application.ScreenUpdating = False
Application.EnableEvents = False
If Range("F27").Value > 0 Then
' Activate desired KTx sheet
sh_num = "KT" & Range("F27").Value
Range("F27").Value = "" 'reset to blank
Sheets(sh_num).Activate
End If
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I need to use the Spin button because it is faster and allow me to skip some sheets (for example if these do not have data).
The problem occurs in both 32 and 64-bit Excel.
Do somebody an idea why this problem is occurring and a workaround? Do I have to change some settings or system properties in Excel? Any help would be highly appreciated.
#mehow
I append my commenst here due to large number of words.
I followed your suggestion and tried the example of a UserForm with inserted active control “Microsoft Office Spreadsheet”. I found out that this would not be a good solution for my case, because the response of such sheet is relatively slow (even on a fast PC like mine) when user inserts values into cells. Furthermore, this would greatly complicate my fairly simple *.xlsm workbook, which has more than 50 sheets (1 sheet for each week, the contents of these sheets are then linked to a main sheet), and completely meets my basic necessities (with the exception of this spin button of course).
In my opinion there is probably necessary to manipulate some kind of system property (like for e.g. Application.ScreenUpdating trick), but I do not have enough VBA knowledge to find it.
To clearly explain my question I would need to share my sample workbook, but I do not know how to upload it to this forum. Unfortunately, I am not able upload/show images successfully on this forum (due to my low rating), which would also help a lot.
BTW, I cannot see images on other questions of this forum, too. . Could this problem occur due to missing plugins in a web browser?
You can use a simple trick... before the "Application.screenupdating = true" you can insert the two lines:
ActiveWindow.SmallScroll Down:=-100
ActiveWindow.SmallScroll Up:=100

Bugs in Excel's ActiveX combo boxes?

I have noticed that I get all sorts of annoying errors when:
I have ActiveX comboboxes on a worksheet (not an excel form)
The comboboxes have event code linked to them (eg, onchange events)
I use their listfillrange or linkedcell properties (clearing these properties seems to alleviate a lot of problems)
(Not sure if this is connected) but there is data validation on the targeted linkedcell.
I program a fairly complex excel application that does a ton of event handling and uses a lot of controls. Over the months, I have been trying to deal with a variety of bugs dealing with those combo boxes. I can't recall all the details of each instance now, but these bugs tend to involve pointing the listfillrange and linkedcell properties at named ranges, and often have to do with the combo box events triggering at inappropriate times (such as when application.enableevents = false). These problems seemed to grow bigger in Excel 2007, so that I had to give up on these combo boxes entirely (I now use combo boxes contained in user forms, rather than directly on the sheets).
Has anyone else seen similar problems? If so, was there a graceful solution? I have looked around with Google and so far haven't spotted anyone with similar issues.
Some of the symptoms I end up seeing are:
Excel crashing when I start up (involves combobox_onchange, listfillrange->named range on another different sheet, and workbook_open interactions). (note, I also had some data validation on the the linked cells in case a user edited them directly.)
Excel rendering bugs (usually when the combo box changes, some cells from another sheet get randomly drawn over the top of the current sheet) Sometimes it involves the screen flashing entirely to another sheet for a moment.
Excel losing its mind (or rather, the call stack) (related to the first bullet point). Sometimes when a function modifies a property of the comboboxes, the combobox onchange event fires, but it never returns control to the function that caused the change in the first place. The combobox_onchange events are triggered even when application.enableevents = false.
Events firing when they shouldn't (I posted another question on stack overflow related to this).
At this point, I am fairly convinced that ActiveX comboboxes are evil incarnate and not worth the trouble. I have switched to including these comboboxes inside a userform module instead. I would rather inconvenience users with popup forms than random visual artifacts and crashing (with data loss).
I don't have a definitive answer for you, but I can tell you that I stopped using ListFillRange and LinkedCell for ActiveX controls about 10 years ago. I don't recall what particular problems I encountered. I just remember coming to the conclusion that whatever little time they saved me isn't worth the brain ache of trying to track down the bugs. So now I populate the controls through code and deal with output in the events.
My active-x combo box works fine when my Dell is docked but resizes to a larger font each time it is clicked when the Dell is undocked - very strange. I added resizing code which works when undocked, but both .height and .scaleheight fail when docked and when triggered programmatically (even stranger).
Sheet2.Shapes("cb_SelectSKU").Select
Selection.ShapeRange.Height = 40
Selection.ShapeRange.ScaleHeight 0.8, msoFalse, msoScaleFromTopLeft
I then added my own enableevents-like switch so that the resizing only occurs when a user selects a combobox value, not when anything is affected while a macro is running.
Select Case strHoldEvents
Case Is = "N" 'Combobox resizing fails with error when triggered programatically (from SaveData)
Call ShowLoadShts
Sheet2.Shapes("cb_SelectSKU").Select
Selection.ShapeRange.Height = 40
Selection.ShapeRange.ScaleHeight 0.8, msoFalse, msoScaleFromTopLeft
Case Else
End Select
Finally that seems to work, whether docked or undocked, whether triggered by the user or during a procedure. We'll see if it holds...
I have a partial reply for the Dell users, and for your formatting problem
The formatting and display problem is another known-but-undocumented issue in Excel.
Many flat-panel monitors (including laptop displays) are unable to render fonts correctly in textbox controls on an Excel spreadsheet: you've got a mild version of this problem.
Our company has recently upgraded to new (and much larger!) monitors, and I can at last use textboxes, labels and combo boxes in worksheets. Our old Samsung screens displayed text controls correctly, but any manual or VBA-driven updates resulted in an illegible jumble of overlapping characters.
Listboxes don't have the problem: it's the 'textbox' part of your combo box that has the issue. Try manipulating a listbox in VBA event procedures: it's a kludge but it works.
In-Cell dropdowns from Data Validation lists don't have the problem. If you set up a validation list for a cell, then set the data validation error messages to empty strings, you can enter free-form text in the cell; the drop-down list is advisory, not a mandatory limit-to-list.
The problem is sometimes ameliorated (but never completely fixed) by using the Terminal or System fonts in your Active-X control.
The problem is sometimes ameliorated (but never completely fixed) by using a VBA event to nudge or resize your Active-X control by 0.75 mm.
Check if your laptop manufacturer has released an upgrade to the display drivers.
...And that's everything I know about the font rendering problem. If Mike (with his Dell laptop) is reading this: Good luck with those workarounds - to the best of my knowledge, there's no real 'fix'.
The stability problem was a major headache for me until Excel 2003 came out: using any Active-X control in the sheet was a source of instability. The Jury's still out on Listbox controls embedded in a sheet, even in Excel 2003: I still avoid using them.
So I was facing the same issues. I had a file with drop down lists on which I had superimposed the combobox to fight the issue of illegibility when zooming out too much. This was what my code looked like INITIALLY:
'=========================================
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim str As String
Dim cboTemp As OLEObject
Dim ws As Worksheet
Set ws = ActiveSheet
On Error GoTo errHandler
If Target.Count > 1 Then GoTo exitHandler
Set cboTemp = ws.OLEObjects("ComboBox1")
On Error Resume Next
If cboTemp.Visible = True Then
With cboTemp
.Top = 10
.Left = 10
.ListFillRange = "Treatment"
.LinkedCell = Target.Address
.Visible = False
.Value = ""
End With
End If
On Error GoTo errHandler
If Target.Validation.Type = 3 Then
'if the cell contains a data validation list
Application.EnableEvents = False
'get the data validation formula
str = Target.Validation.Formula1
str = Right(str, Len(str) - 1)
With cboTemp
'show the combobox with the list
.Visible = True
.Left = Target.Left
.Top = Target.Top
.Width = Target.Width + 15
.Height = Target.Height + 5
.ListFillRange = ws.Range(str).Address
.LinkedCell = Target.Address
End With
cboTemp.Activate
'open the drop down list automatically
Me.ComboBox1.DropDown
End If
exitHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
Exit Sub
errHandler:
Resume exitHandler
End Sub
'====================================
'Optional code to move to next cell if Tab or Enter are pressed
'from code by Ted Lanham
'***NOTE: if KeyDown causes problems, change to KeyUp
'Table with numbers for other keys such as Right Arrow (39)
'https://msdn.microsoft.com/en-us/library/aa243025%28v=vs.60%29.aspx
Private Sub ComboBox1_KeyDown(ByVal _
KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
Select Case KeyCode
Case 9 'Tab
ActiveCell.Offset(0, 1).Activate
Case 13 'Enter
ActiveCell.Offset(1, 0).Activate
Case Else
'do nothing
End Select
End Sub
'====================================
I was facing all sorts of issues but as primarily mentioned on this thread, the LinkedCell issue was the biggest. My selection from the drop down menu would go wherever on the sheet I had clicked last, instead of the cell I had chosen the drop down box from, and in process, also disturbing the code of wherever the selection would go. I used a simple ONE LINE code to make sure my program in ActiveX runs only when its a drop down menu. I used this before the LinkedCell command ran:
If Target.Validation.Type = 3 Then
'... all the normal code here...
End If
So my code now looks like this:
'... Code as before
If Target.Validation.Type = 3 Then
' NEW CODE LINE ABOVE
If Target.Count > 1 Then GoTo exitHandler
Set cboTemp = ws.OLEObjects("ComboBox1")
On Error Resume Next
If cboTemp.Visible = True Then
With cboTemp
.Top = 10
.Left = 10
.ListFillRange = "Treatment"
.LinkedCell = Target.Address
.Visible = False
.Value = ""
End With
End If
End If
' End of the new If
Unbelievably, this worked. And now my excel sheet isn't misbehaving anymore. Hope this helps.
For this reason, I use cells with data validation lists when putting combo boxes on a spreadsheet.

Resources