I am trying to sort columns alphabetically based on the values of cells in Row 2.
Can't figure out what's wrong here - it seems to work only for the first column and then it stops.
Sub reorganise()
Dim v As Variant, x As Variant, findfield As Variant
Dim oCell As Range
Dim iNum As Long
Dim wsa As Worksheet
Set wsa = Worksheets("Skills")
v = Array(wsa.Range("B2", wsa.Cells(2, wsa.Columns.Count).End(xlToLeft)))
For x = LBound(v) To UBound(v)
findfield = v(x)
iNum = iNum + 1
Set oCell = wsa.Rows(2).Find(What:=findfield, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not oCell.Column = iNum Then
Columns(oCell.Column).Cut
Columns(iNum).Insert Shift:=xlToRight
End If
Next x
End Sub
Ok I have figured it out.. was a bit more complicated but here is the full code:
Sub reorganise()
Dim v
Dim x
Dim findfield As Variant
Dim oCell As Range
Dim iNum As Long
Dim wsa As Worksheet
Dim inputArray() As Variant
Set wsa = Worksheets("Skills")
With wsa
Set v = .Range("A2", .Cells(2, .Columns.Count).End(xlToLeft))
End With
v = Application.Transpose(v)
Call BubbleSort(v)
For x = LBound(v, 1) To UBound(v, 1)
findfield = v(x, 1)
iNum = iNum + 1
Set oCell = wsa.Rows(2).Find(What:=findfield, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not oCell.Column = iNum Then
Columns(oCell.Column).Cut
Columns(iNum).Insert Shift:=xlToRight
End If
Next x
End Sub
Sub BubbleSort(arr)
Dim strTemp As String
Dim i As Long
Dim j As Long
Dim lngMin As Long
Dim lngMax As Long
lngMin = LBound(arr, 1)
lngMax = UBound(arr, 1)
For i = lngMin To lngMax - 1
For j = i + 1 To lngMax
If arr(i, 1) > arr(j, 1) Then
strTemp = arr(i, 1)
arr(i, 1) = arr(j, 1)
arr(j, 1) = strTemp
End If
Next j
Next i
End Sub
Basically in addition to what you said, I had to:
Transpose the array
Change the LBound and Ubound and findfield syntax
Come up with an additional procedure to sort out the values of the array alphabetically
1) assign directly the range to your variant variable v - without the Array function. When using the array function, what you are doing is assign an array of one element - consisting of your range returned as an array - to your variable v
2) v will contain a 2 dimensions array:
first dimension will be 1 - for one row returned
second dimension will be as many columns as returned by the range
Then loop through the second dimension of this array - I haven't checked the rest of the code but this should get you on your way
Related
I have autofiltered a worksheet and am trying to establish the unique values within the filtered data. I feel like I have the correct approach, but the my results only show 2 of the possible 8 unique values.
Private Sub GetAllCampusDomains(DomainCol As Collection)
Dim data(), dict As Object, r As Long, i%, lastrow As Long
Set dict = CreateObject("Scripting.Dictionary")
'Clear the previous filter
shtData.ShowAllData
'Filter the data
shtData.Range("A:Y").AutoFilter Field:=6, Criteria1:=shtSetup.Range("CampusName") 'SchoolName
shtData.Range("A:Y").AutoFilter Field:=9, Criteria1:="DomainPerformance" 'ColI
'Inspect the visible cells in ColP
lastrow = shtData.Cells(shtData.Rows.Count, "P").End(xlUp).row
data = shtData.Range("P2:P" & lastrow).SpecialCells(xlCellTypeVisible)
'Find the unique values
For r = 1 To UBound(data)
dict(data(r, 1)) = Empty
Next
data = WorksheetFunction.Transpose(dict.keys())
'Walk through the unique values
For i = 1 To UBound(data)
Debug.Print data(i, 1)
'DomainCol.Add data(i, 1)
Next i
End Sub
The error seems to have to do with this line:
data = shtData.Range("P2:P" & lastrow).SpecialCells(xlCellTypeVisible)
This call only seems to create a 90x1 sized array, when it should be much bigger.
I greatly appreciate your help!
Josh
Non-Contiguous Column Range to Jagged Array
Instead of...
data = shtData.Range("P2:P" & lastrow).SpecialCells(xlCellTypeVisible)
'Find the unique values
For r = 1 To UBound(data)
dict(data(r, 1)) = Empty
Next
...use the following...
Private Sub GetAllCampusDomains(DomainCol As Collection)
'...
Dim rng As Range
Set rng = shtData.Range("P2:P" & lastrow).SpecialCells(xlCellTypeVisible)
getNonContiguousColumn Data, rng
'Find the unique values
Dim j As Long
For j = 0 To UBound(Data)
For r = 1 To UBound(Data(j))
dict(Data(j)(r, 1)) = Empty
Next r
Next j
'...
End Sub
...backed up by the following:
Sub getNonContiguousColumn(ByRef Data As Variant, _
NonContiguousColumnRange As Range, _
Optional FirstIndex As Long = 0)
Dim j As Long
j = FirstIndex - 1
ReDim Data(FirstIndex To NonContiguousColumnRange.Areas.Count + j)
Dim ar As Range
Dim OneCell As Variant
ReDim OneCell(1 To 1, 1 To 1)
For Each ar In NonContiguousColumnRange.Areas
j = j + 1
If ar.Cells.Count > 1 Then
Data(j) = ar.Value
Else
OneCell(1, 1) = ar.Value
Data(j) = OneCell
End If
Next ar
End Sub
Test the previous Sub with something like the following:
Sub testGetNCC()
Const rngAddr As String = "A2:A20"
Dim Data As Variant
Dim rng As Range
Set rng = Range(rngAddr).SpecialCells(xlCellTypeVisible)
getNonContiguousColumn Data, rng
Dim j As Long, i As Long
For j = 0 To UBound(Data)
For i = 1 To UBound(Data(j))
Debug.Print Data(j)(i, 1)
Next i
Next j
End Sub
Please, replace this piece of code:
data = shtData.Range("P2:P" & lastrow).SpecialCells(xlCellTypeVisible)
'Find the unique values
For r = 1 To UBound(data)
dict(data(r, 1)) = Empty
Next
with the next one:
Dim rng As Range, C As Range
Set rng = shtData.Range("P2:P" & lastRow).SpecialCells(xlCellTypeVisible)
'Find the unique values
For Each C In rng.cells
dict(C.Value) = Empty
Next
Your initial code iterates between the first area range cells.
The second one will iterate between all visible range cells...
Currently trying to append all cells in each row into the first cell of that row, and iterate through every row. Problem is I'm dealing with ~3000 rows with about 20 columns of data in each row. Is there any better way to append all cells in a row into one single cell without using a for loop? That could narrow down the code to a single for loop and may speed up the process.
Tried making a nested for loop that iterates through every row then every column per row. It works, but takes far too long when dealing with a large amount of data.
Sub AppendToSingleCell()
Dim value As String
Dim newString As String
Dim lastColumn As Long
Dim lastRow As Long
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
For j = 1 To lastRow
lastColumn = Cells(j, Columns.Count).End(xlToLeft).Column
For i = 2 To lastColumn
If IsEmpty(Cells(j, i)) = False Then
value = Cells(j, i)
newString = Cells(j, 1).value & " " & value
Cells(j, 1).value = newString
Cells(j, i).Clear
End If
Next i
Next j
End Sub
Load everything into a variant array and loop that instead of the range. load the output into another variant array and then put that data as one back in the sheet.
Sub AppendToSingleCell()
With ActiveSheet
Dim lastRow As Long
lastRow = .Cells(.Rows.Count, "A").End(xlUp).row
Dim lastColumn As Long
lastColumn = .Cells.Find(What:="*", After:=.Range("a1"), LookIn:=xlValue, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Dim dtaArr() As Variant
dtaArr = .Range(.Cells(1, 2), .Cells(lastRow, lastColumn)).value
Dim otArr() As Variant
ReDim otArr(1 To lastRow, 1 To 1)
Dim i As Long
For i = LBound(dtaArr, 1) To UBound(dtaArr, 1)
For j = LBound(dtaArr, 2) To UBound(dtaArr, 2)
If dtaArr(i, j) <> "" Then otArr(i, 1) = otArr(i, 1) & dtaArr(i, j) & " "
Next j
otArr(i, 1) = Application.Trim(otArr(i, 1))
Next i
.Range(.Cells(1, 2), .Cells(lastRow, lastColumn)).Clear
.Range(.Cells(1, 1), .Cells(lastRow, 1)).value = otArr
End With
End Sub
It's a bit long, but pretty straight forward.
Explanation inside the code's comments.
Code
Option Explicit
Sub AppendToSingleCell()
Dim newString As String
Dim LastRow As Long, LastColumn As Long
Dim Sht As Worksheet
Dim FullArr As Variant, MergeCellsArr As Variant
Dim i As Long, j As Long
Set Sht = ThisWorkbook.Sheets("Sheet1") ' <-- rename "Sheet1" to your sheet's name
With Sht
LastRow = FindLastRow(Sht) ' call sub that finds last row
LastColumn = FindLastCol(Sht) ' call sub that finds last column
' populate array with enitre range contents
FullArr = .Range(.Cells(1, 1), .Cells(LastRow, LastColumn))
ReDim MergeCellsArr(1 To LastRow) ' redim 1-D array for results (same number of rows as in the 2-D array)
' looping through array is way faster than interfacing with your worksheet
For i = 1 To UBound(FullArr, 1) ' loop rows (1st dimension of 2-D array)
newString = FullArr(i, 1)
For j = 2 To UBound(FullArr, 2) ' loop columns (2nd dimension of 2-D array)
If IsEmpty(FullArr(i, j)) = False Then
newString = newString & " " & FullArr(i, j)
End If
Next j
MergeCellsArr(i) = newString ' read new appended string to new 1-D array
Next i
' paste entire array to first column
.Range("A1").Resize(UBound(MergeCellsArr)).value = MergeCellsArr
End With
End Sub
'=======================================================================
Function FindLastCol(Sht As Worksheet) As Long
' This Function finds the last col in a worksheet, and returns the column number
Dim LastCell As Range
With Sht
Set LastCell = .Cells.Find(What:="*", After:=.Cells(1), LookAt:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, SearchDirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then
FindLastCol = LastCell.Column
Else
MsgBox "Error! worksheet is empty", vbCritical
Exit Function
End If
End With
End Function
'=======================================================================
Function FindLastRow(Sht As Worksheet) As Long
' This Function finds the last row in a worksheet, and returns the row number
Dim LastCell As Range
With Sht
Set LastCell = .Cells.Find(What:="*", After:=.Cells(1), LookAt:=xlPart, LookIn:=xlFormulas, _
SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then
FindLastRow = LastCell.Row
Else
MsgBox "Error! worksheet is empty", vbCritical
Exit Function
End If
End With
End Function
If you're interested in a shorter solution.... It assumes your data begins in cell A1.
Public Sub CombineColumnData()
Dim arr As Variant
Dim newArr() As Variant
Dim varTemp As Variant
Dim i As Long
arr = ActiveSheet.Range("A1").CurrentRegion.Value
ReDim newArr(1 To UBound(arr, 1))
For i = LBound(arr, 1) To UBound(arr, 1)
varTemp = Application.Index(arr, i, 0)
newArr(i) = Join(varTemp, "")
Next i
With ActiveSheet.Range("A1")
.CurrentRegion.Clear
.Resize(UBound(arr, 1), 1) = Application.Transpose(newArr)
End With
End Sub
This is posted by Dammer15 and this is what I'm looking for. However I need it to loop through the entire column. I would ask there directly but I can not comment yet.
Dim My_Number As String
Dim i As Integer
My_Number = Range("AJ")
For i = 1 To Len(My_Number) - 1
If InStr(1, My_Number, "0") = 1 Then
My_Number = Right(My_Number, Len(My_Number) - 1)
Else
Range("AJ") = My_Number
Exit For
End If
Next
You will need to iterate through each value. I would recommend uploading the whole range into an array and then looping through that instead:
Sub foo()
Dim rng As Range
Dim i As Long, j As Long
Dim arr() As Variant
Dim lastRow As Long
With ActiveSheet
lastRow = .Cells(.Rows.Count, "AJ").End(xlUp).Row
Set rng = .Range("AJ1", .Cells(lastRow, "AJ"))
arr = rng.Value
For i = LBound(arr, 1) To UBound(arr, 1)
My_Number = arr(i, 1)
For j = 1 To Len(arr(i, 1)) - 1
If Mid(arr(i, 1), j, 1) <> 0 Then
arr(i, 1) = Right(arr(i, 1), Len(arr(i, 1)) - (j - 1))
Exit For
End If
Next j
Next i
rng.Value = arr
End With
End Sub
You could use a regex to match the lead 0s instead of the bulky replace function you currently have:
Sub TestRe()
Dim LastCell As Range: Set LastCell = ActiveSheet.Columns("AJ").Find("*", SearchDirection:=xlPrevious)
Dim Rng As Range: Set Rng = ActiveSheet.Range("AJ1", LastCell)
Dim Cell As Range: For Each Cell In Rng
Cell.Value = RemoveLead0s(Cell.Value)
Next Cell
End Sub
Function RemoveLead0s(AlphaNum As String) As String
RemoveLead0s = AlphaNum
' RegExp requires "Microsoft VBScript Regular Expressions 5.5" reference
Dim RegEx As New RegExp
With RegEx
.Pattern = "^0*"
If .test(AlphaNum) Then RemoveLead0s = .Replace(AlphaNum, "")
End With
End Function
This is a for loop to find values in a range and create new array full of match results. Problem is viewing the object I see at the first If statement AR2(i) creates an element AR2(0) which is empty then assigns AR2(1) as the If Else value.
Sub rt()
Dim AR0() As Variant, AR1() As Variant, AR2() As Variant
Dim WS0 As Worksheet, WS1 As Worksheet
Dim i As Integer, RW0 As Integer, RW1 As Integer
Dim C As Range
Set WS0 = Sheets("lookup")
Set WS1 = Sheets("centro")
RW1 = WS1.Cells(WS1.Rows.Count, "A").End(xlUp).row
AR0 = WS0.Range("A3:A28")
For i = 1 To UBound(AR0, 1)
With WS1.Range("A2:A" & RW1)
Set C = .find(AR0(i, 1), LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
ReDim Preserve AR2(i)
If Not C Is Nothing Then
AR2(i) = "YES"
Else
AR2(i) = " - "
End If
End With
Next
WS0.Range("B3:B28") = WorksheetFunction.Transpose(AR2)
End Sub
Error was with AR2 creating element AR2(0) without having value assigned. Solution was to set For loop to start from 0 and AR0(i +1, 1) to allow to find this value starting from loop position 0. Thanks!
Sub rt()
Dim AR0() As Variant, AR1() As Variant, AR2() As Variant
Dim WS0 As Worksheet, WS1 As Worksheet
Dim i As Integer, RW0 As Integer, RW1 As Integer
Dim C As Range
Set WS0 = Sheets("lookup")
Set WS1 = Sheets("centro")
RW1 = WS1.Cells(WS1.Rows.Count, "A").End(xlUp).row
AR0 = WS0.Range("A3:A28")
For i = 0 To UBound(AR0, 1) - 1
With WS1.Range("A2:A" & RW1)
Set C = .find(AR0(i + 1, 1), LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
ReDim Preserve AR2(i)
If Not C Is Nothing Then
AR2(i) = "YES"
Else
AR2(i) = " - "
End If
End With
Next
WS0.Range("B3:B28") = WorksheetFunction.Transpose(AR2)
End Sub
I have to loop search multiple ranges and find match to 100k + records. Problem is I get mismatch error when assigning value to variant Arr2(i, 1).
Dim Arr1, Arr2 As Variant
Dim Wks0, Wks1 As Worksheet
Dim i As Integer
Dim Row0, Row1 As Long
Dim C As Object
Set Wks0 = Sheets("HOST")
Set Wks1 = Sheets("OFICI_BANC_USA")
'-- Create array of range -------------------------------------------*
Row0 = Wks0.Cells(Rows.Count, "A").End(xlUp).Row
Row1 = Wks1.Cells(Rows.Count, "A").End(xlUp).Row
Arr1 = Wks1.Range("A2:A" & Row1)
'-- Loop create value on sheet OFIC_BANC_USA found value in sheet HOST -----*
For i = 1 To 5 'UBound(Arr1)
With Wks0.Range("A2:A" & Row0)
Set C = .Find(Arr1(i, 1), LookAt:=xlPart,SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not C Is Nothing Then
'ReDim Preserve Arr2(i, 1)
Arr2(i, 1) = "OK"
Else
Arr2(i, 1) = "NO"
End If
End With
Next
' Transpose new array onto worksheet -------------------------------*
Wks1.Range("B2:B6") = WorksheetFunction.Transpose(Arr2)
'Arr1 = Nothing
'Arr2 = Nothing
I think you want to deal with a two-dimensioned array for the values coming in from wks1 (since you have no choice in the matter) and a single dimensioned array to hold the OK / NO values before stuffing them back into the worksheet.
Sub t()
Dim Arr0() As Variant, Arr1() As Variant, Arr2() As Variant
Dim Wks0 As Worksheet, Wks1 As Worksheet
Dim i As Long
Dim Row0 As Long, Row1 As Long
Dim C As Range
Set Wks0 = Sheets("HOST")
Set Wks1 = Sheets("OFICI_BANC_USA")
'-- Create array of range -------------------------------------------*
Row0 = Wks0.Cells(Wks0.Rows.Count, "A").End(xlUp).Row
Row1 = Wks1.Cells(Wks1.Rows.Count, "A").End(xlUp).Row
Arr1 = Wks1.Range("A2:A" & Row1)
'-- Loop create value on sheet OFIC_BANC_USA found value in sheet HOST -----*
For i = 1 To UBound(Arr1, 1)
With Wks0.Range("A2:A" & Row0)
Set C = .Find(Arr1(i, 1), LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
ReDim Preserve Arr2(i) '<~~ NOTE ReDim single dimensioned array here!
If Not C Is Nothing Then
Arr2(i) = "OK"
Else
Arr2(i) = "NO"
End If
End With
Next
' Transpose new array onto worksheet -------------------------------*
Wks1.Range("B2").Resize(UBound(Arr2), 1) = WorksheetFunction.Transpose(Arr2)
End Sub
Note where I've redimmed arr2. It's going to get a value either way so you need to extend its size in preparation to receive an OK / NO.
Scripting.Dictionary
Sub tt()
Dim arr As Variant, dHOST As Object
Dim Wks0 As Worksheet, Wks1 As Worksheet
Dim i As Long, j As Long
Dim Row0 As Long, Row1 As Long
Dim c As Range, rHOST As Range
Debug.Print Timer
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Set Wks0 = Worksheets("HOST")
Set Wks1 = Sheets("OFICI_BANC_USA")
Set dHOST = CreateObject("Scripting.Dictionary")
dHOST.CompareMode = vbTextCompare
'-- Create dictionary of HOST range --------------------------
Row0 = Wks0.Cells(Wks0.Rows.Count, "A").End(xlUp).Row
arr = Wks0.Range("A2:D" & Row0).Value2
For i = LBound(arr, 1) To UBound(arr, 1)
For j = LBound(arr, 2) To UBound(arr, 2)
'If Not dHOST.Exists(arr(i, j)) Then _
dHOST.Item(arr(i, j)) = j '<~~ for first match (adds 1½ seconds)
dHOST.Item(arr(i, j)) = j '<~~ for overwrite match
Next j
Next i
'-- Create array of OFICI_BANC_USA range ----------------------
Row1 = Wks1.Cells(Wks1.Rows.Count, "A").End(xlUp).Row
arr = Wks1.Range("A2:E" & Row1).Value2
For i = LBound(arr, 1) To UBound(arr, 1)
For j = LBound(arr, 2) + 1 To UBound(arr, 2)
arr(i, j) = "NO" '<~~ seed all NO matches
Next j
Next i
'-- Loop arrayed values from sheet OFIC_BANC_USA found value in dictionary HOST values --
For i = LBound(arr, 1) To UBound(arr, 1)
If dHOST.Exists(arr(i, 1)) Then _
arr(i, dHOST.Item(arr(i, 1)) + 1) = "OK"
Next i
' Stuff it all back into worksheet -------------------------------*
With Wks1.Range("A2:E" & Row1)
.Cells = arr
End With
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
Application.ScreenUpdating = True
Debug.Print Timer
End Sub
200K records in column A of OFICI_BANC_USA worksheet
4 columns # 50K rows each in HOSTS worksheet
~76% match rate
14.73 seconds start-to-finish
In addition to #VincentG's comment, you need to explicitly state which Rows you're using. Also, I uncommented the ReDim, and it seems to be working now:
Sub t()
Dim Arr0() As Variant, Arr1() As Variant, Arr2() As Variant
Dim Wks0 As Worksheet, Wks1 As Worksheet
Dim i As Integer
Dim Row0 As Long, Row1 As Long
Dim C As Object
Set Wks0 = Sheets("HOST")
Set Wks1 = Sheets("OFICI_BANC_USA")
'-- Create array of range -------------------------------------------*
Row0 = Wks0.Cells(Wks0.Rows.Count, "A").End(xlUp).Row
'Arr0 = Wks0.Range("A2:A" & Row0)
Row1 = Wks1.Cells(Wks1.Rows.Count, "A").End(xlUp).Row
Arr1 = Wks1.Range("A2:A" & Row1)
'-- Loop create value on sheet OFIC_BANC_USA found value in sheet HOST -----*
For i = 1 To 5 'UBound(Arr1)
With Wks0.Range("A2:A" & Row0)
Set C = .Find(Arr1(i, 1), LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext)
If Not C Is Nothing Then
ReDim Preserve Arr2(i, 1)
Arr2(i, 1) = "OK"
Else
Arr2(i, 1) = "NO"
End If
End With
Next
' Transpose new array onto worksheet -------------------------------*
Wks1.Range("B2:B6") = WorksheetFunction.Transpose(Arr2)
'Arr0 = Nothing
'Arr1 = Nothing
'Arr2 = Nothing
End Sub
I think I am understanding what you are trying to do. I set my two sheets up like this:
Then using the following code:
Sub jorge()
Application.ScreenUpdating = False
Dim Arr1 As Variant, Arr2 As Variant, Arr3 As Variant
Dim Wks0 As Worksheet, Wks1 As Worksheet
Dim i As Long, j As Long, k As Long
Dim Row0 As Long, Row1 As Long
Set Wks0 = Sheets("HOST")
Set Wks1 = Sheets("OFICI_BANC_USA")
'-- Create array of range -------------------------------------------*
Row0 = Wks0.Cells(Rows.Count, "A").End(xlUp).Row
Row1 = Wks1.Cells(Rows.Count, "A").End(xlUp).Row
Arr1 = Wks1.Range("A2:A" & Row1)
ReDim Arr2(1 To Row1, 1 To 4)
Arr3 = Wks0.Range("A2:D" & Row0)
'-- Loop create value on sheet OFIC_BANC_USA found value in sheet HOST -----*
For i = 1 To UBound(Arr1, 1)
For j = 1 To UBound(Arr3, 2)
Arr2(i, j) = "NO"
For k = 1 To UBound(Arr3, 1)
If Arr3(k, j) = Arr1(i, 1) Then
Arr2(i, j) = "OK"
Exit For
End If
Next k
Next j
Next i
Wks1.Range("B2").Resize(Row1, 4).value = Arr2
Application.ScreenUpdating = true
End Sub
I get this:
This formula will do the same thing, put this in B2:
=IF(ISNUMBER(MATCH($A2,HOST!A:A,0)),"OK","NO")
Copy across and down. This may be prohibitive with the sheer number of calculations, but it is here if you want to try it.