Global VBA date format and decimal separator - excel

Is there a way to change VBA settings globally on PC to accept dates and number on a specified format? (on my case dd/mm/yyyy and comma)
Changing Excel settings doesn't solve it for me.
As an small time VBA developer, I'm mostly creating userforms for data input and validation. Alongside with some basic access privileges, It keeps users (mostly an client's hired arms) from nosing on the database and corrupting it.
But, on form's submitting, the textbox values are saved temporally on spreadsheet's cells. Somehow on this step dates get scrambled and in some cases an 3 decimal places numeric gets multiplied by a thousand (e.g. 1/2/2000 turn to 2/1/2000 and 1,234 turn 1234). It defeats the whole purpose of those applications - data gets corrupted.
I've been able to workaround these using the Format(expression, format) function, but that must be applied every time an date or some precision number is added, or even used on some auxiliary task.
This is an recurrent problem for me because, as an Brazilian, dates are formatted as dd/mm/yyyy and decimal separator is ","(comma) on practically 100% of my local users.
Anybody had similar problems?
TIA

Excel doesn't have a default date format. Excel uses the Window System Date format settings. You can change you system setting by go to Control Panel -> Change date, time and number formats.
Change Date Format in Windows 7, 8.1 and Windows 10 to dd-mm-yyyy
After adjusting the Windows System Settings to dd-mm-yyyy, CDate will expect strings to be in the dd-mm-yyyy.
Range("A1").Value = CDate( "11/01/2016" )
Result: Monday, January 11, 2016

Summary of comments for those to lazy to read.
Alright, as Thomas Inzina pointed, the strait answer to my question is NO, you can't because there isn't such thing in VBA as this Global setting.
As Rory pointed out, the CDate function should solve (indeed it does) this issue, at least as to the date. Again, Thomas answer didn't include it but it points to the windows conf that would be used by the CDate function.
Datetimepicker, suggested by cyboashu, would solve this issue too, but it requires some tweaking on the user's PC to be available. Too much work for me. Although, this approach has the "pretty" advantage, adds value to your project.
Still looking for the comma/dot bad conversion problem. I'll keep editing this answer while none better exists.

Here I write a function called gdate that accepts a string with a date in a specific format. Then I parse the string, then call cdate based on the users date settings.
All I have to do is find/replace cdate with gdate throughout my code. Now I have a way to handle all date formats by always expecting an exact one gdate("mm/dd/yyyy"). Adjust the parsing if you want to expect different format. Building off built-in objects and functions is how we make things work.
Function gdate(ByVal dstring As String)
' 0 = month-day-year; 1 = day-month-year; 2 = year-month-day
d = Mid(dstring, InStr(1, dstring, "/") + 1, Len(dstring) - 5 - InStr(1, dstring, "/"))
m = Left(dstring, InStr(1, dstring, "/") - 1)
y = Right(dstring, 4)
dtype = Application.International(xlDateOrder)
Select Case dtype
Case 0: gdate = CDate(m & "/" & d & "/" & y)
Case 1: gdate = CDate(d & "/" & m & "/" & y)
Case 2: gdate = CDate(y & "/" & m & "/" & d)
End Select
End Function

Related

Comparing dates to set font of text in Excel

I am taking my open tasks from Outlook tasks and putting them into a spreadsheet.
I want to make any late tasks red and bold. This code works except that it also set three lines red, bold that are not late.
Because the ones that are incorrect are in the same month as current date, I am guessing that I have a data type mismatch, or something like that.
I tried using CDate, and that did not work either.
y = 2
For x = 1 To tasks.Count
Set tsk = tasks.Item(x)
'Fill in Data
If Not tsk.Complete Then
exWb.Sheets("Sheet1").Cells(y, 1) = tsk.DueDate
exWb.Sheets("Sheet1").Cells(y, 2) = tsk.Subject
If tsk.DueDate < Date Then
MsgBox tsk.DueDate & " " & Date
'Make red bold
exWb.Sheets("Sheet1").Cells(y, 1).Font.Bold = True
exWb.Sheets("Sheet1").Cells(y, 1).Font.Color = RGB(255, 0, 0)
End If
exWb.Sheets("Sheet1").Cells(y, 3) = tsk.PercentComplete
exWb.Sheets("Sheet1").Cells(y, 4) = tsk.Status
y = y + 1
End If
Next x
enter image description here
In Outlook evaluates date-time values according to the time format, short date format, and long date format settings in the Regional and Language Options applet in the Windows Control Panel. In particular, Outlook evaluates time according to that specified time format without seconds. If you specify seconds in the date-time comparison string, the filter will not operate as expected.
To make sure that the date-time comparison string is formatted as Microsoft Outlook expects, use the Visual Basic for Applications Format function (or its equivalent in your programming language). The following example creates a Jet filter to find all contacts that have been modified before June 12, 2022 at 3:30 P.M local time.
Format("6/12/2022 3:30PM","General Date")
When you are sure that both operands are dates, less or greater should work correctly. Otherwise, you can format dates and use the DateDiff function which returns a long specifying the number of time intervals between two specified dates.
Also, instead of iterating over all items in the tasks folder in Outlook and checking whether a particular task is completed:
For x = 1 To tasks.Count
Set tsk = tasks.Item(x)
'Fill in Data
If Not tsk.Complete Then
You need to use the Find/FindNext or Restrict methods of the Items class. They allow getting items that correspond to the specified criteria. You may read more about these methods in the article that I wrote for the technical blog:
How To: Use Outlook Find and FindNext methods to retrieve Task items
How To: Use Restrict method to retrieve Outlook Task items

