DMAX and Large Numbers (1 Viewer)

gpgb

New member
Local time
Yesterday, 21:09
Joined
Oct 18, 2012
Messages
8
I have been using DMAX,DMIN,DCOUNT,DSUM successfully with VBA for some time (Access 365).

I noted the introduction of the LARGE NUMBER data type and have had cause to use it.

Surprised to note that DMAX doesn't work, IE returns Null

I protected against the Null using NZ but I need to find maxima

Typical code varMaxNumber = DMAX("BigNumber","CZStats")

returns Null

What am I missing?

Have spent a fruitless day looking for possible solutions but cannot locate anything
 

NauticalGent

Ignore List Poster Boy
Local time
Today, 00:09
Joined
Apr 27, 2015
Messages
6,341
Did you try

NZ(DMAX(“BigNumber”,”CZstats”), 0)

If it doesn’t return a number or a zero, then something is wrong with the arguments in your DMax function.
 

gpgb

New member
Local time
Yesterday, 21:09
Joined
Oct 18, 2012
Messages
8
Thanks for the quick reply

As per my initial post, I protected against the Null (as per your suggestion) by using the NZ construct, I always do this

The problem is that DMAX always returns Null, IE DMax fails when the Field Type is "large number".

I could use a recordset and order by size and identify the last record but DMAX is more elegant

I have attached a sample database with DMAX, DMIN and DSUM accessed through the form "Test Form" which identifies the problem. Interestingly DMAX and DMIN fail, DSUM works!

Any insight on this problem appreciated
 

Attachments

  • TestMax.accdb
    544 KB · Views: 95

isladogs

MVP / VIP
Local time
Today, 05:09
Joined
Jan 14, 2017
Messages
18,221
Yes, you're right.
Case of Microsoft left & right hands not working together?
Of course, Large Number datatype only works in the latest version of A2016 (365)

If you change the Large Number datatype to e.g. Number (Double), it will work perfectly. Probably also true for Decimal (not tested)

It also has the advantage that users with earlier versions of Access can open it.

See attached
 

Attachments

  • TestMax-CR.accdb
    544 KB · Views: 85

gpgb

New member
Local time
Yesterday, 21:09
Joined
Oct 18, 2012
Messages
8
Thanks for the reply, confirms what I thought

I need the large number data type, I am working with numbers requiring 58 bytes storage (and beyond) as part of a research project.

I have used Allen Browne's elookup construct to replace DLookup as was hitting "too many databases", almost cured.

Will adapt to create an EMax and EMin (trust this does not infringe any restrictions on his excellent coding)
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 12:09
Joined
May 7, 2009
Messages
19,243
here, i did not change the datatype,
but i replaced dMax, dMin.
see VBA module.
 

Attachments

  • aaTestMax.zip
    39 KB · Views: 89

isladogs

MVP / VIP
Local time
Today, 05:09
Joined
Jan 14, 2017
Messages
18,221
Thanks for the reply, confirms what I thought

I need the large number data type, I am working with numbers requiring 58 bytes storage (and beyond) as part of a research project.

I have used Allen Browne's elookup construct to replace DLookup as was hitting "too many databases", almost cured.

Will adapt to create an EMax and EMin (trust this does not infringe any restrictions on his excellent coding)

From previous experience, Allen is happy with his ideas being adapted.
I asked him before publishing my SQL to VBA and back again example.

You should attribute the original idea to him though.
Allen no longer has anything to do with Access but continues to host the site as a resource for others
 

gpgb

New member
Local time
Yesterday, 21:09
Joined
Oct 18, 2012
Messages
8
Thanks for the feedback Ridders / ArnelGP

I tried ArnelGP's vba replacement for DMax and DMin, worked a treat, has saved me a day coding and testing. Fantastic

Still, would be good to hear from Microsoft as to why DMax,min no longer work and if they perceive this as a bug

Cheers

Guy
 

isladogs

MVP / VIP
Local time
Today, 05:09
Joined
Jan 14, 2017
Messages
18,221
@gpgb
I'm intrigued by this question

I've tried entering data in the following formats:
- Large number (BIGINT)
- Double
- Decimal

See screenshot

As I thought I can enter larger numbers in double format than either of the other two - I gave up on double but its nowhere near the limit - the others are

