Access macro to read emails from MS Outlook - ms-access

I have a macro in Access that connects to the running instance of MS Outlook.
The macro had been working, until last week when I started receiving the error: Activex component can't create object whenever I ran the macro.
Here's a piece of the code and where it's currently failing:
Function GatherDailyStats()
Dim oOlAp As Object, oOlns As Object, oOlInb As Object
Dim oOlItm As Object
'Dim FileName As
Dim i, j As Integer
Dim strDir1 As String
Dim strDir2 As String
'~~> Get Outlook instance
Set oOlAp = GetObject(, "Outlook.Application") '--**THIS IS WHERE IT FAILS**
Set oOlns = oOlAp.GetNamespace("MAPI")
Set oOlInb = oOlns.GetDefaultFolder(olFolderInbox).Folders.Item("Daily Stats")
'~~> Check if there are any actual unread emails
If oOlInb.Items.Restrict("[UnRead] = True").Count = 0 Then
MsgBox "NO Unread Email In Daily Stats folder"
Exit Function
End If
Nothing has changed in the code since I created it and tested it thoroughly.
Update: I just tested the same application on a different computer and it worked perfectly there.

Here is a KB article about the ROT and how Office applications by design don't register until their start up sequence has finished. You may be seeing an issue that was always there, just never ran into it before for whatever reason.
Lifted from this discussion you may want to try adding a fall back to make sure that the application is running:
On Error Resume Next
Set objOutlook = GetObject(, "Outlook.Application")
If Err.Number = 429 Then
Set objOutlook = CreateObject("Outlook.Application")
End If
From that same discussion it is important to note that Outlook 2010 apparently has some kind of issue with registering in the ROT when not started in Administrator mode.
Apparently there is a work around that someone has posted which includes:
...if you assign the Everyone group full rights to the Office install
directory it will then work.
Not sure that is the greatest idea but it is a known issue with Office 2010.
EDIT: here is one last resource.

GetObject will throw an error, if the application isn't running. You need to check for this:
On Error Resume Next
Set oOlAp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then Set oOlAp = New Outlook.Application
Alternatively, you could just create a new instance of your object:
Set oOlAp = CreateObject("Outlook.Application")
Using CreateObject to create a new instance will, of course, increase resource load in cases when an object of same type was already initialized. Saying it differently, to increase performance and lower use of system resources, better use the first suggested solution.

Firstly, always use CreateObject when creating an instance of the Outlook.Application object - Outlook is a singleton, so only one instance will ever be running for the logged in user.
Secondly, what are the versions of Outlook and Access? Are they all the same version>? If not, are they both 32 or 64 bit?

Related

DoCmd.SendObject Method and Error 3211 Access 2013 VBA

