Attempting to split and store strings from a listbox and search then search the contents of the text file I have stored them to, hopefully sorting them in different categories,
firstly I am getting an "Object reference not set to an instance of an object." error with this
Dim variable As String = Nothing
If listArray.SelectedIndex > 0 Then
variable = listArray.Items(listArray.SelectedIndex)
End If
Dim part As String() = variable.Split(New Char() {","c})
Dim line As String
For Each line In part
MessageBox.Show(line)
and secondly, would this be the right code to use for searching those separated strings?
For count As Integer = 0 To Logbook.listArray.Items.Count - 1
Dim searchIndex As String = Logbook.listArray.Items(count).ToString
If searchIndex.Contains(indexSearch.Text) Then
Logbook.listArray.SetSelected(0, True)
End If
Next
I'm pretty new to StackOverflow, my apologies if i'm not up to date with the website etiquette.
am getting an "Object reference not set to an instance of an object."
I guess you don't know that the first item is at index 0 and that SelectedIndex returns -1 if there is no item selected. That's why following code throws that exception:
Dim variable As String = Nothing
If listArray.SelectedIndex > 0 Then
variable = listArray.Items(listArray.SelectedIndex)
End If
Dim part As String() = variable.Split(New Char() {","c}) ' <--- variable Nothing if first item selected
Then you just have to use <> -1 or >= 0:
Dim variable As String = Nothing
If listArray.SelectedIndex >= 0 Then
variable = listArray.Items(listArray.SelectedIndex)
End If
According to the second part of the question(always ask only once), you haven't provided enough informations to understand what you want and what doesn't work with your code.
Related
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")
I'm trying to list the results of a LookUpSet only if they are in another string.
Initially I used the following to get an array of strings seperated by a semi-colon.
Join(LookUpSet(...),";")
The next stage was to test if the strings were in the main string. I tried nesting the return value inside an IIF statement;
Join(LookUpSet(...,IIF(InStr(Fields!BigText.Value,Fields!Text.Value) > 0, Fields!Text.Value, Nothing),...),";")
I understand this doesn't work because the big string that I am comparing against is in my first dataset and the other is in my second dataset
Next I tried to use InStr on the results of the LookUpSet;
IIF(InStr(Fields!BigText.Value, LookUpSet()) > 0, LookUpSet(), Nothing)
This won't work either so I've tried to create custom code and am nearly there;
Code.CheckSetInString(Fields!BigText.Value, LookUpSet())
The code is below, when debugging I receive "Object reference not set to an instance of an object", but can't see anything that I've failed to declare.
How should I troubleshoot which object isn't declared?
The custom code is below for reference.
Function CheckSetInString(ByVal str As String, ByVal setofstrings As Object())
If setofstrings Is Nothing OrElse Not setofstrings.length > 0 Then
Return Nothing
End If
Dim returnedstrings AS [String]()
Dim i As Integer = 0
For Each item As String In setofstrings
If InStr(1, str, item, 1) > 0 Then
returnedstrings(i) = item
i += 1
End If
Next
Return returnedstrings
End Function
Any advice is appreciated,
Dan
I am trying to create an if statement using a checklistbox. How can I make an if statement with my checked value in check list box? I tried using the code below just like in combobox:
If CheckedListBox1.CheckedItems = "AHRM" Then
But I got an error:
value of type cannot be converted to string.
CheckedListBox.CheckedItems returns a collection of all checked items. Not a single string.
You could check it's Count property and then take the first if you expect only one:
Dim checked As String = Nothing
Dim checkedItems = CheckedListBox1.CheckedItems
If checkedItems.Count <> 0 Then checked = checkedItems(0).ToString()
If checked = "AHRM" Then ....
If you expect multiple you could use following little LINQ query and Contains or String.Join(if you want to concat them):
Dim checkedItems = From obj In CheckedListBox1.CheckedItems.Cast(Of Object)()
Select checkedItemAsString = obj.ToString()
Dim containsAHRM As Boolean = checkedItems.Contains("AHRM")
Dim allChecked = String.Join(",", checkedItems)
Dim values As [String] = ""
For i As Integer = 0 To CheckBoxList1.Items.Count - 1
If CheckBoxList1.Items(i).Selected Then
values = CheckBoxList1.Items(i).Value
If values = "AHRM" Then
// your code
end if
End If
Next
i got this far ... my data string, "num_str" contains a set of ~10 numbers, each separated by a comma. the last part of the string is a blank entry, so i use '.Trim' to avoid an error
Dim i As Integer
Dim m_data() As String
m_data = num_str.Split(",")
For i = 0 To UBound(m_data)
If m_data(i).Trim.Length > 0 Then
MsgBox(Convert.ToInt32(m_data(i).Trim))
End If
Next i
as you can see from the Msgbox, each of the numbers successfully pass through the loop.
where i am stuck is how to place all of the 'Convert.ToInt32(m_data(i).Trim)' numbers, which are now presumably integers, into an array.
how do i build an array of integers inside the For / Next loop so i can find MAX and MIN and LAST
TIA
You just need to initialize the array with the zero-based indexer. You can deduce it's initial size from the size of the string():
Dim m_data = num_str.Split({","c}, StringSplitOptions.RemoveEmptyEntries)
Dim intArray(m_data.Length) As Int32
For i = 0 To m_data.Length - 1
intArray(i) = Int32.Parse(m_data(i).Trim())
Next i
Note that i've also used the overload of String.Split which removes empty strings.
This way is more concise using the Select LINQ Operator.
Dim arrayOfInts = num_str.
Split({","c},
StringSplitOptions.RemoveEmptyEntries).
Select(Function(v) Int32.Parse(v.Trim()))
Dim minInt = arrayOfInts.Min()
Dim maxint = arrayOfInts.Max()
I am using Visual Studio.net, Visual Basic and I have a question.
If I have a string that has many lines in it, what is the best way to get the contents of a certain line?
E.g If the string is as follows:
Public Property TestProperty1 As String
Get
Return _Name
End Get
Set(value As String)
_Name = value
End Set
End Property
What is the best way to get the contents of line 2 ("Get")?
The simplest is to use ElementAtOrdefault since you don't need to check if the collection has so many items. It would return Nothing then:
Dim lines = text.Split({Environment.NewLine}, StringSplitOptions.None)
Dim secondLine = lines.ElementAtOrDefault(1) ' returns Nothing when there are less than two lines
Note that an index is zero-based, hence i have used ElementAtOrDefault(1) to get the second line.
This is the non-linq approach:
Dim secondLine = If(lines.Length >= 2, lines(1), Nothing) ' returns Nothing when there are less than two lines
That depends on what you mean by "best".
The easiest, but least efficient, is to split the string into lines and get one of them:
Dim second As String = text.Split(Environment.NewLine)(1)
The most efficient would be to locate the line breaks in the string and get the line using Substring, but takes a bit more code:
Dim breakLen As Integer = Environment.Newline.Length;
Dim firstBreak As Integer = text.IndexOf(Environment.Newline);
Dim secondBreak As Integer = text.IndexOf(Environment.NewLine, firstBreak + breakLen)
Dim second As String = text.Substring(firstBreak + breakLen, secondBreak - firstBreak - breakLen)
To get any line, and not just the second, you need even more code to loop through the lines until you get to the right one.