I need help setting the X and Y axes title inside Excel 2007 VBA. It keeps complaining about "Object required":
Sub macro2()
Dim xAxis As Axis
icount = 1
Charts.Add
Charts(icount).Name = iskewplane & "deg Skew Plane"
Charts(icount).Activate
Set xAxis = Charts(icount).Axes(xlCategory)
With xAxis
.Axis
.AxisTitle.Text = "Theta (deg)"
End With
Is there something wrong in my code? I tried recording the macro during setting the axis title name, but the macro is blank during the name setting.
Any help is appreciated
You should use Option Explicit because iCount wasn't defined and iskewplane wasn't either.
Here is the right code:
Sub mac()
Dim xAxis As Axis
Dim iCount As Integer
iCount = 1
Charts.Add
Charts(iCount).Name = "deg Skew Plane"
Charts(iCount).Activate
Set xAxis = Charts(iCount).Axes(xlCategory)
With xAxis
.HasTitle = True
.AxisTitle.Caption = "Theta (deg)"
End With
End Sub
You first have to create the AxisTitle object - an axis doesn't automatically have one. This is done by setting Axis.HasTitle = True - a slightly unusual method.
Related
I found a GREAT Macro for Word here! :D- How to include BackgroundPatternColor or HighlightColor in a Word Style definition?
I noticed that VBA has a Transparency value - https://learn.microsoft.com/en-us/office/vba/api/word.lineformat.transparency
In the Macro below, can you see any way to add Transparency to it?
Can you see any way to get it to work in this Macro?
Sub ChangeStyleColor()
Dim styl As Word.Style
Dim stylName As String
Dim color As Word.WdColor
stylName = "Theory"
color = RGB(104, 0, 266)
' the style might not exist - if not, create it
On Error Resume Next
Set styl = ActiveDocument.Styles(stylName)
On Error GoTo 0
If styl Is Nothing Then
Set styl = ActiveDocument.Styles.Add(stylName, Word.WdStyleType.wdStyleTypeCharacter)
styl.BaseStyle = Word.WdBuiltinStyle.wdStyleDefaultParagraphFont
End If
CharStyleBackgroundColor styl, color
End Sub
Sub CharStyleBackgroundColor(styl As Word.Style, color As Word.WdColor)
styl.Font.Shading.BackgroundPatternColor = color
End Sub
Many thanks,
OT
I tried just dropping in the line
Transparency = 0.5
beneath the RGB value, but that didn't work.
Then I tried dropping in
,Transparency = 0.5
That generated an error.
I'm attempting to get the trend line equation from the first series in my chart to a shape text box placed elsewhere on the worksheet - however, I can only get the textbox to populate correctly when I'm stepping through the code line by line - during run-time it has no effect:
For Each chtObj In ActiveSheet.ChartObjects
Set cht = chtObj.Chart
For Each srs In chtObj.Chart.SeriesCollection
srs.Trendlines(1).DisplayEquation = True 'Display the labels to get the value
ThisWorkbook.Worksheets("MyDataSheet").Shapes(slopetextboxes(k)).TextFrame.Characters.Text = srs.Trendlines(1).DataLabel.Text
srs.Trendlines(1).DisplayEquation = False 'Turn it back off
Exit For
Next srs
k = k + 1 ' for the slope textboxes
Next chtObj
Note that slopetextboxes is an array containing the names of ~6 shape text boxes.
As far as I know there's no way to get the trend line data label without stopping to display it. I've tried storing it in a string first, DoEvents, and turning Application.ScreenUpdating back on, all to no avail. I'm stumped here.
EDIT: It appears that by placing DoEvents after .DisplayEquation = True I'm able to have some of my shapes populate correctly, but not all. Still appears to be some kind of run-time issue.
BOUNTY EDIT: I've moved ahead to grab the slopes with a formula ran into the data itself, but I still don't understand why I can't grab the chart's .DataLabel.Text during run-time. I can grab it when stepping through, not during run-time. It appears to just take the PREVIOUS series slope and place it in the shape (or a cell, it doesn't even matter where the destination is). DoEvents placed in different spots yields different outcomes, so something must be going on.
Updated with better understanding of the bug. This works for me in excel 2016 with multiple changes to the source data (and therefore the slope)
I tried myChart.refresh - didnt work. I tried deleting and then re-adding the entire trendline, also didnt work.
This works for everything but the first case. First case needs to be hit twice. Same as for .select
If you try and delete trendline even after assigning its text to textbox, this wont work
Option Explicit
Sub main()
Dim ws As Worksheet
Dim txtbox As OLEObject
Dim chartObject As chartObject
Dim myChart As chart
Dim myChartSeriesCol As SeriesCollection
Dim myChartSeries As Series
Dim myChartTrendLines As Trendlines
Dim myTrendLine As Trendline
Set ws = Sheets("MyDataSheet")
Set txtbox = ws.OLEObjects("TextBox1")
For Each chartObject In ws.ChartObjects
Set myChart = chartObject.chart
Set myChartSeriesCol = myChart.SeriesCollection
Set myChartSeries = myChartSeriesCol(1)
Set myChartTrendLines = myChartSeries.Trendlines
With myChartTrendLines
If .Count = 0 Then
.Add
End If
End With
Set myTrendLine = myChartTrendLines.Item(1)
With myTrendLine
.DisplayEquation = True
txtbox.Object.Text = .DataLabel.Text
End With
Next chartObject
End Sub
Here's my code that seems to definitely work when just pressing F5:
Basically, I store the text in a collection, then iterate through all of the textboxes to add the text to the textboxes. If this wasn't precisely what you were asking for, then I hope this helps in any way.
Sub getEqus()
Dim ws As Worksheet
Dim cht As Chart
Dim srs As Variant
Dim k As Long
Dim i As Long
Dim equs As New Collection
Dim shp As Shape
Dim slopetextboxes As New Collection
Set ws = Excel.Application.ThisWorkbook.Worksheets(1)
'part of the problem seemed to be how you were defining your shape objects
slopetextboxes.Add ws.Shapes.Range("TextBox 4")
slopetextboxes.Add ws.Shapes.Range("TextBox 5")
For Each chtObj In ActiveSheet.ChartObjects
Set cht = chtObj.Chart
For Each srs In chtObj.Chart.SeriesCollection
srs.Trendlines(1).DisplayEquation = True 'Display the labels to get the value
equs.Add srs.Trendlines(1).DataLabel.Text
srs.Trendlines(1).DisplayEquation = False 'Turn it back off
Next srs
Next chtObj
For i = 1 To slopetextboxes.Count
'test output i was trying
ws.Cells(i + 1, 7).Value = equs(i)
slopetextboxes(i).TextFrame.Characters.Text = equs(i)
Next
End Sub
Pictures of what the output looks like when i just press the button
Good luck!
This worked for me - I loop through multiple charts on Sheet1, toggling DisplayEquation and then writing the equation to a textbox/shape on the different worksheet. I used TextFrame2.TextRange but TextFrame worked as well, if you prefer that. I wrote to both a regular text box, as well as a shape, which was probably overkill as the syntax is the same for both.
This gets the trendline equation from the first Series - it sounded like you didn't want to loop through all the Series in the SeriesCollection.
Sub ExtractEquations()
Dim chtObj As ChartObject
Dim slopeTextBoxes() As Variant
Dim slopeShapes() As Variant
Dim i As Integer
slopeTextBoxes = Array("TextBox 1", "TextBox 2", "TextBox 3")
slopeShapes = Array("Rectangle 6", "Rectangle 7", "Rectangle 8")
For Each chtObj In ThisWorkbook.Sheets("Sheet1").ChartObjects
With chtObj.Chart.SeriesCollection(1).Trendlines(1)
.DisplayEquation = True
ThisWorkbook.Sheets("MyDataSheet").Shapes(slopeTextBoxes(i)).TextFrame2.TextRange.Characters.Text = .DataLabel.Text
ThisWorkbook.Sheets("MyDataSheet").Shapes(slopeShapes(i)).TextFrame2.TextRange.Characters.Text = .DataLabel.Text
.DisplayEquation = False
i = i + 1
End With
Next chtObj
End Sub
I've written this off as a bug - The only workaround was discovered by BrakNicku which is to Select the DataLabel before reading its Text property:
srs.Trendlines(1).DataLabel.Select
Not a sufficient solution (since this can cause some issues during run-time), but the only thing that works.
I had a similar issue running the code below and my solution was to run Application.ScreenUpdating = True between setting the trendline and querying the DataLabel. Note that screen updating was already enabled.
'Set trendline to the formal y = Ae^Bx
NewTrendline.Type = xlExponential
'Display the equation on the chart
NewTrendline.DisplayEquation = True
'Add the R^2 value to the chart
NewTrendline.DisplayRSquared = True
'Increse number of decimal places
NewTrendline.DataLabel.NumberFormat = "#,##0.000000000000000"
'Enable screen updating for the change in format to take effect otherwise FittedEquation = ""
Application.ScreenUpdating = True
'Get the text of the displated equation
FittedEquation = NewTrendline.DataLabel.Text
If it works when you step through, but not when it runs then it's an issue with timing and what Excel is doing in between steps. When you step through, it has time to figure things out and update the screen.
FYI, Application.Screenupdating = False doesn't work when stepping
through code. It gets set back to True wherever the code pauses.
When did you give it a chance to actually do the math and calculate the equation? The answer is that, you didn't; hence why you get the previous formula.
If you add a simple Application.Calculate (in the right spot) I think you'll find that it works just fine.
In addition, why should Excel waste time and update text to an object that isn't visible? The answer is, it shouldn't, and doesn't.
In the interest of minimizing the amount of times you want Excel to calculate, I'd suggest creating two loops.
The first one, to go through each chart and display the equations
Then force Excel to calculate the values
Followed by another loop to get the values and hide the equations again.
' Display the labels on all the Charts
For Each chtObj In ActiveSheet.ChartObjects
Set cht = chtObj.Chart
For Each srs In chtObj.Chart.SeriesCollection
srs.Trendlines(1).DisplayEquation = True 'Display the labels to get the value
' I take issue with the next line
' Why are you creating a loop, just for the first series?
' I hope this is just left over from a real If condition that wan't included for simplicity
Exit For
Next srs
Next chtObj
Application.ScreenUpdating = True
Application.Calculate
Application.ScreenUpdating = False
' Get the Equation and hide the equations on the chart
For Each chtObj In ActiveSheet.ChartObjects
Set cht = chtObj.Chart
For Each srs In chtObj.Chart.SeriesCollection
ThisWorkbook.Worksheets("MyDataSheet").Shapes(slopetextboxes(k)).TextFrame.Characters.Text = srs.Trendlines(1).DataLabel.Text
srs.Trendlines(1).DisplayEquation = False 'Turn it back off
Exit For
Next srs
k = k + 1 ' for the slope textboxes
Next chtObj
Application.ScreenUpdating = True
Update:
I added a sample file based on your description of the issue. You can select 4 different options in an ActiveX ComboBox which copies values to the Y-Values of a chart. It shows the trend-line equation below, based on the formula & through copying the value from the chart into a Textbox shape.
Maybe 2016 is different, but it works perfectly in 2013. Try it out...
Shape Text Box Example.xlsm
I am trying to change the text color of the chart title of a histogram chart in PowerPoint.
Here is what I do:
var colorFormat = chart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor;
colorFormat.RGB = ...;
// or
colorFormat.ObjectThemeColor = ...;
This works for the standard charts like line charts. But it doesn't work for other chart types like histogram, waterfall, tree map etc.
In these cases, setting ObjectThemeColor sets the text to black. Setting RGB does actually set the correct color. However, in both cases, as soon as the user changes the selection, the text color jumps back to the one it had previously.
How can I set the text color of the title of one of these charts?
I am using VSTO and C# but a VBA solution is just as welcome as long as it can be translated to C# and still work.
Based on what info you gave I built a histogram and waterfall chart in PowerPoint and was successful using:
Sub ChartTitleFontColor()
Dim oShp As Shape
Dim oCht As Chart
'Waterfall on slide 1
Set oShp = ActivePresentation.Slides(1).Shapes(1)
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then
Debug.Print oCht.ChartTitle.Text
oCht.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(251, 5, 40)
End If
'Histogram on slide 2
Set oShp = ActivePresentation.Slides(2).Shapes(1)
If oShp.HasChart Then
Set oCht = oShp.Chart
End If
' Do stuff with your chart
If oCht.HasTitle Then Debug.Print oCht.ChartTitle.Text
oCht.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(251, 5, 40)
End If
' Clean up
Set oShp = Nothing
Set oCht = Nothing
End Sub
Your code works in my test. I created two charts in PowerPoint 2016, the first one a waterfall, and the second another type. The following code changes the title color only (and text just a proof of it being changed) and nothing else. I can select the other chart and nothing changes. I could not find a bug about this in a search. Perhaps something in the remaining code is changing it back?
Sub test()
Dim myPresentation As Presentation
Set myPresentation = ActivePresentation
Dim myShape As Shape
Set myShape = myPresentation.Slides(1).Shapes(1)
Dim theChart As Chart
If myShape.HasChart Then
Set theChart = myShape.Chart
If theChart.ChartTitle.Text = "This is blue" Then
theChart.ChartTitle.Text = "This is yellow"
theChart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(255, 255, 0)
Else
theChart.ChartTitle.Text = "This is blue"
theChart.ChartTitle.Format.TextFrame2.TextRange.Font.Fill.ForeColor.RGB = RGB(0, 255, 255)
End If
End If
End Sub
This is not exactly an answer but I think you should name your object.
Instead of using
ActivePresentation.Slides(1).Shapes(1)
You can name the object.
I've seen this question on font properties and it's got me part of the way.
I'm trying to change the font colour. I so far have the following code:
ActiveSheet.ChartObjects("Chart 2").Activate
ActiveChart.Axes(xlValue, xlSecondary).TickLabels.Font.Color = 5855577
This works fine.
What's irritating me is that I have to do this via activating the chart.
Surely there's a better way. If I do either of the following it doesn't work:
Dim cht As ChartObject
Set cht = ActiveSheet.ChartObjects("Chart 2")
cht.Axes(xlValue, xlSecondary).TickLabels.Font.Color = 5855577
'-------------------------
Dim cht As ChartObject, ax As Axes
Set cht = ActiveSheet.ChartObjects("Chart 2")
Set ax = cht.Axes(xlValue, xlSecondary)
ax.TickLabels.Font.Color = 5855577
I generally try to avoid selecting or activating in my code so this is just annoying! Any ideas?
Axes isn't actually a member of a ChartObject, but a member of ChartObject.Chart.
Therefore, you want to access the Axes-collection of ChartObject.Chart
With ActiveSheet.ChartObjects("Chart 1")
.Chart.Axes(xlValue, xlPrimary).TickLabels.Font.Color = vbRed
End with
Why does it work if you activate it first? Well, because ActiveChart actually returns the Chart-object, instead of the ChartObject-object.
In case you're trying to record a macro, the code for filling the text forecolor won't (TextFrame2 object) work due to a bug already reported to Microsoft, so using the code below, you can do it without issue. You can also change the properties according to your needs.
Use this code:
ActiveChart.Axes(xlCategory).TickLabels.Font.Color = RGB(100, 100, 100)
I prefer also to avoid working with ActvieSheet (if possible).
The code below, will set the nested properties under ChartObject for the properties you need, such as Chart.Axes , and later also for TickLabels.
Code
Option Explicit
Sub Chart_AutoSetup()
Dim ChtObj As ChartObject, ax As Axis, T2 As TickLabels
Dim ShtCht As Worksheet
' change "Chart_Sheet" to your sheet's name (where you have your chart's data)
Set ShtCht = Worksheets("Chart_Sheet") ' <-- set the chart's location worksheet
Set ChtObj = ShtCht.ChartObjects("Chart2") '<-- set chart object
With ChtObj
Set ax = .Chart.Axes(xlValue, xlSecondary) '<-- set chart axes to secondary
Set T2 = ax.TickLabels '<-- set Ticklables object
T2.Font.Color = 5855577
T2.Font.Italic = True ' <-- just another property you can easily modify
End With
End Sub
Is there a way to add a callout label to a point in a chart, without using Select?
Recording a macro, I got this:
Sub Macro9()
ActiveSheet.ChartObjects("SPC").Activate
ActiveChart.FullSeriesCollection(1).Select
ActiveChart.FullSeriesCollection(1).Points(4).Select
ActiveChart.SetElement (msoElementDataLabelCallout)
End Sub
But I would rather like to avoid using Select. I tried simply using the SetElement-method on the point, but that failed. Using the HasDataLabel = True-method simply adds a datalabel.
Is there any workarounds to selecting the point and then using SetElement on the chart, or will I have to settle for something resembling the above macro?
Is this what you are trying? In the below code we have avoided .Activate/.Select completely :)
Feel free to play with .AutoShapeType property. You can also format the data label to show the values in whatever format you want.
Sub Sample()
Dim objC As ChartObject, chrt As Chart, dl As DataLabel
Dim p As Point
Set objC = Sheet1.ChartObjects(1)
Set chrt = objC.Chart
Set p = chrt.FullSeriesCollection(1).Points(4)
p.HasDataLabel = True
Set dl = p.DataLabel
With dl
.Position = xlLabelPositionOutsideEnd
.Format.AutoShapeType = msoShapeRectangularCallout
.Format.Line.Visible = msoTrue
End With
End Sub
Screenshot
As I said in a comment: I couldn't find a way to do this directly but thought I'd be able to work around it.
Turns out I was unsuccessful!
But let's cover an edge case which for some uses will have a pretty easy solution; say you don't need datalabels except for the instances where you want callout:
Sub chartTest()
Dim co As ChartObject
Dim ch As Chart
Dim i As Integer
' The point index we want shown
i = 2
Set co = Worksheets(1).ChartObjects(2)
Set ch = co.Chart
co.Activate
ch.SetElement (msoElementDataLabelCallout)
For j = 1 To s.Points.Count
' We can change this to an array check if we want several
' but not all points to have callout
If j <> i Then s.Points(j).HasDataLabel = False
Next j
End Sub
For anyone desperate, the closest I came was to create an overlay using the original chart as a template. It doesn't work accurately for arbitrary charts, however, due to positioning issues with the callout box.
But at this point, you might as well have just added a textbox or something far less involved than copying a chart, deleting half its contents and making the rest of it invisible...
But for the sake of Cthul-- I mean, science:
Sub pTest()
Dim co As ChartObject
Dim ch As Chart
Dim s As Series
Dim p As Point
Set co = Worksheets(1).ChartObjects(1)
Set ch = co.Chart
Set s = ch.SeriesCollection(1)
i = 2
Call copyChartTest(co, ch, i)
End Sub
Sub copyChartTest(ByRef co As ChartObject, ByRef cht As Chart, ByVal i As Integer)
Dim ch As Chart ' The overlay chart
Set ch = co.Duplicate.Chart
' Set callout
ch.SetElement (msoElementDataLabelCallout)
' Invisibil-ate!
With ch
.ChartArea.Fill.Visible = msoFalse
.SeriesCollection(1).Format.Line.Visible = False
.ChartTitle.Delete
.Legend.Delete
For j = 1 To .SeriesCollection(1).Points.Count
.SeriesCollection(1).Points(j).Format.Fill.Visible = msoFalse
If j <> i Then .SeriesCollection(1).Points(j).HasDataLabel = False
Next j
End With
' Align the charts
With ch
.Parent.Top = cht.Parent.Top
.Parent.Left = cht.Parent.Left
End With
End Sub
And the result: DataLabels intact with only 1 point having callout.
Have you tried this free tool http://www.appspro.com/Utilities/ChartLabeler.htm by Rob Bovey?
There is an option "manual label" which seems to be very close to what you want. I am using the version of 1996-97 which has visible VBA code. I have not checked if the latest version has.
try the below code
Sub Macro9()
ActiveSheet.ChartObjects("SPC").Activate
ActiveChart.SeriesCollection(1).Points(4).HasDataLabel = True
ActiveChart.SeriesCollection(1).Points(4).DataLabel.Text = "Point 4 Test"
End Sub