How to run ms access macro from vb.net? - vb.net

I'm trying to run a macro from ms access 2010 from vb.net 2010 ..
The code I used is
Dim oAccess As Access.ApplicationClass
'Start Access and open the database.
oAccess = CreateObject("Access.Application")
oAccess.Visible = True
oAccess.OpenCurrentDatabase("C:\Users\Yuganshu\Desktop\New folder (4)\WindowsApplication1\db.mdb", False)
'Run the macros.
oAccess.Run("Macro1")
'oAccess.Run("DoKbTestWithParameter", "Hello from VB .NET Client")
'Clean-up: Quit Access without saving changes to the database.
oAccess.DoCmd().Quit(Access.AcQuitOption.acQuitSaveNone)
System.Runtime.InteropServices.Marshal.ReleaseComObject(oAccess)
oAccess = Nothing
This is giving me following error:
Unable to cast COM object of type 'Microsoft.Office.Interop.Access.ApplicationClass' to class type 'WindowsApplication1.Access.ApplicationClass'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
I don't know what to do.

You need to add the correct COM Reference. Click the Project Menu bar then-->Add reference. Under Type Libraries look for Microsoft Access 14.0 or whatever version your machine is running. Then add the following statements.
Imports Microsoft.Office.Interop
Dim Access_Object As New Access.Application
Access_Object = CreateObject("Access.Application")
Access_Object.Application.Visible = True

Related

Access 2007 Error 3151 from DAO.OpenRecordSet. How to fix?

Well this is fascinating. I am using MS-Access 2007 to make a from that will allow users to enter data from lab results.
The from utilizes a VBA code call:
DAO.OpenRecordset("{Sql query}" , DB_OPEN_DYNASET, dbSeeChanges)
This call normally works just fine, but I've noticed that when this form is closed and then re-opened, a 3151 ODBC error is generated.
We are using linked tables through Access 2007 for this form, our SQL-Server 2012 version is as follows.
Microsoft SQL Server Management Studio 11.0.2100.60
Microsoft Analysis Services Client Tools 11.0.2100.60
Microsoft Data Access Components (MDAC) 6.1.7601.17514
Microsoft MSXML 3.0 6.0
Microsoft Internet Explorer 8.0.7601.17514
Microsoft .NET Framework 4.0.30319.237
Operating System 6.1.7601
The DAO.OpenRecordset call is utilized in multiple events. Here is the list.
On_Current , _AfterUpdate , Form_Unload
I have found several reported instances of similar errors on Access 2007 with linked tables to SQL-Server, but none seem to have workable solutions for this issue.
As best I can tell, the 3151 doesn't appear to be affecting the form or data in any negative way. I am able to open the form and everything is where it should be as best I can tell. There are about 20 thousand records on this table, so I may be missing something.
Does anyone have any ideas?
9/14 In response to comments I am adding some additional code.
Here is the call on Form_Unload. It contains the failing line.
Private Sub Form_Unload(Cancel As Integer)
Dim ImportID
Dim rst As DAO.Recordset
Dim db As Database
Set db = CurrentDb
Set ImportID = Me.ImportID
#This is the failing line below.
Set rst = db.OpenRecordset("SELECT [dbo_t_inspect].* FROM [dbo_t_inspect] WHERE [dbo_t_inspect].ImportID= " & ImportID & ";", DB_OPEN_DYNASET, dbSeeChanges)
Here is the call from On_Current. This On_Current call is actually made by a sub-form on the main form.
Private Sub Form_Current()
Dim rst As DAO.Recordset
Dim strImportID As String
If IsNull(Me.ImportID) Then
[Forms]![Inspection Receiving]![LabComplete].Visible = False
[Forms]![Inspection Receiving]![LabPending].Visible = True
Else
strImportID = Me.ImportID
Dim db As Database
Set db = CurrentDb
Set rst = db.OpenRecordset("SELECT [dbo_t_health].*, [dbo_t_health].ImportID FROM [dbo_t_health] WHERE ((([dbo_t_health].ImportID)=" & Me.ImportID & "));", DB_OPEN_DYNASET, dbSeeChanges)
I am not sure where DAO is defined in this solution. I cannot find it's declaration in my folder titled Microsoft Office Access Class Objects I am open to suggestions on where that might be located.
The precise error message is as follows
Failed to connect to {ODBC Connection Name} Error 3151.
I can then select the debug option and the debugger will take me to the line that tried and failed to connect the the ODBC Connection I am using.
The Error is highly reproducible. All I have to do is enable VBA Macros on the Security Alert and then open the form in question. I close out the form after it loads. Once I attempt to reopen the form, I get the error described above. The Form opens anyway after I click Ok on the error.

