SSRS comparing dates in an expression - sql

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

Related

How to check the Year EDT lenght?

I created a Table's Field, and in addition to this, I created my custom EDT, named : MyEDT (for example).
MyEDT is INTEGER type and I have extended the System standard EDT YearBase.
So, if I insert the alphabetic characters (look like "abecjskjfh") I get an error.
But I need to have a rule, I want to insert only value with 4 Number character, I only want values look like : 2000 , 2006, 1982 etc... .
I can check/control this by code, in methods validateWrite or validateField I insered this code :
switch (p1)
{
case fieldNum(MyTable, MyField) :
if (strLen( (strFmt("%1",this.MyField)) ) != 4)
throw error ("Inser only value AAAA");
break;
}
But,It's possible or exist to creato or axtends the YEAR EDT with only 4 number char length ? Or, there is another way to check the length the field valu ?
Thanks all,
enjoy!
If you want to use an integer EDT, I think there is no way to restrict the range of allowed numbers, except the AllowNegative property. So you have to do the validation in code like in your question. But I would suggest to change your validation logic to validate a number range instead of casting the number to a string and then validating the number of characters. This way you could also make sure that users cannot enter a year like 0000.
if (this.MyField< 1900 || this.MyField > 9999)
{
throw error("Please enter a year between 1900 and 9999");
}
Another possibility could be to use a date EDT where you set the DateYear, DateMonth and DateDay properties such that only the year is shown. This would also help with data entry (e.g. 2 gets replaced with 2002) and gives you a nice error dialog if the users enters for example "abc".
You can use X++ match function.
match('<:d:d:d:d>','2004') would match all 4 digit string (0000-9999).
match('<[12]:d:d:d>','2004') would match string 1000-2999.
Alternate way is to use System.Text.RegularExpressions.Regex.IsMatch('1234', '^\d{4}$')

VB.Net Date.ParseExact Culture issue

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.

Compare string dates in vb.net

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.

Datevalue can't read december month

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.

SQL Search with parameter that could be date or could be string

I have a search box where you can enter plain text. The keywords are separated by spaces.
I check each keyword if it fits the format for a date and store 'all keywords' in one array and 'date keywords' in another. All the 'date keywords' are also in the 'all keywords' array, as I can not tell if its 'only' a date or maybe also a description or name. I search over many fields like name, description, etc...
I use something like
SELECT * FROM Tbl
WHERE NOT EXISTS(
SELECT * FROM #SearchItems WHERE NOT(
name LIKE SItem OR
description LIKE SItem OR
field3 LIKE SItem)
)
This searches for entries, where no searchitems exist, that are not found -> Means, it shows only items, where all searchitems are found in any field. I use these two 'NOT's because otherwise I would have to check if the count of found items = count of all items.
But now I have a problem with the dates. Because 10/05/05 is a date but could also be a number in the description. So I want to get all items where there is a 10/05/05 in one of the normal fields, or the date matches the specific date.
But if i add somehting like
AND NOT EXISTS(
SELECT * FROM #DateItems WHERE NOT(
date = DItem)
)
It means, that the item needs to have 10/05/05 as string in a field AND as date, but if I use OR, it means that all item with the right day will be shown, regardless of the other keywords. If I delete the 'date-keywords' from the 'all-keywords' it would not find the string in the description.
How to fix this? I want to get all items from the date, or with the date in description when I enter '10/05/05' but if I enter 'blue 10/05/05' blue has to be in one of the fields and 10/05/05 could be in a normal field OR the date.
Edit: I forgot to mention: In the 'all-keywords' array, the dates are in original format like '10/05/05'. The keywords realized as dates are stored in the 'date-keywords' array in ISO format '2005-05-10'. So i cant do something like WHERE DItem = date OR description like DItem.
As this is a bit hard to describe, please ask if anything is unclear.
Thanks for any help.
I found a solution. And because it took me a good while to get to this soltion i will write it down here, so someone will maybe get help from it.
Since a possible date also should be a regular search string, the search fails when this string is not found. The only exception is when the interpreted date of the string matches the date of the item (in which case the string representation does not need to be found somewhere). But to do this you need to know which 'date-keyword' belongs to which 'all-keywords' search string.
If you have this relation, it is possible to accept an item if the string representation is found OR if the date matches.
So now i load the dates with their string representations into a table and have a simple
OR relation between them: WHERE Date = DateItem OR Field = StrItem.