I have a list of names in Sheet1 which gets updated manually, and I'm trying to program a macro (I want to attach it to a button) that will count the rows with values - COUNTA() - and drop the value in a column (let's say A) with the date it was counted next to it (column B). Here are the problems I'm having:
1 - I can't use "Today()" because it changes every day. I could just type in the date, but it would be much easier if there was a way to do it automatically and have it lock at that date.
2 - I don't know how to tell the macro that every time it executes, it should put the info in the next row down, in order to create (and grow) a list.
Thanks!
To find the last row you can do this:
FinalRow = Cells(Rows.Count, 1).End(xlUp).Row
This will put the number of rows in column 1 (A) in the FinalRow variable.
To add the current date into a cell:
cells(1,1) = Date
You can use this e.g. to go through all lines:
For i=1 to FinalRow
cells(i,2) = Date
next i
Hope I could help.
Related
I would like to find the text "Currency" in columns A or B, store all the currencies listed under Currency. Same process for Amount (Can be in an column)
Store values in an array. Then paste in Output Sheet. The currencies will already be listed in Output sheet in 1st row of the sheet. However if it is a new currency then the code should find last used cell in row 1 and add it. The value of Amount should be added to Output sheet against the currency and ID number also copied from the Source sheet.
I have some code.
Public Sub loopRow()
Dim curArray As Variant
Dim listarray As Variant
Dim cnt As Long
'Find Currency
Dim rgFound As Range
Set rgFound = Range("A:B").Find("Currency")
'Find last used row
curArray = Cells(rgFound.Address).End(xlUp).Row
'Transpose list of currecny from the row down from the word Currency that it has found
listarray = Application.Transpose(Cells(Rows, curArray).End(xlUp)).Row
For cnt = LBound(curArray) To UBound(curArray)
curArray(cnt) = curArray(cnt)
Next cnt
For cnt = LBound(curArray) To UBound(curArray)
'Debug.Print curArray(cnt)
'Copy and paste into Sheet under the correct curreny, if new currency then add this in row A
Next cnt
End Sub
Whilst you need to understand your question is unanswerable as is, I'll do my best to help.
The problem we have is not seeing the source sheet the way you do, as we can't see it at all. You say you have the word Currency in columns A or B or both, and an ID column somewhere, and Amount values everywhere. That's tricky source data. If as is more likely, the ID is in a specific column and the amounts are in a set of columns, then we'd have a chance.
Your question outlines the basic steps you'd want to take pretty well, so you're off to a good start.
However you can do all of the work without VBA, certainly if I'm right about the Source data. Create yourself a working sheet, or multiple working sheets. Definitely one to sort out the full list of currencies. Grab a copy of columns A and B (by formulae) and then have the working sheet go through line by line and use logic to build the list. Spreadsheets are great at this.
Once you have the list, use it as row headers on your Output sheet and use sumifs to get the values. I am not sure how the IDs would fit in, but if they were to be your row headings, then do the same as the above to get the list of unique ids and link them into your Output page in column A. Your sumifs can handle that.
That will hardly tell you all you need to know, but if you work it out you'll have learned a lot about Excel and when you need to go into VBA.
If you'd rather do it with VBA, break down each step until it works, and then go onto the next one.
And if you want more help, paste your data in here. Anonymise it first if you need to.
I have a big excel document with many rows.
The document is arranged by 2 main columns: ID and Year.
Each ID (Column A) has 5 Years associated to it in chronological order.
I need to filter different years by their key. For example I want to filter the year '1998' by the ID '311511'.
The Problem:
The ID column only appears on the first row of every 5 years series (as you can see in the picture attached). In other words, the ID only appears in rows with the year 2001 but is missing from the rest of the rows that contain the years 1997 to 2000.
As I mentioned earlier, it is a very big documents and to fix this manually (copy-paste, etc) is very prone to errors, not to mention the hard work.
Therefore, do you know of any way I could automatically copy the first row to the next 4 rows in the entire document? Some-kind of script or a function that automatically take the value of the first row - like 311511 - and copy it the next 4 empty rows, and after that continues to do the same for the next series - 311512 - and copy it to the next 4 empty rows.
Any help or suggestion will be greatly appreciated!
Presuming your IDs start in cell A1 and there's nothing under the table.
Private Sub fill_with_id()
Dim id As String
For i = 1 To Cells(Rows.Count, 1).End(xlUp).Row + 4
If IsEmpty(Cells(i, 1)) Then
Cells(i, 1) = id
Else
id = Cells(i, 1)
End If
Next i
End Sub
Will fill the table with IDs. Afterwards you can create a pivot-table to create a data-summary of the table and the individual IDs.
Note: I'd recommend saving a copy of the document, as vba-changed document can't be reverted
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
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..
Hello I'm trying to figure out the time difference between data in Column K and J. I need to know how long it took for data to be updated by the amount of days it took, hours, or minutes and am using those columns. I also want to get the average amount of time only if the names in Column A match and enter that information in Column N. This is what I have so far for the first part.
ActiveSheet.Name = "Raw Data"
Range("M2:M").Value = ("K2:K-J2:J" > 1) + ("d:hh:mm")
Thanks for the help.
This should get the results you want. The With ... End With block is used to save having to write Worksheets("Raw Data") all the time. Anything within the block which starts with a . refers to Worksheets("Raw Data")
The formula was adapted from this answer but modified to allow for more than 31 days. We then use the FillDown method to copy the formula in cell M2 down to the same row as the last used cell in column K. The references in the formula adjust automatically to point to the correct row
edit: updated to calculate average elapsed time for each name listed in column A. This is more complicated because we can't directly average the values we put in column M because we have converted them into a text format. I've chosen to use column Z to hold the numeric time values which we need. You could choose any other unused column and you could hide the column so it doesn't display.
The last used row is stored in a variable because we need to use it in a couple of different places. The numeric difference between columns K and J is stored in column Z. The text value in column M is then calculated from the value in column Z.
Finally, the average in column N is calculated using the AVERAGEIF function. This looks through all the used rows in column A, finds those with the same name as the current row and then averages all the values from column Z for any matching rows.
One important point to note: all of the formulas in column N will need to be rewritten if any rows are added or deleted. This is because the last row value stored in those formulas will become incorrect if rows are added or deleted
With Worksheets("Raw Data")
Dim lngLastUsedRow As Long
lngLastUsedRow = .Cells(.Rows.Count, "K").End(xlUp).Row
.Range("Z2").Formula = "=K2-J2"
.Range("Z2:Z" & lngLastUsedRow).FillDown
.Range("M2").Formula = "=FLOOR(Z2,1)&"":""&TEXT(Z2,""hh:mm"")"
.Range("M2:M" & lngLastUsedRow).FillDown
.Range("N2").Formula = "=AVERAGEIF(A$2:A$" & lngLastUsedRow & ",A2,Z$2:Z$" & lngLastUsedRow &")"
.Range("N2:N" & lngLastUsedRow).FillDown
End With