<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Sorting Arrays of User Defined Types</title>
	<atom:link href="http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/</link>
	<description>Daily posts of Excel tips…and other stuff</description>
	<lastBuildDate>Wed, 08 Feb 2012 12:03:16 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
	<item>
		<title>By: GulDukat</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19795</link>
		<dc:creator>GulDukat</dc:creator>
		<pubDate>Wed, 31 May 2006 15:32:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19795</guid>
		<description>&lt;p&gt;Dick,&lt;/p&gt;
&lt;p&gt;your code is great. It has inspired many ideas in me. Thanks a lot for publishing.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Dick,</p>
<p>your code is great. It has inspired many ideas in me. Thanks a lot for publishing.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jamie Collins</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19039</link>
		<dc:creator>Jamie Collins</dc:creator>
		<pubDate>Wed, 01 Mar 2006 09:53:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19039</guid>
		<description>&lt;p&gt;Tushar,&lt;br&gt;
I need no good excuse to use recordsets, collections, and APIs :) BTW the RtlMoveMemory is for my current (ultimate?) approach to the classic COM circular reference problem i.e. parent holds a reference to the child and child needs to hold a reference to the parent (how do you do it? I find this an excellent interview question).&lt;/p&gt;
&lt;p&gt;I think your latter comments are a miniscule amount disingenuous (or tongue in cheek), otherwise you would use a Variant for every variable in your code, wouldn&#039;t you? &lt;/p&gt;
&lt;p&gt;In my line of business I have encountered few situations where a &#039;real&#039; data type is required, yet I often see Single and Double used rather than the more appropriate Decimal, which was implemented in VBA as a Variant. I&#039;d use fixed length string (Private ISBN As String * 10) as variables if they could be used as parameters to or return values from functions (Function GetIsbn() As String * 10). I&#039;m not sure I could live without integers (Long).&lt;/p&gt;
&lt;p&gt;I&#039;m guessing that for you a Variant makes up for the intrinsic types&#039; woeful inadequacies because you can test it for IsMissing. I would agree that VBA6 is losing its appeal in these .NET times e.g. we have nullable types in C# now (http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx). But again, there must be some appeal to you for the status quo otherwise you would do all your development using VSTO, wouldn&#039;t you?&lt;/p&gt;
&lt;p&gt;Back in VBA6, I find using an ADO recordset handy because I can leverage the nullabled data types SQLs need to support but I find I need to retain my Collections for the connivance of supporting enumerable collection classes. And this is where I came in.&lt;/p&gt;
&lt;p&gt;Jamie.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Tushar,<br />
I need no good excuse to use recordsets, collections, and APIs <img src='http://www.dailydoseofexcel.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  BTW the RtlMoveMemory is for my current (ultimate?) approach to the classic COM circular reference problem i.e. parent holds a reference to the child and child needs to hold a reference to the parent (how do you do it? I find this an excellent interview question).</p>
<p>I think your latter comments are a miniscule amount disingenuous (or tongue in cheek), otherwise you would use a Variant for every variable in your code, wouldn&#8217;t you? </p>
<p>In my line of business I have encountered few situations where a &#8216;real&#8217; data type is required, yet I often see Single and Double used rather than the more appropriate Decimal, which was implemented in VBA as a Variant. I&#8217;d use fixed length string (Private ISBN As String * 10) as variables if they could be used as parameters to or return values from functions (Function GetIsbn() As String * 10). I&#8217;m not sure I could live without integers (Long).</p>
<p>I&#8217;m guessing that for you a Variant makes up for the intrinsic types&#8217; woeful inadequacies because you can test it for IsMissing. I would agree that VBA6 is losing its appeal in these .NET times e.g. we have nullable types in C# now (<a href="http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx" rel="nofollow">http://blogs.msdn.com/somasegar/archive/2005/08/11/450640.aspx</a>). But again, there must be some appeal to you for the status quo otherwise you would do all your development using VSTO, wouldn&#8217;t you?</p>
<p>Back in VBA6, I find using an ADO recordset handy because I can leverage the nullabled data types SQLs need to support but I find I need to retain my Collections for the connivance of supporting enumerable collection classes. And this is where I came in.</p>
<p>Jamie.</p>
<p></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Stephen Bullen</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19035</link>
		<dc:creator>Stephen Bullen</dc:creator>
		<pubDate>Tue, 28 Feb 2006 19:47:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19035</guid>
		<description>&lt;p&gt;Jamie, &lt;/p&gt;
&lt;p&gt;In PED, I did indeed use an Interface class, called ISortableObject, which contained a single property called SortKey, which was typed as a Variant. So I got the compile-time knowledge that my classes could be sorted by a generic routine, but I didn&#039;t dirty the interface and sort routine by having different data types to sort on.&lt;/p&gt;
&lt;p&gt;Like most things in Excel (and something we tried to emphasis in PED), there is no &quot;One True Way&quot; of doing anything. Every method will be better or worse depending on the criteria used to evaluate it, and that criteria is most often defined by the problem space, not the developer.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Jamie, </p>
<p>In PED, I did indeed use an Interface class, called ISortableObject, which contained a single property called SortKey, which was typed as a Variant. So I got the compile-time knowledge that my classes could be sorted by a generic routine, but I didn&#8217;t dirty the interface and sort routine by having different data types to sort on.</p>
<p>Like most things in Excel (and something we tried to emphasis in PED), there is no &#8220;One True Way&#8221; of doing anything. Every method will be better or worse depending on the criteria used to evaluate it, and that criteria is most often defined by the problem space, not the developer.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tushar Mehta</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19028</link>
		<dc:creator>Tushar Mehta</dc:creator>
		<pubDate>Tue, 28 Feb 2006 15:52:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19028</guid>
		<description>&lt;p&gt;Jamie,&lt;/p&gt;
