I know RunSQL is for action query but is there....

Eniac

Canadian Nerd
Local time
, 21:25
Joined
Jun 8, 2004
Messages
23
I know RunSQL is for action query but is there some kind of workaround to receive a value from a saved query ?

Surely you guys get this question often, maybe its a sign that MS should give us that darn function :)

I've made this query :

SELECT IIf(IsNull(Max(ID)),0,Max(ID))+1 AS MaxID
FROM History;


I've saved it as a query and I'd like to call it from a module, or at least from a form and receive only the value, not open a window with the value.

Same as if I as was calling a stored proc from oracle basically....

is that feasible ?


(in case you wonder why I need to do that.... I just plain hate autonumbers and I'm trying to take it in charge myself)
 
You could call a public function using DMax to do what you want. Try this...
Code:
Public Function NewNumber() As String
On Error GoTo Err_NewNumber

    NewNumber = DMax("[YourField]", "YourTable")
    'MsgBox NewNumber 'For testing
    
Exit_NewNumber:
    Exit Function

Err_NewNumber:
    MsgBox Err.Number & " - " & Err.Description
    Resume Exit_NewNumber

End Function
 
Hi,

Try this. In Access97 if in 2000 you'll need the Microsoft DAO 3.6 Reference

Code:
Public Function GetMAX() As Integer
Dim Db As DAO.Database
Dim Rst As DAO.Recordset

Set Db = CurrentDb
Set Rst = Db.OpenRecordset("QRY_INTMAX")

MsgBox Rst.Fields(0) ' to display result
GetMAX = Rst.Fields(0) ' to return the result to the calling procedure

Set Rst = Nothing
Set Db = Nothing

End Function

QRY_INTMAX is the name of the saved query. There was only 1 field so i used

Rst.Fields(0) you can use RST![nameofyourfieldhere] to refer to specific field from the query by name. It should be faster than Dmax ( no offence Ghundson ;) )

HTH

The Stoat :)
 
Last edited:
Ah! so this how its done....

Ah! so it is possible to query the database from within a module. I was beginning to wonder why Access is so "popular" if you can't even manipulate your stuff by programming.

I'm still surprised we have to reference to DAO from within Access to programmatically access the tables of the very same database but .. oh well.. :D

I've been in the programming field for quite some time but I have very little experience in Access, thus my newbieness :)

Thanks again.
 
Hi,

DAO is simply what i use in Access 2000 as a lot of my work has to be compatible in 97. If your using 97 then you don't need to ref DAO. To be precise you don't need to put DAO.Recordset. If your using 2000 then you could obviously learn ADO(? :D ) instead.

The Stoat
 
Last edited:
Thought you'd like this...

I took Stoat's function and extended its capabilities to better serve my purposes but I'm sure it can be useful for other people than myself so here it is.

Its a generic function (well... two) to call a saved query and return one or more rows with one or more fields in that query.

I haven't tested it THAT thorougly but so far it seems to be responding well.

....you'll hear from me again, I just started that Access project and I'm not really a pro with it... yet :p

Thanks again and good luck



Code:
Public Function RunQuery(ByVal prmstrQuery As String, _
                         ByVal prmintRowsToReturn As Integer, _
                         ParamArray prmarrReturnFields() As Variant) As Variant
On Error GoTo RunQuery_ERR

Const cRETURN_ALL As Integer = 0   'For row-returning queries
Const cRETURN_FIRST As Integer = 1
Const cRETURN_LAST As Integer = -2 'Any positive number could mess up the return
Const cRETURN_NONE As Integer = -1 'For action queries

Dim objDB As DAO.Database
Dim objRS As DAO.Recordset
Dim objField As DAO.Field
Dim objError As Object

Dim strQuery As String
Dim intRowsToReturn As Integer

Dim arrRSFields() As Variant
Dim arrReturnFields As Variant
Dim arrFields As Variant

Dim i As Integer
Dim j As Integer


ReDim arrFields(0, 0)

arrFields(0, 0) = "#ERROR"

intRowsToReturn = CInt(prmintRowsToReturn) 'safety
strQuery = Trim(prmstrQuery)
arrReturnFields = prmarrReturnFields

