Create a Hyperlink that searches worksheet and selects cell with duplicate contents - vba

I have a value in a cell. This value is duplicated, intentionally, in another part of the worksheet. I would like to be able to click the cell in C5 with contents 12345 and it selects the cell in A1:1600 that contains the same value. I will never have more than 2 cells with this same value in the worksheet, but the values will change.
I appreciate any help you can offer.
Thank You.

This should do the trick - I was unsure of the range you wanted to specify, so I just put it as A1:Z1600, but change it as necessary.
In VBA, paste this into your sheet's code module:
Private Sub Worksheet_FollowHyperlink(ByVal Target As Hyperlink)
Dim OriginalAddress As String
Dim ValToFind As String
Dim CurrentCell As Range
OriginalAddress = Target.Parent.Address
ValToFind = Target.Parent.Value
With Range("A1:Z1600")
Set CurrentCell = .Find(What:=ValToFind)
If OriginalAddress = CurrentCell.Address Then
.FindNext(After:=CurrentCell).Activate
Else
CurrentCell.Activate
End If
End With
End Sub

You can use the Hyperlink function to do what you wanting. But you would have to manually type out the formula for each cell that you wanted to link... Here's an example:
=HYPERLINK("[Book1]Sheet1!F2",12345)
This method is very unwieldy. The only way to do what you want in a robust fashion would be to use VBA.
Edit: I was able to duplicate the issue. The below edits seem to resolve the issue.
This VBA solution used the FindNext function to find the next value in the sheet:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim FirstAddress As String
Dim Rng As Range
Dim x As Long
x = Me.UsedRange.Rows.Count
FirstAddress = Target.Address
Set Rng = Me.UsedRange.Find(Target.Value)
If FirstAddress = Rng.Address Then
Me.UsedRange.FindNext(Rng).Select
Else
Rng.Select
End If
End Sub
This works with a double click for the sheet the code is in, and it doesn't matter where the duplicate value is in that sheet. Just place the code in your worksheet's module.
One last way to do this (although still inferior to VBA) is to insert the hyperlink:
In this example, you click on A2>go to Insert Tab>Hyperlink>Place in This Document and enter the corresponding cell. This hyperlinks cell A2 to F2 so that when A2 is selected F2 is selected.

Related

Update a cell value with Macro VBA

I want to be able to create a button function macro to update stock values based upon one cell that contains the new value and another that identifies the physical cell address.
Very new to VBA and only have a basic understanding
I have tried the below:
Private Sub CommandButton1_Click()
Dim rng As Range
rng = Range(Range("m2").Value2).Select
Set rng.Value = Range("k2").Value
End Sub
So what I want to happen is that when clicking the command button the value in the cell determined by the cell address in M2 is updated to the value in cell K2.
Please help a complete noob trying to learn.
You Set Objects not values:
Private Sub CommandButton1_Click()
Dim rng As Range
Set rng = ActiveSheet.Range("m2")
rng.Value = ActiveSheet.Range("k2").Value
End Sub

Detect change from nested formulas

