I have a refreshable table in excel and I want to filter the rows by a couple of date ranges. Each row has a date and other information.
I want to find the rows that are in the first date range (F1:F2) and are not in the second date range (H1:H2).
The table is refreshable, and can change size. It currently spans A3:X6146. The table is a query, so it will change sizes when a separate date range is used to find the table values.
I don't have much VBA experience, so this problem is tripping me up. Any ideas?
Thanks
EDIT:
I'll try to make the issue clearer.
I have a table that is created via a query that pulls in data that falls between the Starting Date and the Ending Date, 1/1/2016 and 12/31/2017 here. It lists each time an item was purchased, so each one can be listed multiple times.
I want to find which items were purchased (listed in the table) between the Active Date Range start and end dates (cells F1 and F2), and NOT purchased between the Inactive Date range (cells H1 and H2).
Starting Date: 1/1/2016 Active Date Range Start: 3/1/2016 Inactive Date Start: 3/2/2017
Ending Date: 12/31/2017 Active Date Range End: 3/1/2017 Inactive Date End: 9/22/2017
item date
1 9/21/2017
2 9/20/2017
3 9/20/2017
Yes, I can say to you what I would do.
Create one additional column to keep the result value, if is in or out of the date range. Then
dim t() as string, lin as long, linf as long
linf=Range("F65536").End(xlUp).Row 'or any other more precise way to get the final line
redim t(1 to linf-2,1 to 1)
'range dates - are they on the worksheet?
dim rg_dates as Range,r as range,b as boolean
set rg_dates=Sheets("xxxx").Range("B1:B4") ' just an example, the range would be B1:C4 but use only the first column - see below
For lin=3 to linf
b=False
For each r in rg_dates
If cells(lin,"F").value>= r.Cells(1,1) and cells(lin,"G").Value<=r.Cells(1,2).value then
b=true
Exit for
End If
Next r
If b then t(lin-2,1)="Y" else t(lin-2,1)="N"
Next l
Range("Z3:Z" & linf).Value = T
'Then just filter the table.
There would be then many things to do to keep it error free, and how to apply it at the concrete situation. Hopefully with what I wrote above you can get an idea about things you can do using VBA. If you are using code to filter the table you can do all this invisible to the user, creating an extra column for the filter criteria, filtering, and then deleting the whole column..
Related
I have a Table with a column that I added, that checks the date of that row against a formula.
The result of that formulae is TRUE or FALSE and a subsequent Pivot Table Sums a value in the TRUE rows. I Introduced it to get what is called a Rolling Total Income.
There are two formula and I want to swap from one to another using VBA.
The formula are:
=IF([#Date] = "", "", AND([#Date]>=EOMONTH(TODAY(),-13)+1,[#Date]<EOMONTH(TODAY(),-1)))
for the Rolling data.
=IF(AND([#Date] >=G1,[#Date] <=H1),"TRUE","FALSE")
for the Sum of Income between G1 and H1, the financial year start and end dates.
The VBA I have tried is as follows:
Set lo = Sheet2.ListObjects(1) 'Sheet2 is the Income sheet see Project list
lo.Parent.Activate 'Activate sheet that Table is on
Set lColName = lo.ListColumns(9)
lColName.DataBodyRange.Cells(1).Formula = [=IF(AND([#Date] >=G1,[#Date] <=H1),"TRUE","FALSE")]
Running the above errors and gives #VALUE in the first cell in that column, and doesn't ripple through the rest of the column.
What have I done wrong?
Try
lColName.DataBodyRange.Formula = "=IF(AND([#Date] >=$G$1,[#Date] <=$H$1),""TRUE"",""FALSE"")"
Thanks, those changes have sorted it.
One more refinement I am struggling with.
The IF test statement is testing a date against cells, $G1 and $H1 which I set up for ease of debugging. However I have another worksheet in the workbook where I store all the references/static data I use in the various Sheets and I have placed those dates there. In this Module, before the IF statement, I have set those dates against two variables.
startdate = Range("I2").Value
enddate = Range("J2").Value
I now want to use those in the IF statement but cannot get the correct syntax!
This just errors:
"=IF(AND([#Date] >= startdate,[#Date] <= enddate),""TRUE"",""FALSE"")"
How should I write it?
Thanks
I have a date like this (mm/yy) in row 1
A B C D E F
1/19 2/19 3/19 4/19 5/19 6/19 ...
I want the VBA to recognize today's date and match it to current column and return as integer.
Ignoring the days (only matching month and year).
For example, if today is 4/13/2019, it would be 4 (column D)
I would need this in VBA because I will be using it to define a range:
For today To x month
It appears OP was looking for a VBA solution, so here is an alternative.
I can think of a few completely different methods of accomplishing this within VBA. Your question isn't very clear of what you are wanting the end result to be, but it appears you are looking for a function that will return the column number - perhaps so you can use to pinpoint a range.
Function DateCol(ByVal InputDate As Date) As Long
Dim colDate As Date
colDate = InputDate - Day(InputDate) + 1
Dim srcRng As Range
Set srcRng = ThisWorkbook.Worksheets("Sheet1").Rows(1)
DateCol = srcRng.Find(What:=colDate, LookAt:=xlWhole).Column
End Function
You simply take an input date, subtract the days (and add 1 since the first day of the month isn't 0). Then you take this new date and use the .Find() method to locate the range that contains your date on the worksheet, and finally the .Column property to get the number you are looking for.
Here is a small sample usage:
Sub test()
' Example Usage
Cells(10, DateCol(#6/11/2019#)).Value = "Test"
End Sub
In the above test sub, the DateCol() function would have returned the value of 6 in your sample worksheet, making the result:
Cells(10, 6).Value = "Test"
Only issue is that this function doesn't contain any error handling. You will raise an error if the date is not found in .Find(), so ensure that you take this into consideration.
Also, don't forget to change this line to use the true Worksheet:
ThisWorkbook.Worksheets("Sheet1").Rows(1)
I had to redo my answer after messing with the data. this is what i ended up with.
On Row 1 I entered the dates as: 1/1/2019, 2/1/2019, 3/1/2019... and custom formatted the row to only show it as mm/yy.
With the formula below I grab the month and year from the given date and convert it into the first of the month. I am very positive there is a better way to make it but my brain is fried for the day.
=MATCH(NUMBERVALUE(TEXT(A3,"mm")&"/1/"&TEXT(A3,"yy")),$1:$1,0)
Edit: (Edit formula to make it permanent on Row 1 [$1:$1])
Assuming that the date 4/13/2019 is on Cell A3
I am trying to create a turnover report by graphing how many years someone stays in each position (Job Title). I have figured out how to remove exact duplicates and duplicate Start/End dates, however I'm stuck on the final cleanup step. Cleaning up date range for dates that overlap each other, and removing rows for the overlapping dates. This way I am not counting the same day multiple times.
Here is a simplified set of the data I am working with:
I need to define a range by matching names:
John K. = Rows 2-6
Then to only check dates with a matching Job Title:
Sales = Rows 2, 5, 6
Sr. Sales = Rows 3
Sales Mng. = Rows 4
Then for arrays with more than 1 row, check if Start Dates and End Dates fall within each other and ether: 1. Create new row with earliest start date that over laps, latest start date that over laps, and deletes original rows that overlap. 2. Use a loop with Yes/No questions to update an existing row with widest range of overlapping dates and delete rows that fall within that range.
For example, with John K. I would need it to remove rows 5 and 6 as they fall within the date range for row 2, but rows 3 and 4 do not need to be deleted as they are a different Job Title.
For Dom Q., There would be no changes needed as none of his dates fall within each other.
For Henry S., I would need to update D10 to be D11, then delete row 11.
The dataset I will be running this on is 200,000 rows so unfortunately it is too large to manually correct. I saw some good formulas for checking if date ranges fall within each other, however I am not sure how to make them dynamic enough to check only matching names and titles.
Thank you in advance for your thoughts on this and I am happy to provide more data/context if needed.
I found a work around that takes additional manual steps but is still faster than correcting the data line by line. It also requires me to separate the data before hand by Job Title and is entirely dependent on being sorted in a specific way to work correctly.
First make the following sorts:
-Sort Job End Date by A to Z
-Sort Job Start Date by A to Z
-Sort Provider by A to Z
Then I add 3 new columns at the end of my dataset:
New Column 1: End Date Check - To give a checkable end date to blank Job end Date cells
=IF(R2="",TODAY(),R2)
New Column 2: Q <= above AE - Must start in row 3. If Provider (Name) is the same in the row above, check if Job Start Date is less than or equal to the Job End Date in the row above.
=SUMPRODUCT((B3=OFFSET(B3,-1,0))*(Q3<=OFFSET(AE3,-1,0)))
New Column 3: IF AF = 1, AE >= above AE - Must start in row 3. If New Column 2 equals 1, check if End Date is greater than or equal to the end date above it.
=SUMPRODUCT((AF3=1)*(AE3>=OFFSET(AE3,-1,0)))
The end result with unnecessary columns hidden looks like this:
Excel Data Sample 2
After prepping the data I run the following macro. This will start at Cell AF3, check if the value of the cell is 1, if not, it will increase the value of the Current Row (C_Row) and the Previous Row (P_Row) by 1 and check again until it reaches a blank cell. If an AF cell is 1, it will check if the corresponding AG cell is 1 as well. If AG is 1, it will copy the value of the current rows Job End Date and paste it as value only into the previous row's Job End Date and delete the current row, thus creating the largest overlapping time period in a single row and removing the conflicting row. If AE does not equal 1, it will just delete the current row as the overlapping dates fall entirely within the row above it.
Sub Aging_Overlapping_Dates()
Dim C_Row As Long: C_Row = 3
Dim P_Row As Long: P_Row = 2
'Loops until AF = Blank
Do While Not Cells(C_Row, "AF") = ""
'Checks if AF is 1
If Cells(C_Row, "AF") = 1 Then
'If AF is 1, check if AG is 1
If Cells(C_Row, "AG") = 1 Then
'Moves Job End Date to the previous row and deletes current row
Cells(C_Row, "R").Copy
Cells(P_Row, "R").PasteSpecial xlPasteValues
Rows(C_Row).Select
End If
'Deletes Current Row if AF or AG is 1
Rows(C_Row).Select
Selection.EntireRow.Delete
Else
'Increase row count if row was not deleted
C_Row = C_Row + 1
P_Row = P_Row + 1
End If
Loop
End Sub
Is there any way to COUNTIF it's the current date?
For example I have a spreadsheet with work orders, once the employee starts the work order it captures a time stamp, after the work order is completed it is moved to an archive, well I wanted to create a summary sheet that tells me how many orders we have done for that date, the format of the time stamp is:
2/19/2014 17:10:20
So basically I need a COUNTIF to count the column for the current date.
Is this possible?
The new version of Google Sheets has COUNTIFS, which would allow =COUNTIFS(A:A,">="&TODAY(),A:A,"<"&TODAY()+1)
You need to opt in to the new version to make it work, though. ("Try the new Google Sheets")
You would need to apply a function first on the range, which then makes COUNTIF not an appropriate function to count those dates matching 'today'. You can use SUMPRODUCT instead:
=arrayformula(SUMPRODUCT(1*(INT(A1:A100)=TODAY())))
INT strips out the time from the datetime.
If you don't have COUNTIFS available, as per maybeWeCouldStealAVan's suggestion, then you can use two COUNTIF functions like this
=COUNTIF(A:A,">="&TODAY())-COUNTIF(A:A,">="&TODAY()+1)
by counting all entries greater than or equal to today then subtracting all those greater than or equal to tomorrow the result is a count of those on today's date only
That formula will work in Excel or google - another option, similar to Jerry's is to use this googledocs specific formula
=count(filter(A1:A100,int(A1:A100)=today()))
try this:
dim i as integer
dim objDate as date
dim objStartDate as Date
dim objEndDate as Date
dim countOrders as integer
countOrders = 1
objStartDate = 'the start date to check with ( could be the start of the day)
objEndDate = 'the end date to check with (could be the end of the day)
for i = 1 to 'number of rows
objDate = CDate(cells(i, 1))
if (objDate > objStartDate) and (objDate < objEndDate) then
countOrders = countOrder +1
end if
next i
Suppose I have below excel sheet,And I need to find the difference between them and result need to put back to another column:
ColA ColB ColC
9/3/2012 8:31:59 AM 09/17/2012 6:45:56 PM Result
9/4/2012 8:31:59 AM 10/17/2012 6:45:56 PM Result
I did it using Loop and Row-By-Row technique. Looking for a way if it can be done directly by column level subtraction. Say ColB-ColA - > ColC. The whole operation should be performed at a time.Result should come "hh:mm:ss".
CODE
IntRow4=2
Do While objSheet4.Cells(IntRow4,1).Value <> ""
If objSheet4.Cells(IntRow4,9).Value <> "Open" Then
Date1=objSheet4.Cells(IntRow4,7).Value
Date2=objSheet4.Cells(IntRow4,8).Value
objSheet4.Cells(IntRow4,11)=TimeSpan(Date1,Date2)
End If
IntRow4=IntRow4+1
Loop
Update
ColA1 ColB1 ColC1 ColA2 ColB2 ColC2 ..... ColAN ColBN ColCN TotaltimeDurtion
Date Date 11:25:20 Date Date 10:25:00 Date Date 11:25:20 ?
here i have shown only one row,But there can be multiple or N number of rows.What I need to do is,I want to add the time durations and put them to the last colum "TotaltimeDurtion".But the last column can not be fixed.And all the columns for each row shouldn't required values,but all never will be empty.Can we also do this also in column level.here the duration is hh:mm:ss format or as per your instruction [h]:mm:ss. TotaltimeDurtion <- ColC1 + ColC2 + ...+ ColCN.
using the range object, I can set the formula on all the cells within a range at once
range("C1:C10").Formula="=B1-A1"
It will also adjust the formula based on the normal copying riles for absolute addressing.
e.g. with the above example, C10 will be =B10-A10. If I had put the formula as "=B1-$A$1" then C10 would have been =B10-$A$1
You can subtract one date from the other, and then set the formatting of the cell:
'Within the Do..While loop
Dim cell
Set cell = objSheet4.Cells(intRow4,11)
cell.Value = Date2 - Date1
cell.NumberFormat = "hh:mm:ss"