Excel VBA refer to chart seriescollection by string name - vba

I have a need to refer to a seriescollection by name. The MSDN object model page for seriescollection states either an index or a name can be used. However when I try to use a string variable I get error 1004 'Invalid parameter':
Dim sSeriesName As String
dim aRootCats() as string
Dim cSeriesCol As SeriesCollection
For x = 0 To UBound(aRootCats)
sSeriesName = aRootCats(x)
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(sSeriesName)
Next x
I've tried the following too:
sSeriesName = CStr(aRootCats(x)) ' just in case, because I filled this array with variant data type earlier
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(sSeriesName)
and
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(aRootCats(x))
and
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection("Product Support")
UPDATE: I'm also experiencing the same error when looping on the seriescollection:
For c = 1 To cChart.ChartGroups(1).SeriesCollection.Count
Set cSeriesCol = cChart.ChartGroups(1).SeriesCollection(c)
Next c
Any ideas?
Many thanks.

Because you are using a ChartGroup not a Chart, you have to use the Item property of the SeriesCollection and you have to pass a variant. Use either:
cChart.ChartGroups(1).SeriesCollection.Item(1)
or:
cChart.ChartGroups(1).SeriesCollection.Item(CVar(sSeriesName))
(or declare the variable as Variant rather than String)

Related

How to SET category/series name in PowerPoint charts?

