VBA: Interact with Access from within Outlook
I am trying to create some custom buttons in Outlook that interact with a table contained within an Access database. So far I have my buttons working in Outlook, running code that instantiates a custom data access class which in turn handles opening and closing the connection to the database. So far as I can tell, this much works.
However from this class I cannot even perform a simple select query. Can anyone help me understand why the code below might not work? I always end out with a recordset that has no rows but if I run the same sql using the Access query designer it works fine.
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If rs.RecordCount > 0 Then
GetJobID = rs(1).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
vba ms-access outlook
add a comment |
I am trying to create some custom buttons in Outlook that interact with a table contained within an Access database. So far I have my buttons working in Outlook, running code that instantiates a custom data access class which in turn handles opening and closing the connection to the database. So far as I can tell, this much works.
However from this class I cannot even perform a simple select query. Can anyone help me understand why the code below might not work? I always end out with a recordset that has no rows but if I run the same sql using the Access query designer it works fine.
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If rs.RecordCount > 0 Then
GetJobID = rs(1).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
vba ms-access outlook
2
IsEmailID
a string? I wouldn't useReplace
on the parameter - just use an actual parameterized query...
– Comintern
Nov 12 '18 at 2:54
The email ID is stored within Access as a string. Setting a break point aton error resume next
and calling?sql
in the immediate window yields an SQL string that when executed in the Access query designer returns the correct result.I realise parameterised queries would be better however I do not like them cluttering up the the global namespace and don't want to bother with creating and deleting them all the time. I find simply writing out the SQL string and replacing placeholder text to be easy to read and maintain. Neither security nor efficiency are important here.
– Sangster
Nov 12 '18 at 3:28
Cluttering the global namespace? I'm not sure I know what you mean by that. The parameter can be local. Comment out theOn Error Resume Next
and see if you're getting an error.
– Comintern
Nov 12 '18 at 3:30
No errors are occurring with that line commented out. I just get a recordset with no rows in it. My experience with parameterised queries is that they're saved with the database, I did not know they could be local. If they require more lines of code than my approach I'd avoid them anyway because I cannot fold code away in VBA, and I find it hard to read when there's too much in the file.
– Sangster
Nov 12 '18 at 3:35
The problem seems to be withrs.RecordCount
, which always returns-1
. If I replaceif rs.RecordCount > 0
withif Not rs.EOF
then there are indeed rows returned and I can access the correct data by it's index (which should have been 0 and not 1). So the code works but thers.RecordCount
does not, even if I users.MoveLast
followed byrs.MoveFirst
. Can anyone explain why this is?
– Sangster
Nov 12 '18 at 4:07
add a comment |
I am trying to create some custom buttons in Outlook that interact with a table contained within an Access database. So far I have my buttons working in Outlook, running code that instantiates a custom data access class which in turn handles opening and closing the connection to the database. So far as I can tell, this much works.
However from this class I cannot even perform a simple select query. Can anyone help me understand why the code below might not work? I always end out with a recordset that has no rows but if I run the same sql using the Access query designer it works fine.
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If rs.RecordCount > 0 Then
GetJobID = rs(1).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
vba ms-access outlook
I am trying to create some custom buttons in Outlook that interact with a table contained within an Access database. So far I have my buttons working in Outlook, running code that instantiates a custom data access class which in turn handles opening and closing the connection to the database. So far as I can tell, this much works.
However from this class I cannot even perform a simple select query. Can anyone help me understand why the code below might not work? I always end out with a recordset that has no rows but if I run the same sql using the Access query designer it works fine.
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If rs.RecordCount > 0 Then
GetJobID = rs(1).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
vba ms-access outlook
vba ms-access outlook
edited Nov 12 '18 at 6:36
Cindy Meister
14.2k102134
14.2k102134
asked Nov 12 '18 at 2:21
Sangster
31
31
2
IsEmailID
a string? I wouldn't useReplace
on the parameter - just use an actual parameterized query...
– Comintern
Nov 12 '18 at 2:54
The email ID is stored within Access as a string. Setting a break point aton error resume next
and calling?sql
in the immediate window yields an SQL string that when executed in the Access query designer returns the correct result.I realise parameterised queries would be better however I do not like them cluttering up the the global namespace and don't want to bother with creating and deleting them all the time. I find simply writing out the SQL string and replacing placeholder text to be easy to read and maintain. Neither security nor efficiency are important here.
– Sangster
Nov 12 '18 at 3:28
Cluttering the global namespace? I'm not sure I know what you mean by that. The parameter can be local. Comment out theOn Error Resume Next
and see if you're getting an error.
– Comintern
Nov 12 '18 at 3:30
No errors are occurring with that line commented out. I just get a recordset with no rows in it. My experience with parameterised queries is that they're saved with the database, I did not know they could be local. If they require more lines of code than my approach I'd avoid them anyway because I cannot fold code away in VBA, and I find it hard to read when there's too much in the file.
– Sangster
Nov 12 '18 at 3:35
The problem seems to be withrs.RecordCount
, which always returns-1
. If I replaceif rs.RecordCount > 0
withif Not rs.EOF
then there are indeed rows returned and I can access the correct data by it's index (which should have been 0 and not 1). So the code works but thers.RecordCount
does not, even if I users.MoveLast
followed byrs.MoveFirst
. Can anyone explain why this is?
– Sangster
Nov 12 '18 at 4:07
add a comment |
2
IsEmailID
a string? I wouldn't useReplace
on the parameter - just use an actual parameterized query...
– Comintern
Nov 12 '18 at 2:54
The email ID is stored within Access as a string. Setting a break point aton error resume next
and calling?sql
in the immediate window yields an SQL string that when executed in the Access query designer returns the correct result.I realise parameterised queries would be better however I do not like them cluttering up the the global namespace and don't want to bother with creating and deleting them all the time. I find simply writing out the SQL string and replacing placeholder text to be easy to read and maintain. Neither security nor efficiency are important here.
– Sangster
Nov 12 '18 at 3:28
Cluttering the global namespace? I'm not sure I know what you mean by that. The parameter can be local. Comment out theOn Error Resume Next
and see if you're getting an error.
– Comintern
Nov 12 '18 at 3:30
No errors are occurring with that line commented out. I just get a recordset with no rows in it. My experience with parameterised queries is that they're saved with the database, I did not know they could be local. If they require more lines of code than my approach I'd avoid them anyway because I cannot fold code away in VBA, and I find it hard to read when there's too much in the file.
– Sangster
Nov 12 '18 at 3:35
The problem seems to be withrs.RecordCount
, which always returns-1
. If I replaceif rs.RecordCount > 0
withif Not rs.EOF
then there are indeed rows returned and I can access the correct data by it's index (which should have been 0 and not 1). So the code works but thers.RecordCount
does not, even if I users.MoveLast
followed byrs.MoveFirst
. Can anyone explain why this is?
– Sangster
Nov 12 '18 at 4:07
2
2
Is
EmailID
a string? I wouldn't use Replace
on the parameter - just use an actual parameterized query...– Comintern
Nov 12 '18 at 2:54
Is
EmailID
a string? I wouldn't use Replace
on the parameter - just use an actual parameterized query...– Comintern
Nov 12 '18 at 2:54
The email ID is stored within Access as a string. Setting a break point at
on error resume next
and calling ?sql
in the immediate window yields an SQL string that when executed in the Access query designer returns the correct result.I realise parameterised queries would be better however I do not like them cluttering up the the global namespace and don't want to bother with creating and deleting them all the time. I find simply writing out the SQL string and replacing placeholder text to be easy to read and maintain. Neither security nor efficiency are important here.– Sangster
Nov 12 '18 at 3:28
The email ID is stored within Access as a string. Setting a break point at
on error resume next
and calling ?sql
in the immediate window yields an SQL string that when executed in the Access query designer returns the correct result.I realise parameterised queries would be better however I do not like them cluttering up the the global namespace and don't want to bother with creating and deleting them all the time. I find simply writing out the SQL string and replacing placeholder text to be easy to read and maintain. Neither security nor efficiency are important here.– Sangster
Nov 12 '18 at 3:28
Cluttering the global namespace? I'm not sure I know what you mean by that. The parameter can be local. Comment out the
On Error Resume Next
and see if you're getting an error.– Comintern
Nov 12 '18 at 3:30
Cluttering the global namespace? I'm not sure I know what you mean by that. The parameter can be local. Comment out the
On Error Resume Next
and see if you're getting an error.– Comintern
Nov 12 '18 at 3:30
No errors are occurring with that line commented out. I just get a recordset with no rows in it. My experience with parameterised queries is that they're saved with the database, I did not know they could be local. If they require more lines of code than my approach I'd avoid them anyway because I cannot fold code away in VBA, and I find it hard to read when there's too much in the file.
– Sangster
Nov 12 '18 at 3:35
No errors are occurring with that line commented out. I just get a recordset with no rows in it. My experience with parameterised queries is that they're saved with the database, I did not know they could be local. If they require more lines of code than my approach I'd avoid them anyway because I cannot fold code away in VBA, and I find it hard to read when there's too much in the file.
– Sangster
Nov 12 '18 at 3:35
The problem seems to be with
rs.RecordCount
, which always returns -1
. If I replace if rs.RecordCount > 0
with if Not rs.EOF
then there are indeed rows returned and I can access the correct data by it's index (which should have been 0 and not 1). So the code works but the rs.RecordCount
does not, even if I use rs.MoveLast
followed by rs.MoveFirst
. Can anyone explain why this is?– Sangster
Nov 12 '18 at 4:07
The problem seems to be with
rs.RecordCount
, which always returns -1
. If I replace if rs.RecordCount > 0
with if Not rs.EOF
then there are indeed rows returned and I can access the correct data by it's index (which should have been 0 and not 1). So the code works but the rs.RecordCount
does not, even if I use rs.MoveLast
followed by rs.MoveFirst
. Can anyone explain why this is?– Sangster
Nov 12 '18 at 4:07
add a comment |
1 Answer
1
active
oldest
votes
I see you've tracked down the issue to .RecordCount
returning -1.
This is standard behavior for dynamic cursors, from the docs:
The cursor type of the Recordset object affects whether the number of records can be determined. The RecordCount property will return -1 for a forward-only cursor; the actual count for a static or keyset cursor; and either -1 or the actual count for a dynamic cursor, depending on the data source.
Of course, you can modify your code to use a static cursor, but that will impact performance. Instead, to test if there are records in your recordset, use .EOF
(a method returning a boolean to indicate if the recordset is currently at the end of the file). That will save your code from having to load all records, when only loading the first one is required:
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If Not rs.EOF Then
GetJobID = rs(0).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
Thanks for your feedback. I appreciate the info on why the.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amendrs(1).Value
tors(0).Value
and remove theOn Error Resume Next
line completely I'll mark your response as the answer.
– Sangster
Nov 15 '18 at 0:26
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255243%2fvba-interact-with-access-from-within-outlook%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I see you've tracked down the issue to .RecordCount
returning -1.
This is standard behavior for dynamic cursors, from the docs:
The cursor type of the Recordset object affects whether the number of records can be determined. The RecordCount property will return -1 for a forward-only cursor; the actual count for a static or keyset cursor; and either -1 or the actual count for a dynamic cursor, depending on the data source.
Of course, you can modify your code to use a static cursor, but that will impact performance. Instead, to test if there are records in your recordset, use .EOF
(a method returning a boolean to indicate if the recordset is currently at the end of the file). That will save your code from having to load all records, when only loading the first one is required:
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If Not rs.EOF Then
GetJobID = rs(0).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
Thanks for your feedback. I appreciate the info on why the.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amendrs(1).Value
tors(0).Value
and remove theOn Error Resume Next
line completely I'll mark your response as the answer.
– Sangster
Nov 15 '18 at 0:26
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
add a comment |
I see you've tracked down the issue to .RecordCount
returning -1.
This is standard behavior for dynamic cursors, from the docs:
The cursor type of the Recordset object affects whether the number of records can be determined. The RecordCount property will return -1 for a forward-only cursor; the actual count for a static or keyset cursor; and either -1 or the actual count for a dynamic cursor, depending on the data source.
Of course, you can modify your code to use a static cursor, but that will impact performance. Instead, to test if there are records in your recordset, use .EOF
(a method returning a boolean to indicate if the recordset is currently at the end of the file). That will save your code from having to load all records, when only loading the first one is required:
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If Not rs.EOF Then
GetJobID = rs(0).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
Thanks for your feedback. I appreciate the info on why the.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amendrs(1).Value
tors(0).Value
and remove theOn Error Resume Next
line completely I'll mark your response as the answer.
– Sangster
Nov 15 '18 at 0:26
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
add a comment |
I see you've tracked down the issue to .RecordCount
returning -1.
This is standard behavior for dynamic cursors, from the docs:
The cursor type of the Recordset object affects whether the number of records can be determined. The RecordCount property will return -1 for a forward-only cursor; the actual count for a static or keyset cursor; and either -1 or the actual count for a dynamic cursor, depending on the data source.
Of course, you can modify your code to use a static cursor, but that will impact performance. Instead, to test if there are records in your recordset, use .EOF
(a method returning a boolean to indicate if the recordset is currently at the end of the file). That will save your code from having to load all records, when only loading the first one is required:
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If Not rs.EOF Then
GetJobID = rs(0).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
I see you've tracked down the issue to .RecordCount
returning -1.
This is standard behavior for dynamic cursors, from the docs:
The cursor type of the Recordset object affects whether the number of records can be determined. The RecordCount property will return -1 for a forward-only cursor; the actual count for a static or keyset cursor; and either -1 or the actual count for a dynamic cursor, depending on the data source.
Of course, you can modify your code to use a static cursor, but that will impact performance. Instead, to test if there are records in your recordset, use .EOF
(a method returning a boolean to indicate if the recordset is currently at the end of the file). That will save your code from having to load all records, when only loading the first one is required:
Public Function GetJobID(ByVal xEmailID As String) As Integer
'Returns the JobID associated with a given EmailID from the email link table.
'Returns a fail constant if no link exists.
Dim rs As ADODB.Recordset
Dim sql As String
'Exit if not connected.
'Cast to boolean because VBA doesn't recognise connection state integer as boolean.
If Not CBool(mConn.State) Then
GetJobID = RESULT_FAIL_INTEGER
Exit Function
End If
sql = "SELECT [JobID] FROM [EMAIL_LINK_TABLE] WHERE [EmailID]='xEmailID'"
sql = Replace(sql, "EMAIL_LINK_TABLE", EMAIL_LINK_TABLE)
sql = Replace(sql, "xEmailID", xEmailID)
On Error Resume Next
Set rs = mConn.Execute(sql)
If Not rs.EOF Then
GetJobID = rs(0).Value
Else
GetJobID = RESULT_FAIL_INTEGER
End If
End Function
edited Nov 15 '18 at 7:00
answered Nov 12 '18 at 8:15
Erik von Asmuth
18.7k62038
18.7k62038
Thanks for your feedback. I appreciate the info on why the.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amendrs(1).Value
tors(0).Value
and remove theOn Error Resume Next
line completely I'll mark your response as the answer.
– Sangster
Nov 15 '18 at 0:26
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
add a comment |
Thanks for your feedback. I appreciate the info on why the.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amendrs(1).Value
tors(0).Value
and remove theOn Error Resume Next
line completely I'll mark your response as the answer.
– Sangster
Nov 15 '18 at 0:26
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
Thanks for your feedback. I appreciate the info on why the
.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amend rs(1).Value
to rs(0).Value
and remove the On Error Resume Next
line completely I'll mark your response as the answer.– Sangster
Nov 15 '18 at 0:26
Thanks for your feedback. I appreciate the info on why the
.RecordCount
is -1, though I am not a fan of VBA's approach to error handling as the syntax looks nasty to me and without code folding I prefer to use every opportunity to reduce lines of code. When error handling matters I prefer to test for error numbers then return a fail constant and message. In this case it isn't of concern, so fewer lines wins. If you're happy to amend rs(1).Value
to rs(0).Value
and remove the On Error Resume Next
line completely I'll mark your response as the answer.– Sangster
Nov 15 '18 at 0:26
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
I've edited the answer.
– Erik von Asmuth
Nov 15 '18 at 7:04
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53255243%2fvba-interact-with-access-from-within-outlook%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
Is
EmailID
a string? I wouldn't useReplace
on the parameter - just use an actual parameterized query...– Comintern
Nov 12 '18 at 2:54
The email ID is stored within Access as a string. Setting a break point at
on error resume next
and calling?sql
in the immediate window yields an SQL string that when executed in the Access query designer returns the correct result.I realise parameterised queries would be better however I do not like them cluttering up the the global namespace and don't want to bother with creating and deleting them all the time. I find simply writing out the SQL string and replacing placeholder text to be easy to read and maintain. Neither security nor efficiency are important here.– Sangster
Nov 12 '18 at 3:28
Cluttering the global namespace? I'm not sure I know what you mean by that. The parameter can be local. Comment out the
On Error Resume Next
and see if you're getting an error.– Comintern
Nov 12 '18 at 3:30
No errors are occurring with that line commented out. I just get a recordset with no rows in it. My experience with parameterised queries is that they're saved with the database, I did not know they could be local. If they require more lines of code than my approach I'd avoid them anyway because I cannot fold code away in VBA, and I find it hard to read when there's too much in the file.
– Sangster
Nov 12 '18 at 3:35
The problem seems to be with
rs.RecordCount
, which always returns-1
. If I replaceif rs.RecordCount > 0
withif Not rs.EOF
then there are indeed rows returned and I can access the correct data by it's index (which should have been 0 and not 1). So the code works but thers.RecordCount
does not, even if I users.MoveLast
followed byrs.MoveFirst
. Can anyone explain why this is?– Sangster
Nov 12 '18 at 4:07