VBA finding the median without using the function - excel

I'm trying to find the median without using the function but I can't figure out what I'm doing wrong here.
Dim i As Integer
Dim passNum As Integer
Dim temp As Integer
Dim aantal As Integer
Dim n(1 To 50) As Single
Dim p As Integer
Dim j As Single
Dim t As Single
Dim median As Single
aantal = InputBox("how many n variables do you want max 50")
For p = 1 To aantal
n(p) = InputBox("geef " & aantal & " nummers")
Next
'Rem bubble sort names
For passNum = 1 To aantal - 1
For i = 1 To aantal - passNum
If n(i) < n(i + 1) Then
temp = n(i)
n(i) = n(i + 1)
n(i + 1) = temp
End If
Next i
Next passNum
'Rem display alphabetized list
For i = 1 To aantal
Worksheets(1).Cells(i, 1) = n(i)
Next i
'find the median
t = aantal Mod 2
If t > 0 Then
median = n(aantal + 1) / 2
Else
median = (n(aantal / 2) + (n(aatnal) / 2) + 1) / 2
End If
Worksheets(1).Cells(1, 2) = median
End Sub
this is the code that I have right now but it won't find the median everything else works fine.
I've tried changing n(aantal) for something else but that doesn't work either it just either gives me the wrong number or nothing.

Maybe try this:
Sub Median()
Dim i As Integer
Dim aantal As Integer, tmp as double
ReDim n(0) As Double
100:
aantal = InputBox("how many n variables do you want max 50")
If aantal > 50 Then Goto 100
ReDim n(aantal - 1)
For i = 0 To UBound(n)
n(i) = CDbl(InputBox("Geef nr " & i + 1 & " van " & aantal & " nummers"))
Next
For i = LBound(n) To UBound(n)
For j = i + 1 To UBound(n)
If n(i) > n(j) Then
tmp = n(j)
n(j) = n(i)
n(i) = tmp
End If
Next
Next
m = aantal Mod 2
ix = ((aantal + m) / 2) - 1
If (m = 1) Then
nMedian = n(ix)
Else
nMedian = (n(ix) + n(ix + 1)) / 2
End If
Debug.Print nMedian
End Sub

Related

X Unique Randomize Numbers

i need a little bit help.
Is it possible to fill a list with random numbers and to check this list before each loop to see if the number already exists?
I think im on the wrong way with my VBA.
Sub Zufallszahlen()
Dim Rng As Range
Max = 6
Min = 1
Anzahl = 4
counter = 0
innercounter = 0
SZeile = 2
AWert = "X"
Range("C:C").Clear
Do
counter = counter + 1
ZZahl = Int((Max * Rnd) + Min)
innercounter = 0
Do
innercounter = innercounter + 1
If Cells(innercounter, 2) = ZZahl Then
ZZahl = Int((Max * Rnd) + Min)
Else
Loop Until innercounter = Anzahl
' Cells(counter, 1).Value = counter
Cells(counter, 2).Value = ZZahl
Cells(ZZahl, 3).Value = AWert
Loop Until counter = Anzahl
Range("B:B").Clear
End Sub
Use an array to check if random number has already been chosen. Repeat until a vacant array position is found.
Option Explicit
Sub Zufallszahlen()
Const MaxN = 6
Const MinN = 1
Const Anzahl = 4
Const Awert = "X"
Dim ar, n As Long, r As Long, i As Long
n = MaxN - MinN + 1
If n < Anzahl Then
MsgBox "Min to Max range must be >= " & Anzahl
Exit Sub
End If
' values in column B
Dim arB, total As Single, try As Long
arB = Range("B" & MinN).Resize(n).Value2
Do
' avoid endless loop
try = try + 1
If try > 100 Then
MsgBox "Could not solve in 100 tries", vbExclamation
Exit Sub
End If
' generate random selection
ReDim ar(1 To n, 1 To 1)
total = 0
For i = 1 To Anzahl
Do
r = 1 + Int(n * Rnd())
Loop Until ar(r, 1) = ""
ar(r, 1) = Awert
' sum col B
total = total + arB(r, 1)
Next
Range("C:C").Clear
Range("C" & MinN).Resize(n) = ar
Loop Until total >= 10 And total <= 20 ' check total in range
MsgBox "Total=" & Format(total, "0.00"), vbInformation, try & " tries"
End Sub
You can use the Scripting.Dictionary object to check.
Given it's a "Dictionary", it requires that all keys are unique.
This is a crude implementation demonstrating the random filling of that dictionary with all numbers between 50 and 100.
Public Sub DoRandomize()
Dim objUnique As Object, i As Long, lngRandom As Long
Dim lngMin As Long, lngMax As Long, dblRandom As Double
lngMin = 50: lngMax = 100
Set objUnique = CreateObject("Scripting.Dictionary")
Do While objUnique.Count <> (lngMax - lngMin) + 1
Randomize objUnique.Count
lngRandom = (Rnd(objUnique.Count) * (lngMax - lngMin)) + lngMin
If Not objUnique.exists(lngRandom) Then
Debug.Print "Adding ......... " & lngRandom
objUnique.Add lngRandom, vbNull
Else
Debug.Print "Already used ... " & lngRandom
End If
Loop
End Sub
... you'd just need to pull out the relevant parts for your implementation but you can paste that code into your project, run it and see it work for yourself.
Ty Guys thats perfect =) i use this now and it works very nice + i understand my
misconception
Sub Zufallszahlen()
Const MaxN = 29
Const MinN = 1
Const Anzahl = 4
Const Awert = "X"
Dim ar, n As Long, r As Long
n = MaxN - MinN + 1
If n < Anzahl Then
MsgBox "Min to Max range must be >= " & Anzahl
Exit Sub
End If
ReDim ar(1 To n, 1 To 1)
For i = 1 To Anzahl
Do
r = 1 + Int(n * Rnd())
Loop Until ar(r, 1) = ""
ar(r, 1) = Awert
Next
Range("C:C").Clear
Range("C" & MinN).Resize(n) = ar
End Sub
Buts not finally completed.
Can I include this part in another if?
This is intended to ensure that the values ​​of the cells to the left of the cells randomly marked with an x ​​add up to between 10 and 20, for example. Otherwise the random cells should be regenerated

