Strange issue with Index Out Of Range Exception in VB.NET - vb.net

I have a DGV in a VB.NET(2019) project and I copy the cells at specific row index, but am experiencing a strange issue:
TXTItemDetail.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(1).Value
TXTOuterpackQTY.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(2).Value
TXTOuterpackName.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(3).Value
TXTItemCodeSelected.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(4).Value
TXTCGST.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(7).Value
TXTSGST.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(8).Value
TXTIGST.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(9).Value
TSSLHSNCode.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(10).Value
TXTItemCode.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(11).Value
'Error is thrown at the line below!!
TXTRate.Text = DGVItemSearch.Rows(ItemEnteredRow).Cells(5).Value.ToString
Note that on the line on which the error is being generated, the cell index is at 5 while the code has already run through on even higher indexes in the earlier lines of code, going up to cell 11. Yet, an out of range error is generated at this instance.
What I could determine was that I need to place the lines of code in sequence of how the cell numbers appear. For example, if I place cell 5 after 4, this error will not be thrown.
I have used this type of code in many places, but never came across this type of an issue. Could it be some kind of threading issue in VB?
Thank you.

Related

Error HRESULT E_FAIL when iterating through for loop only

I'm seeing the good old "System.Runtime.InteropServices.COMException HResult=0x80004005 Message=Error HRESULT E_FAIL has been returned from a call to a COM component" error when attempting to find an item via a for loop as shown below:
For i = 1 to itemList.Count
oObject = itemList.Item(i)
Next
But not if I hardcode the index, this finds item 1 without issue:
oObject = itemList.Item(1)
Obviously I don't want to do that and need to search through all the objects in my "itemList" to find the one I'm looking for.
I'm being intentionally vague because the software I'm working in is Dassault 3D Experience but am writing macros for it through Visual Studio 2017. I'm not sure where to even start debugging this sort of issue so any suggestions would be appreciated. Thanks.
Edit: adding full code of what I'm trying to do here (find an object, display its name, also select it on screen to double check. I will later add a check to make sure the object found in each loop is really what I'm looking for). All variables have been declared before this section.
selactive = CATIA.ActiveEditor.Selection
selactive.Clear()
product1Service = CATIA.ActiveEditor.GetService("PLMProductService")
oRootOcc = product1Service.RootOccurrence
cVPMOccurrences = oRootOcc.Occurrences
For i = 1 to cVPMOccurrences.Count
oVPMOccurrence = cVPMOccurrences.Item(i)
selactive.Add(oVPMOccurrence)
MsgBox(oVPMOccurrence.Name)
Next
The line that fails is oVPMOccurrence = cVPMOccurrences.Item(i)
Can you do something like this with a For Each loop?
For each oVPMOccurrence as oRootOcc.Occurrence in cVPMOccurrences.Items
selactive.Add(oVPMOccurrence)
MsgBox(oVPMOccurrence.Name)
Next
Using a For Each means you don't have to worry at all about the index
Not sure what the type of oVPMOccurrence is as you haven't specified
Most indexes in .net are zero base. I don't know what itemList is but I suspect the index of the first item is 0.
For i = 0 to itemList.Count - 1
oObject = itemList.Item(i)
Next
Not sure why you want to overwrite the value of oObject on every iteration.

Excel VBA Match if value is null

I have a piece of code within a larger script that simply allocates a value to "i" based on a match. The idea being I want it to give the match value if the value entered is found, or 0 if not. If it's 0, I can then exit sub with a message to the user. However, any time the match finds a null value, it just kills the sub, instead of it being handled as part of the iferror I've introduced. I've tried various manners of checking (using iif(iserror) for example) but none seem to work.
Code causing the issue is below:
i = Application.WorksheetFunction.IfError(Application.WorksheetFunction.Match(username, EL.Range("A:A"), 0), 0)
i is dim as an integer
Username is dim as a string, and comes from an inputbox
EL is dim as a worksheet, and contains the correct info.
This has absolutely no issues if I introduce any name that exists, it only fails as soon as I input a name that does not work, and I'm sort of stumped as to why. I see no reason for it to fail, but feel like I'm missing something simply and in-my-face.
Use this instead. Using Application instead of WorksheetFunction enables the error to be trapped and tested.
i = Application.IfError(Application.Match(UserName, EL.Range("A:A"), 0), 0)
I would use a slightly different approach to trap an error on Application.Match function:
Dim i As Variant
i = Application.Match(UserName, EL.Range("A:A"), 0)
' if Match wasn't able to found a "match"
If IsError(i) Then i = 0

Vb.net - Datatable receiving index out of range exception even though index exists

Sometimes, my application throws random index out of range exceptions, and I'm a bit lost to what the reason is..
Here's a screenshot:
As you can see the index (thi3) is under the rows count, so I don't see the problem??
Edit: This is where I declare the columns for the datatable (happens on form load)
InternalDataTable.Columns.Add("Domain")
InternalDataTable.Columns.Add("Anchor text")
InternalDataTable.Columns.Add("Status")
InternalDataTable.Columns.Add("E. Links")
InternalDataTable.Columns.Add("Thread #")
InternalDataTable.Columns.Add("Tjek", GetType(Boolean))
DataGridView1.DataSource = InternalDataTable
Edit2: I now received an error again, but now at the line below the highlighted line in the image, so indeed the problem is something with the item(x)
If InternalDataTable.Rows(thi3).Item(2) = "" Then
Edit3: Once again, the error occured, see screenshot here https://i.gyazo.com/a7cc582e4cbf33bea59a8efb9bb36497.png - (cant embed images yet) I know i should post code, but this image gives a view that both columns and rows & items are within index.
The problem in your code is that you may have inserted several rows, but you don't have any Columns
InternalDataTable.Rows(thi3).Item(0) = ""
The .Item(0) can be causing theindex out of range exception.
Also, I recommend you changing the whole if to this one:
if thi3 < InternalDataTable.Rows.Count andalso InternalDataTable.Columns.Count > 2 andalso InternalDataTable.rows(Thi3).Item(0) <> "" then
Attention to change the <= to < since accessing the Rowcount index will also generate the index out of range exception.