Decimal places for multiple formats

I am trying to figure out a way to increase/decrease decimal places for selected range (one or multiple cells with potentially multiple different formats).
So far my codes is as follows:
Dim myformat As String
Dim cell As Range
Dim val As Variant
For Each cell In Selection
val = cell.Value
myformat = cell.NumberFormat
If IsDate(val) = False Then
If InStr(1, myformat, ".") > 0 Then
myformat = myformat & "0"
Else
myformat = "0.0"
End If
End If
cell.NumberFormat = myformat
Next cell
Generally, it works, but not in its entirety. What I need it to do is to work for percentage, general, number formats as well as for formulas (not straight put cell values) and CUSTOM formats (this I cannot bypass no matter how hard I try to do it...).
The code should NOT work (should exit sub or do nothing) when it sees that cell contains time/date format (I managed to do that).
Below you will find types of formats I am developing my macro on:
As you can see my way of coding (I'm trying to learn) is to simply edit NumberFormat by reading the existing format and changing it as needed. This works for simple formats, but when combined with custom formats? It just does not work.
Does anyone have any ideas how can I proceed with my idea? Any help is much appreciated!
Thank you in advance for anyone willing to assist me in this. I am getting better in VBA with each day passing but not THAT good, yet ;)
For custom formats that already include a decimal point, instead of:
myformat = myformat & "0"
It would be more reliable to use:
myformat = replace(myformat,".",".0")
This will ensure an extra 0 is added after all decimal points, including in custom number formats with multiple sections, such as:
#,##0.00;[Red]-#,##0.00
To add a decimal point to a number where there isn't yet a decimal point, instead of:
myformat = "0.0"
use:
myformat = replace(myformat,"0","0.0")
Note that it still won't handle all possible custom number formats, which would require an enormous amount of parsing, but it should handle the standard types of formats as per your example.
To remove decimal points, do the reverse:
myformat = replace(myformat,".0",".")
This would leave behind a decimal point after all zeroes are removed, however this could be handled by checking if the number format contained decimal points that weren't followed by zeroes:
If InStr(myformat, ".") > 0 and InStr(myformat, ".0") = 0 then
myformat = replace(myformat,".","")
End if

Prevent Excel converting number range to Date format

I'm using Excel to translate data from one system which outputs .csv files to another which can read in .xls files. One column is sizes, which frequently includes terms like 4-6, 6-8, etc. When the csv is opened in Excel, these are automatically(?) converted to dates (6-Apr, 8-Jun, etc.) I can use
.NumberFormat = "m-d"
to get the data to *look like it should, but of course it's still a date value, and any operations I try to perform with it convert back to date. Is there any way to convert it to text in exactly that format? If I declare the .NumberFormat as "#", it just changes the value to a serial. I use the size, along with several other columns to create one long product ID code for inventory purposes.... when the size changes to a date value, I end up missing some of the data.
I found a solution to this problem that runs entirely from VBA - i.e., doesn't depend on special import conditions. I would appreciate any pointers or recommendations, especially if this has the potential to create unforeseen errors:
Dim Size as String
For i = 2 To LastRow
If IsDate(Range("H" & i).Value) Then
Size = Month(Range("H" & i)) & "-" & Day(Range("H" & i))
Range("H" & i).NumberFormat = "#"
Range("H" & i) = Size
End If
Next i
The column I'm testing includes size values that are string (XL, SM, 12T, etc), along with values that get converted to dates (4-6, 6-8). This seems to convert it back to a string value, and then properly treats it as a string value on all future uses (concatenations and logical tests)

