R
Rick Campbell
The frustrating thing about this message is it is sporadic, i.e., it doesn't
happen on all records.
I'm using a vba module from an O'Reilly book to calculate medians.
The code for the module follows:
======================================
Public Function acbDMedian( _
ByVal strField As String, ByVal strDomain As String, _
Optional ByVal strCriteria As String) As Variant
' Purpose:
' To calculate the median value
' for a field in a table or query.
' In:
' strField: the field
' strDomain: the table or query
' strCriteria: an optional WHERE clause to
' apply to the table or query
' Out:
' Return value: the median, if successful;
' Otherwise, an Error value.
Dim db As DAO.Database
Dim rstDomain As DAO.Recordset
Dim strSQL As String
Dim varMedian As Variant
Dim intFieldType As Integer
Dim intRecords As Integer
Const acbcErrAppTypeError = 3169
On Error GoTo HandleErr
Set db = CurrentDb()
' Initialize return value
varMedian = Null
' Build SQL string for recordset
strSQL = "Select " & strField
strSQL = strSQL & " FROM " & strDomain
' Only use a WHERE clause if one is passed in
If Len(strCriteria) > 0 Then
strSQL = strSQL & " WHERE " & strCriteria
End If
strSQL = strSQL & " ORDER BY " & strField
Set rstDomain = db.OpenRecordset(strSQL, dbOpenSnapshot)
' Check the data type of the median field
intFieldType = rstDomain.Fields(strField).Type
Select Case intFieldType
Case dbByte, dbInteger, dbLong, dbCurrency, dbSingle, dbDouble, dbDate
' Numeric field
If Not rstDomain.EOF Then
rstDomain.MoveLast
intRecords = rstDomain.RecordCount
' Start from the first record
rstDomain.MoveFirst
If (intRecords Mod 2) = 0 Then
' Even number of records
' No middle record, so move to the
' record right before the middle
rstDomain.Move ((intRecords \ 2) - 1)
varMedian = rstDomain.Fields(strField)
' Now move to the next record, the
' one right after the middle
rstDomain.MoveNext
' And average the two values
varMedian = (varMedian + rstDomain.Fields(strField)) / 2
' Make sure you return a date, even when
' averaging two dates
If intFieldType = dbDate And Not IsNull(varMedian) Then
varMedian = CDate(varMedian)
End If
Else
' Odd number or records
' Move to the middle record and return its value
rstDomain.Move ((intRecords \ 2))
varMedian = rstDomain.Fields(strField)
End If
Else
' No records; return Null
varMedian = Null
End If
Case Else
' Non-numeric field; so raise an app error
Err.Raise acbcErrAppTypeError
End Select
acbDMedian = varMedian
ExitHere:
On Error Resume Next
rstDomain.Close
Set rstDomain = Nothing
Exit Function
HandleErr:
' Return an error value
acbDMedian = CVErr(Err.Number)
Resume ExitHere
End Function
========================================
I use the following SQL to produce my results:
========================================
SELECT DISTINCTROW Sales.Style, CityZipLookUp.CityUp AS City,
(Format$(Sales.SoldDate,'mmm yyyy')) AS SDate, Avg(Sales.SoldPrice) AS
Average, CCur(acbDMedian("SoldPrice","Sales","Format$(SoldDate,'mmm yyyy') =
'" & Format$(Sales.SoldDate,'mmm yyyy') & "' And City = '" &
CityZipLookUp.CityUp & "' And [Style] = '" & Sales.Style & "'")) AS Median,
Count(*) AS Sales, Avg(Sales.DaysOnMarket) AS DOM, [Average]/[ListPrice] AS
[SP/LP], Avg(Sales.ListPrice) AS ListPrice
FROM Sales INNER JOIN CityZipLookUp ON Sales.ZipCode = CityZipLookUp.ZipCode
GROUP BY Sales.Style, CityZipLookUp.CityUp, CityZipLookUp.CityUp,
Format$(Sales.SoldDate,'mmm yyyy'),
Year(Sales.SoldDate)*12+DatePart('m',Sales.SoldDate)-1
HAVING (((CityZipLookUp.CityUp)="Nestor"))
ORDER BY Sales.Style DESC ,
Year(Sales.SoldDate)*12+DatePart('m',Sales.SoldDate)-1 DESC;
===========================================
I've checked the data and it looks fine. Nothing pops out to say "fix me!"
The error message so far is consistent, it happens in the same months. I
could understand if the module ALWAYS returned an #error, but not just
sometimes.
Anyone have a clue about this?
TIA
Rick
happen on all records.
I'm using a vba module from an O'Reilly book to calculate medians.
The code for the module follows:
======================================
Public Function acbDMedian( _
ByVal strField As String, ByVal strDomain As String, _
Optional ByVal strCriteria As String) As Variant
' Purpose:
' To calculate the median value
' for a field in a table or query.
' In:
' strField: the field
' strDomain: the table or query
' strCriteria: an optional WHERE clause to
' apply to the table or query
' Out:
' Return value: the median, if successful;
' Otherwise, an Error value.
Dim db As DAO.Database
Dim rstDomain As DAO.Recordset
Dim strSQL As String
Dim varMedian As Variant
Dim intFieldType As Integer
Dim intRecords As Integer
Const acbcErrAppTypeError = 3169
On Error GoTo HandleErr
Set db = CurrentDb()
' Initialize return value
varMedian = Null
' Build SQL string for recordset
strSQL = "Select " & strField
strSQL = strSQL & " FROM " & strDomain
' Only use a WHERE clause if one is passed in
If Len(strCriteria) > 0 Then
strSQL = strSQL & " WHERE " & strCriteria
End If
strSQL = strSQL & " ORDER BY " & strField
Set rstDomain = db.OpenRecordset(strSQL, dbOpenSnapshot)
' Check the data type of the median field
intFieldType = rstDomain.Fields(strField).Type
Select Case intFieldType
Case dbByte, dbInteger, dbLong, dbCurrency, dbSingle, dbDouble, dbDate
' Numeric field
If Not rstDomain.EOF Then
rstDomain.MoveLast
intRecords = rstDomain.RecordCount
' Start from the first record
rstDomain.MoveFirst
If (intRecords Mod 2) = 0 Then
' Even number of records
' No middle record, so move to the
' record right before the middle
rstDomain.Move ((intRecords \ 2) - 1)
varMedian = rstDomain.Fields(strField)
' Now move to the next record, the
' one right after the middle
rstDomain.MoveNext
' And average the two values
varMedian = (varMedian + rstDomain.Fields(strField)) / 2
' Make sure you return a date, even when
' averaging two dates
If intFieldType = dbDate And Not IsNull(varMedian) Then
varMedian = CDate(varMedian)
End If
Else
' Odd number or records
' Move to the middle record and return its value
rstDomain.Move ((intRecords \ 2))
varMedian = rstDomain.Fields(strField)
End If
Else
' No records; return Null
varMedian = Null
End If
Case Else
' Non-numeric field; so raise an app error
Err.Raise acbcErrAppTypeError
End Select
acbDMedian = varMedian
ExitHere:
On Error Resume Next
rstDomain.Close
Set rstDomain = Nothing
Exit Function
HandleErr:
' Return an error value
acbDMedian = CVErr(Err.Number)
Resume ExitHere
End Function
========================================
I use the following SQL to produce my results:
========================================
SELECT DISTINCTROW Sales.Style, CityZipLookUp.CityUp AS City,
(Format$(Sales.SoldDate,'mmm yyyy')) AS SDate, Avg(Sales.SoldPrice) AS
Average, CCur(acbDMedian("SoldPrice","Sales","Format$(SoldDate,'mmm yyyy') =
'" & Format$(Sales.SoldDate,'mmm yyyy') & "' And City = '" &
CityZipLookUp.CityUp & "' And [Style] = '" & Sales.Style & "'")) AS Median,
Count(*) AS Sales, Avg(Sales.DaysOnMarket) AS DOM, [Average]/[ListPrice] AS
[SP/LP], Avg(Sales.ListPrice) AS ListPrice
FROM Sales INNER JOIN CityZipLookUp ON Sales.ZipCode = CityZipLookUp.ZipCode
GROUP BY Sales.Style, CityZipLookUp.CityUp, CityZipLookUp.CityUp,
Format$(Sales.SoldDate,'mmm yyyy'),
Year(Sales.SoldDate)*12+DatePart('m',Sales.SoldDate)-1
HAVING (((CityZipLookUp.CityUp)="Nestor"))
ORDER BY Sales.Style DESC ,
Year(Sales.SoldDate)*12+DatePart('m',Sales.SoldDate)-1 DESC;
===========================================
I've checked the data and it looks fine. Nothing pops out to say "fix me!"
The error message so far is consistent, it happens in the same months. I
could understand if the module ALWAYS returned an #error, but not just
sometimes.
Anyone have a clue about this?
TIA
Rick