VFP常用编程命令及常用函数
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VFP常用编程命令及常用函数
VFP常用编程命令及常用函数
常用编程命令及常用函数
注:在语法中如用方括号“[]”括起来的词句,表示可以不用。
常用命令
假设(if...endif) 循环(do
while...enddo)
分支(do
case...endcase)
赋值(store...to) 调用表单(do form) 调用子程序(do)
返回调用程序(return) 启动事件处理(read
events)
清除事件处理(clear
events)
开关命令执行状态(set talk
on/off)
结束程序(cancel)
常用函数
数值转换字符(str()) 字符转换数值(val()) 取系统日期(date())
取年份(year()) 取月份(month()) 取天日(day())
取整(int()) 四舍五入(round()) 删除标记(delete())
记录号(recno()) 记录数(reccount()) 找到记录(found())
表结尾(eof()) 表开头(bof()) 消除后续空格(trim())
消除前导空格(ltrim())
假设语句
根据一逻辑表达式的值,有条件的执行一组命令。
语法:
IF 逻辑表达式 [THEN]
程序组1
[ELSE
程序组2]
ENDIF
参数:
逻辑表达式代表一逻辑值,如果这逻辑值为真,系统执行程序组1,
否则不执行程序组1,如果有else及程序组2的话,则执行程序组2,如没有则什么也不执行,直接执行endif后面的语句。
备注:
在if...endif之间还可以有if...endif,即该命令是可以嵌套的。
then可以有也可以没有,对程序没有影响。
else及程序组2可以有也可以没有,但如果有的话,在逻辑表达式的值为假时,程序组2将被执行。
if 与 endif 必须配对使用,即有一个 if 必须有一个 endif,否则程序会出错。
举例:
例1:假如分数字段的值大于等于90,则让等级字段的值为“优”,并显示该记录。
程序如下:
if 分数>=90
replace 等级 with '优'
display
endif
例2:在数据库中可以把性别字段设为逻辑型,“真”代表“男”,“假”代表“女”,但显示时不能显示真、假,否则别人看不懂,而应显示男、女,因此我们设一变量xb,根据性别字段的具体值,将xb 的值设为男或女,然后在需要的时候显示xb的值即可。
程序如下:if 性别
xb='男'
else
xb='女'
endif
其中第一句:if 性别,表示“假如性别为真”的意思,不要写成“if性别=.t.”。
以上程序也可以写成如下形式,效果相同:
if .not. 性别
xb='女'
else
xb='男'
endif
即,假如性别不为真的话,xb的值就为女,否则为男。
循环语句(do while...enddo)
根据条件重复执行一组程序。
语法:
DO WHILE lExpression
Commands
[LOOP]
[EXIT]
ENDDO
参数:
lExpression为一逻辑表达式,其值如果是“真”,即执行commands程序组,如果表达的值为“假”,则跳过该段程序组,执行enddo后面的语句。
Commands当表达式 lExpression 值为真时所要执行的程序组。
LOOP此为do while...enddo 命令的一个子句,它可以放在commands程序组中间的任何地方,当程序一旦执行到该子句时,则返回 do while 重新执行。
此子句根据需要可以有,也可以没有。
EXIT与loop一样是 do while...enddo 命令的一个子句,它可以放在commands程序组中间的任何地方,当程序一旦执行到该子句时,则跳出循环,执行enddo后面的语句。
此子句根据需要可以有,也可以没有。
备注:
程序一旦执行到do while 语句,如果lExpression 的值为真,则执行commands程序组,该程序组执行完后,就到enddo语句,enddo会将程序返回 do while 再次验证lExpression 是否为真,如仍是,则又一次执行commands,如此循环往复,直到lExpression 为假,或遇上 exit 语句。
该语句可以嵌套,即循环中还可以有循环。
do while 与 enddo 必须配对使用,即有一个 do while 必须有一个 enddo 否则程序会出错。
举例:
例1:在数据库中不断将记录指针往下移,直到数据库结尾。
程序如下:
do while .not. eof()
skip
enddo
例2:在上面的例子加入此功能,当遇到性别字段为“女”时,跳出循环。
程序如下:
do while .not. eof()
if 性别='女'
exit
endif
skip
enddo
例3:不断将记录指针往下移,当遇到数量字段的值大于等于600时退出循环,如遇到值小于400的,将其值乘2,然后再检验一次是否大于600,如是则退出循环。
程序如下:
do while 数量<600
if 数量<400
replace 数量 with 数量*2
loop
endif
skip
enddo
分支语句(do case...endcase)
根据不同的条件执行不同的程序组。
语法:
DO CASE
CASE 逻辑表达式1
程序组1
[CASE 逻辑表达式2
程序组2
...
CASE 逻辑表达式n
程序组n]
[OTHERWISE
程序组0]
ENDCASE
参数:
CASE 逻辑表达式程序组 ... 当程序执行到 do case 时,便检验第一个 case 的逻辑表达式(逻辑表达式1)是否为真,如不为真,接着检验第二个 case 的逻辑表达式,以此类推直到逻辑表达式n。
当检测到第一个为真的逻辑表达式时,便执行跟随在其后面的程序组,执行完后跳过后面所有的case ,接着执行endcase 后面的语句,也就是说即使后面还有为真的逻辑表达式也不执行了。
如果所有 case 后面的逻辑表达式都为假,则执行 otherwise 后面的程序组(如果有的话,otherwise 及其程序组是可以没有的,如果没有则什么都不做,直接执行 endcase 以后的程序)
备注:
在do case 和 endcase 之间可以有任意多个 case 。
do case 和 endcase 必须配对使用,即有一个 do case 必须有一个 endcase ,否则程序会出错。
举例:
如果工资在200元以下,增加50%;300元以下,增加30%;500元以下,增加20%;其它增加10%。
程序如下:
do case
case 工资<=200
replace 工资 with 工资*1.5
case 工资<=300
replace 工资 with 工资*1.3
case 工资<=500
replace 工资 with 工资*1.2
otherwise
replace 工资 with 工资*1.1
endcase
在这里要注意一个问题,不能把300元的 case 放在200元之前,否则一个100元的,按理应加50%,但当遇到小于300元的 case 时,其逻辑表达式为真(小于200元的肯定小于300元),因此就会执行后面的程序,加30%,并且执行完后,就不再执行其它的 case 了,这样就产生了错误的结果,所以应按从小到大的顺序来排列。
赋值语句(store...to)
将一个数据赋给一个变量。
语法:
STORE 表达式 TO 变量名表
参数:
表达式的值即为要赋给变量的数据。
变量名表即为要被赋值的各变量。
在这里可以是一个变量,也可以是多个变量,如果有多个变量,其间用“,”(逗号)隔开。
备注:
如果是给一个变量赋值,该语句可写成如下形式:
变量名=表达式
表达式可以是一个数值,也可以是一个算术式。
举例:
例1:将3赋给ab、xyz、jfz三个变量,程序如下:
store 3 to ab,xyz,jfz
例2:将变量gz的值加100赋给yfgz。
程序如下:
yfgz=gz+100
调用表单语句
运行一个由表单设计器设计的表单文件。
该文件是经编译过的。
语法:
DO FORM 表单文件名 [NAME 变量名 [LINKED]]
参数
表单文件名即是要运行的由表单设计器设计的表单文件名称。
变量名为调用该表单所用的变量名称,做为表单,不能直接用这的名称去调用它,必须将其赋给一个变量,然后用这个变量来调用它。
如果您不会在这个表单之外调用它,也可以不要这个变量。
在程序中产生的所有变量在程序运行结束后将被释放,即这些变量不再存在,因此也就无法继续调用这些变更,如果为了调试程序需要在程序运行结束后在命令窗口中调用这个表单,必须加上linked 子句。
举例:
在程序中调用xy7表单,并将赋给一个变量lucky,程序如下:
do form xy7 name lucky
调用子程序语句(do)
运行一个VFP程序。
当我们要在一个程序中调用另一个程序(子程序)时使用此命令。
语法:
DO 程序名
参数:
程序名即为被调用的程序名称。
备注:
如被调用的程序的扩展名是“prg”,调用时可不用带扩展名,否则要带上扩展名。
举例:
有一个程序,名称为 xy7.prg,调用它的程序如下:
do xy7
返回调用程序语句(return)
返回调用本程序(该语句所在程序)的程序。
前面讲过调用子程序的语句,从一个程序A调用另一个程序B后,系统便开始执行B程序中的语句,到一定时候往往要从程序B返回程序A,便可使用该语句。
语法:
RETURN
备注:
程序A调用程序B,当从B返回A后,系统接着执行调用语句(do b)下面的一条语句。
举例:
程序a.prg如下:
do while .not. eof()
if 工资<100
do b
endif
skip
enddo
程序b.prg如下:
replace 工资 with 工资*1.5 &&将工资增加50%
display &&显示出该记录,这样可以将所有增加了工资的记录显示出来
return
首先执行程序a.prg,当程序执行到 do b 语句时,便转去执行程序 b.prg ,在程序 b 中执行到 return语句时,又返回程序 a ,并接着执行 do b 的下一条语句 endif 。
启动事件处理语句(read events)
启动VFP的事件处理程序。
语法:
READ EVENTS
备注:
当该命令执行后,系统即停止继续执行后续的语句,这时我们可以调用之前所启动的菜单、表单等对象,并用这些对象的事件程序去完成相应的任务,直到发出clear events命令,系统才接着执行 read events 后面的命令语句。
可能初学者看了上面的内容还不是很清楚,不要紧,我们在后面课程中会进一步讲解。
清除事件处理语句(clear events)
终止由 read events 语句启动的事件处理程序。
语法:
clear events
备注:
发出该命令后,系统将继续执行read events之后的语句。
开关命令执行状态语句(set talk on/off)
确定是否显示VFP命令执行的状态。
语法:
SET TALK ON | OFF
参数:
ON 显示VFP命令执行的状态。
OFF 不显示VFP命令执行的状态。
备注:
使用时,on、off 二者之中必须选择一个。
很多VFP命令执行后,会显示执行后的结果状态,如locate for 命令执行,如找到记录的会显示被找到的记录号,否则会显示“已到文件尾”,但一般我们在程序中是不需要这些显示的,比如找到了记录就直接显示出来,没找到一般用一个对话框来给出更清楚的提示,所以在程序一开始往往要将 set talk 关闭。
结束程序语句(cancel)
结束当前正在运行的所有程序,返回VFP或操作系统。
语法:
cancel
备注:
数值转换字符函数(str())
返回与指定数值表达式对应的字符。
语法:
str(数值表达式[,长度[,小数位数]])
返回值的类型
字符型
参数:
数值表达式:要被转换为字符的数值表达式。
长度:转换后字符的长度。
该长度等于小数点和小数点右边第个数字所占字符的数目总和。
如果指定长度大于所需长度,自动在前面加空格补齐。
如果指定长度小于所需长度,返回一串星(*)号,表示数值溢出。
如省略长度,则默认长度为10。
小数位数:指定返回字符串中的小数位数。
如指定位数小于实际位数,则返回值四舍五入。
如指定位数大于实际位数,则加0补齐。
如省略小数位数,默认为0。
在指定了小数位数的情况下,如指定长度(第二个参数)小于总长度,但大于整数长度,则返回对小数部分做了四舍五入的字符。
备注:
返回后的值看起来还是数的形式,但它的数据类型已经变了,不再是一个数值,也就是不能再用来做加、减、乘、除的算术运算,但可以和字符进行加减。
比如:
'季度'+1
就会出错,因为一个字符是不能和一个数值相加的。
写成如下形式就可以了:
'季度'+str(1,1)
结果是:
季度1
注意,这里一定要指定长度,否则由于默认长度是10,就会出现如下结果:
季度 1
假如不知道数值有几位数怎么办呢?请参见ltrim()函数。
字符转换数值函数(val())
将数字组成的字符表达式转换成数字值。
语法:
val(字符表达式)
返回值的类型
数值型
参数:
字符表达式:要被转换为数值的字符表达式。
该表达式由最多16位的数字组成,若超过16位,则对其圆整。
备注:
val()函数从左到右返回字符表达式中的数字,直到遇到非数值型字符(忽略前面的空格)时为止。
若字符表达式的第一个字符不是数字,也不是正、负号,则返回0。
举例:
a='123'
如果按下面的写法,就会出错,因为一个字符不能与一个数值相加:
a+3
写成如下形式便可以了:
val(a)+3
结果是126。
取系统日期函数(date())
返回由操作系统控制的当前系统日期。
语法:
date()
返回值的类型
日期型
取年份函数(year())
从指定的日期表达式中返回年份。
语法:
year(日期表达式)
返回值的类型
数值型
参数:
日期表达式:指定的日期表达式,该函数即是返回其年份值。
举例:
year(date())
如果当前的系统日期是1999年2月5日,则显示的结果为1999。
取月份函数(month())
从指定的日期表达式中返回月份。
语法:
month(日期表达式)
返回值的类型
数值型
参数:
日期表达式:指定的日期表达式,该函数即是返回其月份值。
举例:
month(date())
如果当前的系统日期是1999年2月5日,则显示的结果为2。
取天日函数(day())
以数值型返回日期表达式是当月的第几天。
语法:
day(日期表达式)
返回值的类型
数值型
参数:
日期表达式:指定的日期表达式,该函数返回该日期是当月的第几天。
举例:
day(date())
如果当前的系统日期是1999年2月5日,则显示的结果为5。
取整函数(int())
返回数值表达式值的整数部分。
语法:
int(数值表达式)
返回值的类型
数值型
参数:
数值表达式:指定的数值表达式,该函数返回其整数部分。
举例:
int(123.47)
结果是123。
四舍五入函数(round())
对指定表达式进行四舍五入运算,并把结果返回。
语法:
round(数值表达式,小数位数)
返回值的类型
数值型
参数:
数值表达式:指定的数值表达式,该函数返回其四舍五入后的值。
小数位数:保留的小数位数。
举例:
int(123.457,2)
结果是123.46。
删除标记函数(delete())
确定当前记录是否已做删除标记,若已做删除标记,返回真(.t.),
否则返回假(.f.)。
语法:
delete([表别名|工作区])
返回值的类型:
逻辑型
参数:
表别名|工作区:该参数指定所要确定的表的别名或所在工作区,即您可以在一个工作区去检测另一工作区的表的记录是否做了删除标记,而另一工作区的表可用其别名或工作区号来指定。
该参数如省略,隐含为当前工作区,如有该参数的话,别名或工作区只选一个。
记录号函数(recno())
返回当前表或指定表中的当前记录号。
语法:
recno([表别名|工作区])
返回值的类型:
数值型
参数:
表别名|工作区:该参数指定所要确定的表的别名或所在工作区,即您可以在一个工作区去得到另一工作区的表的当前记录号,而另一工作区的表可用其别名或工作区号来指定。
该参数如省略,隐含为当前工作区,如有该参数的话,别名或工作区只选一个。
记录数函数(reccount())
返回当前表或指定表中的记录数目。
语法:
reccount([表别名|工作区])
返回值的类型:
数值型
参数:
表别名|工作区:该参数指定所要确定的表的别名或所在工作区,即您可以在一个工作区去得到另一工作区的表的记录数,而另一工作
区的表可用其别名或工作区号来指定。
该参数如省略,隐含为当前工作区,如有该参数的话,别名或工作区只选一个。
找到记录函数(found())
如果locate、continue、seek等查找记录的命令成功(即找到了记录),该函数返回“真”(.t.),否则返回“假”(.f.)。
语法:
found([表别名|工作区])
返回值的类型:
逻辑型
参数:
表别名|工作区:该参数指定所要确定的表的别名或所在工作区,即您可以在一个工作区知道另一个工作区上次查找记录是否找到,而另一工作区的表可用其别名或工作区号来指定。
该参数如省略,隐含为当前工作区,如有该参数的话,别名或工作区只选一个。
举例:
locate for 姓名='庄稼'
found()
如找到记录,显示结果为.t.,否则为.f.。
表结尾函数(eof())
确定记录指针是否在表的结尾处。
语法:
eof([表别名|工作区])
返回值的类型:
逻辑型
参数:
表别名|工作区:该参数指定所要确定的表的别名或所在工作区,即您可以在一个工作区知道另一个工作区表的指针是否在尾部,而另一工作区的表可用其别名或工作区号来指定。
该参数如省略,隐含为当前工作区,如有该参数的话,别名或工作区只选一个。
备注:
这里所说的结尾处,并非是指最后一个记录,而是最后一个记录的后面,即没有记录。
举例:
go bottom
skip
eof()
显示结果为.t.。
如果没有skip,仅仅走到最后一个记录,返回的将是.f.,而必须再往下跳一下才会是“真”结尾。
此时如输入命令:display,则没有记录显示。
这一点与bof()函数不同。
表开头函数(bof())
确定记录指针是否在表的开头。
语法:
bof([表别名|工作区])
返回值的类型:
逻辑型
参数:
表别名|工作区:该参数指定所要确定的表的别名或所在工作区,即您可以在一个工作区知道另一个工作区表的指针是否在开头,而另一工作区的表可用其别名或工作区号来指定。
该参数如省略,隐含为当前工作区,如有该参数的话,别名或工作区只选一个。
备注:
这里所说的开头,并非是指第一个记录,而是第一个记录的前面。
举例:
go top
skip -1
bof()
显示结果为.t.。
如果没有skip -1,仅仅走到第一个记录,返回的将是.f.,而必须再
往上跳一下才会是“真”开头。
但与eof()函数不同,此时如输入命令display,将显示第一条记录。
消除后续空格函数(trim())
将字符表达式的后续空格全部删除,并将结果返回。
语法:
trim(字符表达式)
返回值的类型:
字符型
参数:
字符表达式:指定的字符表达式,该函数将删除其后续空格。
备注:
trim()函数等同于rtrim()函数。
举例:
如表的“姓名”字段长度为10,当前内容为“张三”,那么如下语句:
姓名+'先生:'
其显示结果是:
张三先生:
而语句:
trim(姓名)+'先生:'
显示结果是:
张三先生
消除前导空格函数(ltrim())
将字符表达式前面的空格全部删除,并将结果返回。
语法:
trim(字符表达式)
返回值的类型:
字符型
参数:字符表达式:指定的字符表达式,该函数将删除其后续空
格。
举例:
在讲str()函数时我们举过一个例,即把一个字符与一个数值相加时,应采用如下形式:
'季度'+str(1,1)
但是当我们没有办法确定这个数值的位数时,这个办法就行不通了,您不可能规定它的长度只能是1或2等等。
那么怎么办呢,采用ltrim()函数可以解决了:
'项目'+ltrim(str(sz))
这里假设事先已有一个数值存入了sz变量,但不知道这个数值是几,也就更不知道有几位数,那么在隐含状态下,str()函数将把sz转换为长度为10的字符,其前面可能有若干空格,通过ltrim()函数的处理,不论前面有多少空格,都可以得到如下结果(假设数值是15):项目15
更多编程命令
BLANK 命令
如果发出该命令时不带任何参数,则清除当前记录中所有字段的数据。
语法
BLANK
[FIELDS 字段名列表]
[范围]
[FOR 条件]
[WHILE 条件]
[NOOPTIMIZE]
说明
如果使用了字段名列表,则清除指定字段中的数据,另外也可以在字段名前面加上别名,以清除其它工作区的表中数据,但要注意一点,如果当前工作区的记录指针指在了表的末尾,那么它也不能清除您所指定的其它工作区中的字段,即使其它工作区的记录指针没有指向末尾。
COPY FILE 命令
复制文件。
语法
COPY FILE 文件名1 TO 文件名2
说明
文件名中可以用“*”和“?”,如 *.prg。
要注意的一点是“文件名2”必须有,比如:
copy file *.prg to c:\temp\*.prg
不象DOS 的COPY 命令可以没有目的文件名,而且命令中的“FILE”也一定要有。
COPY STRUCTURE EXTENDED 命令
将当前工作区的表结构信息复制到另一表中。
语法
COPY STRUCTURE EXTENDED TO 表文件名 [FIELDS 字段名表]
参数说明
FileName:指定结构信息所存放的表文件名。
FIELDS 字段名表:指定需要复制表结构中哪些字段的信息,如省略,则复制所有字段的信息。
说明
该命令将一个表的各字段信息复制到一个新表中,每个字段为一个记录,这是一个专门的表,其字段是固定,这些字段分别记录各字段的字段名、长度、数据类型等等,各字段的字段名及其意义如下:
如图1,即为用 COPY STRUCTURE EXTENDED 命令生成的 rsda 表的结构信息表,在这个表中就可以看到 rsda.dbf 表的各字段情况。
那么用这个命令产生的结构信息表有什么用呢?这可以让我们在编程时改变一个表的结构,因为信息结构表也是个表,我们可以象操作一般表一样去修改它的内容,当然修改时要遵从表结构的有关规定,比如字段名不能超过10个字符,字段类型必须是上表中的字符之一,字段名不能重名等等。
当然我们修改了这个表后不会对原表马上产生作用,因为它们已经是分别独立的两个表,在物理上没有任何联系,但我们可以首先使用以下命令:
CREATE 表文件名 FROM 结构信息表文件名
根据结构信息表创建一个新表,再将原表的数据加到这个新表中,删除原表,将新表改为原表名,这样就修改了表的结构。
比如,我们要将 rsda 表部门字段的长度改为20,程序如下:
FLUSH 命令
将表和索引中的数据存入磁盘。
语法
FLUSH
说明
当我们修改一个表时,修改完后,我们可能并不马上将表关闭,那么这时所做的修改可能只是在内存中,而没有真正存到盘,如果这时死机或停电,那么......,所以我们可以在程序适当的地方用此命令确保数据存盘。
比如,我们可以在菜单中加个“保存”命令,该命令就调用FLUSH 语句,供操作者在适当的时候调用此命令来保存数据。
还可以用一个表单,在其中放一个计时器,在计时器的 timer 事件中用此命令,这样就做成一个具有自动保存数据的功能,甚至可以在菜单中加一个设置计时器时间的命令,以供操作者设置自动保存数据的间隔时间。
FOR...ENDFOR 命令
按指定的次数循环执行一组命令。
语法
FOR 变量=初始值 TO结束值 STEP 步长值
命令组
[EXIT]
[LOOP]
ENDFOR | NEXT
参数描述
变量:指定一个变量作为计数器,该变量可以不预先存在,FOR 命令会自动创建。
初始值TO 结束值:即计数器的初始值和结束值,也就是指定循环的次数。
STEP 步长值:设定计数器每次增加或减少的量,如果省略此子句,则每次增加1,比如for jsq=1 to 10,那么将会循环10次,如果是for jsq=1 to 10 step 2,那么循环将会是5次,因为每循环1次计数器增加2,从1到10只需增加5次就行了。
可能有人会问了,既然循环5次,那为什么不 for jsq=1 to 5 呢?这往往是为了在某些情况下使程序编起来方便和易于理解,比如要对数据表中的记录进行某项操作,要求每隔一条记录做一次,起始和结束的记录是根据具体情况变化的,也就是初始值和结束值都是变量,那么我们就可以使用步长子句,并将步长设为2,这样就不用具体去计算到底需要多少次循环了,如果再加上步长也是变量,即有时隔一条记录,有时会隔多条记录,则步长子句就更必要了。
值不断减小来进行某项操作时就需要了,比如我们需要对记录进行某项操作,这个操作要求先处理第10条记录,再第9条(因为在处理第9条时需要根据第10条的情况),依次到第1条,那么我们就可以:
很明显,虽然可以用其它方法,但这样编出的程序最简洁,一目了然。
EXIT 和 LOOP:与 DO WHILE 中的意义一样。
说明
计数器只有在大于结束值时才结束循环,即当计数器等于结束值时仍要循环,也就是说:
for jsq=1 to 10
是循环10次,而不是9次,也就是当jsq 的值为10时,还要循环一次,当它为11时,则退出循环,执行 endfor 之后的程序。
ON ERROR 命令
设置一命令,当系统错误发生时,该命令执行。
这也就是程序员们常说的错误捕获陷井。
所谓错误捕获陷井的意思就是在系统中启动一个监控程序,一旦错误发生,这个监控程序就将错误捕获,并不让错误显示出来,可保证程序的继续运行,然后用一个命令去对出现的错误进行处理,比如显示一个错误提示等。
如果错误不发生,这个命令则始终不执行。
语法
ON ERROR [命令]
参数说明
命令:此即为指定的在捕获错误后所要执行的程序。
一旦程序执行到某个语句发生错误,该命令即被执行,执行完后,接着执行发生错误的下一条语句。