VBA erases local currency number format - vba

I am trying to apply a number format from a named cell to another one, where the source cell format can be a percentage, a currency (€ in my case) or whatever. My code uses the .NumberFormat range property and looks like the one below:
For newCell in newCellsRange
Range("newCell").Value = some_calculation()
Range("newCell").NumberFormat = Range("sourceCell").NumberFormat
Next newCell
It works fine for what concerns the way the range is displayed on the sheet (be it a percentage, a currency or a date).
However, if this very same range is linked to a bar chart and its value used as a label (no fancy formatting, right click on the series > add data labels and that's all), the label format will change when I trigger the macro that updates the chart source range (newCellsRange in my example): the format will change from the Euro currency format to an improper American one: 1 523€ will become 1,523 $, 235 € will become ,235 $.
To give further details, I've found out that the .NumberFormat property of the range is "#,##0 $" (which displays €) while the chart label's one is "# ##0 $". I don't have a clue:
why the macro would make the comma disappear as I don't do anything for that
why "#,##0 $" would show up as € on the spreadsheet while "# ##0 $" would be $.
What can I do not to get this weird format switch?
In case this helps (which I doubt): Excel 2013 32 bits (English version) on W7 Enterprise (English version)

The number format depends on two things. At first on the locale settings of the Windows operating system and at second on the chosen format in Excel. So the "Currency" format can be different dependent on the locale settings. With comma or point as decimal point or with different currency symbols. But in English Excel versions its name will always be "Currency".
In VBA the default language is always US English. This is a dilemma with number formats because the default in US English is the decimal point and $ as currency symbol. So the "Currency" format, taken from the Range.NumberFormat property, will be "#,##0.00 $" also in my German Excel.
If I assign Range.NumberFormat = "#,##0.00 $" in my German Excel then the sheet will map this to the locale "Currency". Why the Chart then has problems with this? I don't know.
Microsoft tries to solve the dilemma in VBA by having ...Local properties. So
For newCell in newCellsRange
Range("newCell").Value = some_calculation()
Range("newCell").NumberFormatLocal = Range("sourceCell").NumberFormatLocal
Next newCell
may solve your problem.

Related

vba customize cells format

I am needing to customize cells with simple thousands format, like 1000, without any separator or decimal.
However, I wish to remove text fonts other than a number when they are input.
For example, I want to input 120118, however in my paper from which I am copying that figures, it is formatted as a date, thereby 12/01/18. I am needing Excel to simply keep it as 120118 after typing, removing the slash (/). I have seen similar settings in access queries.
Have you tried simply pasting only the cell value with:
Selection.PasteSpecial Paste:=xlPasteValues
Or just clear the cell format and format it again with your desired format.
Try:
Selecting the range
Home > Number > Number Format (or Ctrl+1 I think) > Custom
Enter ddmmyy
Okay
Can be done programmatically e.g.
Thisworkbook.worksheets("Sheet1").range("A1:A50").numberformat = "ddmmyy"
The above would only be a visual/cosmetic change and the internal value of each cell would still be a date (technically a number) for calculation purposes.
However, if I've misunderstood and you instead want to go from the date 21 Jan 2018 to the number 210118, I think you would need to get the range's value(s), format as DDMMYY string, then clng() - or maybe (DD*10000) + (MM*100) + (YY) might work, then format as "000000" to preserve leading zeros.

Formula in worksheet and VBA works differently

Cell A1 contains the number 25, which is right-aligned, implying it's a number, not text.
D1 contains the formula:
="" & A1
The 25 in D1 is left-aligned, implying it's text. That is confirmed by the following formula, which returns 1:
=IF(D1="25",1,0)
The following VBA code puts 25 in F1 but the 25 is right-aligned and the IF test returns 0:
Range("F1") = "" & Range("A1")
Any explanation for the discrepancy?
E1 contains the following formula which gives a left-aligned 25 and the IF test returns 1:
TEXT(A1,"0")
However, the following code gives a right-aligned 25 and the IF test returns 0:
Range("F1") = Application.WorksheetFunction.Text(Range("A1"), "0")
Not that I have to use the TEXT function. I just wonder why it works differently than when in a worksheet.
Any rule that tells when or what worksheet functions won't work in VBA code, or more precisely, will give different results than when in worksheet?
When a data is written by vba into a cell, an internal type conversion function is called if required, that is if the data type is different from the cell's numberformat property.
You dont want that conversion function to be called.
To avoid this conversion function to be called, choose the proper Numberformat property for the cell before writing the data.
Range("b4").NumberFormat = "#"
Range("b4") = Application.WorksheetFunction.Text(Range("A1"), "0")
You simply get the wrong idea of what is a number in Excel.
in general ALL input is a string. Also writing "25" in a cell.
However: If possible, Excel will convert all inputs to a numerical value if possible. Also for dates and times.
To prevent this, you simply insert a ' in front of your "text" in the cell.
The confusing part for you is the different behavior for formulas.
A formula will always output a "result" AND the "data type".
So =1+1 will be numeric as the last action was math.
=Left(1+1,1) will be text as the last action was text-based.
For =A1 it will simply copy the type. If there is a formula, then this will be the same. But if there is a "direct input" it will always try to convert to numerical and only be text if it can't be converted or if it starts with a leading ' (A1 itself does this already).
As a result: If there is a plain 25 in the cell, it will always be "numerical" no matter "how" you input the 25.
For newer Excel there is only one exception: if the cell formatting is text prior to entering a number, it will be treated as text (no converting). This does not apply if you change the formatting later.
Simple test:
enter 25 in A1 (formatting general)
enter =ISNUMBER(A1) in A2 (will be TRUE)
set formatting for A1 to "text" (A2 will still be TRUE)
enter 25 in A1 (now A2 will become FALSE)
This may fail (Excel confuses itself sometimes here). Try it with a new sheet. ;)
Hopefully you understood the fault in your logic ;)
The cell alignment says nothing about the cell's contents. Forget about anything being "implied" by it. When you start on a virgin worksheet the format for all cells is "General" which means that Excel will decide the format of what you enter. If you enter a number the format will be "Number". If you enter what looks like a date to Excel the format will be "Date", and for most other things the format will be "Text".
So, if you enter " 25" in a cell formatted as "General" Excel will recognise this to be a number despite the leading spaces, read it is numeric, and format the cell to the right. This will happen regardless of whether you made the entry by hand or used VBA. You can then proceed to format the alignment as you wish.
However, if you enter the number 25 in a cell formatted as Text Excel will recognise the number as text and display it formatted to the left (unless you expressly formatted the horizontal alignment to the right).
The best way to deal with any problems you might encounter in this regard, set the NumberFormat and HorizontalAlignment properties for the cells that you want to write to. You can do that both manually or using VBA.
Worksheet function when used in the worksheet behaves / works the same way as when used in VBA. Consider below code:
Note: Range("B1") contains a numeric value 25
Dim r As Range, v As Variant
Dim wf As WorksheetFunction: Set wf = Application.WorksheetFunction
With Sheet1
Set r = .Range("B1")
v = r.Value2
v = wf.Text(r.Value2, "0")
End With
Now using the local window, let us check the data type of variant v.
SC1: All variables un-initialized
You can see, at the start that all variables have no value and the variant type v is empty.
SC2: Variables initialized and v assigned a value
After executing lines up to v = r.value2, all variable types were confirmed (e.g. Range/Range etc.) and variant v is now Variant/Double.
SC3: Re-assign a value on v but using worksheet function Text
Executing the last line which uses the worksheet function Text, variant v type becomes Variant/String. I think this confirms that the function Text works as expected converting the numeric 25 into a string type.
As for the behavior of passing VBA generated value to worksheet, it is covered by Docmarti's post above.