Change text to specific date format + Excel VBA

I want to change so many dates saved as text in excel sheets to Arabic (Hijri) date format, ie; dd/mm/yyyy to (right to left) yyyy/mm/dd .. it can be done manually be change custom format from Number Format panel ( by choosing the location , calendar type and the right format from list ) then replace the text in cell by same value ..
I need VBA code to automate this replacement process for any ltr date and for existing rtl date just convert the format from general to date ..
another problem , there is some other text around the date in cell like ( dd/mm/yyyy ttt ) . I want the code to remove this text (ttt) ( any text ) and then change to the right format
I found this code but it is not work to my specific need
Changing the date format to yyyy-mm-dd
I appreciate any help , thanks in advance ..
You have a number of separate problems and it is unrealistic to expect someone else to have posted a complete solution to that set of problems or that someone will code a complete solution for you. You need to split your total problem into its components and create or look for a solution to each component.
You have strings that contain CE dates in the format “dd/mm/yyyy”. These dates could be surrounded by text. You give the example “dd/mm/yyyy ttt”. Can ttt contain spaces? Could the “ttt” come before the date? Could the string be as complicated as “aaaa bbbb cccc 12/11/2016 dddd eeee ffff”?
Whatever the situation, I suspect something like:
Dim Part() As String
Part = Split(.Cells(R, C).Value," ")
would be the core of first step. With my complicated example, this would give:
Part(0) = "aaaa"
Part(1) = "bbbb"
Part(2) = "cccc"
Part(3) = "12/11/2016"
: : : :
A loop over the parts of each cell value looking for a string for which IsDate gives True would allow you to find the date so .Cells(R, C).Value = Part(N) would delete the unwanted text.
I would take a copy of your data and try to code a macro that discards the unwanted text. If you can successfully create that macro, you have completed step 1 of your solution. If you have trouble with this macro, you can ask for help here and expect to get it.
The next step is to convert the string “dd/mm/yyyy” to an Excel date. Excel holds dates as the number of dates since 1/1/1900 CE. Replacing:
.Cells(R, C).Value = Part(N)by .Cells(R, C).Value = CDate(Part(N))ought to do the trick. However, Excel sometimes tries to interpret “dd/mm/yyyy” dates as “mm/dd/yyyy”. I think you will be alright but be aware of this possibility.
Your last step is to convert a date from the CE calendar to the Hijri calendar. This is not just a format issue. The two calendars have different year zeroes and different month lengths. There may be a standard conversion function in your country but there does not appear to be one here in the UK. There is help online so you should be able to find a function that will perform the conversion.
You have a number of separate problems and it is unrealistic to expect someone else to have posted a complete solution to that set of problems or that someone will code a complete solution for you. You need to split your total problem into its components and create or look for a solution to each component.
You have strings that contain CE dates in the format “dd/mm/yyyy”. These dates could be surrounded by text. You give the example “dd/mm/yyyy ttt”. Can ttt contain spaces? Could the “ttt” come before the date? Could the string be as complicated as “aaaa bbbb cccc 12/11/2016 dddd eeee ffff”?
Whatever the situation, I suspect something like:
Dim Part() As String
Part = Split(.Cells(R, C).Value," ")
would be the core of first step. With my complicated example, this would give:
Part(0) = "aaaa"
Part(1) = "bbbb"
Part(2) = "cccc"
Part(3) = "12/11/2016"
: : : :
A loop over the parts of each cell value looking for a string for which IsDate gives True would allow you to find the date so .Cells(R, C).Value = Part(N) would delete the unwanted text.
I would take a copy of your data and try to code a macro that discards the unwanted text. If you can successfully create that macro, you have completed step 1 of your solution. If you have trouble with this macro, you can ask for help here and expect to get it.
The next step is to convert the string “dd/mm/yyyy” to an Excel date. Excel holds dates as the number of dates since 1/1/1900 CE. Replacing:
.Cells(R, C).Value = Part(N)by .Cells(R, C).Value = CDate(Part(N))ought to do the trick. However, Excel sometimes tries to interpret “dd/mm/yyyy” dates as “mm/dd/yyyy”. I think you will be alright but be aware of this possibility.
Your last step is to convert a date from the CE calendar to the Hijri calendar. This is not just a format issue. The two calendars have different year zeroes and different month lengths. There may be a standard conversion function in your country but there does not appear to be one here in the UK. There is help online so you should be able to find a function that will perform the conversion.
You have a number of separate problems and it is unrealistic to expect someone else to have posted a complete solution to that set of problems or that someone will code a complete solution for you. You need to split your total problem into its components and create or look for a solution to each component.
You have strings that contain CE dates in the format “dd/mm/yyyy”. These dates could be surrounded by text. You give the example “dd/mm/yyyy ttt”. Can ttt contain spaces? Could the “ttt” come before the date? Could the string be as complicated as “aaaa bbbb cccc 12/11/2016 dddd eeee ffff”?
Whatever the situation, I suspect something like:
Dim Part() As String
Part = Split(.Cells(R, C).Value," ")
would be the core of first step. With my complicated example, this would give:
Part(0) = "aaaa"
Part(1) = "bbbb"
Part(2) = "cccc"
Part(3) = "12/11/2016"
: : : :
A loop over the parts of each cell value looking for a string for which IsDate gives True would allow you to find the date so .Cells(R, C).Value = Part(N) would delete the unwanted text.
I would take a copy of your data and try to code a macro that discards the unwanted text. If you can successfully create that macro, you have completed step 1 of your solution. If you have trouble with this macro, you can ask for help here and expect to get it.
The next step is to convert the string “dd/mm/yyyy” to an Excel date. Excel holds dates as the number of dates since 1/1/1900 CE. Replacing:
.Cells(R, C).Value = Part(N)by .Cells(R, C).Value = CDate(Part(N))ought to do the trick. However, Excel sometimes tries to interpret “dd/mm/yyyy” dates as “mm/dd/yyyy”. I think you will be alright but be aware of this possibility.
Your last step is to convert a date from the CE calendar to the Hijri calendar. This is not just a format issue. The two calendars have different year zeroes and different month lengths. There may be a standard conversion function in your country but there does not appear to be one here in the UK. There is help online so you should be able to find a function that will perform the conversion.

