注册 登录
编程论坛 VFP论坛

求助,VFP表单程序试运行没问题,连编后老报错,求助大家

yunyka 发布于 2020-08-03 15:53, 3775 次点击
写了一个小程序,想结合表单编成exe,在VFP中试运行没问题,但是运行连编后的exe就会在一个判断数据表某个字段是否没有非空记录的地方出错,显示我预置的信息(但是预留数据完全不会报错,试运行也能过)。
报错后exe还会报“文件正在使用”的错误,无法正常退出。

我的主程序:
ON KEY LABEL ALT+F4 DO quit_program
ON SHUTDOWN DO quit_program

SET SAFETY OFF
SET TALK ON

DO FORM D:\Desktop\活动排序\活动排序界面.scx
READ EVENTS

PROCEDURE quit_program
    RELEASE ALL
    CLOSE ALL
    CLEAR EVENTS
    CLEAR ALL
    DELETE FILE *.bak
    DELETE FILE *.dbf
    QUIT
ENDPROC

表单按钮点击代码:

sjk = thisform.名单地址.Value
IF NOT FILE(sjk)
    MESSAGEBOX("请先填写或选择正确名单地址!")
    CANCEL
ENDIF

wenti_gm = thisform.规模.Value
IF INT(wenti_gm)<>wenti_gm OR wenti_gm>99 OR wenti_gm<3
    MESSAGEBOX("请先填写正确的活动规模,3~99间的整数!")
    CANCEL
ENDIF

IF thisform.方法选择.枚举.Value = 1
    my_method = 1
ELSE
    my_method = 2
ENDIF
IF my_method == 1 AND wenti_gm>7
    MESSAGEBOX("活动数量较多,请选择精确计算以保证效率!")
    CANCEL
ENDIF

DO D:\Desktop\活动排序\测算主程序.prg WITH sjk,wenti_gm,my_method

测算主程序代码片段:

PARAMETERS sjk,wenti_gm,my_method
PUBLIC ARRAY cnt_arr4(1,1), cnt_arr5(1,1),ku_chk(1,1)

CREATE TABLE 活动排序.dbf ;
    ( 活动01 c(50))
FOR i = 2 TO wenti_gm
    field_name = "活动"+RIGHT("0"+ALLTRIM(STR(i)),2)
    ALTER table 活动排序 ADD &field_name c(50)
ENDFOR
SELECT 活动排序
APPEND FROM &sjk TYPE CSV
MESSAGEBOX("导入完成!")

**创建相邻两个活动的组合库,并计算两个活动的人次变动数
CLOSE DATABASES
USE 活动排序.dbf ALIAS a IN 1
field_num = AFIELDS(field_arr,"A")
FOR i = 1 TO field_num
    field_name = FIELD(i)
    SELECT COUNT(*) FROM a WHERE ALLTRIM(&field_name)<>"" INTO ARRAY ku_chk
    IF ku_chk(1,1) = 0
        CLOSE DATABASES ALL
        MESSAGEBOX(field_name+" 没有参与人员不合规,请检查提供名单是否合规!!")        &&连编的exe到这里就会出错,无论给的原始数据是什么样
        CANCEL
    ENDIF
ENDFOR

…………
烦请大家看看问题出在什么地方
21 回复
#2
yunyka2020-08-03 16:28
在线等,
#3
wengjl2020-08-03 16:31
 因为你的代码中采用的是绝对路径。所以有可能是:EXE文档的执行路径变了,程序就报错。

