I want to print all the days of a given month in Crystal Report. This is what my Crystal Report looks like:
So on and so forth.
What I have done is, I created a table with dates, when the user pick a month through the date-timepicker my program will insert all the days of the picked month to the table.
Although it can be attempted at SQL level also (as suggested by #aMazing), if you want to do it at Crystal Report level only, you can adapt from the following basic idea to accomplish rows with dates having no records.
Create three formula fields in report design, namely First_Dates, Mid_Dates, Last_Dates and set their values in formula editor as under:
First_Dates
WhilePrintingRecords;
numberVar TotalDays := Day ({Sale_Date_Field}) - 1;
numberVar i;
stringVar DayList := "";
for i := 1 to TotalDays step 1 do
DayList := DayList & ToText(i, 0) & " 0.00 0.00" & Chr(13);
DayList;
Mid_Dates
WhilePrintingRecords;
numberVar FromDay := Day({Sale_Date_Field}) + 1;
numberVar To_Day := Day(Next({Sale_Date_Field})) - 1;
numberVar i;
stringVar DayList := "";
for i := FromDay to To_Day step 1 do
DayList := DayList & ToText(i, 0) & " 0.00 0.00" & Chr(13);
DayList;
Last_Dates
WhilePrintingRecords;
numberVar NextDay := Day ({Sale_Date_Field}) + 1;
numberVar i;
numberVar MonthDays := 30;
if (Month ({Sale_Date_Field}) in [1,3,5,7,8,10,12]) then
MonthDays := 31
else if (Month ({Sale_Date_Field}) in [4,6,9,11]) then
MonthDays := 30
else if (Month ({Sale_Date_Field}) = 2
and Remainder(Year({Sale_Date_Field}), 4) = 0) then
MonthDays := 29
else
MonthDays := 28;
stringVar DayList := "";
for i := NextDay to MonthDays step 1 do
DayList := DayList & ToText(i, 0) & " 0.00 0.00" & Chr(13);
DayList;
Now place these formula fields in your report as under:
First_Dates in Report Header Section
Mid_Dates in Details b Section
Last_Dates in Report Footer Section
Now enable Can Grow option for each of them in the Format Field on the Common tab.
Enable Suppress Blank Section option for Detail b Section in Section Expert.
Format the fields and DayList accordingly.
For multiple months the report can be grouped by Months and First_Dates, Last_Dates formulas can be placed in the Group Header and Footer respectively.
This solution will not work with Cross-Tab format.
Related
Now, I have successfully display the time in "HH:mm" format, but I will need to change it to decimals. For example, the hours is 2.30 meaning 2 hours and 30 minutes, but I need it to be 2.5 meaning 2.5 hours. Please help. Below is my code:
Local NumberVar HoursDiff;
Local NumberVar MinutesDiff;
Local NumberVar SecondsDiff;
Local StringVar strOut;
SecondsDiff := DateDiff('s',{Invoicing.TimeFrom},{Invoicing.TimeTo});
HoursDiff:= SecondsDiff \ (60 * 60);
SecondsDiff := SecondsDiff MOD (60 * 60);
MinutesDiff:= SecondsDiff \ 60;
strOut := strOut & CStr(HoursDiff,0)& '.' & CStr(MinutesDiff,'00');
strOut
Try the following formula, I think it will work for you
timeVar time_value := CTime("2:30");//Time in HH:mm format
stringVar timeString := ToText(time_value);
numberVar time_in_min := ToNumber(Split(timeString,":")[1])*60 + ToNumber(Split(timeString,":")[2]) ;
time_in_min/60;
Convert this returned string value to time format using "time(strout)", then right click on formula field then select format filed option, it will opens a format editor in this select "date and time" tab. Then click on "customize" tab it will opens a custom style window.
in custom style window select time from order field in "Datetime" tab. then click on time tab and select which format you want.
I created a running total for my report, we will named it RT1. Now i created again another running total to get the sum of RT1 but i get the wrong answer. Any advice on how to correctly do this?
I have this formula in my first Running Total
//Formula1
#SpTotalReset
WhilePrintingRecords;
numbervar sp := 0;
//I placed it in my GroupHeader Date
//Formula2
#SpRunningTotal
WhilePrintingRecords;
numbervar sp;
sp := sp + {Sec/Pc};
//I placed it in my Details
//Formula3
#SpTotalDisplay
WhilePrintingRecords;
numbervar sp;
//I placed it in my GroupFooter Date
This is the formulas of my second running total
//Formula1
#MoTotalReset
WhilePrintingRecords;
numbervar mo := 0;
//I placed it in my GroupHeader Date
//Formula2
#MoRunningTotal
WhilePrintingRecords;
numbervar mo;
mo := mo + {#SpTotalDisplay};
//I placed it in my GroupFooter Date beside #SpTotalDisplay
//Formula3
#MoTotalDisplay
WhilePrintingRecords;
numbervar mo;
//I placed it in my GroupFooter Name
Change like this:
#MoTotalReset
WhilePrintingRecords;
Shared numbervar mo := 0;
//I placed it in my GroupHeader Name
And apply shared for all formulas. This should work.
How can I get the 7 days or weekly depends on date range in formula fields of Crystal Report?
Example:
Date Range from March 01, 2014 to March 31, 2014
Output:
Week 1 (March 01 to March 07)
Week 2 (March 08 to March 14)
Week 3 (March 15 to March 21)
Week 4 (March 22 to March 28)
Week 5 (March 29 to March 31)
Custom function RangeWeekSplitter works within one year. Crystal Syntax.
Function (dateTimeVar dFrom, dateTimeVar dTo)
// First day of the year
local dateTimeVar dBegCurrYear:= Date (Year(dFrom), 1, 1);
// Day of year (1 to 365 or 366 in a leap year)
local numberVar nFrom:= DatePart ("y", dFrom);
local numberVar nTo:= DatePart ("y", dTo);
local numberVar i;
local numberVar iTo;
local numberVar nDaysInWeek:= 7; // number of days in the week
local numberVar nWeek:= 0; // counter weeks
local stringVar sResult:= ""; // output string
for i:= nFrom to nTo step nDaysInWeek do
(
nWeek:= nWeek+1;
iTo:= i+(nDaysInWeek-1);
if(i+nDaysInWeek > nTo)
then iTo:= nTo;
// generate output string
sResult:= sResult + chr(13)+
"Week " + CStr(nWeek) + " (" +
CStr(DateAdd ("y", i-1, dBegCurrYear), "MMMM d") +
" to " +
CStr(DateAdd ("y", iTo-1, dBegCurrYear), "MMMM d") +
")";
);
sResult;
Usage example:
// Date range
local dateTimeVar dFrom:= Date (2016, 1, 14);
local dateTimeVar dTo:= Date (2016, 3, 4);
RangeWeekSplitter (dFrom, dTo);
You can use DatePart with "ww", too. See IBM Knowledge Center:
DatePart (intervalType, inputDateTime)
...
ww: Week of year (1 to 53 with firstDayOfWeek and firstWeekOfYear determining the exact days of the first calendar week of the year)
Combined with DatePart ("w", inputDateTime) or DayOfWeek(inputDateTime) getting the day of week, you can calculate your first and last day of the current calendar week.
So for one specific date (inputDateTime), this would be your formula "RangeWeek":
Function (DateTimeVar inputDateTime)
NumberVar cw := DatePart("ww", inputDateTime);
DateTimeVar first := DateAdd("d", 1 - DayOfWeek(inputDateTime, crMonday), inputDateTime);
DateTimeVar last := DateAdd("d", 7 - DayOfWeek(inputDateTime, crMonday), inputDateTime);
"Week " + ToText(cw) + " (" + ToText(first) + " to " + ToText(last) + ")"
You need to give ToText the format strings you want, of course.
Example:
Input: "August 23, 2017"
Output: "Week 34 (August 21 to August 27)"
That makes things easier in the formula where you get the date range.
DateTimeVar from := ...;
DateTimeVar to := ...;
NumberVar cw;
NumberVar count := 0;
StringVar output := "";
for cw := DatePart("ww", from) to DatePart("ww", to) do
(
output := output + chr(13) + RangeWeek(DateAdd("d", 7*count, from));
count := count + 1;
);
output
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);
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.