I'm writing a macro to set categories/series names. New labels are taken from some dictionaries. My first step however was to get those names from each chart. So, in order to get it, I used the code below:
'works fine
'x - any integer
'whole sentence
Application.ActivePresentation.Slides(x).Shapes(x).Chart.ChartGroups(x).CategoryCollection(x).Name
'with variables
Dim objChart As Chart
Dim objChartGroups As ChartGroups
Dim objChartGroup As ChartGroup
Dim objCategoriesColl As CategoryCollection
Dim objCategory As ChartCategory
Dim strCategory As String
Set objChart = ActivePresentation.Slides(x).Shapes(x).Chart
Set objChartGroups = objChart.ChartGroups(x)
Set objChartGroup = objChartGroups.Item(x)
Set objCategoriesColl = objChartGroup.CategoryCollection
Set objCategory = objCategoriesColl(x)
strCategory = objCategory.Name
I checked this property (Name) many times on Microsoft Docs (https://learn.microsoft.com/office/vba/api/powerpoint.chartcategory.name) and it is stated that it is a read/write property. However, when I try to set a new name (in the code below) I receive an error. Is it possible there's a mistake in Docs?
Public Sub EnterNewChartCats( _
lngCategoriesCount As Long, _
objCategoriesColl As CategoryCollection, _
dctDT As Dictionary, _
dctConsts As Dictionary, _
dctRegexes As Dictionary, _
dctUniques As Dictionary)
'lngCategoriesCount - number of categories in a chart
'objCategoriesColl - CategoryCollection object (a list of categories)
'dctDT - a dictionary for names where there's no need to change the label
'dctConsts - a dictionary for non-unique names which appear many times in a presentation
'dctRegexes - a dictionary for names which can be replaced using regular expressions
'dctUniques - a dictionary for names taken from an Excel file (already done)
'booleans for check if a name appears in a dictionary
Dim blnInDT As Boolean
Dim blnInConsts As Boolean
Dim blnInRegexes As Boolean
Dim blnInUniques As Boolean
Dim blnAdd As Boolean
'creating standard variables
Dim objCategory As ChartCategory
Dim i As Long
Dim strCategory As String
Dim strUCaseToCheck As String
For i = 1 To lngCategoriesCount
Set objCategory = objCategoriesColl(i)
strCategory = Trim(objCategory.Name)
'trimmed and upper-case category string to compare with dictionary keys
strUCaseToCheck = UCase(strCategory)
'checking if a category appears in a dictionary
blnInDT = blnInDct(dctDT, strUCaseToCheck)
blnInConsts = blnInDct(dctConsts, strUCaseToCheck)
blnInRegexes = blnAnyValueLikeDctRegex(strUCaseToCheck, dctRegexes)
blnInUniques = blnInDct(dctUniques, strUCaseToCheck)
'checking if a category meets a condition - at least 1 occurrence in any dictionary
blnAdd = blnAnyValue(True, blnInConsts, blnInRegexes, blnInUniques)
'blnAlphabeticChars - a function to check if a category has any letters because
'there's no need to change such labels as '2021' etc.
If Not blnInDT And blnAdd And blnAlphabeticChars(strCategory) Then
'ERROR (objCategory.Name): Can't assign to read-only property
If blnInConsts Then
objCategory.Name = dctConsts(strUCaseToCheck)
ElseIf blnInRegexes Then
objCategory.Name = dctRegexes(strUCaseToCheck)
ElseIf blnInUniques Then
objCategory.Name = dctUniques(strUCaseToCheck)
End If
End If
Next i
Set objCategory = Nothing
End Sub
I've found a workaround (SeriesCollection(x).Values or .XValues) but it's not convenient to use. So, my question is: does exist any way to use Name to set new labels? If no - do you know other workarounds?
EDIT: I've finally managed to change labels via objChart.ChartData.Workbook but it's very slow and, more importantly, a workbook has to be activated (opened) in order to refresh categories/series names. That influenced performance and time of execution greatly so I'm still looking for any other way to do so.
Your first listing is trying to set the name of .CategoryCollection(1). But the help page that you linked to is about .ChartCategory.
In any case, here's how to set the category names:
ActivePresentation.Slides(1).Shapes(1).Chart.Axes(xlCategory).CategoryNames = Array("Test1", "Test2", "Test3", "Test4")

Convert to object in VBA

I have a very strange problem. There is a variable Item of type Variant that contains an array of dictionaries. It comes from another module and I cannot change it. I want to assign it to a dictionary value
Dim MyDict as New Dictionary
set MyDict(key)=Item
This gives an error "Wrong number of arguments or invalid property assignment"
Yet this code works fine:
Dim MyDict as New Dictionary
Dim oTemp as Object
set oTemp=Item
set MyDict(key)=oTemp
Why is it happening and can I do it without using oTemp? There is no CObj function in VBA.
UPD: I have simplified the code above to make it more clear but here is the actual code:
Dim item As Variant
Dim JSONDict As New Dictionary
Dim oTemp As Object
Dim i As Integer
Set JSON = ParseJson(JsonString)
For Each item In JSON.Items
For i = 1 To item.Count
Set oTemp = item(i)
Set JSONDict(item(i)("isbn13")) = oTemp
Next
Next
This code works fine but breaks if I don't use the intermediate oTemp variable. I do not understand why.
Here are screens of Local Window

VBA Run-time error 450 from function returning a collection

Context: I am writing a function which returns words/numbers present in a string which are enclosed by parenthesis.
Example: Calling ExtractParenthesis("This {should} work. But {doesnt}.") should return a collection containing two items, should and doesnt.
Error: The error I receive from the code below is
Run-time error '450': Wrong number of arguments or invalid property
assignment
It doesn't appear on a particular line and I just receive an error message with "OK" and "Help" as options.
Code:
Public Function ExtractParenthesis(strText As String) As Collection
Dim i As Long
Dim RegExp As Object
Dim Matches As Object
Dim Output As New Collection
Set Output = Nothing
Set RegExp = CreateObject("vbscript.regexp")
RegExp.Pattern = "{(.*?)}"
RegExp.Global = True
Set Matches = RegExp.Execute(strText)
For i = 0 To (Matches.count - 1)
Output.Add Matches(i).submatches(0)
Next i
Set ExtractParenthesis = Output
End Function
It works exactly the way you want it for me:
Option Explicit
Public Sub TestMe()
Dim myColl As New Collection
Set myColl = ExtractParenthesis("This {should} work. But {doesnt}.")
Debug.Print myColl(1)
Debug.Print myColl(2)
End Sub
Public Function ExtractParenthesis(strText As String) As Collection
Dim i As Long
Dim RegExp As Object
Dim Matches As Object
Dim Output As New Collection
Set Output = Nothing
Set RegExp = CreateObject("vbscript.regexp")
RegExp.Pattern = "{(.*?)}"
RegExp.Global = True
Set Matches = RegExp.Execute(strText)
For i = 0 To (Matches.Count - 1)
Output.Add Matches(i).submatches(0)
Next i
Set ExtractParenthesis = Output
End Function
I receive "should" and "doesnt" on the immediate window (Ctrl+G). Probably you are not aware that you are returning a collection. It should be used with the Set keyword.
To run it from the immediate window, try like this:
?ExtractParenthesis("This {should} work. But {doesnt}.")(1)
?ExtractParenthesis("This {should} work. But {doesnt}.")(2)
From what I understand of your comment to Vityatas answer you mean you want to run it as a worksheet function - running it directly
The changes I've made to your code will let you use it as a function:
In A1:B1 this will work: {=ExtractParenthesis("This {should} work. But {doesnt}.")}
In A1:A2 use it like this: {=TRANSPOSE(ExtractParenthesis("This {should} work. But {doesnt}."))}
NB: The curly brackets are added by Excel when you enter the formula using Ctrl+Shift+Enter rather than Enter on its own.
The one problem with the code is that you must select the correct number of cells first - if it should return three words, but you've only selected two then you'll only see the first two.
Public Function ExtractParenthesis(strText As String) As Variant
Dim i As Long
Dim RegExp As Object
Dim Matches As Object
Dim Output As Variant
Set Output = Nothing
Set RegExp = CreateObject("vbscript.regexp")
RegExp.Pattern = "{(.*?)}"
RegExp.Global = True
Set Matches = RegExp.Execute(strText)
ReDim Output(1 To Matches.Count)
For i = 1 To (Matches.Count)
Output(i) = Matches(i - 1).submatches(0)
Next i
ExtractParenthesis = Output
End Function

Using a variable as a sheet name

I am getting a RunTime 13 error when trying to use a variable for a sheetname as per below:
Sub inputdata()
Set asheet1 = ThisWorkbook.Worksheets("input").Range("D12")
Set rangeDate = ThisWorkbook.Worksheets("input").Range("inputdate")
Range("F12:M12").Copy
Sheets(asheet1).Select
It is erroring on the line Sheets(asheet1).Select
Any help would be great thanks!
The asheet1 is not a string, you are asigning a range object to it . You should declare asheet1 as string and the change this line to
Dim asheet1 as string
asheet1 = ThisWorkbook.Worksheets("input").Range("D12").Value
That should make it work!
Edit
removed the Set keyword from the string var.
Option Explicit
Sub inputdata()
dim inputSheet as WorkSheet
dim aCellOnInputSheet as Range
dim inputDateCell as Range
dim userSheetName as String
Set inputSheet = ThisWorkbook.Worksheets("input")
Set aCellOnInputSheet = inputSheet.Range("D12")
userSheetName = aCellOnInputSheet.Value
Set inputDateCell = inputSheet.Range("inputdate")
Range("F12:M12").Copy
Sheets(userSheetName).Select
End Sub
EDIT: A couple of points
1) Option Explicit is a must.
2) Define variables and name it appropriately. i.e. define variable which refers to a cell/Range with the name range instead of aSheet - it confuses the reader

