What I need (alphabetical numbering of rows-highlighted in bold(serial column)):
I have tried converting the output of rownumber function into string, But nothing seems to work as I don't have any idea.
Please help!
You can do this with a bit of custom code.
Go to the Report Properties, click the "Code" tab and paste the following code into the custom code window.
Public Function GetRowLetter(RowNum As Integer) As String
' stick the RowNum in a variable that we can reduce until it's zero
Dim r As Integer
Dim i As Integer
Dim s As String ' holds result
s = ""
r = RowNum
' we start at the right side so if the rownum is 28 we want to be back AB
' need to get 'B' first
Do While RowNum > 0
r = Int((RowNum - 1) / 26)
i = (RowNum - 1) Mod 26
s = Chr(i + 65) & s
RowNum = r
Loop
GetRowLetter = s
End Function
This will give "A" for 1, "B" for 2 etc, then it will give "AA" for 27, "AB" or 28 etc...
If you want to return lower case letters instead, swap the 65 for 98
In your report set the textbox value expression to
=Code.GetRowLetter(RowNumber("myDataSetName"))
swap out myDataSetName with the name of your dataset or scope you want to apply it to. Remember the dataset and scope names are case sensitive and must be surrounded by quotes ( " )
Phased Budget
Pretty new to all this.
I'm building a report in SSRS with multiple datasets.
The report has 12 trading periods and an Annual Total.
I've added a total line which sums the budget for 2 datasets using an expression.
The total works fine for the Annual Total but not for any of the periods. It just shows the annual total in each month.
What am I doing wrong?
You can use custom code to store DataSet1 values to an array and then use the stored values to calculate net margin.
Add the following custom code to your report
Dim i1 As Integer
Dim i2 As Integer
Dim sumarray(12) As Decimal
Public Function setSum(ByVal v As Decimal) As Decimal
sumarray(i1) = v
i1 = i1 + 1
Return v
End Function
Public Function getSum() As Decimal
i2 = i2 + 1
Return sumarray(i2-1)
End Function
For your gross margin monthly(dataset1) total use the expression:
= Code.setSum( SUM(Fields!Bud.Value) )
For your net margin monthly total (dataset2) use the expression:
= SUM(Fields!Bud.Value) + Code.getSum()
On a MS Access Table, I would like to have a column that has the first day of the following quarter based on a date in another column.
For example, I have a Start_Date column with a value of 2018-02-04, I would like the record on that column to show that the following quarter would start on 2018-04-01.
I have this working fine in Excel using the following formula:
=DATE(YEAR(M2),((INT((MONTH(M2)-1)/3)+1)*3)+1,1)
In Access, I added the column choosing Calculated Field > Date/Time, but could not figure out a way to get it to work like an Excel.
Has anyone tried this before or know of a possible solution? Thanks
You can use this function:
Public Function DateNextQuarterFirst( _
Optional ByVal datDateThisQuarter As Date) As Date
Const cintQuarterMonthCount As Integer = 3
Dim intThisMonth As Integer
If datDateThisQuarter = 0 Then
datDateThisQuarter = Date
End If
intThisMonth = DatePart("q", datDateThisQuarter) * cintQuarterMonthCount
DateNextQuarterFirst = DateSerial(Year(datDateThisQuarter), intThisMonth + 1, 1)
End Function
To use it in a query with SQL similar to this:
Select *, DateNextQuarterFirst([Start_Date]) As NextQuarterFirst
From YourTable
New to SSRS 2012 & struggling.
I have a report - containing a subreport - on client data. When testing with one client (just to make sure everything was OK) it works perfectly.
When the filter's removed, it's timing out (it's actually saying it's been cancelled by the user, which it hasn't).
Obviously the inclusion of the subreport is the problem (as the main report runs fine without it).
My subreport can validly return multiple records per client. The subreport is grouped on ClientId. I then have a calculated field - say HasIP - that concatenates two fields (IC and PC ) to produce either YesYes or YesNo. The tablix is sorted by HasIP by Z to A.
The info in the ClientID footer are what I'm displaying.
ClientID HasIP
22 YesNo - has two records, but since it has a YesYes, I don't want this one
22 YesYes - has two records, but I want the this one
52 YesYes - may only have 1 record, I want this record
76 YesNo - may only have 1 record, I want this record
Theoretically a client can't have more than one instance of HasIP=YesYes & shouldn't have more than 2 records. How can I recreate this effect in Query Designer? Essentially if HasIP=yesyes, use that record, otherwise use the other record
If I can do this, I can then drop the subreport completely, add this dataset to my main report & use Lookup to get the data.
However, the way our report scenario is set up, I'm not permitted to change the query [I have to click Query Designer button in Dataset Properties] & I have no experience in MDX.
SOLVED!!!:
OK - here's what I've come up with.
Assign numeric order to IC and PC values
I concatenated the IC & PC field values together and assigned values and added the ID of the records in the original subreport. I called this field HasIP
=Switch(Fields!IC.Value+Fields!PC.Value="YesYes", 1,
Fields!IC.Value+Fields!PC.Value="YesNo", 2,
Fields!IC.Value+Fields!PC.Value="NoNo", 3) & "-" & Fields!R_Name.Value
This left me with 2-xxxx, 1-yyyy etc.
I then added a filter to my second dataset:
=Left(Fields!HasIP.Value, 1)
to exclude values of "NoNo"
Concatenate HasIP and other fields in Dataset2 (to be used by LookupSet)
In addition also had to convert the text values into code for output (eg Yes = 1, No = 2, Unknown = 3 etc). I did this by creating a calculated field in Dataset2 (in the report, not the query) which included the HasIP. I delimited HasIP from the value by using a dollar sign.
=Fields!HasIP.Value & "$" &
SWITCH(
left(Fields!CoR.Value, 1)="C", 1,
Left(Fields!CoR.Value, 1)="N", 2,
True, ""
)
This left me with 2-xxxx$2, 1-yyyy$1 etc.
Sort the LookupSet results
LookupSet creates an array (and yes, now you know too). I needed to sort this so that the one I'm after is the first value returned. This is achieved by copying and pasting the following into the custom code section of your report. (I've added the code to allow you to sort in reverse if you need it).
Function JoinSorted(m_Array As Object()) As String()
System.Array.Sort(m_Array)
' Array.Reverse(m_Array) 'uncomment this line if you want to sort in reverse
Dim k As Integer = 0
For i As Integer = 0 To m_Array.Length - 1
If i > 0 AndAlso m_Array(i).Equals(m_Array(i - 1)) Then
Continue For
End If
m_Array(k) = m_Array(i)
k += 1
Next
Dim fred As [String]() = New [String](k - 1) {}
System.Array.Copy(m_Array, 0, fred, 0, k)
Return fred
End Function
You call this by using the following in your report expression:
Join(
Code.JoinSorted(
LookupSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!YourField.Value,"Dataset2")
),""
)
So, regardless of how LookupSet wanted to return the array, I always got 1-yyyy$1 first.
Handling LookupSet output on the report - include default for no records
For some LookupSet results in the report, I needed return a default value if there were no records returned. Otherwise I needed to return the assigned value (1, 2, 3 etc). If found two ways to do this.
This checks to see if the array count [yes, by using length] is greater than zero. If so, then using a mid function on the array result to return the 14th character:
=SWITCH(
LookupSet(
Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2"
)
.Length=0,
2,
LookupSet(
Fields!Main_ID.Value, Fields!Main_ID.Value, Fields!Record_Name.Value, "Dataset2")
.Length>0,
1)
OR
This is the same:
=iif(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Main_ID.Value,"Dataset2"
).Length>0,
Mid(
Split(
Join(
Code.JoinSorted(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Main_ID.Value,"Dataset2")
)
,";")
,";").GetValue(0)
, 'start point of mid
InStr(
Join(
Code.JoinSorted(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Main_ID.Value,"Dataset2"
)
)
,";")
,"$")
+1,
1),
"2"
)
Handling LookupSet output on the report - using of MID when length of value varies
In some cases the value I needed to return varied in length, eg 2 or 10. I also needed to return nothing if the LookupSet didn't return any results. I couldn't use "normal" versions of MID like this:
Mid(
Join(Code.JoinSorted(
LookupSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12d.Value,"Dataset2")),
";"),
InStr(
Join(
Code.JoinSorted(
LookupSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12d.Value,"Dataset2")
),
";"),
"$")+1,
(
InStr(
Join(
Code.JoinSorted(
LookupSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12d.Value,"Dataset2")
),
";"),
";")
-
InStr(
Join(
Code.JoinSorted(
LookupSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12d.Value,"Dataset2")
),
";"),
"$")
- 1)
)
as it threw #ERROR due to the use of -1 (at the end) making the string a negative length for some records.
So, here is what I could use:
=
Mid(
Split(
Join(
Code.JoinSorted(
LookupSet(Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12b.Value,"Dataset2")
),
";"),
";").GetValue(0)
,
InStr(
Join(
Code.JoinSorted(
LookupSet(
Fields!Main_ID.Value,Fields!Main_ID.Value,Fields!Q12b.Value,"Dataset2")
),
";"),
"$")
+1,
1)
By doing this, I could get the results I was after in the details & the footer.
I hope this can help someone else.
I have the following sub in Access 2003 to return the hours elapsed bewteen two datetime fields.
Function DateDifferenceHour(dateStart As Date, dateEnd As Date) As String
'Outputs Hours from two dates
Dim age_hour As Double
age_hour = DateDiff("h", dateStart, dateEnd)
DateDifferenceHour = age_hour
End Function
If I have the following: DateDifferenceHour("07/23/2005","07/23/2005 7:30:00 PM").
It correctly returns 19 hours, but in reality, the time elapsed is 19 hours and 30 minutes.
How can I modify it so it can round off to 20 hours?
Edit:
My original suggestion was "Compute the difference in minutes, divide by 60, and round the quotient to zero decimal places". However, #Jean-François Corbett showed me the limitation of that approach.
? DateDifferenceHour("07/23/2005 7:00:59 PM","07/23/2005 7:30:00 PM")
1
IOW my first attempt rounded a duration of 29 minutes and 1 second up to 1 hour, which is no good. So instead I suggest using the difference in seconds and dividing by 3600.
Function DateDifferenceHour2(dateStart As Date, dateEnd As Date) As String
'Outputs Hours from two dates
DateDifferenceHour2 = _
Format(DateDiff("s", dateStart, dateEnd) / 3600, "0")
End Function
? DateDifferenceHour2("07/23/2005 7:00:59 PM","07/23/2005 7:30:00 PM")
0
There is still the issue of which rounding approach you want.
I chose Format() thinking you would want 2.5 hours rounded up to 3.
The VBA Round() function uses round-to-even, so Round(2.5, 0) would give you 2.
We don't know which you want; you can tell us. Also, dateStart and dateEnd imply dateStart will not be greater than dateEnd. However, if it can be, consider how you want a negative duration "rounded" to the nearest hour. Here are some examples copied from the Immediate Window.
? Round(-2.5, 0)
-2
? Round(-1.5, 0)
-2
? Format(-2.5, "0")
-3
? Format(-1.5, "0")
-2
This works, without any unexpected rounding (aside from the precision of the Date type itself).
Function DateDifferenceHour(dateStart As Date, dateEnd As Date) As String
' Rounds .5's to nearest even integer.
'DateDifferenceHour = CStr( Round( _
' CDbl(dateEnd - dateStart) * 24 ) )
' Rounds .5's up.
DateDifferenceHour = Format( _
CDbl(dateEnd - dateStart) * 24, "0" )
End Function
I put two rounding options so that it rounds to whole numbers; pick your favourite. It's way better programming practice to round explicitly and transparently than having DateDiff implicitly apply its unusual rounding.