Com type object problems to get properties - vb.net

I have the following code in VB.net :
Dim objWorkspace As Object
Dim nrobjects As Integer
Dim dataretrieved As Integer
objWorkspace = GetObject("", "Workspace.Application")
objWorkspace.Documents.Open("d:\testimage.grf")
nrobjects = objWorkspace.Parent.ActiveDocument.ActiveWindow.Application.ActiveDocument.Page.ContainedObjects.Count
Dim info() As PropertyInfo
For Each Item In objWorkspace.Parent.ActiveDocument.ActiveWindow.Application.ActiveDocument.Page.ContainedObjects
testvar = Item
info = testvar.GetType().GetProperties()
Next
The little script is connected to a button on a form. When the button is pressed, a custom program is opened (Workspace) and a test image is loaded into it. This part works.
Then I try to get the number of objects on the loaded image. This also works, but when I try to get their properties, I get all the time nothing.
I tested in debug mode. When I try to access the in objWorkspace using the watch, I get the value "COM Type", and the content I can access only if I press the "Dynamic" field "Expanding will evaluate all members dynamically".
How can I access the fields dynamically within the code?

Related

Access VBA listing collection items in a class module

Although I'm reasonable experienced VBA developer, I have not had the need to use class modules or collections but thought this may be my opportunity to extend my knowledge.
In an application I have a number of forms which all have the same functionality and I now need to increase that functionality. Towards that, I am trying to reorder a collection in a class module, but get an error 91 - object variable or with block not set. The collection is created when I assign events to controls. The original code I obtained from here (Many thanks mwolfe) VBA - getting name of the label in mousemove event
and has been adapted to Access. The assignments of events works well and all the events work providing I am only doing something with that control such as change a background color, change size or location on the form.
The problem comes when I want to reorder it in the collection - with a view to having an impact on location in the form. However I am unable to access the collection itself in the first place.
The below is my latest attempt and the error occurs in the collcount Get indicated by asterisks (right at the bottom of the code block). I am using Count as a test. Once I understand what I am doing wrong I should be able to manipulate it as required.
mLabelColl returns a correct count before leaving the LabelsToTrack function, but is then not found in any other function.
As you will see from the commented out debug statements, I have tried making mLabelColl Private and Dim in the top declaration, using 'Debug.Print mLabelColl.Count' in the mousedown event and trying to create a different class to store the list of labels.
I feel I am missing something pretty simple but I'm at a loss as to what - can someone please put me out of my misery
Option Compare Database
Option Explicit
'weMouseMove class module:
Private WithEvents mLbl As Access.Label
Public mLabelColl As Collection
'Dim LblList as clLabels
Function LabelsToTrack(ParamArray labels() As Variant)
Set mLabelColl = New Collection 'assign a pointer
Dim i As Integer
For i = LBound(labels) To UBound(labels)
'Set mLabelColl = New Collection events not assigned if set here
Dim LblToTrack As weMouseMove 'needs to be declared here - why?
Set LblToTrack = New weMouseMove 'assign a pointer
Dim lbl As Access.Label
Set lbl = labels(i)
LblToTrack.TrackLabel lbl
mLabelColl.Add LblToTrack 'add to mlabelcoll collection
'Set LblList as New clLabels
'LblList.addLabel lbl
Next i
Debug.Print mLabelColl.Count 'returns correct number
Debug.Print dsform.countcoll '1 - incorrect
End Function
Sub TrackLabel(lbl As Access.Label)
Set mLbl = lbl
End Sub
Private Sub mLbl_MouseDown(Button As Integer, Shift As Integer, x As Single, Y As Single)
Dim tLbl As Access.Label
'Debug.Print LblList.Count 'Compile error - Expected function or variable (Despite Count being an option
'Debug.Print mLabelColl.Count 'error 91
'Debug.Print LblList.CountLbls 'error 91
Debug.Print collCount
End Sub
Property Get collCount() As Integer
*collCount = mLabelColl.Count* 'error 91
End Property
In order to have all the weMouseMove objects reference the same collection in their mLabelColl pointer, a single line can achieve it:
LblToTrack.TrackLabel lbl
mLabelColl.Add LblToTrack
Set LblToTrack.mLabelColl = mLabelColl ' <-- Add this line.
But please be aware that this leads to a circular reference between the collection and its contained objects, a problem that is known to be a source of memory leaks, but this should not be an important issue in this case.

Convert String back to Tab Control Property

Background
I have serialized a tab control's property, selected tab. I Am using two objectlists to store the object preset object that is being serialized.
Dim _allPresetsList As New List(Of PresetObject)
Dim _XmlPresetsList As New List(Of PresetObject)
preset.TabPageProperty = TabControl1.SelectedTab.ToString()
Dim objStreamWriter As New StreamWriter(_XmlLocation)
Dim xml As New XmlSerializer(_allPresetsList.GetType)
xml.Serialize(objStreamWriter, _allPresetsList)
objStreamWriter.Close()
Code used to de-serialize
Dim objStreamReader As New StreamReader(_XmlLocation)
_XmlPresetsList = xml.Deserialize(objStreamReader)
objStreamReader.Close()
However I cannot convert it back, this is how I have done it successfully with other controls.
CheckBox1.Checked = _XmlPresetsList(0).CheckBox1Property.ToString()
This does not work though
TabControl1.SelectedTab = _XmlPresetsList(0).TabPageProperty.ToString()
I am getting this error
Value of type 'String' cannot be converted to
'System.Windows.Forms.TabPage'.
Question
How can I convert the tab control string property from string back?
This is what is probably causing your error:
preset.TabPageProperty = TabControl1.SelectedTab.ToString()
This is just going to save something like "TabPage: {TabPage1}". Since SelectedTab is an object property, it cant be serialized and saving the type name of it wont be much help in determining which was selected. As the error states you cant make a TabPage object from a string. Instead save and restore something simpler like the selected index:
preset.TabPageIndex = TabControl1.SelectedIndex
I am not sure of the internals of the PresetObject, but I would use typed properties - in this case Int32 rather than string. The serializer will convert back and forth for you.
You should also turn on Option Strict.
CheckBox1.Checked = _XmlPresetsList(0).CheckBox1Property.ToString()
Checked is a boolean, yet you are assigning a string value to it. Option Strict on will warn you when you are leaving VB to make this type of conversion.

Script Errors In VB

I am trying to stop those annoying Runtime Errors in VB. I am using a tabcontrol with a webbrowser item. I am trying to supress the errors. It does not return any errors but at runtime, it doesn't work. This is my code
CType(TabControl.SelectedTab.Controls.Item(0), WebBrowser).ScriptErrorsSuppressed = True
What am I doing wrong?
Your browser control may not be Item(0) on the page (it could be in a panel etc), so as an alternative (and safer method) you can use the Controls.Find method to search the selected tab and all child controls in order to find the Browser on that tab.
Something like this:
'assumes you have a control named WebBrowser1 on the first tab page etc
Dim browserControlName As String = String.Format("WebBrowser{0}", TabControl1.SelectedIndex + 1)
Dim browser As WebBrowser = CType(TabControl1.SelectedTab.Controls.Find(browserControlName, True).First, WebBrowser)
browser.ScriptErrorsSuppressed = True

Linq DataContext still retrieve "Deleted" object

I'm working with a grid bound to Linq Data "Object list".
The grid behave in a "disconnected fashion" it means that when I edit or suppress a line the change is not immediately submitted to the database. There is a separate "save" button that is to be clicked after all changes are made to call the DataContext.SubmitChanges method.
The problem is when i delete a line in the grid, the deleteonsubmit method is well called, but when i rebind the grid just after, the line is still here !
I need a behavior like with Datatables where the lines in the Deleted state are not displayed when the datatable is bound to a grid. Is this possible ?
Addendum
There is not a lot of code, because the GridView use it's automatic behavior (AutoGenerateColumns, AutoGenerateEditButton etc)
Here is the code I use to Delete the Object
<DataObjectMethod(DataObjectMethodType.Delete)> _
Public Sub Supprimer(ByVal code As Integer)
Dim ctx = getDataContext()
Dim leGerant = (From g In ctx.Gerant Where g.CODE = code).FirstOrDefault
ctx.Gerant.DeleteOnSubmit(leGerant)
End Sub
Here is the code I use to select objects
<DataObjectMethod(DataObjectMethodType.Select)> _
Public Function Selectionner()
Dim ctx = getDataContext()
Return From g In ctx.Gerant
End Function
#magnus
You didn't understand my problem. I do call SubmitChanges when the save button is clicked, and the changes take effects well. The problem is not here.
The problem is when i delete a line in the grid, the deleteonsubmit method is well called, but when i rebind the grid just after, the line is still here ! Normally the deleted object shouldn't appear as a line in the GridView, even if I have not submit my changes to the database yet.
DeleteOnSubmit does not 'delete' the item. It marks it as to be deleted on the next submit.
You need to add the submit line so it becomes:
Dim ctx = getDataContext()
Dim leGerant = (From g In ctx.Gerant Where g.CODE = code).FirstOrDefault
ctx.Gerant.DeleteOnSubmit(leGerant)
ctx.SubmitChanges()
Edit: Assuming the ctx is the same instance in both your calls you could try
<DataObjectMethod(DataObjectMethodType.Select)> _
Public Function Selectionner()
Dim ctx = getDataContext()
Dim deleted = ctx.ObjectStateManager
.GetObjectStateEntries(System.Data.EntityState.Deleted).OfType<Gerant>();
Return (From g In ctx.Gerant).Except(deleted);
End Function
This is untested so I am unsure if it will work but it seems to compile.

How can I load a 'future' forms controls before I use them? Explained in detail:

I am performing a migration on a vb6 program, to vb.net. The basic knowledge you need to understand this question is that there are two forms that need to talk to each other, frmInput1 and frmInput2. I have the following code (behind frmInput1) that checks if a textbox on frmInput2 has a certain value, seemingly before it has loaded:
If frminput2.lblInputMac.Text <> "(no filename)" Then
Dim calc As CalculationCaster = New CalculationCaster
Call calc.FillMac()
cmdNext.Enabled = False
frminput2.FraInner.Enabled = True
I get the following error on the If line when i run it:
"Object reference not set to an instance of an object."
Which i assume means that the object in frmInput2 has not been loaded yet. How can i load frmInput2 before i show it?
Thanks
Nick
frminput2 is probably the implicit global instance of the type frminput2.
If you define a form type in VB6 called MyForm, the platform automatically creates an implicit global variable of the same name MyForm. Whenever you refer to this variable in code, it automatically loads an instance of the form for you.
It's rather as if you had this code.
Public Function MyForm() As MyForm
Static f As MyForm
If f Is Nothing Then
f = New MyForm
End If
Return f
End Function
dim frm1 as new frmInput1
dim frm2 as new frmInput2
At this point, you should be able to communicate between forms without them being displayed. You should not reference forms without explicitly instantiating them.
Create an instance of the form.
Dim f As New frmInput2
Then you can use any properties, methods, or controls on the form.
If f.lblInputMac.Text <> "(no filename)" Then
...
End If