excel VBA for resizing ranges refered with listobject ranges - excel

I what to set a range into a variable to use in:
Private Sub Worksheet_Change(ByVal Target As Range)
I want to refer to a cell which is 3 cells of top of a particular column of a list object.
this way:
set rOverlap = intersect(SRTbl.ListColumns(firstConceptColumn).DataBodyRange.iTem(1).offset(-3, 0).resize(0,3),target)
where firstconceptcolumn=9 (or whatever)
This would not work.
I do it in this way because If I ever decide to add columns at the beginning of the table the code will not need to be chage.
The first row of the listobject is not row1 but row5.
The first 5 rows trigger subroutines when the values change (upon entering data an pressing return)
I also tried it using headerRowRange with:
Set rOverlap = Intersect(SRTbl.HeaderRowRange(firstConceptColumn).offsset(-3, 0).Resize(, 4), Target)
which would not work neither.
Actually as a more fundamental question I am thinking what kind of data is:
SRTbl.HeaderRowRange(firstConceptColumn)
Is that a range?
why cant you use the following:?
SRTbl.HeaderRowRange("name")
Thanks a lot
PS: Everything what I say on stackoverflow is to resize the listobject itself.
PS2: I dont understand neither if there is a difference between these two guys:
.Resize Range("A1:B10")
and
.Resize(1,10)
Jose Ferro

Here is one way:
Option Explicit
Public Sub test()
Dim SRTbl As ListObject, header As Range, ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
Set SRTbl = ws.ListObjects(1)
Set header = SRTbl.ListColumns("Name").Range(1, 1)
Debug.Print header.Offset(-3).Resize(1, 2).Address
End Sub
Here is another:
Option Explicit
Public Sub test()
Dim SRTbl As ListObject, header As Range, ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Sheet2")
Set SRTbl = ws.ListObjects(1)
Set header = SRTbl.HeaderRowRange.Find("Name")
If Not header Is Nothing Then
If header.Row > 3 Then
header.Offset(-3) = "Tada"
End If
End If
End Sub
To refer to whole header width with offset of -3 rows:
SRTbl.HeaderRowRange.Offset(-3)
To simply resize found cell:
header.Offset(-3).Resize(1,2)
To resize to end of table from found cell
Debug.Print header.Resize(1, ws.Range(Split(SRTbl.HeaderRowRange.Address, ":")(1)).Column - header.Column + 1).Address

Related

What is the proper syntax to reference a table by index number in a VBA script

I'm trying to put together a very simple VBA script to clear cell contents within a specified table column range ([Front Straddle]:[Front Option]), of all tables within a specified worksheet. This script will only live within the "VolJump" worksheet, which contains an arbitrary number of identically formatted, differently named tables. Because of this, I felt the best approach was to reference the tables by the index number.
This is where I'm running into issues with the proper referencing/nesting within the 'Range' function, shown below. Any help is greatly appreciated.
Sub ClearCells()
Dim i As Long
Dim sh As Worksheet
Set sh = ThisWorkbook.Worksheets("VolJump")
If sh.ListObjects.Count > 0 Then
For i = 1 To sh.ListObjects.Count
Range("Activesheet.ListObjects(1)[[Front Straddle]:[Front Option]]").Select
Selection.ClearContents
Next i
End If
End Sub
Clear Contents of Table Columns Range
Option Explicit
Sub ClearCells()
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("VolJump")
Dim tbl As ListObject
For Each tbl In ws.ListObjects
ws.Range(tbl.Name & "[[Front Straddle]:[Front Option]]").ClearContents
Next tbl
End Sub
Just using the ListObjects:
Sub ClearColumns()
Dim lo As ListObject
Dim ColNum1 As Long, ColNum2 As Long
For Each lo In ThisWorkbook.Worksheets("Sheet1").ListObjects
'Get the index numbers of the start and end columns.
ColNum1 = lo.ListColumns("Front Straddle").Index
ColNum2 = lo.ListColumns("Front Option").Index
'Resize the range from the start column to the end column and clear it.
lo.DataBodyRange.Columns(ColNum1).Resize(, ColNum2 - ColNum1 + 1).ClearContents
Next lo
End Sub

How to refer to a selected block of cells in vba excel

How to refer in the code to the selected range of cells in the active sheet.
To clarify, I am not asking how to select a range of cell.
Is there any ActiveRange ActiveRegion or something?
I haven't found it...
For example, (not working) here is a simple sub:
Sub test()
Dim region, cel As Range
region = ActiveCell.CurrentRegion
For Each cel In region
cel = 1
Next cel
End Sub
A couple of remarks:
Define all the variables types and Selection is already a Range if a Range is selected. Beware that it may return other objects, so you should check the type of object returned before working with it
Read this
Public Sub LoopActiveRange()
Dim sourceCell As Range
For Each sourceCell In Selection
sourceCell = 1
Next sourceCell
End Sub
To work with Selected cells use Selection property (Excel) MSDN
Example
Option Explicit
Public Sub Example()
Dim rng As Range
For Each rng In Selection
DoEvents
rng.Value = "value" ' adds a to all selected cells
Next
End Sub
Remarks The returned object type depends on the current selection (for example, if a cell is selected, this property returns a Range object). The Selection property returns Nothing if nothing is selected.

Copy non-contiguous cells and paste in a row retaining number format Excel VBA

