How can I apply dynamic number formatting? - excel

I've programmed an Excel document for my cryptocurrency portfolio. I add new currencies in a table, to which I pull data via an API to get the prices. I format the result like this: #.##0,00000000 [$ETH] (for Ethereum).
What I would like to achieve is, that when I input currency in column A, the value in column B is formatted to this currency.
Example: http://prntscr.com/p3sof8
So if I input XRP in A5, the value in B5 would read 0,00000000 XRP.
There's no fixed number of currencies I'd use, since I may add new every day.
Basic version of the above logic would be:
Input currency from column A into formatting argument like: #.##0,00000000 [$], except for BTC where the format would be: ฿0,00000000
.

Place this in your Sheet e.g "Sheet1"
Private Sub Worksheet_Change(ByVal Target As Range)
With Target
If .Count = 1 Then
If .Column = 1 Then
If .Value <> "BTC" Then
.Offset(, 1).NumberFormat = "0.00000000" & """ " & .Value & """"
Else
.Offset(, 1).NumberFormat = """" & ChrW(&HE3F) & """" & "0.00000000"
End If
End If
End If
End With
End Sub

No need to use VBA. You can do this with conditional formatting.
To do the specific example:
Go to cell B5
Click Conditional Formatting > New Rule...
Select Use a formula to determine which cells to format
As the formula, put =$A$5="XRP"
Click Format and on the Number tab, set it to custom such as #.##0,00000000 [$XRP]
I will leave it up to you to generalize this

Related

Adding a formula in an active range using the contents of the cell in that range

I want to add a formula to a range of cells using the contents of the cell.
I am relatively new to VBA and I want to make a macro that reduces my work.
The result should be something like this. Using Round formula as an example.
For example, I select a range of cells and the macro adds the formula to the selected range using the contents of that cell. The below image might be clearer in explaining what I want.
Expected Result:
Sub ApplyRoundFormula()
For Each cell In Selection.Cells
If cell.HasFormula Then
StrCurrentFormula = cell.Formula
StrCurrentFormula = Mid(StrCurrentFormula, 2, 999)
cell.Formula = "=ROUND(" & StrCurrentFormula & ",0)"
ElseIf IsNumeric(cell) Then
cell.Formula = "=ROUND(" & cell.Value & ",0)"
End If
Next
End Sub
This script loops through each cell of a selected range (you can change Selection to any range reference), if it has formulas, it crops the equation mark from the beginning and puts the rest into a ROUND formula. If it doesn't have a formula but it has a numeric value, it puts that numeric value into a ROUND formula.

Custom Excel Formats that reference cells

I would like to have an Excel sheet that displays a custom format. The custom format uses the contents of another cell. Here is an example:
Column A : Show a column of numbers in accounting format in the currency of cell(b1).
Cell(B1) : "XYZ"
The intention is that users can enter their own currency. I know there are formatting tools to do this in Excel but this is a question that implements a custom format based upon another cell contents. That's the real question...
A worksheet_change in the worksheet's private code sheet can alter the number formatting in column A.
private sub worksheet_change (byval target as range)
if not intersect(target, range("b1")) is nothing then
if len(cells(1, "b").value2) = 3 then
dim f as string
f = ucase(cells(1, "b").value2)
f = "0 \" & left(f, 1) & "\" & mid(f, 2, 1) & "\" & right(f, 1)
range(cells(2, "a"), cells(rows.count, "a").end(xlup)).numberformat = f
end if
end if
end sub
There are a maximum number of custom number formats that can be added to the existing number formats without deleting previously created cnfs; I think it's around 30 or so.
Assuming you want something like this:
..then just put this in the Sheet Module:
Sub worksheet_Change(ByVal Target As Range)
Dim sFormat As String
If Not Intersect(Target, Range("NumberFormat")) Is Nothing Then
sFormat = Chr(34) & Target.Value & Chr(34) & " "
Range("FormatWhat").NumberFormat = sFormat & "$#,##0;" & sFormat & "[Red]-$#,##0;-"
End If
End Sub
...and give B1 the Name NumberFormat in the Name Box:
...and likewise name some or all of column A "FormatWhat".
(Using Named Ranges avoids hard-coding references in your code. If you hard code cell address into your code, those references will be pointing at the wrong place if you (or a user) later adds new rows/columns above/to the left of those hard-coded references. Using Names avoids this, and makes for more robust code.
I almost never hard-code cell addresses in my code. I almost always use Excel Tables aka ListObjects to hold any data that VBA interacts with for the same reason...ListObjects are dynamic named ranges that Excel automatically expands/contracts to suit the data.)

