I'm trying to write a simple script that compares and flags similar transactions (rows) and pastes them at the bottom of the sheet. The transactions which are to be flagged should meet the following criteria.
The $amount in the transactions is greater than 4000 or less than -4000 (column 11)
The two transactions being compared have the same part number (column 3)
Two transactions with similar dollar amounts (between 90-110% of each other) and opposite in number sign
Sub checktrans()
Dim newLastRow, rowcount As Long
Dim row, row2, amountcol, partnumcolcol As Integer
amountcol = 16
partnumcol = 3
rowcount = 27307
newLastRow = 37309
For row = 1 To rowcount
For row2 = 1 To rowcount
If Cells(row, amountcol) > 4000 Or Cells(row, amountcol) < -4000 Then
If row <> row2 Then
If Cells(row, partnumcol) = Cells(row2, partnumcol) Then
If Abs(Cells(row, amountcol)) > 0.9 * Abs(Cells(row2, amountcol)) And Abs(Cells(row, amountcol)) < 1.1 * Abs(Cells(row2, amountcol)) Then
If (Cells(row, amountcol) < 0 And Cells(row2, amountcol) > 0) Or (Cells(row, amountcol) > 0 And Cells(row2, amountcol) < 0) Then
ActiveSheet.Rows(row).Copy
ActiveSheet.Rows(newLastRow).PasteSpecial xlPasteAll
newLastRow = newLastRow + 1
ActiveSheet.Rows(row2).Copy
ActiveSheet.Rows(newLastRow).PasteSpecial xlPasteAll
newLastRow = newLastRow + 1
End If
End If
End If
End If
End If
Next row2
Next row
End Sub
I wrote the code above, and it seems to work for a low number of rows (below 500), but when the number of rows exceeds 27000 it goes into a never ending loop that keeps pasting new rows onto the sheet. It also posts each couple of transactions twice, which I understand is flaw in the logic which I have to work out as well.
P.S I am a giant noob when it comes to this, haven't programmed much before, and I'm just learning now to make my life easier.
First thing you can do is to start second loop from the point where first loop is currently. Like For row2 = row + 1 to rowcount. You checked previous records already. This will also fix problem with duplicates and you can delete If row <> row2.
Second, is to use Application.ScreenUpdating = False at the beginning of the macro and Application.ScreenUpdating = True at the end. This turns off screen updating while your macro is running and can be a huge improvement in performance.
At the end you can join all Ifs into one using And, however I don't know if this will improve performance.
Related
I ran into a problem when I try to add the first 10 even numbers in a column regardless of the number of inputs someone has entered into said column.
The issue occurs when there are less than 10 inputs (in my case 7) and I have tried to break the loop if there are no more numbers after the last one but it doesn't seem to work as it crashes Excel; most probably because it loops infinitely.
The original code was fine until I entered below 10 even numbers. When I did it would loop infinitely and crash so I inputted a forceful break in the code (hence the Count=999) but it does not seem to work
Sub TenPosInt()
Dim Total As Integer, size As Integer, myRange As range
Dim Count As Integer
Count = 1
Set myRange = range("W:W")
size = WorksheetFunction.CountA(myRange)
While Count <= 10
If IsEmpty(Cells(Count, "W")) Then
Count = 999
End If
If Cells(Count, "W").Value Mod 2 = 0 Then
Total = Total + Cells(Count, "W").Value
Count = Count + 1
End If
Wend
MsgBox Total
End Sub
My Inputs are currently 2,4,6,5,2,4,6,8,1,3,5 so it does not meet the 10 even integers, however I still want it to run regardless (hence the Count=999 line). The correct return should be 32.
A Do-While/Until loop is recommended instead of While-Wend (see this).*
Here I use a separate counter for row and the number of even values (and stole David's idea of combining the two conditions in the Do line).
Sub TenPosInt()
Dim Total As Long, r As Long, Count As Long
r = 1
Do Until Count = 10 Or Cells(r, "W") = vbNullString
If Cells(r, "W").Value Mod 2 = 0 Then
Total = Total + Cells(r, "W").Value
Count = Count + 1
End If
r = r + 1
Loop
MsgBox Total & " (" & Count & " even numbers)"
End Sub
*Actually I would be more inclined to use one of the other gent's answers, but I have tried to stick as close to yours as possible. (Also a good idea to check a cell is numeric before checking for even-ness.)
Just for fun - here is an approach that uses a For...Next loop, allows for non-numeric entries in Column W, and handles the possibility of blank rows between entries.
Sub TenPosInt()
Dim lastRow As Long
lastRow = Cells(Rows.Count, "W").End(xlUp).Row
Dim i As Long
For i = 1 To lastRow
If Not IsEmpty(Cells(i, "W")) Then
If IsNumeric(Cells(i, "W")) Then
If Cells(i, "W").Value Mod 2 = 0 Then
Dim counter As Long
counter = counter + 1
Dim total As Long
total = total + Cells(i, "W").Value
If counter = 10 Then Exit For
End If
End If
End If
Next
MsgBox total
End Sub
Why not use a standard for loop across a range? this would give more specific inputs for the subroutine.
Description of what is occuring below has been commented out to allow for copy/pasting more easily.
'Define your range (you use columns("W"), but narrow that)... assuming you start in row 2 (assumes row 1 is headers), move to the last row, of the same columns:
lr = cells(rows.count,"W").end(xlup).row
'so you know the last row, loop through the rows:
for i = 2 to lr
'Now you will be doing your assessment for each cell in column "W"
if isnumeric(cells(i,"W").value) AND cells(i,"W").value mod 2 = 0 then
s = s + cells(i,"W").value
counter = counter + 1
if counter = 10 then exit for
end if
'Do that for each i, so close the loop
next i
'You now have determined a total of 10 items in the range and have added your items. Print it:
debug.print s
Edit1: got a comment to not break-up the code in an explanatory fashion, so I have added ' to comment out my explanations in an effort to make my coding portion copy/pasteable as a lump.
RawData is an excel report drawn from an employee database. (Tried to attach the workbook but didn't see how to do that). RawData contains multiple, unwanted duplicate items for some employees. I'm told this is because of a Cartesian join in the employee database that creates the RawData report. Whether or not that's the case, I have no control over how the RawData report is produced. It is what it is.
I need to clean up the RawData report so that the end product looks like the CorrectedView tab, which I corrected manually. RawData can, at times, be several thousand rows so automating the clean-up would be a huge help.
The structure of RawData is in five groupings of columns: Employee Basic Info (cols A-E), Education (cols F-H), Awards (cols I-L), Certifications (cols M-Q) and Accomplishments (cols R-T). In the CorrectedView, what I did was:
Removed the duplicates for each employee in each of the five column sections
Moved the remaining data for each employee upward so that each employee's info begins on his/her first row
Removed any blank rows created between employees after doing #2 above.
I'm looking for a way to automate the process. I have some code (shown below) that accomplishes #1 for the Basic Info section but that's as far as I can get. Thanks for any help.
Sub DelSame()
Dim LastRow As Long, i As Long
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = LastRow To 3 Step -1
If Cells(i, 1).Value = Cells(i - 1, 1).Value Then Rows(i).Range("a1:e1").ClearContents
Next i
End Sub
You pretty much have it... use AND for multiple criteria:
Dim LastRow As Long, i As Long
LastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = LastRow To 3 Step -1
If Cells(i, 1).Value = Cells(i - 1, 1).Value AND Cells(i, 2).Value = Cells(i - 1, 2).Value AND Cells(i, 3).Value = Cells(i - 1, 3).Value Then
Rows(i).Delete
End If
Next i
Edit1:
So, the above suits the first grouping of columns... now for the hard part.
You can use AND sections for ALL columns, so you truly don't get any duplicates between rows (should actually fit the bill, as to not accidentally remove any items).
To get more involved, before you remove any rows, you will want to start storing values to more appropriately work with each grouping of columns, such that you work with rows a to b (untested code).
Dim a as Long, b as Long, i as Long, lr as Long
lr = cells(rows.count,1).end(xlup).row
For i = lr to 3 step -1
If cells(i,1).value = cells(i+1,1).value then
If a = 0 then
a = i + 1
End If
Else
If a > 0 AND b = 0 then
b = i + 1
End If
End If
If b > 0 AND a > 0 Then
'perform narrowed actions on range(cells(a,1),cells(b,1))
a = 0 'resets for next grouping
b = 0 'resets for next grouping
End If
Next i
I have a big Excel sheet with data taken from the sensors from one windfarm.
It is in one column, one below the other, just a clean numbers, integer (example 1435). Those columns represent data from every 15 minutes.
I need to get the data from it and transform it to 10 min data.
My idea was to divide it by 3 (get 5 min data) and just add two of those.
But I need the formula in excel which does that in the other column.
So takes the first column
divide it by 3,
put it in the column next to it,
copy it in 2 more rows below
then repeat the procedure but with the other value in the 15 min data, below the first one.
I hope it makes sense,
much appreciated for any assistance
Just create some simple loops.
Sub tenmindata()
Dim lastRow As Integer
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
lastRow = Range("A" & Rows.Count).End(xlUp).Row
j = 3
For i = 3 To lastRow
For k = 1 To 3
Cells(j, 7) = Cells(i, 3).Value / 3
j = j + 1
Next k
Next i
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
Not sure if I got your question right but try this:
=A1/3*2
Post that in the column next to your data and doubleclick the small black dot:
https://abload.de/img/excelbwbzz.png
My formula below subtracts a cell until it reaches zero, and moves to the next one. The subtraction is based on the value “B”. Each time the formula comes across the value “B”, this action is performed.
Question: I have been trying to advance this to formulae, in that each time “B” is found that cell is minuses until zero and those amount multiple by the adjacent price.
could you please provide me with a formula which does this ?
Example: when it comes across the first B the full value of 100 x 10 will be multiplied and the reminder 50 will be multiplied by 15 i.e. 50 x 15 price of the next A. These values will be summed.
=MAX(SUMIF($A$2:A2,"A",$B$2:B2)-SUMIF($A$2:$A$10,"B",$B$2:$B$10),0)
The reminder of the 50 is coming from the difference between the B 150 - A 100 , which leaves 50 to be still absorbed .
Further Calculation for explanation:
Apologies thats meant to say calculation of 6000
Your question is still very unclear. What does "My formula below subtracts a cell until it reaches zero" mean? Also, as OldUgly pointed out, it seems that you are ignoring the second A. Since we can't understand each other, take a look at the code below and try to rewrite it yourself to fit your needs. It assumes the data is in a sheet named "Data", and that there is a button (Button1) to run the code.
Dim lLastRow As Long
Dim i As Integer
Dim QtyNumberA, QtyNumberB, QtyNumberRem As Integer
Sub Button1_Click()
lLastRow = Worksheets("Data").Cells(2, 1).End(xlDown).Row 'Rows with data, starting 2nd row (titles in the first)
QtyNumberA = 0 'Variable for storing quantities of A
QtyNumberB = 0 'Variable for storing quantities of B
QtyNumberRem = 0 'Variable for storing quantities remaining
For i = 2 To lLastRow 'scan all rows with data
If (Worksheets("Data").Cells(i, 1).Value = "A") Then
QtyNumberA = QtyNumberA + Worksheets("Data").Cells(i, 2).Value
ElseIf (Worksheets("Data").Cells(i, 1).Value = "B") Then
QtyNumberB = QtyNumberB + Worksheets("Data").Cells(i, 2).Value
QtyNumberRem = QtyNumberA - QtyNumberB
Worksheets("Data").Cells(i, 6) = QtyNumberRem
End If
Next
End Sub
I'm trying to speed up a COUNTIFS formula in a table I have.
The table is over 60k rows and the COUNTIFS has three conditions. The formula right now looks like this:
=IF(AND(COUNTIFS([Vessel],[#Vessel],[Date],">"&[#Date],[ETA],"<="&[#ETA]+20)=0,[#Arrived]=1,[#Sailed]=1,[#Date]<MAX([Date])),1,0)
The problem is that the calculation takes a very long time and it triggers everytime something change, even the filter. I don't want to turn calculations to manual in this sheet.
The purpose of the formula is to find the next occurence of the vessel in the line, the ETA can be slightly changed from day to day or the same ship can appear months later. I need to confirm if the vessel appears with the same ETA (or up to 20 days of difference) on another day.
Is there any other solution to this problem?
Maybe try building this as a macro instead, that way you would have control over when it executes.
Here is a start on a method for doing this. It gets the job done but breaks on an error on/after the last line is processed. Edit : Fixed and tested
Public Sub shipcheck()
Application.ScreenUpdating = False
Dim x As Long
Dim y As String
Dim counter As Long
For x = 2 To Range("A85536").End(xlUp).Row ' Assuming data has headers
y = Cells(x, 1) ' This assumes your vessel is in the first column
counter = x + 1
Do
If cells(counter,1) = "" Then Exit Do
If y = Cells(counter, 1) Then
If Cells(x, 2) <> Cells(counter, 2) Then 'This assumes your date is the second column
If DateDiff("d", Cells(x, 3), Cells(counter, 3)) > 20 Then ' this assumes ETA is your third column
Cells(x, 4) = 1 'This assumes the positive test is the fourth column
Cells(counter, 4) = 1
Exit Do
Else
End If
Else
End If
Else
End If
counter = counter + 1
Loop
Next x
Application.ScreenUpdating = True
End Sub