Crystal Reports Ripplestone Ripplestone Tips

Using Wildcard Parameters with Crystal Reports and Ripplestone

I have been working on the next version of Ripplestone and a client had asked about if and how Ripplestone will handle wildcard parameters in a Crystal Report.  I had not used wildcard parameters for awhile so I decided to dig in and build some reports with wildcard parameters and see how they worked when published to Ripplestone.

Creating the Crystal Report

For the report, I made a simple report that would have a parameter for a last name.  The report would use this parameter in the record selection and allow the user to enter wildcard in the format of “LY*” or “LY??” and have the report retrieve records for all the last names that either begin with LY or have four characters in the last name and they begin with LY.

To begin, I created the parameter with the settings to Allow custom values and Allow discrete values set to True.

Next I created the selection using the Select Expert and using the field called BillingLastName set the selection type to be “is like” and used the parameter called LastName as the value.

Running the report within Crystal Reports the user will get a parameter prompt and I entered the value of “LY*”.

The results from this simple report display all the records from the table where the last name begins with “LY”

Publish and Run the Report in Ripplestone

After creating the report in Crystal Reports, it is time to publish the report in Ripplestone and see how the wildcard parameters work.

Publishing the report was the same as any other report, select the report and give it a title click the Publish button.  Once the report was I clicked the Run Report link and got the parameter page.  The page prompts for  the last name and once again I entered “LY*” for the value.  Clicking the Run Report button will then pass the value to the report and the report will refresh the data for the report (in this case the data source was SQL Server) and display the report to the user within their web browser.

The report is returned as a pdf in the web browser.  The Crystal Report uses the wildcard parameter the same when running from Ripplestone as it does when running directly from the Crystal Report designer.

Crystal Reports Crystal Reports Formulas Ripplestone Ripplestone Tips

Converting Numbers to Dates in Crystal Reports

While working with a Ripplestone client today that had a Crystal Reports report that had data that was a date but the database stored the date as a number in the format YYYYMMDD (20090924 for example).  They wanted the date to be displayed in Ripplestone as MM/DD/YYYY (09/24/2009).

In their copy of Crystal Reports Designer they had changed the default number format to only display the number with no formatting.  They then used the following formula to convert the number into a date format:

Mid (ToText ({Database Field}), 5,2) + “/” + Right ( ToText({Database Field}),2) + “/” + Left (ToText ({Database Field}), 4)

This worked great when the number was 20090924, the formula split the number into the following 3 numbers 09, 24 and 2009 and then created the date by adding the “/” between the numbers.

The problem started once the report was published to Ripplestone and run.  The dates on the report were displaying as 90/00/20,0

After a lot of looking at the formula we discovered that the default number for the Crystal Reports Runtime Engine is to add commas and 2 decimals to the number, so that it was displaying as 20,090,924.00

When this was run with the formula, the 3 number were 90, 00 and 20,0.

To fix this problem we needed to remove the formatting from the number before the Mid, Right and Left functions were applied.  To remove the formatting of the number I added extra attributes to the ToText function.  The first attribute was the “#” as the second value.  This removes the commas from the number.  The next attribute was a zero (0) as the third value.  This will set the decimals to be zero and remove the “.00” from the end of the number.  The revised formula is below, with the changes highlighted in red.

