Add a week to a range of dates in VBA - excel

In sheet INPUT, rows of data for week schedule gets inputted. Multiple rows per day is possible. Column A contains the dates of the original week of the schedule. When the complete planning is set in the INPUT sheet (lets say 15 rows by 10 columns of data) a macro can be run which copies the planning to the OUTPUT sheet and creates it for a full year. Therefore I'm coding VBA to copy the block of data and paste it beneath the previous week and update the dates by 7 days.
I'm having difficulties with DateAdd function.
Does anyone know a good solution?
Dim i As Integer
Dim rowCount As Long
Dim columnCount As Long
Sheets("OUTPUT").Select
Sheets("OUTPUT").Cells.Clear
Sheets("INPUT").Select
rowCount = Sheets("INPUT").Range("A6", Sheets("INPUT").Range("A6").End(xlDown)).Rows.Count - 1
columnCount = Sheets("INPUT").Range("A5", Sheets("INPUT").Range("A5").End(xlToRight)).Columns.Count - 1
Range("A5").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("OUTPUT").Select
Range("A1").Select
ActiveSheet.Paste
For i = 1 To 51
Range("A" & Rows.Count).End(xlUp).Select
Range(Selection, Selection.Offset(-rowCount, columnCount)).Copy
Range("A" & Rows.Count).End(xlUp).Select
ActiveCell.Offset(1, 0).PasteSpecial
Range("A" & Rows.Count).End(xlUp).Select
Range(Selection, Selection.Offset(-rowCount, 0)).Value = DateAdd("d", 7, Range(Selection, Selection.Offset(-rowCount, 0)).Value)
Next i

Variable= DateAdd("d", 7, Variable)

I'm not entirely sure what you do with columnCount so this may need to be modified, but I think something like this should get you started
Dim dateVals
Dim destRange as Range
Dim cl as Range
For i = 1 To 51
' initial data
' this gets a range from the last cell in column A, offset by the rowCount variable, and resized based on row/col counters
Set rng = Range("A" & Rows.Count).End(xlUp).Offset(-rowCount).Resize(rowCount,colu‌​mnCount)
' similar size range beginning in row after 'rng'
Set destRange = rng.Offset(rng.Rows.Count)
' Instead of copying the cells/paste special, just transfer the values directly
' Range(rng, rng.Offset(-rowCount, columnCount)).Copy
destRange.Value = rng.Value
' Add 7 days to each cell value
' I assume you only have date values in column 1
For Each cl in destRange.Columns(1).Cells
cl.Value = DateAdd("d", 7, CDate(cl.Value))
Next
Next i

Related

If cell A1 is greater than B1, cut and paste row to first empty row

