So I'm having two issues that I cannot seem to get unkinked. I run reports from a master sheet based off of a template and each finished sheet will have varying numbers of rows. What each finished sheet has in common are two columns(one for a begin date [Column F] and on for an expiration date[Column H]). For each row with a date in Column F I need to add 60 days to the date and put that date in Column H. I have tried working with variations of:
Dim cell As Range
For Each cell In Selection
cell.Value = cell.Value + 60
Next cell
I have tried this also with combinations of different while statements that I use for other things where I am putting values in one column based off of another, but I can't get them to work either.
Some of the problems I am having are: first, when I do manage to get it to enter a date in Column H it always enters 2/29/1900. It doesn't matter if there's a date in Column F or not, or what that date is. Second, when I try to set a range for the selection (this is when I try to combine with "While" statements) it pastes a date number in the entire range instead of only the cells with a date in Column F.
How can I get the macro to only add a date in Column H if there is a date in Column F, and how can I get the darn thing to add 60 days correctly?
Sub Tester()
Dim c As Range, val
For Each c In ActiveSheet.Range("E2:E100")
val = c.Value
If Len(val) > 0 And IsDate(val) Then
c.Offset(0, 2).Value = val + 60
End If
Next c
End Sub
Related
At the end of every month, we copy/paste forecast sales (where the formulas are) as a hardcode into other columns for reference and reconciliation purposes.
For example, copy Column D (January) through Column F (march) into column Q (Jan hardcoded) through S (March hardcoded)
I'm trying to modify my code so the user can select from two data validation dropdowns which month range (e.g. Jan - Mar) on each of the forecast tabs to copy/paste as values.
For example, below is something I've added to copy/paste based on the # rows for a formula.
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Range("T1") = "PPU"
Range("T2") = "=S2/R2"
Range("T2").Copy
Range("T2:T" & LastRow).Select `dynamic row
Selection.PasteSpecial xlFormulas
Range("T:T").Copy
Range("T:T").PasteSpecial xlPasteValues
With my code above, is it possible to alter this so, instead of " & Lastrow", I keep the rows static but make the columns to copy variable, so for lack of a better term firstMonth & secondMonth.
The columns to select would be based off two named ranges where the user chooses from two data validation lists (firstMonth & secondMonth) with each column being assigned a column "letter" (e.g. Jan is column D, Feb Column E, etc.)
Without being dynamic, it would be something like:
Range("D12:F19").Copy
Range("Q12").PasteSpecial xlValues
But I'd like to have the user select with months, via a data validation list, to have hardcoded by choosing a beginning month (firstMonth) and ending month (secondMonth)
Something along the lines of:
Range(firstMonth &"12": secondMonth & "19").Copy `firstMonth in theory is the column letter so, "D12" and secondMonth is the second column letter (F12)
Range("pasteFirstMonth &"12").PasteSpecial xlValues `the firstMonth will be paired with the column letter, say "Q" where it will paste those values. A second column range isn't needed here since only the copied range will paste, not overlapping anything else. This is the "hardcoded" area.
Update: Slightly reconfigured Tim's answer below.
Sub copyColumns()
Dim months, m1, m2, sht
months = Split("Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", ",")
Set sht = ActiveSheet
m1 = Application.Match(sht.Range("Month1").Value, months, 0)
m2 = Application.Match(sht.Range("Month2").Value, months, 0)
sht.Range(sht.Cells(8, 3 + m1), sht.Cells(16, 3 + m2)).Copy
sht.Range(sht.Cells(8, 16 + m1), sht.Cells(16, 16 + m2)).PasteSpecial xlValues
End Sub
Something like this should work:
Sub DoCopy()
Dim months, m1, m2, sht
months = Split("Jan,Feb,Mar,Apr,May,June,July,Aug,Sept,Oct,Nov,Dec", ",")
Set sht = ActiveSheet
m1 = Application.Match(sht.Range("Month1").Value, months, 0)
m2 = Application.Match(sht.Range("Month2").Value, months, 0)
If Not IsError(m1) And Not IsError(m2) Then
'copy range - use offset (3 here) depending on where months begin
sht.Range(sht.Cells(12, 3 + m1), sht.Cells(19, 3 + m2)).Copy
'etc
End If
End Sub
You can prompt the user for selecting the desired months and you can use the Selection object, like
Set rng=Selection
Cells(rng.row, rng.column) gives you the top left cell of the selection,
rng.Columns.Count gives you the number of columns, etc.
From a users perpective it is much easier to select an area on the screen and press a button than entering values or selecting them from list.
I have a spreadsheet that has numbers for a particular year and then subtotals for that year.
The number of instances in a year can vary and there may be a year that doesn't exist i.e., 2018 might be skipped. The title of the totals row is always "FYXX Totals." I have a for loop that goes through the entire column and looks for "FY" Then if it falls within one of three categories (FY1-FY2, FY3-FY7, FY3-FY9; these being variables that represent a year). What I need is for the loop to sum the number in column D, E, F...when "FY" is found. I think using CONCATENATE might be the way to go but I am not sure a) exactly how to do that or b) if that is even the best way to go about it.
Dim rng As Range
Dim SumRow As Integer
Set rng = Range("C4:C" & NextRow)
For Each cell In rng
If Left(cell.Value, 2) = "FY" Then
If 2000 + Int(Mid(cell.Value, 3, 2)) <= FY2 Then 'This is the if statement for the fisrt category
'Here would be the sum function when the if statement is triggered
End If
End If
Next cell
Thanks so much for the help.
SpreadSheet_Picture
The second if loop (right now written for the first category) would need to sum the just the zero that is in column D next to FY17 Total. Keep in mind that sometimes row for FY18 may exist so this macro would have to be able to grab that as well should it exist. But in this case what would have to go into cell "D" & NextRow would be =SUM(D5).
My best attempt at understanding what you're after is that you want to place a formula in each cell of column D where the cell in column C contains FYxx Total, where xx meets certain other criteria. That formula should contain the sum of all the cells in column D for which the cell in the corresponding row of column C contains the same value of FYxx.
The easiest way I can think of to achieve this is to use the SUMIF function:
The formula =SUMIF(B$2:B$999,LEFT(C3,4),D$2:D$999) in cell D3 calculates the sum of all cells in column D where the cell in the corresponding row of column B matches the criterion, i.e. is equal to the first four characters of cell C3.
Unless there are further instances of the same FYxx value elsewhere in column B, the ranges in the first and third arguments of the SUMIF can cover the whole table, which I've assumed here extends to row 999, so you can keep those the same for each cell you place this formula in. You only need to change the row for the cell in column C in the second argument.
In fact if you really want, you can place exactly the same formula in each Total cell in column D:
=SUMIF(B$2:B$999,LEFT(INDEX(C$2:C$999,ROW()-1),4),D$2:D$999)
Here the INDEX function looks up the appropriate cell in column C based on the row of the cell that the function is placed in.
I have two columns with random times and the times come from two different sources so the columns do not have the same amount of data points. I want to start with the first time in the first column and compare it to each time in the second column. If there is a match in times, I would like to pull relevant data. After a match is found (if there is one) I would like for the code to go to the second cell in the first column and compare it to every value in the second column and so on.
Here is the code I have so far:
Sub TransferInfo()
'Activate the Sub to Convert and Format Dates
Call ConvertDates
'Define Variables
Dim st As Worksheet
Dim ts As Worksheet
Dim lastrow As Long
Dim i As Integer
j = 2
'Find and set the last used row
Set st = ThisWorkbook.Worksheets("Data Table")
lastrow = st.Cells(st.Rows.Count, "B").End(xlUp).Row
Set ts = ThisWorkbook.Worksheets("ShopFloor")
'Cycle through/compare Row J, Column 18 based on each cell in Row I, Column 14
For i = 2 To lastrow
Do Until IsEmpty(ts.Cells(j, 8)) Or IsEmpty(st.Cells(j, 2))
If st.Cells(i, 14).Value = ts.Cells(j, 18).Value Then
st.Cells(i, 15).Value = ts.Cells(j, 2).Value
Exit Do
Else
st.Cells(i, 15).Value = ""
End If
j = j + 1
Loop
j = 2
Next i
End Sub
The other sub that I call at the beginning of this sub simply rounds the times in each column to the nearest 15 minute interval to increase the likelihood of matches between the columns.
My question is: The code does not copy and paste any more information although there are times that match between the two columns. Why would the code that I have not work? Also, with larger data sets I am afraid that this the code may crash Excel and because I have a loop within a loop trying to process a lot of data a lot of times, but I don't know of a more efficient way to accomplish what I am trying to without this code.
If anyone has any insights as to why this code doesn't work I would greatly appreciate any help.
Thanks!
Based on your code, it looks like you just need an INDEX/MATCH formula. Use this in O2 and copy down:
=IFERROR(INDEX(B:B,MATCH(N2,R:R,0)),"")
No need for VBA
In my excel sheet I have an varying number of dates in column A with associated totals for each date in column B. The dates are somewhat random but I want to find the sum of the associated totals per week. I'm new to vba and I'm having a bit of trouble figuring out how to calculate the totals per week.
The psudo code for what I'm thinking is:
buttonClicked()
Dim sum As Integer, tempDate As Date, current As Date, i As Integer, j As Integer, match As Boolean
sum = 0
tempDate = Range("A1").Value
current = tempDate
For i = 1 To Rows.Count
for j = 0 to 7
tempDate = addDate(d, i, tempDate)
If cell(i,1).Value = tempDate Then sum = sum + cell(i, 2).Value
match = true
Break
End If
Next j
If match = true Then tempDate = current
Else
`next open space in column D is current
current = tempDate
`next open space in column E is sum
sum = 0
Next i
end
Please let me know if there's any better way to solve this problem other than iterating through the entire list and counting 7 days ahead. I should note that A1 is already assumed to be a sunday and I'm not sure how the commented out lines should be implemented. I would be very grateful for any advice at all.
In other column assign the corresponding Year.WeekNumber to each row using the following formula:
=CONCATENATE(YEAR(A1),".",TEXT(WEEKNUM(A1),"00"))
The totals per Year.Week can be obtained using a SUMIF formula or via a PivotTable. The PivotTable can be auto resize if you use a Dynamic Range as DataSource
If you are looking for a series of 7 row sums from column B, then this formula using native worksheet functions should do.
=SUM(INDEX(B:B, (ROW(1:1)-1)*7+1):INDEX(B:B, (ROW(1:1)-1)*7+7))
Fill down to catch successive week periods.
If you can supply a starting date (e.g. =MIN(A:A)) and add 7 to it in successive rows, then the weekly starting date could be a reference point for a SUMIFS function. In E9 as,
=SUMIFS(B:B,A:A, ">="&D9,A:A, "<"&D9+7)
Fill down as necessary.
If a VBA solution is necessary, that logic can be brought into a VBA sub or function.
I have an excel sheet with lots of data. As you may know, this comes with lots of problems. One major one is having too much data. I am not familiar with vba, but I wanted to know how to clean data.
I have a sheet with 3 fields: date, time, and temp. The temperature is recorded on a minute by minute basis. The temperature is only recorded from 7 am to 10 pm, but the sheet is on a 24 hour basis. So my sheet has a lot of blank cells. So, I want to write a code that states:
if ((time < 7am) or (time > 10pm)):
delete row
Can I do this?
Also, another problem is that the data is not collected on weekends. I am not given a day field, only a date field in this format: 20130102 which is January 02 2013. I want to:
if ((date = saturday) or (date = sunday)):
delete row
Are either of these doable?
My sheets looks like the following:
A .............. B ......... .... C
date........ time ......... temp
Since both your dates and times are formatted differently than normal, we need to manipulate the values to get something to test against. Consider the following example (I've commented each line to help you follow along):
Sub DeleteRows()
Dim lastRow As Long
Dim Cell As Long
Dim dt As Date
'Work with the active sheet.
With ActiveSheet
'Find the last row of your dataset.
lastRow = .Range("A:A").Find("*", searchdirection:=xlPrevious).Row
'Format your time column to a readable time.
.Columns("B").NumberFormat = "[$-F400]h:mm:ss AM/PM"
'Loop through the rows, beginning at the bottom.
For Cell = lastRow To 2 Step -1
'Piece together the date.
dt = Mid(.Cells(Cell, 1), 7, 2) & "/" & _
Mid(.Cells(Cell, 1), 5, 2) & "/" & Left(.Cells(Cell, 1), 4)
'If the date is a Sat or Sun, delete the row.
If Weekday(dt) = 1 Or Weekday(dt) = 7 Then
.Rows(Cell).EntireRow.Delete
'If the time is before 7am or after 10pm, delete the row.
ElseIf Hour(.Cells(Cell, 1)) < 7 Or Hour(.Cells(Cell, 1)) > 22 Then
.Rows(Cell).EntireRow.Delete
End If
Next Cell
End With
MsgBox "Done!"
End Sub
A few things to note about the code. First, we must start at the bottom of the list because as we delete rows, the remaining rows shift upwards. If we were to go from top to bottom (e.g. A1 to A10), if we deleted row 5, row 6 would slide into its place, and the loop would skip row 5 (previously row 6) and go on to row 6. In other words, looping from top to bottom when deleting rows will ultimately skip rows unintentionally.
Second, I had to guess on your time format. While I believe I guessed correctly, I may not have. If I was wrong and my code doesn't change the time column into a readable time, record a macro while changing the format of that column and substitute the new format with mine ("[$-F400]h:mm:ss AM/PM"
).
And lastly, since your date column is an abnormal format (for Excel), we need to reorder the date so that Excel can read it. Once we've done that, we can use the resulting date to see if the date was a Sat. or Sun.
You can do it this way, assuming the column that contains your date is the 2nd (B) :
Dim i As Integer
for i = 1 to cellsCount
If Hour(Cells(i, 2)) < 7 Or Hour(Cells(i, 2) > 22 Then
Rows(i).Delete
Else If WeekDay(Cells(i, 2)) = 7 Or WeekDay(Cells(i, 2)) = 1 Then
Rows(i).Delete
End If
next
You can have more information about the WeekDay function here :
http://msdn.microsoft.com/en-us/library/82yfs2zh%28v=vs.90%29.aspx