Mid (ToText ({Database Field}, “#”, 0), 5,2) + “/” + Right ( ToText({Database Field}, “#”, 0),2) + “/” + Left (ToText ({Database Field}, “#”, 0), 4)

This allowed the number to be formatted correct and when the report was run or scheduled from Ripplestone the dates are displayed in the correct format.

Crystal Reports IIS Ripplestone Vista Windows Server 2008

Running Ripplestone on Vista and Windows Server 2008

I was working with a Ripplestone client to get the software installed on a Vista PC and had a do a few things different than if this was XP Pro or Windows Server 2003.  The main differences were that Vista and Windows Server 2008 use IIS 7 and the .NET framework 1.1 is not installed by default.

I started with the following article on setting up Vista and Windows 2008 to run an ASP.NET 1.1 application.

Install ASP.NET 1.1 with IIS7

Once I got ASP.NET 1.1 installed and configured, I need to make sure that Crystal Reports was installed correctly with the Ripplestone installer.  This was just a matter of checking the permissions and testing the running of a report within Ripplestone.

All together it took an extra 30 minutes to get everything installed and configured correctly.

Crystal Reports Performance Tips Ripplestone Stored Procedures

Crystal Report Performance Tip – Stored Procedures

As I work with clients and their Crystal Reports, one of the items that will come up sooner than later is how to increase the performance of their reports.  The performance issue becomes more noticeable once the reports are published into Ripplestone and the users are interactively running the reports.  If the report takes 5-10 minutes to run the users will let you know that the reports are “taking forever” to run.

One of the suggestions I usually have is to look into using stored procedures to do a lot of the work and have the stored procedure return a table that is easy to report from.  What I mean by “easy to report from” is that the table returned by the stored procedure has as much processing completed within the stored procedure so the report will not need to do the processing.

One of the techniques that I have used often is to have the stored procedure create a temporary table that I will fill with the data needed for the report and return the temporary table as the output of the stored procedure.

To create the temporary table, you declare the table name and the fields that the table will contain.  The example below is for a financial report for profit and loss.

Declare @tblProfitAndLossSummary Table
    (LocationName varchar(50),
    ActualExpense smallmoney,
    ActualRevenue smallmoney,
    NonProductivityPercentage decimal(9,1),
    PaidProductivity decimal(9,1),
    WorkedProductivity decimal(9,1),
    HourlyRate smallmoney)

If the data that will be going into the table will be coming from multiple locations or tables then you might need to do some type of calculation within the stored procedure.  In the above Profit and Loss example I needed to create a SQL Server cursor and then loop through the records and insert a record into the temporary table for each record within the cursor.

        /* Initialize the variables */
        SELECT @ActualRevenue = 0
        SELECT @RegularHours = 0
        SELECT @ActualExpense = 0
        SELECT @NonProductivityPercentage = 0
        SELECT @PaidProductivity = 0
        SELECT @WorkedProductivity = 0

To hold the data for each record, I created a variable for each of the fields in the temporary table and then would insert the data into the temporary table with the following code.

INSERT INTO @tblProfitAndLossSummary

I was then able to run calculations within the Cursor loop such as

/* This gets the Revenue amount for a store */
SELECT @ActualRevenue = SUM(BillingCharges.ChargeAmount)
FROM BillingCharges INNER JOIN BillTo ON BillingCharges.BillNumber = BillTo.BillNumber
WHERE (BillTo.StoreNumber = @StoreNumber)
AND (BillingCharges.PeriodFrom >= CONVERT(DATETIME, @StartDate, 102)) AND (BillingCharges.PeriodTo <= CONVERT(DATETIME, @EndDate, 102))

/* Calculate the Regular Hours */
SELECT @RegularHours = ((@RegularTime + @Category1Time) / 60)

In the above example there were many additional queries and calculations needed to get the values for the 7 fields being inserted into the temporary table.

In the end all the data that the report needs is contained in the temporary table and the last step would be to return the data with a final SELECT statement.

SELECT LocationName,
    SUM(ActualExpense) AS Expense,
    AVG(NonProductivityPercentage) AS AvgNonProdPercent,
    AVG(PaidProductivity) AS AvgPaidProd,
    AVG(WorkedProductivity) AS AvgWorkedProd,
    AVG(HourlyRate) AS AvgHourlyRate
FROM @tblProfitAndLossSummary
GROUP BY LocationName, ActualRevenue
ORDER BY LocationName


The crystal report has the added bonus of being easy to format since most of the data is ready for the report.

In this example the report before the stored procedure was very slow with many formulas and sub-reports.  After the report was re-written with the stored procedure it runs from within Ripplestone in under 5 seconds.

Crystal Reports Microsoft Access Ripplestone

Change the Crystal Reports Set Datasource Location for Ripplestone

One of the more common questions I get from Ripplestone users is how to change where the Crystal Report is getting the data from for the report.  Or a related question is that after a report is published to Ripplestone it gets an error stating that the report can no longer find the data source.  This is very common when the data source is a file based data source such as Microsoft Access, Excel or a dBase database.

First, let me step back and explain why Ripplestone will display the error when the report is published to Ripplestone.  Then we can fix the report to make it work within Ripplestone.

When creating a report that uses a file base database or a file like Excel, the report will use a hard coded path to the file.  In the screen shot below, the report is getting the Access database from a network share.  This report will work great as long as it’s run from the local network and the user running the report has permissions to the network share.  This is the location used to develop the report.

The problem is that when this report is published to Ripplestone, the Ripplestone server will also need to be able to access the database to refresh the report with current data.  The Ripplestone web application also runs under the Network Service local account and that account will need permission granted to access the database.

In the following example, the report was published to a external web server that did not have access to the network share, so it would display an error within Ripplestone stating that the database could not be found.

To solve the problem the database location needed to be changed within the Crystal Report using the Set Database Location dialog box.  The dialog box allows the report to be updated to a different database at a different location.  In the above example the database was moved to the report server at D:\Data\TMS\Applications2009.mdb and the TMS folder was given permission to the Network Service user to read from the folder.

Crystal Reports Set Database Location

As you can see in the about screen shot I create a new database connection in the bottom half with the new database location and then pressed the Update button to update the main report and the sub-reports with the new database.  I was then able to publish the updated Crystal Report to Ripplestone and the report will be able to location and report from the database in the D:\Data\TMS folder.

Crystal Reports Ripplestone

Crystal Reports Group Ranges with Specified Order feature

While working on a report for a Ripplestone client I was able to use the Crystal Report Specified Order option of the Group Expert.  I thought I’d share the process of using the Specified Order feature and how I used it to solve a problem that I was having with the report.

The report was a Crystal Report that would display a list of students for a class and needed to be grouped by the students age.  It was easy enough to group the age by using the Group Expert, but that creates a group for each age.  I needed to have the children grouped by a age range and not by the exact age of the children.

To create a range of ages I clicked on the Options button to open the Change Group Options and then selected “in specified order” from the group by options dropdown.


This activated the Specified Order tab on the dialog box.  On this tab I was able to type the group names in the combo box at the top and enter the 3 groups that I needed.  This created 3 empty groups, so the next step would be to assign values to each of the groups.  This would be the range of ages that I wanted for each of the three groups.


To create the age ranges for each of the 3 groups I clicked on the Edit button to open the Define Named Group dialog box and selected “is between” from the list of options.  Then needed to enter the values for the range of ages.  In the example below the report will groups all the children between the ages of 7 and 9 into the groups called “Ages 7-9”.


After running the records were grouped into the 3 age ranges with totals for each group.


If you have questions or comments, please let me know.