Run Time and Compatibility Errors using Variable Type "Double"

I have a strange issue using Double type variables in my VBA Macros.
The Macro works fine when I test it on some systems, but causes a runtime error '1004' when tested on another system with different language settings.
Both systems use Office 2013.
I have a ScrollBar in a form, with values ranging from -50 to + 50.
Basically an indicator to increase/decrease the value of a range by -/+ 50%
The Macro is something simple like follows:
Dim multiplier As Double
multiplier = CLng(Me.DPScroll.Value) / 100 + 1
ThisWorkbook.ActiveSheet.Range("AB11:AB" & LR).Formula = "=H11*" & multiplier
When the DPScroll.Value = 0 (Multiplier = 1), the form runs file without any errors, but if it has a positive or negative value, it returns
Run-time Error 1004 : Application Defined/Object Defined Error
(On my system, both work fine)
So, I'm guessing the Multiplier is unable to take values in Decimal Points (Eg. 1.07 to increase by 7%)
(Less important issue)
It also causes a strange formatting error on another sheet.
I'm calculating the average of a few rows in a list box and pasting the value to a range. On some systems, the format is retained, but on others it changes and gets multiplied by millions and a Large number is displayed (like 10^E6 times)
Since this is restricted to some systems - are there any regional/language compatablity issues with suing "Double" variable type.
It is indeed a localization issue. As long as you use .Formula the regional settings are always standard US that means the multiplier has to be 1.07 (e.g. not 1,07).
But if the localization is German for example then if the multiplier is cast to a string it becomes 1,07 but .Formula needs the US standard 1.07.
Solution 1
Replace any comma , in multiplier to . using replace()
Solution 2
use .FormulaLocal to use the localized formula:
ThisWorkbook.ActiveSheet.Range("AB11:AB" & LR).FormulaLocal= "=H11*" & multiplier
But then you probably have to deal with other issues like e.g. =IF(A1=0,TRUE,FALSE) becomes localized too (e.g. for german): =WENN(A1=0;WAHR;FALSCH).
Solution 3
Another approach would be to write the multiplier into a named range, so you can use that name in your formula directly as following:
ThisWorkbook.ActiveSheet.Range("AB11:AB" & LR).Formula = "=H11*multiplier"
Therefore you can use ActiveWorkbook.Names.Add "multiplier", multiplier so you even don't need a helper cell for that named range.
But then if you change the multiplier any time, it also changes for every old formula in your sheets where the named range multiplier was used.

