Crystal Reports Date by Year Comparison on a Running Total - crystal-reports

I am using Crystal Reports XI R2.
My table has transaction data by date. I have a group set up by day and a summary to give a count of transactions for each day. I also have a running total set to give a year to date count for each day. Of course it resets on a change in year.
My goal is to be able to find the difference between the YTD count yesterday and the same for the same date last year.
Edit: I've misstated the goal. It isn't to be able to find the difference for just yesterday, but for each day in a range of days.

Create these two formula fields:
//{#LastYearToDate}
If {table.dateField} IN LastYearYTD Then
1
Else
0
//{#ThisYearToDate}
If {table.dateField} IN YearToDate Then
1
Else
0
Insert a summary on each field in the ReportFooter section.

I finally got this nailed down. There is likely a cleaner way of doing this, but....
I converted the dates (started as text yyyy-mm-dd) into text mm/dd/yyyy format:
stringvar yyyyear := {table.dateField}[1 to 4];
stringvar mmonth := {table.dateField}[6 to 7];;
stringvar dday := {table.dateField}[9 to 10];
mmonth + "/" + dday + "/" + yyyyear
Grouped by this field and inserted a count summary into the group header. Created a separate field for the mm/dd portion of each date:
{#textDate}[1 to 5]
Added a flag to see if the date in the current group header matched the previous:
if previous({#mm/dd}) = {#mm/dd}
then 1
else 0
Used a shared variable to store the YTD totals for each year (2 formulas):
shared numbervar totalsCurentYear;
if {#prevDateFlag} = 1 then
totalsCurrentYear := totalsCurrentYear + Sum ({#transactionCount}, {#textDate});
totalsCurrentYear
|
shared numbervar totalsLastYear;
if {#prevDateFlag} = 1 then
totalsLastYear := totalsLastYear + Sum ({#transactionCount}, {#textDate});
totalsLastYear
Put both of these into the group footer (suppressed) and added a field to do the subtraction into the group header.

Related

Find percetage in Crystal report

Hi I'm new in crystal reporting, i would like to make percentage for annual year growth based current year with the previous year.
For example, I would like to check the growth for CMP4 for current year (2017) and previous year (2016).
CMP_vc_Code,InvYear,Jan,Feb,Mar,Apr,May,June,July,Aug,Sep,Oct,Nov,Dec
CMP1,2016,0,0,318.50,68.25,91,182,338,195.25,140.70,0,117.25,0
CMP2,2017,550.30,0,0,0,0,0,0,0,0,0,0,0
CMP3,2017,160.95,0,0,0,0,0,0,0,0,0,0,0
CMP4,2016,3226.90,13141,13131.40,5108.60,4148,5529.60,1082.25,12945.85,5002.30,2239.80,4035.40,4454.35
CMP4,2017,13362.85,8671.35,10233,0,0,0,0,0,0,0,0,0
I have details of the company sales (row data) which is given to the crystal report. So In crystal report, I first group by data based on year and company. Total of each month is generated dynamic using crystal report sum field. Please help me on this.
This should be close to what you are looking for...
1) Make sure your data is grouped be year. (Which it sounds like you are)
2) Insert a SUM summary in the year group footer. (Also sounds good just make sure its in the group footer)
3) Use a formula like this...
Global CurrencyVar b := IF GroupNumber = 1 THEN Sum ({TableName.DollarAmount}, {TableName.Year}) ELSE b;
Global CurrencyVar e := Sum ({TableName.DollarAmount}, {TableName.Year});
Local NumberVar p := IF b = e OR b = 0 THEN 0 ELSE ((e - b) / b * 100); // or whatever calculation you are using...
b := Sum ({TableName.DollarAmount}, {TableName.Year});
p
4) Place the formula field in the group footer, next to the SUM from step #2.

Crystal Reports dateadd function error on interval

I have a date field on which my inventory item was bought. Then I have a lifespan field in months eg 240. Now I am trying to calculate the end of the item's lifespan date but I get an error:
numbervar myVariable := ({TABLE.LIFESPAN} * 30);
dateadd("d", myVariable,{#date})
I get the following error: "Date must be between year 1 and 9999"
As soon as I change the variable to: numbervar myVariable := {TABLE.LIFESPAN};
it works without any errors. Also if I change the dateadd formula to dateadd("d", 7200,{#date}) it works.
The format of the field TABLE.LIFESPAN is decimal(9,2) but none of the value has decimals, eg it will be 240.00
I have also tried
numbervar myVariable := Round({TABLE.LIFESPAN} * 30);
I suspect it has something to do with the decimals.
Help will be greatly appreciated.
you will receive this value once your ({TABLE.LIFESPAN} * 40) causes the year to be greater than 9999. So if {#date} were today's date then {TABLE.LIFESPAN} could not be higher than 73955 or so. I would create a formula for ({TABLE.LIFESPAN} *40) and drop it on the canvas and see what that value is on all records and see if you have an unusually high number somewhere.

convert year-month string into daily dates

recently I asked how to convert calendar weeks into a list of dates and received a great and most helpful answer:
convert calendar weeks into daily dates
I tried to apply the above method to create a list of dates based on a column with "year - month". Alas i cannot make out how to account for the different number of days in different months.
And I wonder whether the package lubridate 'automatically' takes leap years into account?
Sample data:
df <- data.frame(YearMonth = c("2016 - M02", "2016 - M06"), values = c(28,60))
M02 = February, M06 = June (M11 would mean November, etc.)
Desired result:
DateList Values
2016-02-01 1
2016-02-02 1
ect
2016-02-28 1
2016-06-01 2
etc
2016-06-30 2
Values would something like
df$values / days_in_month()
Thanks a million in advance - it is honestly very much appreciated!
I'll leave the parsing of the line to you.
To find the last day of a month, assuming you have GNU date, you can do this:
year=2016
month=02
last_day=$(date -d "$year-$month-01 + 1 month - 1 day" +%d)
echo $last_day # => 29 -- oho, a leap year!
Then you can use a for loop to print out each day.
thanks to answer 6 at Add a month to a Date and answer for (how to extract number with leading 0) i got an idea to solve my own question using lubridate. It might not be the most elegant way, but it works.
sample data
data <- data_frame(mon=c("M11","M02"), year=c("2013","2014"), costs=c(200,300))
step 1: create column with number of month
temp2 <- gregexpr("[0-9]+", data$mon)
data$monN <- as.numeric(unlist(regmatches(data$mon, temp2)))
step 2: from year and number of month create a column with the start date
data$StartDate <- as.Date(paste(as.numeric(data$year), formatC(data$monN, width=2, flag="0") ,"01", sep = "-"))
step 3: create a column EndDate as last day of the month based on startdate
data$EndDate <- data$StartDate
day(data$EndDate) <- days_in_month(data$EndDate)
step 4: apply answer from Apply seq.Date using two dataframe columns to create daily list for respective month
data$id <- c(1:nrow(data))
dataL <- setDT(data)[,list(datelist=seq(StartDate, EndDate, by='1 day'), costs= costs/days_in_month(EndDate)) , by = id]

crystal reports month date range for earnings

My client has a report that accepts a date range to get a report showing projected revenue. So, a user would enter a date range of '1/1/2015 to 1/31/2015' and the report should return data only in the range '1/1/2015 to 1/31/2015 grouped by week. I am instead for the week of 12/29/2014 (which 1/1/2015 fall into) and 2/1/2015 (which 1/31/2015 falls into). The report is intended to group by week, but I do not want days on the report that are earlier than the start date parameter or later than the end date parameter.
The sql statement for this report is:
SELECT job.job, job.status, job.customer_po, job.part_number, job.unit_price,
job.price_uofm, delivery.promiseddate, delivery.remaining_quantity, job.build_to_stock, job.description, job.make_quantity, job.pick_quantity, job.shipped_quantity, job.lead_days
FROM dbo.delivery as delivery RIGHT OUTER JOIN db.job as job on delivery.job = job.job
WHERE job.build_to_stock = 0 AND (job.status = 'active' OR job.status = 'hold' OR job.status = 'pending')
The date range is from this code and parameters:
Max – Maximum(?Date Range)
Min – Minimun(?Date Range)
Date Range - "From " & {#Min} & " to " & {#Max}
This is the group expression
Group 2 Name - GroupName ({#Adj Date 2}, "weekly") & " thru " & cdate(GroupName ({#Adj Date 2}, "weekly"))+6
This is the select expression
{#Date} = {?Date Range} and
not {Job.Build_To_Stock} and
{Job.Status} in ["Active", "Hold", "Pending"]
Do you know how I can prevent the "overflow" of dates outside of date range?
Thx
As long as you have date filtering in your record selection formula there will not be any "overflow" outside of that range. If you've got {Record.Date} in Minimum({?DateRange}) to Maximum({?DateRange}), which it sounds like you do, then your report will not contain any records outside of the parameter regardless of how you group them.
Your problem might stem from over-complicating or misinterpreting the grouping. All you need to do is group by {Record.Date} and select "Group by week" in the grouping options... you don't need any complicated formulas to break it out by week. But be aware that the way weeks are referred to is by their starting date. For example, if you had a record with a date of Feb. 19, 2015, that record would fall into the group labeled "Feb. 15, 2015" even if your {?DateRange} parameter was Feb. 18 - Feb. 15.

Correct ISO week numbering in Crystal Reports XI

How can I get the ISO-8601 week number of a given date in Crystal Reports XI?
Crystal Reports supports the DatePart-function which can give you the ISO week number of a given date.
NumberVar week := DatePart("ww", date, crMonday, crFirstFourDays);
However, in Crystal Reports XI there is a bug that gives erronous results round new year. The best solution is probably to create an own function getISOWeekNumber:
Function (optional DateVar d := CurrentDate)
NumberVar week := DatePart("ww", d, crMonday, crFirstFourDays);
// Correct for that CR doesn't handle the fact that the last days of a year can belong to week 1 of the next year:
if week = 53 and DatePart("ww", cDate(year(d) + 1, 1, 1), crMonday, crFirstFourDays) = 1 then
week := 1
// A bug in CR makes DatePart return values like 9363 for days in January that belongs to the last week of the previous year.
else if week > 53 then
week := DatePart("ww", cDate(year(d) - 1, 12, 31), crMonday, crFirstFourDays);
week;
To get the "week-year" of a specific date, you could then use the following function:
// Returns the year to which the ISO week of the specified date belongs.
// E.g. 2012-12-31 will return 2013, as that date belongs to week 1 of 2013.
Function (optional DateVar d := CurrentDate)
NumberVar week := getISOWeekNumber (d);
if week = 1 and month(d) = 12 then
year(d) + 1
else if week > 10 and month(d) = 1 then
year(d) - 1
else
year(d);