I have a spreadsheet of data in multiple columns. In VBA, I am trying to set a value in each row depending on the data in any one of three of the other columns. It will always be an OR comparison between those data and will need to return one of five values.
So I have created five arrays (they are multidimensional due to reading them in as ranges, however, they could be one dimensional if needed, I suppose), and I was going to compare the three columns to those arrays using a bunch of IF-THEN statements to return the necessary value.
Creating the arrays was easy enough, but I have no idea how to create the IF-THEN process correctly. An example of the process would be something like:
IF A1 is in ArrayA THEN
D1="Dog"
ELSEIF A1 is in ArrayB THEN
D1="Cat"
ELSEIF B1 is in ArrayC THEN
D1="Bird"
ELSEIF B1 is in ArrayD THEN
D1="Monkey"
ELSEIF C1 is in ArrayE THEN
D1="Blue"
ELSE
D1="Other"
I am not sure if this is the most efficient way to accomplish what I am trying to do, so I am definitely open to suggestions for a different approach. Thank you.
Ok, here is how I got it working. Most of this came from another person, but they deleted their comment so I can't thank them.
arrCols = Array(arrA, arrB, arrC, arrD, arrE)
arrVals = Array("Dog", "Cat", "Bird", "Monkey", "Blue")
For i = 2 To rCnt
pID = Cells(i, 2).Value
pName = Cells(i, 3).Value
pGroup = Cells(i, 4).Value
ans = ""
For j = LBound(arrCols) To UBound(arrCols)
If Not IsError(Application.Match(pGroup, arrCols(j), 0)) Then
ans = arrVals(j)
Exit For
ElseIf Not IsError(Application.Match(pName, arrCols(j), 0)) Then
ans = arrVals(j)
Exit For
ElseIf Not IsError(Application.Match(pID, arrCols(j), 0)) Then
ans = arrVals(j)
Exit For
End If
Next j
Cells(i, 5) = IIf(ans = "", "Other", ans)
Next i
I created an array of arrays to search through. The i loop cycles through all rows. The j loop cycles through the arrays within the main array. The three IF statements are needed for checking the three different columns. The returned value is defaulted to "Other" unless it is found in one of the arrays.
The only thing I was able to add to this code was the stuff needed to check three different columns in the row.
Here is an example of how to do it without looping
If Len("," & Join(ArrayA, ",") & ",") <> Len("," & Replace(Join(ArrayA, ","), "," & Range("A1").Value & ",", "") & ",") Then
Range("D1").Formula = "Dog"
ElseIf Len("," & Join(ArrayB, ",") & ",") <> Len("," & Replace(Join(ArrayB, ","), "," & Range("A1").Value & ",", "") & ",") Then
Range("D1").Formula = "Cat"
ElseIf Len("," & Join(ArrayC, ",") & ",") <> Len("," & Replace(Join(ArrayC, ","), "," & Range("A1").Value & ",", "") & ",") Then
Range("D1").Formula = "Bird"
ElseIf Len("," & Join(ArrayD, ",") & ",") <> Len("," & Replace(Join(ArrayD, ","), "," & Range("A1").Value & ",", "") & ",") Then
Range("D1").Formula = "Monkey"
ElseIf Len("," & Join(ArrayE, ",") & ",") <> Len("," & Replace(Join(ArrayE, ","), "," & Range("A1").Value & ",", "") & ",") Then
Range("D1").Formula = "Blue"
Else
Range("D1").Formula = "Other"
End If
Join the array to a string then check the len against the len of the string with the keyword (Range("A1")) replaced with nothing. Put a comma on either side to make sure it is the full word (Don't want something like Catfish to return as a Cat)
And the same thing using InStr instead:
If InStr(1, "," & Join(ArrayA, ",") & ",", Range("A1").Value) > 0 Then
Range("D1").Formula = "Dog"
ElseIf InStr(1, "," & Join(ArrayB, ",") & ",", Range("A1").Value) > 0 Then
Range("D1").Formula = "Cat"
ElseIf InStr(1, "," & Join(ArrayC, ",") & ",", Range("A1").Value) > 0 Then
Range("D1").Formula = "Bird"
ElseIf InStr(1, "," & Join(ArrayD, ",") & ",", Range("A1").Value) > 0 Then
Range("D1").Formula = "Monkey"
ElseIf InStr(1, "," & Join(ArrayE, ",") & ",", Range("A1").Value) > 0 Then
Range("D1").Formula = "Blue"
Else
Range("D1").Formula = "Other"
End If
Related
this is my first time posting!
I have a data set similar to
Essentially there is data split into three columns (ID, Record, and Variable). For each "group" (based on the ID they share), I need to be able to reset the order of the records so that 4 and 5 come last in the "group." Then, the function would be able to go to the next one. Finally, I would expect a result like
A few key points:
I cannot use sorting/filtering because none of the IDs/Records/Variables in the true data set are in numeric order
Cannot split it out into different sheets/macros, because there are thousands of unique IDs.
Tried to work through this, but have some issues with my code doing nothing (below). Any ideas?
Sub GrpUpdate()
Dim f As Long
Dim i As Long
Dim last As Long
grpOne = "4"
grpTwo = "5"
i = 2
f = i
last = Range("A:A").Find(what:=Range("A" & f).Value, after:=Range("A" & f), searchdirection:=xlPrevious, LookIn:=xlValues).Row
For f = i To last
If f = last Then
i = last + 1
f = i
last = Range("A:A").Find(what:=Range("A" & f).Value, after:=Range("A" & f), searchdirection:=xlPrevious, LookIn:=xlValues).Row
ElseIf Not IsError(Application.Match(grpOne, "B" & f & ":" & "B" & last, 0)) And Not IsError(Application.Match(grpTwo, "B" & f & ":" & "B" & last, 0)) Then
Rows(Range("B" & f & ":" & "B" & last).Find(what:=grpOne, after:=Range("B" & f), searchdirection:=xlPrevious, LookIn:=xlValues).Row).Cut
Rows(last).Insert
Rows(Range("B" & f & ":" & "B" & last).Find(what:=grpTwo, after:=Range("B" & f), searchdirection:=xlPrevious, LookIn:=xlValues).Row).Cut
Rows(last).Insert
ElseIf Not IsError(Application.Match(grpOne, "B" & f & ":" & "B" & last, 0)) Then
Rows(Range("B" & f & ":" & "B" & last).Find(what:=grpOne, after:=Range("B" & f), searchdirection:=xlPrevious, LookIn:=xlValues).Row).Cut
Rows(last).Insert
ElseIf Not IsError(Application.Match(grpTwo, "B" & f & ":" & "B" & last, 0)) Then
Rows(Range("B" & f & ":" & "B" & last).Find(what:=grpTwo, after:=Range("B" & f), searchdirection:=xlPrevious, LookIn:=xlValues).Row).Cut
Rows(last).Insert
End If
Next f
End Sub
Try this out:
Sub GrpUpdate()
Dim f As Range, first As Long, last As Long
Dim ws As Worksheet, numRows As Long, addrGroups As String, arrLast, g
Set ws = ActiveSheet 'or whatever
first = 2 'start here
arrLast = Array("4", "5") 'items which (if present) should be last for each Id, in order
Do While Len(ws.Cells(first, "A").Value) > 0
With ws.Cells(first, "A") 'find the last value
last = ws.Range("A:A").Find(what:=.Value, after:=.Cells(1), _
searchdirection:=xlPrevious, lookat:=xlWhole).Row
End With
numRows = 1 + (last - first)
If numRows > 1 Then 'ignore single rows
'Using the range address because we're cutting rows which can be
' weird with Range references....
addrGroups = ws.Cells(first, "B").Resize(numRows).Address 'address for the "group" range
For Each g In arrLast 'loop items to be ordered last
Set f = ws.Range(addrGroups).Find(what:=g, lookat:=xlWhole)
If Not f Is Nothing Then
f.EntireRow.Cut 'move the found row to the end of the group
ws.Rows(last + 1).Insert
End If
Next g
End If '>1 row
first = last + 1 'next Id
Loop
End Sub
I have a few different arrays that are worksheets. What I want to build out is making this code print a group sheets via an array, where the "packages_to_print" array is equal to all the relevant array of sheets that need to printed. If this is not possible, is there a way to select multiple arrays to print?
This code doesn't give me an error, it just doesn't print anything to pdf.
Here's the relevant code. (The lender_package is the same as another variable because I have not built out the case statement for setting that variable to an array yet). Thank you in advance for your help.
Dim common_disclosures As Variant
Dim nh_disclosure As Variant
Dim provident_disclosures As Variant
Dim packages_to_print As Variant
Dim lender_package As Variant
common_disclosures = Array("Certification", "Responsible Use", "Security Procedures", "Acknowledgment", "FACTA Credit Score", "Anti-Steering")
nh_disclosures = Array("Loan Origination and Comp", "Rate Lock", "ECOA")
provident_disclosures = Array("MBFA")
lender_package = Array(provident_disclosures)
If subject_state <> "MA" Then
packages_to_print = Array(common_disclosures, nh_disclosures, lender_package)
Else
packages_to_print = Array(common_disclosures, lender_package)
End If
For j = 1 To (customerpackages * 2)
Worksheets(packages_to_print).Select _
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"C:\users\" & environ_user & "\desktop\" & borrower_array(j - 1) & " disclosures.pdf" _
, Quality:=xlQualityMinimum, IncludeDocProperties:=True, _
IgnorePrintAreas:=False, OpenAfterPublish:=False
Next j
Actually you are using array of arrays in WorkSheets(..) expression. Try joining the arrays as packages_to_print and it is running OK.
If subject_state <> "MA" Then
packages_to_print = Split(Join(common_disclosures, ",") & "," & Join(nh_disclosures, ",") & "," & Join(lender_package, ","), ",")
Else
packages_to_print = Split(Join(common_disclosures, ",") & "," & Join(lender_package, ","), ",")
End If
Full Trial Code, may try it on any new workbook with 8-8 sheets
Sub test()
Dim common_disclosures As Variant
Dim nh_disclosures As Variant
Dim lender_package As Variant
Dim packages_to_print As Variant
common_disclosures = Array("Sheet1", "Sheet4", "Sheet3", "Sheet2", "Sheet5")
nh_disclosures = Array("Sheet2", "Sheet5")
lender_package = Array("Sheet6", "Sheet8")
subject_state = "MA"
If subject_state <> "MA" Then
packages_to_print = Split(Join(common_disclosures, ",") & "," & Join(nh_disclosures, ",") & "," & Join(lender_package, ","), ",")
Else
packages_to_print = Split(Join(common_disclosures, ",") & "," & Join(lender_package, ","), ",")
End If
Worksheets(packages_to_print).Select
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:= _
"C:\Users\user\Desktop\Book1.pdf", Quality:=xlQualityStandard, _
IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:= _
False
End Sub
I am filling two arrays with values one for inclusion and the other for exclusion. All working to this point. The next part should take the values from each array and replace unwanted values with a blank space. This also works but only for the first value. I know i need a loop here but can't get my head around it. Any pointers would be helpful. If there is a better way, I'm all ears.
Sub Service_Symbols()
Application.ScreenUpdating = False
Dim StringArray() As String
Dim i As Long
Dim ii As Long
Dim iii As Long
For i = Sheet2.Cells(Rows.Count, 11).End(xlUp).Row To 2 Step -1
'Seperate multiple values in cells
If InStr(Cells(i, 11).Value, ",") <> 0 Then
StringArray() = Split(Cells(i, 11).Value, ",")
'Place selected values into array for inclusion
For ii = LBound(StringArray) To UBound(StringArray)
If IsInArray(StringArray(), "1") Or IsInArray(StringArray, "4") Or IsInArray(StringArray, "5") Or IsInArray(StringArray, "6") Or IsInArray(StringArray, "7") Or IsInArray(StringArray, "8") Then
result = Join(StringArray(), " ")
End If
Next ii
'Place selected values into array for removal
For iii = LBound(StringArray) To UBound(StringArray)
ResultDel = StringArray(iii)
If InStr(ResultDel, "2") <> 0 Or InStr(ResultDel, "3") <> 0 Or InStr(ResultDel, "9") <> 0 Or InStr(ResultDel, "11") <> 0 Then
del = ResultDel
Debug.Print i; ResultDel
End If
Next iii
'This section not working. Needs to be looped
'Remove unwanted values
ServiceSym = Trim(Replace(Replace(Replace(result, del, ""), del, ""), " ", " "))
ServiceSym = Replace(ServiceSym, " ", ",")
'Sheet1.Range("G" & i).Value = ServiceSym
Debug.Print i; ServiceSym
'Debug.Print result
'Debug.Print i; del
'End of this section not working. Needs to be looped
'transfer selected single values in cells
ElseIf Sheet2.Range("K" & i).Value = "1" Or Sheet2.Range("K" & i).Value = "4" Or Sheet2.Range("K" & i).Value = "5" Or Sheet2.Range("K" & i).Value = "6" Or Sheet2.Range("K" & i).Value = "7" Or Sheet2.Range("K" & i).Value = "8" Then
result2 = Sheet2.Range("K" & i).Value
'Sheet1.Range("G" & i).Value = result2
Debug.Print i; result2
End If
Next i
Application.ScreenUpdating = True
'Call More_Services_Symbols 'Run the more services sub
End Sub
Adding this sub and replacing the section that is not working with a call to the sub should work.
Sub RemoveUnwantedValues(ByRef result As String, del)
Dim i As Integer
Dim arrResult() As String
arrResult = Split(result, " ")
For i = LBound(arrResult) To UBound(arrResult)
arrResult(i) = Trim(Replace(Replace(Replace(arrResult(i), del, ""), del, ""), " ", " "))
arrResult(i) = Replace(arrResult(i), " ", ",")
Next i
End Sub
You can call it this way: RemoveUnwantedValues result, del
Thanks for your help. It turns out i was over complicating things.
All i ended up needing to do was remove the join on result remove loop iii and place If instr, del & ServiceSym inside of loop ii.
Sub Service_Symbols()
Application.ScreenUpdating = False
Dim StringArray() As String
Dim i As Long
For i = Sheet2.Cells(Rows.Count, 11).End(xlUp).Row To 2 Step -1
'Seperate multiple values in cells
If InStr(Cells(i, 11).Value, ",") <> 0 Then
StringArray() = Split(Cells(i, 11).Value, ",")
'Place selected values into array for inclusion
For ii = LBound(StringArray) To UBound(StringArray)
If IsInArray(StringArray(), "1") Or IsInArray(StringArray, "4") Or IsInArray(StringArray, "5") Or IsInArray(StringArray, "6") Or IsInArray(StringArray, "7") Or IsInArray(StringArray, "8") Then
result = StringArray(ii)
'Debug.Print i; result
End If
If InStr(result, "2") <> 0 Or InStr(result, "3") <> 0 Or InStr(result, "9") <> 0 Or InStr(result, "11") <> 0 Then
del = result
'Debug.Print i; "del-"; del
End If
ServiceSym = Replace(result, del, "")
'Sheet1.Range("G" & i).Value = ServiceSym
Debug.Print i; ServiceSym
Next ii
'transfer selected single values in cells
ElseIf Sheet2.Range("K" & i).Value = "1" Or Sheet2.Range("K" & i).Value = "4" Or Sheet2.Range("K" & i).Value = "5" Or Sheet2.Range("K" & i).Value = "6" Or Sheet2.Range("K" & i).Value = "7" Or Sheet2.Range("K" & i).Value = "8" Then
result2 = Sheet2.Range("K" & i).Value
'Sheet1.Range("G" & i).Value = result2
Debug.Print i; result2
End If
Next i
Application.ScreenUpdating = True
'Call More_Services_Symbols 'Run the more services sub
End Sub
I have the code below but I know it could be sped up by putting the data into an array which I don't know how. I'd appreciate any help.
Thanks In advance
For Each rngReportCell In rngReport
If rngReportCell = "" Then Exit For
If VBA.UCase(rngReportCell.Offset(0, 1).Value) = "X" Then
wkbSOR.Sheets("Dashboard").range("SSSFlag").Value = True
Else
wkbSOR.Sheets("Dashboard").range("SSSFlag").Value = False
End If
If rngRetrieveCell.Offset(0, 1).Value <> "" Then _
wkbSOR.Sheets(rngRetrieveCell.Value).range(rngRetrieveCell.Offset(0, 1).Value) _
= "'" & rngReportCell.Value
If rngReportCell.Offset(0, 2) <> "" And gRetrieveCell.Offset(0, 2).Value <> "" Then _
wkbSOR.Sheets(rngRetrieveCell.Value).range(rngRetrieveCell.Offset(0, 2).Value) _
= "'" & rngReportCell.Offset(0, 2).Value
TotalRows = range("Base_" & rngRetrieveCell).Rows.count
TotalCols = range("Base_" & rngRetrieveCell).Columns.count
'Copies values using range.value = range.value
range("A7").Offset(range("A7").CurrentRegion.Rows.count, 0).Resize(TotalRows, TotalCols).Value = _
wkbSOR.Sheets(rngRetrieveCell.Value).range("Base_" & rngRetrieveCell).Value
Next rngReportCell 'Store/Hyperion code
Maybe this will help you:
https://stackoverflow.com/questions/17859531/excel-vba-populate-array-with-range-from-specific-sheet
But essentially you will want to just import the range that you want into a 2-D array and iterate through as so (for example):
'Instantiate variant array
Dim arrValues() As Variant
arrValues = Sheet1.Range("A1:D10")
'Iterate through rows
For i = 1 To 10
'Iterate through columns
For j = 1 To 10
'your code here
Next
Next
I have the following data
Name ID Value
Alice 12C 500
Bob 14 60
Dan 15C 64
Dan 1C 25
Alice 4 556
Bob 11 455
In my data, Alice has both numerical (4) and string+numerical ID (12C) and I want to delete all Alice rows, while I want to hold on to data of names where their ID is strictly numeric (Bob 11, 14) or strictly string+numeric (Dan 15C , 1C).
First I make an array of unique Name entries:
FinalRow = 7
Name_column = 1
n = 1
Dim FID_Array() As Variant
ReDim Preserve FID_Array(1 To 1)
FID_Array(1) = Cells(2, Name_column)
For j = 3 To FinalRow
If Cells(j, Name_column).Value <> FID_Array(n) Then
ReDim Preserve FID_Array(1 To n + 1)
FID_Array(n + 1) = Cells(j, Name_column).Value
n = n + 1
End If
Next j
Then I make an Array of the row numbers that contain a particular Name
ReDim Preserve Count_FID_Array(1 To 1) As Variant
n = 1
range_FID = A2:A7
' In my actual code this is Range_FID
' range_FID = Cells(2, FolderId_column).Address & ":" & Cells(FinalRow, FolderId_column).Address
For Each itm5 In FID_Array()
Count_FID_Array(n) = Application.CountIf(" & range_FID & ", " & itm5 & ")
ReDim Preserve Count_FID_Array(1 To n + 1)
n = n + 1
Next itm5
I don't think my CountIf is working. I have tried to store the value of Count_FID_Array in another cell in a different sheet but I am getting #value!
If I got the countIf to work then I was going to sort the data by name, then double loop to check the ID variable the next "n" times to see if the last digit was "C" for all of them or to check if the ID was numeric for all of them.
Can you please point out why my countif is not working and is there a smarter way to do this?
I am using arrays of names here because in the end I want to feed the array into an autofilter and delete the rows that I don't want.
Update 1 3:45 PM Nov 21 2013: I have solved this as following:
I basically created three columns. First column was 0 or 1 depending on if the the ID was all numbers. The second column was 0 or 1 depending on if the last digit was "C" (in my real work the last two digits are "IB" ) and finally I compared the frequency of these occurences to the frequency of the Name itself. If any of those match then I give it the number 1 else 0. I use this index later to autofilter.
Now I'll try to use zx8754's shorter formula in the VBA code and I will try to address the issues regarding Countif that Joe has raised.
Sub conditionsforsubfolders()
FinalColumn = Cells(1, Columns.Count).End(xlToLeft).Column
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
ActiveWorkbook.ActiveSheet.Columns(FinalColumn + 1).Insert
ActiveWorkbook.ActiveSheet.Columns(FinalColumn + 2).Insert
ActiveWorkbook.ActiveSheet.Columns(FinalColumn + 3).Insert
Isnumber_Column = FinalColumn + 1
Is_IB_Column = FinalColumn + 2
Exceptions_Column = FinalColumn + 3
Cells(1, Isnumber_Column) = "Number"
Cells(1, Is_IB_Column) = "Letters"
Cells(1, Exceptions_Column) = "Exceptions"
For j = 1 To FinalColumn
If Cells(1, j).Value = "TradeId" Then
TradeId_column = j
ElseIf Cells(1, j).Value = "Total Notional per folder" Then
Total_Notional_Per_Folder_Column = j
ElseIf Cells(1, j).Value = "ExternalId" Then
ExternalId_Column = j
ElseIf Cells(1, j).Value = "FolderId" Then
FolderId_column = j
End If
Next j
range_FolderId_fixed = Cells(2, FolderId_column).Address & ":" & Cells(FinalRow, FolderId_column).Address
range_TradeId_fixed = Cells(2, TradeId_column).Address & ":" & Cells(FinalRow, TradeId_column).Address
range_Isnumber = Cells(2, Isnumber_Column).Address & ":" & Cells(FinalRow, Isnumber_Column).Address(RowAbsolute:=False, ColumnAbsolute:=False)
range_Isnumber_fixed = Cells(2, Isnumber_Column).Address & ":" & Cells(FinalRow, Isnumber_Column).Address
range_Is_IB = Cells(2, Is_IB_Column).Address & ":" & Cells(FinalRow, Is_IB_Column).Address(RowAbsolute:=False, ColumnAbsolute:=False)
range_Is_IB_fixed = Cells(2, Is_IB_Column).Address & ":" & Cells(FinalRow, Is_IB_Column).Address(RowAbsolute:=False, ColumnAbsolute:=False)
range_FolderId_cell = Cells(2, FolderId_column).Address(RowAbsolute:=False, ColumnAbsolute:=False)
range_TradeId_cell = Cells(2, TradeId_column).Address(RowAbsolute:=False, ColumnAbsolute:=False)
range_Exceptions = Cells(2, Exceptions_Column).Address & ":" & Cells(FinalRow, Exceptions_Column).Address(RowAbsolute:=False, ColumnAbsolute:=False)
Range(range_Isnumber).Formula = "=Isnumber(" & range_TradeId_cell & ")*1"
Range(range_Is_IB).Formula = "=(RIGHT(" & range_TradeId_cell & ",2)= ""IB"")*1"
Range(range_Exceptions).Formula = "=(SUMIF(" & range_FolderId_fixed & "," & range_FolderId_cell & "," & range_Isnumber_fixed & ")= COUNTIF(" & range_FolderId_fixed & "," & range_FolderId_cell & "))*1 +(SUMIF(" & range_FolderId_fixed & "," & range_FolderId_cell & "," & range_Is_IB_fixed & ")= COUNTIF(" & range_FolderId_fixed & "," & range_FolderId_cell & "))*1 "
Worksheets("Sheet1").UsedRange.AutoFilter Field:=7, Criteria1:="=1"
End Sub
Formula solution, no VBA:
=IF(SUMPRODUCT(--($A$2:$A$7=A2),--(ISNUMBER($B$2:$B$7)))=1,"delete","keep")
The problem with your CountIF call is that you're passing a poorly-formed string. You're literally passing "range_FID & ", " & itm5".
First, you set to properly define range_fid:
Dim range_fid As Range
Set range_fid = [A2:A7]
The call CountIF with:
count_fid_array(n) = Application.WorksheetFunction.CountIf(range_fid, itm5)
With that said, I would go about it differently:
Dim c As Range
Dim people As Collection: Set people = New Collection
Dim person As Collection
Dim code As String
For Each c In Range(Range("a2"), Range("a2").End(xlDown)) ' loop through all rows
If IsNumeric(c.Offset(0, 1)) Then ' check if the ID is numeric or not
code = "num"
Else
code = "alphanum"
End If
On Error Resume Next ' Needed in order to avoid error when person already exists in collection
Set person = New Collection
person.Add c.Value, "name"
person.Add code, "code"
people.Add person, c.Value ' will only be added if name doesn't already exist in collection
On Error GoTo 0
If people(c.Value)("code") <> code Then ' if the format (alpha/num) of the ID on the current row is different than the format of a previous row for this name....
people(c.Value).Remove ("code") ' then set the code to "diff"
people(c.Value).Add "diff", "Code"
End If
Next
For Each person In people ' just display the content; you can take appropriate action here
Debug.Print person("name") & ": " & person("code")
Next
The result is a Collection containing names and a code for each. The code will be one of:
num: all values for a name are numeric (Bob)
alphanum: all values for a name are alphanumeric (Dan)
diff: name has at least one each of numeric and alphanumeric (Alice)
Note that this could be done a little clearer with a Dictionary instead of a Collection, or with a Class, but I chose to take the most straightforward approach.