注册 登录
编程论坛 VFP论坛

如何将表单下段代码的功能通过程序来实现?

cluna2013 发布于 2024-05-28 18:49, 579 次点击
这段代码用来将某个文件夹转换成.dbf表;当把代码拷贝到.prg程序中却执行不了。请教各位高手如何在程序中实现其功能?谢谢!
*ThisForm.wjtran            && 这是表单中自定义过程
LPARAMETERS tcFolder         && 将调用程序传入的数据,赋值给局部内存变量和数组。prg不能用。
LOCAL ARRAY laFiles[1]         && 创建的数组laFiles,[1]表示一组。
LOCAL lcFileName,ii         && 缺少这一步,会漏掉许多内容。
m.tcFolder=ADDBS(m.tcFolder)         && 向路径表达式添加一个反斜杠;没有这条,子目录出不来。
IF ADIR(m.laFiles,m.tcFolder + '*.*','ARD',1) < 3         && 若是文件长度小于3个字节,则不计算;少了D,不能进入子目录。
 RETURN .F.         
ENDIF         
ASORT(m.laFiles,3,-1,1)         && 按第3列排序数组,最后一位数大于0为降序排序。
FOR m.ii=1 TO ALEN(m.laFiles,1)         && LAN(数组名,数组属性),0[返回数组元素数目],1[返回数组的行数],2[返回数组的列数]。
 m.lcFileName=m.laFiles[m.ii,1]         && m.laFiles是 . ;缺少这一步,后面进行不下去
 DO CASE         
  CASE '.'==m.lcFileName Or '..'==m.lcFileName         && 设此可避免直接进入OTHERWISE,出现死循环
  CASE AT('D',m.laFiles[m.ii,5]) > 0         && 该位置若是D,则表明这是一个目录,执行下一行命令。
 ThisForm.wjtran(m.tcFolder + m.lcFileName)        && listfiles与m.tcFolder都是目录的路径,m.lcFileName则是子目录名称
  OTHERWISE         
 lafilesdt1=DTOC(m.lafiles[m.ii,3])        && 字符型日期
 lafilesdt2=m.lafiles[m.ii,4]        && m.lafiles[m.ii,4]是文件的时间值
 m.lafiles[m.ii,2]=CTOT([&lafilesdt1 &lafilesdt2])        && 字符日期时间
 Npath=SUBSTR(m.tcFolder,pathlong+1)        && Npath是子目录+孙目录
 Npath=SUBSTR(Npath,1,LEN(Npath)-1)        
 Npath=Npath+'\'        
 INSERT INTO files1 VALUES (m.lafiles[m.ii,1],m.tcFolder,m.lafiles[m.ii,2])        && 将数据录入到表中;此处不能用listfiles代替m.tcFolder
 ENDCASE         
ENDFOR        
16 回复
#2
csyx2024-05-28 19:11

wjtran( getdir() )

function wjtran(tcFolder)
    LOCAL ARRAY laFiles[1]         && 创建的数组laFiles,[1]表示一组。
    LOCAL lcFileName,ii         && 缺少这一步,会漏掉许多内容。
    m.tcFolder=ADDBS(m.tcFolder)         && 向路径表达式添加一个反斜杠;没有这条,子目录出不来。
    。。。
    FOR m.ii=1 TO ALEN(m.laFiles,1)         && LAN(数组名,数组属性),0[返回数组元素数目],1[返回数组的行数],2[返回数组的列数]。
        m.lcFileName=m.laFiles[m.ii,1]         && m.laFiles是 . ;缺少这一步,后面进行不下去
        DO CASE
        CASE '.'==m.lcFileName Or '..'==m.lcFileName         && 设此可避免直接进入OTHERWISE,出现死循环
        CASE AT('D',m.laFiles[m.ii,5]) > 0         && 该位置若是D,则表明这是一个目录,执行下一行命令。
            wjtran(m.tcFolder + m.lcFileName)        && listfiles与m.tcFolder都是目录的路径,m.lcFileName则是子目录名称
        OTHERWISE
        。。。
    ENDFOR
endfunc

