excel match one with many values - excel

I have data to reconcile between two system. one system might reported value 100 but on another system 50 two times.I need to consider them as possible match.
But not every record will have possible match
Column A Column B
SAP system Local system
100.00 50.00
435.00 50.00
146.25 435.00
53.75 253.50
I should conclude 100 has matching data (50 & 50) & 435 has matching data.I can match the exact one with formula but is there a way to match combination of values like 100.00 case?

This function will find the first matching pair and return the positions of the matching numbers in column B, called as:-
=FindPair(A2,B2:B5)
Option Explicit
Function FindPair(TotVal As Range, SearchVals As Range) As String
Dim Tot As Integer, i As Long, j As Long, length As Long, SearchVal As Double, found As Boolean
Dim store() As Double
Dim sum As Double
length = SearchVals.Rows.Count
ReDim store(length)
SearchVal = TotVal.Cells(1, 1).Value
For i = 1 To length
store(i) = SearchVals(i)
Next i
found = False
FindPair = ""
For i = 1 To length - 1
sum = store(i)
For j = i + 1 To length
If (sum + store(j)) = SearchVal Then
found = True
GoTo finish
End If
Next j
Next i
finish:
If found Then
FindPair = CStr(i) & "," & CStr(j)
End If
End Function

Related

Excel/VBA - How to check the top three and if equal then check based on custom rank?

I have the following data:
Value
Percentages
Rank
A
67%
3
B
57%
4
C
43%
5
D
38%
1
E
67%
2
F
57%
6
In Excel (either formulas or VBA), how would I be able to generate a top three based on first the percentage value - and if the percentages of two or more are equal, then based on rank?
So for example 67% is found twice in column Percentages. However, the second time 67% is found it has a rank of 2, so the first value for the top three would be E and the complete top three would look like this:
1: E
2: A
3: B
I don't even have an idea to start with. I can use the =LARGE formula, but that will only give me the value of the highest and if the value is found in there multiple times, then I don't know from which one it took it. And it also doesn't take into account the custom ranking..
If you have Excel-365 then can try-
=SEQUENCE(3)&":"&INDEX(SORTBY(A2:A7,B2:B7,-1,C2:C7,1),SEQUENCE(3))
Here is a UDF that should work in most versions of Excel (tested in Excel 365). I have chosen to avoid sorting and just repeatedly find the maximum subject to the two conditions. Assumes all percentages and ranks are positive values but can tolerate blank rows.
Function ListTopValues(r As Range, Optional topN As Integer = 3)
Dim arr() As Variant, used() As Boolean
Dim percent As Double, rank As Double
Dim maxPercent As Double, maxRank As Double
Dim value As String, maxValue As String, result As String
Dim rows As Long, n As Long, i As Long, u As Long
' Transer range to array
rows = r.rows.Count
ReDim used(rows)
arr = r.value
' Loop over number of values required
For n = 1 To topN
maxValue = ""
maxRank = 0
maxPercent = 0
u = 0
' Loop over rows of data
For i = 1 To rows
value = arr(i, 1)
percent = arr(i, 2)
rank = arr(i, 3)
' Check if row already used and copy maximum so far
If Not used(i) Then
If percent > maxPercent Or percent = maxPercent And rank < maxRank Then
maxPercent = percent
maxRank = rank
maxValue = value
u = i
End If
End If
Next i
If maxValue <> "" Then _
result = result & maxValue & ","
If u > 0 Then used(u) = True
Next n
If Len(result) > 0 Then _
result = Left(result, Len(result) - 1)
ListTopValues = result
End Function

Finding multiple combinations of sums in Excel

