I am still new to VBA, but I am trying to paste a copied selection of rows and columns from a different workbook to the current workbook. My issue is that it errors out when I try to paste I assume because the selection is larger than the destination selection. Below part of the code (I know, horrible and with selects):
dim i as long
Workbooks.Open Filename:="C:\Users\...\File1.xls"
Range("A15").Select
For i = 1 To n
ActiveCell.FormulaR1C1 = "=CONCATENATE(RC[1],RC[2])"
ActiveCell.Offset(1, 0).Select
Next i
Range("Q15").Select
For i = 1 To n
ActiveCell.FormulaR1C1 = "=VLOOKUP(RC[-16] ,'[file2.xlsm]DST'!C1:C18,1,0)"
ActiveCell.Offset(1, 0).Select
Next i
ActiveSheet.Range("$A$14:$Q$103").AutoFilter Field:=17, Criteria1:="#N/A"
Range("A1").End(xlDown).SpecialCells(xlCellTypeVisible).Copy
Windows("File2.xlsm").Activate
ThisWorkbook.Worksheets("sheet2").Activate
Range("B1").End(xlDown).Offset(1, -1).Select
'moves the active cell to the data end of column A
Debug.Print "Active cell is " & ActiveCell.Address(False, False)
'it puts the cursor correctly here, but it errors out after in the selection
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False
Basically, this is part of a code that is adding a new column in a system export file(1), where a unique searching key composed of the second and third column is used later in a VLOOKUP formula to check if there are any missing products and if there are, those will be added in the reporting file(2), at the end of the data that is there. Column B is used as column A has a formula (another CONCATENATE that can't be used for the selection).
How can I make the selection work ?
The following code isn't the solution but it contains it.
Dim WbTarget As Workbook
Dim WsT As Worksheet
Dim Rng As Range
Set WbTarget = Workbooks("File2.xlsm") ' must be open
Set WsT = WbTarget.Worksheets("Sheet2")
Set Rng = WsT.Range("B1").End(xlDown).Offset(1, -1)
With ActiveSheet
.Range("$A$14:$Q$103").AutoFilter Field:=17, Criteria1:="#N/A"
.Range("A1").End(xlDown).SpecialCells(xlCellTypeVisible).Copy Destination:=Rng
End With
Basically, it avoids the PasteSpecial method which would require source and target ranges to be of identical size.
Its big flaw is its reference to ActiveSheet. You have code here to declare and set a workbook, a worksheet and a range. The target workbook, worksheet and range are never selected or activated. I recommend that you treat the source in the same way.
Set Option Explicit at the top of your code sheet. Remember that it is best practice to make all declarations at the beginning of a procedure and, if you like to allow me one more piece of advice, consider writing the results of worksheet functions into your worksheet rather than the worksheet functions.
Related
Sub Save7()
Dim NextRow As Range
Set NextRow = Range("AC" & Sheets("Sheet1").UsedRange.Rows.Count)
Sheet3.Range("AC14:AG14").Copy
Sheet1.Activate
NextRow.PasteSpecial Paste:=xlValues, Transpose:=False
Application.CutCopyMode = False
Set NextRow = Nothing
End Sub
My purpose of this code is to copy data ( Five columns of 'NO' in AC14 to AG14) from sheet 3 and paste to sheet 1 where the last active cell is at.
The code above is working well, however I made some modification to the sheet tab name for sheet 1. Sheet 1 is now called "Equipment stuffs", while sheet 3 name is remaining unchanged.
After those changes, the macro stopped working. The cause is probably because I don't know how to declare "Equipment stuffs" in the code .
There's no need to do copy/paste to move data from one place on the spreadsheet to another. You should simply assign the Value of the respective Range objects, for example:
Sheet1.Range("NamedRange2").Value = Sheet1.Range("NamedRange2").Value
Also, use code names for the sheets, instead of Sheets("SheetName"), and defined named for the ranges, instead of Range("AC14:AG14", otherwise your code will stop working if the user renames the sheet or inserts or deletes any rows above your reference.
If you want to automate this a little you could collect the active workbook and loop through each sheet using wb.Worksheets. Then collect the name with targetSheet.Name.
Option Explicit
Public Sub getSheet()
Dim wb As Workbook
Dim targetSheet As Worksheet
Set wb = ActiveWorkbook
For Each targetSheet In wb.Worksheets
Debug.Print targetSheet.Name
Next targetSheet
End Sub
I’m brazilian hehe, I understood your question , I’ve a code for alter the data in same worksheet (I’ll attach it here), for you to change the data in another worksheet, you need put on:
Worksheets("NameWorkSheet) Activate
for the VBA that’s refers to this tab.
I'm having problems, Excel is not updating rows referring to other sheets in same workbook when ordering rows alphabetically.
I have a userform in which there's a button insertCM with this code:
Private Sub insertButton_Click()
ActiveCell.EntireRow.Select
Selection.Insert Shift:=xltoDown
Range("A9:AK9").Copy
Range("A8:AK8").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.PasteSpecial Paste:=xlPasteFormats
Range("C10").Copy
Range("C8:C9").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Range("H9:AK9").Copy
Range("H8:AK8").Select
Selection.PasteSpecial Paste:=xlPasteAll
nomCM = Empty
CXinitial = Empty
resteCX = Empty
CCselect = Empty
C4initial = Empty
resteC4 = Empty
compteurCT = Empty
Range("A8").Activate
ActiveCell.RowHeight = 18.6
For i = 2 To ThisWorkbook.Sheets.Count
With Sheets(i).Select
emptyRow = Range("A9").End(xlDown).Offset(0, 2).Row
Range("A9:AL" & emptyRow).Sort _
Key1:=Range("A9"), Order1:=xlAscending
Set SearchRange = Range("A8", Range("A200").End(xlUp))
Set FindRow = SearchRange.Find(nomCM, LookIn:=xlValues, LookAt:=xlWhole)
Range("A" & FindRow.Row).Select
ActiveCell.EntireRow.Activate
End With
Next i
Sheet2.Select
End
End Sub
The userform is used for inserting new clients in several sheets at the same time. Textbox inserts Name, Cost Center, etc., in a blank row and insertButton inserts a new row leaving data inserted in row 8 to go to row 9. After that the code puts all rows alphabetical order so the new client now in row 9 goes to the new one, and cells containing formulas change row numbers.
However some of the sheets have cells containing references to other sheets' cells in the same row. So imagine:
I insert client name "LORUM" "Cost Center 4" and it puts him in row 9 so formula is:
=$C9-COUNTIF($E9:$P9;"CT")+'Sheet5'!$D9
...but when it changes his row to the final one, formula row is:
=$C18-COUNTIF($E18:$P18;"CT")+'Sheet5'!$D9
It does not change row when referring to other sheets.
Any ideas?
It's looks like you've made a good effort, but there are still numerous problems with your code (beside the one line), and I can guarantee that a combination of these issues are preventing your intended outcome.
I can't fix it completely because there are so many bugs that I'm not clear on what you're trying to do, but hopefully this will get you started on the right track...
xlToDown is not a valid reference. You probably mean xlDown
you have a number of undeclared variables and objects, like: i, emptyRow, SearchRange, FindRow, nomCM
you have things (objects?) "set to nothing" that aren't declared or used anywhere: CXinitial, resteCX, CCselect, C4initial, resteC4, compteurCT
your Find statement is looking for nomCM which is empty (and never set), so the Find statement will never find anything.
You should put Option Explicit at the top of every module (especially when learning or troubleshooting). This will prevent issues like the ones above by "forcing" you to properly declare & handle all of your variables, objects, properties, etc.
Near the end, you refer to Sheet2.Select as if Sheet2 is a declared object, instead of using Sheets("Sheet2").Select. I'm not sure why you're selecting the sheet at the very end anyhow.
You have an With..End statement that is doing absolutely nothing since you don't reference it with a . dot anywhere: With Sheets(i).Select .. End With, and also Select isn't used like that.
A mystery End near the end for some reason.
Also, you're unnecessarily doubling up commands like:
ActiveCell.EntireRow.Select
Selection.Insert Shift:=xlDown
..instead of:
ActiveCell.EntireRow.Insert Shift:=xlDown
and another example, all this:
Range("A9:AK9").Copy
Range("A8:AK8").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Selection.PasteSpecial Paste:=xlPasteFormats
Range("C10").Copy
Range("C8:C9").Select
Selection.PasteSpecial Paste:=xlPasteFormulas
Range("H9:AK9").Copy
Range("H8:AK8").Select
Selection.PasteSpecial Paste:=xlPasteAll
...instead of:
Range("A9:AK9").Copy
Range("A8:AK8").PasteSpecial xlPasteValuesAndNumberFormats
Range("C10").Copy
Range("C8:C9").PasteSpecial Paste:=xlPasteFormulas
Range("H9:AK9").Copy Range("H8:AK8")
All of this would be more clear by Googling the documentation for each command you're unfamiliar with, such as:
Range.Copy Method (Excel)
Range.PasteSpecial Method (Excel)
XlPasteType Enumeration (Excel)
All the ActiveCell and ThisWorkbook references are troublesome but again, I'm not sure what to do with them since I don't know your workbook.
Indentation (and general organization) are very important as well. It may not change the way that the code runs, but it will help you (and others) track down existing & potential issues more easily.
Here is your code cleaned up as best as I could:
Option Explicit 'this line goes at the very top of the module
Private Sub insertButton_Click()
Dim i As Long, emptyRow As Long, SearchRange As Range, FindRow As Range, nomCM
nomCM = Empty
ActiveCell.EntireRow.Insert Shift:=xlDown
Range("A9:AK9").Copy
Range("A8:AK8").PasteSpecial xlPasteValuesAndNumberFormats
Range("C10").Copy
Range("C8:C9").PasteSpecial Paste:=xlPasteFormulas
Range("H9:AK9").Copy Range("H8:AK8")
Range("A8").RowHeight = 18.6
For i = 2 To ThisWorkbook.Sheets.Count
With Sheets(i)
emptyRow = .Range("A9").End(xlDown).Offset(0, 2).Row
.Range("A9:AL" & emptyRow).Sort Key1:=.Range("A9"), Order1:=xlAscending
Set SearchRange = .Range("A8", .Range("A200").End(xlUp))
Set FindRow = SearchRange.Find(nomCM, LookIn:=xlValues, LookAt:=xlWhole)
.Range("A" & FindRow.Row).Select
ActiveCell.EntireRow.Activate
End With
Next i
Sheets("Sheet2").Select
End Sub
as per my test, sorting actually doesn't change other sheet direct references
so you may want to use OFFSET to keep referencing the actual current row index
instead of:
=$C9-COUNTIF($E9:$P9;"CT")+'Sheet5'!$D9
use
=$C9-COUNTIF($E9:$P9;"CT")+ OFFSET('Sheet5'!$D1,ROW()-1,0)
I found a solution:
=INDIRECT(ADDRESS(ROW();4;3;1;"Sheet5"))
Where Row() will always refer to the actual cell's row.
Hope it will help you!
Unfortunately I couldn’t find the answer to the below in the other questions – my problem is related to copying and pasting a formula that would use relative cell references instead of dynamic ones.
The general problem with the workbook I’m working on is the fact that it contains of a couple of different sheets with a potential dynamic range change. To give a better outline:
The column the formula has to be in, is based on an offset cell – I cannot give it a static value – and starts in row 2;
The formula itself is as follows: =CONCATENATE(LEFT(AA2,13), “:”, RIGHT(AA2,5) (and the values to be concatenated will always appear in the AA column)
The macro is supposed to insert the formula in the offset cell, copy it and paste it in the entire column, so the cell in row 3 refers to cell AA3 and so on:
Sub Copy1()
Range("A1").Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.End(xlToRight).Select
ActiveCell.Offset(, 1).Select
Dim rng as Range
Set rng = ActiveCell
rng.Select
rng.Offset(1, 0).Select
ActiveCell.FormulaR1C1 = "=CONCATENATE(LEFT(R2C27,13), "":"", RIGHT(R2C27,5))"
rng.Offset(1, 0).Select
Selection.Copy
Range(Selection, Selection.End(xlDown)).Select
ActiveSheet.PasteSpecial
Selection.EntireColumn.Select
Application.CutCopyMode = False
End Sub
The problem is – upon trying to insert exact name of the cell, the macro populates it with the following:
=CONCATENATE(LEFT(‘AA2’,13), "":"", RIGHT(‘AA2’,5))
Because of the quotation marks, the formula doesn’t work.
Using the reference R2C27 results with absolute values being copied and thus every single cell in the column refers to cell AA2.
Is there any possibility make it create, copy and paste relative reference instead of absolute?
R1C1 reference is usually not needed as relative references are auto-adjusted if you copy+paste the formula or assign it to multiple cells. For example:
Range("A2:A9").Formula = "=CONCATENATE(LEFT(AA2,13), "":"", RIGHT(AA2,5)"
If I understand you want the column reference to be always $AA (absolute) while the row reference be relative. You can try this:
ActiveCell.Formula = "=CONCATENATE(LEFT($AA2,13), "":"", RIGHT($AA2,5))"
Then the autofill will adjust automatically the row number while keeping the column at "$AA".
That said, refactor your code to get rid of the select stuff. Look how shorter it will be in addition to using "Explicit references" (just replace "Sheet1" with the actual name of your worksheet):
Sub Copy1()
Dim rng As Range
Set rng = Worksheets("Sheet1").Range("A1").End(xlToRight).Offset(1, 1)
rng.Formula = "=CONCATENATE(LEFT($AA2,13), "":"", RIGHT($AA2,5))"
rng.Copy rng.Parent.Range(rng, rng.End(xlDown))
End Sub
I am very new, never done programming before and never used a forum before. I have read a lot of other posts to get as far as I have done in Excel to try and get it to perform as I require.
Basically I have a number of data sets, each with 4 variables, each set needs to be copied into appropriate fields on another worksheet, then the 2 outputs from this, recorded back onto the first sheet in 2 separate columns for each data set.
I have got the macro to do nearly all of it however it pastes only the last set of data outputs in the cells not each individual set.
Unfortunately I appear not to be able to add screen shots.
Currently my macro text is:
Sub macro1()
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheet1.Range("C2:C6")
For Each rCell In rRng.Cells
rCell.Copy
Sheets("Sheet2").Select
Range("C2").Select
Sheets("Sheet2").Paste
Next rCell
Dim rCell2 As Range
Dim rRng2 As Range
Set rRng2 = Sheet1.Range("D2:D6")
For Each rCell2 In rRng2.Cells
rCell2.Copy
Sheets("Sheet2").Select
Range("D2").Select
Sheets("Sheet2").Paste
Range("C8").Select
Selection.Copy
Sheets("Sheet1").Select
Range("J2:J6").PasteSpecial Paste:=xlPasteValues
Next rCell2
Dim rCell3 As Range
Dim rRng3 As Range
Set rRng3 = Sheet1.Range("E2:E6")
For Each rCell3 In rRng3.Cells
rCell3.Copy
Sheets("Sheet2").Select
Range("E2").Select
Sheets("Sheet2").Paste
Next rCell3
Dim rCell4 As Range
Dim rRng4 As Range
Set rRng4 = Sheet1.Range("F2:F6")
For Each rCell4 In rRng4.Cells
rCell4.Copy
Sheets("Sheet2").Select
Range("F2").Select
Sheets("Sheet2").Paste
Range("D8").Select
Selection.Copy
Sheets("Sheet1").Select
Range("K2:K6").PasteSpecial Paste:=xlPasteValues
Next rCell4
End Sub
Apologies for the repetition, I hope someone can help.
Also if there are any good books that people can rate to learn basic macro and programming language that would be great.
You are using Range variables which is good but you are then using Select which should be avoided.
If you want to copy from Sheets("Sheet1").Range("C2:C6") and paste into Sheets("Sheet2").Range("C2:C6"), you can do this in one line of code. You do not need to loop through the cells for this:
Sheets("Sheet1").Range("C2:C6").Copy Sheets("Sheet2").Range("C2")
Your code as posted was looping through the cells but was always pasting into the same cell.
You can copy a larger block of code and it looks like your code is trying to copy cells C2:F6. Normally you can do that with one line:
Sheets("Sheet1").Range("C2:F6").Copy Sheets("Sheet2").Range("C2")
But maybe the paste special causes the values in columns D & E to get changed?
The PasteSpecial method requires two lines of code but this seems ok in your code. These lines of code copies one value and pastes it into five cells:
Sheets("Sheet2").Range("C8").Copy
Sheets("Sheet1").Range("J2:J6").PasteSpecial Paste:=xlPasteValues
You can simplify your code to:
Sheets("Sheet1").Range("C2:C6").Copy Sheets("Sheet2").Range("C2")
Sheets("Sheet1").Range("D2:D6").Copy Sheets("Sheet2").Range("D2")
Sheets("Sheet2").Range("C8").Copy
Sheets("Sheet1").Range("J2:J6").PasteSpecial Paste:=xlPasteValues
Sheets("Sheet1").Range("E2:E6").Copy Sheets("Sheet2").Range("E2")
Sheets("Sheet1").Range("F2:F6").Copy Sheets("Sheet2").Range("F2")
Sheets("Sheet2").Range("D8").Copy
Sheets("Sheet1").Range("K2:K6").PasteSpecial Paste:=xlPasteValues
And maybe copy larger blocks of cells to reduce the number of copy operations?
Sheets("Sheet1").Range("C2:D6").Copy Sheets("Sheet2").Range("C2")
Sheets("Sheet2").Range("C8").Copy
Sheets("Sheet1").Range("J2:J6").PasteSpecial Paste:=xlPasteValues
Sheets("Sheet1").Range("E2:F6").Copy Sheets("Sheet2").Range("E2")
Sheets("Sheet2").Range("D8").Copy
Sheets("Sheet1").Range("K2:K6").PasteSpecial Paste:=xlPasteValues
I'm trying to work on something in excel VBA but I can't seem to make it work fine.
Here's how it should work:
I need to copy and paste value of "J21" cell from one sheet to another. BUT, value of J21 keeps on changing every week. So I thought what if I create a code where I'll just press an object (say "STORE!") and it copies the value of "J21" from Sheet1 to "C3" Sheet 2. Then when the value of J21 changes, I just press "STORE!" again and it will copy the value of J21 and paste it on "C4" Sheet 2 without changing the previous value on "C3" Sheet 2.
Here's my latest attempt:
Dim myCell As Range, myRange As Range, i As Long
i = 3
Set myRange = Sheets("Summary").Range("C3")
Set myRange = Range(myRange, myRange.End(xlDown))
Sheets("Sheet1").Select
Range("J21").Copy
Sheets("Summary").Select
Cells(i, 3).Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone,
SkipBlanks:=False, Transpose:=False
i = i + 1
myCell and myRange were used for my previous attempts, but it always go on an infinite copy-paste.
Selection and copy-paste in VBA is usually not needed. If you want to modify the value of a cell it is better to just directly use the value property of a range object. You seem to want to establish a reference to the first blank cell below C2 on Sheet2. The problem with your code is that Range(myRange, myRange.End(xlDown)) selects an entire block of cells (above the cell you want) rather than a single cell. While it would be possible to use .End(xlDown) appropriately to get to the cell you want, it is somewhat tricky to get right since it behaves differently depending on whether or not the cell underneath the current cell is blank. A while loop is one way to go. Something like:
Sub store()
Dim target As Range, source As Range
Set source = Sheets("Sheet1").Range("J21")
Set target = Sheets("Sheet2").Range("C3")
Do While Not IsEmpty(target.Value)
Set target = target.Offset(1)
Loop
target.Value = source.Value
End Sub
Chip's suggestion that you learn the basics of VBA is a good one. If you are someone (like me) who learns through books better than with online tutorials, I would recommend almost anything by John Walkenbach -- I first learned to program Excel by reading an early edition of his "Excel VBA Programming for Dummies."