Data Validation Dynamic Range Moves Range Instead of Expanding Range - vba

In Excel, I have a Data Validated range using the OFFSET() function that I'm hoping to dynamically add information to that I can then select in a drop down list. I have a VBA macro that I'm adding information to this list from and instead of expanding the list from $L$10:$L$230 to $L$10:$L$231, it shifts my list down to $L$11:$L$230. What am I doing incorrectly in my Named Range or Data Validation to not make this work? Or does it have something with using VBA to add to the range that causes it to work incorrectly?
"Rooms" in my Name Manager Refers To:
=OFFSET(Sheet1!$L$10,0,0,COUNTA(Sheet1!$L:$L),1)
My Data Validation Drop Down Souce:
=Rooms
My "insert" Macro to add to the list:
Sub insert()
'
' insert Macro
'
'
Range("A2:E2").Select
Selection.Copy
Sheets("Sheet1").Select
Range("L10:P10").Select
Selection.insert Shift:=xlDown
Sheets("INSERT NEW ROOM").Select
ActiveWindow.SmallScroll Down:=-18
Range("A2").Select
End Sub
I also have a "Sort" VBA included in my Sheet1 for every time a new instance is added from the "INSERT NEW ROOM" tab.
Private Sub Worksheet_Change(ByVal Target As Range)
On Error Resume Next
If Not Intersect(Target, Range("L9:L500")) Is Nothing Then
Range("L9").Sort Key1:=Range("L10"), _
Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, _
Orientation:=xlTopToBottom
End If
End Sub

This happens because your insert macro changes the range your named range formula refers to, just like it would any normal formula.
The formula has a reference to cell $L$10. When you execute
Range("L10:P10").Insert Shift:=xlDown
any formula, including the named range formula, that referes to a cell on or below row 10 will be updated to refer to a cell one row down (ie $L$11 in this case)
You can fix this by changing your named range formula to this
=OFFSET(Sheet1!$L$1,9,0,COUNTA(Sheet1!$L:$L),1)
Notice it now refers to cell $L$1 so is not affected by the insert.
Note:
You insert macro could do with some work
Try this instead
Sub InsertRooms() ' renamed to avoid using a built in function name
Range("A2:E2").Copy
Worksheets("Sheet1").Range("L10:P10").insert Shift:=xlDown
Application.CutCopyMode = False
End Sub

Related

Macro for copying certain cells between excel worksheets

I would like to make a macro which will copy certain cells values marked by user in one sheet to another,but into different cells.
In one worksheet we have data in cells from A1 to D1,my goal is to paste them into second worksheet but to another cells (A2,A4,A6,A8 in my case)
And also when somebody copies for example more than four cells it will also paste them right next (B2,B4,B6,B8 and so on..)
I've managed something like this but it does not work
Sub sbCopyRangeToAnotherSheet()
'Copy the data
Sheets("Arkusz2").Range("A2:D2").Copy
Sheets("Arkusz1").Activate
'Select the target range
Range("A2", "A5", "A8", "A11").Select
'Paste in the target destination
ActiveSheet.Paste
Application.CutCopyMode = False
End Sub
The correct syntax is
Sub sbCopyRangeToAnotherSheet()
Sheets("Arkusz2").Range("A2:D2").Copy
Sheets("Arkusz1").Range("A2,A5,A8,A11").PasteSpecial
Application.CutCopyMode = False
End Sub
or you can even do it in one line:
Sub sbCopyRangeToAnotherSheet()
Sheets("Arkusz2").Range("A2:D2").Copy Sheets("Arkusz1").Range("A2,A5,A8,A11")
End Sub
And I recommend to read: How to avoid using Select in Excel VBA.

VBA not updating Excel rows referring to other sheets in same workbook when sorting rows alphabetically

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!

Change from absolute to relative reference in Excel formula (VBA)

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

VBA Code works differently in different workbooks

Hello I have a simple VBA code, which copies a column and pastes it in another column without the empty cells, which are in the original column. It works in the woorkbook, where I wrote it. But I copied it to another one, where I need it. It copies the the needed cells more than once and it fills the whole column the these values.
Range("f5:f2500").ClearContents
With Range("d5:d2500")
.Offset(, 0).SpecialCells(xlCellTypeFormulas, _
xlNumbers).Copy
.Offset(, 2).PasteSpecial skipblanks:=True, _
Paste:=xlPasteValues
End With
The Sub below will copy the formulas (with values in cells) from column D, and paste their values in column F, starting from Cell "F5" and down (without blanks).
The Sub receives the Worksheet.Name as an argument, so all the Ranges inside are fully qualified with that certain worksheet's name.
Code
Option Explicit
Sub CopyColumnWOBlanks(wsName As String)
With Worksheets(wsName)
.Range("F5:F" & .Cells(.Rows.Count, "F").End(xlUp).Row).ClearContents
.Range("D5:D" & .Cells(.Rows.Count, "D").End(xlUp).Row).SpecialCells(xlCellTypeFormulas, xlNumbers).Copy
.Range("F5").PasteSpecial Paste:=xlPasteValues, skipblanks:=True
End With
End Sub
This Main sub below, is just for testing, modify it to fit your needs.
Sub Main()
CopyColumnWOBlanks ("Sheet5") ' <-- change "Sheet5" to whatever worksheet you want the macro to run
End Sub

Copy formula from a specific sheet and cell and drag it down until specific column last row

So far I have this code below; counting last cell is working fine but is copy/pasting the wrong data to wrong sheet. Should copy data and use the formula from Sheet "Parsing" cell B2, and its using the main sheet where is the VBA. Looks lile what is missing is to execute the copy/select to "parsing" sheet, but didnt manage to do it.
Sub drag_formula_original()
Dim myLastRow As Long
With Worksheets("Parsing")
myLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("B2").Copy Destination:=.Range("B2:B" & myLastRow)
Application.CutCopyMode = False
End With
End Sub
Its solved. Thanks a lot.
Range("B2").Copy
The above will grab by default from the Activesheet
you have to tell it what sheet you would like it to pick that range/value from.
sheets("Parsing").Range("B2").Copy
Edit: Just noticed your With
To actually use a with you need to use a "." e.g. your copy line would look like below
.Range("B2").Copy
One other thing to note this:
Range("B2:B" & myLastRow).Select
ActiveSheet.Paste
Is rather inefficient, below would be better. Selecting in general is best to keep away from it is rather slow
Range("B2:B" & myLastRow).Paste
Or with your with
.Range("B2:B" & myLastRow).Paste
I just copied and pasted your code and ran it. I changed nothing in your code except for adding "Option Explicit" before your sub. (Just a personal habit)
Option Explicit
Sub drag_formula_original()
Dim myLastRow As Long
With Worksheets("Parsing")
myLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Range("B2").Copy
Range("B2:B" & myLastRow).Select
ActiveSheet.Paste
Application.CutCopyMode = False
End With
End Sub
I did, however, use a very simple formula in cell B2. What I did was have column A go from 1 to 10 and column C go from 11 to 20. Cell B2 was =A2+C2.
After running the code I checked each cell in column B and they each had the correct formula in them, and not a hard-coded value.
A trick I do when I want to do something like this but can't figure out how is I record a macro of me dragging the cell formula down a little ways and then stop the recording and look at the code it made. From that you should be able to adjust it to do what you want.
When I did that I got this code:
Sub Macro1()
'
' Macro1 Macro
'
'
Range("B2").Select
Selection.AutoFill Destination:=Range("B2:B15"), Type:=xlFillDefault
Range("B2:B15").Select
End Sub