In Excel VBA, how could I compute sum of values which has a total limit that should not exceed $500, and then get corresponding product combination?

I have a table with two Columns Product and Price($).
Product
Price($)
A
100
B
400
C
350
D
50
E
515
F
140
I am trying to use vba to get combination of value of all products that will not exceed $500. I have been trying with this code and I am not sure how to proceed from this point on.
Sub getCombination()
Dim price As Long
Dim limit As Long
Dim i As Integer
Dim j As Integer
Dim combination As String
limit = 500
combination = ""
Range("B2").Activate
price = Range("B2").Value
For i = 1 To 6
For j = 1 To 6
If price <= limit Then
price = price + ActiveCell.Offset(j, 0).Value
combination = combination & ActiveCell.Offset(0, -1).Value & "," & ActiveCell.Offset(1, -1).Value
End If
Next j
Next i
ActiveCell.Offset(1, 0).Activate
MsgBox combination
End Sub
My Expected output is something like
A,B
A,C
A,C,D
B,D
C,F
A,D
C,D
(Please note: Not All output combinations are specified here!)
How should I proceed with the existing code? Or do I really have a better way for me to implement this?
Since the item can be used or not, that is a binary response. Using a binary number with the same number of digits as the number of items we can do all the combinations and do the testing:
Sub getCombination()
Dim rngArr As Variant
rngArr = ActiveSheet.Range("A2:B7")
Dim cnt As Long
cnt = 2 ^ UBound(rngArr, 1) - 1
Dim OutArray As Variant
ReDim OutArray(1 To cnt, 1 To 2)
Dim k As Long
k = 1
Dim i As Long
For i = 1 To cnt
Dim bin As String
bin = Application.Dec2Bin(i, UBound(rngArr, 1))
Dim delim As String
delim = ""
Dim j As Long
For j = 1 To UBound(rngArr, 1)
If Mid(bin, j, 1) = "1" Then
OutArray(k, 1) = OutArray(k, 1) & delim & rngArr(j, 1)
delim = ", "
OutArray(k, 2) = OutArray(k, 2) + rngArr(j, 2)
End If
Next j
If OutArray(k, 2) <= 500 Then
k = k + 1
Else
OutArray(k, 1) = ""
OutArray(k, 2) = 0
End If
Next i
Dim fnlarr As Variant
ReDim fnlarr(1 To k - 1)
For i = 1 To k - 1
fnlarr(i) = OutArray(i, 1)
Next i
Debug.Print Join(fnlarr, " | ")
End Sub

Problem with finding similar numbers in 2 columns in vba

