VBA copy & paste with dynamic range - vba

I'm new with VBA and I'm stuck somewhere. I have to copy last row of column A till column H and paste it untill the last row of column I. Last rows of columnns will be always change.
e.g; my data is in A2:H2 and I5 is the last cell with data.
My code should be copy A2:H2 and paste it A3:H5. And second time I run the macro (after I add new data to respective columns) it should be copy A6:H6 and paste it untill the last row of column I.
I wrote two codes which were not fulfill my needs.
first code is;
Sub OrderList1()
Range("a65536").End(xlUp).Resize(1, 8).Copy _
(Cells(Cells(Rows.Count, 9).End(xlUp).Row, 1))
End Sub
this code skips A3:H4 and only pastes to A5:H5
second code is;
Sub OrderList2()
Range("A2:H2").Copy Range(Cells(2, 8), _
Cells(Cells(Rows.Count, 9).End(xlUp).Row, 1))
End Sub
it copies A2:H3 and paste it A5:H5 but when I add new data it doesn't start to paste from A5:H5. It start from A2:H2 and overwrite to old data.
I can see what I have to change,range should be dynamic range like in the first code,but I can't manage to write the code.
I'll really appreciate little help.

You might want to use this as a starting point:
Dim columnI As Range
Set columnI = Range("I:I")
Dim columnA As Range
Set columnA = Range("A:A")
' find first row for which cell in column A is empty
Dim c As Range
Dim i As Long
i = 1
For Each c In columnA.Cells
If c.Value2 = "" Then Exit For
i = i + 1
Next c
' ok, we've found it, now we can refer to range from columns A to H of the previous row
' to a variable (in the previous row, column A has not been empty, so it's the row we want
' to copy)
Dim lastNonEmptyRow As Range
Set lastNonEmptyRow = Range(Cells(i - 1, 1), Cells(i - 1, 8))
' and now copy this range to all further lines, as long as columnI is not empty
Do While columnI(i) <> ""
lastNonEmptyRow.Copy Range(Cells(i, 1), Cells(i, 8))
i = i + 1
Loop

Try this one for something that allows future functionality, or at least it did for me...Ask if you need help understanding it :)
Option Explicit
Sub lastrow()
Dim wsS1 As Worksheet 'Sheet1
Dim lastrow As Long
Dim lastrow2 As Long
Set wsS1 = Sheets("Sheet1")
With wsS1
'Last row in A
lastrow = Range("A" & Rows.Count).End(xlUp).Row
'Last Row in I
lastrow2 = Range("I" & Rows.Count).End(xlUp).Row
'Cut in A:H and paste into last row on I
wsS1.Range("A2:H" & lastrow).Cut wsS1.Range("I" & lastrow2)
End With
End Sub

Related

Get Column with formula's and get values only to new column

My desired result is to have a separate column at column C, that has values only.
In Column "I" I have a range of data that is in in formulas. I can copy and paste special to a new column to C and that gives me the values only.
But is there a better way to do this? When I read data in New Column C, this gives the range of the pasted data which is messy meaning lots of white spaces.
Thanks :)
Sub Macro2()
'
' Macro2 Macro
'
Sheets("Sheet1").Columns(9).Copy
Sheets("Sheet1").Columns(3).PasteSpecial xlPasteValues
End Sub
Please test.
S1: Select sheet contain data you want to copy
S2: run macro
Sub macro1()
Dim data As Variant
data = ActiveSheet.Columns(9)
ActiveSheet.Columns(3) = data
End Sub
if all of your data is number then just force is to convert to number
Sub macro1()
Dim data As Variant
data = ActiveSheet.Columns(9)
Dim i As Long
For i = LBound(data) To UBound(data)
If Len(data(i, 1)) > 0 Then
data(i, 1) = CLng(data(i, 1))
End If
Next i
ActiveSheet.Columns(3) = data
End Sub
edited as you want to copy the whole column
p/s: this is not an optimize solutio as it read the whole column (1048576 rows)
If you are interested in copying only values, you can do it like this:
Step 1: determine last row in column I: lastRow = Cells(1, 9).End(xlDown).Row.
Step 2: copy all values to column C:
For i = 1 To lastRow
Cells(i, 3).Value = Cells(i, 9).Value
Next i
Putting it all together, the macro is:
Sub CopyPaste()
Dim lastRow, i As Long
lastRow = Cells(1, 9).End(xlDown).Row
'alternatively specify explicitly amount of rows you want to copy, i.e.:
'lastRow = 25
For i = 1 To lastRow
Cells(i, 3).Value = Cells(i, 9).Value
Next i
End Sub

creating a form in excel using VBA

