Variable not declared before it is used with DAO - vb.net

I'm using DAO (been asked not to use ADO.NET) to update an Access database. I'm currently thus far, however, VB2008 is telling me that the variable "daoengine" is not declared before it is used. What am I doing wrong in the following code?
Function update_db()
Dim daoengine As DAO.DBEngine
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
dbs = daoengine.OpenDatabase("Project.mdb")
rst = dbs.OpenRecordset("Log", dao.RecordsetTypeEnum.dbOpenDynaset)
End Function

You should have
Dim daoengine As New DAO.DBEngine
instead of
Dim daoengine As DAO.DBEngine

When you say
Dim daoengine As DAO.DBEngine
you're just creating a variable, daoengine, but it doesn't actually point to anything. You need to do this afterwards:
Set daoengine = New DAO.DBEngine
You can also type Dim daoengine As New DAO.DBEngine, but it's better to do it in the two lines above. If you put the New in the Dim line, you create what's called an "auto-instancing" variable which can magically come to life again after you thought you'd disposed of it.
For more details see the Don't Use Auto-Instancing Object Variables here: Declaring Variables (in VBA)

Related

VBA using function return values instead of variables

I've tried searching the internet for a definitive answer to this two-part scenario but couldn't find anything conclusive. I've been writing VBA procedures for sometime now in both Access and Excel and while trying to streamline some code I came across something of a dilemma
The first part is about using functions to return objects. The example below is generally what I've seen on the web for a function to return an ADODB.Recordset (I've simplified the code so no error handling etc.).
Public Function CreateADORecordset(SQL As String, Connection As ADODB.Connection) As ADODB.Recordset
Dim rst As ADODB.Recordset
Set rst = New ADODB.Recordset
Call rst.Open(SQL, Connection)
Set CreateADORecordset = rst
End Function
The first part of the question is, why do I need a variable called rst when I could rewrite the function as this:
Public Function CreateADORecordset(SQL As String, Connection As ADODB.Connection) As ADODB.Recordset
Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, Connection)
End Function
Is there anything fundamentally wrong with the above rewrite of the function? As the function returns an ADO recordset, why declare a variable separately?
I can take this a step further:
Public Function CreateADOConnection(ConnectionString As String) As ADODB.Connection
Set CreateADOConnection = New ADODB.Connection
Call CreateADOConnection.Open(ConnectionString)
End Function
Public Function CreateADORecordset(SQL As String, ConnectionString As String) As ADODB.Recordset
Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, CreateADOConnection(ConnectionString))
End Function
Again, is this a particularly bad thing to do by using function return objects over declaring objects within the procedures via Dim?
In the grand scheme of things, I've been writing VBA code to transfer the contents of a recordset via GetRows into an Excel range. The function declaration line is:
Public Sub TransferRecordsetArray(GetRows As Variant, Destination As Range)
As TransferRecordsetArray works correctly, I've not included the code.
The dilemma I'm in now is in this scenario, I've reached a point where I don't need to declare any variables for the code to run correctly and I'm unsure how much of a good or bad thing this in terms of functions returning objects, scope and variables, etc.
In order to run the code correctly, I only need one of two lines without variables:
Call TransferRecordsetArray(CreateADOConnection(ConnectionString).Execute(SQL).GetRows, Target)
or
Call TransferRecordsetArray(CreateADORecordset(SQL, CreateADOConnection(ConnectionString)).GetRows, Target)
Any advice/recommendations on this way of writing VBA code would be greatly appreciated. I have used the task manager to keep an eye on memory usage on both methods and it doesn't seem to greatly differ and, it appears that VBA destroys the function return objects after a while, despite them not being explicitly destroyed by setting them to Nothing.
Many thanks.
The first part of the question is, why do I need a variable called rst when I could rewrite the function as this
Public Function CreateADORecordset(SQL As String, Connection As ADODB.Connection) As ADODB.Recordset
Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, Connection)
End Function
You don't need a separate variable. Your code is perfectly fine.
I can take this a step further:
Public Function CreateADOConnection(ConnectionString As String) As ADODB.Connection
Set CreateADOConnection = New ADODB.Connection
Call CreateADOConnection.Open(ConnectionString)
End Function
Public Function CreateADORecordset(SQL As String, ConnectionString As String) As ADODB.Recordset
Set CreateADORecordset = New ADODB.Recordset
Call CreateADORecordset.Open(SQL, CreateADOConnection(ConnectionString))
End Function
Yes, absolutely. Nothing wrong with that.
I've reached a point where I don't need to declare any variables for the code to run correctly
Congratulations, keep it up. :)
Further reading: Is there a need to set Objects to Nothing

VB .NET NullReferenceException, "Object reference not set to an instance of an object" when it seemingly is

as the title reads, I am getting a NullReferenceException that says "Object reference not set to an instance of an object". This is a legacy WinForms app that I am working on so keep in mind the structure of the code is not my doing. I am trying to compare a recordset before and after a change is made to it. I am hitting my issue in trying to make a copy of the old recordset.
Here is my code to populate the copy of the old data, which is in a module:
Public Function Prevdata(ByRef table As ADODB.Recordset) As ADODB.Recordset
Dim i As Integer
Dim pData As New ADODB.Recordset
table.MoveFirst()
If Not table.BOF And table.EOF Then
While Not table.EOF
For i = 0 To table.Fields.Count - 1
pData.AddNew()
pData(table.Fields(i)).Value = table.Fields(i).Value
Next
pData.Update()
table.MoveNext()
End While
End If
PrevData = pData
End Function
And here is my code in one of the forms. These are just with my other variable declarations at the top of the file. GetData just simply creates a recordset:
Public pData As ADODB.Recordset = GetData(tableName)
Public pDataC As ADODB.Recordset = PrevData(pData)
I get the error in the module in PrevData anywhere where "table" is referenced. I appreciate any help.