&lt;p&gt;If you think one late bound reference to one method that is anyway enforced by the system at run time is enough justification to use recordsets, collections, and APIs to move memory around, fine.&lt;/p&gt;
&lt;p&gt;Too many have a knee-jerk reaction to things like variants and late binding.  They miss out on not only the elegant simplicity but *also* the raw power embedded in those capabilities.&lt;/p&gt;
&lt;p&gt;And, BTW, dimensioning variables as integers, reals, or strings is only a miniscule step better than declaring them as variants.  Those constructs, more in tune with the demands of the programming environments from the late &#039;60s to mid &#039;80s, are woefully inadequate for modern computing requirements.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Jamie,</p>
<p>If you think one late bound reference to one method that is anyway enforced by the system at run time is enough justification to use recordsets, collections, and APIs to move memory around, fine.</p>
<p>Too many have a knee-jerk reaction to things like variants and late binding.  They miss out on not only the elegant simplicity but *also* the raw power embedded in those capabilities.</p>
<p>And, BTW, dimensioning variables as integers, reals, or strings is only a miniscule step better than declaring them as variants.  Those constructs, more in tune with the demands of the programming environments from the late &#8217;60s to mid &#8217;80s, are woefully inadequate for modern computing requirements.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jamie Collins</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19027</link>
		<dc:creator>Jamie Collins</dc:creator>
		<pubDate>Tue, 28 Feb 2006 14:53:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19027</guid>
		<description>&lt;p&gt;Stephen,&lt;br&gt;
Erm, I don&#039;t have your book to hand :) Remind me: what criteria did you apply in deciding not to go the interface route? We don&#039;t want to encourge the &#039;Stephen Bullen does it so it must be OK&#039; attitude, do we ;)?&lt;/p&gt;
&lt;p&gt;I suspect it came down to the fact that the interface would be very limited; it would not include any code to implement the sort, of course. &lt;/p&gt;
&lt;p&gt;I still think it is worth using an interface class rather than assuming a coder will use the class/implementation correctly. I prefer the type library to indicate usage rather than the written documentation. And I think avoiding late binding is a worthy goal. &lt;/p&gt;
&lt;p&gt;Just this week I defined this &#039;zero code&#039; interface class:&lt;/p&gt;
&lt;p&gt;&#039; Class module: IColumnParent&lt;br&gt;
Option Explicit&lt;br&gt;
&#039; Class module: IColumnParent (end)&lt;/p&gt;
&lt;p&gt;&#039; Included in class module: CColumn&lt;br&gt;
Friend Sub SetParent(ByVal Ptr As Long)&lt;br&gt;
m_pParent = Ptr&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Private Property Get Parent() As IColumnParent&lt;br&gt;
If m_pParent = 0 Then&lt;br&gt;
  Exit Property&lt;br&gt;
End If&lt;br&gt;
Dim tmp As IColumnParent&lt;br&gt;
CopyMemory tmp, Ptr, 4&lt;br&gt;
Set Parent = tmp&lt;br&gt;
CopyMemory tmp, 0&amp;, 4&lt;br&gt;
End Property&lt;br&gt;
&#039; Included in class module: CColumn (end)&lt;/p&gt;
&lt;p&gt;&#039; Included in implementation class e.g. CTable&lt;br&gt;
Implements IColumnParent&lt;br&gt;
Private m_Columns As CColumns&lt;/p&gt;
&lt;p&gt;Private Sub Class_Initialize()&lt;br&gt;
Set m_Columns = New CColumns&lt;br&gt;
m_Columns.Init ObjPtr(Me)&lt;br&gt;
&#039; Included in implementation class e.g. CTable (end)&lt;/p&gt;
&lt;p&gt;&#039; Included in implementation class&#039;s collection class e.g. CTables&lt;br&gt;
Friend Sub Init(ByVal Ptr As Long)&lt;br&gt;
m_pParent = Ptr&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Public Function Add(ByVal TableName As String) As CTable&lt;br&gt;
Dim oTable As CTable&lt;br&gt;
Set oTable = New CTable&lt;br&gt;
oTable.SetParentSchema m_pParentSchema&lt;br&gt;
...&lt;br&gt;
End Function&lt;br&gt;
&#039; Included in implementation class&#039;s collection class e.g. CTables (end)&lt;/p&gt;
&lt;p&gt;The idea is that only certain classes will be the parent of a Column, say a Table, a View or a Procedure; to do so those classes must implement the &#039;zero code&#039; IColumnParent class. The alternative to this was for CColumn to have three properties: ParentTable, ParentView, and ParentProcedure, only one of which could be non-null, then the associated maintenance e.g. what if a later class could also be the parent?&lt;/p&gt;
&lt;p&gt;Although the zero code interface seems strange it&#039;s my current preferred solution. My next step is to examine the parents of CColumn for common functionality which should perhaps be defined in IColumnParent. &lt;/p&gt;
&lt;p&gt;Jamie.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Stephen,<br />
Erm, I don&#8217;t have your book to hand <img src='http://www.dailydoseofexcel.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Remind me: what criteria did you apply in deciding not to go the interface route? We don&#8217;t want to encourge the &#8216;Stephen Bullen does it so it must be OK&#8217; attitude, do we <img src='http://www.dailydoseofexcel.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ?</p>
<p>I suspect it came down to the fact that the interface would be very limited; it would not include any code to implement the sort, of course. </p>
<p>I still think it is worth using an interface class rather than assuming a coder will use the class/implementation correctly. I prefer the type library to indicate usage rather than the written documentation. And I think avoiding late binding is a worthy goal. </p>
<p>Just this week I defined this &#8216;zero code&#8217; interface class:</p>
<p>&#8216; Class module: IColumnParent<br />
Option Explicit<br />
&#8216; Class module: IColumnParent (end)</p>
<p>&#8216; Included in class module: CColumn<br />
Friend Sub SetParent(ByVal Ptr As Long)<br />
m_pParent = Ptr<br />
End Sub</p>
<p>Private Property Get Parent() As IColumnParent<br />
If m_pParent = 0 Then<br />
  Exit Property<br />
