I'm working on an app that writes to excel. The following piece f code is working properly ( it fills the requested cell) but generating a run time exception that I can't get rid of.
For i = 1 To 1000 Step 1
If Not (cPart.Range("A" & i).Value = Nothing) Then
If (cPart.Range("L" & i).Value = Nothing) Then
cPart.Range("L" & i).Interior.ColorIndex = 3
End If
i = i + 1
End If
Next
the exception is: COMException was unhandled :Exception from HRESULT: 0x800A01A8
any help?
That HRESULT means Object Required. So it seems like one or more of the objects you try to operate on don't exist but as the code is written at the moment, it's difficult to be sure which it is. An immediate concern though is that you're comparing values to Nothing, in VB.Net you're supposed to use Is Nothing to check for that. Also, you've already set up the For loop to go from 1 to 1000, with a step of 1 (which you don't need to include since it's the default) but you're then doing i = i + 1 which looks like a mistake?
So fixing that and splitting it up into it's parts it might give you a better idea to what's not working:
For i = 1 To 1000
Dim aRange As Object = cPart.Range("A" & i)
If aRange IsNot Nothing AndAlso aRange.Value IsNot Nothing Then
Dim lRange As Object = cPart.Range("L" & i)
If lRange IsNot Nothing AndAlso lRange.Value Is Nothing Then
Dim interior As Object = lRange.Interior
If interior IsNot Nothing Then
interior.ColorIndex = 3
End If
End If
End If
Next
I've declared the new objects as Object which might need to be changed to the correct data types (depending on your project settings).
Hopefully you should now be able to run through the code without error and you should also be able to step through the code and find that one of the new objects (aRange, lRange and interior) is Nothing at some point when it shouldn't be which will show you why it threw that error before.
Another advantage to splitting up the code like this is that you'll now be able to dispose of the Excel objects properly so that the Excel instance can shut down cleanly. See this Q&A for info: Excel.Range object not disposing so not Closing the Excel process
Related
Sub initialize()
For boxNum = 1 To 10
vaultValuesForm.Controls("h" & boxNum).Value = ""
vaultValuesForm.Controls("d" & boxNum).Value = ""
Next boxNum
vaultValuesForm.Show
End Sub
Sub button_Populate_Click()
Dim array_h(9) As String, array_d(9) As String
For boxNum = 0 To 9
array_h(boxNum) = vaultValuesForm.Controls("h" & (boxNum + 1)).Value
array_d(boxNum) = vaultValuesForm.Controls("d" & (boxNum + 1)).Value
Next boxNum
Call populateTable(array_h(), array_d())
End Sub
Sub populateTable(array_0() As String, array_1() As String)
For x = 1 To 4
ThisDocument.Bookmarks("bd" & x).Range.Text = array_0(0)
Next x
End Sub
I have tested the functionality of this code at various points, and it works flawlessly right up until this line:
ThisDocument.Bookmarks("bd" & x).Range.Text = array_0(0)
Specifically, until it reaches = array_0(0). In its current state, reaching this point in the Sub results in "Run-time error '5941': The requested member of the collection does not exist." Same deal when I originally tried using = array_0(x) (which is ultimately what I'm trying to accomplish). However, if replaced with something direct such as = "AA", it works. How do I phrase this bit properly to set the bookmark values to those within the array?
Note: In case you're wondering, the arrays are being referenced and passed properly; I tested this by changing the loop to comments and using MsgBox() with various array elements.
The answer from comments. The issue I wasn't aware of was that the bookmarks were being deleted after running the module, so it wouldn't work again unless the bookmarks were created again.
Are you sure the bookmarks bd1...bd4 are still there in the document? Because a bookmark's range.text deletes the bookmark, so if you want to be able to repeat the bookmark text assignments you have to recreate the bookmarks after assigning the texts. FWIW I ran your code and it was fine when bd1..bd2 etc. existed but threw 5941 the next time. (This is quite a common problem!) – slightly snarky Sep 3 at 8:37
So, for the official answer to my question, the way I had done it initially is how; it just couldn't be repeated.
I am trying to ensure that I am addressing entities in ModelSpace, but I get an exception that gives no hint at what the problem is because it's a COM object I guess. Does anyone know what I might be doing wrong? If I take out that line (and the zoom extents line) the remaining code works just fine, so I know my document object is being set correctly.
Dim acDWG As AutoCAD.AcadDocument
' open the drawing
acDWG = acApp.Documents.Open(dgvr.Cells("FullName").Value.ToString)
' ensure the drawing has the modelspace tab activated (doesnt work)
acDWG.ActiveSpace = AutoCAD.AcActiveSpace.acModelSpace
' zoom to extents (sometimes works, sometimes not) '
acApp.ZoomExtents()
' build a selectionset of all blocks named 'Solid1' and then delete them all
Dim ss As AutoCAD.AcadSelectionSet = acDWG.SelectionSets.Add("DELETE")
Dim gpCode(1) As Int16
Dim dataValue(1) As Object
gpCode(0) = 0 : dataValue(0) = "Insert"
gpCode(1) = 2 : dataValue(1) = "Solid1"
ss.Select(AutoCAD.AcSelect.acSelectionSetAll,,, gpCode, dataValue)
ss.Erase()
ss.Delete()
ss = Nothing
Update: I discovered why I am getting the error. The code is correct, but the problem is that the drawing has not completed opening yet. If I put a "wait for 5 seconds" line of code directly after the Open line, it works just fine. So it seems my question is how to open the drawing and have VB.Net wait for a signal from the COM object that it is "ready to continue"? (not sure how to word it)
Use a combination of Do...Loop and a Try...Catch block to "wait" like this:
Dim acDWG As AutoCAD.AcadDocument
acDWG = acApp.Documents.Open(dgvr.Cells("FullName").Value.ToString)
Dim bOpen As Boolean = False
Do Until bOpen = True
Try
acDWG.ActiveSpace = AutoCAD.AcActiveSpace.acModelSpace
bOpen = True
Catch ex As Exception
' ignore the error and try again until it is open
End Try
Loop
I'm having a really strange issue with the DataGridView control in a VS2008 / .NET 3.5 winforms project. I have a simple form with a grid. In the form constructor I call a function to bind the grind to a DataTable, and then loop through the rows setting the background colour of the last cell to LightGrey and the cell itself to read-only if the column value is true. After the form finishes loading the code didn't work i.e. the cells are not set to LightGrey and are not read-only (even though when I step through the code I can see the properties being set). I then call the function again from a button, but this time the colour is changed to LightGrey and the cell is made read-only i.e. the code works.
CODE:
Dim dgr As DataGridViewRow
For i_DsRow As Integer = 0 To ds.Tables(0).Rows.Count - 1
dr = ds.Tables(0).Rows(i_DsRow)
For i_row As Integer = 0 To DgSearch.Rows.Count - 1
dgr = DgSearch.Rows(i_row)
If dr("DsColoumn1").ToString.ToUpper = dgr.Cells("DgColoumn1").Value.ToString.ToUpper Then
If Val(dr("Coloumn2").ToString) = 3 Then
dgr.Cells("SomeColomname").Value = dr("SomeColoumName2").ToString
If dgr.Cells("SomeColomname3").Value.ToString <> "" Then dgr.Cells("SomeColomname3").Value &= ", "
dgr.Cells("SomeColomname3").Value &= dr("SomeColoumName2").ToString
SetCellColor(dgr.Cells("SomeColomname"), dgr.Cells("SomeColomname3"))
End If
Exit For
End If
Next
Next
Private Sub SetCellColor(ByVal resultCell As DataGridViewCell, ByVal ColorCell As DataGridViewCell)
If resultCell.Value.ToString().ToUpper = "A".ToUpper Or resultCell.Value.ToString().ToUpper = "B".ToUpper Then
ColorCell.Style.BackColor = Color.FromName("Red")
ElseIf resultCell.Value.ToString().ToUpper = "C".ToUpper Or resultCell.Value.ToString().ToUpper = "D".ToUpper Then
ColorCell.Style.BackColor = Color.FromName("MediumSeaGreen")
Else
ColorCell.Style.BackColor = Color.FromName("Yellow")
End If
End Sub
Thanks for adding the code. I would suggest putting all formatting in the CellFormatting event of the DataGridView.
There are a couple of gotchas that you have to watch, which looking at your code shouldn't be a problem but to be aware of:
This runs for each cell in the grid. Therefore Database lookups are a really bad idea.
You do best to get values where possible from the eventargs parameter of the method
If you need a code sample, I believe there are some good c# examples (possibly vb to) this one for example.
So. I looked around Stackoverflow before posting this question. I found other Questions, but none of them answered my question.
This is my code:
Sub getData()
ListBox1.Items.Clear()
Dim rowindex As String
Dim found As Boolean = False
Dim actie As String
For Each row As DataGridViewRow In DataGridView1.Rows
If row.Cells.Item("Column1").Value.ToString.Contains("2014-0" & Date.Today.Month.ToString) Then
rowindex = row.Index.ToString()
found = True
actie = row.Cells("Column2").Value.ToString()
ListBox1.Items.Add(actie)
End If
Next
If Not found Then
MsgBox("Item not found")
End If
End Sub
What this does is calls data from a DataGrid. The issue I am having is on 'ListBox1.items.add(actie)'. If I use a Message Box it works fine until I get to the last one and then it also throws the error. (That'll likely be why it throws the error straight away for the ListBox as it adds them all 'at the same time'). I've tried an 'ELSE' but with the else it just says no data found. I thought a Do Until might have worked but it did not.
Error I am getting is: Object Reference Not Set to an Instance of an Object.
I assume this is going to be something really basic and I'm going to hit myself when I turns out to be extremely basic.
Dim Permission As String
Dim chk As String = "p"
Permission = (ds.Tables("privilege").Rows(0).Item(0)).ToString
MessageBox.Show(Permission)
Dim PermissionArray() As String = Split(Permission, ":")
For i As Integer = 0 To 36
If PermissionArray(i) = 1 Then
Try
Dim chkBox As CheckBox = CType(Me.Controls(chk & i), CheckBox)
chkBox.Checked = True
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
End If
Next
This code gives me the following error in catch, i have googled but nothing is working
This is the error: System.NullReferenceException – Object reference not set to an instance of an object.
As you noted chkBox.Checked throws NullReferenceException, you should evaluate the following line for the error:
Dim chkBox As CheckBox = CType(Me.Controls(chk & i), CheckBox)
' This may throw NullReferenceException if there is no (chk & i) control available
chkBox.Checked = True
Although it turned out not to be your problem this time,
Permission = (ds.Tables("privilege").Rows(0).Item(0)).ToString
is a prime candidate for a system.NullReferenceException. This statement relies on everything in your data set being fully and correctly populated or errors can occur.
If the table "privilege" does not exist in the dataset, or the table is empty, or the first column of the first row is null, you can get exceptions and it will be very hard to tell what is wrong. You should test those conditions before relying on the assignment, so you don't get exceptions.
I'll bet you are missing one or more controls "p0" ... "p35" since blindly build the ID, ask the form for the control of that ID but never check if it was actually found. Try including the value of 'i' in your message when the exception is caught. That'll be the first control you're misisng.
And then, be sure to check the return values of functions you call before you USE those return values.