I have a very complex workbook with many tabs. The tabs may have either normal data or formulas in various cells. In the case of formulas, the formulas may be nested from one sheet to the next (i.e. a formula on sheet1 refers to a formula on sheet2 which in turn refers to a formula on sheet3, etc.).
I have a hidden tab that contains the following: source sheet, source range, target sheet, and target range.
A named range has been created over these 4 fields and all applicable rows.
When we wish to save data to the database, we loop through every row in the range mapping and copy the data from the source sheet/range to the target sheet/range. After this, the applicable data is serialized into XML and sent to a web service to be saved.
The problem that we wish to resolve is that we want to mark a cell on a hidden sheet when a change is made by the user to a source range. Since formulas can be nested, the Worksheet_Change event does not pick up the change.
Since a change on one sheet may affect another sheet that is not the active sheet, the Workbook_SheetChange event does not catch the change either.
Is there any way form me to catch when a sheet defined in the mapping is changed, even if it is the result of a formula change several levels deep?
Edit
Thank you for your responses. I was attempting to find the fastest and least process intensive way to determine if data changes within a monitored range. The data may consist of actual data or of nested formulas.
My research showed that I could not actually achieve this result by taking range intersections as I could not detect if the data within a monitored range was modified. This is due to the fact that the monitored range may not be on the active sheet and also may contain formulas.
I have shown the method used to actually detect a change below. If there is any feedback on a better way to achieve the same result, I would appreciated it.
Worksheet_Change event will not work if a cell value is changed by a formula, you need Worksheet_Calculate.
Check out my example workbook here.
And Here for the WebPage of example codes
There is no "easy" way to detect if a nested formula has changed when the formula being monitored is not on the active sheet. While my hope was to detect the modified range and use an intersection of ranges to set a flag, this was not possible because the Worksheet_Change event does not work on formulas and the Workbook_SheetChange event only works on the active sheet. Since my workbooks have over 20+ tabs and 20 - 30 ranges being monitored, this approach does not work. This approach was desired for speed purposes.
Instead, the workbook will need to "check" to see if the current values are the same as the last time the save to database event was called. If not, a dirty flag will be set.
The code for this approach is provided below.
An example of the mapping range is shown in the picture below though in practice there are 20-30 rows comprising this range.
There are three other sheets where Sheet3 contains actual data in A1:H1 and Sheet2 has formulas pointing to Sheet3. Sheet1 has formulas pointing to Sheet2.
As the mapping range indicates, we are looking at a range on Sheet1, even though changes may be made to Sheet3.
The code used is as provided below.
Option Explicit
Public Sub DetermineIfEditOccurred()
Dim oMappingRange As Range
Dim szSourceTab As String
Dim szSourceRange As String
Dim oSourceRange As Range
Dim szTargetTab As String
Dim szTargetRange As String
Dim oTargetRange As Range
Dim oWorksheetSource As Worksheet
Dim oWorksheetTarget As Worksheet
Dim oRangeIntersection As Range
Dim nRowCounter As Long
Dim nCellCounter As Long
Dim szSourceValue As String
Dim szTargetValue As String
Dim oCell As Range
Dim bIsDirty As Boolean
If Range(ThisWorkbook.Names("DirtyFlag")).Value = 0 Then
Set oMappingRange = Range(ThisWorkbook.Names("Mapping"))
For nRowCounter = 1 To oMappingRange.Rows.Count
szSourceTab = oMappingRange(nRowCounter, 1)
szSourceRange = oMappingRange(nRowCounter, 2)
szTargetTab = oMappingRange(nRowCounter, 3)
szTargetRange = oMappingRange(nRowCounter, 4)
Set oWorksheetSource = ThisWorkbook.Worksheets(szSourceTab)
Set oWorksheetTarget = ThisWorkbook.Worksheets(szTargetTab)
Set oSourceRange = oWorksheetSource.Range(szSourceRange)
Set oTargetRange = oWorksheetTarget.Range(szTargetRange)
nCellCounter = 1
For Each oCell In oSourceRange.Cells
szSourceValue = oCell.Value
If szSourceValue = "#NULL!" Or _
szSourceValue = "#DIV/0!" Or _
szSourceValue = "#VALUE!" Or _
szSourceValue = "#REF!" Or _
szSourceValue = "#NAME?" Or _
szSourceValue = "#NUM!" Or _
szSourceValue = "#N/A" Then
szSourceValue = ""
End If
szTargetValue = GetCellValueByPosition(oTargetRange, nCellCounter)
If szSourceValue <> szTargetValue Then
Range(ThisWorkbook.Names("DirtyFlag")).Value = 1
bIsDirty = True
Exit For
End If
nCellCounter = nCellCounter + 1
Next
If bIsDirty Then
Exit For
End If
Next
End If
End Sub
Public Function GetCellValueByPosition(oRange As Range, nPosition As Long) As String
Dim oCell As Range
Dim nCounter As Long
Dim szValue As String
nCounter = 1
For Each oCell In oRange
If nCounter = nPosition Then
szValue = oCell.Value
Exit For
End If
nCounter = nCounter + 1
Next
GetCellValueByPosition = szValue
End Function
The Workbook_SheetChange event is as follows:
Option Explicit
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call DetermineIfEditOccurred
End Sub
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
If Sh.Name <> "MAPPING" Then
Call DetermineIfEditOccurred
End If
End Sub

AutoRefresh Excel VBA

I have a module which I use to check what color the cell contains. If the cell is red, blue or green. But when I use the function: =SumBycolor(cell with colorx;From cell:toCell) it doesn't auto update. I have to open the cell and press enter to make any updates
Anyone have some good tips for how to add auto update?
Function SumByColor(CellColor As Range, rRange As Range)
Dim cSum As Long
Dim ColIndex As Integer
ColIndex = CellColor.Interior.ColorIndex
For Each cl In rRange
If cl.Interior.ColorIndex = ColIndex Then
cSum = WorksheetFunction.Sum(cl, cSum)
End If
Next cl
SumByColor = cSum
ActiveWorkbook.RefreshAll
End Function
If your data is in sheet1 then go to event of that sheet and select Worksheet_SelectionChange and write Sheet1.Calculate. This will calculate the function when ever selection is changed. so you do not have to open the cell and press enter to make any updates. Updates will happen with change in selection.
Paste the following code in sheet code where the formula is kept
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
sheets("data").calculate
End Sub

