By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,717 Members | 1,233 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,717 IT Pros & Developers. It's quick & easy.

Debugging help. SQL/VBA fusion

thelonelyghost
100+
P: 109
Software: Access 2000
Operating System: Windows XP Professional SP3
Problem: Error 2001 based on filter being "ModelYear <= 2006".
Solution: Table's datatype was text when SQL expected number.

I'm in the middle of debugging an issue with some dynamic SQL code and I think I may have missed some important rule. When I try to use it, it pops up with a general syntax error (Runtime Error 2001). My error arises when I have the function Me.frmSubForm.Form.Filter = SQLFilter even though SQLFilter = "ModelYear <= 2006". Here's the relevant function information:

Main function:
Expand|Select|Wrap|Line Numbers
  1. 'Outputs string of SQL statement
  2. Private Function SQLFilter() As String
  3.  
  4. Dim strSQLContent As String, strDelim As String
  5.  
  6. 'detecting whether to use AND or OR
  7. 'based on button 'ANY' or 'ALL'
  8.   strDelim = IIf(Me.btn2SearchSettingsAnyAll.Value = 1, " OR ", " AND ")
  9.  
  10. 'transforming form inputs into SQL code with subfunctions
  11.   strSQLContent = strSQLContent & lib.GreaterThanAttachAnd("ModelYear", Me.txtMinModelYear.Value, strDelim)
  12.   strSQLContent = strSQLContent & lib.LessThanAttachAnd("ModelYear", Me.txtMaxModelYear.Value, strDelim)
  13.  
  14. 'Clean up the concatenation of all of the fields into a SQL statement fragment
  15. SQLFilter = lib.StrReplace(strSQLContent, strDelim, "", 1)
Sub-functions from the lib Module:
GreaterThanAttachAnd():
Expand|Select|Wrap|Line Numbers
  1. 'This code is meant to a string as part of a dynamic SQL statement.
  2. 'strField = field (i.e. 'strJusticeLeague')
  3. 'strValue = control (i.e. 'Me.strBatman')
  4. 'strDelim = 'AND' or 'OR'.
  5.  
  6. Public Function GreaterThanAttachAnd(strField As Variant, strValue As Variant, strDelim As Variant) As String
  7.  
  8.   If strValue = "''" Or strValue = "" Or IsNull(strValue) Then
  9.   Exit Function
  10.   Else
  11.     strValue = Trim(strValue)
  12.     If strValue Like "##/##/####" Then 'filters dates
  13.       strValue = "#" & strValue & "#"
  14.     Else: If IsNumeric(strValue) = False Then strValue = "'" & strValue & "'"
  15.     End If
  16.     GreaterThanAttachAnd = strDelim & strField & " >= " & strValue
  17.   End If
  18.  
  19. End Function
LessThanAttachAnd():
Expand|Select|Wrap|Line Numbers
  1. 'This code is meant to a string as part of a dynamic SQL statement.
  2. 'strField = field (i.e. 'strJusticeLeague')
  3. 'strValue = control (i.e. 'Me.strBatman')
  4. 'strDelim = 'AND' or 'OR'.
  5.  
  6. Public Function LessThanAttachAnd(strField As Variant, strValue As Variant, strDelim As Variant) As String
  7.  
  8.   If strValue = "''" Or strValue = "" Or IsNull(strValue) Then
  9.   Exit Function
  10.   Else
  11.     strValue = Trim(strValue)
  12.     If strValue Like "##/##/####" Then
  13.       strValue = "#" & strValue & "#"
  14.     Else: If IsNumeric(strValue) = False Then strValue = "'" & strValue & "'"
  15.     End If
  16.     LessThanAttachAnd = strDelim & strField & " <= " & strValue
  17.   End If
  18.  
  19. End Function
StrReplace():
Expand|Select|Wrap|Line Numbers
  1. Public Function StrReplace(strHaystack As String, strNeedle As String, strReplaceWith As String, intRepeat As Integer) As String
  2.  
  3. Dim init As Long, i As Integer
  4.  
  5. 'Failsafe for illegal inputs, then declarations after "Else "
  6. If Len(strHaystack) < 1 Or Len(strNeedle) < 1 Or intRepeat > 0 = False Then
  7.     Exit Function
  8. Else
  9.   init = InStr(strHaystack, strNeedle)
  10.   i = IIf(IsNull(intRepeat), 99, intRepeat)
  11. End If
  12.  
  13. Do While init > 0 And IIf(IsNull(intRepeat), 1 = 1, i > 0)
  14.   strHaystack = Left(strHaystack, init - 1) & strReplaceWith & Right(strHaystack, Len(strHaystack) - Len(strNeedle) - init + 1)
  15.  
  16.   'Maintenance for While-loop
  17.   i = IIf(intRepeat > 0, i - 1, i)
  18.   init = InStr(strHaystack, strNeedle)
  19. Loop
  20.  
  21. StrReplace = strHaystack
  22.  
  23. End Function
