Posts tagged ‘MS Access Queries’

November 7th, 2011

MS Access – VBA – Run Parameter Query in VBA

Once one delves into the wonderful world of MS Access & VBA programming, you quickly gets faced with the problem of executing queries and SQL statements from within VBA. No in general, this does not pose much of an issue and there are any number of great tutorials that cover the various way to handle this. For instance, Database Journal has a great article by Danny Lesandrini entitled Executing SQL Statements in VBA Code which covers all the methods available to a developer and explains the pros and cons of each.

That said, all of these articles cover but the basic idea of a simple SQL Statement. What happens if you want to execute a parameter query? How do you approach that. In fact, this isn’t to big an issue either, once you are shown how to handle it.

Firstly, let us very briefly cover the subject of a Parameter. What is a parameter? In a query, we can specify a criteria. In most instances, the criteria will be a static value. That said, it become necessary in many instances to make these criteria dynamic, and to do this there are different methods, but one common approach is to refer to a control on a form, thus allowing the end-user the ability to specify the criteria to apply to the query. This is what I am referring to in this post.

The problem arises that if you merely try to execute a query with a criteria to a form control, it will result in an error “Too Few Parameters”. The work around is that we much first make the database evaluates each parameter before running the query, to do so, we use the following code

    Dim db              As DAO.Database
    Dim qdf             As DAO.QueryDef
    Dim prm             As DAO.Parameter
    Dim rs              As DAO.Recordset
 
    Set db = CurrentDb
    Set qdf = db.QueryDefs("YourQueryName")
 
    For Each prm In qdf.Parameters
        prm = Eval(prm.Name)
    Next prm
 
    Set rs = qdf.OpenRecordset
 
    'Work with the recordset

    rs.Close 'Close the recordset
    'Cleanup after ourselves
    Set db = Nothing
    Set qdf = Nothing

So how does it work exactly? Well, we start off by specifying which query we are working with by setting the value of the qdf variable. Next, we llop through the parameters and evaluate each one. Finally, we execute the query. So simple, once you are shown the proper tachnique!

You may wish to look over the sample database found at Roger’s Access Library entitled Too few Parameters.

June 30th, 2011

MS Access – Sub-Query – Invalid Bracketing

Here is about the most frustrating error message you can get in Access (Okay, there are many others that are just as problematic…)

MS Access Invalid Bracketing Error

I myself had encountered this errors many times in the past and understood the reason (improper SQL statement), but never understood why after performing the necessary correction to the query to make it work, that it would break again?! As of late, I came accross an excellent explanation made by fellow MVP, Dirk Goldgar.

This is a well-known and annoying problem. Access has a preferred, non-standard SQL syntax for derived tables, and if you give it half a chance, it will transform your SQL into that syntax. The standard syntax is:

(SELECT … FROM …) As T

Jet’s preferred, but non-standard syntax is:

[SELECT ... FROM ...;]. As T

.. or some variation thereof. As you see, the parentheses have been changed to square brackets, and a dot (.) has been added after the closing bracket.

Now, this doesn’t matter if the subquery doesn’t include any square brackets of its own — around field or table names, for example. But sometime those are required because of names that use nonstandard characters, and also the Access query designer automatically surrounds everything with brackets “for safety’s sake.” So in these cases, the transformed query becomes syntactically invalid, because Access can’t parse brackets inside of brackets. Once this happens, if the SQL has to be reparsed, an error is raised.

The first workaround for this problem is to ensure that no brackets are present around field names or table names in the SQL of the subquery. If you can do that, then there will be no problem if Access decides to rewrite your SQL in its own quirky way.

If you can’t do that, then you need to design the query in SQL view, and try never to open the query in design view. If you do open it in design view, you must not then save the query, unless you first switch to design view and fix the SQL again.

This is particularly a problem in rowsources for combo and list boxes, since clicking the build button on the RowSource property line automatically opens the query in design view. Flip to SQL view, fix it if necessary, and do your work there.

We have asked Microsoft to fix this bug in the query designer — so far, to no effect.

Feel free to checkout the original post at: http://answers.microsoft.com/en-us/office/forum/office_2003-access/sub-query-headaches/b1e09348-209f-4a2f-acc1-fe7191ae9591

So what have we learnt, yet again? The importance of following naming conventions. In my particular case, like the OP in the original post, I am working with an old database that was developed by someone else and am now trying to fix. So I will have to live with this nuissance until I can do a cleanup of table field names, etc. But the entire issue can easily be entirely avoided by following a simple naming convention.

Lastly, thank you Dirk for the excellent, plain English explanation!

June 13th, 2011

MS Access – VBA – Delete all the Queries

Similarily to deleting tables, if you have ever needed to delete all the queries from a database, it can be a long tedeous task as Access does not allow multiple Object selection. So you have to delete each query, one by one!!! Hence, why I created the simple little procedure below.

