Store named ranges values as variable - excel

I am trying to store a named range like that
Dim sValue As String
sValue = ThisWorkbook.Names("MyRange").Value
I got the range address instead of the values in the named range. What I am trying to do exactly is the following
Suppose the named range is "MyRange" and it is for A1:C4
In a cell, if we typed equal sign and typed "MyRange" and then pressed F9, we got the values as array like that
{"Head1","Head2","Head3";1,2,3;4,5,6;7,8,9}
How to store that in variable string?

to have a String variable formatted as {"Head1","Head2","Head3";1,2,3;4,5,6;7,8,9}, you can do as follows
Dim sValue As String, r As Range
For Each r In ThisWorkbook.Names("MyRange").RefersToRange.Rows
sValue = sValue & Join(Application.Transpose(Application.Transpose(r.Value)), ",") & ";"
Next
sValue = "{" & Left(sValue, Len(sValue) - 1) & "}"
while to store a named range in an array is much simpler (and I'd say, easy to use):
Dim sValue As Variant
sValue = ThisWorkbook.Names("MyRange").RefersToRange.Value

I think you are looking for
sValue = ThisWorkbook.Names("MyRange"),name
to find all names on Activesheet:
Sub test_names()
Dim wsName As String
wsName = ActiveSheet.Name
Dim nameRange As Variant
For Each nameRange In ThisWorkbook.Names
Set rngName = Range(nameRange)
wsParentName = rngName.Parent.CodeName
If (wsParentName = wsName) Then
Debug.Print "Found range " & nameRange.Name
End If
Next nameRange
End Sub

Related

Find a string and get the numerical value to the right of it

I am trying to create a VBA code that when runs, find a certain string in column x but then gets the value to the right of the string in column y. If anyone could help that would be great thanks
You will need to adapt this but I see two ways of doing. Without knowing the answer, you could just use formulas.
Formula
Use a VLOOKUP ... Cell D2 = =VLOOKUP(D1,$A$1:$B$20,2,FALSE)
VBA
You need to change the column you want to search and the amount of columns you want to offset by to get the value.
You also need to adapt it to your solution. I've merely given you the approach and a couple of samples.
Using MATCH ...
Public Sub FindStringAndOffset()
Dim strToSearchFor As String, lngRow As Long, objSheet As Worksheet
Dim varValue As Variant, strColToSearchIn As String, lngOffset As Long
strToSearchFor = "Lookup 8"
strColToSearchIn = "A"
lngOffset = 1
Set objSheet = Sheet1
With objSheet
On Error GoTo ExitGracefully:
lngRow = WorksheetFunction.Match(strToSearchFor, .Range(strColToSearchIn & ":" & strColToSearchIn), 0)
varValue = .Range(strColToSearchIn & lngRow).Offset(0, lngOffset).Value
Debug.Print varValue
End With
ExitGracefully:
End Sub
... or using a VLOOKUP ...
Public Sub FindStringAndOffsetv2()
Dim strToSearchFor As String, objSheet As Worksheet
Dim varValue As Variant, strColToSearchIn As String, lngOffset As Long
Dim strColumnWithOffset As String
strToSearchFor = "Lookup 8"
strColToSearchIn = "A"
lngOffset = 1
Set objSheet = Sheet1
With objSheet
On Error GoTo ExitGracefully:
strColumnWithOffset = Split(.Range(strColToSearchIn & "1").Offset(0, lngOffset).Address, "$")(1)
varValue = WorksheetFunction.VLookup(strToSearchFor, .Range(strColToSearchIn & ":" & strColumnWithOffset), lngOffset + 1)
Debug.Print varValue
End With
ExitGracefully:
End Sub
There are a heap of ways to skin that cat.

Object required error when setting range from two cells

I am trying to convert a text file to Excel sheet. I have to remove some data elements and copy some data elements to several columns. To remove some data, I have to look for a certain String (RUN). After I have that address, I have to search for the next RUN. Inside those two String range, I have to search for another String (NET) and remove it. I have to do it throughout the datasheet since this is frequent.
Here is the code I am trying to use.
Dim name As String: name = "RUN"
Dim secondName As String: secondName = "NET"
Dim rgSearch As Range
' set the range to entire sheet
Set rgSearch = Range(Cells.Address)
Dim rgSearch1 As Range
Dim cell As Range
'search for first occurrence of RUN
Set cell = rgSearch.Find(name)
Dim tempCell As Range
' If not found then exit
If cell Is Nothing Then
Debug.Print "Not found"
Exit Sub
End If
' Store first cell address
Dim firstCellAddress As String, firstRow As Integer, secondRow As Integer
'store address of first result
firstCellAddress = cell.Address
secondRow = cell.Row
Do
'save range to another range for next iteration
Set tempCell = cell.Select
'row variables are for alternate solution I tried
firstRow = secondRow
Debug.Print "Found: " & cell.Address
' search for next instance
Set cell = rgSearch.FindNext(cell)
,set next instance
secondRow = cell.Row
Set rgSearch1 = Range(tempCell, cell).Select
Loop While firstCellAddress <> cell.Address
I have also tried using
Set rgSearch1 = Range("B" & firstRow + 1 & ":B" & secondRow - 1).Select
instead of putting cells inside the range but I get the same result. That is why those firstRow, secondRow variables are there.
With both ideas, I am getting Object Required error. Could someone please show me what I am doing wrong?

How to select columns through VBA when the columns selectin reference is: A,E,D,S

I'm requesting a parameter from the user to specify columns (in Excel) to select, but am having some issues with converting the value to a string that I can use in VBA for reference.
I'm trying to avoid having the user enter A:A,E:E,D:D,S:S and instead just enter A,E,D,S in a cell. I'm sure the answer is right there but at the moment it's escaping me. Any suggestions?
Like I said,
Split on the , and iterate through the resultant array and build the range:
Sub fooooo()
Dim str As String
Dim rng As Range
Dim strArr() As String
str = "A,E,D,S" 'you can change this to the cell reference you want.
strArr = Split(str, ",")
With Worksheets("Sheet1") ' change to your sheet
Set rng = .Range(strArr(0) & ":" & strArr(0))
For i = 1 To UBound(strArr)
Set rng = Union(rng, .Range(strArr(i) & ":" & strArr(i)))
Next i
End With
Debug.Print rng.Address
End Sub
You can always turn this into a Function that returns a range:
Function fooooo(str As String, ws As Worksheet) As Range
Dim rng As Range
Dim strArr() As String
strArr = Split(str, ",")
With ws ' change to your sheet
Set rng = .Range(strArr(0) & ":" & strArr(0))
For i = 1 To UBound(strArr)
Set rng = Union(rng, .Range(strArr(i) & ":" & strArr(i)))
Next i
End With
Set fooooo = rng
End Function
Then you would call it like this from any sub you need:
Sub foofind()
Dim rng As Range
Dim str As String
str = "A,E,D,S"
Set rng = fooooo(str, Worksheets("Sheet1"))
Debug.Print rng.Address

Excel VBA Range for all relevant cells

My macro creates a large text file by writing all the data from all sheets in the active workbook.
In each worksheet, it is necessary to determine a certain rectangular range of cells that would be saved in the text file. It's upper left corner would always be A1, but the lower right corner should be chosen so that the range includes all cells with any content (formatting does not matter).
I thought ws.Range("A1").CurrentRegion would do the trick, but it does not work when A1 and the nearby cells are empty. If the only cell with data in the sheet is Q10, then the range should be A1:Q10.
Of course, I could loop over the ws.Cells range to discover the range of interest, but that's quite time consuming, I hope there's more effective way. If I select all cells in a sheet and do a copy-paste to notepad, I do not end up with hundreds of empty columns and thousands of empty rows, only the relevant data are copied. The question is how to replicate that with VBA.
This is my code so far:
Sub CreateTxt()
'This macro copies the contents from all sheets in one text file
'Each sheet contents are prefixed by the sheet name in square brackets
Dim pth As String
Dim fs As Object
Dim rng As Range
pth = ThisWorkbook.Path
Set fs = CreateObject("Scripting.FileSystemObject")
Dim outputFile As Object
Set outputFile = fs.CreateTextFile(pth & "\Output.txt", True)
Dim WS_Count As Integer
Dim ws As Worksheet
Dim I As Integer
WS_Count = ActiveWorkbook.Worksheets.Count
For I = 1 To WS_Count
Set ws = ActiveWorkbook.Worksheets(I)
outputFile.WriteLine ("[" & ws.Name & "]")
Debug.Print ws.Name
Set rng = ws.Range("A1").CurrentRegion
outputFile.WriteLine (GetTextFromRangeText(rng, vbTab, vbCrLf))
Next I
outputFile.Close
End Sub
Function GetTextFromRangeText(ByVal poRange As Range, colSeparator As String, rowSeparator As String) As String
Dim vRange As Variant
Dim sRow As String
Dim sRet As String
Dim I As Integer
Dim j As Integer
If Not poRange Is Nothing Then
vRange = poRange
Debug.Print TypeName(vRange)
For I = LBound(vRange) To UBound(vRange)
sRow = ""
For j = LBound(vRange, 2) To UBound(vRange, 2)
If j > LBound(vRange, 2) Then
sRow = sRow & colSeparator
End If
sRow = sRow & vRange(I, j)
Next j
If sRet <> "" Then
sRet = sRet & rowSeparator
End If
sRet = sRet & sRow
Next I
End If
GetTextFromRangeText = sRet
End Function
if there is anything in A1:B2 cells, this macro works. It breaks when the A1:B2 is empty and the CurrentRegion property returns Empty.
I think you should use these functions to find the last Row/Column
lastRow = Sheets("Sheetname").Cells(Rows.Count, 1).End(xlUp).Row
lastCol = Sheets("Sheetname").Cells(1, Columns.Count).End(xlToLeft).Column
You specify the name of the sheet and the row/columb-number that you want to find the last cell with information, and it return the number of it.
(In the example the last row in first column, and last column in first row are find)
lastCol will give you an Long as an asnwer. If you want to convert this number into the column letter you can use the next function
Function Col_Letter(lngCol As Long) As String
Dim vArr
vArr = Split(Cells(1, lngCol).Address(True, False), "$")
Col_Letter = vArr(0)
End Function
I hope you find this useful
Thanks to user Rosetta, I've come up with this expression for the sought range:
ws.Range("A1:" & ws.Cells.SpecialCells(xlLastCell).Address)

How to get the address of a range with multiple subranges, including the sheet name in EACH subrange?

With the union statement I created a range existing of multiple subranges, of Worksheet("data"). I need that range for calculations on another worksheet, Worksheet("weekly"). Therefore I want the address of the range including the sheet name in each subrange. rRng is my range existing of several subranges.
rRng.Address(External:=True) returns: "data!$D$1570:$D$1575,$D$2992:$D$3000,$D$5979:$D$5988"
However, to calculate the average of the cells in this range I need: "data!$D$1570:$D$1575,data!$D$2992:$D$3000,data!$D$5979:$D$5988"
The only solution I found so far is:
Dim range_string As String
range_string = ""
Dim SubRange As range
For Each SubRange In rRng
range_string = range_string & SubRange.Address(External:=True) & ","
Next SubRange
range_string = Left(range_string, (Len(range_string) - 1))
Worksheets("weekly").range("$C2").Formula = "=AVERAGE(" & range_string & ")"
There must be a more easy way. Any suggestions?
Kind regards,
Sandra
Each of those subranges is called an Area. You can loop through the Areas of a range and build the string. Here's an example.
Sub test()
Dim rng As Range
Dim rArea As Range
Dim sForm As String
'union the ranges
Set rng = Sheet1.Range("D1570:d1575")
Set rng = Union(rng, Sheet1.Range("D2992:d3000"))
'loop through the areas and build the string
For Each rArea In rng.Areas
sForm = sForm & rArea.Address(, , , True) & ","
Next rArea
'remove the last comma
sForm = Left$(sForm, Len(sForm) - 1)
'insert the formula
Sheet2.Range("A1").Formula = "=AVERAGE(" & sForm & ")"
Debug.Print Sheet2.Range("A1").Formula
End Sub
The debug.print produces:
=AVERAGE(data!$D$1570:$D$1575,data!$D$2992:$D$3000)

Resources