建议,采用相对路径编程。
#4
yunyka2020-08-03 16:37
回复 3楼 wengjl
有道理,我一会儿试试,但是我查看了一下exe终止时的文件,活动排序.dbf这个表成功生成并导入数据了,没有空白列的存在,不知道为什么会在那出错。
还有没有其它出错的可能?
#5
yunyka2020-08-03 17:31
3楼大哥的说法我试了,依旧VFP里面试运行可以,连编的exe会出错,无语了
#6
yunyka2020-08-03 17:54
我发现问题就是这句话:
SELECT COUNT(*) FROM a WHERE ALLTRIM(&field_name)<>"" INTO ARRAY ku_chk
在exe下无论怎么查,ku_chk都是0,但是我用exe运行的过程文件自己重新用这句话查了一下是有结果数据的
不知道哪位高人能解释一下为什么么?因为我程序后面还有很多类似的语句……
#7
jhcwk2020-08-03 18:02
语句 field_name = "活动"+RIGHT("0"+ALLTRIM(STR(i)),2)
wenti_gm是3~99间的整数
#8
yunyka2020-08-03 18:12
回复 7楼 jhcwk
这句话有什么问题么?不太明白
#9
xuminxz2020-08-03 21:32
这个问题已经出现多次了,请遵守VFP基本要求。不要用a-j这10个字母单独作表名或别名,否则可能会出现无法预知的错误。
另外,CLOSE DATABASES是什么目的?它只关闭数据库不关闭数据表,注意区分数据库与数据表的概念。
调试时,你没有打开其它表,运行时可能打了其它表。打开前10个表默认别名由a-j。所以,你运行时可能会提示别名已使用。
注意,在SQL语句中内部别名,不受此规定影响。
SELECT COUNT(*) FROM a WHERE ALLTRIM(&field_name)<>"" INTO ARRAY ku_chk中的a是程序运行时第一个打开的表,不一定是你指定的表。

[此贴子已经被作者于2020-8-3 21:43编辑过]

#10
wengjl2020-08-04 08:56
以下是引用yunyka在2020-8-3 15:53:38的发言:

写了一个小程序,想结合表单编成exe,在VFP中试运行没问题,但是运行连编后的exe就会在一个判断数据表某个字段是否没有非空记录的地方出错,显示我预置的信息(但是预留数据完全不会报错,试运行也能过)。
报错后exe还会报“文件正在使用”的错误,无法正常退出。

我的主程序:
ON KEY LABEL ALT+F4 DO quit_program
ON SHUTDOWN DO quit_program

SET SAFETY OFF
SET TALK ON

DO FORM D:\Desktop\活动排序\活动排序界面.scx
READ EVENTS

PROCEDURE quit_program
    RELEASE ALL
    CLOSE ALL
    CLEAR EVENTS
    CLEAR ALL
    DELETE FILE *.bak
    DELETE FILE *.dbf
    QUIT
ENDPROC

表单按钮点击代码:

sjk = thisform.名单地址.Value
IF NOT FILE(sjk)
    MESSAGEBOX("请先填写或选择正确名单地址!")
    CANCEL
ENDIF

wenti_gm = thisform.规模.Value
IF INT(wenti_gm)<>wenti_gm OR wenti_gm>99 OR wenti_gm<3
    MESSAGEBOX("请先填写正确的活动规模,3~99间的整数!")
    CANCEL
ENDIF

IF thisform.方法选择.枚举.Value = 1
    my_method = 1
ELSE
    my_method = 2
ENDIF
IF my_method == 1 AND wenti_gm>7
    MESSAGEBOX("活动数量较多,请选择精确计算以保证效率!")
    CANCEL
ENDIF

DO D:\Desktop\活动排序\测算主程序.prg WITH sjk,wenti_gm,my_method

测算主程序代码片段:

PARAMETERS sjk,wenti_gm,my_method
PUBLIC ARRAY cnt_arr4(1,1), cnt_arr5(1,1),ku_chk(1,1)

CREATE TABLE 活动排序.dbf ;
    ( 活动01 c(50))
FOR i = 2 TO wenti_gm
    field_name = "活动"+RIGHT("0"+ALLTRIM(STR(i)),2)
    ALTER table 活动排序 ADD &field_name c(50)
ENDFOR
SELECT 活动排序
APPEND FROM &sjk TYPE CSV
MESSAGEBOX("导入完成!")

