简介:这是一份面向VFP初学者和进阶者的《Visual FoxPro 9.0 实用培训教程》电子资料包,聚焦数据库开发全流程,从数据库基础、环境设置、数据表与字段操作,到SQL查询、视图、表单设计、面向过程与面向对象程序设计、报表标签、菜单对话框,再到ODBC连接其他数据库和高级特性均有系统讲解,既适合零基础自学,也适合短期培训班使用。资源包共3个文件,核心为PDF教程,含各知识点详细讲解与实例演示;同时附带HTM格式的打开说明页和图书资源站点的URL快捷方式,便于扩展获取资料;整包约31.32MB,结构简单,下载后即可学习。目前已有359人在CSDN学习该资源。通过这份资料,读者可完整掌握VFP 9.0建表、查询、表单交互、报表输出、菜单定制等实操能力,并理解关系型数据库的通用设计与开发思路,为后续学习SQL Server或Oracle等数据库系统打下扎实基础。 这几年我接过最多的业务之一,就是给"看着像古董但每天都在用"的系统做维护。大概2018年,一个客户把跑了快十年的会员积分系统交到我手上,整套东西就是Visual FoxPro 9.0写的。第一反应自然是想劝对方重写,但等我把十几张数据表和五六十个表单翻完,这个念头彻底打消了——业务逻辑没变、数据量不算大、人员操作习惯已经固化,重写的成本远超想象。后来我做的只是修补报表、加几个查询界面、把数据平稳导到新平台。这类需求,Visual FoxPro 9.0这门老技术反而最顺手。
这篇教程不是照着大学教材念概念,而是写给真正要维护VFP 9.0老系统、或者要在这个平台上做二次开发的人。从环境搭建讲起,依次覆盖数据表设计、表单开发、报表菜单、连编分发,再到老系统最常见的排错点,尽量给出能直接抄的代码和操作路径。无论你是刚被安排接手旧系统的"新人",还是想搞懂VFP 9.0到底能干什么的开发者,这篇内容应该都能帮你少走弯路。
1. 为什么2024年还有人在维护VFP 9.0系统
1.1 VFP 9.0的技术底子到底怎么样
Visual FoxPro 9.0是微软FoxPro产品线的最后一个正式版本,2004年发布,2007年发布SP2之后再没有版本更新,官方支持也早已结束。但Stop Support不等于Stop Working,恰恰相反,VFP 9.0自带的那个关系型数据库引擎,加上一套完整的快速开发环境,让它在一众中小型管理软件里活得非常久。
它的核心能力可以归纳成四点:
- 原生.DBF数据表,单表操作速度极快,几十万条记录完全没压力。
- 内置SQL语法,SELECT、INSERT、UPDATE、DELETE都能直接用。
- 集成了表单设计器、报表设计器、菜单设计器,拖拖控件就能出界面。
- 能编译成独立EXE,目标机器只需要放运行库,不需要装完整开发环境。
说白了,VFP 9.0就是"数据库引擎+编程语言+界面设计器"三合一。放在当年,一个懂数据库的人用一周就能拼出一个能上线的进销存系统,这是它当年普及的根本原因。
1.2 现在还在哪里看到它
我接触到的VFP 9.0系统主要集中在三个场景:
- 中小企业的会员管理、人事档案、进销存、收费系统。
- 学校、医院、事业单位的内部信息管理系统,很多是2005到2015年间建的。
- 老财务系统周边的一些打印、套表、数据整理小工具。
这些系统的共同特点是:数据积累了十几年、业务流程和操作人员深度绑定、换个系统意味着全员重新培训和数据迁移。所以现实往往是,系统还在稳定跑,但没人敢动它。这时候懂VFP 9.0的人就成了"稀缺物种"——不是因为它新,而是因为能听懂老代码、能扩新功能、能平安把数据导出去的人不多。
2. 环境准备与项目组织:别急着写代码
2.1 安装后的第一轮设置
VFP 9.0的安装包不大,装起来也没那么多幺蛾子。装完第一次启动,我建议先把下面三件事做掉,否则以后各种灵异报错:
- 设置默认目录。菜单里找到 Tools -> Options -> File Locations,把 Default Directory 指向你的工作目录。VFP对"当前目录"极其敏感,文件明明在眼前却报"文件不存在",八成就是路径问题。
- 把 Look 页里那些花哨的动画、欢迎对话框关掉,老机器跑起来能快一点。
- 打开命令窗口(Command Window),以后你的大部分操作都会在这里完成。
2.2 项目文件、数据表、程序文件的关系
正规的VFP 9.0系统一定是以项目文件(.pjx)为组织中心的。项目文件管理所有资源:数据表、视图、程序、表单、报表、菜单,最后统一连编成EXE。
我见过太多人图省事,数据表和程序文件散落在不同文件夹,结果半年后自己都找不到对应关系。正确做法是:
项目根目录\ 数据\ *.dbf *.cdx *.fpt 程序\ *.prg 表单\ *.scx *.sct 报表\ *.frx *.frt 菜单\ *.mnx *.mpr 输出\ exe和运行库项目文件里引用的都是相对路径,整体目录拷走就能换台机器继续开发。这一点在维护老系统时特别重要。
2.3 命令窗口是VFP的灵魂
VFP和其他开发工具最大的不同,就是它有一个随时可用的命令窗口。你敲一行命令回车就立即执行,查数据、建表、改设置全都行,比一层层点菜单高效得多。平时我基本不用菜单建表,直接敲:
CREATE TABLE customers (cid C(10), cname C(20), balance N(12,2))命令窗口还是最好的调试场地。变量值到底是多少,随手敲一个问号就能看到:
cname = "张三" ? cname很多老程序员调试VFP程序都是这么干的,哪有问题就把哪一段逻辑搬进命令窗口跑一遍,比加断点还快。
3. 数据表与索引:VFP 9.0的地基工程
3.1 字段类型怎么选才不后悔
VFP的字段类型跟主流数据库差得挺远,新手最容易在类型选择上吃亏。常用类型有这么几种:
| 类型 | 说明 | 使用注意 |
|---|---|---|
| C 字符型 | 必须指定宽度 | 编号、姓名、地址都用它 |
| N 数值型 | 需指定总宽和小数位 | 金额用 N(12,2) |
| D 日期型 | 固定8字节 | 不需要指定宽度 |
| T 日期时间型 | 记录到秒 | 适合流水日志 |
| L 逻辑型 | .T. / .F. | 适合开关状态 |
| M 备注型 | 存大段文本 | 内容存.fpt文件 |
| G 通用型 | 存OLE对象 | 尽量别用 |
两个经验。第一,编号字段老老实实用C(10)这类字符型,不要用数值型——很多编号带前导零、带横杠,数值型一存就变形。第二,金额和数量这类要参与计算的字段用N(12,2),整数部分留够余量,不够再改很麻烦。
3.2 索引不只是为了排序
VFP里索引的作用比一般数据库更复合:它既能改变记录的显示顺序,又能加速查询,还能作为表间关联的桥梁。建索引的语法很简单:
USE customers INDEX ON cid TAG cid_c索引类型分主索引、候选索引和普通索引。主索引一个表只能有一个,且值必须唯一;候选索引类似,但可以有多个;普通索引允许重复值,最常用。
设置了多个索引之后,用SET ORDER TO切换当前的生效索引:
SET ORDER TO cid_c还有一个细节:VFP默认索引文件的扩展名是.CDX,一个表的所有索引都放在同一个CDX文件里,删除或改名时别漏了它。
3.3 多表数据怎么关联
老系统里经常用SET RELATION做表间关联,这种写法在程序里容易绕晕。我更推荐直接用SQL JOIN,逻辑清晰,看代码的人不容易误解:
SELECT a.cid, a.cname, b.score ; FROM customers a JOIN scores b ON a.cid = b.cid ; INTO CURSOR tmp_result分号是VFP的续行符,SQL太长就拆成多行写。INTO CURSOR的用法后面会细说,先记住一个结论:能用SQL解决的问题,别用过程式循环硬扛。
4. 命令窗口到程序文件:两种开发层次怎么配
4.1 过程式写法依然是老系统的主调
VFP 9.0支持完整的面向对象编程,但存量老系统大部分还是过程式写法,你得能看懂。最常见的几个结构是:
* 条件循环处理数据 SELECT customers SCAN FOR balance > 1000 ? cname, balance ENDSCAN * 按索引顺序累计 STORE 0 TO nTotal SELECT orders SCAN nTotal = nTotal + amount ENDSCANSCAN...ENDSCAN是VFP特色的记录遍历结构,省去了显式的移动指针操作。看老代码时先找SCAN和DO WHILE,这是读懂数据流向的关键。
4.2 面向对象部分主要落在表单事件里
VFP 9.0支持用DEFINE CLASS自定义类,也支持完全事件驱动的表单模型。但实际维护老系统,面向对象的主战场在表单的事件代码里——Init、Click、GotFocus、Valid这些。写事件代码时有一个原则:事件里只做一件事,复杂的逻辑拆成单独的方法或过程。
PROCEDURE cmdSave.Click IF Thisform.SaveData() && 调用表单自定义方法 MESSAGEBOX("保存成功", 64, "提示") ELSE MESSAGEBOX("保存失败", 48, "提示") ENDIF ENDPROC这样每个事件代码都短小,出问题一眼能定位。
4.3 游标(Cursor)是最好用的数据中转站
INTO CURSOR 可能是VFP里性价比最高的一条命令。查询结果、汇总数据、临时加工结果,都可以塞进一个临时游标,直接在表单的Grid里显示,用完自动释放,不落盘、不污染数据目录:
SELECT * FROM customers WHERE balance > 5000 INTO CURSOR tmp_vip SELECT tmp_vip BROWSE游标不是物理表,只是内存中的临时数据集。它最大的好处是:你可以在不碰原始表的情况下完成各种筛选和展示,多用户环境下尤其安全。
5. 表单实战:从数据环境到增删改查
5.1 数据环境:打开表单的正确姿势
VFP的表单里,第一件事永远是设置数据环境(Data Environment),而不是急着拖控件。右键表单选"数据环境",把需要的表加进去,再设置好表和表之间的关系。
数据环境的价值在于:表单启动时自动打开表、自动设置索引顺序、关闭时自动释放表。这样表单代码里不需要手工USE和CLOSE,既省事又严谨。凡是表单里直接写USE表名、退出再手动USE关闭的,都是不规范的做法,迟早出问题。
字段绑定也很方便。TextBox的ControlSource属性可以直接下拉选customers.cname,这样控件和字段一一对应,显示和录入都自动完成。
5.2 缓冲模式:多用户不丢数据的保障
单机环境的表单直接改表没问题,但上了多用户环境,直接更新记录可能引发覆盖冲突。标准做法是先开启缓冲:
=CURSORSETPROP("Buffering", 3, "customers") && 行缓冲参数3是开放行缓冲,意思是修改先存在缓冲区,不立即写盘;参数5是表缓冲,适合批量修改。保存时调用TABLEUPDATE(),后悔了用TABLEREVERT(.T.)回滚:
IF TABLEUPDATE(.T.) MESSAGEBOX("保存成功", 64) ELSE =ROLLBACK() MESSAGEBOX("保存失败:" + MESSAGE(), 48, "错误") ENDIF5.3 保存按钮的完整逻辑
综合上面几点,一个标准的保存按钮代码长这样:
PROCEDURE cmdSave.Click * 必填校验 IF EMPTY(Thisform.txtCid.Value) MESSAGEBOX("请填写客户编号", 48, "提示") Thisform.txtCid.SetFocus() RETURN ENDIF * 写入数据表 IF TABLEUPDATE(.T.) MESSAGEBOX("保存成功", 64, "操作完成") Else =ROLLBACK() MESSAGEBOX("保存失败:" + MESSAGE(), 48, "错误") ENDIF ENDPROC保存之前先做必填校验、再提交缓冲,这个顺序不要反。有些老代码先把数据写了,再回头检查空值,结果产生大量脏数据,这是我在真实系统里见过的教训。
5.4 查询条件与Grid显示的组合
列表界面离不开Grid控件。最省事的做法是:文本框输入关键字,点查询按钮执行SQL,结果进游标,再把游标指定给Grid:
PROCEDURE cmdQuery.Click cKey = ALLTRIM(Thisform.txtKey.Value) SELECT * FROM customers ; WHERE cname LIKE '%' + cKey + '%' ; INTO CURSOR tmp_list Thisform.Grid1.RecordSource = "tmp_list" ENDPROCVFP的SQL支持通配符LIKE,配合字符串拼接就能实现模糊查询。注意SQL里中文字符串用单引号,和本地习惯的双引号不一样,写错会报语法错误。
6. 报表、菜单与连编分发:把系统完整交出去
6.1 报表设计器的正确用法
VFP的报表设计器基于"数据带区"概念,分成页标头、细节、页注脚、汇总等区域。最快入手的方式是先建一个快速报表,再微调布局:
- 在项目管理器里新建报表,打开报表设计器。
- 菜单"报表"->"快速报表",选择数据表和字段。
- 调整各字段在细节带区的位置。
- 在页注脚插入页码表达式。
预览和打印都靠命令:
REPORT FORM customers_report PREVIEW REPORT FORM customers_report TO PRINTER报表里最常见的坑是字段宽度不够、中文被截断。设计器里要多留余量,字体建议用宋体或微软雅黑,老系统用仿宋的也不少。
6.2 菜单与主程序
菜单在项目管理器里新建,用菜单设计器画出来,保存后生成.MNX文件,再通过"生成"得到.MPR程序文件。主程序里这样挂载:
DO mainmenu.mpr READ EVENTSREAD EVENTS是不可缺少的一行——它是VFP进入事件循环的开关。没有它,窗口显示一下程序就退了;有了它,程序才会一直等着用户操作,直到执行CLEAR EVENTS才退出。
6.3 连编EXE和运行库分发
开发完成后,在项目管理器里点"连编",选择"连编可执行程序",生成EXE。分发到目标机器时,如果对方没装VFP,需要把运行库文件一起带上,最核心的是VFP9R.DLL,还有VFP9RENU.DLL(英文资源)、VFP9RCHS.DLL(简体中文资源,取决于有没有用到中文内置对话框)。
经验之谈:运行库和EXE放同一个目录最省事,别指望目标机器上的System32都是干净的。老系统从一台机器搬到另一台机器,80%的启动失败都是因为运行库缺失或版本不对。
7. 老系统排错经验:路径、日期、并发与数据互通
7.1 程序开头必须做的几件事
我每次接手老系统,都会在入口程序顶部加这几行,能省掉无数莫名其妙的坑:
SET DEFAULT TO 你的工作目录 SET PATH TO 数据目录 SET DATE TO YMD SET MARK TO "-" SET DELETED ON SET EXCLUSIVE OFF逐一解释:SET DEFAULT解决找不到文件;SET DATE解决日期格式混乱;SET DELETED决定带删除标记的记录是否还参与操作——必须设为ON,否则统计数字会跟着错;SET EXCLUSIVE OFF让表以共享方式打开,多用户环境下必须这么设,否则第二个人打不开表。
7.2 并发与锁表问题
共享模式下,写记录之前要确认表没有被别人锁住。老系统里常见的错误是不做任何判断直接REPLACE,结果在高峰期丢数据。可靠做法是:
IF RLOCK() REPLACE balance WITH balance + 100 UNLOCK ELSE MESSAGEBOX("记录正被其他人使用,请稍后重试", 48, "提示") ENDIFRLOCK()请求锁定当前记录,成功返回.T.,操作完立即UNLOCK释放。批量更新时用SET REPROCESS TO 3让系统自动重试几次,避免网络闪断导致瞬间失败。
7.3 和其他系统互通的三条路
维护老系统往往不只是VFP内部的事,数据总要流出去。实践中我用得最多的是三种方式:
- 其他语言读VFP数据:用VFP OLE DB Provider(VFPOLEDB)或者ODBC的Microsoft Visual FoxPro Driver,C#、Python、Java都能连上.DBF文件。
- VFP读SQL Server:用SQL Pass-Through技术,先连接再执行:
nHandle = SQLSTRINGCONNECT("driver=SQL Server;server=服务器名;database=库名;uid=sa;pwd=密码") SQLEXEC(nHandle, "SELECT * FROM 业务表", "tmp_sql") SELECT tmp_sql BROWSE- 导出Excel/CSV:简单数据直接
COPY TO temp TYPE XLS,复杂报表可以生成CSV或XML,再交给其他工具处理。
7.4 动手前先备份
最后说一条我用血泪换来的规矩:任何对老系统的改动,先整体复制项目目录,再单独把.DBF文件备一份。VFP没有内置的版本管理,一个错误的REPLACE就可能把整个表更新掉,而且没有后悔药。我习惯在服务器上留一个带日期的备份目录,改一次备一次,看起来笨,但每次出事都是它捞了我。
Visual FoxPro 9.0确实老了,官方连补丁都不再更新,但存量系统的现实需求还在,能读懂老代码、能安全操作里面的数据,本身就是一种很值钱的能力。学它的时候别贪多求全,把数据表、索引、表单、报表、菜单这条主线串起来,再把程序入口那几条SET命令背熟,基本就能应付日常维护了。至于要不要把老系统迁移到新平台,那是另一个话题——前提永远是先把老平台的逻辑和数据摸透,而这恰恰是VFP基础扎实的人最擅长的事。
本文还有配套的精品资源,点击获取