VBA dates collected correctly but output wrongly

I grab dates from one spreadsheet and output them onto another spreadsheet. After grabbing the date, when I debug.print it is in the correct format. When I output the date, debug.print also displays the correct format. However, the format on the spreadsheet the value has just been sent to, doesnt show the correct format.
I am using:
Sheets(SheetName).Cells(RowNum, ColNum).Value = Data
Sheets(SheetName).Cells(RowNum, ColNum).NumberFormat = "dd/mm/yyyy"
after I have pasted the value, but the months and days are still switched the wrong way.
Is there something I am doing wrong?? If I right click the cell it thinks it's date is dd/mm/yyyy but instead of 4th Sept it is showing 9th April.
This might be some trouble with localization:
Try using NumberFormatLocal, if DanielCooks tip didn't help ;)
edit: erlier it was statet by mister Cook, to check if the given data is correct.
edit:
With my german version I have quite some trouble to use / as the seperator, that is why i tryied with this code .NumberFormat ="dd-mm-yyyy;#" - works fine; I can switch days and month as I like.
edit:
With .NumberFormatLocal = "TT/MM/JJJJ" I have to use the german shorts for day, month and year, but now I can use / as the seperator.
You should experiment a litte bit with some formats strings ;)
Sorry to resurrect an old post, however I had a problem with VBA outputting a valid date as US style with the actual date changed for example 1st May changed to 5th Jan. I came upon this post but I didn't find the answer I needed here and now that I have worked it out I thought I would share it:
The key is not to define the variable storing the date as a "date" but as a "double", e.g.
Dim ReportDate As Double
ReportDate = Date
Range("E6").Value = ReportDate
This works as it outputs the numeric "date value" which excel then formats locally e.g. 41644 gets formatted as "05/01/14" using UK format or "01/05/14" using US format.
Hope this proves useful to other people (probably me when I forget how I solved it in six months time).
In the end I had to format the cell as "TEXT" to keep the correct format
(1) You need to define the variable to "Date" type to read the input, then set the date format before assigning it to the date variable.
(2) You also need to format the date output to make it work !
'**Read the date input****
Dim date1 as Date
Range("B2").NumberFormatLocal = "dd/mm/yyyy"
date1 = Range("B2").Value
'**Output the date****
Range("E2").Value = date1
Range("E2").NumberFormatLocal = "dd/mm/yyyy"

Resources