**创建相邻两个活动的组合库,并计算两个活动的人次变动数
CLOSE DATABASES
USE 活动排序.dbf ALIAS a IN 1
field_num = AFIELDS(field_arr,"A")
FOR i = 1 TO field_num
    field_name = FIELD(i)
    SELECT COUNT(*) FROM a WHERE ALLTRIM(&field_name)<>"" INTO ARRAY ku_chk
    IF ku_chk(1,1) = 0
        CLOSE DATABASES ALL
        MESSAGEBOX(field_name+" 没有参与人员不合规,请检查提供名单是否合规!!")        &&连编的exe到这里就会出错,无论给的原始数据是什么样
        CANCEL
    ENDIF
ENDFOR

…………
烦请大家看看问题出在什么地方

SELECT COUNT(*) FROM a WHERE EVALUATE(field_name)……
#11
sdta2020-08-04 09:51
IF ku_chk(1,1) = 0
改为
IF _tally = 0
试试
#12
yunyka2020-08-04 10:08
回复 9楼 xuminxz
多谢指导,受教了。写prg运行的时候一直没有出现类似的问题,所以没太在意,以后多注意一下。
但是这次的问题并不是这个原因导致的
#13
yunyka2020-08-04 10:12
回复 10楼 wengjl
的确是这句话的问题,你说得方法我还没试,但是我把
SELECT COUNT(*) FROM a WHERE alltrim(&field_name)<>"" INTO ARRAY ku_chk
改成
SELECT COUNT(*) FROM a WHERE NOT EMPTY(&field_name) INTO ARRAY ku_chk
程序就执行出正确结果了……
感觉很奇怪,为什么单独执行prg时alltrim(&field_name)<>""没问题,连编成exe之后就不行?
#14
yunyka2020-08-04 10:14
回复 11楼 sdta
感谢版主的关注,我找到问题所在了,把
SELECT COUNT(*) FROM a WHERE alltrim(&field_name)<>"" INTO ARRAY ku_chk
改成
SELECT COUNT(*) FROM a WHERE NOT EMPTY(&field_name) INTO ARRAY ku_chk
程序就执行出正确结果了……
感觉很奇怪,为什么单独执行prg时alltrim(&field_name)<>""没问题,连编成exe之后就不行?
#15
sdta2020-08-04 11:11
以下是引用yunyka在2020-8-4 10:14:29的发言:

感谢版主的关注,我找到问题所在了,把
SELECT COUNT(*) FROM a WHERE alltrim(&field_name)<>"" INTO ARRAY ku_chk
改成
SELECT COUNT(*) FROM a WHERE NOT EMPTY(&field_name) INTO ARRAY ku_chk
程序就执行出正确结果了……
感觉很奇怪,为什么单独执行prg时alltrim(&field_name)<>""没问题,连编成exe之后就不行?

这样改也行
按我说的方法改也行,问题就是出现在查询数据为空的情况下
#16
xuminxz2020-08-04 15:04
把所有的CLOSE DATABASES改为close table 试试
#17
吹水佬2020-08-04 16:24
观察一下,结果是什么?
mm = "1"
? mm == ""
? mm <> ""
? "" <> mm
#18
yunyka2020-08-04 16:57
回复 19楼 吹水佬
版主的意思是与空字符的比对结果么?
我运行结果是
只有本站会员才能查看附件,请 登录


好像没问题……
#19
吹水佬2020-08-04 19:44
回复 20楼 yunyka
只有本站会员才能查看附件,请 登录
#20
yunyka2020-08-04 22:40
回复 21楼 吹水佬
我之前为了确保比对不出错,默认exact on
我的结果和你的不一样应该是这个原因
感谢版主指教
#21
gs25367856782020-08-05 07:42
这位朋友,在VF中凡是出现
alltrim(&field_name)<>""
这种与空字条串比较的,一定失败!
应当改写成
LEN(alltrim(&field_name))>0
#22
yunyka2020-08-05 08:25
回复 23楼 gs2536785678
感谢指导,以后多注意下
1