#3
cluna20132024-05-28 20:37
以下是引用csyx在2024-5-28 19:11:22的发言:
wjtran( getdir() )

我过去曾经使用PROCEDURE来完成表单调用过程的方法,请问,您这段代码是不是下面要表达的意思?谢谢!
PROCEDURE wjtran
USE 打开要使用的表
。。。。。。
RETURN


[此贴子已经被作者于2024-5-28 20:42编辑过]

#4
cluna20132024-05-29 05:43
以下是引用csyx在2024-5-28 19:11:22的发言:
wjtran( getdir() )
function wjtran(tcFolder)
    LOCAL ARRAY laFiles[1]         && 创建的数组laFiles,[1]表示一组。
    LOCAL lcFileName,ii         && 缺少这一步,会漏掉许多内容。
    m.tcFolder=ADDBS(m.tcFolder)         && 向路径表达式添加一个反斜杠;没有这条,子目录出不来。
    IF ADIR(m.laFiles,m.tcFolder + '*.*','ARD',1) < 3         && 若是文件长度小于3个字节,则不计算;少了D,不能进入子目录。
        RETURN .F.
    ENDIF
    。。。

根据您的思路,接下来两行代码被提示【无效】
#5
csyx2024-05-29 06:26
1. 2楼代码是你的原代码,仅红色部分是我加上的,你说无效的两行代码只要是从原来的方法中复制的就不应该无效
2. use files1 这句不能放在 function 或者 procedure 中,因为一旦遇到子目录就会执行递归调用,重复打开同一个表不是个好点子

[此贴子已经被作者于2024-5-29 06:33编辑过]

#6
cluna20132024-05-29 06:35
回复 5楼 csyx
用wjtran( getdir() )代码指向文件夹,选定之后却回复【文件'wjtran.prg'不存在】,这是怎么回事?
无效的两行代码的确是从原来的方法中复制的

[此贴子已经被作者于2024-5-29 06:40编辑过]

#7
csyx2024-05-29 06:59
wjtran(getdir()) 这句是在你的 prg 文件里,还是在命令窗口中执行的?

如果是在 prg 过程文件里,那就 do 过程文件名.prg

如果是在命令窗口中执行,就先 set proc to 过程文件名.prg,再 wjtran(getdir())
或者 do wjtran in 过程文件名.prg with getdir()
#8
csyx2024-05-29 07:24
以下是引用cluna2013在2024-5-29 06:35:18的发言:
无效的两行代码的确是从原来的方法中复制的

复制都能让代码无效?那还有啥好想的,这台电脑嘎了,换新呗
#9
cluna20132024-05-29 08:22
回复 8楼 csyx
用function wjtran(tcFolder)……ENDFUNC 取代LPARAMETERS tcFolder不成功,说明缺东西。下面是.prg代码,您看问题出在哪?

SET SAFETY OFF                   && 指定在改写已有文件时不显示对话框
SET TALK OFF                    && 阻止对话结果发送到 Visual FoxPro 主窗口、系统信息窗口、图形状态栏或用户自定义窗口
SET SYSMENU OFF             && 在程序执行期间废止 Visual FoxPro 主菜单栏
SET DATE ANSI                    && 设置中国日期格式为yy.mm.dd
SET HOURS TO 24                && 将时间设为24小时制
SET CENTURY ON                && 设置日期格式为带世纪的
SET PATH TO CURDIR()            && 设置当前路径为默认路径
PUBLIC Rdn,Wjname,Apath,Nufiles1,Nufiles2,Search
Rdn=0
Wjname=[words]
CLOSE ALL
DO CASE
CASE DIRECTORY([C:\&Wjname\])=.T.
    Apath=FULLPATH([C:\&Wjname\])
CASE DIRECTORY([D:\&Wjname\])=.T.
    Apath=FULLPATH([D:\&Wjname\])
CASE DIRECTORY([E:\&Wjname\])=.T.
    Apath=FULLPATH([E:\&Wjname\])
CASE DIRECTORY([F:\&Wjname\])=.T.
    Apath=FULLPATH([F:\&Wjname\])
CASE DIRECTORY([G:\&Wjname\])=.T.
    Apath=FULLPATH([G:\&Wjname\])