If cell in column I1-I14 is greater than cell in column J1-J14, I want to cut the entire row and paste values to the first empty row. (From row 16 and down.)
If cell i is greater than cell j, cut row and paste values to first empty row (row 16 in this example)
This code just pastes in the first row:
Sub Knapp6_Klicka()
Dim i As Long
Dim j As Long
j = 1
For i = 3 To 500
If Cells(i, 9).Value > Cells(i, 10).Value Then
Cells(i, 12).EntireRow.Cut Sheets("Blad1").Range("A" & j)
j = j + 1
End If
Next i
End Sub
I tried to combine the paste with two different solutions.
One like this, where I recorded a macro and went to the last cell, then up to the first empty cell:
Range("A1048576").Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Range("A1").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
And one solution that I found on an Excel community:
Sub compareresult()
Dim row1 As Integer
Dim row2 As Integer
row2 = 1
For row1 = 8 To 500
If sheet1.Cells(row1, 11).value > sheet1.Cells(row1, 9).value Then
sheet1.Cells(row1, 1).EntireRow.Copy Sheets(11).Cells(row2, 1)
row2 = row2 + 1
End If
Next row1
End Sub
If cell in column I1-I14 is greater than cell in column J1-J14, i want to cut entire row and paste values to the first empty row. (From row 16 and down)
Here is a method which doesn't cut and paste in a loop. Since you are not deleting the row or "cutting and inserting" the row, here is a simple approach. The below code follows a basic logic
Logic
Loop and identify the range.
If found, then copy the range in 1 go.
Finally clear the range which was copied (if copied).
Code
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim rngToCopy As Range
Dim i As Long
'~~> Change this to relevant sheet
Set ws = Sheet1
With ws
'~~> Loop and identify the range
For i = 2 To 14
If .Range("I" & i).Value2 > .Range("J" & i).Value2 Then
If rngToCopy Is Nothing Then
Set rngToCopy = .Rows(i)
Else
Set rngToCopy = Union(rngToCopy, .Rows(i))
End If
End If
Next i
'~~> If found then copy and clear
If Not rngToCopy Is Nothing Then
rngToCopy.Copy .Rows(16)
rngToCopy.Clear
End If
End With
End Sub
EDIT:
To incorporate new edits
Works perfectly! Thanks! :) I failed to fully describe my problem.. What i also need is to paste it as special (only paste the value and not the formulas). Do you got any quick solution for that? – Johl 5 hours ago
Replace
rngToCopy.Copy .Rows(16)
to
rngToCopy.Copy
DoEvents
.Rows(16).PasteSpecial Paste:=xlPasteValues
Have a try with this.
It's based on the range you gave. Skipped over row 1 since you have headers in it.
Dim i As Long, lRow As Long, ws As Worksheet
Set ws = Sheets("Blad1") 'Your sheet name
lRow = ws.Range("I" & Rows.Count).End(xlUp).Row + 1 'Finding the last row
If lRow < 16 Then lRow = 16 'The starting row you want to cut to
For i = 2 To 14 'Your range of rows to check
If ws.Range("I" & i) > ws.Range("J" & i) Then
ws.Range("I" & i).EntireRow.Cut ws.Range("A" & lRow) 'Cutting the whole row so you use column A to cut to
lRow = lRow + 1 'Move down 1 row for where to cut to
End If
Next i
Edit:
Because you only want the values to copy accross we can't use Cut and PasteSpecial xlValues so instead we will duplicate the value of the entire row to the new location, then clear the row (filling in for the cutting part). If clear is too much we can just ClearContents to remove the values in the cells instead of the formatting if that happens. Make sure to always save before running VBA code for the first time.
Dim i As Long, lRow As Long, ws As Worksheet
Set ws = Sheets("Blad1") 'Your sheet name
lRow = ws.Range("I" & Rows.Count).End(xlUp).Row + 1 'Finding the last row
If lRow < 16 Then lRow = 16 'The starting row you want to cut to
For i = 2 To 14 'Your range of rows to check
If ws.Range("I" & i) > ws.Range("J" & i) Then
ws.Range("A" & lRow).EntireRow.Value = ws.Range("I" & i).EntireRow.Value 'Copying the values over
ws.Range("I" & i).EntireRow.Clear 'Clear the row
lRow = lRow + 1 'Move down 1 row for where to cut to
End If
Next i
Your code is doomed to failure because you do not take into consideration that you are cutting the found row. Think about what that means. Your row with the In,Out is row 15 and you wish to paste to row 16. If you cut row 5 (for example) then rows 15 and 16 will become rows 14 and 15. It also means that your next row (which you think will be row 6) will actually be what was row 7 before the cut.

VBA Finding Last Row

I'm trying to copy down a formula down to the last row. I've got code for doing so but it won't work.
My code to find the last row is:
lRow = ws.Range("G" & ws.Rows.Count).End(xlUp).Row
The rest of my code is as follows:
Sub Inventory()
Dim lRow As Integer
lRow = ws.Range("G" & ws.Rows.Count).End(xlUp).Row
'Inventory Macro
Range("G2").Select
' Selects cell G2
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=RC[-5]-RC[-2]"
' Calculates Inventory for the first month by subtracting Production Units from Demand
Range("G3").Select
' Selects cell G3
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = "=RC[-5]-RC[-2]+R[-1]C"
' Calculates Inventory for the rest of the months by subtracting Production Units from Demand plus the previous month's Inventory
Range("G3").Select
Selection.AutoFill Destination:=Range("G3:G" & lRow)
Range("G3:G" & lRow).Select
End Sub
Your problem probably stems from the column in which you determine the last row. Here is another version of your code that avoids selecting anything.
Sub Inventory2()
'Inventory Macro
' Calculates Inventory for the rest of the months by subtracting
' Production Units from Demand plus the previous month's Inventory
Dim Ws As Worksheet
Dim lRow As Long
Set Ws = ActiveSheet ' better: name the sheet: Worksheets("Sheet1")
With Ws
lRow = .Cells(.Rows.Count, "A").End(xlUp).Row ' this can't be column G
.Cells(2, "G").FormulaR1C1 = "=RC[-5]-RC[-2]"
.Range(.Cells(3, "G"), .Cells(lRow, "G")).FormulaR1C1 = "=RC[-5]-RC[-2]+R[-1]C"
End With
End Sub

Cut a table halfway in Excel

