Updating a chart while VBA is running - vba

I'm trying to see visually what happens to a set of data in Excel each time I increment a driving variable by 1.
The data is visualised in a chart and the increments are done via a for-next loop on an integer n.
Each time I increment n, the values in a table update and the chart should update too. Except it doesn't. The table updates but the chart waits to the end of the routine and shows its position for the last value of n only.
I have put a wait command in, tried Charts("Chart 1").Refresh etc but the chart won't update (albeit the table feeding it does) during the intermediate steps of the code as I'd like it to. I'm on automatic calculation so its not that that's causing the problem.
How do I get the chart to update to the table values whilst the code is running. This was the code sorry.
Sub Walkthrough()
Dim n As Integer
For n = 0 To 77
Range("L3").Value = n
Application.ScreenUpdating = True
ActiveChart.Refresh
Application.Wait Now + #12:00:01 AM#
Next n
End Sub

This is how to make it workable:
Option Explicit
Sub Walkthrough()
Dim n As Long
Application.ScreenUpdating = True
For n = 0 To 5
Range("a1").Value = n
Application.Wait Now + #12:00:01 AM#
Next n
End Sub
Make sure that A1 is your dependent range in the example. By default the Application.ScreenUpdating is set to True in Excel, thus you do not need to set it explicitly.

I had success by activating the chartObjects in the ActiveSheet. However, I am not 100% sure about the DoEvents calls. Excels selection behavoiur was a bit strange after the procedure finished. Propably because a ChartObject was still activated. Therefore, I finally activate the ActiveSheet.
Option Explicit
Sub Walkthrough()
Dim myChart As ChartObject
For Each myChart In ActiveSheet.ChartObjects
myChart.Activate
DoEvents
Next
ActiveSheet.Activate
DoEvents
End Sub

Related

IF statement within a loop

I need help figuring out what I am doing wrong. Keep in my mind im an amateur.
I have two Workbooks, Workbook A and Workbook B. In workbook A I have a value in cell a1 and workbook B i have lets say 10 sheets with values in column A and B.
I would like to match value from a1 in workbook A by looping through all sheets in workbook B, and then returning the address if where it found it. I then write an if statement if the value is found to stop the loop because I will later have it search another cell, though I got stuck so I haven't written that line of code yet.
Here is the code and Ill note where im stuck.
sub autocheck()
dim found as varient
dim I as integer
dim val as varient
set val=workbooks("A").worksheets("primary").range("a1").value
For I = 1 to 10
on error resume next
set found=workbooks("b").worksheets(i).range("a:b").match(val)
found= found.address
if isempty(found) then
next i
else
exit for
end if
end sub
Here I get an error saying can not have next with out for.
Any idea how I get around these? I apologize for the formatting.
Thank you all!
The problem is the if statement is spanning outside the loop. You should just exit the loop with the if statment and keep it contained inside the for
For I = 1 to 10
on error resume next
set found=workbooks("b").worksheets(i).range("a:b").match(val)
found= found.address
if isEmpty(found) then
//do something
else
exit for
end if
next i
end sub
Your code should have "screamed" a few times:
dim val as variant ? maybe as Variant.
You should (or trying) to use match, your syntax is closer to Find. Using Find should also include a scenario Find didn't find the result. In any way, you need to Set the Find function result to a Range object.
Your closing Next I should be after the End If, not in the middle.
Using on error resume next doesn't make your error go away, you are just "closing your eyes" hoping it will go away.
More notes in my code's comments below.
Modified Code
Option Explicit
Sub autocheck()
Dim found As Range
Dim foundAdress As String
Dim i As Long
Dim val As Variant
Set val = Workbooks("A").Worksheets("primary").Range("a1").Value
For i = 1 To 10
Set found = Workbooks("b").Worksheets(i).Range("A:B").Find(what:=val)
If Not found Is Nothing Then ' Find was successfull
foundAdress = found.Address
Exit For
Else ' Find failed
' in your code do nothing, continue looping
End If
Next i
End Sub

Excel VBA: Animating Visibility of a Range w/ RowHeight loop