i have problem with my code in vba. I have to find how much similar numbers are in column 1 and 2, but for example Column 1 (6,6,34,21,23,40) and column2 (49,34,6,9,6,20) should write 3 cause there are pairs 6-6, 6-6 and 34-34. I know its messy explenation but i hope its understandable. My code so far is:
Sub totolotek()
Dim i As Integer
Dim x As Integer
Dim j As Integer
Dim liczba As Integer
Dim suma As Integer
Dim ileLosowan As Integer
Range("B2:C7").Interior.Color = RGB(135, 134, 125)
Range("B2:B7").Font.ColorIndex = 3
Range("C2:C7").Font.ColorIndex = 5
ileLosowan = 7
Randomize
For i = 2 To ileLosowan
x = Int(Rnd * (49) + 1)
Range("c" & i) = x
Next i
For i = 2 To 7
liczba = Range("c" & i)
For j = 2 To 7
liczbe = Range("b" & j)
If liczbe = liczba Then
Range("c" & i).Interior.Color = RGB(255, 255, 0)
Range("b" & j).Interior.Color = RGB(255, 255, 0)
suma = suma + 1
End If
Next j
Next i
Range("c" & 9) = suma
End Sub
Try this. I invested some time and I added some lines of code. The macro find all the number pairs.
Example (6,6,3,4,2) (2,3,6,9,0) --> results 3: (6-6, 3-3, 2-2)
Sub totolotek()
Dim i As Integer
Dim x As Integer
Dim j As Integer
Dim liczba As Integer
Dim suma As Integer
Dim ileLosowan As Integer
Dim str_B As String, str_C As String, str_BC As String
Dim max_rand As Long
ileLosowan = 20 ' you can change the number of element in the column
max_rand = 49 ' max randum number
start_row = 2 'start_row
str_BC = "B2:C" & ileLosowan
str_B = "B2:B" & ileLosowan
str_C = "C2:C" & ileLosowan
Range(str_BC).Interior.Color = RGB(135, 134, 125)
Range(str_B).Font.ColorIndex = 5
Range(str_C).Font.ColorIndex = 5
Randomize
For i = start_row To ileLosowan
x = Int(Rnd * (max_rand) + 1)
Range("C" & i) = x
Next i
For i = start_row To ileLosowan
x = Int(Rnd * (max_rand) + 1)
Range("B" & i) = x
Next i
liczba_array = Range("B" & start_row & ":B" & ileLosowan).Value2
liczbe_array = Range("C" & start_row & ":C" & ileLosowan).Value2
ReDim ID_array(1 To 1)
ID_array(1) = max_rand + 1
Count = 1
For i = 1 To UBound(liczba_array, 1)
For j = 1 To UBound(liczbe_array, 1)
For k = 1 To UBound(ID_array, 1)
If ID_array(k) = j Then
GoTo out
End If
Next k
If liczba_array(i, 1) = liczbe_array(j, 1) Then
Range("B" & (start_row + i - 1)).Interior.Color = RGB(150 + Count * 20, 0, 0)
Range("C" & (start_row + j - 1)).Interior.Color = RGB(150 + Count * 20, 0, 0)
suma = suma + 1
ID_array(Count) = j
Count = Count + 1
ReDim Preserve ID_array(1 To Count)
Exit For
End If
Next j
out:
Next i
Range("C" & ileLosowan + 2) = suma
End Sub
Something like this will do what you're after. Just incorporate it into you're code cause I don't really know what's going on there.
Dim i As Long, j As Long, arr As Variant, Total As Integer
For i = 2 To 7 'Rows to loop through in the column
Total = 0
arr = Split(Range("A" & i), ",") 'Split column A using the comma
For j = 0 To UBound(arr) 'Loop through the split values
If InStr(Range("B" & i), arr(j)) > 0 Then 'Find if value is within other column
Total = Total + 1 'If it is, add 1 to total
End If
Next j
Range("C" & i) = Total 'Write total to another column on same row
Next i
Or if you want a basic function for it that you can use in your sheet you can use this:
Public Function CountMatches(Cell As String, Rng As Range, Optional Delim As String)
Dim i As Long, j As Long, arr As Variant, Total As Integer
If Delim = "" Then Delim = ","
If Rng.Count > 1 Then
CountMatches = "Please choose 1 cell to compare to."
Exit Function
End If
Total = 0
arr = Split(Cell, Delim) 'Split column A using the comma
For j = 0 To UBound(arr) 'Loop through the split values
If InStr(Rng, arr(j)) > 0 Then 'Find if value is within other column
Total = Total + 1 'If it is, add 1 to total
End If
Next j
CountMatches = Total
End Function
Use it like =CountMatches(A1,B1,",")

Parsing excel string of numbers using vba