Excel MsgBox with VBA for multiple linked range

I need some help with an excel problem.
It is a combination of the two problems below:
1) Excel - Popup message with sound alert when cell value meets certain criteria
2) VBA code to show Message Box popup if the formula in the target cell exceeds a certain value
In Sheet1, I have a range of products and sales figure.
Example: Sheet1
In Sheet2, I have multiple columns of sumif() functions. Example: Sheet2.
It contains a column of names in (A:A) and data in (B:B) & (C:C) which are linked to cells in other sheets. I would like a pop up notification saying ("Text in column A" sold is > 20) when the value of any cell in column B exceeds 20 or column C exceeds 40.
For example: If one of the cell value in column "B" gets updated to 33 (which is >20) and the corresponding cell value in column "A" contains text as "Charlie", excel sheet should popup message saying "Charlie sold is > 20".
The below VBA code accomplishes this IF it was raw data. However, it does not work when the cells are linked to data from other sheets, as in the case of this workbook.
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.column = 2 and target.value > 1 Then
MsgBox target.offset(0,-1).text & " sold is > 20"
End If
End Sub
This alternative code works with data linked from other sheets, however it only applies to a specific cell, not an entire column.
Private Sub Worksheet_Calculate()
If Sheets("Sheet2").Range("B2").Value > 20 Then
MsgBox "B2 is >20", vbOKOnly
End If
End Sub
What I'm trying to achieve is this: As I input my raw data in Sheet1, the figures in Sheet2 column(B:B) and column(C:C) get updated. Once any of the cells in Sheet2 column(B:B) exceed 20 or column(C:C) exceed 40, there will be a popup notification that links back to column A text such as MsgBox target.offset(0,-1).text & " sold is > 20". Is there a way to combine the above two codes to achieve this?
Any alternative solutions are welcome too, thank you!
Compare all the Sums in Summary table
Private Sub Worksheet_Calculate()
Dim RangeToCheck As Range
Dim Cell As Range
Set RangeToCheck = Sheets("Sheet2").Range("B2:B5") 'See comment #1
For Each Cell In RangeToCheck.Cells
With Cell
If .Value2 > 20 Then
MsgBox "Product: " & .Offset(columnoffset:=-1).Value2 & _
" in cell: " & .Address & " is " & .Value2 & ">20", vbOKOnly
End If
End With
Next
End Sub
Comments
I recommend turning the range on Sheet2 to Excel table and using ListObject and Listcolumns instead.
Off topic hint: You can also use some counter, put the range into an VBA array and loop through array, it will be faster, than refering to sheet cell one after another. See Writing efficient VBA UDFs (Part 1).

Excel formula in VBA code