'---------------------------------------------------------------------------------------
' Procedure : DeleteAllQueries
' Author    : Daniel Pineault, CARDA Consultants Inc.
' Website   : http://www.cardaconsultants.com
' Purpose   : Deletes all the queries from the active database
' Copyright : The following may be altered and reused as you wish so long as the
'             copyright notice is left unchanged (including Author, Website and
'             Copyright).  It may not be sold/resold or reposted on other sites (links
'             back to this site are allowed).
'
' Revision History:
' Rev       Date(yyyy/mm/dd)        Description
' **************************************************************************************
' 1         2011-Jun-10                 Initial Release
'---------------------------------------------------------------------------------------
Function DeleteAllQueries()
On Error GoTo Error_Handler
    Dim db               As DAO.Database
    Dim qdf              As DAO.QueryDef
 
    DoCmd.SetWarnings False
    Set db = CurrentDb
    For Each qdf In db.QueryDefs
        DoCmd.DeleteObject acQuery, qdf.Name
    Next
 
Error_Handler_Exit:
    DoCmd.SetWarnings True
    Set qdf = Nothing
    Set db = Nothing
    Exit Function
Error_Handler:
    MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
           "Error Number: " & Err.Number & vbCrLf & _
           "Error Source: DeleteAllQueries" & vbCrLf & _
           "Error Description: " & Err.Description, _
           vbCritical, "An Error has Occurred!"
    Resume Error_Handler_Exit
End Function
May 25th, 2011

MS Access – VBA – Hide Object Pane

Here is a simple bit of code that permits you to hide the MS Access’ main object browser, to stop nosy users from accessing tables, queries, etc…

DoCmd.SelectObject acTable, , True
DoCmd.RunCommand acCmdWindowHide

In conjunction with the code to determine whether the user is running the runtime or full version of Access (see MS Access – Determine if Runtime or Full Version
) you could insert a section of code such as:

If SysCmd(acSysCmdRuntime) = False Then
    DoCmd.SelectObject acTable, , True
    DoCmd.RunCommand acCmdWindowHide
End If

This would also be a good place to enable any custom command bars/ribbons and/or disable any built-in command bars/ribbons…

April 30th, 2011

MS Access – JET SHOWPLAN

I came across an article about optimizing queries using a hidden JET tool call SHOWPLAN which basically generates a showplan.out file (which is merely a text file) which elaborates the method used by Access to execute the query. With this information it is possible to perform optimizations, determine which fields require indexing…

I’m not going to rewrite the article, if the subject interests you, then simply look at the source article.

That said, I did want to try and add a little more information for anyone trying to get this to work using Windows 7 (possibly Windows Vista – untested). To be able to use ShowPlan one must create a registry entry to enable it. In the original atricle, they indicate that the base registry key is found at:

\\HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\JET\4.0\Engines

this may be the case for Windows XP, but if you are using Windows 7 (and I suspect Vista as well) you will not find this key. Instead look for:

\\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Jet\4.0\Engines

June 22nd, 2010

MS Access – Calculate the Age

If you have ever needed to calculate the age between two dates, then the function below is for you. Often people mistakenly believe that the age calculation can simply be accomplished using the DateDiff() function, but this is not the case and a slightly more complexe function is required to do the job.

To merely calculate the age of an individual in years, you can simply use the DateDiff().

=DateDiff("yyyy", [DOB], Date()) - IIF(Format([DOB], "mmdd") > Format(Date(), "mmdd"), 1, 0)

However, if you would like a little more detail (Years, Months, Days) you can use a function such as the one presented below.

Function fAge(dteStart As Variant, dteEnd As Variant) As Variant
'*******************************************
'Purpose:   Accurately return the difference
'           between two dates, expressed as
'           years.months.days
'Coded by:  raskew (from MS Access forum)
'Inputs:    From debug (immediate) window
'           1) ? fAge(#12/1/1950#, #8/31/2006#) 'Calculate btw 2 specific dates
'           2) ? fAge(#12/30/2005#, Date()) ' Calculate as of today's date
'*******************************************
Dim intHold   As Integer
Dim dayhold   As Integer
 
   'correctly return number of whole months difference
   'the (Day(dteEnd) < Day(dteStart)) is a Boolean statement
   'that returns -1 if true, 0 if false
   intHold = DateDiff("m", dteStart, dteEnd) + (Day(dteEnd) < Day(dteStart))
 
   'correctly return number of days difference
   If Day(dteEnd) < Day(dteStart) Then
      dayhold = DateDiff("d", dteStart, DateSerial(Year(dteStart), Month(dteStart) + 1, 0)) + Day(dteEnd)
   Else
      dayhold = Day(dteEnd) - Day(dteStart)
   End If
 
   fAge = LTrim(Str(intHold \ 12)) & " years " & LTrim(Str(intHold Mod 12)) & " months " & LTrim(Str(dayhold)) & " days"
 
End Function