I am trying parse a number string and create rows accordingly. On the left of the Example Data picture is an example of the input data with the right being my desired output. I am wanting to insert a unique row of data for each digit within the brackets for each number combination.
Here is an example of the code I used to try to solve the problem.
Option Explicit
Sub example()
Dim num As Variant
Dim x As Variant
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim m As Integer
Dim test As Variant
Dim test2 As Variant
Dim count As Integer
m = 0
For i = 1 To 3
num = Range("C" & 5 + i + m).Value
For j = 1 To Len(num)
test = Mid(num, j)
If Left(Mid(num, j), 1) = "[" Then
For k = 1 To Len(num) - (j + 1)
m = m + 1
Range("C" & 5 + m + i - 1).EntireRow.Insert
test2 = Left(Mid(num, j + k), 1)
Range("C" & 5 + m + i - 1).Value = Left(num, j - 1) + test2
Next k
End If
Next j
Next i
End Sub
Please consider using the following script:
Sub splitcombinations()
Dim rngCell As Range
Set rngCell = ThisWorkbook.Sheets(1).Range("A2")
Dim strCombinationDigits As String, strBaseDigits As String
Dim intCombinationDigitsLen As Integer
Dim x As Integer
Do While rngCell.Value2 <> ""
If InStr(rngCell.Value2, "[") > 0 Then
strCombinationDigits = Mid(rngCell.Value2, InStr(rngCell.Value2, "[") + 1, InStr(rngCell.Value2, "]") - InStr(rngCell.Value2, "[") - 1)
intCombinationDigitsLen = Len(strCombinationDigits)
strBaseDigits = Left(rngCell.Value2, InStr(rngCell.Value2, "[") - 1)
ActiveSheet.Range(rngCell.Offset(1, 0), rngCell.Offset(intCombinationDigitsLen - 1, 0)).EntireRow.Insert
For x = 1 To intCombinationDigitsLen
rngCell.Offset(x - 1, 0).Value2 = strBaseDigits & Mid(strCombinationDigits, x, 1)
rngCell.Offset(x - 1, 1).Value2 = rngCell.Offset(0, 1).Value2
rngCell.Offset(x - 1, 2).Value2 = rngCell.Offset(0, 2).Value2
Next
End If
Set rngCell = rngCell.Offset(intCombinationDigitsLen , 0)
Loop
End Sub

How can I set the range for the Sheet3 lots of columns called(attribute value1,attribute value2..N)

I want this code to search the column name called((attribute value1,attribute value2..N)
If that column contains fraction values, it should convert it to decimal. I'm using this macros(VBA).
The code is working but it is converting only one column(attribute value1).
It will take more time because I have multiple columns(attribute value2...N) that have fraction values.
Please help me out I am struck here.
Sub deci()
Dim LR As Long
Dim Dash As Long
Dim Whole As Double
Dim lngDataColumn As Long
Dim pi
lngDataColumn = 4
Sheets("Sheet3").Select
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
For r = 2 To LR
s = Cells(r, lngDataColumn)
arr = Split(s, ",")
For i = LBound(arr) To UBound(arr)
Whole = 0
P = InStr(arr(i), " IN")
If P > 0 Then
Worksheet = (Left((arr(i)), P - 1))
Else
Worksheet = arr(i)
End If
Dash = InStr(Worksheet, "-")
If Dash > 0 Then
Whole = Frac(Left(Worksheet, Dash - 1))
Worksheet = Mid(Worksheet, Dash + 1)
End If
af = Right(arr(i), Len(arr(i)) - P + 1)
evfrac = Whole + Left(CStr(Evaluate(Worksheet)), 5)
' evfrac = Whole + Format(Evaluate(frac), "0.###")
ss = ss & evfrac & af & ", "
Next i
Cells(r, lngDataColumn) = Left(ss, Len(ss) - 2)
ss = ""
Next r
End Sub
Function Frac(ByVal X As String) As Double
Dim P As Integer, N As Double, Num As Double, Den As Double
X = Trim$(X)
P = InStr(X, "/")
If P = 0 Then
N = Val(X)
Else
Den = Val(Mid$(X, P + 1))
If Den = 0 Then Err.Raise 11 ' Divide by zero
X = Trim$(Left$(X, P - 1))
P = InStr(X, " ")
If P = 0 Then
Num = Val(X)
Else
Num = Val(Mid$(X, P + 1))
N = Val(Left$(X, P - 1))
End If
End If
If Den <> 0 Then
N = N + Num / Den
End If
Frac = N
End Function
The reason it's only doing one column is because that's exactly what your telling it to do with this section of the code:
lngDataColumn = 4
Sheets("Sheet3").Select
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
Because your setting lngDataColumn as a fixed figure, your code is only executed on column 4. If you want to do more columns as a loop, you need to increment this value in the same maner you are incrementing r in your for loop.
For example:
lngDataColumn = 10
Sheets("Sheet3").Select
For 4 To lngDataColumn
LR = Cells(Rows.Count, lngDataColumn).End(xlUp).row
'Rest of code
Next lngDataColumn

Resources