End If<br />
Dim tmp As IColumnParent<br />
CopyMemory tmp, Ptr, 4<br />
Set Parent = tmp<br />
CopyMemory tmp, 0&amp;, 4<br />
End Property<br />
&#8216; Included in class module: CColumn (end)</p>
<p>&#8216; Included in implementation class e.g. CTable<br />
Implements IColumnParent<br />
Private m_Columns As CColumns</p>
<p>Private Sub Class_Initialize()<br />
Set m_Columns = New CColumns<br />
m_Columns.Init ObjPtr(Me)<br />
&#8216; Included in implementation class e.g. CTable (end)</p>
<p>&#8216; Included in implementation class&#8217;s collection class e.g. CTables<br />
Friend Sub Init(ByVal Ptr As Long)<br />
m_pParent = Ptr<br />
End Sub</p>
<p>Public Function Add(ByVal TableName As String) As CTable<br />
Dim oTable As CTable<br />
Set oTable = New CTable<br />
oTable.SetParentSchema m_pParentSchema<br />
&#8230;<br />
End Function<br />
&#8216; Included in implementation class&#8217;s collection class e.g. CTables (end)</p>
<p>The idea is that only certain classes will be the parent of a Column, say a Table, a View or a Procedure; to do so those classes must implement the &#8216;zero code&#8217; IColumnParent class. The alternative to this was for CColumn to have three properties: ParentTable, ParentView, and ParentProcedure, only one of which could be non-null, then the associated maintenance e.g. what if a later class could also be the parent?</p>
<p>Although the zero code interface seems strange it&#8217;s my current preferred solution. My next step is to examine the parents of CColumn for common functionality which should perhaps be defined in IColumnParent. </p>
<p>Jamie.</p>
<p></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Stephen Bullen</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19026</link>
		<dc:creator>Stephen Bullen</dc:creator>
		<pubDate>Tue, 28 Feb 2006 10:29:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19026</guid>
		<description>&lt;p&gt;Jamie, When writing about an ISortableObject interface in Chapter 11 of Professional Excel Development, I decided to just use a Variant SortKey and assume the reader would only use it to sort objects that had sort keys of similar data types.&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Jamie, When writing about an ISortableObject interface in Chapter 11 of Professional Excel Development, I decided to just use a Variant SortKey and assume the reader would only use it to sort objects that had sort keys of similar data types.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jamie Collins</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19025</link>
		<dc:creator>Jamie Collins</dc:creator>
		<pubDate>Tue, 28 Feb 2006 09:53:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19025</guid>
		<description>&lt;p&gt;Speaking of doing things &#039;correctly&#039;, like Tushar I too had the idea of making the UDF a class but then to have a collection class to organize the instances and a parent class which could sort its children, a bit like this:&lt;/p&gt;
&lt;p&gt;&#039; Class module: CParent&lt;br&gt;
Option Explicit&lt;/p&gt;
&lt;p&gt;Public Enum InfoTypeEnum&lt;br&gt;
  InfoTypeGood&lt;br&gt;
  InfoTypeBad&lt;br&gt;
  InfoTypeUgly&lt;br&gt;
End Enum&lt;/p&gt;
&lt;p&gt;Private m_MyInfos As CMyInfos&lt;/p&gt;
&lt;p&gt;Private Sub Class_Initialize()&lt;br&gt;
Set m_MyInfos = New CMyInfos&lt;br&gt;
m_MyInfos.SetParent ObjPtr(Me)&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Public Function EnumerateInfoType(ByVal infoType As InfoTypeEnum)&lt;br&gt;
Select Case infoType&lt;br&gt;
  Case InfoTypeGood&lt;br&gt;
    EnumerateInfoType = &quot;Good&quot;&lt;br&gt;
  Case InfoTypeBad&lt;br&gt;
    EnumerateInfoType = &quot;Bad&quot;&lt;br&gt;
  Case InfoTypeUgly&lt;br&gt;
    EnumerateInfoType = &quot;Ugly&quot;&lt;br&gt;
End Select&lt;br&gt;
End Function&lt;/p&gt;
&lt;p&gt;Public Property Get MyInfos() As CMyInfos&lt;br&gt;
Set MyInfos = m_MyInfos&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Public Property Get Output() As String&lt;br&gt;
Dim sReturn As String&lt;br&gt;
Dim myInfo As CMyInfo&lt;br&gt;
For Each myInfo In m_MyInfos&lt;br&gt;
  sReturn = sReturn &amp; myInfo.Output &amp; vbCrLf&lt;br&gt;
Next&lt;br&gt;
sReturn = Left$(sReturn, Len(sReturn) - Len(vbCrLf))&lt;br&gt;
Output = sReturn&lt;br&gt;
End Property&lt;br&gt;
&#039; Class module: CParent (end)&lt;/p&gt;
&lt;p&gt;&#039; Class module: CMyInfos&lt;br&gt;
Option Explicit&lt;/p&gt;
&lt;p&gt;Private m_rsMyInfos As ADODB.Recordset&lt;br&gt;
Private m_colMyInfos As Collection&lt;br&gt;
Private m_pParent As Long&lt;/p&gt;
&lt;p&gt;Public Property Get Item(ByVal Index As Variant) As CMyInfo&lt;br&gt;
&#039; Attribute Item.VB_UserMemId = 0  &#039; uncomment in text editor&lt;br&gt;
Set Item = m_colMyInfos.Item(Index)&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Public Property Get NewEnum() As IUnknown&lt;br&gt;
&#039; Attribute NewEnum.VB_UserMemId = -4      &#039; uncomment in text editor&lt;br&gt;
&#039; Attribute NewEnum.VB_MemberFlags = &quot;40?  &#039; uncomment in text editor&lt;br&gt;
    Set NewEnum = m_colMyInfos.[_NewEnum]&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Friend Sub SetParent(ByVal Ptr As Long)&lt;br&gt;
