Finding function next value in a specific column - vba

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.

Related

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:

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

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

Find a cell with Today's date in C4:V4 and paste content into cells below

I'm trying to figure out how to write a code that would :
copy contents of Array A,
look into Array B at the headers with dates,
find current date
and paste the contents directly beneath that cell.
So far the best I managed to achieve was have a macro find the date if I typed today's date specifically.
Edit: I was trying to repurpose a record macro and while the first time I recorded the same macro it worked, the next times it didn't all of sudden.
Sub Macro1()
Dim myDate As String
myDate = Format(Date, DDMMYYY)
Range("A5:A11").Select
Selection.Copy
Range("Table29[[#Headers],[23/01/2017]:[11/02/2017]]").Select
Selection.Find(What:="25/01/2017", After:=ActiveCell, LookIn:=xlFormulas _
, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Range(ActiveCell.Offset(1, 0), ActiveCell.Offset(7, 0)).Select
ActiveSheet.Paste
End Sub
Also I'm not sure but I feel like I was lacking some reference to activate Date function in VBA because whenever I try to use it I keep getting errors, even when I try to replicate other codes I found on google with Date in them.
Edit 2: I managed to get as far as paste stuff into desired array, but I still struggle to make Date work. If I don't manually type in the date, it won't work.

Replace Cell with Header Cell

I'm trying to figure out how to either substitute or replace a cell's data with existing data from a header cell.
In the most succinct way to describe it:
If cell = 'unchecked', then replace with the cell's header cell.
There are numerous columns so I can't specifically say replace with a specific cell for all. It would vary depending on the cell.
As in: (not code but won't let me save request without indentation.)
C3=unchecked, then pull C1.
H18=unchecked, then pull H1.
P4=unchecked, then pull P1.
Just cycle through the columns, replacing the term "unchecked" with the value found in the first row of that column.
dim c as long, rplc as string
rplc = "unchecked"
with activesheet
with .cells(1, 1).currentregion
for c = 1 to .columns.count
with .columns(c)
.replace what:=rplc, replacement:=.cells(1, 1).value2, _
lookat:=xlwhole, matchcase:=false
end with
next c
end with
end with
This is a generic framework and is intended to give you something to get started with. Transcribe it for your own purposes and use debug (e.g. F8) to walk through the code to make sure it is doing what you want. If you run into trouble, come back and explain what you do not understand, what errors are occurring and what you have discovered through debug.
You will want to change the ActiveSheet property reference to an actual worksheet name.

Excel VBA; Referencing Variable Ranges

I'm trying to automate a process that takes a monthly report and generates an exception report based on the data. Since the volume of the data in the report varies from month to month, i need to account for that. What methodology is best for referencing a variable range?
For example, instead of referencing the range A1:F7087, i want to reference the entire range that includes any data. For as simple as this appears to be, I haven't been able to find any guidance on it. Appreciate any input. Thanks
Dim rng As Range
Set rng = Range(Range("A1"), Range("A1").SpecialCells(xlLastCell))
This will set rng to contain all cells up to last filled, it will also contain all empty rows and columns.
You should also read this, important part from this article about xlLastCell:
Depending on what you are trying to accomplish, this cell may not be the cell that you are actually looking for. This is because, for example, if you type a value into cells A1,A2, and B1, Excel considers the last cell to be B2, which could have a value or not...
There are pros and cons with just about any method you choose to reference the dynamic block of data you wish to include with your report.
The caveat that comes with .SpecialCells(xlLastCell) is that it may encompass a cell that was previously used but is no longer within the scope of the data. This could occur if your data shrinks from one month to the next although recent service packs and updates provided for Excel 2010/2013 will shrink the rogue last cell through saving the workbook. I'm sure many of us have at one time or another mistyped a value into AZ1048576 and had to jump through hoops getting Excel to internally resize the extents of the actual data. As mentioned, with later versions of Excel, this problem is all but a footnote in history.
One last thing to note is that cells formatted as anything but plain-Jane General will halt the shrink so if last month's report had a formatted Subtotal line 50 rows below where it is this month, the .SpecialCells(xlLastCell) will be referencing an area 50 rows too long.
If you have a contiguous block of data with some blank cells possible but no fully blank rows or columns that segregate your data into islands then I prefer the following approach.
With sheets("Sheet1")
Set rng = .Cells(1, 1).CurrentRegion
End With
The area referenced by the above code can be demonstrated by selecting A1 and tapping Ctrl+A once (twice is A1:XFD1048576). The cells selected will be a rectangle encompassing the last column with data and the last row with data as the extents. Previously used cells and cells that have retained formatting from previous reports have no effect; only cell values and formulas. However, it must be emphasized that the island of data stops at the first fully blank row or column.
The last method I will mention is to position in (aka .Select or otherwise start at) A1 and use .Find with a wildcard searching backwards so that it ends up starting at XFD1048576 and searching toward A1 for the first value or formula it can find first by row then repeated by column.
Dim lr As Long, lc As Long, rng As Range
With Sheets("Sheet3")
lr = .Cells.Find(What:=Chr(42), After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
lc = .Cells.Find(What:=Chr(42), After:=.Cells(1, 1), LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Set rng = .Cells(1, 1).Resize(lr, lc)
End With
This is really the only true method of getting an accurate representation of your data block but its thoroughness is not usually necessary.
Sub highlight()
Dim obj As Range
For Each obj In Sheet1.UsedRange
If obj.Value = Range("A1").Value Then
obj.Interior.Color = vbYellow
Else
obj.Interior.Color = vbWhite
End If
Next obj
End Sub