Jul 7 '10 #1

✓ answered by NeoPa

thelonelyghost: I know there's no .Filter or .FilterOn in my code above because it's stand-alone for a command button. I didn't think it was too relevant but I'll add the code from that too. It was pretty much exactly as I described it and it works for everything else I've tested it on, so I don't see this as being the issue.
That's probably true. However, it gives us, that haven't any direct access to your database, both context (without which it is very difficult to think of, let alone solve, your problem) and confirmation of other information you've given us. You'd be surprised at how often we are led up the garden path by information which fits the poster's understanding, yet which is simply wrong. Posted code gives us clues as to how much to rely on certain statements. As communication is 90+% of the issue when dealing over a web page, this is very important.
thelonelyghost: The horrible thing is that this error comes up on line 5 of the above button's code if the filter is already on, whereas it's on line 6 if the filter is off.
This makes perfect sense. If .FilterOn is true then the new filter value is applied immediately (line #5). If not, then it is only applied after it is set to True (Line #6).
thelonelyghost: For further info on my error 2001, it says:
Expand|Select|Wrap|Line Numbers
  1. "Runtime Error '2001':
  2. You canceled the previous operation."
  3. Continue(greyed)    End       Debug       Help(greyed)
  4.  
Good news and bad news. The good news is that this information is very helpful. The bad is that it often indicates a corruption in your database. Not guaranteed, but it's a worrying indicator.
thelonelyghost: The fields for min and max model year, since I want to search it as a range or each one independently (hence using '>=' and '<=' instead of 'BETWEEN'), are text boxes with an input mask of 4 numerical characters. I just take the value of the field and input that into the SQL though so there shouldn't be a datatype issue, right? You saw my SQL output...
I saw your SQL output, but as in my previous post (#7) I don't know the datatype of your field [ModelYear]. As I said, if it's a string then the SQL would be wrong. The control that you're describing doesn't come into this at all. Entirely unrelated.
thelonelyghost: Did that help? It didn't do much for me. The exact same error in the past was caused by SQL syntax being off. You may be familiar with my issues with the dates and our talk about Format()? (linkback) This issue honestly has me stumped even worse than the last set of obstacles, mostly because the error is so general.
It certainly did.

Please note the bolded text in the quote. It would be a good idea to ignore this whole point in future as irrelevant. If someone asks for information, it is better to trust that they probably know why they want it, rather than trying to understand why. Not understanding certainly doesn't indicate it is not worth providing whatever's requested. It just gets in the way of positive communication, which is the most important individual element when dealing with someone across a forum web page.

My advice, after all that, is to check the type of the [ModelYear] field in your table. If it is not numeric then that could well be your problem. If it is numeric, then I suggest you look at Compacting/Repairing your database. This may be recoverable. If not, then you may need to consider recreating any objects that are not recovered. Never good news I know, but check out [ModelYear] first. It may be less drastic than that.

Share this Question
Share on Google+
12 Replies


NeoPa
Expert Mod 15k+
P: 31,769
What's the error message and where does this line occur within the various pieces of code posted?
Jul 7 '10 #2

NeoPa
Expert Mod 15k+
P: 31,769
By the way, some general debugging tips with SQL and VBA are included indented below :
One of the most popular (frequently occurring rather than best liked) problems we get is with SQL strings being manipulated in VBA code.

The reason this is so difficult is that all the work is being done at a level of redirection. What I mean by this is that the coder is never working directly with the SQL itself, but rather with code which in turn, is relied on to produce the SQL that they are envisaging is required. It's rather similar to the problems coders have historically had dealing with pointers.

Anyway, a technique I often suggest to coders struggling with this (at any level. This happens to experienced coders too.) is to use either the MsgBox() function, or Debug.Print into the Immediate Pane of the debugger window, to display the value of the SQL in the string before using it (That's assuming you're not good with debugging generally. Personally I would trace to the line, then display the value prior to allowing execution of the string - See Debugging in VBA). It's really much easier to appreciate what a SQL string is meant to do, and where there may be problems, when you can see it in its entirety, and in its true form, rather than as the code is about to create it.
Jul 7 '10 #3

thelonelyghost
100+
P: 109
Sorry if this wasn't clear. It's error 2001, which I've found is Access's way of saying "General syntax error. FIX IT!" I went line-by-line and followed how each variable (such as strValue) changed along the way, and it all does it as I expected. I checked to see if the SQL made sense and it did to me, but I'm posting this to make sure I didn't miss some rule with setting a filter. An example of a rule I've overlooked in the past is comparing '29' with 29 proves difficult, so I made an exclusion rule for numbers and dates when applying quotes.

BTW, NeoPa, since I know you've been following my progress I thought you'd enjoy this news. I rewrote the copyrighted find function I talked about in earlier threads, debugged it, successfully tested it, and added functionality. It's posted above as the StrReplace() function.

EDIT: added error number and rearranged OP to be an easier read.
Jul 7 '10 #4

thelonelyghost
100+
P: 109
Also (watch me double-post!) I was already following your suggestion of posting the overall function's output for SQLFilter. On the last line of my OP (before I revised it), I said it was a string containing "ModelYear <= 2006", taken verbatim from the debugger.

The issue that prompts the SQL syntax error is trying to apply it to a filter (Me.frmSubForm.Form.Filter = SQLFilter) or, if the filter isn't turned on yet, turning the filter on (Me.frmSubForm.Form.FilterOn = True).
Jul 7 '10 #5

NeoPa
Expert Mod 15k+
P: 31,769
thelonelyghost: I was already following your suggestion of posting the overall function's output for SQLFilter. On the last line of my OP (before I revised it), I said it was a string containing "ModelYear <= 2006", taken verbatim from the debugger.
I'm not surprised, but I couldn't be sure. It never hurts to drop that bit in I find, even if the OP themselves is already aware of it.

I'll try to find where the problem is, and what the error message is from what you've posted already, but if you get a second dropping the line number and procedure of the line of code that it errors on and the actual error message (The message I find when I search for 2001 is "Invalid picture".) would be a help.
Jul 8 '10 #6

NeoPa
Expert Mod 15k+
P: 31,769
thelonelyghost: Sorry if this wasn't clear. It's error 2001, which I've found is Access's way of saying "General syntax error. FIX IT!" I went line-by-line and followed how each variable (such as strValue) changed along the way, and it all does it as I expected. I checked to see if the SQL made sense and it did to me, but I'm posting this to make sure I didn't miss some rule with setting a filter. An example of a rule I've overlooked in the past is comparing '29' with 29 proves difficult, so I made an exclusion rule for numbers and dates when applying quotes.
In your case there may well be a problem if your field [ModelYear] is a string. Otherwise I see no problem with that as a .Filter value. I would change it, if it were me, to :
Expand|Select|Wrap|Line Numbers
  1. [ModelYear]<=2006
but that is about readability and being explicit with code - not to fix any perceived error.
thelonelyghost: BTW, NeoPa, since I know you've been following my progress I thought you'd enjoy this news. I rewrote the copyrighted find function I talked about in earlier threads, debugged it, successfully tested it, and added functionality. It's posted above as the StrReplace() function.
Well done. I have a similar function myself. Not exactly the same requirement, but similar. I use the Replace() function heavily in that. I doubt that would work for your specific requirements though. Mine takes multiple pairs of parameters as well as the original string, and replaces the first of each pair with the second, as many times as it finds them.
Jul 8 '10 #7

NeoPa
Expert Mod 15k+
P: 31,769
I'm sorry. I looked through all your code but could find nothing that set the .Filter property, or even the .FilterOn one.

I've commented already as much as I can on the string you posted, otherwise I see no more I can do now.
Jul 8 '10 #8

thelonelyghost
100+
P: 109
I know there's no .Filter or .FilterOn in my code above because it's stand-alone for a command button. I didn't think it was too relevant but I'll add the code from that too. It was pretty much exactly as I described it and it works for everything else I've tested it on, so I don't see this as being the issue.

Expand|Select|Wrap|Line Numbers
  1. 'Displays search results in subform
  2. 'based on partial SQL string contstructed with SQLFilter function
  3. Private Sub btnSearch_Click()
  4.  
  5. Me.frmSubForm.Form.Filter = SQLFilter
  6. Me.frmSubForm.Form.FilterOn = True
  7. Me.frmSubForm.Form.OrderBy = Me.cmbGroupBy
  8.  
  9. 'Me.frmSubForm.Form.RecordSource = BuildSQLStr
  10.  
  11. End Sub
The horrible thing is that this error comes up on line 5 of the above button's code if the filter is already on, whereas it's on line 6 if the filter is off. For further info on my error 2001, it says:

Expand|Select|Wrap|Line Numbers
  1. "Runtime Error '2001':
  2. You canceled the previous operation."
  3. Continue(greyed)    End       Debug       Help(greyed)
  4.  
The fields for min and max model year, since I want to search it as a range or each one independently (hence using '>=' and '<=' instead of 'BETWEEN'), are text boxes with an input mask of 4 numerical characters. I just take the value of the field and input that into the SQL though so there shouldn't be a datatype issue, right? You saw my SQL output...

Did that help? It didn't do much for me. The exact same error in the past was caused by SQL syntax being off. You may be familiar with my issues with the dates and our talk about Format()? (linkback) This issue honestly has me stumped even worse than the last set of obstacles, mostly because the error is so general.
Jul 8 '10 #9

NeoPa
Expert Mod 15k+
P: 31,769
thelonelyghost: I know there's no .Filter or .FilterOn in my code above because it's stand-alone for a command button. I didn't think it was too relevant but I'll add the code from that too. It was pretty much exactly as I described it and it works for everything else I've tested it on, so I don't see this as being the issue.
That's probably true. However, it gives us, that haven't any direct access to your database, both context (without which it is very difficult to think of, let alone solve, your problem) and confirmation of other information you've given us. You'd be surprised at how often we are led up the garden path by information which fits the poster's understanding, yet which is simply wrong. Posted code gives us clues as to how much to rely on certain statements. As communication is 90+% of the issue when dealing over a web page, this is very important.
thelonelyghost: The horrible thing is that this error comes up on line 5 of the above button's code if the filter is already on, whereas it's on line 6 if the filter is off.
This makes perfect sense. If .FilterOn is true then the new filter value is applied immediately (line #5). If not, then it is only applied after it is set to True (Line #6).
thelonelyghost: For further info on my error 2001, it says:
Expand|Select|Wrap|Line Numbers
  1. "Runtime Error '2001':
  2. You canceled the previous operation."
  3. Continue(greyed)    End       Debug       Help(greyed)
  4.  
Good news and bad news. The good news is that this information is very helpful. The bad is that it often indicates a corruption in your database. Not guaranteed, but it's a worrying indicator.
thelonelyghost: The fields for min and max model year, since I want to search it as a range or each one independently (hence using '>=' and '<=' instead of 'BETWEEN'), are text boxes with an input mask of 4 numerical characters. I just take the value of the field and input that into the SQL though so there shouldn't be a datatype issue, right? You saw my SQL output...
I saw your SQL output, but as in my previous post (#7) I don't know the datatype of your field [ModelYear]. As I said, if it's a string then the SQL would be wrong. The control that you're describing doesn't come into this at all. Entirely unrelated.
thelonelyghost: Did that help? It didn't do much for me. The exact same error in the past was caused by SQL syntax being off. You may be familiar with my issues with the dates and our talk about Format()? (linkback) This issue honestly has me stumped even worse than the last set of obstacles, mostly because the error is so general.
It certainly did.

Please note the bolded text in the quote. It would be a good idea to ignore this whole point in future as irrelevant. If someone asks for information, it is better to trust that they probably know why they want it, rather than trying to understand why. Not understanding certainly doesn't indicate it is not worth providing whatever's requested. It just gets in the way of positive communication, which is the most important individual element when dealing with someone across a forum web page.

My advice, after all that, is to check the type of the [ModelYear] field in your table. If it is not numeric then that could well be your problem. If it is numeric, then I suggest you look at Compacting/Repairing your database. This may be recoverable. If not, then you may need to consider recreating any objects that are not recovered. Never good news I know, but check out [ModelYear] first. It may be less drastic than that.
Jul 8 '10 #10

thelonelyghost
100+
P: 109
Possible further insight: The same exact error as above happens when I choose something from the Engine combo box (viewed as "3.9L", as a string). Debugging showed that it was identifying it by the ID number from the lookup table. Searching by the associated content (i.e. content = "3.9L" versus ID = "12") from the lookup table fixes this issue.
Jul 8 '10 #11

thelonelyghost
100+
P: 109
Just saw the new post. I looked at the table I'm filtering and slapped my forehead. It was as simple as datatype mismatch, like you suggested. I could have sworn earlier that it was a number datatype, but in fact it was a text datatype. For a while I didn't realize one could put an input mask on anything other than text fields so... :) IT'S SOLVED!

Apologies for the needless info, I thought it helped explain why I didn't include it in the information to begin with. I'm well aware that most people on this site know what they're doing when they ask for things such as your request for error description and it was in no way meant to insult you.

Side note, I do appreciate the instructions on local forum ettiquette since, I've very recently and shockingly realized, not every forum has the same basic rules. I'm just trying to seamlessly fit into the community here while simultaneously learning more about this software.
Jul 8 '10 #12

NeoPa
Expert Mod 15k+
P: 31,769
As you say, I've caught a number of your posts, so I know better than to think you're not trying to work well with us. I just felt a few pointers may help due to the apparent difficulties in this particular thread. I never felt insulted by the way. That would be more likely to trigger a deafening silence than pointers on how better to proceed :D

This sounds like a difficult one in truth. I remember when I first fell over that sort of confusion. It was actually where a field was set up as a ComboBox in the table itself. Confused me mightily.

Anyway, all resolved now, and I can happily say that I'm looking forward to more of your questions. You always do your best to explain them well and work with us to resolve the issue.
Jul 8 '10 #13

Post your reply

Sign in to post your reply or Sign up for a free account.