Search code examples
excelvbasortinguser-defined-types

how to select values from a user defined type?


I've sorted my data into a user defined type where Dy is the date of the measurement, Tm is the time, and pH is the measurement.

Type pHData
    Dy As Date
    Tm As Date
    pH As Single
End Type

Now I would like to sort the data by day (each day has a different number of data points), so that I can find the mean, min, max, etc. I've already made an array of the unique dates, so now I want to select values for each unique date

Something like (sorry the syntax is not perfect, but I hope you get the idea):

For i = LBound(uniqueArr) to UBound(uniqueArr)
  For j = LBound(pHData) to UBound(pHData)
    if pHData.Dy(j)== uniqueArr(i)
       'store in temp array to find mean, etc.' 
    else
        Next i
  Next j

Any suggestions?


Solution

  • If you just want the min, max, mean, then you don't need to store the values in a temp array. See example below. Also, take care to write pHData(j).Dy, not pHData.Dy(j).

    For i = LBound(uniqueArr) to UBound(uniqueArr)
      ' Re-initialise min, max, sum
      phMin = VeryLargeNumber   ' Choice of VeryLargeNumber depends on your application. 
      phMax = - VeryLargeNumber ' Make it beyond the range of possible pH values. 
      phSum = 0
      phCount = 0
      For j = LBound(pHData) to UBound(pHData)
        With phData(j)
        If .Dy== uniqueArr(i)
    
           ' These will be used to calculate the mean later           
           phCount = phCount + 1
           phSum = phSum + .pH  
    
           ' Is this the max or min so far?
           If .pH > phMax Then
             ' This is the largest pH value encountered so far
             phMax = .pH
           ElseIf .pH < phMin Then
             ' This is the smallest pH value encountered so far
             phMin = .pH
           Else
             ' This pH value is neither the largest nor smallest encountered so far.
             ' Do nothing.
           End If
    
        Else
           ' This measurement was not taken on this date. 
           ' Do nothing.
        End If
        End With
    
        phMean = phSum / phCount 
    
        ' Here goes some code to store this date's 
        ' min, max, and mean somewhere convenient.
    
      Next j
    Next i
    

    If you really want to store things in a temp array, the code will be more messy and also slower... Here we go:

    Dim todaysValues() As [Whatever type you need]
    
    For i = LBound(uniqueArr) to UBound(uniqueArr)
    
      ' First, count how many measurements were taken today.
      phCount = 0
      For j = LBound(pHData) to UBound(pHData)
        If phData(j).Dy== uniqueArr(i)
           phCount = phCount + 1
        Else
           ' This measurement was not taken on this date. 
           ' Do nothing.
        End If
      Next j
    
      ' Now resize the temp array and store today's measurements in it.
      ReDim todaysValues(1 To phCount)
      phCount = 0
      For j = LBound(pHData) to UBound(pHData)
        If phData(j).Dy== uniqueArr(i)
           phCount = phCount + 1
           todaysValues(phCount) = phData(j).pH
        Else
           ' This measurement was not taken on this date. 
           ' Do nothing.
        End If
      Next j
    
      ' Here goes some code to calculate statistics (min, max, etc.)
    
    Next i