Setting series name in Excel Graph causes flicker - vba

I am creating an Excel Spreadsheet graph using VBA like so:-
Private Sub Chart_Calculate()
Title$ = Range("charttitle")
ActiveChart.Axes(xlCategory).Select
With ActiveChart.Axes(xlCategory)
.MinimumScale = 0
.MaximumScale = 300
.MinorUnit = 10
.MajorUnit = 50
.Crosses = xlCustom
.CrossesAt = 0
.ReversePlotOrder = True
.ScaleType = xlLinear
.DisplayUnit = xlNone
End With
End Sub
I then attempt to set the series name, like this:-
ActiveChart.SeriesCollection(1).Name = CStr(some_value) & " Some Text"
When I add this line of code to the sub, it causes the Chart_Calculate function to be activated numerous times in rapid succession, causing the graph to flicker for a few seconds before stabilising.
Does anyone know what the matter is, and what I should do about it?
(This is Excel 2003 running on Windows XP.)
EDIT: PortlandRunner's suggestion cleared up the problem during the graph redrawing, but it still exists if the Graph is visible at startup. See also this.

Try inserting Application.Calculation = xlCalculationManual at the beginning of your code, and Application.Calculation = xlCalculationAutomatic at/near the end of your code.

Related

VB PowerPoint, showing a picture when several others are clicked

I've been learning today some VBA basics to apply in powerpoint, but I have some experience in some other languages. As title says, I want a picture to be shown after I click on 3 other pictures before that. When any of this 3 pictures are clicked, they trigger a tick to be shown above that image, and I'm using those as a refer to code my macro. I have the following:
Sub Condicion()
Set Diapo14 = ActivePresentation.Slides(14)
If Diapo14.Shapes("tick1").Visible = True And _
Diapo14.Shapes("tick2").Visible = True And _
Diapo14.Shapes("tick3").Visible = True Then
Diapo14.Shapes("FlechaDer").Visible = True
End If
End Sub
I have the picture I want to show (FlechaDer) with a disappear effect as soon as the slide starts, but no matter what I do, when I test the slide, the picture is always there. Maybe I'm not applying the correct approach, hope someone can help me. I'm not even sure if this can be done in PowerPoint.
I got it working with the code below. I had to replace the "ticks" in the If cycle, and instead of them I used the pictures that once clicked popped up the ticks:
Sub Can12()
Set Diapo12 = ActivePresentation.Slides(12)
Diapo12.Shapes("Can").Visible = False
If Diapo12.Shapes("Can").Visible = False And Diapo12.Shapes("Wool").Visible = False And Diapo12.Shapes("Pencil").Visible = False Then
Diapo12.Shapes("FlechaDer").Visible = True
End If
End Sub
Sub Wool12()
Set Diapo12 = ActivePresentation.Slides(12)
Diapo12.Shapes("Wool").Visible = False
If Diapo12.Shapes("Can").Visible = False And Diapo12.Shapes("Wool").Visible = False And Diapo12.Shapes("Pencil").Visible = False Then
Diapo12.Shapes("FlechaDer").Visible = True
End If
End Sub
Sub Pencil12()
Set Diapo12 = ActivePresentation.Slides(12)
Diapo12.Shapes("Pencil").Visible = False
If Diapo12.Shapes("Can").Visible = False And Diapo12.Shapes("Wool").Visible = False And Diapo12.Shapes("Pencil").Visible = False Then
Diapo12.Shapes("FlechaDer").Visible = True
End If
End Sub
It worked fine on activating an animation (Right Arrow popping up) when all 3 items were clicked. I had to add the corresponding macro to the picture. (Can, wool and pencil)

How To Speed Up VBA Code