Running VB.Net code in my program, without creating instances, or parameters. Is it possible?

I am currently trying to make a program where you can type a VB.NET script into a richtextbox (strCode) and then execute it. Like as if I executed it in Visual Studio.
My current code look like this:
Dim objCompilerParameters As New CompilerParameters
objCompilerParameters.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.dll")
objCompilerParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")
objCompilerParameters.GenerateInMemory = True
Dim objCompileResults As CompilerResults
Dim Provider As CodeDomProvider = CodeDomProvider.CreateProvider("VisualBasic")
objCompileResults = Provider.CompileAssemblyFromSource(objCompilerParameters, strCode)
' Get a reference to the assembly.
'
Dim objAssembly As System.Reflection.Assembly = objCompileResults.CompiledAssembly
' Create an instance of the DynamicCode class referenced in the source code.
'
Dim objTheClass As Object = objAssembly.CreateInstance("Dynam.DynamicCode")
'----------------------------------------------------------------------------------------------------
' Create a parameter to be passed into the ExecuteCode function in class DynamicCode.
Dim objFunctionParameters(0) As Object
objFunctionParameters(0) = "Parameter 1"
'----------------------------------------------------------------------------------------------------
'Creating Result
Dim objResult As Object = objTheClass.GetType.InvokeMember("ExecuteCode", _
BindingFlags.InvokeMethod, Nothing, objTheClass, objFunctionParameters)
'---------------------
This runs fine .. as long as the namespace in my script is "Dynam", and the public class is "TestClass". Also the Public Function has to be named "ExecuteCode". Just like in the script.
Is there a way to create this, without having to hardcode the function and class names? So I can just call the classes, and functions whatever the user wants to call them.
Thanks in advance. I hope it made a little sense. If not, please let me know.

Setting field 'InputMask' properties programmatically

I have an Access database divided into front and back ends.
I need to modify the value of a property associated to one of the fields in a table programmatically. I do remember achieving something similar years ago, but that was for forms.
It seems that the properties of a table can only be set at design time; any attempt to modify the values using code (myField.Properties("InputMask").Value = "000000") causes an error.
All in all, there are about 40 or 50 tables in a batch of roughly 80 that have a particular type of field that has to be changed, so I'd rather do this using code than manually. Could anyone suggest a method for doing this using VBA, please?
Presently I've looked at dropping and recreating the field using CurrentDb.Execute sqlString, but I'd like to retain the InputMask property if at all possible.
The original database is a 2002/3 format, but I'm editing this in Access 2010.
I got the following code to work. It will change the InputMask of the specified Table and Field....
Option Compare Database
Option Explicit
Sub Test_It()
Dim WGD
WGD = Resize_And_AddInputMask("Table3", "SomeNbr")
End Sub
' Modified version of code found at: http://www.tek-tips.com/viewthread.cfm?qid=1708626
Public Function Resize_And_AddInputMask(ByVal someTableName As String, ByVal someZCField As String)
Dim db As DAO.Database
Dim td As DAO.TableDef
Dim fd As DAO.Field
Dim prp As DAO.Property
Set db = CurrentDb
Set td = db.TableDefs(someTableName)
Set fd = td.Fields(someZCField)
fd.Properties("InputMask") = "000099"
fd.Properties.Refresh
db.TableDefs.Refresh
Set prp = Nothing
Set fd = Nothing
Set td = Nothing
Set db = Nothing
End Function

VBA Groupwise Email

I'm using Excel 2013, Windows 7, Groupwise 12.
The code should be pretty straight forward, but I keep getting an error
"Active X component can't create object"
I've made sure the references are there according to the Groupwise's development documents which is simply their "gwcma1.dll" and I just can't figure out what is going on.
Theory right now is that Groupwise was installed some way that didn't populate the registry information needed for the code to create the object even though it is in the object browser.
Code:
Dim gwAccount As GroupwareTypeLibrary.Account2
Set gwApp = CreateObject("NovellGroupwareSession")
I've used this code for years on older versions of excel and windows and groupwise, and I can't figure out what has changed.
---EDIT---
Here's the beginning part of the code. After this is just standard loops and logic that all works.
Here's the first part of it. After this point, it's just standard loops and and logic.
Sub EmailPDFs()
Dim i, k As Long
Dim PhysicianCount As Long
Dim StartPoint As Long
Dim CurrentNPI As Long
Dim CurrentEmail As String
Dim CurrentFileName As String
Dim CurrentFilePath As String
Dim CurrentDate As String
Dim EmailBody As String
'Declaration for Email
Dim gwMessage As GroupwareTypeLibrary.Message2
Dim gwAccount As GroupwareTypeLibrary.Account2
Dim gwApp As GroupwareTypeLibrary.Application
Set gwApp = CreateObject("NovellGroupwareSession")
Set gwAccount = gwApp.Login()
---EDIT 2---
I tried Application2 and still the same error. I think I was trying the older one and the properties were the same on the object, but Application2 let you do proxy email access which I wasn't worried about.
For creating a new application, I may need a refresh on the syntax but I'm assuming you're suggesting something like:
Dim xlApp as Excel.Application
Set xlApp = New Excel.Application 'Early Binding
Set xlApp = CreateObject(“Excel.Application”) 'Late Binding