Issue regarding .Find method in VBA - excel

In this line of code here
w6 = Range(NewNewNewDataColumn & MOPNumber":" & NewNewNewDataColumn).Find(What:=w5, after:=Range(NewNewNewDataColumn & 1), searchdirection:=xlPrevious).Row
I am looking for w5 in a column which goes
Row 1 = 25
Row 2 = 24
Row 3 = 23
.
.
.
Row 26 = 0
Row 27 = 1
Row 28 = 2
.
.
.
Row 49 = 23
Row 50 = 48
Row 51 = 25
This method is used as these number are referance points for Cells that contain the useful information.
where w5 is the number 0 to 25. Works fine expect for one slightly major issue, which is instead of finding the number "1" its fine the first mention of 1 so in this case "21" So will give back the row number for the number 21 not the number 1. Is there a way to change the code to search for the entire mention of w5. Does that make sense?
Thank for any help your able to provide
Mark

w6 = Range(NewNewNewDataColumn & ":" & NewNewNewDataColumn).Find(What:=w5, after:=Range(NewNewNewDataColumn & 1), LookAt:=xlWhole, searchdirection:=xlNext).Row
Above is the line of code thatg I used and solved it, the LookAt:=xlWhole i belive was the critical statement within the line enabling the code to work as intended.

Related

Counting number of instances according to date difference (Excel/VBA)

I have the following data:
Excel Table Screen Capture
That is:
Acquirer ID ||| Target ID (not useful) ||| Date
123 ||| 456 ||| 20/01/2020
789 ||| 910 ||| 28/02/2019
I would like an additional column where for each acquirer I have a count of how many acquisitions it made in the past 3 years.
Therefore, for each acquirer ID with a given date, I need to count how many times that ID appears with a date less than 3 years distant from that date.
Thus if an acquirer made an acquisition in 2020, 2016, 2015 and 2014, in each instance, the count will amount to 0, 2, 1, 0 respectively for that given acquirer.
I have tried with COUNTIFS(), IF (), VLOOKUP(), but I could not get the result wanted as, once the condition is met, it sums all the IDs irrespective of the dates.
I also tried writing a Macro on VBA but my knowledge of the language is basically 0. I post the code in case it gives a better idea of the problem
Dim Sheet As Worksheet
Set dbs = ThisWorkbook.Sheets("db")
Dim i As Integer, j As Integer, count As Integer
lr = dbs.Cells(Rows.count, 1).End(xlUp).Row
x = 0
For i = 2 To lr
For j = i + 1 To lr
Set myrange = Range("i:lr")
If dbs.Cells(i, 4).Value - Application.WorksheetFunction.VLookup(dbs.Cells(i, 4).Value, myrange, 4, False) < 3 Then
'I get a bug with Application.WorksheetFunction.VLookup, it might be that an error must be dealt with in case of missing values
count = count + 1
End If
Next j
Next i
dbs.Cells(i, 5).Value = count
End Sub
Any help is really appreciated, thank you in advance.
For Acquirer in A2:A10 and Dates in C2:C10, this formula goes in D2 and counts the number of records where all of the following are true:
Acquirer ID is the same as A2
Date is less than the date in C2
Date is greater than or equal to 3 years before the date in C2
=COUNTIFS($A$2:$A$10,A2,$C$2:$C$10,"<"&C2,$C$2:$C$10,">="&EDATE(C2,-36))

VBA to list number combinations sequentially in two columns

