变量代表一个特定的数据项或值,并充当该值的占位符。公式遇到某个变量时,它便搜索该变量的值并将此值用于公式中。与常量值不同,可以给变量反复赋以不同的值。将某个值赋给变量后,该变量便保持此值,直到再赋以一个新值时为止。由于这种灵活性,在使用变量之前必须声明它们,以便 Crystal Reports 意识到它们的存在并了解您想如何使用它们。

如果希望按区号创建客户报表,则可以创建一个变量,该变量将从客户传真号码中提取区号。以下示例是一个名为 areaCode 的变量:

Local StringVar areaCode;
areaCode := {Customer.Fax} [1 To 3];
变量声明(Crystal 语法)
变量声明(Crystal 语法)

在公式中使用变量前必须声明它。变量可以保存某个给定类型的值。允许的类型是七种简单类型(数字、货币、字符串、布尔值、日期、时间和日期时间),六种范围类型(数字范围、货币范围、字符串范围、日期范围、时间范围和日期时间范围)以及保存上述类型数组的变量。这为变量提供了总共 26 种不同的类型。

声明变量时,还指定了它的名称。变量不能与任何对 Crystal 语法有效的函数、运算符或其他关键字同名。例如,变量不能被命名为 Sin、Mod 或 If,因为 Sin 是内置函数,Mod 是内置运算符,而 If 是内置关键字。当在公式编辑器中键入公式时,内置函数、运算符或其他关键字的名称均以不同的颜色突出显示,因此很容易检查出变量名是否与它们冲突。

变量一经声明后,即可在公式中使用。例如,可能希望为其赋以一个初始值:

Local NumberVar x;
x := 10;

声明数字型变量的关键字的末尾为 Var。Crystal 语法中所有的变量类型都是如此。

变量只能保存一种类型的值。例如,如果一个变量保存数字型值,则无法再用其保存字符串型值。

Local StringVar y;
y :
= "hello";
//正确 — Length 函数应该有字符串型参数。
Length (y);
//错误 — y 只能保存字符串值。
y := #Jan 5, 1993#;
//错误 — y 只能保存字符串值。
y := ["a", "bb", "ccc"];
//错误 — Sin 函数应该有数字参数。
Sin (y);

在单个表达式中可以同时声明变量和给变量赋值。例如:

Local NumberVar x := 10 + 20;
Local StringVar y := "Hello" + " " + "World";
Local DateVar z := CDate (#Sept 20, 1999#);
Local NumberVar Range gradeA := 90 To 100;

这是一个不错的方法,因为效率将会提高,并且当变量初始化不正确时,有助于防止出现常见的错误。

下面是声明和初始化范围变量的另外一些示例:

Local NumberVar Range gradeA;
Local DateVar Range quarter;
gradeA := 90 To 100;
quarter := CDate (1999, 10, 1) To CDate (1999, 12, 31);

变量作用域(Crystal 语法)

变量作用域用于定义某个公式的变量可在多大程度上用于其他公式。Crystal Reports 中的作用域有三个级别:

  • 局部
  • 全局
  • 共享

每个变量都有一个作用域,该作用域在变量声明时指定。

局部变量(Crystal 语法)

具有局部作用域的变量是使用 Local 关键字 + 类型名称(带有后缀 Var)+ 该变量名声明的。

局部变量只限于单个公式以及该公式的单个求值。也就是说,无法从其他公式访问某个公式中的局部变量值。

示例

//Formula A
Local NumberVar x;
x :
= 10;
//Formula B
EvaluateAfter ({@Formula A})
Local NumberVar x;
x :
= x + 1;

函数调用 EvaluateAfter ({@Formula A}) 确保公式 B 在公式 A 之后求值。公式 A 返回一个值 10,公式 B 返回一个值 1。公式 B 无法访问公式 A 中的 x,因此不能使用值 10 来加 1;对于公式 B 中未初始化的局部变量 x,公式 B 改用默认值 0,因此加 1 后便得到 1。

也可以在不同的公式中使用相同的名称、不同的样式创建局部变量。例如,公式 A 和公式 B 中的类型声明与下列内容不冲突:

//Formula C
Local StringVar x := "hello";

局部变量是三种作用域中最有效的。另外,它们在不同的公式中互不干扰。因而,只要可能最好将变量声明为局部变量。

全局变量(Crystal 语法)

全局变量使用相同的内存块在整个主报表中存储一个值。除子报表中的公式外,该值随后可用于所有声明此变量的公式。如下例所示声明全局变量:

Global StringVar y;
默认情况下,也可以省略创建全局变量的 Global 关键字。
StringVar y; //等同于: Global StringVar y;

然而,虽然局部变量容易声明,但建议只有在全局变量能力不足的情况下才使用局部变量。

由于全局变量在整个主报表中共享它们的值,因此不能在某个公式中使用某个类型声明全局变量后,再使用同一个名称在不同的公式中以不同的类型声明全局变量。

//Formula A
Global DateVar z;
z :
= CDate (1999, 9, 18)
//Formula B
NumberVar z;
z :
= 20

在这种情况下,如果首先输入并保存公式 A,则当检查或试图保存公式 B 时,Crystal Reports 将返回错误。这是因为将全局变量 z 声明为数字类型与先前在公式 A 中将其声明为日期类型冲突。

何时使用全局变量

全局变量通常用于执行复杂的计算,计算的公式结果取决于实际打印的报表的分组和页面布局。为此,需创建若干公式,将它们置于报表的不同节,并通过全局变量使这些不同的公式互相作用。

示例

//Formula C
Global NumberVar x;
x :
= 10;
//Formula D
WhileReadingRecords;
Global NumberVar x;
x :
= x + 1

如果将公式 C 置于“报表头”,然后将公式 D 置于“详细资料”节,则公式 C 先于公式 D 求值。公式 C 经过一次求值后,“详细资料”节每次出现记录时,便求值公式 D。公式 C 返回 10。对于第一条明细记录,公式 D 返回 11。这是因为 x 的值 10 在公式 C 中设置之后就被保留了。然后公式 D 将此值加 1,将 x 设置为 11 并返回 11。对于第二条明细记录,公式 D 将 1 加到此前保留的 x 值(其值为 11)上,返回 12。对于剩余的明细记录,将继续进行此过程。

调用 WhileReadingRecords 使得 Crystal Reports 在读取报表的每个记录时重新对公式 D 求值。否则,由于该公式不包含任何数据库字段,因此程序在从数据库读取记录之前,只对该公式进行一次求值。处理连续记录时,公式将返回值 11 而不是 11、12、13 等等。

如果表达式 x := x + 1 由 x := x + {订单细节.数量} 替换,将产生基于 {订单细节.数量} 运行总计的效果,但是由于公式 C,起始值将是 10 而不是 0。在这种情况下,可以不必调用 WhileReadingRecords,因为它将因公式包含数据库字段而自动出现。

共享变量(Crystal 语法)

共享变量使用相同的内存块,在整个主报表及其所有子报表中存储变量值。因而,共享变量甚至比全局变量更普遍。若要使用共享变量,请在主报表内的公式中声明它,如下所示:

Shared NumberVar x := 1000;
并在子报表内的公式中声明它,如下所示:
Shared NumberVar x;

为使用共享变量,在共享变量可以在主报表和子报表之间传递之前,必须先声明该变量并给其赋值。

posted on 2011-04-14 14:59  笨笨小媛  阅读(2767)  评论(1编辑  收藏  举报