Is there a possibility to address a chart object in an excel sheet via its exact position? Google didn't help so far so any input is appreciated.
Best regards,
Stefan
You can use TopLeftCell and BottomRightCell to find a chart between given range.
Sub testChart()
Dim oChart As Chart
'/ Selecet the chart , if found in Range D4:F10
Set oChart = findChart(Sheet1.Range("D4:F10"))
If Not oChart Is Nothing Then
oChart.Parent.Select
Else
MsgBox "No chart found."
End If
End Sub
Function findChart(ByVal rngChart As Range) As Chart
Dim oChart As Chart
Dim oChartObj As ChartObject
Dim wksChart As Worksheet
Dim rngCArea As Range
Set wksChart = rngChart.Parent
For Each oChartObj In wksChart.ChartObjects
Set rngCArea = Intersect(wksChart.Range(rngChart.Address), wksChart.Range(oChartObj.TopLeftCell, oChartObj.BottomRightCell))
If Not rngCArea Is Nothing Then
Set oChart = oChartObj.Chart
End If
Next
Set findChart = oChart
End Function
Related
Sub OO()
Dim oPPApp As Object, oPPPrsn As Object, oPPSlide As Object
Dim oPPShape As Object
Dim FlName As String
'~~> Change this to the relevant file
FlName = "C:\Users\lich_\Documents\test.pptx"
'~~> Establish an PowerPoint application object
On Error Resume Next
Set oPPApp = GetObject(, "PowerPoint.Application")
If Err.Number <> 0 Then
Set oPPApp = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
oPPApp.Visible = True
Set oPPPrsn = oPPApp.Presentations.Open(FlName, WithWindow:=msoFalse)
Set oPPSlide = oPPPrsn.Slides(2)
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
End Sub
As you can see above, I'm trying to edit the chart data in vba.
But since I have control many charts later, I would like to make the workbook invisible ( or not open it at all if possible )
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
In this code I opened by "ActivateChartDataWindow" method and change the data which I want and Closed.
Is there any way to make the window invisible or to edit data without even opening?
Thank you for your help in advance.
It's possible to update existing chart data without Activate as per #mooseman's answer.
However, if the chart is new/inserted at runtime, as far as I know this cannot be accomplished with interop, as the AddChart method adds the chart and simultaneously creates/activates the Excel Workbook. While you may not need to call the Activate method, there is no way to insert or add a new chart that doesn't involve opening an Excel instance. There is no way around this, this is just how the UI functions and it is by design.
To Update Data in EXISTING Chart / ChartData
Below native PowerPoint VBA, but should port easily to Excel with proper reference(s)
Sub test()
Dim PPT As PowerPoint.Application
Dim pres As Presentation
Dim sld As Slide
Dim shp As Shape
Dim cht As Chart
Dim rng As Object ' Excel.Range
Set PPT = Application 'GetObject(,"PowerPoint.Application")
Set pres = ActivePresentation
Set sld = pres.Slides(1)
Set shp = sld.Shapes(1)
Set cht = shp.Chart
Call changeData(cht, 6.3)
pres.Slides.AddSlide pres.Slides.Count + 1, sld.CustomLayout
Set sld = pres.Slides(pres.Slides.Count)
sld.Shapes.AddChart().Chart.ChartData.Workbook.Application.WindowState = -4140
Set cht = sld.Shapes(1).Chart
Call changeData(cht, 3.9)
End Sub
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
The requirement is to use the With block in VBA.
Some brief tests suggest this is also doable via Interop from python using win32com:
from win32com import client
ppt = client.Dispatch("PowerPoint.Application")
pres = ppt.ActivePresentation
sld = pres.Slides[0]
cht = sld.Shapes[0].Chart
cht.ChartData.Workbook.Worksheets[0].ListObjects[0].Range.Cells(2,2).Value = 9
And also in C#:
using Microsoft.Office.Interop.PowerPoint;
public static void foo(int value = 10)
{
Application ppt = new Microsoft.Office.Interop.PowerPoint.Application();
Presentation pres = ppt.ActivePresentation;
Slide sld = pres.Slides[1];
Chart cht = sld.Shapes[1].Chart;
{
cht.ChartData
.Workbook.Worksheets[1].ListObjects[1].Range.Cells(2, 2).Value = value;
}
}
To Minimize the ChartData / Workbook Window:
In practice I have not had reliable luck using the With method. If you cannot get it to work, then the next-best option is to minimize the window immediately:
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
.Activate
.Workbook.Application.WindowState = -4140 '## Minimize Excel
'## DO STUFF:
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
Note that this method does briefly flash Excel on the screen, and this sucks because in that brief instant, it can intercept keystrokes/etc.
You don't have to activate the chartdata worksheet to make changes to it.
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("B2").Value = 0.1231
End with
You can also set the chartdata sheet to equal a range in an excel sheet
path2 = "C:\JohnDoe\Vasquez_061118.xlsm"
Set xlWorkBook = Workbooks.Open(FileName:=path2, ReadOnly:=True)
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("A1:B2").Value = xlWorkBook.Sheets(1).Range("A2:B3").Value
End With
Sub OO()
Dim oPPApp As Object, oPPPrsn As Object, oPPSlide As Object
Dim oPPShape As Object
Dim FlName As String
'~~> Change this to the relevant file
FlName = "C:\Users\lich_\Documents\test.pptx"
'~~> Establish an PowerPoint application object
On Error Resume Next
Set oPPApp = GetObject(, "PowerPoint.Application")
If Err.Number <> 0 Then
Set oPPApp = CreateObject("PowerPoint.Application")
End If
Err.Clear
On Error GoTo 0
oPPApp.Visible = True
Set oPPPrsn = oPPApp.Presentations.Open(FlName, WithWindow:=msoFalse)
Set oPPSlide = oPPPrsn.Slides(2)
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
End Sub
As you can see above, I'm trying to edit the chart data in vba.
But since I have control many charts later, I would like to make the workbook invisible ( or not open it at all if possible )
With oPPSlide.Shapes("Chart1").Chart.ChartData
.ActivateChartDataWindow
.Workbook.Worksheets("Sheet1").Range("B2").Value = 0.1231
.Workbook.Close
End With
In this code I opened by "ActivateChartDataWindow" method and change the data which I want and Closed.
Is there any way to make the window invisible or to edit data without even opening?
Thank you for your help in advance.
It's possible to update existing chart data without Activate as per #mooseman's answer.
However, if the chart is new/inserted at runtime, as far as I know this cannot be accomplished with interop, as the AddChart method adds the chart and simultaneously creates/activates the Excel Workbook. While you may not need to call the Activate method, there is no way to insert or add a new chart that doesn't involve opening an Excel instance. There is no way around this, this is just how the UI functions and it is by design.
To Update Data in EXISTING Chart / ChartData
Below native PowerPoint VBA, but should port easily to Excel with proper reference(s)
Sub test()
Dim PPT As PowerPoint.Application
Dim pres As Presentation
Dim sld As Slide
Dim shp As Shape
Dim cht As Chart
Dim rng As Object ' Excel.Range
Set PPT = Application 'GetObject(,"PowerPoint.Application")
Set pres = ActivePresentation
Set sld = pres.Slides(1)
Set shp = sld.Shapes(1)
Set cht = shp.Chart
Call changeData(cht, 6.3)
pres.Slides.AddSlide pres.Slides.Count + 1, sld.CustomLayout
Set sld = pres.Slides(pres.Slides.Count)
sld.Shapes.AddChart().Chart.ChartData.Workbook.Application.WindowState = -4140
Set cht = sld.Shapes(1).Chart
Call changeData(cht, 3.9)
End Sub
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
The requirement is to use the With block in VBA.
Some brief tests suggest this is also doable via Interop from python using win32com:
from win32com import client
ppt = client.Dispatch("PowerPoint.Application")
pres = ppt.ActivePresentation
sld = pres.Slides[0]
cht = sld.Shapes[0].Chart
cht.ChartData.Workbook.Worksheets[0].ListObjects[0].Range.Cells(2,2).Value = 9
And also in C#:
using Microsoft.Office.Interop.PowerPoint;
public static void foo(int value = 10)
{
Application ppt = new Microsoft.Office.Interop.PowerPoint.Application();
Presentation pres = ppt.ActivePresentation;
Slide sld = pres.Slides[1];
Chart cht = sld.Shapes[1].Chart;
{
cht.ChartData
.Workbook.Worksheets[1].ListObjects[1].Range.Cells(2, 2).Value = value;
}
}
To Minimize the ChartData / Workbook Window:
In practice I have not had reliable luck using the With method. If you cannot get it to work, then the next-best option is to minimize the window immediately:
Sub changeData(c As Chart, v As Double)
Dim rng As Object
With c.ChartData
.Activate
.Workbook.Application.WindowState = -4140 '## Minimize Excel
'## DO STUFF:
Set rng = .Workbook.Worksheets(1).ListObjects(1).Range
rng.Cells(2, 2).Value = v ' etc.
.Workbook.Close
End With
End Sub
Note that this method does briefly flash Excel on the screen, and this sucks because in that brief instant, it can intercept keystrokes/etc.
You don't have to activate the chartdata worksheet to make changes to it.
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("B2").Value = 0.1231
End with
You can also set the chartdata sheet to equal a range in an excel sheet
path2 = "C:\JohnDoe\Vasquez_061118.xlsm"
Set xlWorkBook = Workbooks.Open(FileName:=path2, ReadOnly:=True)
With oPPSlide.Shapes("Chart1").Chart.ChartData
'this updates the value in the datasheet
.Workbook.Sheets(1).Range("A1:B2").Value = xlWorkBook.Sheets(1).Range("A2:B3").Value
End With
I am looking for VBA codes to create think cell chart from excel ranges.
All I found in the internet were VBA codes through which I can update a named thinkcell chart.
However I want the macro to create a new powerpoint and new thinkcell chart from my defined range.
Would that be possible?
Below is the code I found through which one can update Thinkcell chart, but not create a new thinkcell chart.
Sub UpdateThinkCellChart(Rng As Range, sChartName As String)
'Get the think-cell add-in object
Dim tcaddin As Object
Dim ppapp As Object
Dim pres As Object
Set tcaddin = Application.COMAddIns("thinkcell.addin").Object
'Set PowerPoint instance
'Set ppapp = New PowerPoint.Application
On Error Resume Next
Set ppapp = GetObject(, "Powerpoint.Application")
On Error GoTo 0
'Create PowerPoint presentation if none is open:
If ppapp Is Nothing Then
MsgBox "No PowerPoint presentation is open. Please open the relevant presentation and ensure that you have pre-assigned chart names to your ThinkCell charts"
Exit Sub
End If
'Dim pres As PowerPoint.Presentation
Set pres = ppapp.ActivePresentation
' The name sChartName must have been previously assigned to the chart using
' the control in the floating toolbar (left-click on the Think-Cell chart to see this)
' The final argument indicates whether the data range is transposed or not.
Call tcaddin.UpdateChart(pres, sChartName, Rng, False)
End Sub
Sub CopyToTC_ChartNo1()
Dim Rng As Range, sRange As String, sChartName As String
'Insert values:
sRange = "C21:F25"
sChartName = "ChartNo1"
Set Rng = ActiveSheet.Range(sRange)
Call UpdateThinkCellChart(Rng, sChartName)
End Sub
I have a worksheet where there is a chart on the first sheet, showing some data from a named range.
The named range looks like this:
=OFFSET(chart_data!$B$2,0,0,COUNTA(chart_data!$B:$B)-1)
where chart_data is a different sheet.
I also have a VBA script that is supposed to set colors of the chart same as background colors of corresponding cells. The script follows:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim cht As ChartObject
Dim i As Integer
Dim vntValues As Variant
Dim s As String
Dim myseries As Series
Dim nRange As Range
For Each cht In ActiveSheet.ChartObjects
For Each myseries In cht.Chart.SeriesCollection
If myseries.ChartType <> xlPie Then GoTo SkipNotPie
s = Split(myseries.Formula, ",")(2)
vntValues = myseries.Values
For i = 1 To UBound(vntValues)
If Range(s).Cells(i).Interior.Color <> 16777215 Then
myseries.Points(i).Interior.Color = Range(s).Cells(i).Interior.Color
End If
Next i
SkipNotPie:
Next myseries
Next cht
End Sub
My problem is that when I try to evaluate Range(s), where s = "report!values_list", I get
Run-time error '1004':
Method 'Range' of object '_Worksheet' failed
How can I solve this?
Try to do it on different Office. It works for me, some of Offices blocked the dynamic range. Try to make it on different PC with different type of MS Office and make them some simply task with dynamic range. If it will work, you just copy your code there and it will work even in your sheet.
You can get the range corresponding to a name like this:
ThisWorkbook.Names ("somename").RefersToRange
I have the following code that works
Sub TestMe()
Dim crt As ChartObject
Dim shp_Shape As Shape
Dim chartX As Chart
For Each crt In ActiveSheet.ChartObjects
Set chartX = crt.Chart
For Each shp_Shape In chartX.Shapes
If shp_Shape.Type = msoTextBox Then
shp_Shape.Select
MsgBox (Selection.Formula)
End If
Next
Next
End Sub
What I want to do though is simplify the code so I don't have to select the shp_Shape object.
Something like msgbox(shp_Shape.Formula)
I want to be able to read this formula without actually having to select anything.
That way I can get the property even if the sheet is hidden or the chart/sheet is protected.
Any ideas?
The msoTextBox Shape doesn't have a .Formula property. What you need is TextFrame2.TextRange.Text
Try this
Sub TestMe()
Dim crt As ChartObject
Dim shp_Shape As Shape
Dim chartX As Chart
For Each crt In ActiveSheet.ChartObjects
Set chartX = crt.Chart
For Each shp_Shape In chartX.Shapes
If shp_Shape.Type = msoTextBox Then
MsgBox shp_Shape.TextFrame2.TextRange.Text
End If
Next
Next
End Sub
SCREENSHOT
FOLLOWUP FROM COMMENTS
If your msoTextBox Shape is linked with a formula then you need the below
shp_Shape.DrawingObject.Formula