So unless you're importing BIGINT data from SQL server, I'm not sure what the advantages are.

Suggest you contact MS via the Access User Voice forum - they do actually respond ... sometimes!
https://access.uservoice.com/

@arnelgp
That's a neat bit of code you uploaded - TLookup etc
It says the author is Pete Best dating back from 1996.
Do you have a weblink for him in case there's more goodies available by him
 

Attachments

  • Capture.PNG
    Capture.PNG
    8.2 KB · Views: 139

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 12:09
Joined
May 7, 2009
Messages
19,243
i dont, thst was an old download.
 

gpgb

New member
Local time
Yesterday, 21:09
Joined
Oct 18, 2012
Messages
8
Thanks again for all you help

I have posted similar remarks to this thread on the MS Access User Voice forum and they have already responded

Will revert on the benefits I found from using large number with examples

Regards
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Today, 12:09
Joined
May 7, 2009
Messages
19,243
just modified the tMax, and tMin.
the previous it can't handle combination field,

like:

tMax("[SmallNumber] + [BigNumber]", "table1")

Now, it can.

Code:
Option Compare Database   'Use database order for string comparisons
Option Explicit

' Replacement Functions for DLookup, DCount & DSum , DMax & DMin
'
' Notes:
' Any spaces in field names or table names will probably result in an error
' If this is the case then provide the brackets yourselfs, e.g.
' tLookup("My field","My table name with spaces in") will blow big time
' tLookup("[My field]","[My table name with spaces in]") will be ok
' These functions will not bracket the field/table names for you so as to
' remain as flexible as possible, e.g. you can call tSum() to add or multiply or
' whatever along the way, e.g. tSum("Price * Qty","Table","criteria") or if you're
' feeling adventurous, specify joins and the like in the table name.
'
' See tLookup function for changes from last version
'
' Uses DAO
'
' VB Users
' Get rid of tLookupParam() and the case in the error trapping
' of tLookup() that calls it, this uses a function built-in to
' MS-Access.

Public Enum tLookupReset
    tLookupDoNothing = 0
    tLookupRefreshDb = 1
    tLookupSetToNothing = 2
End Enum


Function tCount(pstrField As String, pstrTable As String, Optional pstrCriteria As String, Optional pdb As Database, Optional pLookupReset As tLookupReset = tLookupDoNothing) As Long

' Function tCount
' Purpose: Replace DCount, which is slow on attached tables
' Created: 1 Feb 1996 T.Best

' TB 28 Jan 2003
' Make this call TLookup() so we'll only need concentrate on
' one set of error handling code
    tCount = tLookup("count(" & pstrField & ")", pstrTable, pstrCriteria, pdb, pLookupReset)

End Function
Function tMax(pstrField As String, pstrTable As String, Optional pstrCriteria As String, Optional pdb As Database, Optional pLookupReset As tLookupReset = tLookupDoNothing) As Variant

' Function tMax
' Purpose: Replace DMax, which is slow on attached tables
' Created: 1 Feb 1996 T.Best

' TB 28 Jan 2003
' Make this call TLookup() so we'll only need concentrate on
' one set of error handling code

' ArnelGP 11 Feb 2014
' uses Top Value
    pstrTable = "(Select Top 1 " & pstrField & " As Expr9999 From " & pstrTable & _
            " Where " & IIf(IsMissing(pstrCriteria), "(1=1)", pstrCriteria) & _
            " Order By 1 Desc)"
    tMax = tLookup("Expr9999", pstrTable, , pdb, pLookupReset)
    'tMax = tLookup("max(" & pstrField & ")", pstrTable, pstrCriteria, pdb, pLookupReset)
End Function

Function tMin(pstrField As String, pstrTable As String, Optional pstrCriteria As String, Optional pdb As Database, Optional pLookupReset As tLookupReset = tLookupDoNothing) As Variant

' Function tMin
' Purpose: Replace DMin, which is slow on attached tables
' Created: 1 Feb 1996 T.Best

' TB 28 Jan 2003
' Make this call TLookup() so we'll only need concentrate on
' one set of error handling code
    