So, in Sheet1 I have base of some names and it looks like this:
In Sheet2 I'm working with these names from Sheet1. I'm doing that in a way that I'm entering Code value in column A and in column B I get the Name, in column C I get the Last Name. That looks like this:
I've done this with formulas, entering it in the formula bar. For column A(or Name) I've used this formula: =IFERROR(VLOOKUP(A2;Sheet1!A:C;2;FALSE);"") and for column B(or Last Name) I've used this one: =IFERROR(VLOOKUP(A2;Sheet1!A:C;3;FALSE);""). I've dragged these formulas to row 20 and it works great.
Now, what I'd like to do is to put these formulas into Excel VBA code and them to work for noted range. I've just started to use VBA and I don't know how to do it in it, tried something but doesn't work, ..., I've done this so far. I'm new to this Excel/Macro/VBA thing so any help would be appreciated.
The below code will work if you type in your Code values in sheet2 and highlight them, and run this macro:
Selection.Offset(0, 1).FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-1],Sheet1!C[-1]:C,2,FALSE),"""")"
Selection.Offset(0, 2).FormulaR1C1 = "=IFERROR(VLOOKUP(RC[-2],Sheet1!C[-2]:C,3,FALSE),"""")"
Selection.Offset(0, 1).Value = Selection.Offset(0, 1).Value
Selection.Offset(0, 2).Value = Selection.Offset(0, 2).Value
Edit: If you are wanting to update values as you type use (thank you #PeterAlbert for added optimisation!):
Private Sub Worksheet_Change(ByVal Target As Range)
'end if the user made a change to more than one cell at once?
If Target.Count > 1 Then End
'stop system activating worksheet_change event while changing the sheet
Application.EnableEvents = False
'continue if column 1(A) was updated
'and
'dont continue if header or row 1 was changed
If Target.Column = 1 And Target.Row <> 1 Then
With Target.Offset(0, 1) 'alter the next cell, current column +1 (column B)
'RC1 = current row and column 1(A) e.g. if A2 was edited, RC1 = $B2
'C1:C2 = $A:$B
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,Sheet1!C1:C2,2,FALSE),"""")"
.Value = .Value 'store value
End With
With Target.Offset(0, 2) 'alter the next cell, current column +2 (column C)
'C1:C3 = $A:$C
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,Sheet1!C1:C3,3,FALSE),"""")"
.Value = .Value 'store value
End With
End If
Application.EnableEvents = True 'reset system events
End Sub
Explinatioin of RC:
The FormulaR1C1 formula types are good to use when referencing a cell with respect to the current cell. There a few rules to remember:
The R stands for Row and C is for Column and the integer after it, if any, defines the row or column;
As a basis the RC formula references itself;
Any number following the R or C wraped in [] is an offset to itself, e.g. if you are in cell A1 and use R[1]C[1] you would be referencing cell B2;
Also any number following the R and C is an exact, e.g. if you reference R2C2 no matter the cell you are in would also point to B2; and
To complicate things if you were in cell C5, e.g. using Range("C5").FormulaR1C1 = and coded the follwing:
"=RC[-1]" references cell B5
"=RC1" references cell A5, more rightly $A5
"=R[1]C[-2]" references cell A6
"=Sum(C[-1]:C5)" is =Sum(B:E), more rightly =Sum(B:$E)
If I understand your question and comments correctly, you want to ensure that columns B&C always show you the right values based on your formula, but also want to protect (and maybe even hide the formula) from the users.
I'd suggest you use sheet protection instead: all you need to do is to unlock the cells you want the users to edit, i.e. select column A and in the _ Format cells_ dialog uncheck "Locked" in the Protection tab. Similarly for columns B&C, check "Hidden". Now right click the sheet name and select Protect Sheet. Once this is done, the user can edit column A - but will not see the formula in B&C and cannot edit those cells.
If for some reasons you need to ensure this in VBA, use the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False 'to prevent endless loop
With Target.Offset(, 2 - Target.Column).Resize(, 2)
.FormulaR1C1 = "=IFERROR(VLOOKUP(RC1,Sheet1!C1:C3,COLUMN(RC),0),"""")"
.Value = .Value
End With
Application.EnableEvents = True
End Sub
You need to place this in the module of the worksheet.

How can I obtain the displayed value instead of actual value in Excel?

I have a cell containing a date ex. "05/11/09"
It is currently displayed as "11-MAY-09". How do I copy-paste or use VBA to get the string "11-MAY-09" into the cell next to it ( NOT "05/11/09")?
I can't figure it out other than piecing out the date pieces by itself.
Range("B1").Value = Range("A1").Text
Using the cell's .text instead of .value modifier will copy the text formatting instead of the raw date.
Chuck
I believe you can use the TEXT function to format a date value to your liking.
The format string of "dd-mmm-yy" would format "05/11/09" as "11-MAY-09".
Use the Format function.
Format("5/11/2009", "DD-MMM-YY")
This will return:
11-May-09
If case matters:
UCase(Format("5/11/2009", "DD-MMM-YY"))
returns:
11-MAY-09
"The same answer but with a different function (that has worked for me):
Public Function DisplayText(ByVal pRange As Range) As String
DisplayText = pRange.Text
End Function
Just use =DisplayText(A1). If you change the cell format this function will return the displayed text"
cc: alvaroc
How can I get the displayed value of a cell in MS Excel ( for text that was converted to dates)?
Try this:
Sub FormattedText()
Dim r As Range
On Error Resume Next
Set r = Application.InputBox(prompt:="Select cell", Type:=8)
If r.Count <> 1 Or r Is Nothing Then
Exit Sub
End If
On Error GoTo 0
ActiveCell = "'" & r.Text
End Sub
It will put text of a selected cell (prompted) in the active cell.
You should be able to right click on the cell and set the format as General. This will allow you to put something in without it being automatically formatted to something else.
To save yourself from copying and pasting you will also want to start by putting in the date you want and not formatting and then copying.
In VBA you can do this:
Range("B2") = Range("A2")
Range("B2").NumberFormat = "dd-mmm-yyyy hh:mm:ss" 'Date as 10-Jun-2005
If you need to loop it then:
Range("B" & i) = Range("A"& i)
Range("B" & i).NumberFormat = "dd-mmm-yyyy hh:mm:ss" 'Date as 10-Jun-2005
Another way to do it.
Low-tech but very easy way - paste it into Word, then copy back into Excel! Can take a while with a big file, however... buts works great for one-off uses!

Resources