If strQuery & "x" <> "x" Then
  Set objDB = CurrentDb
  Set objRS = objDB.OpenRecordset(strQuery)
  
  If intRowsToReturn = cRETURN_NONE Then
    'Only action queries will request "RETURN_NONE"
    arrFields(0, 0) = objDB.RecordsAffected
  ElseIf objRS.RecordCount > 0 Then
  
    If Not IsArray2(arrReturnFields) Then
      Select Case intRowsToReturn
        Case cRETURN_ALL
          arrFields = objRS.GetRows()
        
        Case cRETURN_FIRST
          arrFields = objRS.GetRows(1)
        
        Case cRETURN_LAST
          'This is as straightforward as i can make it to fetch the last on a "generic" basis
          objRS.MoveLast
          ReDim arrFields(objRS.Fields.Count - 1, 0)
          i = 0
          For Each objField In objRS.Fields
            arrFields(i, 0) = objField.Value
            i = i + 1
          Next objField
          Set objField = Nothing
          
        Case Else 'Any other positive integer will be considered as the # of rows to return
          If intRowsToReturn > 0 Then
            arrFields = objRS.GetRows(intRowsToReturn)
          End If
      End Select
    Else 'User requested to return only specific field (slower...)
      ReDim arrRSFields(UBound(arrReturnFields))
      For i = 0 To UBound(arrRSFields) 'Create an array of field objects based on the return list
        Set arrRSFields(i) = objRS.Fields(arrReturnFields(i))
      Next i
     
      Select Case intRowsToReturn
        Case cRETURN_ALL
          ReDim arrFields(UBound(arrRSFields, 1), objRS.RecordCount - 1)
          j = 0
          Do
            For i = 0 To UBound(arrRSFields, 1)
              arrFields(i, j) = arrRSFields(i).Value
            Next i
            
            j = j + 1
            objRS.MoveNext
          Loop Until objRS.EOF
        
        Case cRETURN_FIRST
          objRS.MoveFirst
          For i = 0 To UBound(arrRSFields, 1)
            arrFields(i, 0) = arrRSFields(i).Value
          Next i
          
        Case cRETURN_LAST
          objRS.MoveLast
          For i = 0 To UBound(arrRSFields, 1)
            arrFields(i, 0) = arrRSFields(i).Value
          Next i
          
      End Select
      
    
    End If 'Not IsArray2(arrReturnFields)
  End If 'Rst.RecordCount > 0
End If 'strQuery & "x" <> "x"

RunQuery_END:
  Set objRS = Nothing
  Set objDB = Nothing
  
  If IsArray2(arrRSFields) Then
    For i = 0 To UBound(arrRSFields, 1)
      Set arrRSFields(i) = Nothing
    Next i
    Erase arrRSFields
  End If
  
  RunQuery = arrFields 'Return the resultset as an array


Exit Function
RunQuery_ERR:
  If DBEngine.Errors.Count > 0 Then
    ReDim arrFields(1, DBEngine.Errors.Count) 'dont put .count - 1, first row is needed ...
    arrFields(0, 0) = vbObjectError
    arrFields(1, 0) = "#ERROR"
    i = 1
    For Each objError In DBEngine.Errors
      arrFields(0, i) = objError.Number
      arrFields(1, i) = objError.Description
      i = i + 1
    Next objError
  Else
    ReDim arrFields(1, 1)
    arrFields(0, 0) = vbObjectError
    arrFields(1, 0) = "#ERROR"
    arrFields(1, 0) = Err.Number
    arrFields(1, 1) = Err.Description
  End If
  
  Resume RunQuery_END

End Function

Public Function IsArray2(ByRef prmTestArray)
  On Error Resume Next
  'Do not make calls to CheckError here, we handle errors manually
  Dim intCrasher
  
  intCrasher = UBound(prmTestArray)
  IsArray2 = ((Err.Number = 0) And (intCrasher > -1)) 'Returns true or false
  Err.Clear
End Function
 
I agree with Stoat that a Recordset is clearly the way to go,

but personally I would use ADO not DAO, ADO has far better functions, is far more versatile and practically everything else uses ADO.
 