I am trying to creat a form in excel using VBA, but I am stuck at the Code. I need to find out the code to enter a data to my worksheet using VBA form . here is the code I am using, but doesn't work..
Private Sub cmdAdd_Click()
Dim LastRow As Range
Dim DPDIAdhocRequestTable As ListObject
With LastRow
Cells(1, 2) = RequesterName.Value
Cells(1, 3) = RequesterPhoneNumber.Value
Cells(1, 4) = RequesterBureau.Value
Cells(1, 5) = DateRequestMade.Value
Cells(1, 6) = DateRequestDue.Value
Cells(1, 7) = PurposeofRequest.Value
Cells(1, 8) = ExpectedDataSaurce.Value
Cells(1, 9) = Timeperiodofdatarequested.Value
Cells(1, 10) = ReoccuringRequest.Value
Cells(1, 11) = RequestNumber.Value
Cells(1, 12) = AnalystAssigned.Value
Cells(1, 13) = AnalystEstimatedDueDate.Value
Cells(1, 14) = AnalystCompletedDate.Value
Cells(1, 15) = SupervisiorName.Value
End With
End Sub
can you help me to figure out the correct code for enter command?
thank you so much for your help.
As #Adam said - you've created LastRow and not assigned it to anything.
I'm guessing it's the next row you want to paste your data into, so it should be a Long holding the row number rather than an actual reference to the cell.
In the code below you could qualify the form controls by adding Me., for example Me.RequesterName.Value
https://msdn.microsoft.com/en-us/library/office/gg251792.aspx
Private Sub cmdAdd_Click()
Dim wrkSht As Worksheet
Dim LastRow As Long
'The sheet you want the data to go into.
Set wrkSht = ThisWorkbook.Worksheets("Sheet1")
'You're after the last row number, rather than referencing the range so LastRow is a Long.
'This looks for the last cell containing data in column A (the 1 in 'Cells(...)').
LastRow = wrkSht.Cells(Rows.Count, 1).End(xlUp).Row + 1
'With... End With block. Cells is preceded by a '.' notation - indicating it's referencing the 'With wkrSht'#
'https://msdn.microsoft.com/en-us/library/wc500chb.aspx
With wrkSht
'Using LastRow as row number in cell reference.
.Cells(LastRow, 2) = RequesterName.Value
'Before adding dates to the sheet you might want to check that the
'user entered a date and not rubbish.
.Cells(LastRow, 5) = DateRequestMade.Value
'You could use CDATE to force it to a date - will try and coerce the entered text into a date.
'Note - 1 will be changed to 01/01/1900 (so will need to add extra code to check it really is a date).
.Cells(LastRow, 5) = CDate(DateRequestMade.Value)
End With
End Sub
The first problem is that you've created a Range named LastRow but haven't assigned anything to it.
'Declaration
Dim LastRow As Range
'Assigns the last row based on the last item in Column A
Set LastRow = Range("A" & Rows.Count).End(xlUp).Row
With LastRow
...
End With
The second issue is a minor syntax error in your With LastRow block.
With LastRow
Cells(x,y).Value = "Foo"
End With
Should be
With LastRow
.Cells(x,y).Value = "Foo"
End With
Which is essentially the same as saying LastRow.Cells(x,y).Value = "Foo". Without the "." in front of Cells() VBA will not apply the With to that object, and assume you meant ActiveSheet.Cells()

copy and paste entire row from one to another sheet issue

I would like to copy entire row from today Sheet to last available row of main Sheet if today Sheet B2:B cell value = "Update". However, I come up with copy area and paste area are not the same size issue. I've tried many ways but cannot get it solved. Can anyone help? Thanks in advanced.
Sub getnew()
Dim Sheet1 As Worksheet
Dim Sheet3 As Worksheet
Dim lastrow As Integer
Dim i As Integer
Set Sheet1 = ThisWorkbook.Sheets("main")
Set Sheet3 = ThisWorkbook.Sheets("today")
lastrow = Sheet3.Range("C" & Rows.Count).End(xlUp).Row
Dim erow As Long
For i = 2 To lastrow
erow = Sheet1.Range("C" & Rows.Count).End(xlUp).Row + 1
If Sheet3.Cells(i, 2).Value = "Update" Then
Sheet3.Cells(i, 2).EntireRow.Copy Destination:=Sheet1.Range("B" & erow)
End If
Next i
End Sub
You are trying to copy the entire row of a worksheet, but you are pasting that row in another sheet, starting at column B. They aren't the same size, because an entire row contains 16,384 columns, but a row starting at column B only has 16,383 columns.
You have a few options to resolve this:
You could paste the entire row onto the other sheet at column A, like so:
Sheet3.Cells(i, 2).EntireRow.Copy Destination:=Sheet1.Range("A" & erow)
Or you could copy only the number of columns which you care about, instead of trying to copy the entire row, like so [I don't know what it is you're trying to copy, so you will need to figure out how exactly you want to size it. I have assumed that 10 columns is sufficient]:
Sheet3.Range(Cells(i, 2), Cells(i,11)).Copy Destination:=Sheet1.Range("B" & erow)

