Using a variable to define a range [duplicate] - vba

This question already has answers here:
Excel VBA, getting range from an inactive sheet
(3 answers)
Closed 7 years ago.
I am attempting to store the value of an 8 x 1 range into a range of identical dimensions, but on another sheet in the workbook. This would be easy except that my script is looping through different ranges of these same dimensions and I need to store them all on the second sheet. Currently my code looks like this:
Sheets("Sheet1").Range(Cells(i, 2), Cells(i + 7, 2)).Value = Sheets("Sheet2").Range("OriginalData").Value
Where "i" is the variable being used as the iterator in the loop.
This code throws an error "Error 1004 "Application-defined or Object-defined error"". Can someone explain what I'm doing wrong, and how to properly define range objects dynamically in this fashion?

Your problem is that the Cells inside the Sheets("Sheet1").Range don't know that they are supposed to belong to Sheets("Sheet1").
with Sheets("Sheet1")
.Range(.Cells(i, 2), .Cells(i + 7, 2)) = _
Sheets("Sheet2").Range("OriginalData").Value
end with
'alternate
Sheets("Sheet1").Range("B" & i).Resize(8, 1) = _
Sheets("Sheet2").Range("OriginalData").Value
The With ... End With statement allows you to definitively pass the parent worksheet into both .Range and .Cells with the prefix period (aka full stop).

Would a copy and paste work? I'm not sure of the specifics of your data but seems like a copy and paste would work better.
So like
Sheets("Sheet1").Range("x:x").Copy Sheets("Sheet2").Range("x:x")

Related

Efective method to find last row vba excel [duplicate]

This question already has answers here:
Find last used cell in Excel VBA
(14 answers)
Closed 4 years ago.
i have the following method to set to define a ranga:
Set RegJan = Sheets("BD").Range("T3:T50000")
the range is smaller than this, but in order to make it work for some months, i set it to 50000 rows.
i then use this code in the following line of vba:
ws.Cells(8, 2).Value = Application.WorksheetFunction.SumIfs(RegJan,
EquipaBd, EquipaForm, AgenteBd, AgenteForm) 'Soma dos Registos
This last line i already transformed in a loop so that it calculates in every line i need it,the problem is that i have to do the first line of code for every month of the year an for 6 more variables
is there a better way of doing this? possibly a dynamic way?
This might give you some ideas:
With Sheets("BD")
' Since T is column #20 and goes to 6 more
For col = 20 To 26
' get last row
lastRow = .Cells(.Rows.Count, col).End(xlUp).Row
' set range
Set yourRng = .Range(.Cells(3, col), .Cells(lastRow, col))
' you might want to change 8,2 to make dynamic
ws.Cells(8, 2).Value = Application.WorksheetFunction.SumIfs(yourRng , EquipaBd, EquipaForm, AgenteBd, AgenteForm)
Next
End With

excel vba: creating a range without referencing a sheet