I hope someone can help me with this as it's driving me up the wall!
There are 5 non-contiguous cells in a worksheet that I want to copy to the next empty row on another worksheet whilst retaining the number formatting (which varies). I have this so far but am struggling working out how to retain formatting. Can anyone please help? Thanks I anticipation.
`With wsCalc
For bRun = 1 To 4
bData(bRun) = Application.Choose(bRun, .Range("g2"), .Range("b2"), .Range("R2"), .Range("Q14"))
Next bRun
End With
wSResults.Cells(Rows.Count, "a").End(xlUp).Offset(1).Resize(, 4).Value = bData
`
Here's a possible solution, using your hard-coded cell addresses. You will have to set wsCalc and wsResults to their proper worksheets. Slightly more elegant would be to define a "non-contiguous" range on your wsCalc sheet (select the 1st cell, keep Ctrl pressed and select the next one etc, then type a name in the drop-down box just to the left of the formula bar).
Option Explicit
Sub CopyWithFormat()
Dim wsCalc As Worksheet
Set wsCalc = ActiveSheet 'Or whatever your calc sheet is
Dim rngSource As Range
Set rngSource = wsCalc.[G2,B2,R2,Q14]
Dim wsResults As Worksheet
Set wsResults = ActiveSheet 'Or whatever your result sheet is
Dim clDest As Range
Set clDest = wsResults.Cells(Rows.Count, "a").End(xlUp).Offset(1)
Dim cl As Range
For Each cl In rngSource.Cells
clDest.Value = cl.Value
clDest.NumberFormat = cl.NumberFormat
Set clDest = clDest.Offset(1)
Next cl
End Sub
Instead of using .Value, try .Text. It retains formatting. See below.
Gary's Student is right, text is read only, it should be used for the input not the output.
bData(bRun) = Application.Choose(bRun, .Range("g2").Text, .Range("b2").Text, .Range("R2").Text, .Range("Q14").Text)
I also agree with other answer the entire code could be set up more straight forward.

Named range giving Error 1004 'Method 'Range' Of Object 'Worksheet' Failed'

This code was working just fine, but I did a bunch of other code that manipulates and reads the same area of the sheet and now this section does not work.
I have tried a bunch of stuff with syntax but none worked. It may be that I need to resize my array but since im setting it equal to a range I didnt think that I had to. Also It says the problem is the range but I dont know. I would rather not have to resize as its taking from a larger table whose line items will be dynamic but I can do that and make it dynamic if I need to. I did try deleting the range and renaming it and it did not work.
Private Sub UserForm_Initialize()
Dim codes()
Dim ws As Worksheet
Set ws = Worksheets("Sheet1")
codes = ws.Range("cCodes")
CostCode1.List = codes ''these are combo boxes
CostCode2.List = codes
CostCode3.List = codes
CostCode4.List = codes
CostCode5.List = codes
CostCode6.List = codes
'' ADD UNITS
End Sub
you don't need to declare the sheet for the named range.
named ranges are stored as an external address including the sheet's Name.
codes = Range("cCodes")
should be sufficient.
As far as I can tell the error comes because you don't have the named range "cCodes").
Go to Formulas -> Name Manager and check your names. Alternatively, use a range directly in the code, i.e.: codes = ws.Range("A1:A100")
To answer your question in the comment:
Is there a way for me to directly reference the three columns of the table that I want to set to the array
Here are a few ways to manipulate the range from your table into the array (specific rows/columns), and back on the sheet (see comments in code). Hope this helps.
Option Explicit
Sub test()
Dim rngData As Range
Dim arrData As Variant
With Range("Table1") 'this is only the content of the table, does not include the headers
Set rngData = Range(.Cells(1, 1), .Cells(.Rows.Count, 3)) 'Set the range starting at cell row 1, col 1 - until total number of rows in table, col 3
'Set rngData = rngData.Offset(-1).Resize(.Rows.Count + 1) 'if you want to include headers as well
Debug.Print rngData.Address
End With
arrData = rngData 'allocate the data from the range to the array
rngData.Offset(0, Range("Table1").Columns.Count + 1) = arrData 'put the array back on the sheet, 1 column to the right of the table
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Range("N1").Resize(UBound(arrData), UBound(arrData, 2)) = arrData 'put the array back on the sheet in a specific range
End Sub

How to set a ListObject equal to another ListObject?

I would like to set a ListObject to be an exact copy of another ListObject just like how you can set a range to be an exact copy of another range. Is this possible?
I've tried the following but it did not work:
Set destinationWorksheet.ListObjects("tblPriorTable") = sourceWorksheet.ListObjects("Table1")
It is important that the "tblPriorTable" ListObject not be deleted, because I have formulas in my workbook which reference that ListObject and those formulas break when the ListObject gets deleted. I just want to essentially overwrite the contents of "tblPriorTable" to be equal to another ListObject without ever deleting "tblPriorTable".
You can use a procedure like this:
Sub Copy_Contents(FromTable As ListObject, ToTable As ListObject)
With ToTable
If Not .DataBodyRange Is Nothing Then
.DataBodyRange.ClearContents
End If
.Range(2, 1).Resize(FromTable.ListRows.Count, FromTable.ListColumns.Count).Value = FromTable.DataBodyRange.Value
End With
End Sub
Note that it assumes your two listobjects have the same number of columns.
The ListObject does not have a .Copy method, but a Range does:
Sub lksdhfs()
Dim r As Range
Set r = ActiveSheet.ListObjects(1).Range
r.Copy Range("g30")
End Sub
NOTE:
The copy produces another ListObject, not just a pile of cells.Make sure the two tables do not overlap.

Resources