Create Range excluding column in middle - vba

I have the problem of needing to exclude a column in the middle of my excel worksheet. Is there a way of creating a range that excludes a column not on the edges of the data. The range is dynamic ranging from A1:AA#. The column "F" needs to be excluded from this range. This range needs to be stored for use in a pivotTable.
Range("A1:E4,G1:J4").Select
This is how the excel macro recorder creates a range with a gap, but I cannot find a way to modify this so the last cell is dynamic.
Thanks.

Just as you should avoid using the .Select Method, you should also avoid using the .UsedRange when possible (See here).
You can try something like this. It is not as clean, but may prove to be less bug prone.
Dim LRow As Long
LRow = Range("A" & Rows.Count).End(xlUp).Row
Dim MyRange1 As Range, MyRange2 As Range, BigRange As Range
Set MyRange1 = Range("A1:E" & LRow)
Set MyRange2 = Range("G1:J" & LRow)
Set BigRange = Application.Union(MyRange1, MyRange2)
BigRange.Select
You can then refer to your BigRange directly moving forward.

If you have only one set of data in your sheet, you could try something like that :
Intersect(ActiveSheet.UsedRange, Range("A:E,G:AA")).Select
This will select everything that contains data up to column AA on the sheet except for column F.
Whenever possible , you should avoid using .select .activate but you only provide one line of your code so I can't help you much on that part except redirect you to this.

you could use
Dim rng As Range
Set rng = Intersect(Range("A:E,G:AA"), Rows(1).Resize(Cells(Rows.Count, 1).End(xlUp).Row))
where the column index in Cells(Rows.Count, 1) lets you choose what column size your range after

Related

Selecting range without knowing number of rows or columns having data in Excel/VBA

I am looking for code for two different types of selection. One code would select in an L shape all of the rows in one column and all of the columns in one row. In the example of having data in the range A1:A10, and data in row 10 only from col A - K. The selection would look like an L. How can you do this without knowing how many rows or columns have data in them?
The second code would have the same data, but need to select the whole range A1:K10 in that example, but the code would need to select whatever range had the data.
i found the answer. i have to do a union. here is the code with the union at the end.
Sub mywork()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim rng As Range
'~~> Set this to the relevant worksheet
Set ws = [Sheet1]
With ws
'~~> Get the last row and last column
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
lCol = .Cells(lRow, .Columns.Count).End(xlToLeft).Column
'~~> Set the range
Set rng = .Range(.Cells(lRow, 1), .Cells(lRow, lCol))
End With
Set rng = Application.Union(Range("A1:A" & lRow), rng)
rng.Select
End Sub
activesheet.usedrange.address should tell you the used range.
In your case something like this should work: [sheet1].usedrange.select (Replaces all the code in the module)
The benefit here is the fact that you are not hard coding "A1:A" against the last identified cell, works well if you have blank rows at the top.

Filter a column and select the last used row

I want to filter a particular column in Excel sheet and then select the range of it until the last used row.
For getting a particular column I am using
ActiveSheet.Range("$A$1:$D30").AutoFilter Field:=3 , Criteria1:= "1"
And for finding the last row I am using
Cells(ActiveSheet.Rows.Count,1).End(xlUp).Row
I am not able to combine both together. If I run both the commands together, I am getting the entire results instead of filtered results.
I know it may be a simple one, But I am not able to do it. Can anybody help me in doing it?
My requirement is that the first the column should be filtered and then the range of until the last unused row should be selected. So that I can do some commands using the selection.
Try this:
With Range("A1:D" & Range("a1048576").End(xlUp).Row)
.AutoFilter Field:=3, Criteria1:="1"
.Resize(, 1).Offset(1).SpecialCells(xlCellTypeVisible).Select
End With
Use the SpecialCells Method with the xlCellTypeVisible argument. I also qualified the worksheet to work with, since it's way more stable than using ActiveSheet (should always be avoided, unless absolutely necessary.)
Dim ws as Worksheet
Set ws = Sheets("mySheet") 'change to the sheet name you need
Dim lRow as Long
lRow = ws.Cells(ws.Rows.Count,1).End(xlUp).Row
ws.Range("$A$1:$D" & lRow).AutoFilter Field:=3 , Criteria1:= "1"
Dim rRng as Range, cel as Range
Set rRng = ws.Range("A2:A" & lRow).SpecialCells(xlCellTypeVisible) 'assumes header row in column 1
'Updated code based on your comments.
For each cel in rRng
objRecipients.Add cel
Next
ws.AutoFilterMode = False

IF THEN VBA MACRO - Update one column if contents of another = 100%

I have a workbook with "Results" being sheet 3, this being the worksheet I want to use.
I have tried a few formulaes to try and add a macro to do the following:
I have column G with percentages. I then have column I where I would like there to be a result saying TRUE/FALSE where the contents of G are equal to 100%. Column G is formatted to percentage with two decimals.
Some considerations: I have my first row being a Hyperlink to another sheet, then my headings, then the first row of "results". I have 457 rows, if there is a measurement of the range, perhaps it could be on A?
I keep getting this error 9 with my range and have got a bit stuck.
Thanks in advance!
Sub PartialHits1()
Dim rng As Range
Dim lastRow As Long
Dim cell As Range
With Sheet3
lastRow = .Range("G" & .Rows.Count).End(xlUp).Row
Set rng = .Range("G1:G" & lastRow)
For Each cell In rng
If cell.Value = 100
Then
cell.Range("I1:I1").Value = 100
End If
Next
End With
End Sub
(I have hacked this a bit, just was trying to get it to set as 100 instead of the TRUE/FALSE Also was playing around near the Sheet 3 part as I got errors.)
RangeVariable.Range can refer only to a cell within RangeVariable, so you can't refer to column I in this way. Try: .Range("I"&cell.row)=100.
Also your criteria is probably wrong, if you have 100% in a cell it's actual value is 1.
And last question: why do you want to do this with VBA, it would be much more simple with worksheet function =IF(G3=1,100,"")