m_pParent = Ptr&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Public Function Add( _&lt;br&gt;
  ByVal Name As String, _&lt;br&gt;
  ByVal StartDate As Date, _&lt;br&gt;
  ByVal infoType As InfoTypeEnum _&lt;br&gt;
) As CMyInfo&lt;/p&gt;
&lt;p&gt;Dim myInfo As CMyInfo&lt;/p&gt;
&lt;p&gt;Set myInfo = New CMyInfo&lt;br&gt;
m_colMyInfos.Add myInfo, CStr(ObjPtr(myInfo))&lt;/p&gt;
&lt;p&gt;With myInfo&lt;br&gt;
  .Init Name, StartDate, infoType&lt;br&gt;
  .SetParent m_pParent&lt;br&gt;
End With&lt;/p&gt;
&lt;p&gt;Set Add = myInfo&lt;br&gt;
End Function&lt;/p&gt;
&lt;p&gt;Public Property Get Count() As Long&lt;br&gt;
Count = m_colMyInfos.Count&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Friend Function Remove(ByVal Index As Variant) As Boolean&lt;br&gt;
On Error Resume Next&lt;br&gt;
m_colMyInfos.Remove Index&lt;br&gt;
Remove = (Err.Number = 0)&lt;br&gt;
On Error GoTo 0&lt;br&gt;
End Function&lt;/p&gt;
&lt;p&gt;Private Sub Class_Initialize()&lt;br&gt;
Set m_colMyInfos = New Collection&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Friend Function Init( _&lt;br&gt;
    ByVal Ptr As Long _&lt;br&gt;
) As Boolean&lt;br&gt;
m_pParent = Ptr&lt;br&gt;
Init = True&lt;br&gt;
End Function&lt;/p&gt;
&lt;p&gt;Private Sub Class_Terminate()&lt;br&gt;
Dim myInfo As CMyInfo&lt;br&gt;
For Each myInfo In m_colMyInfos&lt;br&gt;
  myInfo.SetParent 0&lt;br&gt;
Next&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Public Sub Sort()&lt;/p&gt;
&lt;p&gt;Dim memberCount As Long&lt;br&gt;
memberCount = m_colMyInfos.Count&lt;br&gt;
If memberCount &lt; 2 Then  &#039; less than two&lt;br&gt;
  Exit Sub&lt;br&gt;
End If&lt;/p&gt;
&lt;p&gt;Set m_rsMyInfos = New ADODB.Recordset&lt;br&gt;
With m_rsMyInfos&lt;br&gt;
  .Fields.Append &quot;Name&quot;, adVarChar, 35&lt;br&gt;
  .Fields.Append &quot;StartDate&quot;, adDate&lt;br&gt;
  .Fields.Append &quot;InfoType&quot;, adInteger&lt;br&gt;
  .Fields.Append &quot;CInfo&quot;, adIUnknown&lt;br&gt;
  .Open&lt;/p&gt;
&lt;p&gt;  Dim myInfo As CMyInfo&lt;br&gt;
  Dim row As Long&lt;/p&gt;
&lt;p&gt;  For row = 1 To memberCount&lt;br&gt;
    Set myInfo = m_colMyInfos(row)&lt;br&gt;
    .AddNew&lt;br&gt;
    .Fields(&quot;Name&quot;).Value = myInfo.Name&lt;br&gt;
    .Fields(&quot;StartDate&quot;).Value = myInfo.StartDate&lt;br&gt;
    .Fields(&quot;InfoType&quot;).Value = myInfo.infoType&lt;br&gt;
    .Fields(&quot;CInfo&quot;).Value = myInfo&lt;br&gt;
  Next&lt;/p&gt;
&lt;p&gt;  .Sort = &quot;Name, StartDate, InfoType&quot;&lt;/p&gt;
&lt;p&gt;  Dim colMyInfos As Collection&lt;br&gt;
  Set colMyInfos = New Collection&lt;/p&gt;
&lt;p&gt;  .MoveFirst&lt;br&gt;
  For row = 1 To memberCount&lt;br&gt;
    Set myInfo = .Fields(&quot;CInfo&quot;).Value&lt;br&gt;
    colMyInfos.Add myInfo, CStr(ObjPtr(myInfo))&lt;br&gt;
    .MoveNext&lt;br&gt;
  Next&lt;/p&gt;
&lt;p&gt;  Set m_colMyInfos = colMyInfos&lt;/p&gt;
&lt;p&gt;End With&lt;/p&gt;
&lt;p&gt;End Sub&lt;br&gt;
&#039; Class module: CMyInfos (end)&lt;/p&gt;
&lt;p&gt;&#039; Class module: CMyInfo&lt;br&gt;
Option Explicit&lt;/p&gt;
&lt;p&gt;Private m_Name As String&lt;br&gt;
Private m_StartDate As Date&lt;br&gt;
Private m_InfoType As InfoTypeEnum&lt;/p&gt;
&lt;p&gt;Private m_pParent As Long&lt;br&gt;
Private Declare Sub CopyMemory Lib &quot;kernel32? Alias &quot;RtlMoveMemory&quot; _&lt;br&gt;
    (pDst As Any, pSrc As Any, ByVal ByteLen As Long)&lt;/p&gt;
&lt;p&gt;Friend Sub SetParent(ByVal Ptr As Long)&lt;br&gt;
m_pParent = Ptr&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Private Function CParentFromPtr(ByVal Ptr As Long) As CParent&lt;br&gt;
Dim tmp As CParent&lt;br&gt;
CopyMemory tmp, Ptr, 4&lt;br&gt;
Set CParentFromPtr = tmp&lt;br&gt;
CopyMemory tmp, 0&amp;, 4&lt;br&gt;
End Function&lt;/p&gt;
&lt;p&gt;Public Property Get Parent() As CParent&lt;br&gt;
If m_pParent = 0 Then&lt;br&gt;
  Exit Property&lt;br&gt;