I would like to list the possible combinations of numbers 1 to 26 in columns A and B, in the following format:
1 1
1 2
1 3
1 4
...
1 25
1 26
2 1
2 2
2 3
...
etc
For Column A, I could have:
Range("A1:A26") = 1
Range("A27:A52") = 2
etc
But this seems long winded and there must be a better way of doing this.
I have found this code as an answer to another question which gives
Range("A1")=-500
Range("A1").Select
Selection.DataSeries Rowcol:=xlColumns, Type:=xlLinear, Date:=xlDay, _
Step:=1, Stop:=500, Trend:=False
as a way to list numbers sequentially but I would need to amend it to reach 26 and then start again from 1, all the way to the end of the list in Column A. How can I achieve this?
Try these formulas and then drag down as far as you need (row 676):
A1 =ROUNDUP(ROW()/26,0)
B1 =IF(MOD(ROW(),26)=0,26,MOD(ROW(),26))
A VBA solution as an alternative to the Excel formulas given in the previous reply. (Untested)
MyRow = 1 ' or wherever you want to start
MyCol = 1 ' or wherever you want to start
For A = 1 to 26
For B = 1 to 26
Cells(MyRow,MyCol).Value = A
Cells(MyRow,MyCol+1).Value = B
MyRow = MyRow + 1
Next B
Next A
The advantage of this approach instead of the formula described above is that it is not dependent on where you place the data. It can also be adapted if you want (e.g.) combinations of 5 to 24, or even A is 1 to 26 and B is 1 to 10.
But, the formula described in the previous answer is also a cool way of doing it.
If you changed:
For A = 1 to 26
For B = 1 to 26
to
For A = 1 to 26
For B = A to 26
then this would be useful for a non-directional combination (e.g. if [1,2] is the same as [2,1]).

to get last row of each day from excel sheet

