I am using vb.net and I create a list of months (3 char representation) by using the following function.
Public Function getMonths() As Array
Dim months As String = ""
For i = 1 To 12
months += StrConv(MonthName(i, True), VbStrConv.ProperCase) + ","
Next
months = months.Substring(0, months.Length - 1)
getMonths = months.Split(",")
End Function
This works beautifully, as the site I am building can change language etc on the fly.
However when I try to then change the month back to the numeric value to process using this function
Public Function monthToNumber(ByVal monthin As String, ByVal culture As System.Globalization.CultureInfo) As Integer
monthToNumber = DateTime.ParseExact("01/" + monthin + "/1999", "dd/MMM/yyyy", culture).Month
End Function
, the date.ParseExact throws an exception of date input is not in a valid string.
The month is being produce by the culturalisation, so I can't understand the failure. This only happens with a culture of {pt-PT}. The process works fine for spain, uk, france,italy.
If you use DateTime.ParseExact, you have to use the right DateSeparator.
For pt-PT, it's not /, but -.
/ can work as default DateSeparator, but only if you use CultureInfo.InvariantCulture. But if you do, you can't parse the culture specific date abbreviation.
That's why your code fails.
To generate the month abbreviations, simple use DateTimeFormatInfo.AbbreviatedMonthNames or DateTimeFormatInfo.AbbreviatedMonthGenitiveNames; no need to write a method yourself.
Also, you should look into String.Join (another thing you don't have to reinvent).
For parsing the string back, you could use something like
monthToNumber = DateTime.ParseExact(monthin, "MMM", culture).Month
No need for day/year if you simply use MMM for your format string.
Related
I have some basic expressions to highlight certain fields:
=IIF(Fields!Failure.Value > 0, "Red", "Transparent")
However, I have another field that contains dates in the following format:
22/08/2016 22/08/2016 - each field can contain multiple dates.
This is stored in SQL as a VARCHAR.
I need to run a similar expression in my report to achieve the following:
If the date is 1 day older than the date the report is run, highlight the field. If the date is greater than 1 day older, highlight the field a different colour.
I#m familiar with basic expressions, but I can't think of an easy way to obtain the current date, and then compare between the two.
As others have said, you really shouldn't be using hacks like this...
But, this should work for you:
=iif(Len(Replace(Replace(Fields!DateField.Value," ",""), Format(Today, "dd/MM/yyyy"),"")) = 0, "Transparent" ,iif(Len(Replace(Replace(Replace(Fields!DateField.Value," ",""), Format(Today, "dd/MM/yyyy"),""), Format(Today().AddDays(-1), "dd/MM/yyyy"),"")) = 0, "Green", "Red"))
Essentially, remove the joining character (in this case, space) and then replace all instances of the current date in the given format. If there are any characters left, you have a date that doesn't match today. Then take that value and repeat for any instances of yesterday.
Obviously this will fall down if your date formatting changes.
But then you already knew that comparing dates as strings was a bad idea, right...
You can use the Split function to generate an array of values. Of course, you'll still need to select one of those to test. The following may get you going again.
=Iif(
CDate(
Split(
"21/08/2016, 22/08/2016",
","
).GetValue(0)
) < Today,
"True",
"False"
)
If, however, you are dealing with a date string that can contain any number of dates and you to test all of them then a simple SSRS expression won't handle that. Fortunately we can use a bit of custom code.
Right-click the report background and select report properties. Click the 'Code' item and paste the following into code box
Public Function TestDate(DateString As String) As String
Dim DatesArray() As String = Split(DateString)
Dim ReturnValue As String = "Transparent"
For Each d As String In DatesArray
If Date.Parse(d) = DateAdd(DateInterval.Day, -1, Date.Today) Then
ReturnValue = "Red"
End If
If Date.Parse(d) < DateAdd(DateInterval.Day, -1, Date.Today) Then
ReturnValue = "DarkRed"
End If
Next
Return ReturnValue
End Function
Now change the expression as below
=Code.TestDate("21/08/2016 22/08/2016")
I've used Date.Today in the VB to restrict the comparison of the date to the day. If you wanted to be more precise ie: the exact time, use Date.Now instead
I cannot control these circumstances at the moment so please bear with me.
I pull email addresses from a field called EMAIL_O, and sometimes they are completely valid (somename#domain.com) and other times they have a 12-character phone number appended at the front (123-456-7890somename#domain.com).
How can I, in MS Access, detect which type of field I am seeing and remove the phone number appropriately when pulling in this data? I cannot just take the mid() from the 13th character because if the email is valid, I'd be removing good characters.
So somehow I need to detect the presence of a number and then apply the mid(), or just take the full field if no number is present.
Use pattern matching to check whether EMAIL_O starts with a phone number.
EMAIL_O = "123-456-7890somename#domain.com"
? EMAIL_O Like "###-###-####*"
True
EMAIL_O = "somename#domain.com"
? EMAIL_O Like "###-###-####*"
False
So you can use that strategy in an IIf expression. Apply Mid when EMAIL_O matches the pattern. Otherwise, just return EMAIL_O unaltered.
? IIf(EMAIL_O Like "###-###-####*", Mid(EMAIL_O, 13), EMAIL_O)
somename#domain.com
Those were examples copied from the Immediate window. If you want to use the same approach in a query ...
SELECT IIf(EMAIL_O Like "###-###-####*", Mid(EMAIL_O, 13), EMAIL_O) AS email
FROM YourTable;
Using the Left and IsNumeric functions you can just check to see if the first character is numeric, something like that is below. (Untested code).
Public Function CheckEmail(strEmail As String)
If IsNumeric(Left(strEmail, 1)) Then
strEmail = Right(strEmail, Len(strEmail - 13))
CheckEmail = strEmail
Else
CheckEmail = strEmail
End If
End Function
You can use regular expressions to get this done. Assume the number format in front of the email has a dynamic length you would not be able to start from 13th char as you suggested. Try pattern matching and replacing using RegEx. This would eliminate the entire string finding/cutting/joining operations
Try this:
Public Function FN_GET_EMAIL(iEmail As String) As String
Const mPattern As String = "^[0-9_-]+[0-9_-]"
With CreateObject("vbscript.RegExp")
.Pattern = mPattern
.Global = True
FN_GET_EMAIL = Nz(.Replace(iEmail, ""), "")
End With
End Function
sample results:
?FN_GET_EMAIL("123123123-123123123123-1231231231231EmailWith1123123Number#domain.com")
EmailWith1123123Number#domain.com
?fn_get_email("123-456-7890somename#domain.com")
somename#domain.com
in addition you can add a proper email validation or even change the pattern as per your needs without doing a complex string operation.
You could check for a numeric header:
If IsNumeric(Replace(Left(Nz([Email]), 12), "-", "")) Then
' chop 12 chars
Else
' use as is
End If
Hi in my program i am converting the dates in string for my application purposes. I want to compare those strings to see if the dates have the appropriate difference between them. Example date1 = "07/02/2015 12:12:000" and date2 = "08/02/2015 16:15:000". How can i compare for starters only the year value without parsing the string to date. Thanks in advance.
I have tried with .Length -something but with no luck at all.
Convert to DateTime objects and then use the normal arithmetic operations to compare them.
dim d1 = DateTime.Parse(input1); // Use ParseExact or more control
dim d2 = DateTime.Parse(input2);
If d1.Year != d2.Year Then
' years do not match
End If
' or even...
If (d1 - d2).Days > 365 Then
// more than a year apart (modulo leap years)
End If
Meta comment: I know you said "without parsing", but unless you have a really good reason (and tell us) and sensible answer will be to parse: because it is much easier and far easier to get right.
I work on a macro vba which manipulate different dates.
I have an incomprehensive error with Decembre. For exemple
DateValue("11-NOV-14")
return : 11/11/2014
DateValue("11-DEC-14")
return an error type '13'
I already try to put the string into a var and pass it to DateValue but same results.
Maybe i can get around this problem but i want to know why i have this mystic error.
Thanks for your help.
Your is a system-dependent problem. The month of November passes well because, in French, November = Novembre so "11-NOV-14" is equal to the English version.
However, "Décembre" is different because it has an accent on the second letter. In fact, on a French system, this will be ok:
a = DateValue("11-DéC-14")
while this will be not:
a = DateValue("11-DEC-14")
To avoid this problem and make the code "language-independent" (without asking the user to change the date formatting from the Control Panel), I think you should add a function that translate dates from string to date values:
Function MyDateValue(ByVal myDate As String) As Date
myDay = Left(myDate,2)
myMonth = Right(Left(myDate,6),3)
Select Case myMonth
Case "JAN":
myMonth = 1
'etc.
End Select
myYear = Right(myDate,2)
MyDateValue = DateSerial(myYear,myMonth,myDay)
End Function
So, you will be able to use myDateValue rather than DateValue and will make sure that it will work with your input data whatever will be the system language.
I have a table called documents one of the fields is called location which shows the file path for the document. I need to change it from D:\........ to H:\.....
How can I do this using update in sql as the file paths vary in length and there are lots of records
You can use string helper function to achieve the same. Something like below
UPDATE documents SET location = 'H:' + Mid(location, 2, Len(location) - 2)
WHERE Left(location, 1) = 'D'
Here, Len() function returns the length of the string literal
Left() function returns 1 character from the left of the string literal
Mid() function give you substring from a string (starting at any position)
See MS Access: Functions for more information on the same.