I'm having difficulty finding any information about this particular issue. The only information I've found is that this seems to have been a bug in Access 2010 (I'm hoping that they fixed it for 2013 and that I'm simply ignorant of the solution).
I'm using the DoCmd.SendObject Method in access vba to send a report via email in outlook upon the on_click event for a command button. My code seems to work just fine and the email goes out as intended. The issue is that after running the code I'm unable to make any changes to the table that serves as the record source to the report, even though the report is closed. I get error 3211 "cannot lock record source because it is in use....."
I've removed the DoCmd.SendObject code and have no issues making changes to the tables and I don't receive the error. I am assuming that the method itself establishes some sort of link or connection between Outlook and the table.
So, my question is how to fix this. Is there VBA code that can terminate the link/connection between outlook and a table after using the DoCmd.SendObject Method?
To all,
I ended up using a different method for sending emails, which ultimately resolved all my issues and turned out to be more flexible than the SendObject method. Below is the code I used, hopefully you will find it useful:
(Just a note for others who find the code useful: I elsewhere used code to create a pdf file, which is why the pdf file name is a variable)
'Create a new e-mail and attach previously created pdf
Dim strLocation As String
Dim OutApp As Object
Dim OutMail As Object
Dim EmailTo As Variant
Set OutApp = CreateObject("Outlook.Application")
Set OutMail = OutApp.CreateItem(0)
EmailTo = DLookup("Email", "tblTempProcessing")
With OutMail
.To = EmailTo
.CC = ""
.BCC = ""
.Subject = "Subject Text"
.Body = "Body Text"
.Attachments.Add ("C:\Folder\SubFolder\" & Variable & ".PDF")
.Send
End With
On Error GoTo 0

Microsoft VBScript compilation error: Expected end of statement

I am trying to insert some records into MS Access Table with the help of below VB Script. But when am trying to execute it, it's throwing Compilation error: Expected end of statement. Could someone please help me figure out where am I going wrong.
Private Sub Form_Click()
Dim dbs As DAO.Database
Dim DbFullNAme As String
DbFullName = "D:\G\Diamond\FINAL MS-Access\MS-Access project.accdb"
Set dbs = OpenDatabase(DbFullName)
dbs.Execute "INSERT INTO [2014_Status] ( Prompt, Project_Name, STATUS,Release_Name )SELECT RoadMap.SPRF_CC, RoadMap.SPRF_Name, RoadMap.Project_Phase,RoadMap.Release_Name FROM RoadMap WHERE (((Exists (select 1 FROM [2014_Status] where RoadMap.SPRF_CC = [2014_Status].[Prompt]))=False));"
dbs.Close
End Sub
VBScript (as opposed to VBA or other dialects) does not support typed Dims. So
Dim dbs As DAO.Database
Dim DbFullNAme As String
need to be
Dim dbs
Dim DbFullNAme
VBscript has no native OpenDatabase() function. You need to use ADO to connect to your Access 'database'. First create a connection
Set dbs = CreateObject("ADODB.Connection")
Then determine the connection string and
dbs.Open cs
The rest of your code should work.
Update wrt comment:
The error message:
D:\G\Diamond\FINAL MS-Access\query1.vbs(2, 9) Microsoft VBScript compilation error: Expected end of statement
prooves that the OT tried to write a VBScript (the addition of the misleading vba/access tags is (C) Pankaj Jaju).
So lets break down the real reason why this code doesn't work.
You copied and pasted Visual Basic for Applications(VBA) into a .VBS(Visual Basic Script) file and expected it to work, I assume.
The problem with this is that VBA and VBScript are slightly different languages. Review the info section for both tags on stackoverflow when you get the opportunity.
For now lets just patch your code and maintain your DAO object so you don't have to reconstruct your Database usage with ADODB.
ExecuteInsert
Sub ExecuteInsert()
Dim dbs, DbFullName, acc
Set acc = createobject("Access.Application")
DbFullName = "D:\G\Diamond\FINAL MS-Access\MS-Access project.accdb"
Set dbs = acc.DBEngine.OpenDatabase(DbFullName, False, False)
dbs.Execute "INSERT INTO [2014_Status] ( Prompt, Project_Name, STATUS,Release_Name )SELECT RoadMap.SPRF_CC, RoadMap.SPRF_Name, RoadMap.Project_Phase,RoadMap.Release_Name FROM RoadMap WHERE (((Exists (select 1 FROM [2014_Status] where RoadMap.SPRF_CC = [2014_Status].[Prompt]))=False));"
dbs.Close
msgbox "done"
End Sub
Changes made.
Blocked your dim'd variables and removed As *** statements for vbscript compatibility
Set an access object so you could maintain the remainder of your code.
Added the acc.DBEngine. before OpenDatabase with additional parameters.
Renamed your Sub from Form_Click to ExecuteInsert, then placed ExecuteInsert at the top of the code so that the vbscript activates the sub. If you just place a sub in a vbscript file, it will not necessarily run, you have to activate it directly.
This code is tested and functions. Best of luck to you.
Adding to Ekkehard.Horner
http://www.csidata.com/custserv/onlinehelp/vbsdocs/vbs6.htm
VBScript has only one data type called a Variant. A Variant is a
special kind of data type that can contain different kinds of
information, depending on how it's used. Because Variant is the only
data type in VBScript, it's also the data type returned by all
functions in VBScript.

VB6- Open Access DB or one of it's forms with ADO object

My application written with visual basic 6 and it has an Access database. I want to add a VB form and open the database in this form to make db edits the DB in that. I have this code for oppenning:
Dim db As DAO.Database
Set db = DBEngine.workspaces(0).opendatabase("c:\ss.mdb")
I have a form inside that database. This form makes the data insertion process faster. I want to open this access form with my application.
How i should do this??
Note: I have this code that uses Microsoft access 14 object library.
Dim appaccess As Access.Application, dbstr As String
On Error Resume Next
Set appaccess = New Access.Application
Set appaccess = CreateObject("Access.Application")
dbstr = "c:\ss.mdb"
'Or dbstr="c:\my documents\yourfile.mdb
'put the correct path here.
appaccess.OpenCurrentDatabase dbstr
appaccess.DoCmd.OpenForm "aa", acLayout
appaccess.Visible = True
But when i run this code the form appears and after a while it gets disapear. besides using access object library creates some access version conflicts. So, Although it is not necessary but i prefer to do that with ADO object. Anyway, i' looking for e method to solve my problem.
Thank you for your help
ADO provides methods to interact with various data sources. Although you can use it for Access db files, it doesn't provide methods to utilize Access forms.
With your current approach, you use CreateObject to set the object variable appaccess to a new Access application instance, then open your form within that instance. However, when the variable goes out of scope, the Access instance closes and the form disappears.
You might revise your VB6 code to keep the variable in scope until you're finished with the Access instance. Unfortunately, I don't know how to fit that change into the rest of your code, and I've never used VB6.
Alternatively, you could use the Shell Function to start the Access instance, then use GetObject() to set your object variable to that instance.
With the Shell() approach, you would need to supply the full path to MSACCESS.EXE. You can find the folder where it's located by reading the registry. Here's a VBScript sample which does that, and I'm hoping you can adapt it easily for VB6.
Option Explicit
Dim MSAccFolder
Dim RegKey
Dim WSHShell
RegKey = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\" _
& "CurrentVersion\App Paths\MSACCESS.EXE\Path"
Set WSHShell = WScript.CreateObject("WScript.Shell")
MSAccFolder= WSHShell.RegRead(RegKey)
WScript.Echo "MS Access Folder: " & MSAccFolder
Set WSHShell = Nothing
One thing is that you're using DAO in that first chunk of code rather than ADO.
Maybe that doesn't matter though because there's no reference to db in your second chunk of code.
So the first chunk of code looks to be unecessary.
I don't know why you have 2 set statements for appaccess, you don't need the second one.
Also I'd suggest that you comment out the 'on error resume next' statement so you can see which line is causing the error while debugging.
If you're going to use VB, you should abandon the Access Automation stuff and create your form in VB. Then use ADO to open and work with the Access file. This is much more efficient than using VB to automatically open an Access form.

Trouble Adding Web Service to VS2010 for SSRS CLR Stored Proc

I am attempting to reference the SSRS web service and it is not going as expected, please let me know what I'm doing wrong.
In VS 2010:
Step 1) Add Service Reference
Address=http://myserver/reportserver/reportservice2005.asmx?wsdl (server does not have a named instance)
name = ReportingServices2005_BETA
Step 2) Then in my clr_sproc I write:
_
Public Shared Sub TestMonkey2(RptName As SqlString,
Params As SqlString,
FileName As SqlString)
Dim rs As New ReportingServices2005_BETA()
Result:
I get an error in the error list "Error 1 Type expected"
I can write these lines without error...
Dim rs As New ReportingServices2005_BETA.Job
Dim rs As New ReportingServices2005_BETA.Role
Dim rs As New ReportingServices2005_BETA.Task
but those to not match all of the tutorials on the web?
I know I'm missing something simple...
thanks
Found my problem, I was adding a Service Reference instead of a Web Reference, problem solved.
But in the long run, I found you cannot use ReportingServices2005 in a CLR due to security restrictions. I'm back to the drawing board.
dang.