Ive been trying to make something in Excel to find multiple combinations of sums.
I have list of numbers that needs to be added together to be either within ranges of 500-510 or 450-460.
Only two numbers from the list can be used to find the sum. the numbers can not be used more than once. and giving the combinations of multiple results would be great. and if a number is not used it is ok.
I've tried the solver add-in and some other tips I found from this site but could not find something that gives multiple answers.
Does anyone know if this will be possible?
I'd break this into 2 tasks. First would be to simply generate all of the index pairs to test in the input array. That's relatively simple with recursive procedure. This one uses a private Type to store the pairs, but it could adapted to use some other method of storing the pairs:
Private Type Tuple
ValueOne As Long
ValueTwo As Long
End Type
Private Sub FindCombinations(elements As Long, ByRef results() As Tuple, _
Optional ByVal iteration As Long = 0)
If iteration = 0 Then ReDim results(0)
Dim idx As Long
For idx = iteration To elements - 1
Dim combo As Tuple
With combo
.ValueOne = iteration
.ValueTwo = idx
End With
results(UBound(results)) = combo
If iteration <> elements And idx <> elements Then
ReDim Preserve results(UBound(results) + 1)
End If
Next
If iteration < elements Then FindCombinations elements, results, iteration + 1
End Sub
Then, you use a "entry-point" procedure to generate the index combinations, use those to index into your source array, and apply your selection criteria:
Private Sub FindMatchingSets(testSet() As Long)
Dim indices() As Tuple
FindCombinations UBound(testSet) + 1, indices
Dim idx As Long, results() As Tuple
For idx = LBound(indices) To UBound(indices)
Dim tupleSum As Long
tupleSum = testSet(indices(idx).ValueOne) + testSet(indices(idx).ValueTwo)
If indices(idx).ValueOne <> indices(idx).ValueTwo And _
((tupleSum >= 500 And tupleSum <= 510) Or _
(tupleSum >= 450 And tupleSum <= 460)) Then
Debug.Print testSet(indices(idx).ValueOne) & " + " & _
testSet(indices(idx).ValueTwo) & " = " & tupleSum
End If
Next
End Sub
It isn't clear what you intend to do with the results, so this simply outputs the calculated values to the Immediate Window. Example calling code:
Private Sub Example()
Dim test(4) As Long
test(0) = 100
test(1) = 200
test(2) = 250
test(3) = 260
test(4) = 400
FindMatchingSets test
End Sub
May modify it according to your need & try
Sub test()
Dim X, Y, TRw, GotNum, First, Second As Long
TRw = 1
With ThisWorkbook.ActiveSheet
For X = 1 To 100 ' assumed col A1 to A100 is the list
GotNum = .Cells(X, 1).Value
If (GotNum >= 450 And GotNum <= 460) Or (GotNum >= 500 And GotNum <= 510) Then
.Cells(X, 1).Font.Color = RGB(255, 0, 0)
First = GotNum
For Y = X + 1 To 100
GotNum = .Cells(Y, 1).Value
If (GotNum >= 450 And GotNum <= 460) Or (GotNum >= 500 And GotNum <= 510) Then
Second = GotNum
TRw = TRw + 1
.Cells(TRw, 3).Value = First ' write 1st Number in Col C
.Cells(TRw, 4).Value = Second ' write 2nd Number in Col D
.Cells(TRw, 5).Value = First + Second ' write Sum of 1st & 2nd in Col C
End If
Next Y
End If
Next X
End With
End Sub
I think your question needs to be a little clearer in terms of what your expected output is (do you want a list of combos, or just to see the results?), but here's my solution.
I've put a list of 20 numbers in column Y, and assigned them all a letter (a through to t) in column X
Then I've built a matrix of the combinations of a to t, and have entered the following formula (the below is for cell C3, but it can be copied and pasted into all parts of the matrix)
=IF(C$2=$B3,"x",VLOOKUP(C$2,$X:$Y,2,FALSE)+VLOOKUP($B3,$X:$Y,2,FALSE))
I've then used conditional formatting to set the colour of the cells if they meet your criteria for the sum - you can do this by highlighting all the sums (cell C3:V22) and going to
home / conditional formatting / new rule...
picking the rule type format only cells that contain
and then in the drop down menus picking Cell Value / Between / Your high range
and then selecting a format (fill background colour, usually)
Do this once for the "high" sum, and once for the "low" sum. You can make the colours the same or different, depending on what you want to see.
I've also for reference included a reference to what the number is in Row 1 and column A. The formula for row 1 is (example is for C1, but it can be copied across)
=VLOOKUP(C2,$X:$Y,2,FALSE)
And the formula for column A is (example for A3) =VLOOKUP(B3,$X:$Y,2,FALSE)
The advantage of this approach is that it's all in excel (no code required), but the disadvantage is that it's hard to get a list of results. You could use a different formula to just return the sum (e.g. return the text "205+298") when it meets one of the conditions, but then it's still a pain to get it out of the matrix format and into a single list. Much easier using VBA

How do I modify a sample code for primefactorization in Excel VBA to a specific column of numbers?

I have in Column K:
K8 is 6384 i.e. =SUM(J1:J8)
K9 is 2598 i.e. =SUM(J2:J9)
K10 is 12176 i.e =SUM(J3:J10)
:
:
K5488
up to K5488 (No numbers in sequence, all different numbers)
The largest number appearing in K is 1 400 000.
I need in Column M: The prime factors of each number in K
e.g. K8 is 6384 then M8 should be 2,2,2,2,3,7,19
k9 is 2598 then M9 should be 2,3,433 etc.
I found the following code by John Coleman on your site (Mar 28) which tested well, but seeing I have no programming knowledge, I don't know how to modify it to use in my columns K & M setup.
Here's the sample code:
Function Factor(ByVal n As Long, Optional FirstTrial As Long = 2) As String
Dim i As Long
Dim t As Long
Dim limit As Long
Dim rest As String
Dim s As String
If n = 1 Then
Factor = n
Exit Function
End If
limit = Int(Sqr(n))
t = FirstTrial
Do While t <= limit
If n Mod t = 0 Then
rest = Factor(n / t, t)
If rest <> "1" Then
s = t & "," & rest
End If
Factor = s
Exit Function
Else
If t = 2 Then t = 3 Else t = t + 2
End If
Loop
'if we get here:
Factor = n
End Function
Function PrimeOrFactor(n As Long) As String
Dim s As String
s = Factor(n)
If n = 1 Then
PrimeOrFactor = "Neither"
ElseIf (s) = Trim(n) Then
PrimeOrFactor = "Prime"
Else
PrimeOrFactor = s
End If
End Function
Tested like:
Sub test()
Dim i As Long
For i = 1 To 20
Cells(i, 1) = i
Cells(i, 2) = PrimeOrFactor(i)
Next i
End Sub
The function you provided is a udf (user defined function) to be used in your worksheet.
If you put the functions you provided in a normal code module, you can enter the following in your worksheet in M8:
=Factor(K8)
and copy that function down to your desired range.

