I originally needed to select top 5% of the selected items but, it couldn't roundUP the number of highlighted items. For example: If there are 25 items in the list, 5% is 1.25 and Conditional Format is only selecting 1 item. According to my report, it should round it up and select 2 items.
As I couldn't find a way to do this, I decided to manually calculate the number of items which would show how many to be highlighted (in a cell).
It would be easier if there is a way to make the conditional format round up the number of selected items.
such as:
.rank = 5 (but should round it up)
.percent = True
If it is not possible,
I would like to highlight the top X values in a column using the conditional formatting.
The value X (The rank) is calculated in a cell and will change everytime the macro is run.
I've tried the code below but, it doesn't work.
Dim i As Integer
i = Workbooks("a.xlsm").Worksheets("b").Range("A1")
Selection.FormatConditions.AddTop10
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1)
.TopBottom = xlTop10Top
.Rank = i
.Percent = False
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
End With
I'm getting the error on ".rank = i" line which makes me think it is not possible to assign a variable there or I might be assigning the cell wrongly.
I also tried ".rank = i.Value" which seems to be wrong as well (Compile error: Invalid qualifier)
I'm a newbie in vba and any help would be appreciated.
ps: using office 365.
Thank you
Update: The code above works as long as the "i" value is not zero.
I managed to create a simple If statement to prevent the error.
'In my report i cannot be below 0
If i > 0 Then
Insert the code above here
'If there is no data to be highlighted
Else
'Do Nothing
End If
If a Non-VBA solution can work for you, you can use this. I made a fake dataset, just a list of 25 values (numbers 1 to 25). You want to highlight 5% higher values. 5% of 25 = 1,25, but rounded up it's 2. So you want to highlight any cell which value is one of those top 2 values in this case.
I got this:
As you can see, values 25 and 24 are highlighted. The Conditional Formatting Rule (CFR) I'm using is based on this formula:
=RANK(A1;$A$1:$A$25;0)<=ROUNDUP(COUNTA($A$1:$A$25)*0,05;0)
This is how it works:
RANK(A1;$A$1:$A$25;0) will rank the value inside the list, in descendent order.
ROUNDUP(COUNTA($A$1:$A$25)*0,05;0) will count how many cells are in the list (25) and will get the 5% (multiplying by 0,05, change 0,05 to the % you need), and it will round it up (in this case, the output will be 2).
Last Step will compare the value of Step 1 with the value of step 2. If it's less or equal to 2 (in this case), it will be highlighted as you can see
Please, note that this CFR may not work properly if there are blanks values.
Also, the good thing is that changing the 0,05 part to whatever % you need, the CFR will update perfectly. You can even bind it to a cell, and change the value of the cell manually :)
Hope this works for you!
AppliesTo property gives you the range where the condition applies.
You can then get the cell count from that, multiply it with the 5% and round it up using a WorksheetFunction.
.Rank = WorksheetFunction.RoundUp(.AppliesTo.Cells.Count * 0.05, 0)
.Percent = False
Related
I was trying to adjust the decimals of many values in an excel worksheet.
The objectives were:
- For values higher than 100, no decimals;
- For values lower than 100 but higher than 10, one decimal; and,
- For values lower than 10, two decimals
I thought using VBA would be simple enough, even though I never used it before. Unfortunately I was wrong. Please see my code below. For some reasons, only the "elseif" section of the code is working. For values lower than 100, the decimals are adjusted correctly. It is not the case for the "if" section of my code though.
It also seems that the code works in cells outside the range (A1:D11) (as long as I select them); which is good since my worksheet is pretty big. I don't understand why though.
I would appreciate if you could shed some light on these mysteries.
Sub adjust_decimal()
'
'
'
'
Dim cell As Range
For Each cell In Range("A1:D11")
If cell.Value > 100 Then
Selection.NumberFormat = "0;General"
ElseIf cell.Value < 100 Then
Selection.NumberFormat = "[<10]0.00;[<100]0.0;General"
End If
Next cell
End Sub
You can use a single line of code:
Range("A1:D11").NumberFormat="[<10]0.00;[<100]0.0;0".
With this rule, numbers below 10 will have 2 decimals, numbers equal or higher than 10 but below 100 will have 1 decimal, and any other case will be a integer.
Please, notice that this applies only to format,it does not change the value at all. If the value is 200,55 you'll see it as 201, but the numeric value used in any calculations involving that cell will use 200,55, not 201.
I have a spreadsheet with roughly 1500 lines, and I am trying to count the number of lines which have one cell value at 0 or lower, and then group them based off of the first 3 characters in another cell in that line.
This is my first attempt trying VBA, and I have done research on each section of this code but I've seen a fair number of contradicting answers for how to do each part of it. I based the code off of one I found to count the number of cells with a certain word in them, so it may be very far off from what I want.
For Each Cell in Range("S26:S1500")
Cell.Activate
If IsEmpty(Cell) Then Exit For
If Left(Cell.Value,3) >= 100 And Left(Cell.Value,3) <=150 And
If ActiveCell.Offset(0,-17) < 1 Then
MisProd = MisProd + 1
The result should be the total number of cells that start with 100 to 150 and have a cell 17 cells left as less than 1.
I instead receive a compile error: Expected: expression.
Updated First function had a couple type-o's. I tested and this one works.
This would probably be better as a custom function. Here's the syntax I think you're looking for.
Function MisProd (srchRNG As Range) As Long
Dim cell As Range
For Each cell In Intersect(srchRNG, srchRNG.Worksheet.UsedRange).Cells
'I use the intersection function so users can selet a whole column)
If IsEmpty(cell) Then
'probably do nothing if it's empty?
'might also be better to use Isnumeric(Left(cell.value,3)) to avoid errors.
ElseIf Left(cell.Value, 3) >= 100 And Left(cell.Value, 3) <= 150 Then
'this is a range of 101 to 149...
If cell.Offset(0, -17) < 1 Then
'if column b for this row is less than 1
MisProd = MisProd + 1
End If
End If
Next Cell
End Function
You could use this in combination with a macro as shown here.
Sub nowAmacro()
MsgBox "Your results are " & MisProd (Range("S26:S1500"))
'better to specify the sheet such as Sheet1.Range("S26:S15000")
End Sub
Firstly, the previous comments and answers are all good and will fix your VBA. Though if you're just trying to learn VBA then working out what your error is would be ideal. Put a break in your code and see if you can run through until your error occurs. It is probably something to do with an unusual row of data.
If it is definitely getting through your first half dozen rows, put a Debug.Print cell.row in and after it has errored, check your output window for the offending row number.
These methods will teach you to debug VBA code. And yours is mostly fine. Stop activating that cell as mentioned, and use "<= 0" not "< 1" for column A. Although that might be the same thing if they're all integers.
But finally, consider not using VBA for a logical task like this if you can. IF you have the ability to add columns to your sheet, add one to get the NUMBERVALUE of column S and then another to show a 1 or 0 if your conditions are met. Then sum the cells in your second column.
I have two worksheets with data from different sources. I need to copy the data to a single worksheet and remove duplicates. To achieve this objective, I need all the data formatted the same on both worksheets. All of this is already coded except with one column of data I am having issues. These columns contain a representation for percentage. In worksheet A, the value is showing as .4386 which equates to 43.86%. I use this code that converts the value without issue:
Worksheets("Verification").Range("F2:F2000").NumberFormat = "0.00%"
In worksheet B, the same data is shown as 43.86, but the above code changes it to 4386.00%. I also tried changing this line to .NumberFormat = "General\%" and this almost works, but returns a value of 44%. What do I need to add to my code to get this to show 43.86% on worksheet B?
Sorry for the slow reply in comments - I will just submit an answer.
Like Ralph said, it's really better to make sure they are the same number.
43.1 and .431 are not the same number.
For Each c In [A1:A10]
If c.Value < 1 Then
c.Value = c.Value * 100
End If
c.NumberFormat = "0.00\%"
Next c
Results:
You are stating that .4386 on worksheet A is the same data [...] as 43.86 on worksheet B. So, Excel is correct to convert 43.86 to 4386.00%. Maybe you need a conditional formatting: when the number is smaller or equal to 1 then format it "0.00%" and otherwise format it as "0.00""%""".
Yet, I would assume that you'll be running into problems when comparing the data between the sheets with this solution. Hence, I would divide all numbers on sheet B by a 100 first to really make them comparable.
Note, that just by making numbers "look alike" they are not the same. Example: write in cell A1 the value 1000 and in cell B1 also 1000. Then change the number format for A1 to 0 and the number format for B1 to 0, (or to 0. outside the US). A1 will show 1000 while B1 will show 1. If you ask in cell C1 =A1=B1 you will get a TRUE as the answer.
I have a couple columns of data, and I am trying to highlight those instances where the second date occurs before the first, to show if there are any mistakes in the data.
ID Start Date End Date
1 01/01/15 01/15/15
2 01/06/15 01/02/15
3 01/06/15 01/03/15
4 01/11/15 01/13/15
I would like to be able to highlight the cells where the end date is earlier than the start date. All of the date conditional formatting links I have been directed to are for basing it off of current date, or one specific date, and I am kind of lost.
Thanks!
This is kinda complicated if you have no coding experience. The best way to solve this problem is to write a VBA script yourself. So I will go Step by step with the process of doing that with the complete code.
1) Open your Excel file, then go to the Developer Tab.
(If you do not see it, go to File->Options, Click on Customize Ribbon, and add click on Developer for the main tabs.
2) Click on the Visual Basic button, under the developer tab.
3a) Paste the following code in:
Sub ColorCellsWithIncorrectEndDate()
Dim Rows
Rows = ActiveSheet.UsedRange.Rows.Count
For i = 2 To Rows
If Cells(i, 2).Value > Cells(i, 3).Value Then
Cells(i, 3).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next
End Sub
3b) The code above works if your excel sheet is in the exact same format it was listed above.
--If the cells are not in the same columns, then you will adjust the numbers that are in "Cells(i,#)" so that the number corresponds to the column. (ie. A=1, B=2, C=3...). Right now it is checking for column B (Start Date) to be greater than column C (End Date). And is then coloring Cell C if it is true.
--If the cells are not in the right row then you adjust the line that says "For i = # To Rows" The Number corresponds directly to the row number.
--If you want a different color then go to this website: http://www.w3schools.com/tags/ref_colorpicker.asp, and replace the "65535" with any one of those valid numbers.
4) SAVE and exit out of visual basic
5) Return to your Excel Sheet and click Developer->Macros. (A dialog box will appear)
6) Select "ColorCellsWithIncorrectEndDate" in the dialog box, and click Run.
7) All the end dates that are past the start date will be highlighted in yellow (or whatever color you chose)
Hope this helps!
-BlindingFog
Dates can be compared by < just like numbers. One possibility would be to research how to do conditional formatting which highlights the smallest entry in each row. If any row has the second rather than the first date column highlighted then it is a problem row.
It is also possible to do it more directly. The key thing to do when none of the predefined conditional rules work is to use Conditional Formatting/New Rule/Use a formula to determine which cells to format. If the data that you show starts in A1 (so that 01/15/15 is in C2), go to C2 and create a conditional formatting rule given by the formula
= C2 < B2
Then -- just paste the formatting down the rest of the dates in column C
I have a piece of code that formats cell according to requirements:
Range.Font.Italic = Microsoft.Office.Core.MsoTriState.msoTrue;
Range.HorizontalAlignment = XlHAlign.xlHAlignGeneral;
Range.NumberFormat = "0.0_%_);(0.0)_%;-_%_)";
And this code is invoked then button on custom ribbon is pressed. It's similar to percentage cell format. One more thing I have to add is multiplying the cell value by 100.
For instance
cell value is set to 0.15, I click button and value changes to 15%.
cell value is set to 2.5, I click button and value changes to 250% etc. (very similar to default Excel Precentage cell style)
However, if I do something like this:
decimal result = Convert.ToDecimal(cell.Value);
cell.Value = result * 100;
and user hits button multiple times, value is multiplied every time. Is there a way to specify something like display format, so that actual value is preserved and only displayed value is multiplied by 100? Or another way to prevent value from being multiplied multiple times?
Well you don't need to multiply it by 100
If the cell has .15 then apply the formatting
Range.NumberFormat = "0.00%"
It will automatically change to 15.00 % and you don't need to multiply it by 100.
FOLLOW UP
An out of the box thinking... Why not hide the % symbol by setting the color of the % to white?
VBA CODE
Sub HidePercentage()
Dim Temp As String
Temp = Format(ActiveCell.Value, "0.00%")
With ActiveCell
.NumberFormat = "#"
.HorizontalAlignment = xlRight
.Formula = CStr(Temp)
.Characters(Start:=Len(Temp), Length:=1).Font.ColorIndex = 2
End With
End Sub
SNAPSHOT
A dirty way would be maintain a hidden sheet, Move original value, or maintain flag for that cell in hidden sheet on button click