End If&lt;br&gt;
Set Parent = CParentFromPtr(m_pParent)&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Friend Sub Init( _&lt;br&gt;
  ByVal Name As String, _&lt;br&gt;
  ByVal StartDate As Date, _&lt;br&gt;
  ByVal infoType As InfoTypeEnum _&lt;br&gt;
)&lt;br&gt;
m_Name = Name&lt;br&gt;
m_StartDate = StartDate&lt;br&gt;
m_InfoType = infoType&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Public Property Get Name() As String&lt;br&gt;
Name = m_Name&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Public Property Get StartDate() As Date&lt;br&gt;
StartDate = m_StartDate&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Public Property Get infoType() As InfoTypeEnum&lt;br&gt;
infoType = m_InfoType&lt;br&gt;
End Property&lt;/p&gt;
&lt;p&gt;Public Property Get Output() As String&lt;br&gt;
Output = _&lt;br&gt;
    m_Name &amp; vbTab &amp; _&lt;br&gt;
    Format$(m_StartDate, &quot;yyyy-mm-dd&quot;) &amp; vbTab &amp; _&lt;br&gt;
    Parent.EnumerateInfoType(m_InfoType)&lt;br&gt;
End Property&lt;br&gt;
&#039; Class module: CMyInfos (end)&lt;/p&gt;
&lt;p&gt;&#039; Example usage&lt;br&gt;
Sub UseClasses()&lt;/p&gt;
&lt;p&gt;    Dim Parent As CParent&lt;br&gt;
    Set Parent = New CParent&lt;br&gt;
    With Parent&lt;/p&gt;