Excel - Inserting formula with VBA

Hello Stackoverflow friends,
I am struggling for 1 hour with a formula I would like to insert via VBA:
Formula = "=IFERROR(VLOOKUP(Q" & j & ";Table1[#All];2;FALSE);"""")"
ThisWorkbook.Worksheets("Sheet1").Cells(j, "AE").FormulaArray = Formula
I get the following error message:
Run-time error '1004' - Application-defined or object-definied error
Is there an issue with the brackets or double quotes?
Thanks!
Replace the semicolons with commas:
Formula = "=IFERROR(VLOOKUP(Q" & j & ",Table1[#All],2,FALSE),"""")"
OpenOffice uses semicolons to separate function parameters, Excel normally uses commas, and always uses commas when setting formulas in the above fashion.
When programming in any lanugage also in VBA - better not tied up user to specific regional settings or specific excel version.
So instead of this:
Formula = "=IFERROR(VLOOKUP(Q" & j & ";Table1[#All];2;FALSE);"""")"
ThisWorkbook.Worksheets("Sheet1").Cells(j, "AE").FormulaArray = Formula
Better use this approach, when you determine exact user environment:
s = Application.International(xlListSeparator)
Formula = "=IFERROR(VLOOKUP(Q" & j & s +"Table1[#All]" + s + "2" + s + "FALSE)" + s + """"")"
ThisWorkbook.Worksheets("Sheet1").Cells(j, "AE").FormulaArray = Formula
p.s. I didn't checked the formula for the brackets etc. but just indicating the correct usage of list separator, and how to insert formulas with VBA code within cells in correct way.
As well, as previous post says - excel probably change the formula automatically when you open it. However excel do not change VBA code automatically, so be aware and pay attention to proper code in VBA.
Depending on the regional settings, the list separator (which is also used to separate parameters in functions) is either the semicolon or the comma. This applies when typing a formula into a cell.
Excel dynamically adjusts the list separator (and function names) according to the regional settings of the current computer when a file is opened.
So, if a user with German regional setting, which have the list separator ; saves a file, then a user with US regional settings and a list separator , opens the same file, Excel will adjust the German list separators in the formulas automatically.
When writing VBA, though, you will always need to use the US-English conventions for the list separator, which is the comma.

Excel - Copy the displayed value not the actual value

I am a pilot, and use a logbook program called Logten Pro. I have the ability to take excel spreadsheets saved from my work flight management software, and import them into Logten Pro using the CSV format.
My problem however, is that the work flight management software, exports the date and time of take-off of a flight into one cell in the following excel format: DD/MM/YYYY H:MM:SS PM.
This is handled fine by Excel, and is formatted by default to DD/MM/YY even though the actual value is more specific, comprising of the full length date and time group.
This is a problem because Logten Pro will only auto-import the date if it is in DD/MM/YY format, and there is no way to pull out just the displayed DD/MM/YY date rather than the full date time group actual value, unless you manually go through and delete the extra text from the function box.
My question is: Is there a VBA macro that can automatically copy the actual displayed text, and paste it into another cell, changing the actual value as it does, to just the DD/MM/YY value? Additionally, can this be made to work down a whole column rather than individual cells at a time?
Note I have no VBA experience so the perfect answer would just be a complete VBA string I could copy and paste.
Thank You.
As pointed out in the comments, you'd better not use VBA but formulas instead.
This formula:
TEXT(A1,"dd-mm-yyy")
will return the formated date in a text way. You can drag and drop the formula in the whole range of your cells and Copy/Paste Special > Values so that you will only have the needed values to get imported in Logten Pro.
There are three options using formulas.
Rounddown
Excel stores the date time as a number and uses formatting to display it as a date.
The format is date.time, where the integer is the date and the fraction is the time.
As an example
01/01/2012 10:30:00 PM is stored as 40909.9375
All the values after the decimal place relate to the hours and minutes
So a formula could be used to round the number down to a whole number.
=ROUNDDOWN(A1,0)
Then format the value as a short date.
It will then display as 01/01/2012
INT
As above, but using a different formula to get rid of the fraction (time)
=INT(A1)
Text
Alternately the date only could be extracted as text using this formula
=TEXT(A1,"dd/mm/yyyy")
It will then display as 01/01/2012
I'm a bit late to the party on this one, but recently came across this as was searching for answers to a similar problem.
Here is the answer I finally came up with.
Option Explicit
Sub ValuesToDisplayValues()
Dim ThisRange As Range, ThisCell As Range
Set ThisRange = Selection
For Each ThisCell In ThisRange
ThisCell.Value = WorksheetFunction.Text(ThisCell.Value, ThisCell.NumberFormat)
Next ThisCell
End Sub
This answers the question as asked, apart from the new values are pasted over the existing ones, not into a new cell, as there is no simple way to know where you would want the new values to be pasted. It will work on the whole range of selected cells, so you can do a whole column if needed.