Excel VBA find address and assign to variable then reuse value - vba

I'm trying to find if there's a given title on a cell, pass the address of that cell to a variable and use such location to adjust the size of the column. The reason I'm doing this is because I'm writing several functions which will shift the position of the columns. I'd appreciate it if someone could take a look and tell me what I'm doing wrong.
Option Explicit
Sub adjustColumns()
Dim PONumberCell As String
Dim PONumberAddress As Range
Dim TopLabelinColumn As Range
For Each TopLabelinColumn In Range("A1:Z1").Cells
If TopLabelinColumn Like "PO_NUMBER" Then TopLabelinColumn.Value = "PO"
PONumberCell = TopLabelinColumn.Address
Set PONumberAddress = PONumberCell
PONumberAddress.ColumnWidth = 70
Next TopLabelinColumn
End Sub

edited after OP's further request:
you are confusing a Range object (such as PONumberCell is meant to be) with a String variable one (like PONumberAddress), so
Set PONumberAddress = PONumberCell
doesn't work because you are trying to assign an object variable to a String one
but you can be more effective avoiding the loop and using the Find() method
Option Explicit
Sub adjustColumns()
Dim PONumberAddress As String
Dim PONumberCell As Range
Set PONumberCell = Range("A1:Z1").Find(what:="PO_NUMBER", LookIn:=xlValues, lookat:=xlPart, MatchCase:=False)
If Not PONumberCell Is Nothing Then
With PONumberCell
.value = "PO"
PONumberAddress = .Address
.EntireColumn.ColumnWidth = 70
End With
Else
Set PONumberCell = Range("A1:Z1").Find(what:="PO", LookIn:=xlValues, lookat:=xlWhole, MatchCase:=False) '<--| if it didn't find "PO_NUMBER" then it seaches for a complete match of "PO"
If Not PONumberCell Is Nothing Then PONumberCell.EntireColumn.ColumnWidth = 70
End If
End Sub

Following the comments above, there are a few erros in your code:
Setting the PONumberAddress Range, you need to use the syntax : Set PONumberAddress = Range(PONumberCell) using the address string found in brackets.
To set the column width, use : PONumberAddress.Columns.ColumnWidth = 70.
According to your post, I think you want to do this only for columns where the header text is "PO_NUMBER", therefore you need all the code below inisde your If : If TopLabelinColumn.Value Like "PO_NUMBER" Then.
Code
Option Explicit
Sub adjustColumns()
Dim PONumberCell As String
Dim PONumberAddress As Range
Dim TopLabelinColumn As Range
For Each TopLabelinColumn In Range("A1:Z1").Cells
If TopLabelinColumn.Value Like "PO_NUMBER" Then
TopLabelinColumn.Value = "PO"
PONumberCell = TopLabelinColumn.Address
Set PONumberAddress = Range(PONumberCell)
PONumberAddress.Columns.ColumnWidth = 70
End If
Next TopLabelinColumn
End Sub

Related

formula leaving whitespace

