Logical Error in my code - excel

I have written the code below in which I have to first identify smallest, 2nd smallest and so on numbers and then obtain the row numbers for them (I am saving the row numbers in a separate column, here column 50, in case there are more than one such number) and copy contents from one column (Here column 2) to another (Here Column 7) in the order of the row numbers, i.e. Smallest first, then 2nd smallest, and so on.
There are 172 such data sets starting at every 43 rows
This will continue till the sum of the numbers in the new column (45 row of Column 7 of each dataset) (To which the data is copied) is less than a specified number (45 row of Column 1 in every data set, i.e., A45 then A88)
EDIT: The sums being compared above, i.e. G45 is compared to A45 is through formula in the sheet itself
Dim m As Range, cl As Range, k As Double, b As Double, lIndex As Double, a As Double, multi As Double, l As Integer, x As Double
Set m = ActiveSheet.Range("E3:E40")
multi = 2 'To move to starting position of the data set
For i = 1 To 172
b = 45 + 43 * (i - 1)
For k = 1 To 38
a = Application.Small(m, k) 'To find the kth smallest number
l = 1
For j = 1 To 38 'To store the matching row numbers (Multiple instances) in column 50
Cells(j, 50).Value = 0 'Initializing to column no. 50 to 0
If Cells(j + multi, 5).Value = a Then 'Checking for match
Cells(l, 50).Value = j + multi 'Storing Row coordinates in column no. 50
l = l + 1
End If
Next j
'==============THE FOLLOWING IS THE AREA WHERE THE PROBLEM MIGHT BE======================
For o = 1 To l - 1 'To Copy the values based on the criteria
x = Cells(o, 50).Value
If Cells(b, 7).Value <= Cells(b, 1).Value Then '"CRITERIA" Checking whether sum of the column is less than or equal to sum of first column of set
Cells(x, 7).Value = Cells(x, 2).Value
End If
Next o
Next k
Set m = m.Offset(43)
multi = multi + 43
Next i
The problem is that the condition for copying copy (The sum should be less than certain value) is not working. It actually copies all the data from column 2 to column 7.
Can someone help in finding what might be the reason for this...
NOTE: I checked and confirmed that the code to store row numbers in column 50 is working fine. So the problem might be in the lower half of the code which is the for loop with variable "o"

I went ahead and pushed this myself with this.
Realized there were multiple mistakes:
I had to initialize the new column to 0. That I missed. Changed column from 7 to 6 due to some reasons.
I did not exit the main for-loop when the criteria was reached due to which the process went on even after the process was supposed to be complete. Used the Boolean variable flag for this.
While counting for the iterations involving the repetition of the value given by small function, the variable "l" was counted one +1. Made suitable adjustments. (Changed column from 50 to 500 due to some reason)
I observed that Excel was not updating the calculated valued by itself, so included Application.Calculate function at the beginning.
Here is the working code:
Application.Calculate
Dim m As Range, cl As Range, k As Double, b As Double, lIndex As Double, a As Double, multi As Double, l As Double, x As Double, Check As Double, flag As Boolean
l = 2
Set m = ActiveSheet.Range("E3:E40")
multi = 2 'To move to starting position of the data set
flag = False
For i = 1 To 172
b = 45 + 43 * (i - 1)
Cells(b, 6).Value = 0
For p = 3 To 40
Cells(p + ((i - 1) * 43), 6).Value = 0 'Initializing to column no. 6 to 0
Next p
For k = 1 To 38
If flag = True Then
flag = 0
Exit For
End If
If k + l - 2 <= 38 Then
a = Application.Small(m, (k + l - 2))
k = k + l - 2
Else
Exit For
End If
l = 1
For j = 1 To 38
Cells(j, 500).Value = 0 'Initializing to column no. 500 to 0
If Cells(j + multi, 5).Value = a Then 'Checking for match
Cells(l, 500).Value = j + multi 'Storing Row coordinates in column no. 500
l = l + 1
End If
Next j
For o = 1 To l - 1
x = Cells(o, 500).Value
Cells(x, 6).Value = 0
Cells(b, 6).Value = Cells(b, 6).Value + Cells(x, 2).Value
Check = Cells(b, 6).Value
If Cells(b, 6).Value <= Cells(b, 1).Value Then 'Checking whether sum of the column is less than or equal to sum of first column of set
Cells(x, 6).Value = Cells(x, 2).Value
Else:
Cells(x, 6).Value = Cells(b, 1).Value - (Cells(b, 6).Value - Cells(x, 2).Value)
Cells(b, 6).Value = Cells(b, 6).Value - Cells(x, 2).Value + Cells(x, 6).Value
flag = True
Exit For
End If
Next o
Next k
Set m = m.Offset(43)
multi = multi + 43
Next i
End Sub