OTHERWISE
    ThisForm.Refresh
    RETURN
ENDCASE
pathlong=LEN([&Apath])
Apath=SYS(5)+[\]+Apath
CREATE TABLE files1 (文件名 C(160), 路径 C(28), 修改时间 T)        && 创建表模板; 2024.5.11修改
DO wjtran
wjtran(Apath)        && 取代ThisForm.wjtran ([&Apath])
*ThisForm.wjtran ([&Apath])                                                  && 建立Apath函数
SORT TO Read ON 修改时间/D
SELECT 1
USE Read
GO RECNO()
Nufiles1=RECCOUNT()

DO FORM \Form\Reading.scx
READ EVENTS
RETURN

*PROCEDURE wjtran            && 由下面FUNCTION wjtran(tcFolder)取代
FUNCTION wjtran(tcFolder)
    LOCAL ARRAY laFiles[1]         && 创建的数组laFiles,[1]表示一组。
    LOCAL lcFileName,ii         && 缺少这一步,会漏掉许多内容。
    m.tcFolder=ADDBS(m.tcFolder)         && 向路径表达式添加一个反斜杠;没有这条,子目录出不来。
    IF ADIR(m.laFiles, m.tcFolder + '*.*', 'ARD', 1) < 3            && 若是文件长度小于3个字节,则不计算;少了D,不能进入子目录。
        RETURN .F.
    ENDIF
    ASORT(m.laFiles, 3, -1, 1)                                && 按第3列排序数组,最后一位数大于0为降序排序。
    FOR m.ii=1 TO ALEN(m.laFiles,1)         && LAN(数组名,数组属性),0[返回数组元素数目],1[返回数组的行数],2[返回数组的列数]。
        m.lcFileName=m.laFiles[m.ii,1]         && m.laFiles是 . ;缺少这一步,后面进行不下去
        DO CASE
        CASE '.'==m.lcFileName Or '..'==m.lcFileName         && 设此可避免直接进入OTHERWISE,出现死循环
        CASE AT('D',m.laFiles[m.ii,5]) > 0         && 该位置若是D,则表明这是一个目录,执行下一行命令。
        wjtran(m.tcFolder + m.lcFileName)        && listfiles与m.tcFolder都是目录的路径,m.lcFileName则是子目录名称
        OTHERWISE
        lafilesdt1=DTOC(m.lafiles[m.ii, 3])                    && 字符型日期
        lafilesdt2=m.lafiles[m.ii, 4]                            && m.lafiles[m.ii, 4]是文件的时间值
        m.lafiles[m.ii, 2]=CTOT([&lafilesdt1 &lafilesdt2])        && 字符日期时间
        Npath=SUBSTR(m.tcFolder,pathlong+1)            && Npath是子目录+孙目录
        Npath=SUBSTR(Npath,1,LEN(Npath)-1)
        Npath=Npath+'\'
        INSERT INTO files1 VALUES (m.lafiles[m.ii, 1], m.tcFolder, m.lafiles[m.ii, 2])    && 将数据录入到表中;此处不能用listfiles代替m.tcFolder
        ENDCASE
    ENDFOR
ENDFUNC
RETURN


[此贴子已经被作者于2024-5-29 09:02编辑过]

#10
csyx2024-05-29 08:42
太长了懒得看,执行结果是什么?
#11
cluna20132024-05-29 08:51
回复 10楼 csyx
在 m.tcFolder=ADDBS(m.tcFolder)打住,【程序错误】,【函数参数值、类型或书目无效。】
#12
csyx2024-05-29 09:06
先把明显的错误改了

1. prg 里面不可能允许使用 thisform 这样的关键字 - ThisForm.Refresh、ThisForm.subpath ([&Apath])
2. Apath=SYS(5)+[\]+Apath 这句几个意思? 其后加一句 messagebox(Apath) 看看是什么

#13
csyx2024-05-29 09:11
3. DO wjtran 这句不对。没给 wjtran传参数,这样一来 tcFolder 就变成 .F.,显然类型不对

#14
csyx2024-05-29 09:16
4. 随意使用宏替换符号,不良习惯,一旦文件夹名称中带有空格或小数点就会导致错误的结果