How to loop a dynamic range and copy select information within that range to another sheet

I have already created a VBA script that is about 160 lines long, which produces the report that you see below.
Without using cell references (because the date ranges will change each time I run this) I now need to take the users ID, name, total hours, total break, overtime 1, and overtime 2 and copy this data into sheet 2.
Any suggestions as to how I can structure a VBA script to search row B until a blank is found, when a blank is found, copy the values from column J, K, L, M on that row, and on the row above copy value C - now paste these values on sheet 2. - Continue this process until you find two consecutive blanks or the end of the data...
Even if you can suggest a different way to tackle this problem than the logic I have assumed above it would be greatly appreciated. I can share the whole code if you are interested and show you the data I began with.
Thank you in advance,
J
As discussed, here's my approach. All the details are in the code's comments so make sure you read them.
Sub GetUserNameTotals()
Dim ShTarget As Worksheet: Set ShTarget = ThisWorkbook.Sheets("Sheet1")
Dim ShPaste As Worksheet: Set ShPaste = ThisWorkbook.Sheets("Sheet2")
Dim RngTarget As Range: Set RngTarget = ShTarget.UsedRange
Dim RngTargetVisible As Range, CellRef As Range, ColRef As Range, RngNames As Range
Dim ColIDIndex As Long: ColIDIndex = Application.Match("ID", RngTarget.Rows(1), 0)
Dim LRow As Long: LRow = RngTarget.SpecialCells(xlCellTypeLastCell).Row
'Turn off AutoFilter to avoid errors.
ShTarget.AutoFilterMode = False
'Logic: Apply filter on the UserName column, selecting blanks. We then get two essential ranges.
'RngTargetVisible is the visible range of stats. ColRef is the visible first column of stats.
With RngTarget
.AutoFilter Field:=ColIDIndex, Criteria1:="=", Operator:=xlFilterValues, VisibleDropDown:=True
Set RngTargetVisible = .Range("J2:M" & LRow).SpecialCells(xlCellTypeVisible)
Set ColRef = .Range("J2:J" & LRow).SpecialCells(xlCellTypeVisible)
End With
'Logic: For each cell in the first column of stats, let's get its offset one cell above
'and 7 cells to the left. This method is not necessary. Simply assigning ColRef to Column C's
'visible cells and changing below to CellRef.Offset(-1,0) is alright. I chose this way so it's
'easier to visualize the approach. RngNames is a consolidation of the cells with ranges, which we'll
'copy first before the stats.
For Each CellRef In ColRef
If RngNames Is Nothing Then
Set RngNames = CellRef.Offset(-1, -7)
Else
Set RngNames = Union(RngNames, CellRef.Offset(-1, -7))
End If
Next CellRef
'Copy the names first, then RngTargetVisible, which are the total stats. Copying headers is up
'to you. Of course, modify as necessary.
RngNames.Copy ShPaste.Range("A1")
RngTargetVisible.Copy ShPaste.Range("B1")
End Sub
Screenshots:
Set-up:
Result:
Demo video here:
Using Filters and Visible Cells
Let us know if this helps.

Range address, where do I find the sheet?

I work on a UDF and the user inputs a range, say "sheet1!A1:C8".
In the VBA I write the following:
Function RelativeSearch(Search, rng As Range, Row, Column)
MsgBox rng.Address
Here the msgbox only gives me A1:C8. How can I get the "Sheet1"?
I have tried to make rng as string but that does not work as I have to use rng.find later in the code.
Anyone know of a way to get the sheet from the range?
The Range object has a Worksheet property, so:
rng.Worksheet.Name will do what you want.
In addition the Address property has an External argument, so:
rng.Address(External:=True) yields the entire range address, e.g., [Book1]Sheet1!$D$28.
To get a reference to the Sheet, use rng.Parent.
In your specific case, you are looking for rng.Parent.Name.
So you could do
MsgBox rng.Parent.Name & "!" & rng.Address
This is not an answer to the question you asked, but I suspect it might help you avoid having to ask the question.
If you are trying to find, within rng, the value passed as Search, and then return a value derived by some offset by Row and Column, there is no need to know what worksheet rng is on:
Excel formula (perhaps in cell Sheet4!D6):
=RelativeSearch("b",Sheet1!A1:A6,3,2)
Code which will search the range A1:A6 in Sheet1 for the value "b" and then return the value from the cell that is 3 rows below and 2 columns to the right:
Function RelativeSearch(Search, rng As Range, Row, Column)
Dim r As Range
Set r = rng.Find(What:=Search, LookIn:=xlValues, LookAt:=xlWhole)
If r Is Nothing Then
RelativeSearch = CVErr(xlErrNA)
Else
RelativeSearch = r.Offset(Row, Column).Value
End If
End Function
(If you want it to be consistent with VLOOKUP's syntax, you will need to use r.Offset(Row - 1, Column - 1) rather than r.Offset(Row, Column).)