I'm trying to use a late binding to email from VBA in Access 2010 and Access 2003. 2003 gives me 'Could not complete the operation. Once or more paramet values are not valid.' and 2010 gives me 'Invalid procedure call or argument.' I've done the step through and it fails at .send near the bottom. Am I setting up my binding wrong? I'm trying to do this without using Microsoft Object Library in the References.
Thanks.
'Refers to Outlook's Application object
Dim appOutlook As Object
'Refers to an Outlook email message
Dim appOutlookMsg As Object
'Refers to an Outlook email recipient
Dim appOutlookRec As Object
'Create an Outlook session in the background
Set appOutlook = CreateObject("Outlook.Application")
'Create a new empty email message
Set appOutlookMsg = appOutlook.CreateItem(olMailItem)
'Using the new, empty message...
With appOutlookMsg
strSQL = "SELECT Email FROM Employees WHERE " & sqlVar & " = True"
Set myR = CurrentDb.OpenRecordset(strSQL)
Do While Not myR.EOF
Set appOutlookRec = .Recipients.Add(myR!Email)
appOutlookRec.Type = olTo
myR.MoveNext
Loop
strSQL = "SELECT Email FROM Employees WHERE '" & user & "' = Username"
Set myR = CurrentDb.OpenRecordset(strSQL)
Set appOutlookRec = .Recipients.Add(myR!Email)
appOutlookRec.Type = olCC
.Subject = wonum
.Body = "Department: " & strDep & vbNewLine & vbNewLine & _
"Issue is at: " & strIssue & vbNewLine & vbNewLine & _
"Priority is: " & strPriority & vbNewLine & vbNewLine & _
"Complete by: " & strDate & vbNewLine & vbNewLine & _
"Description: " & strDesc
.Send
End With
Without a reference, VBA will not know about Outlook constants such as olTo and olCC. With late binding (no reference), you must supply the values for constants rather than the names of the constants.
However, since you didn't report a compile error about those constants, that suggests your code module does not include Option Explicit in its Declarations section. Trying to troubleshoot VBA code without Option Explicit is a waste of time.
Add Option Explicit, then choose Debug->Compile from the VB Editor's main menu and fix anything the compiler complains about. Resume you troubleshooting afterward.
There is an article here on sending email via Outlook using early and late binding. In the "Late Bound Conversion Checklist" at the end, the last suggestion is
Add optional arguments that have a default value
I cannot vouch for that advice because when I need to send email messages from Access I use CDO, not Outlook. Still, it sounds like it might be worth a try.
Related
I have this database and it was working perfect, but today it started hating me. I started getting a Compile error: Can't find project or library. I looked around and found that when using the front end on a different computer, under VBA and references, it was missing a reference for Microsoft Word 15.0 Object Library.
My computer I have the Microsoft Word 16.0 Object Library checked. How can I get this to work on other computers with 15.0 and 16.0?
Here is the code
Private Sub cmd_LocateFile_Click()
On Error GoTo Error_Handler
Dim sFile As String
Dim sFolder As String
Dim ID As Long
Dim sTarget As String
sFile = FSBrowse("", msoFileDialogFilePicker, "All Files (*.*),*.*")
If sFile <> "" Then
sFolder = ("\\aiowima23fp1\Ecological Sciences and Engineering\Cultural Resources\New - Cultural Resources Request Database") & "\" & sAttachmentFolderName & "\"
If FolderExist(sFolder) = False Then MkDir (sFolder)
ID = RequestID_FK ' Set current record id.
sTarget = sFolder & CStr(ID) & "-" & GetFileName(sFile)
If CopyFile(sFile, sFolder & GetFileName(sTarget)) = True Then
Me!FullFileName.Value = sTarget
Else
End If
End If
Error_Handler_Exit:
On Error Resume Next
Exit Sub
Error_Handler:
MsgBox "The following error has occured" & vbCrLf & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Source: " & sModName & "\cmd_LocateFile_Click" & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl <> 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occured!"
Resume Error_Handler_Exit
End Sub
Adding references to Word during development has the advantage to be able to use strongly typed word objects and thus being able to take advantage of IntelliSense. But these references are, as you have experienced, sensible to versioning. Therefore, I suggest you remove the reference to Word once development is achieved. You will also have to replace all Word-related types by Object, i.e. use late binding. This makes the application more robust with respect to versioning.
You can get an existing Word instance which is already open or open a new one with this code snippet, without any references to Word DLLs.
Public Function GetWordApplication() As Object
'Gets an active Word application or opens a new Word instance.
'Raises Error No. 8 if word cannot be opened.
On Error Resume Next
'Find existing instance of Word
Set GetWordApplication = GetObject(, "Word.Application")
If Err.Number <> 0 Then 'Not found, create new instance.
Set GetWordApplication = CreateObject("Word.Application")
End If
'Following code is optional. You can instead test for Nothing at the call site
On Error Goto 0
If GetWordApplication Is Nothing Then
Err.Raise 8, "YourApp.GetWordApplication", "Word could not be opened."
End If
End Function
I am currently working on an access 2013 database. On one of the forms I have a button that collects information, then puts it into an outlook 2013 email and sends it. the code itself works, but sometimes (i can't predict when) I get an error that reads "run-time error '48', Error loading DLL". Once this happens i have to restart the computer in order to get the button working again. I have only been working with VBA for a few weeks and have not had any luck finding out a way to fix this.
-the computers this program (it is a split database) is on have both office 2010 and 2013 on them . i don't know if this is causing the issue, but i don't know enough about what happens when they are on the pc at the same time to rule it out.
-this issue happens on both .accde and .accdb versions of the program
here is what the debugger shows when the error happens
'below is the code for the button that sends the email
Public Sub Command239_Click()
Dim oApp As Outlook.Application
Dim oMail As MailItem
Dim db As Database
'there is code a bunch of code between here that does not
'relate to sending the email
'accessing outlook
Set oApp = CreateObject("Outlook.application")
Set oMail = oApp.CreateItem(olMailItem) ' <<<<<<<<<<< this line is highlighted in yellow >>>>>>>>>>>>>>
'this is for the body of the email.
'things in quotes are text
'& between variables text and newlines
'type the variable to write its value
'vbCrLF goes to the next line
oMail.Body = "Incident Log: " & clsORopen & ", " & Lgst & ", " & Tme & vbCrLf & Division & ": " & Location & ", " & secLocation & vbCrLf & "Circuit/Apparatus: " & Circuit & vbCrLf & "Caused by: " & cause & ", " & rtcause & vbCrLf & vbCrLf & Disturbance & vbCrLf & vbCrLf & "Person Notified: " & Notified & vbCrLf & "Returned to Normal: " & Returned & vbCrLf & "User: " & getusername & " Date: " & Format(Now, "MMM,d,yyyy")
'the subject
oMail.Subject = Division & " - " & Tyype & ", " & Circuit
'sending to these people
oMail.To = emaillist
oMail.Send
Set oMail = Nothing
Set oApp = Nothing
Seems like an issue on 64-bit Windows with 32-bit Office. One suggested solution:
http://support.mccpilotlog.net/support/solutions/articles/9864-windows-pc-run-time-error-48-error-loading-dll
More info here:
https://www.experts-exchange.com/questions/29012275/MS-Access-Run-time-error-48-Error-Loading-dll-after-upgrading-from-2013-64-bit-to-2016.html
I have the following code in an MS Access Form object.
Private Sub UpdatePMText(sLang As String)
'Used to pass both Mandate and Language Info to called Sub that will execute the queries
Dim iMandate As Integer
'Check if there is text in the box.
If Me.Controls("txtInput_PM_" & sLang & "_DRAFT") = Null Or Me.Controls("txtInput_PM_" & sLang & "_DRAFT") = "" Then
MsgBox ("There is no text in the " & sLang & " DRAFT Field." & vbNewLine & "The operation will not be executed.")
Exit Sub
End If
iMandate = Me.txtMandateID
Call modUpdateText.macro_PMText(iMandate, sLang)
End Sub
If I refer to the Controls directly and simply type out the names of the forms, for example txtInput_PM_EN_DRAFT then the code works as intended.
The error message I get is that Access can't find the "Field" I'm referring to when I am on the first IF statement line. I have tried changing the .Controls to .Fields but that didn't work either.
I do not want to repeat the same code for every language I need to run. How do I reference control names dynamically in MS Access? What am I missing?
I think you need to add some basic troubleshooting. The answer is probably simpler than you think. It's likely you're just trying to lookup a textbox with mispelled name or it's failing on the Null comparison (as suggested by #HansUp)
I would try modifying your basic sub and testing it with this subroutine. As long as your code is in your current form and you're not referencing a subform your method will work.
Private Sub UpdatePMText(sLang As String)
Const ERR_MISSING_CONTROL As Long = 2465
On Error GoTo Err_UpdatePMText
Dim sTextBox As String
sTextBox = "txtInput_PM_" & sLang & "_DRAFT"
'Check if there is text in the box.
If Nz(Me.Controls(sTextBox).Value, "") = "" Then
MsgBox ("There is no text in the " & sLang & " DRAFT Field." & vbNewLine & "The operation will not be executed.")
Exit Sub
End If
Exit Sub
Err_UpdatePMText:
If Err.Number = ERR_MISSING_CONTROL Then
MsgBox "Error: No Such Textbox: " & sTextBox
Else
MsgBox "Error Looking Up Textbox: """ & sTextBox & """" & vbCrLf & Err.Description
End If
End Sub
I am making a application which will verify a login to a MySQL Server, which is being done with an ADODB.Connection, then open up another HTA if no errors are given. I am trying to achieve this using nothing but HTA, VBScript and hard work … Without going into too much detail, I would like to catch an error message which will come up if the user puts in the wrong username/password.
Normally, if you do put in the wrong password or username, it comes up with a HTML Error message, which doesn't look very user friendly. That's what this code is trying to catch and make more friendly. Code segment below:
Sub MainLogin_click
dim strError
Uname = usertext.Value
Pword = passtext.Value
cstring = "DRIVER={MySQL ODBC 5.2w Driver};SERVER=Localhost;UID=" & Uname _
& ";PWD=" & Pword & ";DATABASE=maindb;"
conn = CreateObject("ADODB.Connection")
On Error Resume Next
conn.Open cstring
Call MakeDSN
If Err.Number <> 0 Then
strError = "LongBow Error" & VbCrLf & " Error Number: " & Err.Number _
& VbCrLf & " Error Source: " & Err.Source _
& VbCrLf & " Error Description: " & Err.Description
MsgBox(strError)
Err.Clear
Else
Set objShell = CreateObject("WScript.Shell")
objShell.Run("bin\LongBowAgent.hta")
Window.close
conn.Close
End If
On Error GoTo 0
End Sub
Basically when I run this code, and my HTA as a whole, either
Nothing happens, no activity when the 'login' button is pressed.
or
I get a nice error box (even with the right username/password) saying
Error 424, VBScript runtime error, object Required.
Honestly - I've been at this for 2 days now and tried many things. None have really worked, but then Google Searching can only do so much.
Any Help, and any advise would be great. I do not mind trying something completely different here, so long as it stays within HTA & VBScript.
The scope of your OERN is to large - it does not only hide errors of the .Open, but also problems in MakeDSN and in the error handling code.
Ironically, the first culprit is not covered by the OERN:
conn = CreateObject("ADODB.Connection")
is wrong, because you assign an object. Try
Set conn = CreateObject("ADODB.Connection")
I have linked the sql server tables to ms access so that I can use ms access as the front end.I was able to access the tables from access, until I run into an error ODBC call failed when I tried to open one of the tables. There was no problem with the other tables. Actually I have changed a column name in sql server after creating a link. Is this the problem? I am really worried about this as I was about to use access as a front-end for my future purposes.
When you link to a remote table, Access stores metadata about that table. When you later change the table structure, the metadata doesn't get updated to capture the change.
Delete the link. Then recreate the link. That way the metadata will be consistent with the current version of the table.
Yes changing the column name after linking the table is most likely causing your failure. Is it is now trying to pull data from a column that no longer exists. You will need to relink the table. You can programatically link tables in access. We do that in may of our access applications and drive the tables that need to be linked from a local access table.
Public Sub LinkODBCTables()
Dim objRS As DAO.Recordset
Dim objTblDef As DAO.TableDef
Dim strTableName As String
Dim strAliasName As String
Dim strDSN As String
Dim lngTblCount As Long
Set objRS = CurrentDb.OpenRecordset( _
" select TableName," & _
" AliasName," & _
" DSN," & _
" DatabaseName," & _
" Development_DSN," & _
" UniqueIndexCol" & _
" from tblODBCLinkedTables " & _
" order by TableName", dbOpenSnapshot)
While Not objRS.EOF
' Check to see if we already have this linked tableDef
' We don't care if it is not actually in there
strTableName = objRS.Fields("TableName")
If Not IsNull(objRS.Fields("AliasName")) Then
strAliasName = objRS.Fields("AliasName")
Else
strAliasName = strTableName
End If
If DEV_MODE Then
strDSN = objRS.Fields("Development_DSN")
Else
strDSN = objRS.Fields("DSN")
End If
On Error Resume Next
CurrentDb.TableDefs.Delete strAliasName
If Err.Number <> 0 And _
Err.Number <> 3265 Then ' item not found in collection
Dim objError As Error
MsgBox "Unable to delete table " & strAliasName
MsgBox Err.Description
For Each objError In DBEngine.Errors
MsgBox objError.Description
Next
End If
On Error GoTo 0
Set objTblDef = CurrentDb.CreateTableDef(strAliasName)
objTblDef.Connect = g_strSQLServerConn & _
"DSN=" & strDSN & _
";DATABASE=" & objRS.Fields("DatabaseName") & _
";UID=" & g_strSQLServerUid & _
";PWD=" & g_strSQLServerPwd
objTblDef.SourceTableName = strTableName
On Error Resume Next
CurrentDb.TableDefs.Append objTblDef
If Err.Number <> 0 Then
Dim objErr As DAO.Error
For Each objErr In DBEngine.Errors
MsgBox objErr.Description
Next
End If
On Error GoTo 0
' Attempt to create a uniqe index of the link for updates
' if specified
If Not IsNull(objRS.Fields("UniqueIndexCol")) Then
' Execute DDL to create the new index
CurrentDb.Execute " Create Unique Index uk_" & strAliasName & _
" on " & strAliasName & "(" & objRS.Fields("UniqueIndexCol") & ")"
End If
objRS.MoveNext
Wend
objRS.Close
End Sub
We are using a single SQLServer login for our access applications so the g_strSQLServerUID and g_strSQLServerPwd are globals that contain that info. You may need to tweek that for your own needs or integrated security. We are setting up two DSNs one for production and the other for development. The DEV_MODE global controls wich set of DSNs are linked. You can call this code from a startup macro or startup form. It will deleted the old link and create a new link so you always have the most up to date schema.