Hi thanks everyone in advance.
I have a data set. lets say A3 to Z30. the number of rows and columns varies. also there are blanks in the set. So lets say i want to select the entire section but there's a blank in Z29 and X30 using
Range("A3").Select
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy
isn't going to work.
But the values in column A is continuous. So i think the first part will work
Range("A3").Select
Range(Selection, Selection.End(xlDown)).Select
now i know this may seem elementry but how the heck do i select all the rows i just highlighted? this needs to be dynamic because as i said the number of columns and rows vary.
Oh and bonus karma and kudos if you can help me to figure out the next part. I need to select the range and paste it immediately after the the last row but the value in the first cell or A31 in this case would need to change and that is being pulled from a list in sheet2
Use the .EntireRow method.
Here is an example:
Dim report as Worksheet
Set report = Excel.ActiveSheet
report.cells(1,1).EntireRow.Select
If you want to select the cells themselves, you can use the .UsedRange method.
Here is an example:
Dim report As Worksheet
Set report = Excel.ActiveSheet
report.Range(report.Cells(1, 1), report.Cells(1, report.UsedRange.Columns.Count)).Select
EDIT
Here is an example for part II of your question (as requested):
Sub test2()
Dim report As Worksheet
Set report = Excel.ActiveSheet
report.Cells(1, 1).EntireRow.Copy
report.Cells(report.UsedRange.Rows.Count + 1, 1).EntireRow.PasteSpecial xlPasteAll
End Sub
Be sure to note that the .UsedRange method also includes cells that have no values but have been formatted by the user; e.g., if you add bold font (even if you don't add the text itself) to a cell in row 1000, your .UsedRange.Rows.Count will be 1000.
Additionally, you can check my answer in the following link for more guidance. I've been told the notes are very helpful for beginners:
Excel Macro - Paste only non empty cells from one sheet to another (Stack Overflow)
You might want to look at this, and consider what you could do with Range.CurrentRegion, Range.Resize and Range.Offset, so you might get:
Range("A3").CurrentRegion.Copy
Additionally, there's no need to use Range.Select unless you want a user to see what is happening; instead of (for example) a Range.Select followed by a Selection.Copy() (which copies to the clipboard), you could just use a Range.Copy(Range), which copies direct to the target range.
As to the second part, you could:
Dim CopyRow as Long
CopyRow = Range("A3").CurrentRegion.Rows.Count
Range("A3").CurrentRegion.Copy(Range("A3").CurrentRegion.Offset(CopyRow))
Range("A3").Offset(CopyRow) = x ' Insert your reference to the Sheet 2 value here
I am aware that this thread is old, however I was looking for help with something similar. I knew my starting cell for my range, but the number of rows and columns were going to be dynamic. Using the following code worked for me:
Range("A2").Select
Range(Selection, Selection.End(xlDown).End(xlToRight)).Select
Hopefully anyone in the future can make use of this simple solution.
Related
Ok, back again!
I have tried to search throught this and other forums to find a similar solution, but everything Ive found is either just different enough that I cant figure out the application to my problem, or super complex, and I cant translate it! So Im hoping someone can help me here. Thanks in advance!!
Here is the scenario. I have a database that Im needing to add data to. Quote Number, PO Number,SubSystem Part Name, Vendor, Material, Price, Qty. Etc.
Long story short, and without getting into the context of why I did it this way (mostly because I think I would botch the explaination and be more confusing than helpful!) ... I have essentially 3 tables right next to each other.
Table 1 is columns H and I. These all have a formula similar to =if(isblank(J4),"",$I$1) Where I1 is the PO Number (which will remain the same for this set of entries.)
Table 2 is a pivot table in columns J through M. Using a slicer the user can select what sub systems they need for this PO. The pivot table will repopulate with the appropriate part numbers and unique information contained in another table.
Table 3 is a regular table in columns N through R. These columns have some formulas like above that pull from a single cell (for entering the date), some pull information from another table based on information in column J via a VLOOKUP, and some information is entered manually.
That might be too much information, but better to have it and not need it eh?
So heres the goal. With a VBA macro, I want to copy the data and paste it onto another sheet, at the bottom of a database. The trick is, because that whole setup above runs based on information coming from a pivot table, the list changes length constantly. It will never be longer than a certain length (still TBD) but will almost always be shorter. I can copy the whole thing, and have it paste to another sheet below the last entry... but it pastes below the last empty cell in the database sheet. What I mean is this:
The longest the table could be would be range H4:R38 for example. So I copy that, paste it to Sheet2 starting at cell A2. Upon further inspection, we see that there is only actual data in the range H4:R11. However, when we pasted it to Sheet2 it pasted the whole range H4:R38. When I run the macro again, instead of the new data set being pasted to row A10 (the row after where the data should have ended), it pastes to something like row 36... because its pasting below all the blank cells.
I have no idea what to do or where to start. Any help would be greatly appreciated! Thanks so much!
Code I've Tried:
Dim fabricationrange As Range
Dim destination As Range
Dim LastBBUFabDatabaseRow As Long
Worksheets("Sub Systems").Range("h4:r38").Copy
With ThisWorkbook.Sheets("BBU Fab. Database")
Worksheets("bbu fab. database").Range("z" & Rows.Count).End(xlUp).Offset(1).PasteSpecial Paste:=xlPasteValues
Range("b" & Rows.Count).End(xlUp).Offset(1).PasteSpecial xlPasteValuesAndNumberFormats
lastbbufabdatabserow = .Cells(.Rows.Count, 2).End(xlUp).Row = 1
Set destination = .Cells(LastBBUFabDatabaseRow, 2)
destination.Value = PasteSpecial.Values
End With
Untested but here's a brute-force approach to locating the first empty row:
set rngDest = ThisWorkbook.Sheets("BBU Fab. Database").rows(2) '<< start here
do while application.counta(rngDest) > 0
set rngDest = rngDest.offset(1, 0) 'next row
loop
Worksheets("Sub Systems").Range("H4:R38").Copy
rngDest.cells(1).PasteSpecial xlPasteValuesAndNumberFormats '<< paste to col A
Set dr = Range(Selection, Cells(Rows.Count, Selection.Column).End(xlUp)(xlToRight))
Basically, I want to select a whole range spanning across numerous rows and columns with data being populated interspersed
It works perfectly upto Xlup. But when I add Xltoright, it doesn't take effect.
enter image description here
If you are trying to go right and down of current selection then consider the following code.
As you later attempt to select in sheet 1 I am going to assume you actually meant Worksheet("Sheet1").
If that is the case you can more safely do the following:
Sub hi()
Dim dr As Range
With ThisWorkbook.Worksheets("Sheet1")
Set dr = .Range(Selection, .Cells(.Rows.Count, Selection.Column).End(xlUp).End(xlToRight))
End With
Debug.Print dr.Address
End Sub
Note:
Bear in mind that Cells /Range without a qualifying Worksheet will use the Activesheet. See the excellent discussion here:
Is the . in .Range necessary when defined by .Cells?.
Synopsis:
With "." is faster, avoids potential for error 1004 and is generally considered best practice.
I am currently trying to create a macro for Excel in which a column containing certain values (numbers basically) will be displayed in a new column in a normalized way (highest number = 1, lowest number = 0).
Usually, I would just use the formula:
=(J2-MIN($J$2:$J$XXX))/(MAX($J$2:$J$XXX)-MIN($J$2:$J$XXX))
However, as the length of the column is dynamic and will change for each set of values, I cannot enter a value for XXX.
Now, I found out how to have a dynamic range (e.g.: numRows = Range(Selection, Selection.End(xlDown)).Rows.Count) but I did not manage to merge both functions.
I found a thread already in this site about normalization of data but I think it was a bit of a different story and this one here should be simpler.
I would appreciate any help! As I just started working with macros (2h ago) I would also appreciate if this will be in simple language.
EDIT:
First of all, thanks for the quick reply!
I naively tried making it work with this code:
Sub Normalize_TEST()
'
' Normalize_TEST Makro
'
'
Range("A1").Select
numRows = Range(Selection, Selection.End(xlDown)).Rows.Count
Range("K2").Select
ActiveCell.FormulaR1C1 = "=(("J2")-MIN($J$2:$J$numRows$))/((MAX($J$2:$J$numRows$)-MIN($J$2:$J$numRows$))
Range("K2").Select
Selection.AutoFill Destination:=Range(Cells(2, 11), Cells(numRows, 11))
End Sub
But it is not working and I get an error message ("error of compiling").
I just realize now that you are absolutely right, I don't even need VBA. Your line of =(J2-MIN($J:$J))/(MAX($J:$J)-MIN($J:$J)) works fine. I wasn't aware that with $j:$J it realizes to not include empty cells.
I simply used this code now for cell K2 and then did a VBA autofill function for the rest.
I think this can be closed.
Thank you #tigeravatar for your super quick help!
I'm going to preface this by saying that I am very new to VBA and this is my first project with it however, I'm trying quite hard because otherwise it is manual copy paste ~200 times.
Unfortunately, for a first project it has been difficult.
EDITED FOR CLARITY (HOPEFULLY): The main idea is that I need to start at the beginning of a drop down list, copy the first string listed, then paste that string down the column. This changes the numerical data adjacent to the right. I then want to select this newly changed numerical data and copy and paste it to a different sheet in the same workbook in the first blank space in column F. I then want the code to iterate through the drop down list and do this for all 51 strings in the drop down. However it needs to paste offset by 3 columns for each iteration to copy the data to the correct column in the other sheet.
Here is my code thus far
Option Explicit
Sub PtComp()
'
' PtComp Macro
'
'
Dim List1 As String
Dim Range1 As Range
Dim Line1 As Range
Dim i As Integer
Dim Begin As Range
ActiveWorkbook.Sheets("Sample Data Summary").Activate
List1 = Selection
Set Range1 = Evaluate(ActiveSheet.Range(List1).Validation.Formula1)
For Each Line1 In Range1
Selection.Copy
ActiveSheet.Range(Selection, Selection.End(xlDown)).Select
ActiveSheet.Paste
ActiveCell.Offset(0, 1).Select
ActiveSheet.Range(Selection, Selection.End(xlDown)).Select
Application.CutCopyMode = False
ActiveSheet.Selection.Copy
ActiveWorkbook.Sheets("Pt Comparison").Activate
Begin = ActiveSheet.Range("F1").End(xlDown).Offset(-1, 0)
For i = 0 To 148 Step 3
Begin.Offset(0, i).Select
ActiveSheet.PasteSpecial Paste:=xlPasteValues
Next i
Next Line1
End Sub
It is highlighting this line
Set Range1 = Evaluate(ActiveSheet.Range(List1).Validation.Formula1)
Any help would be greatly appreciated. Sorry if my code is trash, like I said, first timer hoping to get better.
EDIT: Also, I looked back at older questions with the same error and thought that it was maybe because it wasn't clear what worksheet I was trying to define the range in, hence why my code is full of 'ActiveSheet' but still no luck.
Your code assumes List1 contains a valid range address, and thus that the active cell on that "Sample Data Summary" worksheet, contains a valid range address.
Apparently that isn't always the case. Search for more details on the On Error statement for ideas about how you could go about handling that situation.
You need to read up on How to avoid using Select in Excel VBA macros, and know that clipboard operations in a tight loop is pretty much the single slowest thing you can do in Excel-VBA.
Seems you want something like this:
Set Range1 = Evaluate(Selection.Validation.Formula1)
Your code blows up on Range(List1) because List1 does not contain a valid range address.
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