#15
cluna20132024-05-29 12:05
回复 14楼 csyx
1.thisform都去除;
2.Apath=SYS(5)+[\]+Apath

这一句还真错了,Apath直接表达为【E:\WORDS】
改正之后下面代码能产生files1表,却没有录入数据[INSERT INTO files1 VALUES (……]

CREATE TABLE files1 (文件名 C(160), 路径 C(28), 修改时间 T)        && 创建表模板; 2024.5.11修改
FUNCTION wjtran(tcFolder)
    LOCAL ARRAY laFiles[1]         && 创建的数组laFiles,[1]表示一组。
    LOCAL lcFileName,ii         && 缺少这一步,会漏掉许多内容。
    m.tcFolder=ADDBS(m.tcFolder)         && 向路径表达式添加一个反斜杠;没有这条,子目录出不来。
    IF ADIR(m.laFiles, m.tcFolder + '*.*', 'ARD', 1) < 3            && 若是文件长度小于3个字节,则不计算;少了D,不能进入子目录。
        RETURN .F.
    ENDIF
    ASORT(m.laFiles, 3, -1, 1)                                && 按第3列排序数组,最后一位数大于0为降序排序。
    FOR m.ii=1 TO ALEN(m.laFiles,1)         && LAN(数组名,数组属性),0[返回数组元素数目],1[返回数组的行数],2[返回数组的列数]。
        m.lcFileName=m.laFiles[m.ii,1]         && m.laFiles是 . ;缺少这一步,后面进行不下去
        DO CASE
        CASE '.'==m.lcFileName Or '..'==m.lcFileName         && 设此可避免直接进入OTHERWISE,出现死循环
        CASE AT('D',m.laFiles[m.ii,5]) > 0         && 该位置若是D,则表明这是一个目录,执行下一行命令。
        wjtran(m.tcFolder + m.lcFileName)        && listfiles与m.tcFolder都是目录的路径,m.lcFileName则是子目录名称
        OTHERWISE
        lafilesdt1=DTOC(m.lafiles[m.ii, 3])                    && 字符型日期
        lafilesdt2=m.lafiles[m.ii, 4]                            && m.lafiles[m.ii, 4]是文件的时间值
        m.lafiles[m.ii, 2]=CTOT([&lafilesdt1 &lafilesdt2])        && 字符日期时间
        Npath=SUBSTR(m.tcFolder,pathlong+1)            && Npath是子目录+孙目录
        Npath=SUBSTR(Npath,1,LEN(Npath)-1)
        Npath=Npath+'\'
        INSERT INTO files1 VALUES (m.lafiles[m.ii, 1], m.tcFolder, m.lafiles[m.ii, 2])    && 将数据录入到表中;此处不能用listfiles代替m.tcFolder
        ENDCASE
    ENDFOR
ENDFUNC
3.删除DO wjtran语句,直接跟上FUNCTION wjtran(tcFolder),结果产生了files1.dbf文件,但是没有数据被录入,而在表单过程程序之后,数据被录进表中;
4.宏替换表达的结果是正确的,不能不用。

[此贴子已经被作者于2024-5-29 12:07编辑过]

#16
csyx2024-05-29 14:19
1. 也不用删掉 DO wjtran,改成 DO wjtran with Apath 即可
2. DO wjtran with Apath 与 wjtran(Apath) 只需保留一条
3. procedure wjtran
   lparameters tcFolder
   。。。
   endproc

   function wjtran(tcFolder)
   。。。
   endfunc
是完全等效的两种写法,vfp 不区分用 procedure 还是 function

坚持使用宏替换的陋习是你的自由,不多说了



[此贴子已经被作者于2024-5-29 14:23编辑过]

#17
cluna20132024-05-29 17:26
回复 16楼 csyx
改用
2. DO wjtran with Apath 与 wjtran(Apath) 只需保留一条
3. procedure wjtran
   lparameters tcFolder
   。。。
   endproc
获得成功。谢谢!
效果:用.prg非常费时,远不及由表单执行该功能好用。

[此贴子已经被作者于2024-5-29 18:55编辑过]

1