vba.blacktorgroup.com/Warranty Claims

Modelling a warranty claim as an object, not four arrays.

Ride Me Cycles tracked open warranty claims as four parallel arrays, frame numbers, purchase dates, fault descriptions and statuses, kept in step by array index alone. A class module gives each claim its own identity instead, one that can't quietly fall out of step.

A translucent black cube etched with a moss-green map of the world's continents, glowing softly against black.
BlackTor Group Ltd Dartmoor, UK
A note on this page

A reference, not a client write-up.

Illustrative, per the note on the main VBA page: not real client work. It sits alongside the Frame-Number Check and Resilient Export pages as a deeper dive on one routine that comes up often enough to be worth its own write-up.

The issue

Four arrays, kept in step by index alone, don't stay in step.

With a claim's fields spread across four separate arrays, the only thing tying a frame number at index 12 to its fault description is that it's also at index 12 in a different array. Sort one array to review claims by date and the other three are now describing entirely different claims unless every one of them is sorted identically, by hand, every time.

It also has no room for behaviour: working out how many days a claim has left under warranty means writing that calculation out again everywhere it's needed, rather than asking the claim itself.

Class module

clsWarrantyClaim: one object per claim, with its own behaviour

' ===== Class Module: clsWarrantyClaim ===== Option Explicit Private mstrFrameNumber As String Private mdatPurchaseDate As Date Private mstrFaultDetail As String Private mblnIsResolved As Boolean Public Property Get FrameNumber() As String FrameNumber = mstrFrameNumber End Property Public Property Let FrameNumber(ByVal strValue As String) mstrFrameNumber = strValue End Property Public Property Get PurchaseDate() As Date PurchaseDate = mdatPurchaseDate End Property Public Property Let PurchaseDate(ByVal datValue As Date) mdatPurchaseDate = datValue End Property Public Property Get FaultDetail() As String FaultDetail = mstrFaultDetail End Property Public Property Let FaultDetail(ByVal strValue As String) mstrFaultDetail = strValue End Property Public Property Get IsResolved() As Boolean IsResolved = mblnIsResolved End Property Public Sub MarkResolved() mblnIsResolved = True End Sub ' DaysRemainingUnderWarranty ' -------------------------- ' Ride Me Cycles' standard warranty is 24 months from purchase. Returns ' the number of whole days left before it lapses, or 0 once it already ' has -- never a negative number, so a caller can test "> 0" directly ' instead of also having to check the sign. Public Function DaysRemainingUnderWarranty() As Long Const WARRANTY_MONTHS As Integer = 24 Dim datExpiryDate As Date datExpiryDate = DateAdd("m", WARRANTY_MONTHS, mdatPurchaseDate) DaysRemainingUnderWarranty = _ Application.WorksheetFunction.Max(0, DateDiff("d", Date, datExpiryDate)) End Function ' ===== Standard Module ===== Option Explicit ' BuildOpenClaimsCollection ' ------------------------- ' Reads the Warranty Claims sheet into a Collection of ' clsWarrantyClaim objects, keyed by frame number, so a claim can be ' retrieved directly by colOpenClaims(strFrameNumber) instead of a ' linear search through parallel arrays. Public Function BuildOpenClaimsCollection() As Collection Dim colOpenClaims As New Collection Dim wksClaims As Worksheet Dim varClaimsData As Variant Dim lngRowIndex As Long Dim objClaim As clsWarrantyClaim Set wksClaims = ThisWorkbook.Worksheets("Warranty Claims") varClaimsData = wksClaims.Range("A2:D" & _ wksClaims.Cells(wksClaims.Rows.Count, "A").End(xlUp).Row).Value For lngRowIndex = 1 To UBound(varClaimsData, 1) Set objClaim = New clsWarrantyClaim With objClaim .FrameNumber = varClaimsData(lngRowIndex, 1) .PurchaseDate = varClaimsData(lngRowIndex, 2) .FaultDetail = varClaimsData(lngRowIndex, 3) End With ' Collection keys must be unique -- On Error traps the rare case ' of two claims logged against the same frame number, rather ' than letting the whole build fail on one bad row. On Error Resume Next colOpenClaims.Add objClaim, Key:=objClaim.FrameNumber On Error GoTo 0 Next lngRowIndex Set BuildOpenClaimsCollection = colOpenClaims End Function

Every field a claim has lives inside one object now, so sorting, filtering or passing a claim around always carries its frame number, purchase date and fault detail together. There's no longer a second or third array that has to be kept in step by hand.

DaysRemainingUnderWarranty is what a class module adds that four arrays never could: real behaviour attached to the data. Any code holding a claim object can ask it directly, rather than that calculation being copied out at every place it's needed and risking drifting out of sync with itself.

Keying the Collection by frame number means a specific claim is retrieved directly with colOpenClaims(strFrameNumber), rather than looping through every claim to find the one that matches.

Result

A claim can be sorted, filtered or passed around without falling apart.

Claims now behave as single, self-contained records. A sort or a filter on the Collection can never leave a frame number pointing at the wrong fault description.