I have an excel file with a VBA code (Not written by me)
How this code works is user enters a 6 digit number in a user form, the VBA then checks another sheet and if this 6 digit number is present on the worksheet.
If it does, it changes the stage, but if it doesn't it adds this 6 digit number to the worksheet
It used to work perfectly, but now because the excel file has grown in the number of rows, almost 6000 rows, this code is become very slow, takes up to 20 seconds to update the sheet
Can someone please help me speed this code up, or suggest another way to acheive it
The code is below
Private Sub cmdPSDUdate_Click()
Dim x
If (Me.PSDUDateRow = "") + (Me.PSDStageCB.ListIndex = -1) Then Exit Sub
With Sheets("psdata stage cals").ListObjects("PSDataStageCals")
x = Application.Match(Val(Me.PSDUDateRow), .ListColumns(1).DataBodyRange, 0)
If IsNumeric(x) Then
.ListRows(x).Range(2) = Me.PSDStageCB.Value
Else
.ListRows.Add.Range = Array(Val(Me.PSDUDateRow), Me.PSDStageCB)
End If
End With
Me.PSDUDateRow.Value = ""
Me.PSDStageCB.Value = ""
Me.PSDUDateRow.SetFocus
End Sub
Thanks in advance
Rahul
You could turn off screenupdating, automatic calculations etc
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
‘Place your macro code here
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
In general, there are two ways to speed up VBA code:
Write good code, that does not use Select, Activate, ActiveCell, Selection etc - How to avoid using Select in Excel VBA
Refer to these routines on the start and on the end of the code:
Public Sub OnEnd()
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.AskToUpdateLinks = True
Application.DisplayAlerts = True
Application.Calculation = xlAutomatic
ThisWorkbook.Date1904 = False
Application.StatusBar = False
End Sub
Public Sub OnStart()
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
Application.Calculation = xlAutomatic
ThisWorkbook.Date1904 = False
ActiveWindow.View = xlNormalView
End Sub
(For improvement ideas, kindly make PullRequest)
I think that Calculation should be always set to xlAutomatic, as far as if you need xlCalculationManual to speed up, it is a good idea to refactor the code. Furthermore manual calculation is too risky.
The same goes for Date1904 - it is always set to False.
In addition to the tweaks suggested by Storax, your code is slow because you are bringing data cell-by-cell over the Excel/VBA divide.
Furthermore, you can radically speed up your MATCH function by using the Binary version of it. Have a read of http://dailydoseofexcel.com/archives/2015/04/23/how-much-faster-is-the-double-vlookup-trick/ and also try to minimise the amount of individual transfers you do across the Excel/VBA divide by either performing the lookups entirely within the Excel sheet (by using VBA to write the formula in the sheet and execute it there) or by bringing all the data into VBA in one go using variant arrays, performing your logic, and then by dumping it back in one go. Google "Efficient way to transfer data between Excel and VBA" or something similar. Also check out any articles from Charles Williams on the subject.
I don't see anything wrong with your code. Perhaps the Workbook itself is the culprit. Is it becoming huge and slow to open ?
If yes, try searching for 'cleanup excel file'.
Some results I found:
https://excelfilecleaner.codeplex.com/
https://support.microsoft.com/en-us/help/3070372/how-to-clean-up-an-excel-workbook-so-that-it-uses-less-memory
When crunching large chunks of data in Excel that requires frequent referencing of cells, it’s always much much faster to copy the data to an array (copy the entire worksheet if necessary), process the data within the array, and then write back to the worksheet if necessary. Copying data from worksheet to array is a one line command that is very very fast. Same with array to worksheet. Relatively speaking, referencing cells is a very time consuming process compared with referencing elements of an array.

Getting a 400 error in VBA

I'm getting a frustrating error in my macro code. I have a small bit of code in two subs one opens all data groups and changes some of the print options and the other closes the groups and changes some of the print options.
This works fine but when I save and close on re-open if I click the macro buttons I get a 400 error message. To fix this I have comment out all the .pagesetup code and then run the macros again then uncomment and run the macro line by line and then the 400 error will disappear. However once I save and close this will come back and I have to repeat everything. Any help would be greatly appreciated.
Sub PropertyStrat_Click()
'
' PropertyStrat_Click Macro
'
ActiveSheet.Outline.ShowLevels RowLevels:=2 ' to expand the rows
Worksheets("Sheet1").PageSetup.Orientation = xlPortrait
Worksheets("Sheet1").PageSetup.PaperSize = xlPaperA3
Worksheets("Sheet1").PageSetup.Zoom = False
Worksheets("Sheet1").PageSetup.FitToPagesTall = 1
Worksheets("Sheet1").PageSetup.FitToPagesWide = 1
Worksheets("Sheet1").PageSetup.CenterHorizontally = True
Worksheets("Sheet1").PageSetup.CenterVertically = True
End Sub
Sub SimpleView_Click()
ActiveSheet.Outline.ShowLevels RowLevels:=1 ' to collapse the rows
Worksheets("Sheet1").PageSetup.PrintArea = "$A$1:$J$29,$A$30:$J$50"
Worksheets("Sheet1").PageSetup.Orientation = xlLandscape
Worksheets("Sheet1").PageSetup.PaperSize = xlPaperA4
Worksheets("Sheet1").PageSetup.Zoom = 100
Worksheets("Sheet1").PageSetup.CenterHorizontally = False
Worksheets("Sheet1").PageSetup.CenterVertically = False
End Sub