Getting UCase, Trim, Left libary errors in VBA

I have a application that opens excel files. When I run a macro function in my excel that was opened with the application. I'm getting Compile error "Can't find project or library" on the "UCase" "Trim" "Left" just to name a few. In my macro functions, I have multiply cases of using the above functions. I also have references to "Visual Basic For Application", "Microsoft Excel 12.0 Object Library", "OLE Automation", "Microsoft Office 12.0 Library", Microsoft Forms 2.0 Object Library."
If I run excel by itself without the application, there is no errors. Is there any explanation to why this is happening? Libraries mix match? Works fine for the developer and a few but as for the rest of users, they will get these errors.
It's because those methods belong to Excel Application so that you must call them by preceding their name with the Excel object name (and possibly with its relevant member, too) you must have instantiated before
for instance
example 1: late binding
Option Explicit
Sub LateBindingExcel()
Dim xlApp As Object 'declaring your application object as of "Object" type doesn't require any reference to Excel library
' open an Excel session
Set xlApp = CreateObject("Excel.Application")
' call Excel application WorksheetFunction.Trim()
MsgBox xlApp.WorksheetFunction.Trim(" see how spaces get trimmed by this function ")
End Sub
example 2: early binding
Option Explicit
Sub EarlyBindingExcel()
Dim xlApp As Excel.Application 'declaring your application object as of "Excel.Application" type requires adding Excel library reference to your project
' open an Excel session
Set xlApp = CreateObject("Excel.Application")
' call Excel application WorksheetFunction.Trim()
MsgBox xlApp.WorksheetFunction.Trim(" see how spaces get trimmed by this function ")
End Sub
one sensible difference between the two binding "styles" is that the latter allows you exploiting IntelliSense features while the former doesn't
It is likely due to the 'Visual Basic for Applications' in the Tool reference refers to non-presence library. This may happen if the developer use the library in their customized directory instead of default library.
There are 2 means to solve the issue.
Make global replacement of all string related functions (Format, Left, Right, Mid, Trim etc) with prefix VBA. e.g. VBA.Left. This will force the use of functions within standard library.
Move all your excel sheets to another new workbook and then, select the 'Visual Basic for Applications' from Tool reference.

CreateObject function for "Shell.Application" vs "InternetExplorer.Application"

In an answer to this post VBA Macro For Already Open IE Window CreateObject() is used twice, once with "Shell.Application" and another time with "InternetExplorer.Application".
The first time it is used to reference an already open or already active window.
The second time it is used to create a new browser window.
Sub GetIE_LateBinding()
Dim IE As Object
With CreateObject("Shell.Application").Windows
If .Count > 0 Then
' Get IE
Set IE = .Item(0) ' or .Item(.Count - 1)
Else
' Create IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
End If
IE.Navigate "http://support.microsoft.com/kb/q176792/"
Set IE = Nothing
End With
End Sub
I tried the following code. It results in a new IE window each time even when there is already an instance open.
Public Sub Trial()
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
End Sub
I can understand the behavior of "InternetExplorer.Application" - creating new IE application instance each time hence new window. But "Shell.Application" seems to fetch already open shell application instance and hence, we are able to browse the already open IE windows. Seems a bit confusing. What am I missing?
Note: I am guessing something related to class_initialize() for "Shell.Application".
IE and Explorer used to be the same program which is why Shell.Application lists open IE Windows. It is only doing this because they used to both be Explorer windows. You are lucky this meets your needs.
CreateObject is used to create a new object.
GetObject(filename) connects to an open file, and if not open, opens it.
Set xlBook = GetObject("C:\Users\David Candy\Documents\Super.xls")
msgbox xlbook.name
GetObject("","shell.application") connect to an existing object and fails if it's not running.
Set GetExcelApp = GetObject("", "Excel.Application")
Msgbox GetExcelApp
Don't get too hung up on objects. Many objects are just function libraries like Shell.Application. You created a new function library object.
From COM help.
**Component Automation**
Mapping Visual Basic to Automation
Visual Basic provides full support for Automation. The following table lists how Visual Basic statements translate into OLE APIs.
Visual Basic statement OLE APIs
CreateObject (ProgID)
CLSIDFromProgID
CoCreateInstance
QueryInterface to get IDispatch interface.
GetObject (filename, ProgID)
CLSIDFromProgID
CoCreateInstance
QueryInterface for IPersistFile interface.
Load on IPersistFile interface.
QueryInterface to get IDispatch interface.
GetObject (filename)
CreateBindCtx creates the bind context for the subsequent functions.
MkParseDisplayName returns a moniker handle for BindMoniker.
BindMoniker returns a pointer to the IDispatch interface.
Release on moniker handle.
Release on context.
GetObject (ProgID)
CLSIDFromProgID
GetActiveObject on class ID.
QueryInterface to get IDispatch interface.
Dim x As New interface
Find CLSID for interface.
CoCreateInstance
QueryInterface
© Microsoft Corporation. All rights reserved.