I am interested in showing/hiding several ranges on my workbook. Normally I would just test whether or not the range is already hidden and set the following to either true or false rng.EntireRow.Hidden.
I would like to make my project feel more like an app (yes I know excel probably isn't the best place to go with it, but attention to small details like this is my kind of thing). The following is an example of what I am trying to do. It works, especially on a clean worksheet/workbook. The problem is that on the workbook in which I am trying to use it, there is already a ton of data/formatting/shapes on the worksheet. This is causing "skips" in the smoothness of the loop. I have tried different step by's, but nothing really seems to solve it. The DoEvents was necessary in order to see any animation at all.
If anyone has an idea on how to make this work, or if it's at all possible, that would be great. Thanks!
Sub testView()
Dim rng As Range
Dim i As Integer
With ActiveSheet
Set rng = .Range(.Cells(1, 1), .Cells(20, 1))
If rng.EntireRow.Hidden = True Then
For i = 1 To 15 Step 1
rng.EntireRow.RowHeight = i
DoEvents
Next i
Else
For i = 14 To 0 Step -1
rng.EntireRow.RowHeight = i
DoEvents
Next i
End If
End With
End Sub
I do a lot of animations in Excel for pedagogical reasons (mostly animations of charts). I sometimes use variations of the following sub:
Sub Pause(delay As Double)
Dim start As Double
start = Timer
Do While Timer < start + delay
DoEvents
Loop
End Sub
Then in the main code, have something like Pause 0.10 after (or instead of) where you currently have DoEvents. Low tech, but it sometimes helps.

Pause Excel graph while data is updating

I have lots of data that is pulled by a press of a button from SQL query through connections in Excel. Then I compose few simple calculations to get results. I also have 4 graphs that are based off that data.
I run into an issue where the code will take few minutes to execute. I believe it is due to the fact that while data is being updated, graphs are updated as well. I ran into that conclusion after removing graphs, it was significantly faster.
Is there a way to speed up this process a bit? Can I pause the graphing and resume it after all the data have been updated?
Thank you!
Have you considered offsetting the chart area in vba and switching back at the end of the code?
Here's how you can Select the Chart Area in VBA.
For example. If you want to chart data in Range A1:A10 then you can do the following
Charts(1).SetSourceData Source:=Sheets(1).Range("B1:B10")
your logic
Charts(1).SetSourceData Source:=Sheets(1).Range("A1:A10")
This "Aims" the chart at a different range so that it doesn't try to recompute the graph after each cell change. Once your logic is complete, then "Aim" it back at the correct range.
I suggest using
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
And perhaps also
Application.EnableEvents = False
Before the query,
And reversing it after the query
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
The way I did it was to clear all series in all the graphs at the beginning. Formatting stays the same on each graph.I created a sub that I call in the main program from where I am sending each chart variable name declared as ListObject and assigned a chart name.
Private Sub DeleteOldData(CurrentChart As ChartObject)
Dim s As Long
With CurrentChart
For s = .Chart.SeriesCollection.Count To 1 Step -1
.Chart.SeriesCollection(s).Delete
Next s
End With
End Sub
Then, I update the data. After, I re-assign all the series back the graph through another sub.
Private Sub AddData(CurrentChart As ChartObject, table1 As ListObject, table2 As ListObject, series1 As String, series2 As String)
CurrentChart.Chart.SeriesCollection.NewSeries
CurrentChart.Chart.FullSeriesCollection(1).Name = series1
CurrentChart.Chart.FullSeriesCollection(1).Values = table1.ListColumns(2).DataBodyRange
CurrentChart.Chart.FullSeriesCollection(1).XValues = table1.ListColumns(1).DataBodyRange
CurrentChart.Chart.SeriesCollection.NewSeries
CurrentChart.Chart.FullSeriesCollection(2).Name = series2
CurrentChart.Chart.FullSeriesCollection(2).Values = table2.ListColumns(2).DataBodyRange
CurrentChart.Chart.FullSeriesCollection(2).XValues = table2.ListColumns(1).DataBodyRange
CurrentChart.Chart.FullSeriesCollection(2).Select
DoEvents
End Sub
table1 and table2 are the tables from where I am pulling the data. I had to add 2 graphs on 1 chart from 2 different tables. Series1 and Series2 are the names for the series. I declared them before calling each sub.

Excel VBA Auto Filter Pivot Table

I have compiled VBA code to filter through each name in a pivot table and then call other subroutines to manipulate and format the table. This code has worked perfectly for me in the past but after updating the source table and making minor formatting changes to the pivot table it now fails me.
Here is the code:
Sub AutoFilterEachName()
Piv_Sht = ActiveSheet.Name
Sheets(ActiveSheet.Name).Select
For Each PivotItem In ActiveSheet.PivotTables(1).PageFields(1).PivotItems
ActiveSheet.PivotTables(1).PageFields(1).CurrentPage = PivotItem.Value
Call PivotCopyFormatValues
Call DeleteRows2
Call DeleteRows2
Call AddComment
Call Move_Save_As
Sheets(Piv_Sht).Select
Next
End Sub
First: the line ActiveSheet.PivotTables(1).PageFields(1).CurrentPage = PivotItem.Value doesn't change the filter to the first value of the Name filter when the code is started.
Second: When the routine reaches Next it goes to End Sub with out going back up to the For Each line. I have tried adding Next PivotItem whit no results. So it runs through the code once and stops.
I am at a dead end so any help is appreciated.
Sorry for the 7 month delayed response; if you still need help...I think this might help you achieve the result you are seeking:
Sub AutoFilterEachName()
Dim pTbl As PivotTable
Dim piv_sht As Worksheet
Dim i As Long
Set piv_sht = ThisWorkbook.ActiveSheet
Set pTbl = piv_sht.PivotTables(1)
piv_sht.Select
For i = 1 To pTbl.PageFields(1).PivotItems.Count
'set the PageField page equal to the name of the PivotItem at index i
'if you need to cycle through multiple PageFields, consider a nested For loop or For Each loop
pTbl.PageFields(1).CurrentPage = pTbl.PageFields(1).PivotItems(i).Name
Call PivotCopyFormatValues
Call DeleteRows2
Call DeleteRows2
Call AddComment
Call Move_Save_As
piv_sht.Select
Next i
End Sub
One reason your For Next wasn't executing and going immediately to End Sub is because your PageFields were empty; if there are no PageFields to loop through, then your loop will exit immediately. One solution to this is to always make sure there is at least one PageField. You could achieve this by entering this code before your For Loop:
pTbl.PivotFields(1).Orientation = xlPageField
This will insert the first PivotField in your table as the PageField.

Vb excel loop not updating

I have the following code and what I try to do is basically collect data and locate that data in a cell starting from A1 up to A100 the data comes from cell M4 this particular cell is dynamic and is constantly changing it's value, is Pulling data from DDE
the code works but for some reason it takes the first value and does not update as the M4 is changing.
Any Ideas?
Sub looptest()
Dim loop_ctr As Integer
For loop_ctr = 1 To 100
ActiveSheet.Range("A" & loop_ctr).Value = Worksheets("sheet1").Range("M4")
Application.Wait (Now + TimeValue("0:00:01"))
Next loop_ctr
MsgBox " Done! "
End Sub
After Application.Wait ... line try adding:
DoEvents
As written, you code doesn't expose Excel to any other system events, like your DDE, to update the Excel application for the entire 100 second execution time of your loop.