ADO Connection to Access leaves .ldb file behind with Screen.MousePointer = vbHourglass

I'm writing an MS Outlook (2003) macro which uses an ADO Connection to an Access DB (2003). I am opening a connection, getting some records into a Recordset, which I use to populate a grid (but not bind to). I then close the Recordset and Connection and set both to Nothing.
The process creates an instance of MSACCESS.EXE, and a .ldb file for the Access DB, both of which remain after I have closed the Connection, Recordset, Macro and Outlook itself. One or both of these remnants is preventing opening the Access DB until the MSACCESS.EXE process is manually killed and the .ldb file is deleted.
Similar posts say "close the connection" but that is not solving the problem.
Here's the VBA code:
Screen.MousePointer = vbHourglass
Set db = New ADODB.Connection 'Declared at module level
Set rs = New ADODB.Recordset 'Declared at module level
Dim sSQL As String
sSQL = "SELECT Customers.ContactFirstName As Name, Customers.ContactLastName As Surname, Customers.EmailName AS Email, Customers.Address, Customers.Area, Customers.Town FROM qryCustomersWithEmail ORDER BY Customers.ContactLastName ASC"
db.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & "C:\My Documents\Tables.mdb;Persist Security Info=False"
rs.Open sSQL, db, adOpenStatic, adLockReadOnly
If rs.RecordCount > 0 Then
'actions performed on recordset removed
End If
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
Screen.MousePointer = vbDefault
It's on Vista.
I'm doing this to provide my customer with an easy way to send bulk emails to everyone in his Access database. I tried by accessing Outlook from Access but the security "feature" of Outlook, which pops up a warning message for every email created, scuppered this approach.
UPDATE.
I removed PopulateFlexGrid and the problem still occurred just for opening and closing the recordset. What I previously omitted from this sample, as I considered it irrelevant is that I wrapped the code with Screen.MousePointer = vbHourglass at the start and Screen.MousePointer = vbDefault at the end. I removed this and the problem no longer occurs. Stepping through I see MSACCESS.EXE start up in TM when I call Screen.MousePointer = vbHourglass.
I also tried a version where I used DAO instead of ADO, no other difference, and it works without creating .ldb or starting up an MSACCESS.exe. This works with the Screen.Mousepointer code in there.
Can anybody explain this?
The answer to this is that the reference to
Screen.MousePointer
which i'd omitted as irrelevant, is actually a member of Access. Hence when i call it MSACCESS starts up.
I should have used
Me.MousePointer = fmMousePointerHourGlass
So it's my fault for copying some code from Access VBA to Outlook VBA and expecting it to work the same. Apologies to all of you who spent time looking at this!
What is the code of the function PopulateFlexGrid? Is it possible this is not closing the recordset passed to it?
Try removing this line and instead just looping through the code without doing anything and seeing if it still leaves the LDB. If it still leaves the LDB then the problem is not with the PopulateFlexGrid function
I agree with david saying there is something unclear here. Such a code cannot create an instance of Access or an .ldb file. This code could even run without Access being installed on the machine.
Could you open your recordset with a clientSide cursor? Using a serverSide cursor might cause the access file to be modified (not sure ...) in a way or another. To make sure that your next command does not interfeer in a way or another with access, you could even copy your record locally (to an xml file), close both records and connection, reopen the recordset with the xml file as datasource, and then populate your flexgrid.
By the way, and though it has nothing to do with your problem, it is usually preferable to split the object declaration to:
dim myObect as ADODB....
set myObject = New ADODB....