WorkSite SDK - Cannot create ActiveX component

I am attempting to learn how to develop applications to interact with the Autonomy WorkSite 8.5 server and have found the WorkSite DB Administrators COM Developers Reference Guide, it has helped me somewhat and I can now see the types of objects that I can interface with however, I am stumbling on showing the members of a group.
My code is as follows. This is for a VB.NET Windows Forms application.
Dim ObjNRDMS As IMANADMIN.NRTDMS
Dim ObjSessions As IMANADMIN.NRTSessions
Dim ObjSession As IMANADMIN.NRTSession
Dim ServerName As String
ServerName = "SERVERNAME"
' Create the NRTDMS object
ObjNRDMS = GetObject("IMANADMIN.NRTDMS")
' Add the Server to the NRTSessions object and
' get a NRTSession object for the server
ObjSessions = ObjNRDMS.Sessions
ObjSessions.Add(ServerName)
ObjSession = ObjSessions.Item(1)
' Login to the Server
ObjSession.TrustedLogin()
Dim ObjDBs As IMANADMIN.NRTDatabases
Dim ObjDB As IMANADMIN.NRTDatabase
Dim ObjGroup As IMANADMIN.NRTGroup
' ObjSession is a previously defined NRTSession object
' Get the first database defined for ObjSession object
ObjDBs = ObjSession.Databases
ObjDB = ObjDBs.Item(1)
ObjGroup = ObjDB.GetGroup("TEST")
txtOutput.AppendText(ObjGroup.Users.ToString)
However, when I debug this code in Visual Studio (2008), I get the error:
Cannot create ActiveX component at the line `ObjNRDMS =
GetObject("IMANADMIN.NRTDMS")
I have run regsvr32 iManAdmin.dll.
Can anyone offer any assistance on this problem?
I've read on page 21 of the DB Admin COM guide that it mentions to execute iManAdmin - REGSERVER from the command prompt, however this will not work for me with Windows reporting that the file does not have a open with program set.
I ended up resolving this issue by using the iManage worksite Interop.iManAdmin.dll

How to securely store Connection String details in VBA

I have an Excel Template that has hardcoded Ms Access MDB path in the VBA code used to connect to the Access tables and save, retrieve data.
I migrated the MS Access Database over to SQL Server with Integrated Authentication for the Excel Template Users.
My question is, What is the Recommend Way / Best Practice for storing the SQL Server DB connection string and retreiving it in Excel 2007 VBA to save and retrieve data?
In the past, I have done the following.
Use a Registry Key setting that has the Connection String. Then in the VBA, write a function that reads the registry key and returns the connection string.
Have a "Settings" hidden sheet within the Excel Template, with named cell for the connection string. Read the connection string in VBA by accessing that named range.
Use a .INI txt file that goes with the Excel template. (This is not ideal and I want to avoid this as it builds a dependency on that external file)
I don't like # 1 because I want to avoid writing to/reading from Registry if possible.
# 2 feels ok, thought I am not sure if there is a better "cleaner" way for doing this.
Any thoughts?
This is what I would do safely store connection string credentials
Download and install Visual Studio Express 2012 for Windows (FREE)
Open it as Administrator and create a New Project. Select Visual C# then Class Library and rename it to HiddenConnectionString
In the Solution Explorer, rename Class1.cs to MyServer.cs
Right click your MyConnection project in the Solution Explorer and select Add Reference
Type activeX in the search box and tick the Microsoft ActiveX Data Objects 6.1 Library
Copy and paste the below code into the MyServer.cs completely replacing whatever is in the file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.IO;
using ADODB;
namespace HiddenConnectionString
{
[InterfaceType(ComInterfaceType.InterfaceIsDual),
Guid("2FCEF713-CD2E-4ACB-A9CE-E57E7F51E72E")]
public interface IMyServer
{
Connection GetConnection();
void Shutdown();
}
[ClassInterface(ClassInterfaceType.None)]
[Guid("57BBEC44-C6E6-4E14-989A-B6DB7CF6FBEB")]
public class MyServer : IMyServer
{
private Connection cn;
private string cnStr = "Provider=SQLOLEDB; Data Source=SERVER\\INSTANCE; Initial Catalog=default_catalog; User ID=your_username; Password=your_password";
public MyServer()
{
}
public Connection GetConnection()
{
cn = new Connection();
cn.ConnectionString = cnStr;
cn.Open();
return cn;
}
public void Shutdown()
{
cn.Close();
}
}
}
Locate the cnStr variable in the code and update your connection string details.
Right click the *HiddenConnectionString* solution in the Solution Explorer and select Properties.
Click the Application tab on the left side, then Assembly Info and tick Make Assembly COM-Visible
Click the *Build* from the menu on the left and tick Register For COM Interop
Note: If you are developing for 64-bit Office then make sure you change the Platform Target on the Build menu to x64! This is mandatory for 64-bit Office COM libraries to avoid any ActiveX related errors.
Right click the HiddenConnectionString in the Solution Explorer and select Build from the menu.
If everything went OK then your HiddenConnectionString.dll and HiddenConnectionString.tlb should be successfully generated. Go to this path now
C:\Users\administrator\Documents\Visual Studio 2012\Projects\HiddenConnectionString\HiddenConnectionString\bin\Debug
and you should see your files.
Now open Excel and go to VBE. Click Tools and select References.
Click the Browse button and navigate to the HiddenConnectionString.tlb.
Also, add references to Microsoft ActiveX Object 6.1 Library - this is so you can use ADODB library.
Now right click anywhere in the Project Explorer window and Insert a new Module
copy and paste the below code to it
Option Explicit
Sub Main()
Dim myCn As MyServer
Set myCn = New MyServer
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.Open "Select * from [TABLE_NAME]", myCn.GetConnection
Range("A1").CopyFromRecordset rs
rs.Close
myCn.Shutdown
Set rs = Nothing
Set myCn = Nothing
Columns.AutoFit
End Sub
Replace the [TABLE_NAME] with an actual table name in your database.
Hit F5 or hit the green play button on the ribbon.
If everything went OK, you should now see the returned Table on your spreadsheet.
my sample:
As you can see. Adding references to your own COM-library and storing the login credentials and other sensitive data inside the compiled .dll protects your data(connection string). It's very difficult to decompile the *.dll file to get any sensible information from it. There are various coding techniques to protect your *.dll even more but I am not going to go into details now. This itself achieves what you asked for.
myCn.GetConnection returns the ADODB.Connection object that was initialized inside the referenced COM library. No Excel user will be presented with the connection string or sensitive data (actually nobody else neither).
You can modify the C# code to accept parameters from VBA i.e. login, password, initial catalog, query to execute etc... if you have users with different privileges on the instance of your SQL Server it wouldn't be a bad idea to allow people to log in.
Note: there is no error handling added in the C# code and VBA. I would strongly recommending working on it if you're planning to use the technique I have described above.
How about storing it under CustomDocumentProperties?
Note: I am not sure, if the workbook (based on a given template) will inherit the property defined using CustomDocumentProperties in the template.