crystal training jan 2011 (3)

Upload: caryn3965

Post on 09-Apr-2018

217 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/7/2019 Crystal Training Jan 2011 (3)

    1/16

    Continuing Crystal Education

    January 2011

    The Aging Report

    Database JOINS

    Bucketing with DatesGrouping and Summarizing

    Using a simple crosstab

  • 8/7/2019 Crystal Training Jan 2011 (3)

    2/16

    A few notes:

    All screenshots herein were generated with Crystal 9.0. Other versionsmay look a little different, but all core functionality is identical. The data being

    used is from an Accounting package called Atrex, and all data is real productiondata.

    That being said, the principles outlined here are fundamental, and can be

    transposed to any data system one should care to use.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    3/16

    Why JOINS are importantand why were talking about them again

    Relational Database Design

    Here is the ugly fact; even though your customers and their associated data (i.e.

    calendar items, history items, invoices, etc.) appear to be all in the same place, theymost assuredly are not, from a data perspective. This isRelational Database Design.

    Much like Godzilla vs. Mothra, the one-to-one vs. one-to-many problem is as old asdata.

    One to One : Each customer only as one address, one territory, etc.

    One to Many : Each customer has many pending items, many invoices, etc.

    Think of it this way: if we wanted to trackboth customer information (territory,address) andinvoice information (date of invoice, amount) in the same table, this table

    would need multiple rows for the same customer (one row for every invoice).

    What you would get is this (sometimes referred to as a monolithic design).

  • 8/7/2019 Crystal Training Jan 2011 (3)

    4/16

    Where it is much more efficient to store CUSTOMERS in one table andINVOICES in another table, shown here.

    [CUSTOMERS]

    [INVOICES]

    But the key here is to relate the tables to one another, so we know which bunch ofinvoices belong to what customer. We do this, no pun intended, with a key field.

    Every database has its own design. In our example, both the CUSTOMERS table

    and INVOICES table have a field called CUSTNUM. It would therefore make sense thatother related tables in our database will have a CUSTNUM field as well.

    This is the essence of a JOIN between two tables; relating the key field. In this

    case;CUSTOMERS.CUSTNUM = INVOICES.CUSTNUM

  • 8/7/2019 Crystal Training Jan 2011 (3)

    5/16

    We will need to define this JOIN in the Crystal Report Designer before we canuse data from both tables. If we were using other tables as well, these could be added and

    JOINED in the same manner.

    After adding the tables to your Crystal Report, link them (with the Visual LinkingExpert) by dragging one key field to its corresponding key field in another table.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    6/16

    There is one more thing to define; the type of JOIN. This is done by right-clickingon the actual join line in the Visual Linking Expert and selecting Options.

    This displays the Link Options window. On the bottom right-hand side, we canchange the join type. Youll notice the default isEqual(otherwise known as an INNER

    JOIN). The two types you are likely to need are the Equaland theRight Outer.

    An INNER (Equal) JOIN behaves in the following manner:

    - It will return rows from CUSTOMERS (left side) onlyif there is both a row

    in CUSTOMERS anda row in INVOICES (right side)- So, INVOICES without CUSTOMERS are ignored

    - And CUSTOMERS without INVOICES are ignored

    A LEFT OUTER JOIN behaves in the following manner:

    - It will return rows from CUSTOMERS (left side) even if they have no rows inINVOICES (right side)

    - INVOICES without CUSTOMERS are ignored

  • 8/7/2019 Crystal Training Jan 2011 (3)

    7/16

    JOINS impact recordsets

    Why is this all important? The biggest reason to understand JOINS in this contextis because you will need to ask yourself the question:

    Do I want to see customers who have no invoices on my report?

    If so, then remember, use the LEFT OUTER JOIN. If not, then use the default

    INNER (Equal) JOIN. Customers without invoices are probably not appropriate on ourAging report. But you need to be aware of the options. More importantly, how those

    options will impact your recordset in Crystal.

    Now that weve added our tables to the report (and defined their JOIN), letsmove onto the logic behind our Aging Report.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    8/16

    Bucketing Datamaking sense of a summary

    Date-Range Buckets

    Let us pause for a moment and reflect on what exactly the Aging report is going

    to show us.

    - For every customer, show a summary of unpaid invoices for

    o 0-30 days

    o 31-60 dayso 61-90 days

    o 90+ days

    Now lets see the same list using our back-end database fields:

    - CUSTOMER.LASTNAME is our Company field

    - INVOICES.SUBTOTAL is the dollar amount of the invoice- INVOICES.TRANSDATE is the date of the invoice

    So, for every CUSTOMER.LASTNAME:

    - Sum INVOICES.SUBTOTAL based ono INVOICES.TRANSDATE in 30 days old

    o INVOICES.TRANSDATE in 31-60 days oldo INVOICES.TRANSDATE in 61-90 days old

    o INVOICES.TRANSDATE greater than 90 days old

    The Problem of Double-Bucketing

    You will notice that our two middle buckets dont start exactly on the day in

    question. The 31-60 code needs to exclude day 30, otherwise any invoice that landsexactly on day 30 will appear in both buckets.

    Same problem with 61-90; it must exclude day 60 for the same reason.

    The main idea here is that when you start defining your own buckets, great caremust be made against double-bucketing. Crystal has no idea what you are trying to

    accomplish and will, stupidly, do exactly what its told.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    9/16

    Date-Range Buckets as a Crystal Formula

    So, the first thing we need to do is create a Crystal Formula that will kick outwhich bucket an invoice belongs in based on TRANSDATE. We can do this with one

    formula as shown here:

    Create a formula called frmDateBucket.

    Our new formula will evaluate INVOICES.TRANSDATE, and our first part ofthe bucket code will look like this:

    {INVOICES.TRANSDATE} IN CURRENTDATE TO CURRENTDATE - 31

    THEN '0-30 days'

    So, if the TRANSDATE falls between today and 31 days ago, print out 0-30days. The 0-30 days will be our first bucket name. But there are more buckets we

    need, so we will use an ELSE and then insert the code for the next bucket:

    {INVOICES.TRANSDATE} IN CURRENTDATE TO CURRENTDATE - 31THEN '0-30 days' ELSE

    IF {INVOICES.TRANSDATE} IN CURRENTDATE - 31 TO CURRENTDATE -

    61 THEN '31-60 days'

    So now our formula is kicking-out the text 0-30 days OR 31-60 days based

    on TRANSDATE, it is easy enough to add the rest of the code thusly;

    {INVOICES.TRANSDATE} IN CURRENTDATE TO CURRENTDATE - 31

    THEN '0-30 days' ELSE

    IF {INVOICES.TRANSDATE} IN CURRENTDATE - 31 TO CURRENTDATE -

    61 THEN '31-60 days' ELSEIF {INVOICES.TRANSDATE} IN CURRENTDATE - 61 TO CURRENTDATE -

    91 THEN '61-90 days' ELSE

    IF {INVOICES.TRANSDATE} < CURRENTDATE - 90 THEN '90+ days'

    The last bucket (90+ days) bears some explanation. Because we are onlyconcerned here with invoices that are olderthan 90 days, we need not use a range for that

    evaluation. Rather, it is enough to just use the less than operator to return if theTRANSDATE is older (less than) today minus 90.

    Because the less than operator does not include the operand (90) (as less thanor equal to would) we can use the value of 90, whereas the other buckets stagger a day

    ahead (31, 61) to exclude the previous bucket.

    What we are left with is a nice little Crystal Formula that kicks out specific textbased upon a condition. The kicked-out text can then be used as a Group, which

    ultimately is what we want to do.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    10/16

  • 8/7/2019 Crystal Training Jan 2011 (3)

    11/16

    Grouping and Summarizing your Bucketsnow for the easy part

    Insert your Groups

    Our first group level will be CUSTOMERS.LASTNAME, which is where our

    company name is kept.Within Crystal, select Insert | Group.

    From the drop-down list, select the LASTNAME field from the CUSTOMERStable. Crystal will automatically create a group Header and Footer on the report. Group

    #1 Name, is of course the CUSTOMER.LASTNAME field.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    12/16

    Now repeat the same procedure for our frmDateBucket formula field. Youll end

    up with two Group Headers and Footers.

    Running the report at this point will provide no summary data, but you will get an

    immediate sense of how the data is being grouped by inspecting the Group Tree on theleft hand side.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    13/16

    Inserting your Summaries

    Now that weve encoded our logic into Crystal Groups, it is a simple procedure toadd summaries.

    Go to Insert | Summary.

    You must first select the fieldname SUBTOTAL before you can specify that the desired

    summary function will be a SUM. Then you must choose where the summary iscalculated (in which group). Notice that Ive chosen our special formula field,

    frmDateBucket.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    14/16

    Now our report output will look something like this:

    You can see with the indentations Ive made how the group are nested within eachother. LASTNAME (Company), then frmDateBucket (Date bucket) and finally a SUM of

    SUBTOTAL, calculated for each Date Bucket.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    15/16

    The Crosstab Approacheasier and prettier

    The Crosstab Object

    A better way to look at the same data would be from a crosstab object. Crosstabs

    summarize data by dimensions (think of a pivot table in excel). Dimensions are analogousto Groups.

    To insert a crosstab, select Insert | Crosstab.

    The Crosstab object needs three components; a row, a column and a summarized

    field.

    Our Row will be CUSTOMERS.LASTNAME.Our Column will be frmDateBucket.

    Our summarized field with be a SUM on INVOICES.SUBTOTAL.

    You may place the crosstab object anywhere in the report, unlike other summary

    fields which must be placed in specific locations.

  • 8/7/2019 Crystal Training Jan 2011 (3)

    16/16

    Now our report output will look something like this:

    Many users prefer this format compared to the tree format outlined earlier. Thecrosstab will automatically provide totals on the right and bottom of the object for each

    row and column.

    Any field within the crosstab can be formatted like any other field, so you candefine the currency format, etc.