Related

Type mismatch error when adding decimals to a variable "vSum"

Sub Calc()
Dim vSum As Single
Dim lRow As Integer
lRow = Sheet1.Range("C" & Rows.Count).End(xlUp).Row
vSum = 0: c = 0
Range("Z2").EntireColumn.ClearContents
For j = 2 To lRow Step 10
If Cells(j, 3).Value <> 0 Then
vSum = vSum + Cells(j, 3)
c = c + 1
Range("Z" & c + 1).Value = Cells(j, 3)
End If
Next j
Range("AB2").Value = Format(vSum / c, "00.00")
Range("AB5").Value = c
Call StDev
End Sub
The purpose is to find the average. I know there is an easier way but I want to understand the error.
The Value of a cell is its content - not its numerical value. So if you have a string in that cell, you will get the string.
The check If Cells(j, 3).Value <> 0 Then will compare the content of the cell with the number 0. Any content of the cell except 0 (and an empty cell) will return True, including the mentioned strings. But vSum is a number and if the cell contains as string, this will give you a Type mismatch.
Easiest way is to use the isNumeric-function to check if the cell contains a number and use the Val-Function to check if the value is not 0
If isNumeric(Cells(j, 3).Value And Val(Cells(j, 3).Value) <> 0 Then

Insert a row n times

I´ve an Excel file with 10 Columns. In columns 2, 3, 4 I have a number or a dash.
If the sum of these 3 cells is greater than 1, I need to replace that entire row with n rows that have only one of the columns with the value 1 but the other cells stay the same.
Example
1 - - #-> leave it as is
- 2 - #-> replace that row with 2 rows : - 1 - ; - 1 -
2 - 1 #-> replace that row with 3 rows : 1 - - ; 1 - - ; - - 1;
I managed to iterate from bottom up, but I´m having trouble storing a row in memory, manipulate it and insert below.
Sub Test()
Dim rng As Range
Dim count20, count40, count45, total, i As Integer
Set rng = Range("A3", Range("A3").End(xlDown))
For i = rng.Cells.count To 1 Step -1
count20 = 0
count40 = 0
count45 = 0
total = 0
count20 = Cells(rng.Item(i).Row, 10).Value
If count20 > 1 Then
total = total + count20
End If
count40 = Cells(rng.Item(i).Row, 11).Value
If count40 > 1 Then
total = total + count40
End If
count45 = Cells(rng.Item(i).Row, 12).Value
If count45 > 1 Then
total = total + count45
End If
If total <> 0 Then
MsgBox total
End If
Next i
End Sub
EDIT 2
I’ve provided alternative code based on your latest comment. It uses columns J-L (10-12) as the numeric cells to be changed, and columns A-I (1-9) and M-AD (13-30) as the cells with text to be preserved. As before, sheet 1 starting in row 3 is assumed, and you can change this to whatever you need.
Option Explicit
Sub testJtoL()
Dim LastRow As Long, i As Long, j As Long, c As Long, _
insertR As Long, TopRow As Long, BottomRow As Long
Dim b As Range
Dim ws As Worksheet
'*** This code is based your values being in Columns J-L (10-12) in sheet 1 ***
'Set sheet 1 as ws
Set ws = Sheet1
'Sheet1 column J is used here to get your last row
LastRow = ws.Cells(Rows.Count, 10).End(xlUp).Row
'*** This code is based your values starting in Row 3 ***
For c = LastRow To 3 Step -1
'Determine number of rows to insert based on sum of that row
insertR = Application.WorksheetFunction.Sum(Range(Cells(c, 10), Cells(c, 12))) - 1
If insertR = 0 Then GoTo skip
'STEP 1 insert the correct number of rows
With ws.Range(Cells(c + 1, 1), Cells(c + insertR, 30))
.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
End With
'STEP 2 fill the values into the correct number of rows
insertR = insertR + 1
With ws.Range(Cells(c, 1), Cells(c, 30))
.Resize(insertR, 30).Value = .Value
End With
TopRow = c
If insertR = 0 And c = 3 Then
BottomRow = c
Else
BottomRow = c + insertR - 1
End If
'STEP 3 replace all numbers with 1 or "-"
'Replace numbers in column J
If ws.Range(Cells(c, 10), Cells(c, 10)).Value = "-" Then GoTo SkipA
i = ws.Range(Cells(c, 10), Cells(c, 10)).Value
j = 1
For Each b In ws.Range(Cells(TopRow, 10), Cells(BottomRow, 10))
If j <= i Then
b.Value = 1
b.Offset(0, 1).Value = "-"
b.Offset(0, 2).Value = "-"
Else
b.Value = "-"
End If
j = j + 1
Next b
SkipA:
'Replace numbers in column K
j = 1
For Each b In ws.Range(Cells(TopRow, 11), Cells(BottomRow, 11))
If b.Value = "-" Then GoTo SkipB
i = b.Value
If j <= i Then
b.Value = 1
b.Offset(0, 1).Value = "-"
Else
b.Value = "-"
End If
j = j + 1
SkipB:
Next b
'Replace numbers in column L
j = 1
For Each b In ws.Range(Cells(TopRow, 12), Cells(BottomRow, 12))
If b.Value = "-" Then GoTo SkipC
i = b.Value
If j <= i Then
b.Value = 1
Else
b.Value = "-"
End If
j = j + 1
SkipC:
Next b
skip:
Next c
End Sub

Fill down rows randomly by Loop

I have the values on the range "A1:O1".
Each Column has a unique value in this range.
I need help to develop a loop that will fill down 04 times on each column the same Top Value (Column Value). Below a Pseudo Code
Sub FillDownRowsRandomly()
Dim i As Integer, j As Integer
'RamdomRow=Total of 04 unique ramdom numbers
'choosen from 01 to 06 {1,2,3,4,5,6}
'meaning that in a loop of 6 interations, when fill down
'2 will be Null or empty
'
For i = 1 To 15 'Columns "A" To "O"
For j = 2 To 7 '
'
Cells(RandomRow, i).Value = Cells(1, i).Value
Next j
Next i
End Sub
Below an Image where will be possible identify the result of the code.
Disregard the "Null" word written in the cells. I wrote that just to clarify that during the random loop, the code "ignored that cell".
Maybe something like:
Sub FillDownRowsRandomly()
Dim x As Long, y As Long, z As Long
With Sheet1 'Change accordingly
For y = 1 To 15
z = 0
Do While z < 4
x = Int((7 - 2 + 1) * Rnd + 2)
If .Cells(x, y) <> .Cells(1, y) Then
.Cells(x, y) = .Cells(1, y)
z = z + 1
End If
Loop
Next y
End With
End Sub
Loop the columns and randomly place the values till there are four in the six rows.
Sub FillDownRowsRandomly()
ActiveSheet.Range("A2:O7").ClearContents
Dim i As Long
For i = 1 To 15 'iterate the columns
Do Until Application.CountIf(ActiveSheet.Cells(2, i).Resize(6), ActiveSheet.Cells(1, i).Value) >= 4
Dim j As Long
j = Application.RandBetween(2, 7)
ActiveSheet.Cells(j, i).Value = ActiveSheet.Cells(1, i).Value
Loop
Next i
End Sub

Update Cost Centres from Other Sheet using Excel VBA

I am making a list of financial cost centres of different departments of a company every time it updates in the sheet "Union" i have to update it in number of sheets so I am trying to develop a vba to do that but failed to get desire results, since I am new to vba programming so any favour will just like to fetch fish into the water.
Here is the source sheet "Union"
It goes on till column45 like this having costcentres detail of individual departments.
Now the sheet I want to update is "REC_INT"
It also goes around 250 rows.
You see cost centres are updated in 1st and 3rd but in 4th cost centre 1002-94q not updated and similary more when we go down, moreover when I run the vba again it will update the updated costcentres again and 1002-610 will appear two times here similarly 102-60001.
Sub CostCentresUpdates()
Dim i As Long
Dim x As Long
Dim j As Long
Dim z As Long
Dim q As Long
Dim a As Long
Shex = 200
For i = 10 To Shex Step 1
For j = 1 To 50 Step 1
If Worksheets("REC_INT").Cells(i, 3).Value = Worksheets("Union").Cells(1, j).Value Then
For z = 2 To 20 Step 1
For x = i + 1 To 20 Step 1
If IsEmpty(Worksheets("Union").Cells(z, j).Value) Then
GoTo y
End If
If Worksheets("Union").Cells(z, j).Value = Worksheets("REC_INT").Cells(x, 4).Value Then
GoTo q
End If
If Worksheets("Union").Cells(z, j).Value = "" Then
GoTo a
End If
Worksheets("REC_INT").Rows(x + 1).Insert shift:=xlShiftDown
Worksheets("REC_INT").Rows(x).EntireRow.Copy _
Destination:=Worksheets("REC_INT").Range("A" & Worksheets("REC_INT").Rows.Count).End(xlUp).Offset(x - 1)
Worksheets("REC_INT").Cells(x + 1, 3).Value = ""
Worksheets("REC_INT").Cells(x + 1, 18).Value = ""
Worksheets("REC_INT").Cells(x + 1, 19).Value = ""
Worksheets("REC_INT").Cells(x + 1, 20).Value = ""
Worksheets("REC_INT").Cells(x + 1, 4).Value = Worksheets("Union").Cells(z, j).Value
Next x
q:
Next z
End If
a:
Next j
y:
Next i
End Sub

FIFO using Excel Formula or VBA

Here is my "IN" List -
PN Qty Price
A 100 5
B 150 6
C 150 7
D 50 -9
E 100 5
F 5 9
G 20 6
I 5 7
J 15 7
J 30 10
K 100 10
K 50 10
A 20 8
Here is my "OUT" List -
PN Qty
A 120
B 10
C 110
D 60
E 100
J 20
J 10
Expected Results -
Manual Formula to calculate Price for PN = "A" = ((100*5)+(20*8))/120
PN Qty Price Total
A 120 5.5 660
B 10 6 60
C 110 7 770
D 60 -9 -540
E 100 5 500
J 20 7.75 155
J 10 10 100
I want to implement FIFO logic to calculate the Total Price in "OUT" List based on "Quantity" in "IN" List.
When you have tables like this, the outgoing button with following code:
Private Sub Outgoing_Click()
Dim pn As String
Dim ammout As Long
Dim current As Long
pn = InputBox("Which Item do you want to take out?")
ammount = InputBox("How Item do you want to take out?")
Dim cells As Long
Dim fifo As Double
counter = 1 //line where your table starts
current = 0
fifo = 0
Do Until IsEmpty(cells(counter, 13).Value Or current = ammount)
If cells(counter, 13).Value = pn Then
If cells(counter, 14).Value > (ammount - current) Then
fifo = fifo + (ammount - current) * cells(current, 15).value
current = ammount
Else
fifo = fifo + cells(counter, 14).Value * cells(counter, 15).Value
current = current + cells(counter, 14)
cells(counter, 14).Value = 0
End If
counter = counter + 1
Loop
fifo = fifo / ammount
End Sub
Should be work.
I did not match lie if you have enough in your current list and others so the validation part is missing.
your "Expected Results" doesn't match your "Manual Formula"
following this latter
Option Explicit
Sub main()
Dim cell As Range
Dim dictSum As Object
Dim dictRept As Object
Set dictSum = CreateObject("Scripting.Dictionary")
Set dictRept = CreateObject("Scripting.Dictionary")
With Worksheets("IN")
For Each cell In .Range("A2", .Cells(.Rows.Count, 1).End(xlUp))
dictSum(cell.Value) = dictSum(cell.Value) + cell.Offset(, 1).Value * cell.Offset(, 2).Value
dictRept(cell.Value) = dictRept(cell.Value) + cell.Offset(, 1).Value
Next
End With
With Worksheets("OUT")
For Each cell In .Range("A2", .Cells(.Rows.Count, 1).End(xlUp))
cell.Offset(, 2) = dictSum(cell.Value) / dictRept(cell.Value)
cell.Offset(, 3) = cell.Offset(, 1) * cell.Offset(, 2)
Next
End With
End Sub

Resources