Avoid Cell specification when moving across for loop

I am trying to use step functions to describe a curve. This is mainly due to other methods not being as precise as this one, in which the data points are connected by a linear relationship.
I have a table of x-values. Each x-value is taken, and compared to a second table until the following condition is met:
Value2>Value1
Once that is achieved, the second table is used to construct a linear relationship, with which I can accurately calculate the first values actual result, the y-value (assuming y = f(x) ), which is introduced to a last table.
This process has to be repeated then exactly the same way, however the table from which the first value is taken and the table from below which contains the results shifts to the right for every table iteration.
The code I used is as follows:
Sub alpha()
Dim a As Integer
a = 0
Begin_Count:
a = a + 1
Dim l As Integer
For l = 1 To 13
'Check the first value
Val1 = Range(Chr(a + 66) & (l + 269))
'Check the numbers to compare range
Dim i As Integer
For i = 1 To 12:
Val2 = Range(Chr(67) & (i + 284))
If Val2 > Val1 = True Then
'Calculate Cl
dy = (Range("D" & (i + 284)) - Range("D" & (i + 283)))
dx = (Range("C" & (i + 284)) - Range("C" & (i + 283)))
x = (Val1 - Range("C" & (i + 283)))
y = Range("D" & (i + 283))
Cl = ((dy / dx) * x) + y
'Insert Cl
Range(Chr(a + 66) & (l + 299)).Value = Cl
Exit For
End If
Next
Next
If a < 101 = True Then
GoTo Begin_Count
End If
End Sub
This code runs until it reaches the point in which the cells from Excel are labeled "AA","AB",etc., at which the code gives an error.
Can anyone help me out with this?
Instead of:
Range(Chr(a + 66) & (l + 299)).Value = Cl
use
Cells(l+299, a).Value = Cl
In general it's easier to use Cells() with two numeric arguments than to try to create an address string to pass to Range(), particularly if you're working on a single cell.
Just a couple quick things...
Always use Option Explicit in your code modules. It forces you to declare your variables and helps avoid crossing up value types.
Always create a worksheet object, so you can "guarantee" which worksheet your code refers. It makes it more clear, especially when you're involving multiple worksheets (maybe not now, but later).
Finally, refer to the values in your table using the Cells(rowindex,columnindex) format. This way you can index rows and columns numerically.
Option Explicit
sub alpha()
Dim ws as Worksheet
Dim a as Integer
Dim lrow as Integer, lcol as Integer
Dim irow as Integer, icol as Integer
Dim
Set ws = Activesheet
a = 0
Val1 = ws.Cells(lrow, lcol).value
end sub

Split and sort strings components using Excel

I have a column in Excel with the format:
A01G45B45D12
I need a way to format it like this, that is divide the string into groups of three characters, sort the groups alphabetically and then join them together with a + sign between:
A01+B45+D12+G45
I wonder it this is possible using the built in formulas in Excel or if I have to do this using VBA or something else, I already have the code for this in C# if there is an easy way to use that from Excel. I have not written plugins for Excel before.
Edit to add:
The above is just an example, the string can be of "any length" but its always divisible by three and the order is random so I cannot assume anything about the order beforehand.
Sub ArraySort()
Dim strStarter As String
Dim strFinish As String
Dim intHowMany As Integer
Dim intStartSlice As Integer
strStarter = ActiveCell.Offset(0, -1).Value 'Pulls value from cell to the left
intHowMany = Int(Len(strStarter) / 3)
ReDim arrSlices(1 To intHowMany) As String
intStartSlice = 1
For x = 1 To intHowMany
arrSlices(x) = Mid(strStarter, intStartSlice, 3)
intStartSlice = intStartSlice + 3
Next x
Call BubbleSort(arrSlices)
For x = 1 To intHowMany
strFinish = strFinish + arrSlices(x) & "+"
Next x
strFinish = Left(strFinish, Len(strFinish) - 1)
ActiveCell.Value = strFinish 'Puts result into activecell
End Sub
Sub BubbleSort(list() As String)
'Taken from power programming with VBA
'It’s a sorting procedure for 1-dimensional arrays named List
'The procedure takes each array element, if it is greater than the next element, the two elements swap positions.
'The evaluation is repeated for every pair of items (that is n-1 times)
Dim First As Integer, Last As Long
Dim i As Long, j As Long
Dim temp As String
First = LBound(list)
Last = UBound(list)
For i = First To Last - 1
For j = i + 1 To Last
If list(i) > list(j) Then
temp = list(j)
list(j) = list(i)
list(i) = temp
End If
Next j
Next i
End Sub

Resources