i need to find the last record of each day in excel if there are multiple entries
*******intention is to get EOD balance ROW OF EACH DATE********
like i have data in excel something like this
date CR_DR amount EOD balance
----------------------
7/9/2017 19:09 CR 10 10
7/10/2017 18:37 CR 25 35
7/10/2017 21:06 DR 10 25
7/11/2017 19:21 CR 15 40
7/15/2017 14:17 DR 20 20
7/17/2017 17:12 CR 100 120
7/18/2017 7:44 DR 30 90
7/18/2017 14:08 DR 50 40
7/18/2017 16:52 CR 120 160
for which i need to get data like (get the last row of each day)
7/9/2017 19:09 CR 10 10
7/10/2017 21:06 DR 10 25
7/11/2017 19:21 CR 15 40
7/15/2017 14:17 DR 20 20
7/17/2017 17:12 CR 100 120
7/18/2017 16:52 CR 120 160
Solution 1
Enter the following formula in Cell F2
=IFERROR(MAX(IF(INT($A$2:$A$10)=INT(INDEX($A$2:$A$10, MATCH(0, FREQUENCY(IF(EXACT(INT($A$2:$A$10), TRANSPOSE(INT($F$1:F1))), MATCH(ROW($A$2:$A$10), ROW($A$2:$A$10)), ""), MATCH(ROW($A$2:$A$10), ROW($A$2:$A$10))), 0))),$A$2:$A$10,0)),"")
This is an array formula so commit it by pressing Ctrl+Shift+Enter. Drag/Copy down as required.
Then in Cell G2 enter
=VLOOKUP($F2,$A$2:$D$10,COLUMN(C1)-COLUMN($A$1),FALSE)
Drag this formula across (to right) till Cell I2 and down as required.
See image for reference.
Solution 2
Instead of using an ugly looking long formula, here we'll use a helper column.
In Cell F2 enter the following formula
=MAX(IF(INT($A$2:$A$10)=INT(A2),$A$2:$A$10,0))
This is an array formula so commit it by pressing Ctrl+Shift+Enter. Drag/Copy down as required.
Then in Cell G2 enter
=IFERROR(INDEX($F$2:$F$10,MATCH(0,INDEX(COUNTIF($G$1:G1,$F$2:$F$10),0,0),0)),"")
Drag/Copy down as required.
Finally, in Cell H2 enter
=VLOOKUP($G2,$A$2:$D$10,COLUMN(C1)-COLUMN($A$1),FALSE)
Drag this formula across (to right) till Cell J2 and down as required.
See image for reference.
EDIT : As per comment.
Instead of
=VLOOKUP($G2,$A$2:$D$10,COLUMN(C1)-COLUMN($A$1),FALSE)
use below formula in Cell H2
=INDEX(B$2:B$10,MAX(IF($A$2:$A$10=$G2,ROW($A$2:$A$10)-ROW(INDEX($A$2:$A$10,1,1))+1)))
This is an array formula so commit it by pressing Ctrl+Shift+Enter. Drag this formula across (to right) till Cell J2 and down as required. Drag/Copy down as required.
Screen-Shot :
Ok, this is crude and I'm sure there are "proper" ways to do this, but it works for what you want to do. I used columns A thru D for the data. In column F I used the formula =Left(A3,5) and copied it down. You will have to modify according to your situation. Hope this helps or gets you headed in right direction. Good Luck
Sub FindLast()
'FIND LAST LISTED DATE AND COPY
Dim myCount, myCount2, myRange, myRow, x, y, r
r = 3
myCount = Sheets("Sheet1").UsedRange.Rows.Count - 2
MsgBox "Rows used are " & myCount
For x = 3 To myCount Step 1
y = Range("F" & x).Value
MsgBox "Value of x is " & x
MsgBox "Value of y is " & y
myCount2 = WorksheetFunction.CountIf(Range("F3:F" & myCount + 2), y)
MsgBox "myCount2 value is " & myCount2
Max_date = Application.WorksheetFunction.Max(Range("A" & x & ":" & "A" & x + myCount2 - 1))
myRow = Range("A" & x + myCount2 - 1).Row
MsgBox "myRow number is: " & myRow
MsgBox CDate(Max_date)
Sheets("Sheet1").Range("I" & r).Value = Max_date
Sheets("Sheet1").Range("J" & r).Value = Range("B" & myRow).Value
Sheets("Sheet1").Range("K" & r).Value = Range("C" & myRow).Value
Sheets("Sheet1").Range("L" & r).Value = Range("D" & myRow).Value
r = r + 1
If myCount2 <> 1 Then
x = x + (myCount2 - 1)
Else
x = x
End If
Next x
End Sub
You will notice there are a lot of message boxes. I used these to test the parameters and make sure they were coming out like I wanted. When you are comfortable with how it's working, just comment them out.
Also, the output is set to I3 thru L8 for the example you posted. Please make sure to edit these if your real sheet has any data in these areas. My suggestion is test first to get familiar with what's happening. I did't put any "failsafes" or "exits" in, as I ran out of time. There are plenty of examples on this site to help with that.
Regards
It requires entering the dates in column A (I didn't feel motivated enough to figure out how to pull the unique ones out), but if you are feeling spunky, you could use some array formulas. :-)
Column A Column B C D E
7/9/2017 7/9/2017 19:09 CR 10 10
7/10/2017 7/10/2017 21:06 DR 10 25
7/11/2017 7/11/2017 19:21 CR 15 40
7/15/2017 7/15/2017 14:17 DR 20 20
7/17/2017 7/17/2017 17:12 CR 100 120
7/18/2017 7/18/2017 16:52 CR 120 160
Enter dates in column A. Then in column B enter:
=IFERROR(INDEX(Date,SMALL(IF(ROUNDDOWN(Date,0)=$A1,ROW(Date)-1),COUNTIFS(Date,">="&$A1,Date,"<"&$A1+1))),"")
closing out of the cell with CTRL-SHIFT-ENTER so that the formula in the formula bar looks like
{=IFERROR(INDEX(Date,SMALL(IF(ROUNDDOWN(Date,0)=$A1,ROW(Date)-1),COUNTIFS(Date,">="&$A1,Date,"<"&$A1+1))),"")}
Note: it does not work to enter the curly braces yourself. ;-) You must close out of the cell with CTRL-SHIFT-ENTER!
The Date in the formula is a named range - I don't like typing $A$2:$A$10 all the time. If you don't want to do named ranges, replace Date with $A$2:$A$10 or your applicable range.
Column C:
=IFERROR(INDEX(CR_DR,SMALL(IF(ROUNDDOWN(Date,0)=$A1,ROW(Date)-1),COUNTIFS(Date,">="&$A1,Date,"<"&$A1+1))),"")
Same thing - close out of cell with CTRL-SHIFT-ENTER. Named range again for CR_DR, same rules as for Date above. Copy/paste the for the other columns, changing the range that INDEX is searching as appropriate for the column you want.
Explanation: ROUNDDOWN removes the time from the date in your source data so that it can match it to the date in column A. If the date matches, its row (-1 because the row number of A2 is 2, but it is the first item in $A$2:$a$10) is put into an array for the SMALL function. This chooses the nth smallest item from the array, defined by the COUNTIFS function, which counts how many dates fall between the date in column A and the day after the date in column A (thus actually giving you the largest item). INDEX then uses the range and looks up the row number that SMALL delivered to it. If it errors out, the cell is blank.
If you don't want to hand-enter specific dates, auto-fill for all dates and it will simply be blank on dates with nothing:
7/9/2017 7/9/2017 19:09 CR 10 10
7/10/2017 7/10/2017 21:06 DR 10 25
7/11/2017 7/11/2017 19:21 CR 15 40
7/12/2017
7/13/2017
7/14/2017
7/15/2017 7/15/2017 14:17 DR 20 20
7/16/2017
7/17/2017 7/17/2017 17:12 CR 100 120
7/18/2017 7/18/2017 16:52 CR 120 160

