VBA: Interact with Access from within Outlook











up vote
0
down vote

favorite












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









share|improve this question




















  • 2




    Is EmailID a string? I wouldn't use Replace on the parameter - just use an actual parameterized query...
    – Comintern
    Nov 12 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 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 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 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 at 4:07















up vote
0
down vote

favorite












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









share|improve this question




















  • 2




    Is EmailID a string? I wouldn't use Replace on the parameter - just use an actual parameterized query...
    – Comintern
    Nov 12 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 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 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 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 at 4:07













up vote
0
down vote

favorite









up vote
0
down vote

favorite











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









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 12 at 6:36









Cindy Meister

13.7k102034




13.7k102034










asked Nov 12 at 2:21









Sangster

31




31








  • 2




    Is EmailID a string? I wouldn't use Replace on the parameter - just use an actual parameterized query...
    – Comintern
    Nov 12 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 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 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 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 at 4:07














  • 2




    Is EmailID a string? I wouldn't use Replace on the parameter - just use an actual parameterized query...
    – Comintern
    Nov 12 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 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 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 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 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 at 2:54




Is EmailID a string? I wouldn't use Replace on the parameter - just use an actual parameterized query...
– Comintern
Nov 12 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 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 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 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 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 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 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 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 at 4:07












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










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





share|improve this answer























  • 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 at 0:26










  • I've edited the answer.
    – Erik von Asmuth
    Nov 15 at 7:04











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',
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
});


}
});














draft saved

draft discarded


















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








up vote
1
down vote



accepted










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





share|improve this answer























  • 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 at 0:26










  • I've edited the answer.
    – Erik von Asmuth
    Nov 15 at 7:04















up vote
1
down vote



accepted










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





share|improve this answer























  • 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 at 0:26










  • I've edited the answer.
    – Erik von Asmuth
    Nov 15 at 7:04













up vote
1
down vote



accepted







up vote
1
down vote



accepted






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





share|improve this answer














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






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 at 7:00

























answered Nov 12 at 8:15









Erik von Asmuth

18.2k51938




18.2k51938












  • 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 at 0:26










  • I've edited the answer.
    – Erik von Asmuth
    Nov 15 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 at 0:26










  • I've edited the answer.
    – Erik von Asmuth
    Nov 15 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 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 at 0:26












I've edited the answer.
– Erik von Asmuth
Nov 15 at 7:04




I've edited the answer.
– Erik von Asmuth
Nov 15 at 7:04


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python