' ArnelGP 11 Feb 2014
' uses Top Value
    
    pstrTable = "(Select Top 1 " & pstrField & " As Expr9999 From " & pstrTable & _
            " Where " & IIf(IsMissing(pstrCriteria), "(1=1)", pstrCriteria) & _
            " Order By 1 Asc)"
    tMin = tLookup("Expr9999", pstrTable, , pdb, pLookupReset)
    'tMin = tLookup("min(" & pstrField & ")", pstrTable, pstrCriteria, pdb, pLookupReset)

End Function

Function tSum(pstrField As String, pstrTable As String, Optional pstrCriteria As String, Optional pdb As Database, Optional pLookupReset As tLookupReset = tLookupDoNothing) As Double

' Function tSum
' Purpose: Replace DSum, which is slow on attached tables
' Created: 1 Feb 1996 T.Best

' TB 28 Jan 2003
' Make this call TLookup() so we'll only need concentrate on
' one set of error handling code
    tSum = Nz(tLookup("sum(" & pstrField & ")", pstrTable, pstrCriteria, pdb, pLookupReset), 0)

End Function


Function tLookup(pstrField As String, pstrTable As String, Optional pstrCriteria As String, Optional pdb As Database, Optional pLookupReset As tLookupReset = tLookupDoNothing) As Variant
    On Error GoTo tLookup_Err

    ' Function  tLookup
    ' Purpose:  Replace DLookup, which is slow on attached tables
    '           For where you can't use TbtLookup() if there's more
    '           than one field in the criteria or field is not indexed.
    ' Created:  9 Jan 1996 T.Best
    ' Mod       1 Feb 1996 T.Best
    '   Error Trapping brought in line with this procurement system.

    ' Mod       13 Apr 1999 T.Best
    '   Lookups to ODBC datasource use the gdbSQL database object.

    ' Mod       14 Apr 1999 T.Best
    '   gdbSQL object no good if doing lookup on a local table, DOH!

    ' Mod       11 Jan 2002 G.Hughes
    '   Removed gdbSQL as it was slowing tLookup Down.!!!!!!!!!

    ' Mod       Unlogged
    '   Someone put gdbSQL back in

    ' Mod       27 Jan 2003 T. Best
    '   Optimise gdbSQL to use Pass-through, it wickedly fast

    ' mod       13 Mar 2003
    '   Taken out gdbSQL for redistribution and replaced
    '   the DbEngine with CurrentDB to avoid the now well
    '   documented (in CDMA) DbEngine reference bug.
    '   Added tLookupReset Parameter which does the following
    '   tLookupDoNothing    Do nothing
    '   tLookupRefreshDb    Refreshes collections on the db
    '   tLookupCloseDb      Sets the db to nothing
    '   Also added a db parameter so programmer can call it using
    '   their own db variable, which may be something they opened
    '   elsewhere (Idea by D.Fenton in CDMA).

    Static dbLookup As DAO.Database
    Dim rstLookup As DAO.Recordset
    Dim varvalue As Variant
    Dim strSQL As String

    ' if calling function sends a db then we'll use that
    If Not pdb Is Nothing Then
        Set dbLookup = pdb
    Else
        ' If our db vari is not initialised or the calling
        ' process wants the db objects refreshed then we'll
        ' set the db var using CurrentDb()
        If dbLookup Is Nothing Or pLookupReset = tLookupRefreshDb Then
            If Not dbLookup Is Nothing Then
                Set dbLookup = Nothing
            End If
            Set dbLookup = CurrentDb()
        End If
    End If


    ' If no criteria specified then we don't even want to get as far
    ' as putting the word "where" in there
    If Len(pstrCriteria) = 0 Then
        strSQL = "Select " & pstrField & " From " & pstrTable
    Else
        ' handle those instances where you call tLookup using a field
        ' on a form but can't be bothered to check whether it's null
        ' first before calling, e.g. =tLookup("col1","table","col2=" & txtWhatever)
        ' if txtWhatever was null it would cause an error, this way if there's
        ' nothing after the "=" sign then we assume it was null so we'll make
        ' it look for one.
        ' You may want to handle this differently and avoid looking up
        ' data where the criteria field is null and just always return a
        ' null in which case you'd need to add code to avoid doing the
        ' lookup altogether or just change the criteria to " = Null" as
        ' nothing will ever match with " = Null" so the function would
        ' return null.
        If Right(RTrim(pstrCriteria), 1) = "=" Then
            pstrCriteria = RTrim(pstrCriteria)
            pstrCriteria = Left(pstrCriteria, Len(pstrCriteria) - 1) & " is Null"
        End If

        ' build our SQL string
        strSQL = "Select " & pstrField & " From " & pstrTable & " Where " & pstrCriteria
    End If

    ' now open a recordset based on our SQL
    Set rstLookup = dbLookup.OpenRecordset(strSQL, dbOpenSnapshot, dbReadOnly)

    ' chekc if we returned anything at all
    If Not rstLookup.BOF Then
        ' return the value returned in the query
        varvalue = rstLookup(0)
    Else
        ' no records matched, return a null
        varvalue = Null
    End If
    tLookup = varvalue