My sheet contains of cars that are placed at a certain location and need to be checked. This list is made twice a day and sometimes contains of 10 rows, sometimes 14, sometimes 12 etc. Now I would like to cut half of the rows and place it next to the other rows (in this case paste it in cell E). I would like to automate this process so in the VBA should be:
Count number of rows (X)
Cut the rows from X/2 to X
Paste the data in cell E1
I found this function which returns the middle cell. However, I would like to put this together in a sub.
Function Middle(r As Range) As Variant
Dim i As Long, j As Long
If r.Columns.Count > 1 Then
Middle = [#N/A]
Exit Function
End If
i = r.Row
j = r.Rows.Count
Middle = Cells(i + (j - 1) / 2, r.Column).Address
End Function
Sub cutting()
Range("Middle:C" & Range("A" & Rows.Count).End(xlUp).Row).Select
Selection.Cut
Range("E2").Select
ActiveSheet.Paste
Range("A1:C1").Select
Selection.Copy
Range("E1").Select
ActiveSheet.Paste
Cells.Select
Cells.EntireColumn.AutoFit
Range("E8").Select
End Sub
Before
After
You don't need to select the data to work with it.
Try:
Sub Test()
Dim lLastRow As Long
Dim lCutRow As Long
With ThisWorkbook.Worksheets("Sheet1") 'Change Sheet1 to the name of your sheet.
lLastRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'Find last row in column A.
If lLastRow > 1 Then
lCutRow = (lLastRow / 2) + 1
.Range(.Cells(lCutRow, 1), .Cells(lLastRow, 3)).Cut Destination:=.Cells(1, 5) 'Paste to row 1, column 5 (E1).
End If
End With
End Sub

Excel Macro to add COUNTA to new top row

I have an Excel 2013 worksheet where each column has a header row, and then the word "DIRECT" in some or all of the cells. No other data exists in the columns, just "DIRECT" or blanks. No columns are blank, they all have "DIRECT" at least once.
I'm looking for a macro that does the following:
Adds a new top row
Ignores the original header row, but gets a count of the cells with "DIRECT" in them
Puts that number in the corresponding new top cell for each column
Does the above actions for each column in the worksheet
Works regardless of the last column or row with data (I have to run this on several different-sized worksheets)
I recorded a macro that gets close, but it has two problems:
It adds the COUNTA data out to the last row of the workbook, which isn't needed (the populated columns will be a couple hundred, not thousands)
It references a specific cell range, so could cut off data for sheets with more rows
Sub AddColumnCountsRecorded()
'
' AddColumnCounts Macro
'
'
Rows("1:1").Select
Selection.Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Range("J1").Select
ActiveCell.FormulaR1C1 = "=COUNTA(R[2]C:R[15]C)"
Range("J1").Select
Selection.Copy
Range(Selection, Selection.End(xlToRight)).Select
ActiveSheet.Paste
End Sub
If it helps:
Column "A" can determine the last row where data could be (that's the "username" column", so no blanks there) - although this last row will also change from sheet to sheet.
Row 2 (the header row) can determine the last column where data could be - it has no blank columns; in each column, at least one cell will have the word "DIRECT".
Any advice on editing the existing macro or concocting a new one from scratch would be greatly appreciated!
Thanks!
UPDATE:
Much thanks to Scott, here's what I ended up with - this adds the non-blank cell count to the active worksheet and stops at the last row with data in it. I just call it directly, without the 2nd section of code proposed below:
Sub AddColumnCountsRecorded()
With ActiveSheet
.Rows("1:1").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Dim lRow As Long, lCol As Long
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
lCol = .Cells(2, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(1, 2), .Cells(1, lCol)).FormulaR1C1 = "=COUNTA(R[2]C:R[" & lRow & "]C)"
End With
End Sub
Give this a shot. I made a separate sub that you can pass the worksheet reference too.
Sub AddColumnCountsRecorded(ws As Worksheet)
With ws
.Rows("1:1").Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Dim lRow As Long, lCol As Long
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
lCol = .Cells(2, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(1, 2), .Cells(1, lCol)).FormulaR1C1 = "=COUNTA(R[2]C:R[" & lRow & "]C)"
End With
End Sub
Call it like this:
Sub ColumnCount()
AddColumnCountsRecorded Worksheets("Sheet1")
End Sub

VBA Macro to AutoFill Right until Last Column

I have a report that is automatically pulled that requires Sums to be added at the end of certain columns. The report remains static from Column A-R but the amount of columns as of S can be as few as 1 or go up until 52. The amount of rows are never static. I already know how to find the last row and my sums need to start at column J but when I try to autofill to the right to the last column that contains data (on the same row I have summed J), it spits back an error or doesn't work. Anyone know how to do this? This is what I have for code thus far.
Sub TV_Buysheet()
'
' Macro1 Macro
'
Range("J1").Select
FIRST_ROW = ActiveCell.Row
Selection.End(xlDown).Select
LAST_ROW = ActiveCell.Row
Selection.Offset(2, 0).Select
ActiveCell.FormulaR1C1 = "=SUM(R[" & FIRST_ROW - LAST_ROW - 2 & "]C:R[-2]C)"
Dim lastCol As Long
lastCol = Cells(2, Columns.Count).End(xlToLeft).Column
ActiveCell.AutoFill Destination:=Range(ActiveCell, lastCol), Type:=xlFillDefault
End Sub
Just missing the line of code that autofills to the last column...
To find the last column, the following should work
Dim lngLastColumn As Long
lngLastColumn = Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Range(Activecell, Cells(Activecell.Row, lngLastColumn)).FillRight

Resources