I would like to know if I can save a generic range, without it having a sheet name attached to it?
Lets say that my program creates a sheet for every day of the week, and then makes headings for every sheet. I want to give it a few ranges, and it must merge and add different headings to those ranges in EVERY sheet. So the headings of every sheet looks the same.
I have the following range for example:
...
Set rowTwoHeadingKiloRange = Range(Cells(2, 4), Cells(2, 8))
Set rowTwoHeadingUnitRange = Range(Cells(2, 10), Cells(2, 14))
...
Now when I try to pass this range in a dictionary to every sheet that gets created, I find that I have undesired results as some of the headings gets created on sheets where they do not belong (And I think that is because when the range is created, it attaches to the active sheet at that moment - which may be different from time to time).
So now I basically have a function that looks something like this...
Public Function colmHeadingsAndSpacing(sheetName)
With Worksheets(sheetName)
...
Set rowTwoHeadingKiloRange = Range(Cells(2, 4), Cells(2, 8))
Set rowTwoHeadingUnitRange = Range(Cells(2, 10), Cells(2, 14))
...
End with
End Function
... and I run the function every time I create a sheet, with the name of the sheet that was just created given through. But this runs the function 7 times, when I use the same data (range) every time. Also I feel that it is not working properly as well (I still get strange reactions - ranges ending up in wrong sheets).
Second question, is there a way to find out on a range, what sheet is "attached" to the range. Something like: msgbox rowTwoHeadingKiloRange.worksheets.name which will give the result of Sunday
You were close. To attach your Range and Cell to the With statement you need to use a full-stop . before the keyword. Like this:
Public Function colmHeadingsAndSpacing(sheetName)
With ThisWorkbook.Worksheets(sheetName)
...
Set rowTwoHeadingKiloRange = .Range(.Cells(2, 4), .Cells(2, 8))
Set rowTwoHeadingUnitRange = .Range(.Cells(2, 10), .Cells(2, 14))
...
End with
End Function
This is good practice to qualify every range reference with it's attached worksheet. I went one step further included a workbook reference (ThisWorkbook). Now it's fully qualified.
For the second question -- try MsgBox rowTwoHeadingKiloRange.Parent.Name to get the name of the worksheet. It's usually better to start with the worksheet name rather than work back to it though.
A range is a reference of a (mostly rectangular) area on a sheet. So referring to a range without defining a sheet like Set r = Range ("B2:F10") is exactly the same as Set r = Activeworkbook.Activesheet.Range ("B2:F10"). So for more professional purposes VBA offers you the flexibility in the following way:
Dim wb As Workbook
Dim ws As Worksheet
Set wb = Workbooks.Add ' open new xlsx file
Set ws = Activesheet OR
Set ws = wb.Activesheet OR
Set ws = wb.Sheets(1)
' do something else here and later when neither wb nor ws is active, you can
Set r = wb.ws.Range("B5:G22") OR
Set r = ws.Range("B5:G22")
An addition: for producing a number of sheets of the same format, you may consider using templates either. Then you need to fill in only the differences programatically. Less programming, easier maintenance :)

Looping with ranges not allowing Range(Cells,Cells) only Range("A:A")

