Automatic Hyperlinks within Excel sheet? - excel

I want excel to automatically create hyperlinks to another cell. I have one column with different strings and when i type the name of one of the existings strings in another column i want a hyperlink to the cell in the first column automatically. Is this possible and how would you then do it?

if you're using VSTO:
Declare SortedList Object in ThisAddin to keep Keywords and Range Address
Dim keywordList As New SortedList(Of String, String)
In Application.SheetChange can you catch the string you typed.
You can use Target.Value and Target.Address.
Look up for Target.Value in the SortedList. If nothing found add new entry to the list with value and range address.
if entry is already declared get the address from the list and create Hyperlink for Target
Public Sub Application_SheetChange(ByVal Sh As Object, ByVal Target As Microsoft.Office.Interop.Excel.Range) Handles Application.SheetChange
Dim value As String = CStr(Target.Value)
If liste.ContainsKey(value) Then
Dim address As String = String.Empty
keywordList.TryGetValue(value, address)
If Not String.IsNullOrEmpty(address) Then
Target.Parent.Hyperlinks.Add(Target, address)
End If
Else
keywordList.Add(CStr(Target.Value), CStr(Target.Address))
End If
End Sub

Not exactly what you asked for but it could make the job:
Assuming you have a file named "test.xlsx"
In column "A" write your strings
In column "C" write string you want to make hypertext link
In column "D" write =MATCH(C2;A:A;0)
In column "E" write =HYPERLINK("[test.xlsx]A"&D2;"GO TO "&C2)
Points 4 and 5 could by merged into one formula.
The difference between your description and my solution is that I construct hyperlink in adjacent cell (not the cell you write search string into)

Related

