In my RDLC report I want to show my data grouped by a particular column. Here is the fields of the dataset that are returned by the method
Module name, Documentation date, Walk Date, Flushing date, Testing Date
I want to show in my report module wise how many items are Documented, Walked, Flushed, Tested. How I can do that?
I have tried to create Parent group on Module name but doing so repeats multiple lines per group ( as many lines as there are for that particular group), but I just want to show count of Documentation, Walk, FLushing etc) against each module.
Assuming that you want to count the number of non-NULL records for the Date fields in SSRS, you can use the ISNOTHING function to check each field:
=SUM(IIF(ISNOTHING(FIELDS!DocumentationDate.VALUE), 0, 1))
This just checks the field and counts the record as 1 if it's not null.
Related
I am currently trying to report on stock quantities with a timeframe for each item in stock;
Stock at the selected minimum date within the timeframe
Stock at the selected max date within the timeframe
I have a single quantity field of an item from a transaction which I am adding to my report twice however both with differing formulas under select expert.
Stocks.Date = MINIMUM(Stocks.Date)
Stocks.Date = MAXIMUM(Stocks.Date)
I've grouped by product and have all fields in the group header. I have tried looking online for solutions but I haven't found anything that really solves the problem. If you need more information please ask, this is wrecking my brain.
Essentially what I want is(for each stock item):
Quantity field1:
SELECT Stock.Quantity WHERE Stock.Date = MINUMUM(Stock.Date)
Quantity field2:
SELECT Stock.Quantity WHERE Stock.Date = MAXIMUM(Stock.Date)
Hope this helps clarify what I'm after
Create two SQL expression fields:
// {%MIN_DATE}
(
SELECT MINIMUM(Date) FROM Stock
)
// {%MAX_DATE}
(
SELECT MAXIMUM(Date) FROM Stock
)
Then reference them in the record-selection formula:
{Stock.Date} IN [{%MIN_DATE},{%MAX_DATE}]
You can't include Crystal's aggregate functions in the record selection formula because it is self-referential. It's like saying "define set A as the largest element of set A". In your case, you're effectively saying, "Only include records in my report where the date is the most recent record in my report"... doesn't make sense.
Instead, you have to include all records and only "process" the ones where {StockSales.Date}=maximum({StockSales.Date},{StockSales.ItemID}). You can accomplish this by comparing the date of each record to the maximum date for that item ID and saving the stock quantity off in a variable if it is a match. You can then display the variable in the item's group footer.
The first step is to move all your Group Header 1 elements into Group Footer 1 instead. Then you'll need to create 2 new formulas to manage the variable:
//{#Update variable}
// Place this formula in the Details section
whileprintingrecords;
numbervar qty;
if {StockSales.Date}=maximum({StockSales.Date},{StockSales.ItemID})
then qty := {StockSales.Quantity}
//{Display variable}
// Place this formula in the Group Footer 1 section where you want the quantity to display
whileprintingrecords;
numbervar qty;
If your aim is to show the max and min in the report, then you can try the below Steps:
Go to the Group field, Right Click on the object ->Format Object->Display String-> Give the Formula:
CStr (Maximum ({Stocks.Date}));
To show both min and max in the same report, drag the Date field twice into the report and for one object give Minimum Date another with Max date.
For Maximum: CStr (Maximum ({Stocks.Date}));
For Minimum : CStr (Minimum ({Stocks.Date}));
Your Select Expert doesn't make any sense to me.
You are retriving the records from Min Date to Max Date in other words you are retriving the whole table data in to your report in this case what is the use of select expert.
If you don't mention any thing in select expert then also you can whole table data.
If you really want to filter some data then provide some paramters to the user so that you can filter in those parameters then your select expert will become something like.
Stocks.Date>={?StartDate} and Stocks.Date<={?EndDate}
If my understanding is wrong then edit the question clearly with your requirement.
Edit-------------------------------------------------------------------------------------
In this case don't use select expert, Do calculations in your report itself in formula fields.
create a formula as:
#Minimumn
if Stock.Date = MINUMUM(Stock.Date)
then <Stockitemahere>
For Maximum create another formula as:
#Maximum
if Stock.Date = MAXIMUM(Stock.Date)
then <Stockitemahere>
Place both formulas on design part of the report.
Take care date filtering shouldn't be in select expert
I am working on a Order (MVC) system where the orders transition to different states, i.e new order, paid, shipped, etc. Each state can have multiple transitions. Originally I thought I would have a status table with an ID and Description and then a transition table that would have current status and transitions status, with each transition on a single row. In order to populate a selection box, I would have to do the join to get the descriptions. Now I am thinking I could do it all in one table and add a comma separate column which would list the possible transitions. Is this a good idea or is there a better way?
Any RDBMS promotes database normalization, There are 6 forms of database normalization. Normally if you can get to first three it is good enough.
The first Normal Form states: you should have only one piece of information in a column and a column should store on one piece/Type of information.
Now if your case when you are try to save a comma deliminited list of transitions. if you have to pick only record with a particular type of transitions state?? it will be a messy query.
Also imagine a scenario where you have to update a column for a particular record when transition state is changed, again a very messy , error prone and performance killer query.
Therefore follow the basic rules of Database Normalization, and stick to your 1st which was to create a separate table and use IDs to define transition state, and add a new row whenever a transition changes.
My Suggestion
Simply Have one column for [current status] and one Column for [transition], add a new row everytime any of the values change.
Also a datetime column with default value to current datetime. Which will allow you to go back in history and see different status and transition states of a record in point in time.
Have only one column in only One table which stores this information reference this column in other tables if you need to.
I'll separate this post in 3 sections to be as clear as possible. The first one will be informations you need to know. Second one will be the solutions I tried so far to get this working. Third section will be the questions. I also have to precise that's the first time I'm using CrystalReports.
Informations
I'm currently working with Visual Studio 2010 with C# and I'm using SAP Crystal reports. I'm displaying the data using MySQL database.
Now, here are the tables I use to display the report:
Table : orders
Fields : id(primaryKey), date(DATE), quantity(INT), fksizes(INT), fkclients(INT)
Table : sizes
Fields : id(primaryKey), name(VARCHAR(30)), price(FLOAT)
Relationship between these 2 tables : orders.fksizes with sizes.id
Basically, I'm passing a range of dates as parameters to the Crystal Reports to display informations only between those dates. Then, I created 2 parameters : StartDate and EndDate both of type Date.
What I've tried
Here's the original query I'm using to display what I want without the date range condition :
SELECT sizes.name, SUM(orders.quantity) AS totalQty,
(SUM(sizes.price) * orders.quantity) AS totalPrice,
orders.date
FROM orders
INNER JOIN sizes ON orders.fksizes = sizes.id
GROUP BY sizes.name, orders.date
This query works correctly and display the total quantity sold and the total price for each size name. At the report's footer, I'm using a Summary field in which I got the total sum of all totalQty named sumTotalQty. I have another field for the same purpose for totalPrice named sumTotalPrice.
I have 2 rows of data test which are :
Size name Quantity sold Total Price
------------------------------------------------------------------------------
Big 2 $6.00
XBig 7 $28.00
The field sumTotalQty displays 9 and sumTotalPrice displays $34.00 which is exact results. I have to precise that the first row has 2013-10-29 as value for orders.date and the second one 2013-10-30.
Now, I want to select a range of dates for which I want to display the results. As an example, I select from 2013-10-30 to today, I should get only the second row with sumTotalQty displaying 7 and sumTotalPrice displaying $28.00. I got the single row correctly displayed, but sumTotalQty displaying 9 and sumTotalPrice displaying $34.00 which are incorrect following the date range.
I then tried to add a WHERE clause to my sql query to specify the date range like this (in Database --> Database expert...):
SELECT sizes.name, SUM(orders.quantity) AS totalQty,
(SUM(sizes.price) * orders.quantity) AS totalPrice, orders.date
FROM orders
INNER JOIN sizes ON orders.fksizes = sizes.id
WHERE orders.date BETWEEN '{?StartDate}' AND '{?EndDate}'
GROUP BY sizes.name, orders.date
I got no result displayed with it. So, I think {?StartDate} and {?EndDate} are just not set but I'm really not sure. The same goes for WHERE orders.date BETWEEN #StartDate AND #EndDate.
Questions
Why aren't {?StartDate} and {?EndDate} set even if I have entered a date range when I'm prompted to give them ?
With the original query (without the WHERE clause), how can I get the right result in my summarize fields with the date range given ? It's like it sums from the database and not from the report fields.
EDIT
After many searches, 2 other questions came in my head :
Is it possible to add DateTimePicker in the report so the user will be able to enter a starting date and an end date easily ? The report would be refreshed automatically after that.
Is there a way to create or use Crystal Reports events (OnLoad, AfterLoad,...) ?
Thank you for all help I'll get.
Question 1: You either use BETWEEN (? AND ?) or BETWEEN (#StartDate AND #EndDate)
Question 2: You would have to group your data and then use totals in your report.
Edit: After discovering that the issue is with the parameter declaration, I suggest taking a look at some of the following posts:
http://www.dotnetperls.com/sqlparameter
Why do we always prefer using parameters in SQL statements?
Do some more research and you will find lots of info on the net. What I would suggest is to add some input boxes (TextBox, DateTimePicker, etc.) to your page where the user can input the parameter values and then pass them programmatically to the report. That way you can pass the parameters to the SQL statement and get the correct data to your report. You also won't need parameters in your report.
As far as CR events go, there is the Init event, which is public
http://msdn.microsoft.com/en-us/library/aa691447(v=vs.71).aspx
and then there are some Viewer events that could be useful
http://msdn.microsoft.com/en-us/library/ms227097(v=vs.80).aspx
I have developed an eCommerce application in C# and ASP.Net. For the Admin users "dashboard" landing page, I would like to give them a GridView that shows them the total sales dollar amount for a couple different time ranges, these would be my columns (ie last day, last week, last month, last year, total ever). I would like to give these values for orders that are in different status' (ie complete, paid but not shipped, in progress). Something similar to this:
|OrderStatus|Today|LastWeek|LastMonth|
|Processed |$10 |$100 |$34000 |
|PaidNotShip|$4 |$12 |$45 |
My question: What is the best/most efficient way to do this? I know that I could write separate SQL statements and union them together and bind the gridview to a sqldatasource:
(select amountForYesterday, amountForLastWeek from sales where orderStatus = processed)
UNION
(select amountForYesterday, amountForLastWeek from sales where orderStatus = paidnotshipped)
But that seems like a pain and very inefficient, since I would effectively be writing a separate query for each value.
I could also do this in the .cs page behind on load and programmatically populate the grid view row by row.
This GridView would only show information for the user's specific organization, so it would have to filter based on that as well.
I'm kind of at a loss as to how to do this without writing a massive query and continually hitting that query and database each time the page is viewed.
Any ideas?
I prefer using LINQ to work with data and/or GridViews (accessing the rows etc.). Have a look at a project I have on GitHub, which does exactly what I am mentioning here, as example. Note that this is just a sandbox I used previously for illustration purposes.
GitHub Repo
https://github.com/pauloosthuysen/int
Other useful info:
http://www.codeproject.com/Articles/33685/Simple-GridView-Binding-using-LINQ-to-SQL
The Sales etc. for LastWeek and LastMonth does not change very often. You could store that in a static Dictionary indexed by organization or summarize it in a separate table for faster access. This way you will not need to select the same huge amount of rows to get the same numbers over and over again. Unless special demands I would stick to the Dictionary solution because it is simple but a combination could also be a good solution
There is no direct way of doing it.
However instead of hitting the DB to the sum of every columns, you can perform the stuff using you datatable which is used for binging to your grid.
All you need to do is use
Dim iSumSal As Integer
iSumSal = StudentTable.Compute("SUM(sal)", "")
similarly you can perform for other columns.
once this is done. then just add a new row to you data table with all the summed values in it.
And then you can bind it to your grid.
optional - you can put some text value in the first column of you new row as "Total:"
thanks
rahul
crystal reports formula field
Good day,
I am making a sales report on Crystal Report - VS2010 c#
I have this view in MS SQL
vSales
OrderNo
OrderDate
Amount
PaymentType
Payment type can either be Cash or Check
I performed select all because I need both in the same report
so how do I get the sum of Amount where PaymentType is equal to cash?
I used Sum for my total Amount, both check and cash, in the formula workshop
Sum ({vDailySales.Amount})
I can't modify my SELECT statement because I need all the record with cash & check payment
Create two formulas - CashAmount and CheckAmount, for example second one:
if {vDailySales.PaymentType}="cheque"
then {vDailySales.Amount}
else 0
On report, use aggregates of said formulas - like Sum({#CashAmount}).
There are two ways I would use; depending on what output I wanted.
The first way, and the simplest would be group on the payment type. Then create a sum in the footer of the group. You can use the "Running Total" tool or use the code below.
SUM({vDailySales.Amount}, {vDailySales.PaymentType})
This will show a result for each of the payment types, so in your case twice, once for cash and once for cheque.
I think through here you can use formulas in the "Evaluate" section of running total; where you would use a true/false statement for what you wanted to show. The statement for "cash" for example would be:
if {vDailySales.PaymentType}="Cash" then true else false
The other method, which would be simpler if you wanted a grand total would be to use a conditional sum.
Define the variables in the header:
SHARED numbervar sumcash;
SHARED numbervar sumcheque;
sumcheque:=0;
sumcash:=0;
Then for each line in the report; add a field to conditionally sum the amounts; using a formula like:
SHARED numbervar sumcash;
SHARED numbervar sumcheque;
if {vDailySales.PaymentType}="cheque" then
sumcheque = sumcheque + {vDailySales.Amount};
else
sumcash = sumcash + {vDailySales.Amount};
Then at the bottom of the report, make a formula to display each of the variables seperately.
A third option is to use a running-total field. Because of how they are calculated, they need to be in a footer section.
To create one, follow these steps:
select the {vDailySales.Amount} field on the canvas, right click, then select Insert, Running Total...
Set the Running Total Name field as appropriate, perhaps 'Sum of Cash'.
Ensure that the Type of Summary is 'sum'.
Select the 'Use a formula' option, click the conditional-formula button, then enter the following as the formula's text:
{vDailySales.PaymentType}="Cash"
Select 'Never' for the Reset option or 'On change of group' (selecting the appropriate group) if this RT field will tally an amount by group.
Place field in the Report Footer section.
Repeat the process for a second running-total field that will summarize cheques (change step 4 to reference "Cheque" instead of "Cash".