I have the following formula designed to flag rows in a ListObject:
=IF( [#[Is Closed]]="Y", "", "Y")
I have some vba code that looks for these value via StrCmp, and was surprised to find that the Text property of the cell was " Y " (as opposed to "Y").
There are some obvious easy work arounds but can someone explain why the formula is leaving whitespace and how to force it not to?
Cheers,
UPDATE
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' FindAllInColumn
' To find a value regardless of hidden rows and autofulter settings that can make
' other methods unreliable
'
' aSearchRange : the range of data to search, which MUST be a single column
' aLookUpVal : the value
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function FindAllInColumn(aSearchRange As Range, aLookUpVal As Variant) As Excel.Range
Debug.Assert aSearchRange.Columns.Count = 1
Dim rngEach As Range
Dim rngResult As Excel.Range
For Each rngEach In aSearchRange
' Debug.Print rngEach.Address & ": Value " & rngEach.Text
' If IsValued(rngEach.Text) Then Stop
If (StrComp(rngEach.Text, aLookUpVal) = 0) Then
If rngResult Is Nothing Then
Set rngResult = rngEach
Else
Set rngResult = Application.Union(rngResult, rngEach)
End If
End If
Next rngEach
Set FindAllInColumn = rngResult
End Function
The FIX
StrComp(rngEach.Value2, aLookUpVal, vbTextCompare)
Changing .Text to .Value2 instead. Odd, but at least it works now
In general empty spaces in Excel sometimes cause a lot of problems. As the OP has found out himself, .Value2 seems like a universal problem-solver of many strange cases.
Try to select the cell and check the following code, it will print possible "hidden" empty spaces:
Option Explicit
Public Sub TestMe()
Dim rng As Range
Dim cnt As Long
Set rng = Selection
For cnt = 1 To Len(rng)
Debug.Print Asc(Mid(rng, cnt, 1))
Next cnt
End Sub

How to loop Range.Find in VBA?

I am new to VBA so please don't judge too harsh. Having said that below is my issue with Range.Find.
I have a crosstab with a column that has "https" link to pictures; and I have a working VBA to turn these links into actual pictures in each cell for that column. However, my issue is when I add another column into the Crosstab or move column around, my VBA stops working and I end up with my links without actual pictures (since, the picture code is set to the initial column where my links reside).
I figured there should be a way to make it more dynamic by using Range.Find. I have managed to find information on Range.Find, but my code won't work. Is there anyway anyone could help out?
Here is the code:
Function picRng() As Range
Set picRng = ActiveSheet.Range("A1:Z1000")
Set rngFindValue = ActiveSheet.Range("A1:Z1000").Find(what:="http", Lookat:=xlPart)
Do
Set rngFindValue = Search.FindNext(rngFindValue)
Loop While Not rngFindValue is Nothing
End Function
if you want to loop thru all the instances of the search arguments here is the correction of your code
Function picRng() As Range
Set picRng = ActiveSheet.Range("A1:Z1000")
Set rngfindvalue = picRng.Find(what:="http", Lookat:=xlPart)
If Not rngfindvalue Is Nothing Then
rngFirstAddress = rngfindvalue.Address
Do
MsgBox rngfindvalue.Address
Set rngfindvalue = picRng.FindNext(rngfindvalue)
Loop Until rngfindvalue Is Nothing Or rngfindvalue.Address = rngFirstAddress
End If
End Function
You do not need a loop for Find(). If you need the last value in Find(), you need to refer it in the arguments (searchDirection) Something like this will give the last value:
Public Function LocateFind() As Range
Dim rngCell As Range
Dim rngRangeToLookAt As Range
Set rngRangeToLookAt = Range("A1:A100")
Set LocateFind = rngRangeToLookAt.Find("YourValueHere", searchdirection:=xlPrevious)
End Function
Set lx_rangeFind = ActiveSheet.UsedRange.Find(What:=strToFind, LookIn:=xlValues, LookAt:=xlPart)
Set lx_rangeFindFirst = lx_rangeFind
Do
Set lx_rangeFind = ActiveSheet.UsedRange.Find(What:=strToFind, LookIn:=xlValues, LookAt:=xlPart, After:=lx_rangeFind)
'Rest of the code
'now lx_rangeFind has the cell Number
Loop While lx_rangeFindFirst.Address <> lx_rangeFind.Address

someExcel VBA: Cannot create a range object successfully

This is my first question here, so bear with me. I'm a security consultant working on a huge firewall migration, for which I got my VBA skill from under a thick layer of dust. So far I have managed to get all my issues resolved by searching, but this issue: I get errors when doing exactly how I find it everywhere.
What I want to do:
I have an array that contains (among other things), strings formatted like this: "A3:P59", representing a cell range.
Now, this are ranges within a table. When I get the address of a certain cell in the table, I want to test if it's in that range.
I wrote a test function:
Function TestCellRange() As Boolean
Dim tbl As ListObject
Dim cell, rng, test As range
Dim range As range
Dim bRow, eRow As Integer
Set tbl = shRulebase.ListObjects("tblBFFirewallRules")
shRulebase.Activate
With shRulebase
cell = tbl.DataBodyRange(5, 1).Address(False, False) 'it's this command that gives me issues
Set range = .range(.Cells(bRow, 1), .Cells(eRow, 16))
Debug.Print cell
'Set rng = shRulebase.range(range)
Debug.Print rng
Set test = Application.Intersect(cell, range(range(A3), range(P59)))
If test Is Nothing Then
MsgBox ("oops")
TestCellRange = False
Else
MsgBox ("yup yup")
TestCellRange = True
End If
End With
End Function
Now whatever I try, I keep getting blocked on the set range:
set range = .Range("A3:P59") -> will return "object required", on the "set test" line (if i use intersect (cell, range))
Set range = range("A3:P59") -> will return object variable or with block variale not set on the same line
Set range = .range(.Cells(bRow, 1), .Cells(eRow, 16)) -> will step through, but debug.print returns a type mismatch and "Set test = Application.Intersect(cell, range)" returns a "object required"
Any help would be really appreciated...I'm all to familiar with networks ip's and the bits and bytes of it, but here I am a bit out of my comfort zone and I need to finish this by tomorrow :(
Greetings,
Kraganov
EDIT Some More tries:
rng and cell as variant:
cell = tbl.DataBodyRange(5, 1).Address(False, False)
rng = .range("A3:P59").Address(False, False)
Set test = Application.Intersect(cell, rng)
==>I would get objects required
just using rng as range and trying to set it without "set"
rng = .range("A3:P59")
EDIT 2 : I found a way around using the range.
So what I was trying to do, was the following:
I had a table that contains information about firewall rules. However, not every line describes a rule. There are also lines that described the context in which the rules below that line were to be placed.
Outside of the table, aside of those lines there would be a cell with the range of cells for that context. I wanted to use that to describe the context for those rules, if I pulled them.
I ended up looping through the table rows and identifying those specific rows and setting a "context" variable when, a row like that was met.
Try setting the cell as well as following:
set cell = tbl.DataBodyRange(5, 1).Address(False, False)
What is cell? A Range?
You do not need to add 'set' to the range value assignment.
Try just
range = .Range("A3:P59")
Function TestCellRange() As Boolean
Dim tbl As ListObject
Dim cellToTest As Range
Dim testResult As Range
Set tbl = shRulebase.ListObjects("tblBFFirewallRules")
Set cellToTest = tbl.DataBodyRange.Cells(5, 1)
'or with one more level of indirection
'Set cellToTest = shRulebase.range(tbl.DataBodyRange.Cells(5, 1).Value)
Set testResult = Application.Intersect(cellToTest, [A3:P59])
If testResult Is Nothing Then
MsgBox ("oops")
TestCellRange = False
Else
MsgBox ("yup yup")
TestCellRange = True
End If
End Function
Thanks to the post of VincentG I found the working solution. Thanks for that.
Function TestCellRange() As Boolean
Dim tbl As ListObject
Dim cellToTest As range
Dim testResult As range
Set tbl = shRulebase.ListObjects("tblBFFirewallRules")
shRulebase.Activate
Set cellToTest = tbl.DataBodyRange.Cells(5, 1)
'or with one more level of indirection
'Set cellToTest = shRulebase.range(tbl.DataBodyRange.Cells(5, 1).Value)
Set testResult = Application.Intersect(cellToTest, range("A3:P59"))
If testResult Is Nothing Then
MsgBox ("oops")
TestCellRange = False
Else
MsgBox ("yup yup")
TestCellRange = True
End If
End Function

Using .range property on string that includes sheet name

I have a string inside a cell in a workbook that I am using to define the address of a range that a lookup should be done upon.
As an example, let's say the string is called LookupRange and has the value:
''Rate Sheet'!Y111:AA126
My problem is that in my code, when I set the range I have to use:
Set yRange = ThisWorkbook.Worksheets("Rate Sheet").Range(LookupRange)
Is there a way to use the .Range() property without using the .Worksheets() property?
For instance, maybe a way to do something like:
Set yRange = ThisWorkbook.Range(LookupRange)
If not, I guess I might have to write some code to extract the sheetname from the sheet range?
Assuming LookupRange is a String, you can extract the Sheet and Range from the string using Mid() and InStr():
Sub TestIt()
Dim LookupRange As String
LookupRange = "'Rate Sheet'!Y111:AA126"
SheetL = Mid(LookupRange, 2, InStr(2, LookupRange, "'") - 2)
RangeL = Mid(LookupRange, InStr(1, LookupRange, "!") + 1, Len(LookupRange))
Set yRange = ThisWorkbook.Sheets(SheetL).Range(RangeL)
End Sub
I don't know exactly what sort of look up you are doing, but this should work..(parse it as a string)
Sub range_set()
Dim rr As Range
Set rr = Range(CStr(Range("LookupRange")))
Debug.Print Application.WorksheetFunction.VLookup(1, rr, 2, False)
End Sub
Where the named range "LookupRange" is a single cell that contains the sheet address "Sheet2!Y111:AA126" (or whatever) to be used in a "lookup".
Set yRange = Application.Range("'Rate Sheet'!Y111:AA126")

VB syntax (named arguments)

I have a VB script with a line that looks like this:
Set startCell = referenceCell.EntireColumn.Find(tmp).offset(0,columnOffset)
But I want to specify the find (to search exactly for the given word in each column) to something like:
Set startCell = referenceCell.EntireColumn.Find(tmp, lookat:=xlWhole).offset(0,columnOffset)
all according to
http://msdn.microsoft.com/en-us/library/office/ff839746(v=office.15).aspx
But that gives me a syntax error. (I hate VB)
I have also tried
Set tmp = "Precondition" & preconditionNumber
Set startCell = ReferenceCell.EntireColumn.Find(what:=tmp,lookat:=xlWhole).offset(0,columnOffset)
and even
Set startCell = ReferenceCell.EntireColumn.Find(what:=tmp).offset(0,columnOffset)
none of which works.
How should I call the Find function to get a Whole Word-Search?
The variable declaration looks like this:
Dim startCell
for preconditionNumber = 0 to 15
Set startCell = Nothing
tmp = "Precondition" & preconditionNumber
Set startCell = referenceCell.EntireColumn.Find(tmp).offset(0,columnOffset)
...
Here is the exact syntax error message.
Use something like:
Sub luxation()
Dim ReferenceCell As Range, rCol As Range, tmp As String
Dim GotIt As Range, MoveOver As Range, columnOffset As Long
Set ReferenceCell = Range("B9")
Set rCol = ReferenceCell.EntireColumn.Cells
tmp = "happiness"
columnOffset = 2
Set GotIt = rCol.Find(what:=tmp, after:=rCol(1), lookat:=xlWhole)
Set MoveOver = GotIt.Offset(0, columnOffset)
MoveOver.Select
End Sub
Fixing VBA hatred is even easier, just repeat:
VBA is my friend.
30 times every morning