Clean up Named Range Addresses with Errors (e.g. #REF!)

I set up a named range, let's call him RngIn.
He has 3 cells, and his address refers to A1:A3
Next, I delete Row 2.
My RngIn now shows #REF! error (correctly) in its RefersTo property:
"=A1,Sheet1!#REF!,A2"
This means I cannot manipulate the rest of that named range using VBA, because of the Method 'Range' of Global Object error.
The range is created during a process, and if a user subsequently needs to delete one row for whatever reason, my future code will fail because it needs to know where the rest of the named range data is...
I have tried many ways to access the remaining address information for this range, in VBA, but failed so far, e.g.
Dim RngAddress As String
Dim RngIn As Range
Set RngIn = Range("A1:A3")
RngAddress = RngIn.Address
RngAddress = RngIn.RefersToRange.Address
RngAddress = RngIn.RefersTo
RngAddress = Replace(RngIn.Address, "Sheet1!#REF!", "")
What I ideally want to see in a text string as the result for RngIn is:
"=A1,A2"
Because A2 is now the location of the data which was originally in A3.
Not sure I understand this well: your example code does not use Defined Names (aka Named Ranges).
lets suppose you create a Name called RangeIn that refers to A1,A3,A5 and you then delete Row 3.
The RefersTo for RangeIn is now =Sheet1!$A$1,Sheet1!#REF!,Sheet1!$A$4
This code removes the Sheet1!#REF!, to leave the Name RangeIn referring to =Sheet1!$A$1,Sheet1!$A$4
Option Explicit
Option Compare Text
Sub ChangeRef()
Dim strAd As String
strAd = ThisWorkbook.Names("RangeIn").RefersTo
strAd = Replace(strAd, "Sheet1!#REF!,", "")
ThisWorkbook.Names("RangeIn").RefersTo = strAd
End Sub
In cases like this, I set the start and end points of my named ranges to be the cell above and the cell below the range where the user can delete, and then use the OFFSET or INDEX function to resize that range to exclude my bookmarks. Or I use Excel Tables, which can handle row deletions without returning #REF errors.

Target in a change event code doesn't give me what I want

In a Worksheet_Change event routine, the target value is not of a specific cell but that of the range address of the pivot table that cell belongs to.
The code below is intended to detect if a certain named cell was created. If it wasn't then no action is needed. But if it was, then the value of that named cell will point to one less than the column of the cell that I want to detect changed, prompting a certain action.
I expect the change to occur in the value of a Report Filter field of a pivot table, which I fully expect to be in row 4, but at a column that is 1 more than the value of the dynamically-created named cell "cLeft" I checked the existence of.
I detect the change via a change event. However, instead of giving the address of the one cell that changed, I get the range address of the full pivot table. How can I get only the address of the cell that changed?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Pos As String
Dim rNW As Long
Dim cNW As Long
Dim rSE As Long
Dim cSE As Long
On Error Resume Next
Pos = Range("cLeft").Address
If Err <> 0 Then
On Error GoTo 0
Else
Call GetCorners(Target, rNW, cNW, rSE, cSE)
If rNW = 4 And cNW = Range("cLeft") + 1 Then
.
.
<some action>
.
.
End If
End If
End Sub
Sub GetCorners(Rng As Range, rNW As Long, cNW As Long, rSE As Long, cSE As Long)
' Decode the upper left and lower right of the range into appropriate row and column values.
Dim ArR() As String
Dim ANW() As String
Dim ASE() As String
Dim RngStr As String
RngStr = Rng.Address(ReferenceStyle:=xlR1C1)
' See if the range is a single cell. If it is, replicate it at the end.
If InStr(RngStr, ":") = 0 Then RngStr = RngStr & ":" & RngStr
ArR = Split(RngStr, ":")
ANW = Split(ArR(0), "R")
ANW = Split(ANW(1), "C")
ASE = Split(ArR(1), "R")
ASE = Split(ASE(1), "C")
rNW = Val(ANW(0))
cNW = Val(ANW(1))
rSE = Val(ASE(0))
cSE = Val(ASE(1))
End Sub
I have a pivot table whose "Northwest" corner is always in row 4. Its column number can vary. In my example it is column 101. At the moment of creation of the pivot table I also create a named cell called "cLeft". In it I then record the number of the leftmost column of the pivot table, 101.
The pivot table has only one report filter for a field called "Status". The position of the filter is always in row 4 and column number equal to 1 + the value of cLeft. In the example, it is row 4, column 102.
I want to perform some additional action when the value of the filter changes. For that, I use the above code, but it doesn't work all that well because the value of "target" is not the address of the one cell that changes, R4C102, but the address of the whole pivot table, R4C101:R29C117, which also changes, depending on the selection.
How can I coax the address R4C102 out of the routine? I don't want to use Worksheet_SelectionChange because, although that gives me the answer I want, it requires me to select the cell holding the filter first, and then change the filter, a 2-step sequence I can't expect the end users to remember to do.

Searching a Range in Excel VBA

I have a string array, and in each slot of the array is a 'range of columns' in a string format e.g "B:J" "k:W" "AC:AG"
The method is being passed a string which is a column name e.g "C"
I need to search see if "C" is inside "B:J".
So basically it needs to check to see if "C" is in "BCDEFGHIJ" which it is and if it is break from a loop
But if I input "A" it should then go to the next slot in the array.
Thank
This function will return the position in the array where the single column is included in the range. It uses the Intersect property to determine if the two ranges intersect.
Function ArrayPos(sColLetter As String, vaRanges As Variant) As Long
Dim i As Long
Dim sh As Worksheet
Dim lReturn As Long
Set sh = Sheet1
For i = LBound(vaRanges) To UBound(vaRanges)
If Not Intersect(sh.Columns(sColLetter), sh.Columns(vaRanges(i))) Is Nothing Then
lReturn = i
Exit For
End If
Next i
ArrayPos = lReturn
End Function
It's used like this, from the Immediate Window for example
?arraypos("M",array("B:J","K:W"))
1
You would want to add some error checking to make sure the arguments can be converted to ranges, but I'll leave that to you. You could do this without Range objects by splitting the range string on colon and comparing the ASCII values of the letters.
You might take a look at
How to convert a column number (eg. 127) into an excel column (eg. AA)
sheet.Application.ActiveCell.Column //for current selected column
int col=sheet.Range("A").Column; // for any choosen column
returns current column number, just apply the same for your range B:J, check if J (10) > C (3) > B ( 2)
Then you can say that it is inside that range.
In case of need the other way around this function with the link I gave you.
ConvertToAlphaColumnReferenceFromInteger(sheet.Application.ActiveCell.Column)
Done for C#/.NET

Search Excel with multiple string criteria

I'd like to search a description cell for ANY words (criteria) from a predefined list, and pull the relevant dollar amount for the item from the adjacent cell.
To illustrate, here is my setup:
A | B | C | D | E | F |
Date | Descr.| Amount| Cat1 | Cat2 | Cat3 |
D,E,F: Each one of these are item categories. If the item in that row belongs to a category, I would like its amount to populate that category cell in that same row. Each category cell has a formula to test for this and perform the operation.
My first thought was to use VLookup, but I have a list of lookup values. I haven't been able to successfully do that. Each of the category cells has a formula like this -->
=IF(SUM(COUNTIF($B10,{"*costco*","*saputo*","*t & t*"}))>0,$C10," ")
Column B refers to the description, which is searched for any of the criteria. If any of the words are contained in the description, the cell is filled with the amount from column C, otherwise its left with a space.
This works perfectly as is, however I need the criteria (costco, saputo, t&t in this case) to be flexible (add or remove strings to the list) rather than hard-coded in the formula. This is my issue: the formula stops working if I replace the criteria with a reference to another cell. I'm relatively new to excel and not familiar with restrictions/constraints of its functions, which I suspect is the issue.
Any help is much appreciated, let me know if I need to provide more info.
Ankit
Create a Name (like a named range, but refers to a value rather than a range.)
For Excel 2007 and 2010, on the Formulas tab, Defined Names group, Name Manager
For Excel 2003 Insert, Names, Define
Create a new Name (lets use the name "KeyWords") , set it "Refers To" value to
={"*costco*","*saputo*","*t & t*"}
Formula then becomes EDIT enter as an array formula
=IF(SUM(COUNTIF($B10,KeyWords))>0,$C10," ")
Editing the list then becomes editing the value of KeyWords refers to value. This can be done through the Name Manager, or if you wish, through VBA
EDIT
Sample VBA
Sub SetKeyWords()
Dim wb As Workbook
Dim nm As Name
Set wb = ActiveWorkbook
Set nm = wb.Names("KeyWords")
nm.RefersTo = "={""NewString""}"
End Sub
Load the strings you are seeking into an array (via converting a range into an array, or having the user select the strings from a small form you design)
Sub MyLookup(arrCategories() As Variant)
Dim searchrange As Range
Dim xCell As Range
Dim count As Integer
'set searchrange to the proper column
For Each xCell In searchrange
For Each catg In arrCategories
If xCell = catg Then
'Do something here
End If
Next catg
Next xCell
End Sub
You may need to adjust your string array based on whether case matters. Depending on the size of your set of data, it might be better to convert searchrange into an array.
There may be a faster way to see if certain strings are found within a given range, but this is the general idea.

Retrieving Cell name in Excel

Is there a way of displaying the cell name of a particular cell in another cell? I would like to display the cell name in the adjacent cell so that the user is able to identify the cell name without clicking it.
ADDRESS(ROW(),COLUMN()) will give you the address, e.g. $A$1 of the current cell. Add/subtract from the row/column values (numbers) to reference the cell you are after.
If you don't want the $ then you can find and replace it with SUBSTITUTE(ADDRESS(ROW(),COLUMN()),"$","") and get just A1 for example
This function would give the name of the NamedRange the cell belongs to:
Public Function CellName(oCell As Range) As Variant
Dim oName As Name
For Each oName In ThisWorkbook.Names
If oName.RefersToRange.Parent Is oCell.Parent Then
If Not Intersect(oCell, oName.RefersToRange) Is Nothing Then
CellName = oName.Name
Exit Function
End If
End If
Next
CellName = CVErr(xlErrNA)
End Function
It loops through all the names in the workbook, and then for each name it checks if it refers to any thing in this the sheet input parameter is from. If it is then it checks if the input cell and the rages referred by the name intersect. If they do it returns the name of the range.
In Excel 2013, and maybe in some older versions too, ADDRESS() accepts third parameter that defines the format of the address to be returned with following values:
1 - Absolute (default)
2 - Absolute row/Relative column
3 - Relative row/Absolute column
4 - Relative
so lets say in cell A1
ADDRESS(ROW();COLUMN()) //outputs $A$1
ADDRESS(ROW();COLUMN();1) //outputs $A$1
ADDRESS(ROW();COLUMN();2) //outputs A$1
ADDRESS(ROW();COLUMN();3) //outputs $A1
ADDRESS(ROW();COLUMN();4) //outputs A1
If you want to display the name of cell D3 in cell A1 type:
ADDERSS(ROW(D3);COLUMN(D3);4) //outputs text D3 in cell A1
Technically, you could combine the SUBSTITUTE() and new FORMULATEXT() functions to do this, if you don't mind adding a hidden column in your sheet.
Assume cell A1 is named FOO
Add a simple reference formula in B1 to the named cell =FOO
Add a formula in C1 =SUBSTITUTE(FORMULATEXT(B2),"=","")
Hide Column B
Cell C1 will contain the value FOO (or the RC reference for unnamed cells)
Adjust as needed, your mileage (or kilometerage) may vary.
It doesn't seem to be possible, which is weird. You'd think that the cell() function should provide a way to get the name, but it doesn't. Bummer.
ActiveWorkbook.Sheets.Item(1).Cells(row, col).Name.Name
I took some 'advice' from the answer above from Adarsha. I got a similar result to the code below, with that loop and a few refinements. However my 'tip for excel' macros is to make your debugger your best friend.
Function name_of(clls)
'
name_of = ""
'
Dim nam As String
Dim rg As Range
Set rg = clls
'
nam = rg.Name.Name
'
name_of = nam
'
End Function 'name_of
A little bit of patience and perseverance, gave me exactly what I was looking for -- A user defined function to give me the defined name of a cell. What happens if the same Cell has more than one name? Try that and see. It is a simple test, so I want to leave that for you to experiment, learn and pass on your new knowledge.
This will work in very basic circumstances:
Public Function CellName(cel As Range) As Variant
Dim nm As Name
For Each nm In Names
If nm.RefersTo = "=" & cel.Parent.Name & "!" & cel.Address Then
CellName = nm.Name
Exit Function
End If
Next
CellName = CVErr(xlErrNA)
End Function
It won't work if the cell is part of a named range, it won't show multiple names for the cell, it won't work for cells included in named formulae (like =OFFSET() ranges, for example).
The
"=" & cel.Parent.Name & "!" & cel.Address
thing is pretty clunky, too. There may be a better way to do the check. Creating a Range object from the RefersTo and using Intersect() might work.
Excel does have a function "Cell()" that you can get certain properties from.
You can use =Cell("row", K9) and get back row number 9 and there's an equivalent "col" parameter but it returns the column number (11) rather than the letter.
Reference the named cell in another cell, E12 in this case, and then use this formula: ="'"&FORMULATEXT(E12). This puts an apostrophe in front so it will show the name or formula as text.
You can place your cursor in an empty cell, type = then click on the named cell. It will display the cell contents. Then you change the format of the cell to text and it will show =

Resources