Change formula references during copy

I have a worksheet containing 35 columns of formulas which looks up data from another worksheet. Every time data is entered into the lookup worksheet ("Data") I want to add another set of formulas to the bottom of the row. I've managed to get the code to copy the correct formulas over these 35 columns, to the correct location at the bottom. But when they paste, the exact text of the formulas is copied, rather than changing the cells referenced.
e.g. formula "=OFFSET(Data!$B$1,(A7736-1)*34,0)" copied from row 7736 into row 8300 should become =OFFSET(Data!$B$1,(A8300-1)*34,0) but stays as "=OFFSET(Data!$B$1,(A7736-1)*34,0)"
This is my code
Dim workbk As Workbook
Dim databk As Workbook
Dim MRD As Worksheet
Dim formularrange As Range
Dim lasttrayname As String
Dim datarow As Long
Dim nrow As Long
Dim loopcount As Long
Dim urow As Long
Set workbk = ActiveWorkbook
'set Macro recording information sheet
Set MRD = Worksheets("Macro RunDate")
'find last date updated
urow = Worksheets("Macro RunDate").Range("A" & Rows.Count).End(xlUp).Row
'find last tray used
lasttray = MRD.Range("B" & urow).Value
'find row to paste raw tray data
datarow = Worksheets("Data").Range("A" & Rows.Count).End(xlUp).Row
Do while *condition*
'...More code here....
Loopcount = 0
Loopcount = loopcount + 34
Loop
Go to Tidy:
Tidy:
If loopcount > 0 Then
'convert to correct number of rows to copy
loopcount = (loopcount)/34*8
'copy formulas in Sheet2 for correct number of trays
'determine end row by finding "lasttray"
nrow = Worksheets("Sheet2").Range("A:A").Find(What:=lasttray, _
SearchOrder:=xlByRows, LookIn:=xlValues, SearchDirection:=xlNext).Row + 8
'repeat formulas
Worksheets("Sheet2").Range(Cells(nrow + 1, "A"), Cells(nrow + loopcount + 1, _
"S")).Formula = Worksheets("Sheet2").Range("A3975:s" & 3975 + loopcount).Formula
'calculate formula values
Worksheets("Sheet2").Range("A:E").Calculate
End If
So my question is, how do I copy these formulas and get the references to change?
Thanks in advance
Instead of setting the Formula property, you could use Copy:
Dim Source As Range
Dim Dest As Range
Set Source = Worksheets("Sheet2").Range("A3975:s" & 3975 + loopcount)
Set Dest = Worksheets("Sheet2").Range(Cells(nrow + 1, "A"), Cells(nrow + loopcount + 1, _
"S"))
Source.Copy Dest
Excel will then increment the row numbers just as it would when copying manually.
Use .FormulaR1C1 rather than .Formula.
– From the comment by #Rory Jun 4 '14 at 13:16
Instead of using cell1 = cell2, do the following:
Range(cell1).Select
Application.CutCopyMode = False
Selection.Copy
Range(cell2).Select
ActiveSheet.Paste
That should paste the relative formula.

Infinite loop while gathering datasets from several worksheets

