How to expand a group in Excel by using Hyperlink(or by maybe assigning Macro to Hyperlink) - vba

I have a table at the top of my sheet and this table has a different section names.
I'd like to insert a hyperlink to these section names to go and open it's group below when I click them.
Please Refer to the view of my table and sections as default (Collapsed)
I could create a macro which:
Expands all groups
Goes to the Section that I clicked,
Collapses all groups
Only opens the group on active cell,
But assigning this macro to ~20 different sections increases the file size.
After some search I found this on SO: Excel: Assign a macro to a hyperlink? So maybe there is a way to connect this two method?
How this can be solved?

I'd suggest creating a master sheet with the "group" table and any rollups you need. The subsequent sheets could have all the "section" data on them. This has the added benefit of being more scaleable.
Is it strictly necessary to have all the information on the same sheet? This is pretty much why Excel has multiple sheets. Using multiple sheets would also allow you to use standard hyperlinks.
However, if you would like some VBA to get you closer, consider the code below. This grabs the value form the active cell, then searches for the next cell with that value. If the section with the found cell is collapsed, it expands it and visa versa.
Sub OpenSection()
Dim x As String
x = ActiveCell.Value
Dim y As String
y = Cells.Find(What:=(x), After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Address
'Range("b1").Value = y
With ActiveSheet
With .Range(y).EntireRow
If .ShowDetail = False Then
.ShowDetail = True
Else
.ShowDetail = False
End If
End With
End With
End Sub

Related

Finding function next value in a specific column

I am trying to make a macro button that will automatically select column H and then search and select one by one in an array(one every time I click the macro) every cell in that specific column, that contains the € symbol. I can do that exactly as I want manually using the native excel search function but it is time consuming. Yet I don't know how to do that in VBA. Note that the cells in column H are currency formatted..The code that almost works for me so far is this:
Search = InStr(ActiveCell.NumberFormat, Chr(128))
Selection.Find(What:=Search, After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
BUT the above code doesn't automatically select column H for search. I have to do that manually. When i insert in the above code Columns("H").Select (in order to make the code select the column H automatically) the macro selects the first cell that contains the € symbol in the column H (which is what i want) BUT when clicking again it does not go to the NEXT cell that contains the € symbol in that column. It sticks on the first finding. Could you please help me?
You should always avoid using Selection. or .Select.
Instead of Selection.Find specify the correct range:
Worksheets("MySheetName").Columns("H").Find
Also have a look at the Range.FindNext Method (Excel). With find you will always find the first occurrence only. For further searches you will need to use FindNext.
I am not sure what do you want to achieve, but if you need to find cells formatted as Currency, I would rather use this code:
Sub findCur()
Dim rngCol As Range
Set rngCol = Range("H:H")
With Application.FindFormat
.Clear
.NumberFormat = "$#,##0.00"
End With
rngCol.Find(What:="*", After:=ActiveCell, SearchFormat:=True).Select
End Sub
Add a condition to the selection, something like:
If Selection.Column<>7 then Columns("H").select
This way if you are already in column H, it won't reselect it, but if you are not there, it will go there.

Arrange columns based on the order of values in an array - and buttons disappearing

I have this code which is looking in a column (On a different sheet at XFD1) and creating an array from the values in that column. Then it is searching for those values one at a time across a row on the current sheet. When it finds a match, it cuts the column and inserts it at the location that corresponds to the order of the values in the array.
I'm not getting any compile errors. I placed a button (not ActiveX) on the worksheet and used it to execute the code. Here is what I see:
Nothing appears to happen. Columns are not moved at all.
The computer is obviously "thinking " because the whirly-gig is spinning away.
And here is the Mysterious part - The button disappears! it never comes back. I placed several buttons on the worksheet and tried them all. The button disappears every time.
I really need to get this working. All I want is to reorder the columns to the same order as my list on the other sheet (95 items in the list). I thought this code would do it but I seem to have entered the Twilight Zone and things are not as they seem (at least from my perspective)!
Here it is:
Sub Reorder_Columns()
Dim arrColumnOrder(1 To 95) As String
Dim index As Integer
Dim Found As range
Dim tick As Integer
For index = 1 To 95
arrColumnOrder(index) = UserFormDropDownDataSheet.range("XFD1")
Next index
Application.ScreenUpdating = False
tick = 1
For index = LBound(arrColumnOrder) To UBound(arrColumnOrder)
Set Found = Rows("1:1").Find(arrColumnOrder(index), LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
If Not Found Is Nothing Then
If Found.column <> tick Then
Found.EntireColumn.Cut
Columns(tick).Insert Shift:=xlToRight
Application.CutCopyMode = False
End If
tick = tick + 1
End If
Next index
Application.ScreenUpdating = True
End Sub
The answer to the question concerning what was wrong with my original code is:
First, I was trying to set the size of the array but should have been working with a dynamic array as I expect the data in my array column will grow as I add more columns to the sheet I am trying to sort. So, Dim arrColumnOrder(1 To 95) As String should have been Dim arrColumnOrder As Variant.
I was then trying to iterate over my array with
For index = 1 To 95
arrColumnOrder(index) = UserFormDropDownDataSheet.range("XFD1")
Next index
Which of course is all wrong. I replaced this with
arrColumnOrder = UserFormDropDownDataSheet.range("XFD1:XFD95").Value
Then, in
Set Found = Rows("1:1").Find(arrColumnOrder(index), LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
Should have been "... Find (arrColumnOrder(index, 1)..."
The answer to why the button was moving is that I did not Set the format option of the button (right click the button, Format Control>Properties>Select "Don't move or size with cells.") So when things were moving (and weirdly because my code was all wrong) The button moved with the cell when the column was copied and pasted.
Here is my final code and it works and does exactly what it is expected to do. Namely, it creates an array from the data in the range "XFD1:XFD95" (on a separate worksheet where I have the column headers stored in the proper order), then it sorts the columns in the active worksheet to match the order of the array. I did not want to explicitly call a sheet name as this will run on varying sheets. Using Find as opposed to Match, works just fine for me as this is not a huge amount of data I'm dealing with so speed is not an issue.
Sub Reorder_Columns()
Dim arrColumnOrder As Variant
Dim index As Interger
Dim Found As range
Dim tick As Integer
arrColumnOrder = UserFormDropDownDataSheet.range("XFD1:XFD95").Value
Application.ScreenUpdating = False
tick = 1
For index = LBound(arrColumnOrder) To UBound(arrColumnOrder)
Set Found = Rows("1:1").Find(arrColumnOrder(index, 1), LookIn:=xlValues, LookAt:=xlWhole, _
SearchOrder:=xlByColumns, SearchDirection:=xlNext, MatchCase:=False)
If Not Found Is Nothing Then
If Found.column <> tick Then
Found.EntireColumn.Cut
Columns(tick).Insert Shift:=xlToRight
Application.CutCopyMode = False
End If
tick = tick + 1
End If
Next index
Application.ScreenUpdating = True
End Sub
For me, one of the big lessons here is to not try to write code when I have only slept for two hours! I was really tired and making silly mistakes because I was not thinking clearly. I got a good night's rest and then this morning I was easily able to see where I went wrong.

Making an excel VBA macro to change dates and format

I'm a complete novice at macros but I've had trouble finding the exact solutions I need, and more trouble combining them. I get this raw data report which needs a couple of changes before I can input it into our master data set for reporting. These things need to happen (please refer to the picture):
The date needs to be expressed in the formation "mmm-yy". I've tried to add "01/" to make "01/04/2017" (I'm Australian so this is the 1st of April), but for some reason it automatically changes it to 04/01/2017. Ultimately, I need 04/2017 to go to Apr-17 for all data in the column
"Medical Div" change to "Medical" and "Mental Health Div" change to "Mental Health" - i've already sorted a macro for this, but not sure how to combine it with another macro for the other functions I'm wanting.
If anyone can help providing code or links to good resources which will allow me to perform all these functions at once with one macro that would be great.
Thanks
This can easily be done with Power Query instead of VBA. Power Query is a free add-in from Microsoft for Excel 2010 and 2013 and built into Excel 2016 as "Get and Transform". Conceptually, the steps are:
Load the data
insert a new column with a formula that combines the text "1/" with the column Month-Year
change the type of the new column to Date
remove the old Month-Year column
select the Division column
replace " Div" with nothing
Save the query
When new data gets added to the original data source, just refresh the query. All this can be achieved by clicking icons and buttons in the user interface. No coding required.
Well, for point 2, how about recording a macro and using Find and Replace twice?
This should combine them into a macro for you. Then you can copy paste that elsewhere.
As for the date, Excel has an predisposition to convert to US format. Try this first (assuming "Month-Year" column is B)
Range("B2") = DateValue(Range("B2"))
Then apply formatting later.
Private Sub mySub()
Dim myRng As Range
Dim r As Range
Dim LastRow As Long
Dim mySheet As Worksheet
Dim myFind1, myFind2 As Variant
Dim myReplace1, myReplace2 As Variant
'This will get the number of rows with value in the sheet
LastRow = Sheets("Sheet1").UsedRange.Rows.Count
'This is for the first find and replace. It will search all cells with exact value of "Medical Div" in the sheet and change it to "Medical".
myFind1 = "Medical Div"
myReplace1 = "Medical"
'This is for the second find and replace. It will search all cells with exact value of "Mental Health Div" in the sheet and change it to "Mental Health".
myFind2 = "Mental Health Div"
myReplace2 = "Mental Health"
'This will loop through the entire column with the date that needs to have the format mmm-yy. It will convert the 04/2017 to date format first before making it Apr-17.
With Sheets("Sheet1")
Set myRng = Sheets("Sheet1").Range("A2:A" & LastRow)
For Each r In myRng
r.Value = CDate(r.Value)
Next r
End With
myRng.NumberFormat = "mmm-yy"
'This will loop through the active worksheet and apply the find and replace declared above.
For Each mySheet In ActiveWorkbook.Worksheets
mySheet.Cells.Replace what:=myFind1, Replacement:=myReplace1, _
LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
mySheet.Cells.Replace what:=myFind2, Replacement:=myReplace2, _
LookAt:=xlWhole, SearchOrder:=xlByRows, MatchCase:=False, _
SearchFormat:=False, ReplaceFormat:=False
Next mySheet
End Sub
Here is a code that you could try.
It will change the date format of the column with Month-Year to
"Apr-17" regardless of the current date format.
It will also find and replace the Medical Div and Mental Health Div
to "Medical" and "Mental Health".
You will need to change the range to suit your needs. I have set the column for the month-year to column A. You must change it to column B if that is where your dates are.
This is my data before running the macro:
Here is my data after running the macro:

Removing all $ from formulas in Excel

This is a hack-y Excel question, certainly not standard procedure. Apologies in advance.
Inside a workbook, I have a financial model. It spans three sheets: Revenue and Expense, which both read information from Inputs. Together, the sheets form a complete model.
I want to expand my workbook by creating a duplicate model alongside my first one. The idea is to have side-by-side scenarios that I can compare. 2 sets of inputs, 2 sets of expense calcs, and 2 sets of revenue calcs, each set side-by-side on its respective tab.
Normally, I would just copy the formulas over and 'bam' I've got a duplicate model. Unfortunately, I can't do this because I used a ton of $ characters, locking my cell references. Copying the formulas in Revenue off to the right wouldn't change which cells the formulas reference on Inputs tab. The model is large enough that it would take hours to remove the cell reference locks from each formula manually.
My current plan is to use VBA to remove all of the $ characters from formulas and then go ahead with the copy pasting method.
Will this work?
How can I remove a specific character from formulas using VBA?
You can press ctrl+' this will change all the cells from showing their value to showing their formula. In this view you can press ctrl+H to replace all $ with nothing and click "Replace All".
So no need to code it all in vba, which would have been possible too, but probably a bit more complicated.
This will remove all the dollar signs you wanted to remove.
Pay attention though if you make any edits extrapolating formulas in the new dollar-sign-less sheet, that it will probably be incorrect for it will also extrapolate the set references which should contain a $.
For removing the $ in external link paths in Excel -
Sub ExtLinks_RelativePaths()
This macro converts external links in selected cells to relative links by removing the $ from the cell reference
' Source: todd.kluge#merrillcorp.com
Dim myCells As Range, curCell As Range
Dim myVal As Boolean
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
Set myCells = ActiveSheet.UsedRange
On Error Resume Next
For Each curCell In myCells
curCell.Select
myVal = IsFormula(curCell)
If myVal = True Then
With Selection
.replace What:="$", Replacement:="", LookAt:=xlPart, SearchOrder:= _
xlByColumns, MatchCase:=False, SearchFormat:=False, ReplaceFormat:=False
End With
End If
Next curCell
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
MsgBox ("Formulas on the active sheet now have relative references.")
End Sub
Function IsFormula(cell_ref As Range)
IsFormula = cell_ref.HasFormula
End Function

VBA Referring to a cell using Sheet Name not working properly

Summary: I am writing a macro that takes names from many different sheets in an excel file and compiles them together on a "master list", but I'm having trouble with referencing a cell on another sheet.
The Problem: When I refer to a specific cell using the sheet name as reference with Sheets("MasterList").ActiveCell.Offset(0, 1), nothing gets picked up. However, when I remove Sheets("MasterList") the macro works fine (the macro is currently on "MasterList" at the time which is the only way this would work). Also, the spelling for the name of the sheet was correct in my code.
Question: Why is this happening? The logic behind the code seems sound, and I'm spelling my sheet name correctly.
Code:
Do
If Sheets("MasterList").ActiveCell.Offset(0, 1) = firstName Then 'IF FIRST AND LAST NAMES MATCH, EXIT THE CHECK
Exit Do
End If
On Error Resume Next
Cells.Find(What:=lastName, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Loop Until Err.Number > 0
ActiveCell is a property of the Application object, not a Sheet.
There is only one ActiveCell, and it is the active cell on the currently active sheet.
It's not entirely clear what you are trying to do. But in general you should avoid Select and Activate with this sort of code. Use instead somthing like:
Dim wsMasterList as Worksheet
Set wsMasterList = Thisworkbook.WorkSheets("MasterList") ' assuming the vba code is in the workbook containing MasterList
To track the last used cell in MasterList use a variable like
Dim rMasterList as Range
Set rMasterList = wsMasterList.Cells( ... ' Specify the cell you want
Then use rMasterList.Offset(0, 1) to refer to cells relative to that cell
Searching on MasterList use:
Dim cl as Range
Set cl = wsMasterList.UsedRange.Find( ... )
If Not cl Is Nothing Then
' cl will be Nothing if the search term is not found
' ...