As in everything, surely there's a reason and a situation for both.

As far as my own knowledge goes, DAO would be more for database handling situation. Meaning messing with the database itself, manipulating its objects...etc.

ADO would be more for querying.

But what do i know, i never used DAO before because I never really worked in access before.

I'm used to programming website with ASP or VB with Oracle or SQL server behind so ADO was always the answer.

I went with DAO because I assumed it was THE way to go in Access.

But when you think about it, for basic operations like this... im not sure one is more efficient than the other, they're done by the same shop and their DOM is somewhat "shared". The only obvious difference is that DAO is geared more toward handling the database, and as such, it exposes different properties and method.

Whereas ADO, is geared more toward querying the database don't have to expose root objects.

Just a thought anyway...

But I'm curious, I did try to do my stuff with ADO at first but never could manage to find how to actually connect to the database.

How would you do that ?

I mean, how to just call the query "QRY_INTMAX" from within the module ?

Where do you assign "CurrentDB" with ADO ?
 
Curtsey of Mile-O
Code:
' create connection and recordset objects
Dim cnn As ADODB.Connection
Dim rst As ADODB.Recordset

' set connection object to current database
Set cnn = CurrentProject.Connection
' set recordset object to your query (assumes query is qryExample)
Set rst = New ADODB.Recordset

' open the recordset
' note that in ADO, the standard recordset is forward- and read-only
rst.Open "qryExample", cnn
' this would open the recordset as static with pessimistic locking:
'rst.Open "qryExample", cnn, adOpenStatic, adLockPessimistic

' things we can do with our recordset
With rst
    ' navigate our recordset
    .MoveNext
    .MovePrevious
    .MoveLast
    .MoveFirst

' add a record to our recordset
    .AddNew
    .Fields("MyField") = "NewValue"
    .Update

' edit a record in our recordset
    ' note that ADO does not require or provide a .Edit method
    .Fields("MyField") = "NewValue"
    .Update

' delete a record from our recordset
    .Delete

' get a count of the records in our recordset
' be careful in ADO since the default type of recordset (forward-only)
'  will always return -1 for the recordcount
    Debug.Print .RecordCount
        
' close the recordset object (connection to the query)
    .Close

End With

' clear the defined objects
Set rst = Nothing
Set cnn = Nothing

End Sub

'When using the OpenRecordset line you can specify the type of recordset
'you wish to open. Press F1 over the command to get a list of these opening
'methods such as Snapshot, Dynamic, and AppendOnly.
 
Last edited:
Looks like you got better search capabilities than me, I did see the numerous posts of mile-o but not that one.

So its "currentproject" i was searching for.. i probably would have never found it that easily.

I like the ADO approach because I'm much more conformtable with it, thanks for your help.
 
I started messing with this but got the error "User-defined type not defined". If I remember correctly, this is a problem with the references. However, if I go to Tools -> References, it is grayed out. Any ideas?
 
I must have been in debug mode (although I thought I opened the module fresh). I tried again and it worked. But now I've got another error. All I added was this:

Dim Db As DAO.Database
Dim Rst As DAO.Recordset

Set Db = CurrentDb
Set Rst = Db.OpenRecordset("qryMatching_Balance")

I get the error: Runtime error '3061':
Too few parameters. Expected 1


EDIT: OK, so it seems this error is caused by references within the query. The drama continues...
 
Last edited:
Hi All,

ADO can't be used in 97 and seeing as my db's have to compatible on both 200x and 97 i have to use DAO. Really should spend sometime with ADO as it's so much more like the VBscript stuff i use. Anyway, Kraj, odds on your qry is requesting something maybe a spelling mistake in one of the qry select parameters?

PS read your PM's

The stoat

EDIT Ok didn't see you edit i was posting :D :D
 
There's no mistake in the query since it works fine when not being called by VB. It seems more likely that VB just can't handle a recordset that calls other recordsets, unless maybe it is defined completely within the code, which is a royal pain in the arse (if possible at all given my code-writing ability). I've looked at examples of such code on the forums and my head started swimming :( Perhaps I'll be able to do it with assisstance, but I should do that in my other thread.
 

Users who are viewing this thread

Back
Top Bottom