tLookup_Exit:
    On Error Resume Next
    rstLookup.Close
    Set rstLookup = Nothing
    Exit Function

tLookup_Err:
    Select Case Err
    Case 3061
        ' Error 3061 - Too Few Parameters - Expected x, you know those programmers
        ' should really parse out those form object references for themselves but
        ' we can try to retrieve the situation here by evaluating any parameters
        ' we find in the SQL string.
        tLookup = tLookupParam(strSQL, dbLookup)
    Case Else
        MsgBox Err.Description, 16, "Error " & Err.Number & " in tLookup() on table " & pstrTable & vbCr & vbCr & "SQL=" & strSQL
    End Select
    Resume tLookup_Exit
    Resume

End Function

Function tLookupParam(pstrSQL As String, pdb As Database) As Variant
' Called when tLookup, tCount, tMax, tMin or tSum have bombed out
' with an expected parameter error, will go and create a querydef
' and then attempt to evaluate the parameters
' Error Trapped: 12/02/1999 10:21:24 Admin
    On Error GoTo tCountParam_Err
    Dim qdf As DAO.QueryDef
    Dim rst As DAO.Recordset
    Dim PRM As DAO.Parameter
    Dim strMsg As String
    Dim I As Long

    Set qdf = pdb.CreateQueryDef("", pstrSQL)
    strMsg = vbCr & vbCr & "SQL=" & pstrSQL & vbCr & vbCr
    For I = 0 To qdf.Parameters.Count - 1    ' Each prm In qdf.Parameters
        Set PRM = qdf.Parameters(I)
        strMsg = strMsg & "Param=" & PRM.Name & vbCr
        Debug.Print PRM.Name
        PRM.Value = Eval(PRM.Name)
        Set PRM = Nothing
    Next
    Set rst = qdf.OpenRecordset()
    rst.MoveFirst
    tLookupParam = rst(0)

tCountParam_Exit:
    On Error Resume Next
    Set PRM = Nothing
    rst.Close
    Set rst = Nothing
    qdf.Close
    Set qdf = Nothing
    Exit Function

tCountParam_Err:
    Select Case Err
    Case Else
        MsgBox Err.Description & strMsg, 16, "Error #" & Err.Number & " In tLookupParam()"
    End Select
    Resume tCountParam_Exit
    Resume
End Function

EDIT: just tetrd and failed. replace IsMissing() there with =.

pstrcriteria="", "(1=1)",....
 
Last edited:

isladogs

MVP / VIP
Local time
Today, 05:09
Joined
Jan 14, 2017
Messages
18,221
Thanks again for all you help

I have posted similar remarks to this thread on the MS Access User Voice forum and they have already responded

Will revert on the benefits I found from using large number with examples

Regards

Tried unsuccessfully to find your post on user voice so I could read the MS reply. Do you have a direct link?
 

isladogs

MVP / VIP
Local time
Today, 05:09
Joined
Jan 14, 2017
Messages
18,221
Ah OK Colin, something I probably would never have to use then. :D

That was indeed my point .... :D
However there's no reason why you can't use the module code that arnel included as it dates back to 1996 - pre-Access 97 let alone 2007!

See attached - to import into your own VB project, just remove the .txt suffix I added so I could post it here

EDIT - sorry - hadn't spotted that arnel had already posted the code separately
 

Attachments

  • modTLookUp.bas.txt
    9.6 KB · Views: 123
Last edited:

Users who are viewing this thread

Top Bottom