This is my first time to code in VBA.
I have several worksheets in a file and they are in order by dates.
So what I am trying to do is to collect data sets in a worksheet if they have the same period of time.
date1 value1
date2 value2
date3 value3
Since they are in order I just compare the first date values and if they are different it moves on to the next worksheet. If they are the same then copy the value and do the same process until it reaches the last worksheet.
However it copies one worksheet fine but after that Excel freezes.
I would be appreciated if you find any errors or give me other suggestions to do it.
Following is my code:
Sub matchingStock()
Dim sh1 As Worksheet, sh2 As Worksheet
' create short references to sheets
' inside the Sheets() use either the tab number or name
Set sh1 = Sheets("combined")
Dim col As Long
'since first column is for Tbill it stock price should place from the third column
col = 3
Dim k As Long
'go through all the stock worksheets
For k = Sheets("WLT").Index To Sheets("ARNA").Index
Set sh2 = Sheets(k)
' Create iterators
Dim i As Long, j As Long
' Create last rows values for the columns you will be comparing
Dim lr1 As Long, lr2 As Long
' create a reference variable to the next available row
Dim nxtRow As Long
' Create ranges to easily reference data
Dim rng1 As Range, rng2 As Range
' Assign values to variables
lr1 = sh1.Range("A" & Rows.Count).End(xlUp).Row
lr2 = sh2.Range("A" & Rows.Count).End(xlUp).Row
If sh1.Range("A3").Value = sh2.Range("A3").Value Then
Application.ScreenUpdating = False
' Loop through column A on sheet1
For i = 2 To lr1
Set rng1 = sh1.Range("A" & i)
' Loop through column A on sheet1
For j = 2 To lr2
Set rng2 = sh2.Range("A" & j)
' compare the words in column a on sheet1 with the words in column on sheet2
'Dim date1 As Date
'Dim date2 As Date
'date1 = TimeValue(sh1.Range("A3"))
'date2 = TimeValue(sh2.Range("A3"))
sh1.Cells(1, col).Value = sh2.Range("A1").Value
' find next empty row
nxtRow = sh1.Cells(Rows.Count, col).End(xlUp).Row + 1
' copy the word in column A on sheet2 to the next available row in sheet1
' copy the value ( offset(0,1) Column B ) to the next available row in sheet1
sh1.Cells(nxtRow, col).Value = rng2.Offset(0, 6).Value
'when the date is different skip to the next worksheet
Set rng2 = Nothing
Next j
Set rng1 = Nothing
Next i
'sh3.Rows("1:1").Delete
Else
GoTo Skip
End If
Skip:
col = col + 1
Next k
End Sub
I cannot identify a specific error so this is a list of suggestions that may help you identify the error and may help improve your code.
Suggestion 1
Do you think the Else block of If-Then-Else-End-If is compulsory?
If sh1.Range("A3").Value = sh2.Range("A3").Value Then
:
Else
GoTo Skip
End If
Skip:
is the same as:
If sh1.Range("A3").Value = sh2.Range("A3").Value Then
:
End If
Suggestion 2
I do not like:
For k = Sheets("WLT").Index To Sheets("ARNA").Index
The value of property Index for a worksheet may not what you think it is. This may not give you the set or sequence of worksheets you expect. Do you want every worksheet except "Combined"? The following should be more reliable:
For k = 1 To Worksheets.Count
If Worksheets(k).Name <> sh1.Name Then
:
End If
Next
Suggestion 3
You use:
.Range("A" & Rows.Count)
.Range("A3")
.Cells(1, col).Value
.Cells(Rows.Count, col)
rng2.Offset(0, 6)
All these methods of identifying a cell or a range have their purposes. However, I find it confusing to use more than one at a time. I find .Cells(row, column) and .Range(.Cells(row1, column1), .Cells(row2, column2)) to be the most versatile and use them unless there is a powerful reason to use one of the other methods.
Suggestion 4
I cannot decypher what this code is attempting to achieve.
You say: "I have several worksheets in a file and they are in order by dates. So what I am trying to do is to collect data sets in a worksheet if they have the same period of time."
If you have set Worksheet("combined").Range("A3").Value to a particular date and you want to collect data from all those sheets with the same value in cell A3 then the outer For-Loop and the If give this effect. But if so, if does not matter how the worksheets are ordered. Also you start checking cell values from row 2 which suggests row 3 is a regular data row.
The outer loop is for each worksheet, the next loop is for each row in "combined" and the inner loop is for each row in the worksheet selected by the outer loop. The middle loop does not appear to do anything but set rng1 which is not used.
Perhaps you can add an explanation of what you are trying to achieve.
Suggestion 5
Are you trying to add an entire column of values from the source worksheets to "Combined". The macro below:
Identifies the next free row in column A of "Combined"
Identifies the last used row in column A of "Sheet2"
Assumes the first interesting row of "Sheet2" is 2.
Adds the entire used range of column A of "Sheet2" (complete with formatting) to the end of "Combined"'s column A in a single statement.
This may demonstrate a better way of achieving the effect you seek.
Sub Test()
Dim RngSrc As Range
Dim RngDest As Range
Dim RowCombNext As Long
Dim RowSrcFirst As Long
Dim RowSrcLast As Long
With Worksheets("Combined")
RowCombNext = .Cells(Rows.Count, "A").End(xlUp).Row + 1
Set RngDest = .Cells(RowCombNext, "A")
End With
With Worksheets("Sheet2")
RowSrcFirst = 2
RowSrcLast = .Cells(Rows.Count, "A").End(xlUp).Row
Set RngSrc = .Range(.Cells(RowSrcFirst, "A"), .Cells(RowSrcLast, "A"))
End With
RngSrc.Copy Destination:=RngDest
End Sub