How can I set OptionButton font using VBA For Loop?

I am trying to manually set every OptionButton's font on a sheet to be a uniform size and type using a For Loop.
I can do them manually by writing out each specific button's information but I have hundreds of buttons.
I can even get VBA to write the correct syntax to a test Worksheet by using this code here:
`Private Sub Thisworkbook_Open()
For i = 1 to Worksheets("Core").OLEObjects.Count
If TypeName(Worksheets("Core").OLEObjects(i).Object) = "OptionButton" Then
Worksheets("testsheet").Range("A" & i).Value = Worksheets("Core").OLEObjects(i).Name
End If
Next i
End Sub`
But what I can't do is put the rest of this below code along with the above code to have ONE clean and concise statement that will manually set all OptionButton values to these settings:
`With Worksheets("Core").OptionButton1
.Font.Size = 11
.Font.Name = "Calibri"
.Font.Bold = False
End With`
Can someone explain to me how I can make this work?
Actually you have your answer in your question, all you have to do is to put your properties to correct location, as follows:
For i = 1 To Worksheets("Core").OLEObjects.Count
If TypeName(Worksheets("Core").OLEObjects(i).Object) = "OptionButton" Then
Worksheets("Core").OLEObjects(i).Object.FontSize = 5
' Remaining code goes here.
End If
Next i

Excel VBA AutoFit runs slowly

I have an excel vba macro that creates and formats a sales quote. I have a function that autofits merged cells. I use this function to autofit description fields as some of them are long and some are short. On a typical quote, this function is called around 40 times. The macro completes in under a second. If I run the exact same macro again (perhaps with different settings on how it will display) it takes upwards of 30-60 seconds. There's nothing in the rest of the macro that slows down with each run except for the following block:
Is there something that could be making this code run slower for the exact same set of inputs?
Sub AutoFit_Height(ByVal Target As Range)
Dim MergeWidth As Single
Dim cM As Range
Dim CWidth As Double
Dim NewRowHt As Double
With Target
.MergeCells = False
CWidth = .Cells(1).ColumnWidth
MergeWidth = 0
For Each cM In Target
cM.WrapText = True
MergeWidth = cM.ColumnWidth + MergeWidth
Next
'small adjustment to temporary width
MergeWidth = MergeWidth + Target.Cells.count * 0.66
.Cells(1).ColumnWidth = MergeWidth
.EntireRow.AutoFit
NewRowHt = .RowHeight
.Cells(1).ColumnWidth = CWidth
.MergeCells = True
.RowHeight = NewRowHt
End With
End Sub
Go to the start of the main body of code (the one that calls this subroutine) and add
Application.ScreenUpdating = False
as one of the first lines. Then at the end of that function, after this subroutine has been called, turn it back on:
Application.ScreenUpdating = True
This will keep it from redrawing the screen for every change in column/row size, resulting in a significantly faster run time.
Optimazing your script might start with
using xlsb file saving extension
look for any unecessary formatting by deleting unused rows and
columns and saving so to make the vertical and horizontal scroll bar
scroll just to the necessary data
Use named range as much as possible
This could be added to your script
At the start of the main module from where you call other modules or functions
With Application
.DisplayAlerts = False
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With
At the end of the main module task is complete
With Application
.DisplayAlerts = True
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
As you are manipulating many worksheet objects that's quite a cpu intensive process. A change in algorithm could improve time needed for this process. Maybe you should post the entire code so to help you further.
Cheers,
Pascal
http://multiskillz.tekcities.com
Autofit is painfully slow for me to. The only thing I can add to any other answer here is to put it in a separate module and only call it when necessary or time is available. Also, to implement last, once all other code is tested and working.