&lt;p&gt;      Dim i As Long&lt;br&gt;
      For i = 0 To 4&lt;br&gt;
          .MyInfos.Add _&lt;br&gt;
              Array(&quot;Joe&quot;, &quot;Bob&quot;, &quot;Bob&quot;, &quot;Joe&quot;, &quot;Joe&quot;)(i), _&lt;br&gt;
              Array(#1/1/2006#, #2/1/2006#, #1/15/2006#, #6/30/2005#, #1/8/2006#)(i), _&lt;br&gt;
              Array(2, 1, 1, 2, 1)(i)&lt;br&gt;
      Next i&lt;br&gt;
      Debug.Print .Output&lt;br&gt;
      Debug.Print&lt;br&gt;
      .MyInfos.Sort&lt;br&gt;
      Debug.Print .Output&lt;br&gt;
    End With&lt;/p&gt;
&lt;p&gt;End Sub&lt;br&gt;
&#039; Example usage (end)&lt;/p&gt;
&lt;p&gt;But then I thought, maybe that&#039;s too much for a blog.&lt;/p&gt;
&lt;p&gt;Jamie.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Speaking of doing things &#8216;correctly&#8217;, like Tushar I too had the idea of making the UDF a class but then to have a collection class to organize the instances and a parent class which could sort its children, a bit like this:</p>
<p>&#8216; Class module: CParent<br />
Option Explicit</p>
<p>Public Enum InfoTypeEnum<br />
  InfoTypeGood<br />
  InfoTypeBad<br />
  InfoTypeUgly<br />
End Enum</p>
<p>Private m_MyInfos As CMyInfos</p>
<p>Private Sub Class_Initialize()<br />
Set m_MyInfos = New CMyInfos<br />
m_MyInfos.SetParent ObjPtr(Me)<br />
End Sub</p>
<p>Public Function EnumerateInfoType(ByVal infoType As InfoTypeEnum)<br />
Select Case infoType<br />
  Case InfoTypeGood<br />
    EnumerateInfoType = &#8220;Good&#8221;<br />
  Case InfoTypeBad<br />
    EnumerateInfoType = &#8220;Bad&#8221;<br />
  Case InfoTypeUgly<br />
    EnumerateInfoType = &#8220;Ugly&#8221;<br />
End Select<br />
End Function</p>
<p>Public Property Get MyInfos() As CMyInfos<br />
Set MyInfos = m_MyInfos<br />
End Property</p>
<p>Public Property Get Output() As String<br />
Dim sReturn As String<br />
Dim myInfo As CMyInfo<br />
For Each myInfo In m_MyInfos<br />
  sReturn = sReturn &amp; myInfo.Output &amp; vbCrLf<br />
Next<br />
sReturn = Left$(sReturn, Len(sReturn) &#8211; Len(vbCrLf))<br />
Output = sReturn<br />
End Property<br />
&#8216; Class module: CParent (end)</p>
<p>&#8216; Class module: CMyInfos<br />
Option Explicit</p>
<p>Private m_rsMyInfos As ADODB.Recordset<br />
Private m_colMyInfos As Collection<br />
Private m_pParent As Long</p>
<p>Public Property Get Item(ByVal Index As Variant) As CMyInfo<br />
&#8216; Attribute Item.VB_UserMemId = 0  &#8216; uncomment in text editor<br />
Set Item = m_colMyInfos.Item(Index)<br />
End Property</p>
<p>Public Property Get NewEnum() As IUnknown<br />
&#8216; Attribute NewEnum.VB_UserMemId = -4      &#8216; uncomment in text editor<br />
&#8216; Attribute NewEnum.VB_MemberFlags = &#8220;40?  &#8216; uncomment in text editor<br />
    Set NewEnum = m_colMyInfos.[_NewEnum]<br />
End Property</p>
<p>Friend Sub SetParent(ByVal Ptr As Long)<br />
m_pParent = Ptr<br />
End Sub</p>
<p>Public Function Add( _<br />
  ByVal Name As String, _<br />
  ByVal StartDate As Date, _<br />
  ByVal infoType As InfoTypeEnum _<br />
) As CMyInfo</p>
<p>Dim myInfo As CMyInfo</p>
<p>Set myInfo = New CMyInfo<br />
m_colMyInfos.Add myInfo, CStr(ObjPtr(myInfo))</p>
<p>With myInfo<br />
  .Init Name, StartDate, infoType<br />
  .SetParent m_pParent<br />
End With</p>
<p>Set Add = myInfo<br />
End Function</p>
<p>Public Property Get Count() As Long<br />
Count = m_colMyInfos.Count<br />
End Property</p>
<p>Friend Function Remove(ByVal Index As Variant) As Boolean<br />
On Error Resume Next<br />
m_colMyInfos.Remove Index<br />
Remove = (Err.Number = 0)<br />
On Error GoTo 0<br />
End Function</p>
<p>Private Sub Class_Initialize()<br />
Set m_colMyInfos = New Collection<br />
End Sub</p>
<p>Friend Function Init( _<br />
    ByVal Ptr As Long _<br />
) As Boolean<br />
m_pParent = Ptr<br />
Init = True<br />
End Function</p>
<p>Private Sub Class_Terminate()<br />
Dim myInfo As CMyInfo<br />
For Each myInfo In m_colMyInfos<br />
  myInfo.SetParent 0<br />
Next<br />
End Sub</p>
<p>Public Sub Sort()</p>
<p>Dim memberCount As Long<br />
memberCount = m_colMyInfos.Count<br />
If memberCount &lt; 2 Then  &#8216; less than two<br />
  Exit Sub<br />
End If</p>
<p>Set m_rsMyInfos = New ADODB.Recordset<br />
With m_rsMyInfos<br />
  .Fields.Append &#8220;Name&#8221;, adVarChar, 35<br />
  .Fields.Append &#8220;StartDate&#8221;, adDate<br />
  .Fields.Append &#8220;InfoType&#8221;, adInteger<br />
  .Fields.Append &#8220;CInfo&#8221;, adIUnknown<br />
  .Open</p>
<p>  Dim myInfo As CMyInfo<br />
  Dim row As Long</p>
<p>  For row = 1 To memberCount<br />
    Set myInfo = m_colMyInfos(row)<br />
    .AddNew<br />
    .Fields(&#8220;Name&#8221;).Value = myInfo.Name<br />
    .Fields(&#8220;StartDate&#8221;).Value = myInfo.StartDate<br />
    .Fields(&#8220;InfoType&#8221;).Value = myInfo.infoType<br />
    .Fields(&#8220;CInfo&#8221;).Value = myInfo<br />
  Next</p>
<p>  .Sort = &#8220;Name, StartDate, InfoType&#8221;</p>
<p>  Dim colMyInfos As Collection<br />
  Set colMyInfos = New Collection</p>
<p>  .MoveFirst<br />
  For row = 1 To memberCount<br />
    Set myInfo = .Fields(&#8220;CInfo&#8221;).Value<br />
    colMyInfos.Add myInfo, CStr(ObjPtr(myInfo))<br />
    .MoveNext<br />
  Next</p>
<p>  Set m_colMyInfos = colMyInfos</p>
<p>End With</p>
<p>End Sub<br />
&#8216; Class module: CMyInfos (end)</p>
<p>&#8216; Class module: CMyInfo<br />
Option Explicit</p>
<p>Private m_Name As String<br />
Private m_StartDate As Date<br />
Private m_InfoType As InfoTypeEnum</p>
<p>Private m_pParent As Long<br />
Private Declare Sub CopyMemory Lib &#8220;kernel32? Alias &#8220;RtlMoveMemory&#8221; _<br />
    (pDst As Any, pSrc As Any, ByVal ByteLen As Long)</p>
<p>Friend Sub SetParent(ByVal Ptr As Long)<br />
m_pParent = Ptr<br />
End Sub</p>
<p>Private Function CParentFromPtr(ByVal Ptr As Long) As CParent<br />
Dim tmp As CParent<br />
CopyMemory tmp, Ptr, 4<br />
Set CParentFromPtr = tmp<br />
CopyMemory tmp, 0&amp;, 4<br />
End Function</p>
<p>Public Property Get Parent() As CParent<br />
If m_pParent = 0 Then<br />
  Exit Property<br />
End If<br />
Set Parent = CParentFromPtr(m_pParent)<br />
End Property</p>
<p>Friend Sub Init( _<br />
  ByVal Name As String, _<br />
  ByVal StartDate As Date, _<br />
  ByVal infoType As InfoTypeEnum _<br />
)<br />
m_Name = Name<br />
m_StartDate = StartDate<br />
m_InfoType = infoType<br />
End Sub</p>
<p>Public Property Get Name() As String<br />
Name = m_Name<br />
End Property</p>
<p>Public Property Get StartDate() As Date<br />
StartDate = m_StartDate<br />
End Property</p>
<p>Public Property Get infoType() As InfoTypeEnum<br />
infoType = m_InfoType<br />
End Property</p>
<p>Public Property Get Output() As String<br />
Output = _<br />
    m_Name &amp; vbTab &amp; _<br />
    Format$(m_StartDate, &#8220;yyyy-mm-dd&#8221;) &amp; vbTab &amp; _<br />
    Parent.EnumerateInfoType(m_InfoType)<br />
End Property<br />
&#8216; Class module: CMyInfos (end)</p>
<p>&#8216; Example usage<br />
Sub UseClasses()</p>
<p>    Dim Parent As CParent<br />
    Set Parent = New CParent<br />
    With Parent</p>
<p>      Dim i As Long<br />
      For i = 0 To 4<br />
          .MyInfos.Add _<br />
              Array(&#8220;Joe&#8221;, &#8220;Bob&#8221;, &#8220;Bob&#8221;, &#8220;Joe&#8221;, &#8220;Joe&#8221;)(i), _<br />
              Array(#1/1/2006#, #2/1/2006#, #1/15/2006#, #6/30/2005#, #1/8/2006#)(i), _<br />
              Array(2, 1, 1, 2, 1)(i)<br />
      Next i<br />
      Debug.Print .Output<br />
      Debug.Print<br />
      .MyInfos.Sort<br />
      Debug.Print .Output<br />
    End With</p>
<p>End Sub<br />
&#8216; Example usage (end)</p>
<p>But then I thought, maybe that&#8217;s too much for a blog.</p>
<p>Jamie.</p>
<p></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jamie Collins</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19024</link>
		<dc:creator>Jamie Collins</dc:creator>
		<pubDate>Tue, 28 Feb 2006 09:43:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19024</guid>
		<description>&lt;p&gt;Tushar,&lt;br&gt;
Let me try from a different angle. Do you agree that having weakly-typed arguments to your procedures is less than ideal? You&#039;ve used the key word &#039;implements&#039; in your reply but not in your code ;).&lt;/p&gt;
&lt;p&gt;Because your SortInfo routine has a Variant parameter it will compile and even run for any class but it&#039;s kind of relying on coincidence to work i.e. late binding will &#039;discover&#039; a SortInfo method at run-time. &lt;/p&gt;
&lt;p&gt;What I&#039;m saying is, if one&#039;s aim is to do things &#039;correctly&#039; then it would be better to use early binding. In other words, you have stated in your description that the implementation class must have a SortInfo method but you haven&#039;t imposed that requirement in your code.&lt;/p&gt;
&lt;p&gt;You could define an interface class with a SortInfo method which your &#039;sortable&#039; classes can implement. Trouble is, this SortInfo would itself need weakly typed parameters. &lt;/p&gt;
&lt;p&gt;I was thinking one step ahead, more along these lines:&lt;/p&gt;
&lt;p&gt;&#039; Class module: IMehtaData&lt;br&gt;
Option Explicit&lt;/p&gt;
&lt;p&gt;Property Get DataType() As Long: End Property&lt;br&gt;
Property Let DataType(ByRef RHS As Long): End Property&lt;/p&gt;
&lt;p&gt;Property Get UserName() As String: End Property&lt;br&gt;
Property Let UserName(ByRef RHS As String): End Property&lt;/p&gt;
&lt;p&gt;Property Get StartDate() As Date: End Property&lt;br&gt;
Property Let StartDate(ByRef RHS As Date): End Property&lt;br&gt;
&#039; Class module: IMehtaData&lt;/p&gt;
&lt;p&gt;&#039; Class module: MyInfo&lt;br&gt;
Option Explicit&lt;/p&gt;
&lt;p&gt;Implements IMehtaData&lt;/p&gt;
&lt;p&gt;Dim lType As Long, sName As String, dStart As Date&lt;/p&gt;
&lt;p&gt;Private Property Get IMehtaData_DataType() As Long: IMehtaData_DataType = lType: End Property&lt;br&gt;
Private Property Let IMehtaData_DataType(uType As Long): lType = uType: End Property&lt;/p&gt;
&lt;p&gt;Private Property Get IMehtaData_UserName() As String: IMehtaData_UserName = sName: End Property&lt;br&gt;
Private Property Let IMehtaData_UserName(uName As String): sName = uName: End Property&lt;/p&gt;
&lt;p&gt;Private Property Get IMehtaData_StartDate() As Date: IMehtaData_StartDate = dStart: End Property&lt;br&gt;
Private Property Let IMehtaData_StartDate(uStart As Date): dStart = uStart: End Property&lt;br&gt;
&#039; Class module: MyInfo (end)&lt;/p&gt;
&lt;p&gt;&#039; In an implementation class&lt;br&gt;
Public Sub sortClassItems( _&lt;br&gt;
ByRef Obj1 As IMehtaData, _&lt;br&gt;
ByRef Obj2 As IMehtaData)&lt;br&gt;
    If Obj1.DataType &gt; Obj2.DataType Then&lt;br&gt;
        swapItems Obj1, Obj2&lt;br&gt;
    ElseIf Obj1.DataType  Obj2.UserName Then&lt;br&gt;
        swapItems Obj1, Obj2&lt;br&gt;
    ElseIf Obj1.UserName  Obj2.StartDate Then&lt;br&gt;
        swapItems Obj1, Obj2&lt;br&gt;
        End If&lt;br&gt;
End Sub&lt;/p&gt;
&lt;p&gt;Sub swapItems( _&lt;br&gt;
ByRef Obj1 As IMehtaData, _&lt;br&gt;
ByRef Obj2 As IMehtaData)&lt;br&gt;
    Dim Temp As IMehtaData&lt;br&gt;
    Set Temp = Obj1&lt;br&gt;
    Set Obj1 = Obj2&lt;br&gt;
    Set Obj2 = Temp&lt;br&gt;
End Sub&lt;br&gt;
&#039; In an implementation class (any)&lt;/p&gt;
&lt;p&gt;Jamie.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Tushar,<br />
Let me try from a different angle. Do you agree that having weakly-typed arguments to your procedures is less than ideal? You&#8217;ve used the key word &#8216;implements&#8217; in your reply but not in your code <img src='http://www.dailydoseofexcel.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Because your SortInfo routine has a Variant parameter it will compile and even run for any class but it&#8217;s kind of relying on coincidence to work i.e. late binding will &#8216;discover&#8217; a SortInfo method at run-time. </p>
<p>What I&#8217;m saying is, if one&#8217;s aim is to do things &#8216;correctly&#8217; then it would be better to use early binding. In other words, you have stated in your description that the implementation class must have a SortInfo method but you haven&#8217;t imposed that requirement in your code.</p>
<p>You could define an interface class with a SortInfo method which your &#8216;sortable&#8217; classes can implement. Trouble is, this SortInfo would itself need weakly typed parameters. </p>
<p>I was thinking one step ahead, more along these lines:</p>
<p>&#8216; Class module: IMehtaData<br />
Option Explicit</p>
<p>Property Get DataType() As Long: End Property<br />
Property Let DataType(ByRef RHS As Long): End Property</p>
<p>Property Get UserName() As String: End Property<br />
Property Let UserName(ByRef RHS As String): End Property</p>
<p>Property Get StartDate() As Date: End Property<br />
Property Let StartDate(ByRef RHS As Date): End Property<br />
&#8216; Class module: IMehtaData</p>
<p>&#8216; Class module: MyInfo<br />
Option Explicit</p>
<p>Implements IMehtaData</p>
<p>Dim lType As Long, sName As String, dStart As Date</p>
<p>Private Property Get IMehtaData_DataType() As Long: IMehtaData_DataType = lType: End Property<br />
Private Property Let IMehtaData_DataType(uType As Long): lType = uType: End Property</p>
<p>Private Property Get IMehtaData_UserName() As String: IMehtaData_UserName = sName: End Property<br />
Private Property Let IMehtaData_UserName(uName As String): sName = uName: End Property</p>
<p>Private Property Get IMehtaData_StartDate() As Date: IMehtaData_StartDate = dStart: End Property<br />
Private Property Let IMehtaData_StartDate(uStart As Date): dStart = uStart: End Property<br />
&#8216; Class module: MyInfo (end)</p>
<p>&#8216; In an implementation class<br />
Public Sub sortClassItems( _<br />
ByRef Obj1 As IMehtaData, _<br />
ByRef Obj2 As IMehtaData)<br />
    If Obj1.DataType &gt; Obj2.DataType Then<br />
        swapItems Obj1, Obj2<br />
    ElseIf Obj1.DataType  Obj2.UserName Then<br />
        swapItems Obj1, Obj2<br />
    ElseIf Obj1.UserName  Obj2.StartDate Then<br />
        swapItems Obj1, Obj2<br />
        End If<br />
End Sub</p>
<p>Sub swapItems( _<br />
ByRef Obj1 As IMehtaData, _<br />
ByRef Obj2 As IMehtaData)<br />
    Dim Temp As IMehtaData<br />
    Set Temp = Obj1<br />
    Set Obj1 = Obj2<br />
    Set Obj2 = Temp<br />
End Sub<br />
&#8216; In an implementation class (any)</p>
<p>Jamie.</p>
<p></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tushar Mehta</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19012</link>
		<dc:creator>Tushar Mehta</dc:creator>
		<pubDate>Mon, 27 Feb 2006 13:42:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19012</guid>
		<description>&lt;p&gt;Jamie,&lt;/p&gt;
&lt;p&gt;Where in the sort routine does the code require any specific class property?  It only needs a class that implements the sortClassItems method.  I&#039;ve duplicated the SortInfo routine below though I imagine it will be posted w/o any indentation.&lt;/p&gt;
&lt;p&gt;Sub SortInfo(ByRef aInfo As Variant)&lt;br&gt;
    &#039;Basic bubble sort&lt;/p&gt;
&lt;p&gt;    Dim i As Long, j As Long&lt;/p&gt;
&lt;p&gt;    For i = LBound(aInfo) To UBound(aInfo) - 1&lt;br&gt;
        For j = i + 1 To UBound(aInfo)&lt;br&gt;
            aInfo(i).sortClassItems aInfo(i), aInfo(j)&lt;br&gt;
            Next j&lt;br&gt;
        Next i&lt;/p&gt;
&lt;p&gt;    End Sub&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Jamie,</p>
<p>Where in the sort routine does the code require any specific class property?  It only needs a class that implements the sortClassItems method.  I&#8217;ve duplicated the SortInfo routine below though I imagine it will be posted w/o any indentation.</p>
<p>Sub SortInfo(ByRef aInfo As Variant)<br />
    &#8216;Basic bubble sort</p>
<p>    Dim i As Long, j As Long</p>
<p>    For i = LBound(aInfo) To UBound(aInfo) &#8211; 1<br />
        For j = i + 1 To UBound(aInfo)<br />
            aInfo(i).sortClassItems aInfo(i), aInfo(j)<br />
            Next j<br />
        Next i</p>
<p>    End Sub</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jamie Collins</title>
		<link>http://www.dailydoseofexcel.com/archives/2006/02/23/sorting-arrays-of-user-defined-types/#comment-19009</link>
		<dc:creator>Jamie Collins</dc:creator>
		<pubDate>Mon, 27 Feb 2006 10:00:00 +0000</pubDate>
		<guid isPermaLink="false">http://www.dailydoseofexcel.com/?p=1356#comment-19009</guid>
		<description>&lt;p&gt;Tushar Mehta: &quot;One can leverage that additional capability to write a generic sort routine that&lt;br&gt;
works with *any* kind of object.&quot;&lt;/p&gt;
&lt;p&gt;JamieC: Your code requires those objects have properties named DataType, UserName and StartDate. For me, that does not equate to any kind of object; in fact, not one of my classes would be able to use your &#039;generic&#039; routine.&lt;/p&gt;
&lt;p&gt;Rather than late binding using Variant variables, one could do it &#039;correctly&#039; and leverage the advantages of early binding (IntelliSense, syntax checking, improved runtime performance, etc) by creating an interface class, say IMehtaData (sorry, couldn&#039;t resist :)), which classes needing to use the SortInfo method can Implement. This way the arguments to SortInfo can be typed as IMehtaData and you could legitimately say that your method were &quot;a generic sort routine that&lt;br&gt;
works with *any* object of a class that Implements my IMehtaData interface.&quot;&lt;/p&gt;
&lt;p&gt;Jamie.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
</description>
		<content:encoded><![CDATA[<p>Tushar Mehta: &#8220;One can leverage that additional capability to write a generic sort routine that<br />
works with *any* kind of object.&#8221;</p>
<p>JamieC: Your code requires those objects have properties named DataType, UserName and StartDate. For me, that does not equate to any kind of object; in fact, not one of my classes would be able to use your &#8216;generic&#8217; routine.</p>
<p>Rather than late binding using Variant variables, one could do it &#8216;correctly&#8217; and leverage the advantages of early binding (IntelliSense, syntax checking, improved runtime performance, etc) by creating an interface class, say IMehtaData (sorry, couldn&#8217;t resist <img src='http://www.dailydoseofexcel.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ), which classes needing to use the SortInfo method can Implement. This way the arguments to SortInfo can be typed as IMehtaData and you could legitimately say that your method were &#8220;a generic sort routine that<br />
works with *any* object of a class that Implements my IMehtaData interface.&#8221;</p>
<p>Jamie.</p>
<p></p>
]]></content:encoded>
	</item>
</channel>
</rss>