Background:
I have an array of 7 x 30 cells to loop through. For each of the 30 columns (Dim j), I am looping through rows (Dim i) 1 to see if a value is present and if so start copying the range of rows 2 through 7.
In attempting to use (e.g.):
Sheets("NAME").Range(Cells(i+1,1),Cells(i+7,1)).Copy
I am getting a 1004, Application-defined or object-defined error, that I have been able to alleviate using:
Sheets("NAME").Range("A" & i+1 & ":A" & i+7 & ").Copy
Error on line from my code:
Sheets("RM").Range(Cells(i + 6, 2), Cells(i + 13, 2)).Copy
Issue:
This has worked for items with known columns, but I am unsure how to proceed for a variable column, as well. I know that this doesn't work:
Sheets("NAME").Range(Cells(i+1,j),Cells(i+7,j)).Copy
I would need to find a way to fit this Range model without Cells to work for j, a variable column.
Question:
Is there a way to make this work using Range without using Cells?
My only guess is the following, which I believe uses incorrect syntax:
Sheets("NAME").Range(Columns(j) & i+1 & ":" & Columns(j) & i+1).Copy
Any help would be appreciated!
Edit: added the error 1004 name to this Issues section.
Try prefacing your Cells( call with the sheet i.e. Range(Sheets("Sheet1").Cells(1, 1), Sheets("Sheet1").Cells(2, 2))
When you omit the sheet in a call to Cells or Range then it will default to a reference to the currently selected sheet, so if you're calling Sheets(Unselected Sheet).Range(Cells(1, 1)) it gets confused between which sheet you're referring to.

Excel VBA Copy Paste [duplicate]

This question already has answers here:
Excel VBA, getting range from an inactive sheet
(3 answers)
Closed 7 years ago.
I'm trying to copy and paste a certain range from one worksheet to two other worksheets. This is a snippet of code where it seems to go wrong:
row = ActiveWorkbook.Sheets("SheetX").Cells(Rows.Count, 3).End(xlUp).Row
ws.Range("A1", "J1").Copy
ActiveWorkbook.Sheets("Sheet1").Range("B2", "K2").PasteSpecial xlPasteValues
ActiveWorkbook.Sheets("SheetX").Range(Cells(row, 3), Cells(row,12)).PasteSpecial xlPasteValues
Since the amount of rows is dynamic "row" holds the row number I want to paste it to.
The problem is that I get a "Application-defined or Object-defined"-error on the last line, where I try to past it to the second worksheet.
When you run Cells(row,3) you are actually calling Cells(row,3) on the ActiveSheet and not on Sheets("SheetX"). Instead you should do this:
row = ActiveWorkbook.Sheets("SheetX").Cells(Rows.Count, 3).End(xlUp).Row
ws.Range("A1", "J1").Copy
ActiveWorkbook.Sheets("Sheet1").Range("B2", "K2").PasteSpecial xlPasteValues
Range(ActiveWorkbook.Sheets("SheetX").Cells(row, 3), ActiveWorkbook.Sheets("SheetX").Cells(row,12)).PasteSpecial xlPasteValues

Excel/VBA How to move data from one worksheet to another after last used cell?

I've got a workbook with 9 different worksheets in which 1 of the sheets if 4 of them combined into 1 sheet for further comparison which from a copy and paste point of view is easy but im looking at it from an automation point of view as the length of rows can increase and decrease depending on data.
i need sheet A to copy in first on the left hand side on columns A,B,C which is then followed by sheet B which is inserted directly below sheet a on the same columns. Sheets C and D are similar but on the right of the first 2 sheets in columns H,I,J so they can be compared
I've tried to be clever and run multiple for loops on each sheet copying the data over to this work sheet with A&B sharing a global variable and C&D holding another so they went into the right places. Issue i had with this is long running times and mainly crashing on excel.
i also tried copying an pasting all the columns but didn't work as they vary in length so cant be recorded.
I finally tried a way of setting an row counter to be the last used row of the previous sheet to work but it also resulted in crashing.
Sheets("Income").Select
Dim xell As Range
For Each xell In Range("A1:A3005")
If Not xell.Value = "" Then
xell.EntireRow.Copy
Sheets("Workings").Select
Cells(z, "A").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=True, Transpose:=False
Sheets("Income").Select
z = z + 1
End If
Next xell
This is an example of my first attempt with the other sheets code being similar anyone got an idea of how to copy 4 work sheets into 1 in the desired destinations>?
Some things:
First, stop using Sheets().Select. There is no need, it will just flicker madly. You can safely use Sheets("Workings").Cells(...) to reference Cells on a Sheet.
Second, Cells() takes only integers as parameters, not "A". At best, this will be converted to 65 (ASCII) which is wrong for your case. Use Cells(z, 1) instead of Cells(z, "A").
Third, z needs to start at 1, not 0. You didnt initialize it anywhere so it will start as 0, which crashes.
You could try this:
Sub CopyIt()
allSheets = Array(Array(sheets("A"), sheets("B")), Array(sheets("C"), sheets("D")))
Set destSheet = sheets("Dest")
Set startRange = destSheet.Range("A1")
For Each doubleSheet In allSheets
For Each srcSheet In doubleSheet
Set firstEmpty = srcSheet.Columns(1).Find("")
If Not firstEmpty Is Nothing Then
RowCount = srcSheet.Columns(1).Find("").Row - 1
Range(srcSheet.Cells(1, 1), srcSheet.Cells(RowCount, 3)).Copy Destination:=startRange
Set startRange = startRange.Offset(RowCount, 0)
End If
Next
Set startRange = destSheet.Range("H1")
Next
End Sub