How to pass a dynamic array into a VBA object. Compile error: Invalid use of property

I'm trying to pass an array into a custom class for storage and further use within that object. The class object has the following definition:
' Class Name: MBRMCurves
Implements ICurves
Private m_lInterpDates() As Long
Public Property Get InterpDates() As Long()
InterpDates = m_lInterpDates
End Property
Public Property Let InterpDates(lInterpDates() As Long)
m_lInterpDates = lInterpDates
End Property
The module that calls this code looks like this:
Dim objResult As New MBRMCurves
'Store the forward prices
Dim fx_fwd() As Double
'Store the interpolation dates
Dim int_dates() As Long
'initially there are no people
Dim NumberTenors As Integer
NumberTenors = 0
Dim cell As range
' Create ranges of Dates
Dim range As range
Dim range_topcell As range
' TODO Pri1 Create the Curves Obj
With Worksheets("test")
' Populate the dates of the FWD rates.
Set range_topcell = .range("B5")
Debug.Print range_topcell.Value
Set range = .range(range_topcell, range_topcell.End(xlDown))
Debug.Print range.Count
' Add more columns to the FWD array
ReDim fx_fwd(0 To range.Count - 1, 0 To 3)
ReDim int_dates(0 To range.Count - 1)
' Set the counter
NumberTenors = 0
' Populate the dates of the FWD rates into the first column of the dates array.
For Each cell In range
NumberTenors = NumberTenors + 1
int_dates(NumberTenors - 1) = cell.Value
Next cell
' Add interpolation dates to Curves object
objResult.InterpDates int_dates
The last line in the above code is giving me the compile error: Invalid use of property.
I believe that the syntax of me Let function is correct, but I might be missing a more subtly nuanced oversight.
Can anyone see what I'm doing wrong? I'm working with Excel 2003 and VBA 6.5 on Windows XP.
Any suggestions would be greatly appreciated.
Thanks,
Christos
a property is not a method call and you need to set it equal to your array:
objResult.InterpDates = int_dates
There still might be an issue with the array your passing in but this is a first step.