Add a column to a VSTO ListObject that has an existing data source?

Does anyone know how to add a column to an existing list object in Excel, one that has already got a data source bound to it from a SQL source?
I just want to add another column with a formula in every cell for that column of data, to match whatever amount of data is showing at the time.
I have the below 2 examples of what I have tried so far, 1. Gives a syntax error only at runtime of Syntax error: Missing operand before '=' operator. 2. Gives an obscure COM exception.
1.
Dim prodDateCol = New DataColumn("Prod Date", GetType(System.Int32),
"=LEFT([Production Code],4)")
ComplaintsListObject.ListColumns.Add(prodDateCol)
2.
Dim objListCol = ProdListObject.ListColumns.Add()
Dim listColRange = objListCol.DataBodyRange
listColRange.Cells(1, 1) = "=LEFT([Production Code],4)"
I know alternatively I could do this using the Excel cells after first checking each time the list object changes in size, but before looking into how to do that in more detail.. I was hoping there was a way to do this using the List Object itself.
Anyone got any examples or suggestions?
Thanks
UPDATE:
I have adjusted this slightly for testing and also looked more at the use of .Expression and it only allows certain functions, so I have changed LEFT to SUBSTRING.
This example still returns a COM exception of Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
Dim prodDateCol As DataColumn = New DataColumn
prodDateCol.ColumnName = "Prod Date"
prodDateCol.DataType = System.Type.GetType("System.Int32")
prodDateCol.Expression = "SUBSTRING([Production Code],1,4)"
ComplaintsListObject.ListColumns.Add(prodDateCol)

How delete a series from an Excel chart using VBA

I'm trying to delete the empty series from a chart in Excel 2003 using VBA. I've seen that others have had this issue in the past and I have tried all methods mentioned in their posts but have been unable to find anything that works consistently.
The chart has 14 series in it and anywhere between 3 or 9 of them can be empty. The empty ones are always between Series 4 - 12.
I've tried a few variations of code but this is primarily it:
Sheets("chart-1").Select
ActiveChart.PlotArea.Select
For i = 12 To 4 Step -1
Dim theSeries As Series
MsgBox (ActiveChart.SeriesCollection(i).Name)
Set theSeries = ActiveChart.SeriesCollection(i)
MsgBox (theSeries.Name)
theSeries.Delete
Next
I can run it successfully once for a chart, but all subsequent cycles fail with a Unable to get the Name property of the Series class error. It fails on the call to .Name.
I been able to get it work by inserting integers directly, but it will only run once for all integers except 1. It run it multiple times for Series(1).
For instance if I simply call: ActiveChart.SeriesCollection(1).Delete, then the series is deleted, but if I then run it with another integer (4, 9, 12) it won't run. It will work again for 1, but only 1. It will also work once with other integers (say 4), but all subsequent calls will fail even if I change the integer to 1 or keep it as 4, or change it to some other number.
The behaviour is really quite strange.
Any ideas would be greatly appreciated. I can't simply call ActiveChart.SeriesCollection(1).Delete repeatedly because the first 3 series are always non-empty.
Thanks.
** Update **
I just ran a test manually executing the following:
Sheets("ch-v2-12mth").Select
ActiveChart.PlotArea.Select
MsgBox (ActiveChart.SeriesCollection(1).Name)
I cycled through the SeriesCollection trying the numbers 1 - 16 (there are only 14 Series in the chart) to see the result.
1 - 3 worked fine
4 - 13 errored with Unable to get the Name property of the Series class
14 worked fine
15 - 16 errored with Method 'SeriesCollection' of object '_Chart' failed <- not surprising given the number of series in the chart.
This type of behaviour makes me think that there is a bug with Excel. Any other ideas?
There are bugs in Excel when you delete all the series from a chart. My workaround is to always leave at least one series (even if it has no data in it) in the chart. That seems to work for me.
Just thought of another thing. When you delete a series, the indexes of all the remaining series get reduced by one, so you can't delete them by looping from 1 to the number of series. What you can do instead is have a do loop that deletes them until the SeriesCollection.Count = 0 (or 1, see my comments earlier). Or a for loop that iterates backwards and always deletes the last series (i.e. SeriesCollection(SeriesCollection.Count).Delete
You cannot remove all series or the chart will remove itself. what I do to work around this is to rename all exisiting series; then enter your code to build new stuff; then run another snippet to remove the series you renamed
'rename existing series
With ActiveChart
DoEvents
For i = .FullSeriesCollection.Count To 1 Step -1
.FullSeriesCollection(i).Name = "remove" & i
Next i
End With
'your code here to build new charts
'last piece of code to remove the earlier series marked for deletion
With ActiveChart
DoEvents
For c = .SeriesCollection.Count To 1 Step -1
If .SeriesCollection(c).Name Like "*Series*" Then .SeriesCollection(c).Delete
Next c
End With
'also, you need to step backwards because each time you remove a series it will re-index
You can simplify your code to this:
Sheets("chart-1").Select
For i = 12 To 4 Step -1
MsgBox "Series " & i & ": """ ActiveChart.SeriesCollection(i).Name & """"
ActiveChart.SeriesCollection(i).Delete
Next
I don't know why the code was not working for you, but simpler is usually better. And you don't need to know the series name to delete a series.