## Formula levels

Formulas can be categorized into 6 levels. These levels determine when the actual statements in your formula will be executed. JReport Engine will make several passes over the data to determine when formulas are executed. Even though an individual formula appears to be a certain level, if it references anything in the higher level then it also becomes the higher level.

- Constant level formula
  A constant level formula is a formula that does not refer to any DBFields, summaries, global variables, page level special fields (the value of the special field is ready at the time when the report result is generated) or other non-constant formulas. For example, `return CurrentDate()` is a constant formula. JReport will execute these formulas before fetching data from the dataset, so if you place it in the report header, it will be executed immediately as it is encountered.
- Record level pass one formula
  A formula is a record level pass one formula if and only if the following are true:
  - Refers to a DBField or any other formula which references a DBField.
  - Does not refer to any page level special fields or formulas which refer to page level special fields.
  - Does not refer to any global variable or any record level pass two formulas
  - Does not refer to a summary field.

  Record level pass one formulas are executed on each record immediately after the record is fetched from the dataset. They are often used in the detail panel of banded reports and tables such as calculating a value based on other DBFields such as `return @PRICE - @COST`.

- Record level pass two formula
  A formula is a record level pass two formula if and only if the following are true:
  - Refers to a DBField and a summary.
  - Refers to any other record level pass two formula.

  Record level pass two formulas are executed on each record of the dataset but only after the data has been grouped. For example, if a record level pass two formula is placed in the banded header, the group is considered to be the entire report. If it is placed in a group header such as Category, it will be the value after all of the detail rows have been processed for the group. For example, you might want to print in a group footer the group name and total such as `return "Total for " + @CATEGORY + ": " + @Sum_Total;`.

- Group level formula
  A formula is a group level formula if it refers to only summaries or other group level formulas. For example, if you have a summary called Sum_Total and a summary called Count_Detail, you could write a record level pass two formulas as `return @Sum_Total / @Count_Detail` to print the average total sales on each line of the order.

  These formulas are executed when breaking the group on which the summaries are defined which could be a group or the entire report for a report level summary in the banded header or banded footer.

- Report global and global formulas
  If a formula refers to a global variable or report global variable and does not refer to any page level special fields, there are several rules for when the formula will be calculated.
  - Report Header and Group Header: Formula will be calculated when the group starts.
  - Page Header, Page Footer and Detail: Formula will be calculated on each record after the data has been grouped the same as record level pass two formulas.
  - Report Footer and Group Footer: Formula will be calculated when ending the group or report.

  These formulas will be calculated based on all of the records of the group or report. For example, if you are calculating an accumulated total that you display in a report footer or group footer, then it will work as expected. For example, you may want to calculate a total margin such as:

  `global number GrossProfit = 0;
  GrossProfit = GrossProfit + (@Price - @Cost);
  return GrossProfit;
  `

  However, if you are showing a running total in the detail, you will see the group or report total on every line rather than the expected running total. The solution is to convert the formula to a page level formula by adding a reference to any page level special fields (see below).

- Page level formula
  All of the other formula types are converted to a page level formula if the formula refers to next(), prev() or any of the page level special fields. Page level special fields include FetchDate, FetchTime, RecordNumber, PageNumber, PrintDate, and PrintTime.

  The page level formulas are calculated in the exact sequence of the panels as they are laid out in JReport Engine. Thus if a page level formula includes any of the page level special fields, it will be calculated in the detail or group header and footer exactly in the order they are laid out. In the above example, to do a running total on each detail the code is as follows:

  `PageNumber;
  global number GrossProfit = 0;
  PageNumber;
  GrossProfit = GrossProfit + (@Price - @Cost);
  return GrossProfit;`

  PageNumber also controls the sequence of calculations around page breaks. If PageNumber is referenced, the calculation will be done before the page break. If PageNumber is not referenced, the calculation will be done after the page break. This is important when using formulas for setting properties.