Does there exist a VBA command which does not change the formula of a cell, but its value?

Suppose in a worksheet the formula of R4 cell is =B1+B2, and its current value is 10.
A VBA command Range("R4").Value = 5 will change both its formula and its value to 5.
Does anyone know if there exists a VBA command which changes the value of R4 to 5, but does not change its formula, such that its formula is still =B1+B2?
PS: we can also achieve the same state in another way: 1) do a Range("R4").Value = 5 2) change the formula of R4 to =B1+B2 but without evaluating it. In this case, does there exist a VBA command which change the formula of a cell without evaluating it?
Edit: What I want to do is...
I would like to write a function, which takes a worksheet where some cells may be out of date (the formula does not match its value), and generates automatically a VBA Sub, this VBA Sub can reproduce this worksheet. The VBA Sub may look like:
Sub Initiate()
Cells(2,3).Value = 5
Cells(4,5).Value = 10
...
Cells(2,3).Formula = "=2+3"
Cells(4,5).Formula = "=C2+C2"
...
End Sub
Such that running Initiate() builds one worksheet with same values and formulas.
Without the VBA command I am asking, this Initiate() will be hard to generated.
You cannot change the value of a cell to something different than what the cell formula computes to.
Regarding your p.s.: You can probably change the formula of a cell without re-evaluation by changing the calculation mode to manual. But that would of course apply to the entire workbook, not just this one cell
EDIT: maybe a solution would be to temporarily save the formula of the cell in either a tag of that cell, or a hidden worksheet?
It is quite simple to change the result of a formula without changing the formula itself:
Change the value of of its argument(s). This is a Solver-type approach:
Sub ForceDesiredResult()
Dim r As Range
Set r = Range("B2")
With r
If r.HasFormula Then
.Formula = .Formula & "-5"
Else
.Value = .Value - 5
End If
End With
End Sub
Here is some very dirty code that will save all values of all formulas on the active sheet as custom properties of the sheet, and a 2nd sub that will mark red all cells where the value has changed from it's original value, while preserving all formulas. It will need some error-checking routines (property already exists, property doesn't exist,...) but should give you something to work with. Since I don't really understand your problem it's a bit hard to say ;)
Sub AddCustomProperty()
Dim mysheet As Worksheet
Dim mycell2 As Range
Dim myProperty As CustomProperty
Set mysheet = ActiveWorkbook.ActiveSheet
For Each objcell In mysheet.UsedRange.Cells
Debug.Print objcell.Address
If objcell.HasFormula Then Set myProperty = mysheet.CustomProperties.Add(objcell.Address, objcell.Value)
Next objcell
End Sub
Sub CompareTags()
Dim mysheet As Worksheet
Dim mycell2 As Range
Dim myProperty As CustomProperty
Set mysheet = ActiveWorkbook.ActiveSheet
For Each objcell In mysheet.UsedRange.Cells
Debug.Print objcell.Address
If objcell.HasFormula Then
On Error Resume Next
If mysheet.CustomProperties(objcell.Address).Value <> objcell.Value Then
objcell.Font.ColorIndex = 3
On Error GoTo 0
End If
End If
Next objcell
End Sub

Getting the selected cell's range from a different worksheet in Excel

I'm trying to set up Excel so that the cell's value that is selected in the first worksheet is set to the value of a cell that's double clicked in a different worksheet. So far my code looks like this:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Dim c As Range
For Each c In Sheet1.Range("M11:M24")
If IsEmpty(c) Then
c.Value = Target.Value
Exit For
End If
Next c
End Sub
What this does is sets the first empty cell in the range m11:m24 to the contents of the double clicked cell in the other worksheet. What I want though is not a static "M11:M24" range, but instead have the user select a cell in the first worksheet by clicking on it, move to the other worksheet, double click a cell in that worksheet and have the value appear in the selected cell on the first worksheet. I think I could have it so that there is a variable set up to save which cell is selected in the first worksheet and then just access that from the other worksheet. But I'd prefer if there was away built in to Excel to just choose the selected cell.
Is there a way to get the selected cell/range in Excel?
I solved this easily. The code is:
Sheet1.Activate
ActiveCell.Value = Target.Value
If you want to do a whole selection, try
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
Sheet1.Activate
Dim r As Range
Set r = Selection
r.Value = Target.Value
End Sub