Sum all rows in excel with the same value in a certain column

So basically I will have a changing list of names entered like so
Deborah 9 30
Steven 4 22
Michelle 9 26
Michelle 8 30
Alice 10 28
John 3 21
David 7 23
David 9 26
David 7 24
Lucy 6 24
and my goal is to write a macros so that the names appear like this
Deborah 9 30
Steven 4 22
Michelle 17 56
Alice 10 28
John 3 21
David 23 73
Lucy 6 24
so all the rows with the same value for column 1 will be a sum of the values in the other column and consolidated to one row. The names are going to be changing, so I cant hardcode in IF something = "Michelle" it has to just be IF these rows = these other rows. I am trying to automate a tedious task at work, thanks for any suggestions!
If the duplicated names are in consecutive rows, then try this short macro:
Sub DeDup()
Dim N As Long, i As Long
N = Cells(Rows.Count, "A").End(xlUp).Row
For i = N To 2 Step -1
If Cells(i, 1) = Cells(i - 1, 1) Then
Cells(i - 1, 2) = Cells(i - 1, 2) + Cells(i, 2)
Cells(i - 1, 3) = Cells(i - 1, 3) + Cells(i, 3)
Range(Cells(i, 1), Cells(i, 3)).Delete Shift:=xlUp
End If
Next i
End Sub
You can create a distinct sorted list of names using an array formula with INDEX, MATCH, MAX and COUNTIF as described here:
http://www.get-digital-help.com/2009/04/14/create-a-unique-alphabetically-sorted-list-extracted-from-a-column/
Then you can just use a simple SUMIF function for each name in the result.
Just use a sumif formula. you can manipulate it to your needs. It will sum what you want in a given row. Or use an array if you would like.

Cannot make .Offset to work in excel vba macro

I am stuck, and would like a little hlep. I'm trying to get a qty on Column D12, d14, d16 .... to d42. Than multiply this qty by a value. the value sheet look like this.
Value Sheet
A B C
ItemName Quality Confort
1 Chair 2 1
2 Bed 0 3
3 Table 1 1
Quantity Sheet
A B C D
ItemName QTYColumn
12 .. Table 2
13
14 .. Chair 5
15
16 .. Bed 6
Total Sheet
A B
Quality 12 (2*1 + 5*2 + 6*0 )
Confort 25 (2*1 + 5*1 + 6*3 )
I'm pretty sur I have the hardest part done. I can check and grab the quantity from all the sheets I want. I also got a function done where you pass the name of the item, and the stats name, and it return me the results I want.
so, I got this part of the code atm which doesnt work, and its driving me nuts.
For Counter = 12 To 42 Step 2
For Each qColumn In QTYColumn
Set QTY = Range(qColumn & Counter)
Dim ItemName As Range
ItemName= QTY.Offset(-2, 0).Select
total = total + (QTY * GetValue(ItemName, "Confort"))
Next qColumn
Next Counter
My problem is with the ItemName variable. Its always empty and as soon as I get to it with the debugger, the function stops and it closes. Anyone have any idea as to why ? it's important for me to get it base on the offset -2 and not the column adress because it might be different depending of the sheet, and the only "sure" way to find it is the get the 2nd cell to the left of the quantity cell.
ItemName= QTY.Offset(-2, 0).Select does not mean anything !
Either you Select:
QTY.Offset(-2, 0).Select
or you get the value:
ItemName= QTY.Offset(-2, 0).Value '(value can be omitted here)
But then, Dim ItemName As Range does not make sense. It should be a String or a a number.
or you get the range:
Set ItemName= QTY.Offset(-2, 0) ' then you need Set

Resources