医院管理系统
现代化的医院也应该有现代化的管理系统。在科技日益发达的今天,人们的身体健康也在不断受到重视。因此,医院进行现代化管理就变得尤为重要。这里,我们以一个典型的医院管理系统为例子,来讲述如何建立一个使用的医院管理系统。
1.1. 系统设计
1.1系统目标设计
通过一个医院管理系统,使医院的管理工作系统化、规范化、自动化,从而达到提高医院管理效率的目的。1.2开发设计思想
本系统开发设计思想:
尽量采用公司现有软硬件环境,及先进的管理系统开发方案,从
而达到充分利用公司现有资源,提高系统开发水平和应用效果的目的;
系统应符合医院员工管理的规定,满足医院日常管理的需要,并
达到操作过程中的直观、方便、实用、安全等要求;
系统采用模块化程序设计方法,这样既便于系统功能的各种组合,
又便于未参与开发的技术维护人员补充、维护。
系统应具备数据维护功能,及时根据用户需求进行数据的添加、
删除、修改、备份等操作。
1.3开发和运行环境选择
开发工具:Visual FoxPro 6.0;
运行环境:Window9.x或Windows20001.4系统功能分析
系统功能分析事在系统开发的总体任务的基础上完成的。本例子中的医院管理系统需要完成功能主要有:
员工各种信息的输入,包括员工基本细细、职称、岗位。
员工各种的查询、修改,包括员工基本信息、职称、岗位、工资
等。
员工的人事调动管理。 病人信息的管理。 病院病床的管理。 药剂资源管理。 仪器资源管理。
系统用户管理、权限管理。1.5系统功能模块设计
在系统功能分析的基础上,考虑Visual FoxPro 6.0 程序编制的特点,得
到如图1所示的系统功能模块图。
管理系统 图1 系统功能模块图
病床病人资料 图2 数据关系图
医生 针对本实例,通过对医院管理的内容和数据关系分析,我们设计的数据项和
2.2. 数据库设计
在数据库应用系统的开发过程中,数据库的结构设计是一个非常重要的问题。数据库结构设计的好坏将直接对应用系统的效率以及实现的效果产生影响,好的数据库结构会减小数据库的存储量,数据的完整性和一致性比较高,系统具有较快的相应速度,简化基于此数据库的应用程序的实现等。
在数据库系统开始设计的时候应该尽量考虑全面,尤其应该仔细考虑用户的各种需求,避免浪费不要的人力和物力。2.1数据库需求分析
数据库需求分析是数据结构设计的第一阶段,是非常重要的一个阶段。在这个阶段主要是收集基本数据、数据结构以及确定数据处理的流程,组成一份详尽的数据字典,为以后进一步设计打下基础。
在仔细调查医院管理过程的基础上,我们得到本系统所处理的数据关系如图2所示。
数据结构如下:
员工基本状况包括的数据项有员工号、员工姓名、性别、所在部
门、身份证号、生日、籍贯、国籍、民族、婚姻状况、健康状况、参加工作时间、员工状态、家庭住址、联系电话等。
员工工资状况包括的数据项有员工号、工资项别、工资金额等。 医院工作岗位信息包括的数据项有工作岗位代号、工作岗位名称
等。
医院部门信息包括的数据项有部门代号、部门名称、部门负责人
等。
病人信息包括的数据项有病人姓名、病人性别、入院时间、病人
所属科室、病人状况、病人主治医生、房间号、病床号等。
药剂资源管理信息包括的数据项有药剂代号、药剂名称、药剂价
格、药剂库存数量、备注等。
医疗仪器管理包括的数据项有仪器代号、仪器名称、仪器价格、
仪器数量、备注等。
有了上面的数据结构、数据项和数据关系,我们就进行下面的数据库设计。2.2数据库概念结构设计
这一设计阶段是在需求分析的基础上,设计出能够满足用户需求的各种实体,以及确定他们之间的关系,为后面的逻辑结构设计打下基础。本实例根据上面的设计规划出的实体有员工实体、部门实体、岗位实体、病人实体、药剂实体、仪器实体。
实体和实体之间的关系E-R图如图3所示。2.3数据库逻辑结构设计
我们需要将上面的数据库概念结构转化为Visual FoxPro 6.0数据库系统所支持的实际数据模型,也就是数据库的逻辑结构。
在上面的实体以及实体之间关系的基础上,我们就可以形成数据库中的表格以及各个表格之间的关系。
医院管理系统数据库中各个表格的设计结果如表1到表7所示。每个表格对应在数据库中的一个表。
工资病人病床1对应11对应对应n1医生1对应
JOB_ID
EMP_ID
EMP_XL
EMP_NO
DEPT_ID
列 名
JOB_NAME
EMP_DUTY
EMP_NAME
EMP_STATE
EMP_EMAIL
EMP_JOB_ID
DEPT_NAME
1DATEDATE
列 名
EMP_NATION
EMP_TELENO
EMP_HEALTH
EMP_GENDER
EMP_DEPT_ID
EMP_COUNTRY
EMP_BIRTHDAY
EMP_MARRIAGE
列 名
DEPT_MANAGER
EMP_HOMETOWN
EMP_STARTWORK
DEPT_VICEMANAGE
EMP_HOMEADDRESS
表3 为部门信息表
表2 为工作岗位情况表。
1
NUMBERIC(3)
CHARACTER(10)
表1为员工基本状况表(这里主要针对医生,读者可自行建立护士等的数据表),其中涵盖了常用的字段。
NUMBERIC(6)NUMBERIC(3)NUMBERIC(6)NUMBERIC(3)NUMBERIC(6)NUMBERIC(10)CHARACTER(2)CHARACTER(8)CHARACTER(2)CHARACTER(20)CHARACTER(10)CHARACTER(10)CHARACTER(10)CHARACTER(10)CHARACTER(10)CHARACTER(10)CHARACTER(10)CHARACTER(10)
NUMBERIC(6)
NULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNULLNOT NULL
表1 PERSONNEL员工基本状况表
数据类型可否为空
民族国籍籍贯生日性别学历职务联系电话家庭住址员工状态健康状况婚姻状况身份证号员工姓名所在部门号
说明
工作岗位代号参加工作时间员工号(主键)联系E-mail地址
NUMBERIC(3)
CHARACTER(10)
NULL
图3 实体之间关系E-R图
NTO NULL
表2 JOB工作岗位情况表数据类型可否为空
表3 DEPT 部门信息表数据类型可否为空
NULL
NULL
NULL
NOT NULL
n
工作岗位名称
部门名称
1
说 明
说 明
部门主任代号
工作岗位代号(主键)部门副主任代号
部门代号(主键)
TMS_USER
POTION_ID
TMS_PSWD
POTION_REM
PATIENT_BED
PATIENT_DOC
POTION_PRICE
POTION_NAME
PATIENT_DEPT
APPARATUS_ID
PATIENT_NAME
PATIENT_ROOM
PATIENT_STATE
PATIENT_GENDER
APPARATUS _REM
POTION_QUANTITY
APPARATUS _PRICE
APPARATUS _NAME
PATIENT_DATE_START
表5 为药剂信息表。
表4 为病人信息表。
APPARATUS _QUANTITY
表6 为医疗仪器信息表。
列 名列 名列 名
NUMBERIC(3)NUMBERIC(3)NUMBERIC(5,2)CHARACTER(40)CHARACTER(10)CHARACTER(2)CHARACTER(3)CHARACTER(2)CHARACTER(10)CHARACTER(10)CHARACTER(10)CHARACTER(10)
NUMBERIC(3)NUMBERIC(3)NUMBERIC(5,2)CHARACTER(40)CHARACTER(10)
列 名
CHARACTER(10)
NULLNULLNULLNULLNULLNULLNULLNULLNULLNOT NULLNOT NULLNOT NULLNOT NULL
表5 药剂信息表POTION
数据类型可否为空表6 医疗仪器信息表 APPARATUS
数据类型可否为空
NOT NULL
表7 管理TMS系统的用户口令表TMS数据类型可否为空
备注备注仪器数量仪器价格仪器名称药剂价格药剂名称病人病床号病人房间号药剂库存数量
说 明说 明说 明
仪器代号(主键)药剂代号(主键)病人状况病人主治医生
CHARACTER(20)
CHARACTER(10)
NULLNULL
表4 病人信息表PATIENT数据类型可否为空
NOT NULL
NOT NULL
NOT NULL
NOT NULL
口令
入院时间
病人性别
说明
病人所属科室
用户名(主键)
3 数据库结构的实现
在需求分析、概念结构设计的基础上得到数据的逻辑结构之后,我们就可以在Visual FoxPro6.0数据库系统中实现该逻辑结构。
病人姓名(主键)
一个企业可以有多个用户管理该系统,因此就需要为不同的用户设置不同的口令。
表7 为管理TMS系统的用户口令表。
在Visual FoxPro6.0的主菜单中单击,在弹出的“New(新建)”对话框中选中“Project(项目)”,单击“新建文件”按钮。此时弹出“Create(创建)”对话框,这是为该项目设置存储路径,请将项目名设为Hospital(医院)的项目,保
存在磁盘中。例如“D:\\hospital”文件夹。
项目建立好后,就可以实现数据库结构了。注意,Visual FoxPro6.0的数据库结构试依靠项目存在的。
在如图4所示Project Manager(项目管理器)中展开Data(数据)文件夹,鼠标选中Database(数据库),单击右侧的New(新建)按钮。
在弹出的“New Database(新建数据库)”对话框中单击“New Database(新建数据库)”选项,然后将文件存储为D:\\hospital\\database\\hospital.dbc。
现在就可以为数据库添加数据表了,表的具体内容如表1至7所示。项目以表4为例讲解数据表的创建过程。
图4 新建数据库
在弹出的Database Designer(数据库设计器)中单击鼠标右键,选择“New
Table(新建表)”,如图5所示。将其存储为“D:\\ hospital\\database\\patient.dbc”。所有的表均放在“D:\\ hospital\\database\\”目录下,以便使用和管理。
图5 新建数据表
图 6 设置表的字段
现在可以为表填写内容了,设计表的内容主要试设计表中的字段的
Name(名称)、Type(类型)、Width(宽度)以及表的DecimalIndex(索引)。表中的字段如图6所示,具体内容参见前面的表4。
表的结构设计好后,单击“OK”按钮存储,关闭设计栏,系统会提示为刚完成的表输入数据。输入数据后一个数据表的创建就完成了。
4 各个功能模块的创建
图7 欢迎界面
4.1系统欢迎界面及主界面模块设计
当软件运行出现欢迎界面后一段时间内按下空格键后就进入系统主界面。1.1. 欢迎界面设计
这个部分的设计思路试为整个系统设计一个“欢迎使用”的画面,为防止单调,加入字体闪烁的效果。其步骤如下:
为表单加上背景画面,设定表单的Picture属性为希望加入的图画路径及名称,在图片上面有颜色和大小随时间改变的文字“欢迎使用医院管理系统”。
设置表单的Icon属性为一图标文件(.ico),可以代表表单左上角的VISUAL FOXPRO图标。
为表单添加一个标签控件,注明软件设计者等信息,表单的界面如图17所示。
为表单添加一个记时器(Timer)控件,他的属性Interval表明间隔时间。在记时器的Timer事件中编程使该表单释放并调用主界面表单。Timer事件是从表单运行到Interval属性规定的时间间隔过后被触发的。
在表单的KeyPress Event事件中编写代码,使当空格键按下时将该表单释放并执行主界面表单。KeyPress Event事件是当有键按下时被触发的。
在表单的Click Event事件中编写代码,使当鼠标单击时将该表单释放并执行主界面表单。该表单如图7所示。
根据前面的设计思路,为了实现表单中的字体颜色何大小随事件变化(本例为每秒变化一次),拟定了如下的步骤:
新建一个表单,存储为“ksjm”。在表单适当位置添加Label控件,填入所续显示的文字。
在表单的Init Event事件中填入如下代码:public ipublic ji=0j=0
设计两个全局变量以控制事件发生条件。
在表单的KeyPress Event事件中填入如下的代码:LPARAMETERS nKeyCode, nShiftAltCtrlthisform.release*释放本表单
do form hospital\\form\\main*执行表单
在表单的Click Event事件中填入如下代码:thisform.release*释放本表单
do form hospital\\form\\main*执行表单main
在表单中添加一个Timer控件,设置其Interval属性为1000(单位是毫秒),表单中Timer的Timer Event事件的代码如下:
if i=0
thisform.label1.fontsize=22
*将表单中label1控件的字体大小设为22thisform.label2.fontsize=24
*将表单中label2控件的字体大小设为24thisform.label1.forecolor=16711935thisform.label2.forecolor=65535*控制显示字体的颜色和大小i=1j=j+1else
thisform.label1.fontsize=24 thisform.label2.fontsize=22
thisform.label1.forecolor=16711935 thisform.label2.forecolor=65535 *控制显示字体的颜色和大小 i=0 j=j+1 endif
*控制10次显示 if j>10
thisform.release
do form hospital\\form\\main *打开系统主界面 endif
这段代码的功能在于实现了界面上的字体随时间变化颜色和大小。
以上为欢迎界面的设计,接下来是主界面的设计。主界面的主要功能是引导使用者进入各个下级表单。
2.2. 系统主界面设计本表单的设计思路如下:
为表单设计背景和ico图标。
设置各个按钮引导使用者进入下一级表单。 设置“退出”按钮以便退出主程序。具体的操作步骤如下:
新建一个表单,存储为“main”。设置表单各外观参数。如表8所示。
表8 医院管理系统表单参数
属 性 名值说 明CAPTION医院管理系统表单标题WIDTH397表单宽HELGHT269表单高
ICON图标文件位置
为了使主界面功能清晰,首先加入两个容器控件(容器1和容器2)。
在容器1中加入3个按钮,分别为“门诊部”,“住院部”,“药品仪器”;容器2中加入1个按钮,为“员工管理”。
右下角加入按钮“退出”。
为各个按钮添加Click 事件代码。“门诊部”按钮代码如下:do form hospital\\form\\mzb
*打开“门诊部管理”界面,实例中本部分程序未编写thisform.enabled=.F.
“住院部” 按钮代码如下:do form hospital\\form\\zyb*打开“住院部管理”界面thisform.enabled=.F.
“药品仪器” 按钮代码如下:do form hospital\\form\\ypyq*打开“药品仪器管理”界面thisform.enabled=.F.
“员工管理” 按钮代码如下: do form hospital\\form\\yggl*打开“员工管理”界面thisform.enabled=.F.
“退出” 按钮代码如下:this form.release*释放本表单clear events*关闭整个系统
主界面表单如图5-8所示。5.4.2 住院部模块的设计
医院的住院部的病人管理及病床管理是本模块需要解决的问题。合理安排病床,使得病人在住院期有一个宽松的环境,不至于出现一个病房挤满而另一个病房一个病人也没有的状况,利用计算机来管理是非常有必要的。
1.住院部管理模块主界面
图5-9 住院部管理主界面
图5-8 系统主界面
本表单主要功能是引导使用者进入分级表单,因此力求简单明了。本表单的目标设计如图5-9所示,表单的名称为zyb。
清楚了本表单要设计的功能后,下面就是具体的操作步骤:新建一个表单,存储为“zyb”。
设置表单的各外观参数,如表5-9所示。
住院部主界面参数
属 性 名值说 明
CAPTION医院管理系统表单标题WIDTH389表单宽HELGHT203表单高
ICON图标文件位置
向表单中合适的位置添加Lable控件,填入“住院部数据管理”,为了是字体美观,将Lable控件的Alignment属性设置为“2-center”(居中),Font(字体)属性设置为“隶书”,FontSize(字体大小)设置为20。
在表单中加入Option Group(选项按钮组)组件。
本表单只用到了两个管理项目,故其Button Count属性设置为2。在控件
2.病人管理模块设计
上单击鼠标右键选Edit(编辑),将两个Button的Caption设置为需要的“病床管理”和“病人管理”并调整好位置和大小。
“确定”按钮的功能是根据选择者所选的Option Group的选项进入不同的分级表单,其代码如下“
selename=thisform.optiongroup.value*判断所选的内容if selename=1
do form hospital\\form\\bcg1*打开下级表单“病床管理”else do form hospital\\form\\brg1*打开下级表单“病人管理”ednif
添加一个“退出”按钮,功能为释放本表单,激活系统主界面。其代码如下:
thisform.releasemain.enabled=.T.
该表单主要是为使用者提供对住院部病人的一览,查询,添加等具体功能。
其设计思路如下:
因功能较多,为了使一个表大怒中能够显示大量的信息。本表单使用PageFrame(页框)控件,具体目标如图5-10所示。
表单中页框共分为6个子页面,分别为“一览”,“简单查询”,“高级查询”,以及“添加”,“编辑”,“删除”,使用者单击各页面标题就可以进入各个子页面,从而实现相应的功能。
(1)“一览”子页面用来显示整个住院部的病人资料。缺省以记录输入顺序排序。表格内显示病人资料,当使用者单击列头时,会根据该表中此列的顺序重新排列一个表格中的记录。
图10 病人管理界面
表10 病人管理界面参数
属性名值说明
CAPTION病人管理表单标题WIDTH604表单宽HEIGHT454表单高
ICON图标文件位置
向表单中添加PageFrame控件,将其PageCount(页面数)属性设为6,即共6个子页面。各页面的Caption属性分别设为“一览”、“简单查询”、“高级查询”、“添加”、“编辑”、“删除”。在适当位置添加Label控件,命名为“病人管理”。
(2)“简单查询”为使用者提供一个简单的病人查询方式——由一个字段检索病人记录。如“病人姓名”、“入院时间”、“所属科室”、“主治医生”和“病房号”。
(3)“高级查询”实际上就是可集合简单查询中提供的字段的内容,可精简简单查询的结果,从而更快地得到病人信息。
(4)使用者可通过“添加”页面提供的功能向病人的数据库中添加新的记录。
(5)“编辑”页面中使用者可以编辑已经存在的记录。
(6)在“删除”页面中,提供了通过输入病人姓名来删除记录的方式,同时还可以删除数据库中空白的记录。
通过如下的步骤来实现上述功能:新建一个表单,存储名为“brg1”.
设置表单的各外观参数,如表10所示。
单击鼠标右键,在Date Environment(数据环境)中添加表Patient。(1)“一览”子页面的设计步骤如下:
拖动表Patient至表单中。将其加入到子页面1中,结果如图10所示。改动表格中名列名称,分别为“病人姓名”、“性别”、“入院时间”、“科室”、“病症”、“主治医生”、“病房号”、“病床号”。调整各列宽至合适宽度,Alignment属性为“2-Middle Center”(居中)。
填写各列头的Click代码。
Column1 Header(病人姓名)Click代码:Set order to patient_na
*以“病人姓名”为索引排列go top
thisform.pageframe1.page1.grdpatient.refreshColumn2 Header(性别)Click代码:Set order to patient_ge
*以“病人性别”为索引排序go top
thisform.pageframe1.page1.grdpatient.refreshColumn3 Header(入院时间)Click代码:Set order to patient_da
*以“入院时间”为索引排序go top
thisform.pageframe1.page1.grdpatient.refreshColumn4 Header(科室)Click代码:Set order to patient_de
*以“所属科室”为索引排序go top
thisform.pageframe1.page1.grdpatient.refreshColumn6 Header(主治医生)Click代码:Set order to patient_do
*以“主治医生”为索引排序go top
thisform.pageframe1.page1.grdpatient.refreshColumn7 Header(病房号)Click代码:Set order to patient_ro
*以“病房号”为索引排序go top
thisform.pageframe1.page1.grdpatient.refresh
因不需要对“病症”和“病床号”进行排序,因此其Column Header的Click代码不要填。
另外,为防止对表格内容进行误操作修改或删除,将表格各Column的Text的Enabled属性设为“E”。
(2)“简单查询”页面的设计如图11所示。
图11“简单查询”子页面
本例中提供“病人姓名”、“入院时间”、“所属科室”、“主治医生”和“病房号”等5个字段可做查询关键字。
向表单中添加OptionGroup控件,设置Button Count属性为5。更改相应的Caption属性。
添加按钮“进入查询”,填写Click事件代码:
if thisform.pageframe1.page2.optiongroup1.option1.value=1*选中的是其中组件1时
thisform.pageframe1.page2.text1.enabled=.Tthisform.pageframe1.page2.text1.setfocusendif
if if thisform.pageframe1.page2.optiongroup1.option2.value=1*选中的时其中组件2时
thisform.pageframe1.page2.text2.enabled=.Tthisform.pageframe1.page2.text2.setfocusendif
if thisform.pageframe1.page2.optiongroup1.option3.value=1*选中的是其中组件3时
thisform.pageframe1.page2.text3.enabled=.Tthisform.pageframe1.page2.text3.setfocusendif
if thisform.pageframe1.page2.optiongroup1.option4.value=1*选中的是其中组件4时
thisform.pageframe1.page2.text4.enabled=.Tthisform.pageframe1.page2.text4.setfocus
endif
if thisform.pageframe1.page2.optiongroup1.option5.value=1*选中的是其中组件5时
thisform.pageframe1.page2.text5.enabled=.Tthisform.pageframe1.page2.text5.setfocusendif
thisform.pageframe1.page2.optiongroup1.option1.enabled=.F.thisform.pageframe1.page2.optiongroup1.option2.enabled=.F.thisform.pageframe1.page2.optiongroup1.option3.enabled=.F.thisform.pageframe1.page2.optiongroup1.option4.enabled=.F.thisform.pageframe1.page2.optiongroup1.option5.enabled=.F.thisform.pageframe1.page2.command1.enabled=.F.thisform.pageframe1.page2.command2.enabled=.T.thisform.pageframe1.page2.command3.enabled=.T。*为防止误操作,将不用的控件设为不可用。
这段代码的功能是判断使用者选择的要查询的字段,将相应的文本框变为可填写,便于使用者操作。
添加直线下各控件Text1~Text5及Label控件,各Text的Enabled属性设为“.E.”。注意Text3的InputMask及Format属性均设为“9999/99/99”,即按“年/月/日”的格式输入和读出数据。注意前面在设置数据库的表Patient的Patient_date_start字段的InputMask及Fromat属性时也应设为“9999/99/99”。这样设置以后,使用者就只能在该文本框中输入数字了,如果输入的不为数字,则系统拒绝接受。
添加按钮“显示查询结果”,其Click代码为:
inname=alltrim(thisform.pageframe1.page2.text1.value)indate=alltrim(thisform.pageframe1.page2.text2.value)indept=alltrim(thisform.pageframe1.page2.text3.value)indoct=alltrim(thisform.pageframe1.page2.text4.value)inroom=alltrim(thisform.pageframe1.page2.text5.value)*获取输入的值
select patient_name as 病人姓名,;patient_gender as 性别,;
patient_date_start as入院时间,;patient_dept as 科室,;patient_state as 病症,;patient_doc as 主治医生,;patient_room as 病房号,;patient_bed as 病床号;from patient;
where patient_name=inname;and patient_date_start=indate;and patient_dept=indept;and patient_doc=indoc;and patient_room=inroom
*根据条件选择出要显示的字段
这段代码的功能时将查询到的符合条件的记录罗列出来。添加按钮“重新查询”,Click代码为:
thisform.pageframe1.page2.optiongroup1.option1.value=1thisform.pageframe1.page2.optiongroup1.option2.value=0thisform.pageframe1.page2.optiongroup1.option3.value=0thisform.pageframe1.page2.optiongroup1.option4.value=0thisform.pageframe1.page2.optiongroup1.option5.value=0*使选项组的状态恢复
thisform.pageframe1.page2.optiongroup1.option1.enabled=.T.thisform.pageframe1.page2.optiongroup1.option2. enabled=.T.thisform.pageframe1.page2.optiongroup1.option3. enabled=.T.thisform.pageframe1.page2.optiongroup1.option4. enabled=.T.thisform.pageframe1.page2.optiongroup1.option5. enabled=.T.*使选项组为可用
thisform.pageframe1.page2.command1.enabled=.T.thisform.pageframe1.page2.text1.value=””thisform.pageframe1.page2.text2.value=””thisform.pageframe1.page2.text3.value=””thisform.pageframe1.page2.text4.value=””thisform.pageframe1.page2.text5.value=””*将各文本框清空
thisform.pageframe1.page2.text1.enabled=.F.thisform.pageframe1.page2.text2enabled=.F.thisform.pageframe1.page2.text3.enabled=.F.thisform.pageframe1.page2.text4.enabled=.F.thisform.pageframe1.page2.text5.enabled=.F.*使各文本框为可用
thisform.pageframe1.page2.command2.enabled=.F.thisform.pageframe1.page2.command3.enabled=.F.*将按钮恢复不可用
这段代码的功能时恢复查询前的状态,重新输入要查询的字段。(3)“高级查询”中大多数内容与“简单查询”页面类似,如图12所示。
查询的字段选择改为CheckBox控件,共5个。“进入查询”按钮Click代码为:
if thisform.pageframe1.page3.check5.value=1thisform.pageframe1.page3.text5.enabled=.T.thisform.pageframe1.page3.text5.serfocusendif
if thisform.pageframe1.page3.check4.value=1thisform.pageframe1.page3.text4.enabled=.T.thisform.pageframe1.page3.text4.serfocusendif
if thisform.pageframe1.page3.check3.value=1thisform.pageframe1.page3.text3.enabled=.T.thisform.pageframe1.page3.text3.serfocusendif
if thisform.pageframe1.page3.check2.value=1thisform.pageframe1.page3.text2.enabled=.T.thisform.pageframe1.page3.text2.serfocusendif
if thisform.pageframe1.page3.check1.value=1thisform.pageframe1.page3.text1.enabled=.T.thisform.pageframe1.page3.text1.serfocusendif
*依次检查各复选框的值
thisform.pageframe1.page3.check1.enabled=.F.thisform.pageframe1.page3.check2.enabled=.F.thisform.pageframe1.page3.check3.enabled=.F.
图12 “高级查询”子页面
thisform.pageframe1.page3.check4.enabled=.F.thisform.pageframe1.page3.check5.enabled=.F.thisform.pageframe1.page3.command1.enabled=.T.thisform.pageframe1.page3.command2.enabled=.F.thisform.pageframe1.page3.command3.enabled=.F.*为防止误操作,将不用的控件设为不可用
注意各CheckBox的判断和“简单查询”中的区别。其功能与“简单查询”子页面中的相应按钮也有所区别。
添加“显示查询结果”按钮,其Click事件代码为:inname=alltrim(thisform.pageframe1.page3.text1.value)indate=alltrim(thisform.pageframe1.page3.text2.value)indept=alltrim(thisform.pageframe1.page3.text3.value)indoct=alltrim(thisform.pageframe1.page3.text4.value)inroom=alltrim(thisform.pageframe1.page3.text5.value)*获得文本框输入的各信息
select patient_name as 病人姓名,;patient_gender as 性别,;
patient_date_start as入院时间,;patient_dept as 科室,;patient_state as 病症,;patient_doc as 主治医生,;patient_room as 病房号,;patient_bed as 病床号;from patient;
where patient_name=inname;and patient_date_start=indate;and patient_dept=indept;and patient_doc=indoc;and patient_room=inroom*选择出要显示的字段
这个按钮的功能与“简单查询”子页面中相应按钮类似,读者可参阅前面的内容。
添加“重新查询”按钮,其Click事件代码如下:thisform.pageframe1.page3.check1.value=0thisform.pageframe1.page3.check2.value=0thisform.pageframe1.page3.check3.value=0thisform.pageframe1.page3.check4.value=0thisform.pageframe1.page3.check5.value=0*将各复选框组件状态恢复为未选状态
thisform.pageframe1.page3.check1.enabled=.T.thisform.pageframe1.page3.check2.enabled=.T.thisform.pageframe1.page3.check3.enabled=.T.thisform.pageframe1.page3.check4.enabled=.T.thisform.pageframe1.page3.check5.enabled=.T.*将各复选框组件变为可用状态
thisform.pageframe1.page3.command1.enabled=.T.thisform.pageframe1.page3.text1.value=””thisform.pageframe1.page3.text2.value=””
thisform.pageframe1.page3.text3.value=””thisform.pageframe1.page3.text4.value=””thisform.pageframe1.page3.text5.value=””*将各文本框清空
thisform.pageframe1.page3.text1.enabled=.F.thisform.pageframe1.page3.text2enabled=.F.thisform.pageframe1.page3.text3.enabled=.F.thisform.pageframe1.page3.text4.enabled=.F.thisform.pageframe1.page3.text5.enabled=.F.
thisform.pageframe1.page3.command2.enabled=.F.thisform.pageframe1.page3command3.enabled=.F.*将各控件恢复至初始状态
(4)紧接这设计“添加”子页面,界面如图13所示。
图13 “添加”子页面
其“确定”按钮的Click代码为:
inname=alltrim(thisform.pageframe1.page4.text1.value)ingend=alltrim(thisform.pageframe1.page4.text2.value)indate=alltrim(thisform.pageframe1.page4.text3.value)indept=alltrim(thisform.pageframe1.page4.text4.value)instat=alltrim(thisform.pageframe1.page4.text5.value)indoct=alltrim(thisform.pageframe1.page4.text6.value)inroom=alltrim(thisform.pageframe1.page4.text7.value)inbedd=alltrim(thisform.pageframe1.page4.text8.value)*从文本框1至8获得输入的信息cMessageTitle=’管理系统’
cMessageText=’确定要添加吗?’nDialogType=4+32
nAnswer=messagebox(cMessageText,nDialgType,cMessageTitle)*确定添加时给出的提示do case
case nAnswer=6
set order to patient_naseek inname
*检查病人名是否重复if ! found()
insert into patient values
(inname,ingend,indate,indept,instat,indoct,inroom,inbedd)
各控件如图13所示。注意入院时间Text控件的InputMask及Format属性。
messagebox(“添加完毕”,48,”操作成功”)else
messagebox(“病人名重名”,48,”错误”)*若病人名重名,给出提示endif
thisform.pageframe1.page4.text1.value=’’thisform.pageframe1.page4.text2.value=’’thisform.pageframe1.page4.text3.value=’’thisform.pageframe1.page4.text4.value=’’thisform.pageframe1.page4.text5.value=’’thisform.pageframe1.page4.text6.value=’’thisform.pageframe1.page4.text7.value=’’thisform.pageframe1.page4.text8.value=’’*添加完毕后清空各文本框
thisform.pageframe1.page4.text1.setfocuscase nAnswer=7endcase
这段代码的功能时将使用者输入的新的病人的数据添加到数据库中,其中含有必要的纠错功能。
(5)“编辑“子页面如图14所示。“确定”按钮的Click代码为:
inname=alltrim( thisform.pageframe1.page5.text1.value)ingend=alltrim( thisform.pageframe1.page5.text2.value)indate=alltrim( thisform.pageframe1.page5.text3.value)indept=alltrim( thisform.pageframe1.page5.text4.value)instat=alltrim( thisform.pageframe1.page5.text5.value)indoct=alltrim( thisform.pageframe1.page5.text6.value)inroom=alltrim( thisform.pageframe1.page5.text7.value)inbedd=alltrim( thisform.pageframe1.page5.text8.value)*获取各输入值
cMessageTitle=’管理系统’
cMessageType=’确定要修改吗?’nDialogType=4+32
nAnswer=messagebos(cMessageText,nDialogType,cMessageTitle)do case
case nAnswer=6*如果选择“是”set order to patient_na
*设置数据表索引为patient_naseek inname
*检查要操作的病人记录if found() update patient set patient_gender=ingend,;patient_date_start=indate,;patient_dept=indept,;patient_state=instat,;patient_doc=indoct,;patient_room=inroom,;
patient_bed=inbedd where patient_name=innamemessagebox(“资料更新完毕”,48,”操作成功”)else
*检查病人名是否存在
messagebox(“该病人名不存在”,48,”错误”)thisform.pageframe1.page5.text1.value=’’thisform.pageframe1.page5.text2.value=’’thisform.pageframe1.page5.text3.value=’’thisform.pageframe1.page5.text4.value=’’thisform.pageframe1.page5.text5.value=’’thisform.pageframe1.page5.text6.value=’’thisform.pageframe1.page5.text7.value=’’thisform.pageframe1.page5.text8.value=’’*如果没有该病人则将各文本框清空thisform.pageframe1.page5.text1.serfocus*并将光标焦点置于文本框1endif
case nAnswer=7
*如果选择“否”则不执行任何步骤endcase
本代码的功能是按使用者输入的病人的姓名查找数据库,如果找到符合的记录则修改该记录的数据。
图14 “编辑”子页面
“重新编辑”按钮的Click代码为:thisform.pageframe1.page5.text1.valu=’’thisform.pageframe1.page5.text2.valu=’’thisform.pageframe1.page5.text3.valu=’’thisform.pageframe1.page5.text4.valu=’’thisform.pageframe1.page5.text5.valu=’’thisform.pageframe1.page5.text6.valu=’’thisform.pageframe1.page5.text7.valu=’’thisform.pageframe1.page5.text8.valu=’’*将各文本框清空
thisform.pageframe.page5.text1.setfocus
(6)本例中的“删除”页面较为简单,如图15所示。
该子页面提供了按“病人姓名”删除记录的方式,如果读者需要以别的方式来删除记录,可自行设计。
“确定”按钮的Click代码为:
inname=alltrim(thisform.pageframe1.page6.text1.value)cMessageTitle=’管理系统’
cMessageText=’确定要删除吗?’nDialogType=4+32
nAnswer=messagebox(cMessageText, nDialogType, cMessageTitle)do case
case nAnswer=6
set order to patient_naseek inname
*检查要删除的记录是否存在
if !found
messagebox(“该记录不存”,48,”错误”)else
thisform.pageframe1.page2.grdpatient.recordsource=’’*将表patient以独占方式打开,执行删除命令use patient exclusive
delete from patient where patient_name=innamepack
thisform.pageframe1.page2.grdpatient.recordsource=’patient’thisform.pageframe1.page2.grdpatient.refreshmessagebox(“删除完毕”,48,”操作成功”)endif
case nAnswer=7endcase
使用者单击此按钮后系统根据前面文本框填入的病人姓名查找并进行删除。
图15 “删除”子页面
“删除空白记录”按钮Click代码:
thisform.pageframe1.page2.grdpatient.recordsoure=’’use patient exclusive*检查是否空白记录
delete from patient where empty(patient_name)pack
thisform.pageframe1.page2.grdpatient.recordsource=’patient’thisform.pageframe1.page2.grdpatient.refresh
这段代码的功能在于删除病人名为空的数据库的记录。到此为止,病人管理的页面就完成了。
属 性 名
CAPTIONFONTNAMEFONTSIZEALIGNMENT
图16 病床管理模块主界面
3.病床管理模块
为了方便贵病床的管理,使医院的住院状况达到最佳状态,合理有效地为病人分配病床是必要的。
本模块要求管理员能轻松的利用提供的界面实现病床的查询、分配等功能,设计的界面如图16所示。具体的功能如下所列:
(1)(1) 列出所有的病床的分配情况。(2)(2) 查询空的病床。
(3)(3) 查询未分配病床的病人。
(4)(4) 对未分配病床的病人分配病房和病床。(5)(5) 对已分配病床的病人进行调整。(6)(6) 将已离开的病人的床位记录清空。
为了是功能清晰,本界面使用“容器”对各功能的控件进行分类,使整个界面一目了然,便于操作。
整个表单的设计过程如下:
新建一个表单,存储名为“bcgl”。
向表单顶部正中位置添加Label(标签),各参数如表11所示。
病床管理
录书26
2-中央
表11 病床管理标签参数
值
说 明
标签标题字体字大小
标签的对齐方式
修改表单各外观参数,如表12所示。
表12 病床管理界面参数
表13 个组合框数据源相关设置
RowSourceRowSourceType容 器RowSource注释
Combo1201,202病房号1-值Combo21,2,3病床号1-值Combo3Patient.patient_name病人姓名6-值
添加一个“分配确定”按钮,填写其Click事件代码:
因功能较多,这段代码较长。请读者耐心阅读,体会其中各语句的功能。下段代码的功能是为病人分配病床,其中涵盖了必要的纠错及提示。
inroom=alltrim(thisform.container1.combo1.value)inbed=alltrim(thisform.container1.combo2.value)inpatient=alltrim(thisform.container1.combo3.value)if empty(inroom)or empty(inbed)or empty(inpatient)*提示管理员资料有输入错误,如图17所示messagebox(‘资料不足‘,48,’错误’)elsesele bed
set order to patient_naseek inpatientif found()
*当要分配病床的病人已分配过病床时,提示管理员是否要修改已分配的病人的病床,如图18所示。
cMessageTitle=’管理系统’
cMessageText=’该病人已经分配过病床,要修改吗?’nDialogType=4+32
nAnswer=messagebox(cMessageText, nDialogType, cMessageTitle)do case
case nAnswer=6
update bed set patient_name=” where patient_name=inpatient*更新表bed,将该病人的原床位信息清空sele patient
locate for patient_room=inroom and patient_bed=inbedreplace patient.patient_room with”patient.patient_bed with”*根据要分配的房间号和病床号查找记录
属 性 名值说 明
CAPTION病床管理表单标题WIDTH527表单宽HEIGHT420表单高
ICON图标文件位置
向表单中添加3个container(容器),右击鼠标键,选择“编辑”后进入各容器的编辑,向其中添加需要的控件。笔者的添加顺序如下:
Container1(容器1):病床分配添加4个Label(标签),填入相应内容。添加3个Combo控件(组合框),分别为其设置RowSource(数据源)和RowSourceType(数据源类型)属性,具体设置如表13所示。
图18 重复提示
图17 资料不足错误提示
update bed set patient_name=inpatient;
where room_number=inroom and bed_number=inbed*更新表bed
update patient set patient_room=inroom;
patient_bed=inbed where patient_name=inpatient*更新表patientcase nAnswer=7endcaseelse
update bed set patient_name=inpatient where room_number=inroom and bed_number=inbed
update patient set patient_room=inroom,
patient_bed=inbed where patient_name=inpatient
*如果要分配病床的病人本来就没有病床,则直接更新表patient和bedendifendif
thisform.container3.grid1.refresh
添加一个“清空确定”按钮,填写其Click事件代码:inroom=alltrim(thisform.container1.combo1.value)inbed=alltrim(thisform.container1.combo2.value)*提示管理员资料有输入错误if empty(inroom)or empty(inbed)messagebox(‘资料不足’,48’错误’)else
cMessageTitle=’管理系统’
cMessageText=’确定要清空该病床的病人吗?’*提示管理员是否要进行此操作nDialogType=4+32
nAnswer=messagebox(cMessageText, nDialogType, cMessageTitle)do case
case nAnswer=6*更新表bed
update bed set patient_name=’’;
where room_number=inroom and bed_number=inbed*更新表patient
update patient set patient_room=’’;patient_bed=’’;
where patient_room=inroom and patient_bed=inbedcase nAnswer=7endcaseendif
thisform.container3.grid1.refresh
上段代码的功能是清空选中的病床占用资料,清空之后该病床无病人占用,原在该床的病人成为“无床病人”,该床成为“空床”。
Container2(容器2):查询空床及无床位病人添加两个按钮,分别设置其Caption(标题)。“列出所有空床位”的按钮Click代码为:select bed
select room_number as 病房号,;bed_number as 病床号,;patient_name as 病人姓名;
from bed where empty (patient_name)*将所有空床位的记录列出
“列出所有无床病人”的按钮Click事件代码为:select patient
select patient_name as 病人姓名,;patient_room as 病房号,;patient_bed as 病床号;
from patient where empty(patient_room)or empty(patient_bed)*将所有无床病人的记录列出Container3(容器3):病床一览
添加一个表格,设置其RecordSource(数据源)为“bed”,RecordSourceType为“1-表”。
为方便按病房查看病床情况,为表格的Column1的Header1添加Click事件代码:
set order to room_numbergo top
thisform.container3.grid1.refresh*按“病房号”索引排序
在表单底部添加一个“退出”按钮,其Click事件代码为:thisform.release*释放本表单
到此为止,病床管理模块的开发也完成了。4.3 药品仪器管理模块设计
本模块旨在为用户提供一个功能简单的药品仪器的一览、购买的功能。本模块实现的主要功能有:药品、仪器资料一览和药品、仪器的购买。本模块创建的具体实现步骤如下:新建表单,存储名为ypyq.
修改表单各外观参数,如表14所示。
表14 病床管理界面参数
属 性 名值说 明CAPTION药品仪器管理表单标题WIDTH545表单宽HEIGHT416表单高
ICON图标文件位置
在数据环境中添加表apparatus和potion。添加控件PageFrame(页框),子页面数为2并为子页面设置标题。编辑Page1(子页面1),标题为药品管理。添加表格GrdPotion(直接从数据环境中拖曳),为其设置MouseUp事件代码:
LPARAMETERS nButton,nShift,nXCoord,nYCoordThisform.pageframe1.page1.text1.refresh
在子页面1中添加标签1个,文本框2个,设置Text1(文本框1)的Contro1Source属性为“potion.potion_name”。并设置Enabled属性为”.F.”。
在子页面1中添加“确定”按钮,填写其Click事件代码:getpotion=alltrim(thisform.pageframe1.page1.text1.value)getnumber=alltrim(thisform.pageframe1.page1.text2.value)*获得输入信息
cMessageTitle=’管理系统’cMessageText=’确定购买吗?’nDialogType=4+32
nAnswer=messagebox(cMessageText,nDialgType,cMessageTitle)do case
case nAnswer=6
*将“购买数目”与“库存”相加,就算药品的现有量numbersum=val(getnumber)+potion.potion_quantit*更新数据库
update potion set potion_quantity=numbersum where potion_name=getpotionthisform.pageframe1.page1.grdpotion.refreshcase nAnswer=7endcase
*将“购买数目”文本框中值清空,等待下次输入thisform.pageframe1.page1.text2.value=’’
本段代码的功能是将要买的药品的数量根据输入的数据进行更新。程序运行如图19所示。
图19 药品管理子页面
对Page2(子页面2)进行类似的操作,添加表格GrdApparatus。标签1个、文本框2个,“确定”按钮1个,如图20所示。
“确定”按钮Click事件代码如下:
getapparatus=alltrim(thisform.pageframe1.page2.text1.value)getnumber=alltrim(thisform.pageframe1.page2.text2.value)*获得输入信息
cMessageTitle=’管理系统’
cMessageText=’确定要购买吗?’nDialogType=4+32
nAnswer=messagebox(cMessageText,nDialgType,cMessageTitle)do case
case nAnswer=6
numbersum=val(getnumber)+apparatus. Apparatus_quantity*计算仪器的现有台数
update apparatus set apparatus_quantity=numbersum where apparatus_name=getapparatus
*更新表apparatus
thisform.pageframe.page2.grdapparatus.refreshcase nAnswer=7endcase
thisform.pageframe1.page2.text2.value=’’
这段代码的功能与“药品管理”子页面的相应按钮相似。
图20 仪器管理子页面
主程序要实现的功能有:
确认安装目录并设定其为默认路径。这样执行所有的表单、报表、程序、菜单等就不用再加路径。
声明应用程序执行的配置环境。 打开开始桌面,开始相应事件。
执行应用程序结束后,还原系统环境配置。 在项目管理器中找到“Code(代码),添加一个新的Program(程序)。存储为main.prg并设置其为程序主文件(Set Main),如图21所示。
4.4 系统主程序设计
前面设计出的表单不是可执行程序,如要单独运行,需要为其添加主程序。
图21 设置为主文件
填写代码:clear screenclear event*打开数据库
open database database\\hospital*执行开始表单do form form\\ksjm*设置系统环境配置do setting*移去白框
_screen.left=-1000*开始相应事件read events
*收到“Clear Events”命令后关闭数据库,还原系统环境配置close reset
新建程序setting.prg
setting.prg设置系统环境配置:set sysmenu off*将系统菜单关闭set sysmenu to set status off
*不显示图象状态框set talk off
*指定在Visual FoxPro主窗口、系统信息窗口、图形状态栏、或自定义窗口中不显示命令结果set clock status
*将时钟在指定的位置上显示,而不放在图形状态栏中set palette off
*不使用Visual FoxPro默认的调色板
set bell off
*打开计算机喇叭,使计算机在指定的时候发声set safety off
*指定在覆盖已有的文件时不打开一个对话框set escape on
*指定在按下Esc键后,中断命令和程序的运行set keycomp towindowsset carry on
*指定在创建新记录时,将当前记录所有字段的数据复制到新记录中set confirm onset exact on
*指点两个表达式必须长度相等才能进行比较set near onset ansi offset lock on
*指定在执行某些需要只读访问一个表的命令时,具有自动锁定表的功能set exclusive off
*指定在网络上任何用户可以共享和修改网上打开的表set multilocks onset deleted on
*表示在命令中使用范围参数处理记录时,不访问标有删除标记的记录set optimize on
*指定可以使用Rushmore优化技术set refresh to 0,5
*设定网络中表的刷新事件set collate to ‘stroke’
*设定字符型字段的排列顺序set default to sys(5)+curdir()*设置默认文件目录set path to sys(5)+curdir()*指定查找文件目录set sysformats off
*指定当修改Windows系统设置修改时,不更新Visual FoxPro系统设置以下设置关系时间、货币,是否设置不影响整个程序。Set seconds onSet century offSet currency leftSet cirremcu tp’nt$’Set hours to 12Set date to usaSet decimals to 2Set fdow to 1Set fweek to 1Set mark to ‘.’Set separator ‘.’Set point to ‘.’新建程序reset.prg
reset.prg还原系统环境配置,包括恢复系统菜单和其他一些开发环境必需的配
置。
Set sysmenu to defaultSet sysmenu onSet talk on Set notify onSet exclusive on Set safety on
Modify window screen
5 开发中的难点和解决技巧
5.1 索引(Index Tag)
不同的表使用各自的索引,程序员可利用这些索引对表内的数据实现排序、查询、编辑和筛选等功能。
1.1. 设置方法
(1)要进行索引的表的字段的索引栏选中,如图22所示。(2)设置索引方式。缺省的索引方式是升序(或降序),但FoxPro并不将索引表达式限制为单个字段。实际上任何字段组合都可以作为索引表达式。将表达式弄得过分复杂只会使它成为一个候选索引。比如用Last_Name和First_Name来建立一个候选索引。
(3)若要建立一个复杂的表达式,请单击Table Designer(表设计器)对话框中的Expression(表达式)文本框右边的按钮。FoxPro显示Expression
Builder(表达式生成器)的对话框。FoxPro可以利用Expression Builder对话框来帮助建立复杂的表达式。Funtions用于访问FoxPro的内置函数,这些函数分为4组,即Data(日期)、Logical(逻辑)、Matih(数学)和String(字符串)。单击函数数字右边的箭头按钮,显示一个下拉函数列表来选定函数。对于一个函数,FoxPro会自动将插入光标放入括号中,然后就可以输入参数了。(4)设置索引的类型。FoxPro提供了4种索引类型:Primary(主索引)、Candidate(候选索引)、Unique(唯一索引)和Regular(普通索引)。2. 索引类型
(1)(1) 索引
主索引是在指定字段或表达式中不允许出现重复值的索引。主索引主要用于主表或被被引用的表,用来在一个永久关系中建立参照完整性。对应一个表而言,只能创建一个主索引。如果在任何已含有重复的字段中指定主索引,FoxPro将产生错误信息。
主索引可确保字段中输入值的唯一性并决定了处理记录的顺序。如果需要的话,可以为数据库中每一个表建立一个主索引。如果某个表已经有了一个主索引,那么就可以继续添加候选索引。
图22 选中要索引的字段
(2)(2) 选索引
候选索引可作为主关键字的索引,因为它不包含Null值或重复值。候选索引像主索引医院要求字段值的唯一性并决定了出来记录的顺序。在数据库表和自由表中均可为每个表建立多个候选索引。
(3)(3) 唯一索引
唯一索引不允许两个记录具有相同的索引值,这种要求与主索引相同。为了保持同早期版本的兼容性,可以建立一个唯一索引,以指定字段的首次出现值为基础,选定一组记录,并对记录进行排序。
(4)(4) 普通索引
普通索引是除唯一索引、主索引和候选索引以外的索引。普通索引可用来对记录排序和搜索记录,它不强迫记录中的数据具有唯一性。此外,普通索引还可作为一对多永久关系中多方。普通索引也可以决定记录的出来顺序,但是允许字段中出现重复值。在一个表中可以加入多个普通索引。
3.选择原则
根据所建索引类型的不同,可以完成不同的任务。那么任何选择合适的所有类型呢?可以根据以下的准则:
(1)如果需要排序记录,以便显示、查询和打印,可以使用普通索引、候选索引或主索引。
(2)如果要在字段中控制重复值的输入并对记录进行排序,对数据库表则可以使用普通索引或候选索引,对自由表可以使用候选索引。
(3)如果准备设置表关系,则可以根据表在关系中所起的作来来分别使用普通索引、主索引或候选索引。
4.注意事项
在设置索引字段的时候要特别注意的是索引字段名不能超过10个字符,如果超过10个字符则表自动截取该字段名的前10个字符作为索引字段。如在本
图 23 实际的索引字段
索引表达式也有限制条件,它要根据索引表达式字符串的长度而定,同时
也取决于它的值。索引文件为索引表达式及其值保留了有限的空间。如果时独立索引,索引表达式最多可以包含220个字符。FoxPro将产生的索引值限定为100个字符。如果将该独立索引定义为紧凑型独立索引(一种特殊类型的独立索引,它只需要较少的磁盘空间),那么该索引表达式将与For表达式共享磁盘空间。两个表达式字符串的组合长度不得超过512个字符,各个索引值不得超过240个字符。符合索引也要符合类似的要求。符合索引与带有重复标记的紧凑型索引没有什么不同,他们有着相同的限制条件。5.2 多级引用
在程序中经常对Form(表单)、PageFrame(页框)、Grid(表格)等控件进行刷新,以及提取Text(文本框)、Combobox(组合框)的值等操作。这需要程序员在调用该对象的时候要了解整个表单的结构,搞清楚各个控件之间的从属关系,以便进行多级引用。
实例中的patient表的索引字段“patient_name”被截取为“patient_na”,因此程序员在开发程序中使用索引字段时应使用“patient_na”而不是“patient_name”,如图23所示。否则会出现“索引未找到”的错误提示,如图24所示。
图 25 多级引用示例
我们这里以“病人管理”的表单为例进行讲解。如图25所示,表单中含有PageFrame(页框),页框中第二页中含有OptionGroup(选项组控件),该控件中有5个选项按钮(Option)每个选项按钮有各自的属性。因此,如果要取用某个选项按钮的某个属性,如要验证“病人姓名”按钮是否被选中,即验证该按钮的Value(值)是否为1。我们首先理清楚整个从属关系(->表示从属关系)
Value->Option->OptionGroup->Page->PageFrame->Form用中文表示就是:
属性->选项->选项组->子页面->页框->表单因此我们所引用的对象就是:
thisform.pagefrane1.page2.optiongroup1.option1.value
其实页可以通过单击属性栏中的下拉箭头查看表单的整个结构,如图26所示。
某些时候还可以使用更为简单的引用方式。比如某控件的Click事件要引用的就是该控件的获取值Value,在引用该值的时候可以写作“this.value”。这样既节省了程序行,又能保证引用的正确性,提高了代码的效率。
图26 属性栏中查看表单的结构
5.3 SQL语言
在本例中大量使用了SQL对语言就数据库进行操作,如查询显示、数据更新、数据删除等等。那么SQL语言到底是什么东西,包含哪些内容,能实现哪些功能呢?我们下面会做具体的介绍。
SQL就是Structured Query Language,即结构化查询语言的缩写。Visual FoxPro的SQL命令实际是一个数据库语言,包含查询语言。数据定义语言、数据操纵语言和数据控制语言4部分。它能利用Rushmore技术优化性能,并且一个SQL语言命令可以用来替换多个Visual FoxPro 命令。这样可以大大地减少程序行,提高程序效率。SQL命令有:
1.1.ALTER TABLE-SQL命令
修改一个已有的表,使用该命令可以更改表中每个字段的名称、类型、精度、范围、设定对Null值的支持以及参照完整性规则。
2. CREATE CURSOR-SQL命令
创建一个临时表,使用该命令可以定义临时表中每个字段的名称、类型、精度、范围、设定对Null值的支持以及参照完整性规则。这些定义可以从命令本身也可以从一个数组获得。
3.3. CREATE TABLE-SQL命令
创建一个表,使用该命令可以定义新表中的每个字段的名称、类型、精度、范围、设定对Null值的支持以及参照完整性规则。
4.4. DELETE-SQL命令
利用SQL语法将表中指定的记录作上删除标记。
基本语法:DELETE FROM [DatabaseName!] TableName [WHERE
FilterCondition1[AND|OR FilterCondition2……]]
语法解析
FROM [DatabaseName!]TableName用来指定从DatabaseName(数据库名)指定的数据库给TableName(表明)指定的表中记录加删除标记。如果数据库不死当前数据库,必修加上包含该表的数据库名DatabaseName。在数据库名的后面、表TableName名的前面应用感叹号(!)隔开。
[WHERE FilterCondition1[AND|OR FilterConditon2….]]用来指定只给某些记录做删除标记的条件。其中,FilterCondition指定要做删除标记的记录必须满足的条件。可以包含多个筛选条件,他们用AND 或OR 操作符连接。也可以使用NOT操作符给一个逻辑表达式的值取反或使用EMPTY()函数检查一个空的字段。
本例中的实例:
delete from patient where empty(patient_name)delete from patient where patient_name=inname
具体参见“病人管理模块设计”中的“删除子页面”的设计。其中patient为当前数据库中的表,empty (patient_name)、patient_name=inname为删除标记条件。凡是满足条件的该表中的记录均被标记。注意,这里说明只是标记,实际上表中的记录并未真正删除,需要使用“Pack”命令进行删除。“Pack”命令的用法请读者自己查阅相关资料。
5.5. INSERT-SQL命令
在一个已存在表的末尾追加一个新记录。该新记录包含了INSERT命令中列出的或一个数组中的数据。
基本语法:INSERT INTO dbf-name[(fname1[,fname2,…])] VALUES
(eExpression1[,eExpression2,[…]])或者INSERT INTO dbf-name FROM ARRAY ArrayName |FROM EMEVAR
语法解析:
INSERT INTO dbf-name指定要添加新记录的表名。dbf-name中可以包含路径,也可以是一个名称表达式。如果指定的表没有打开,则Visual FoxPro将自动将其打开。如果所指定的表是打开的,INSERT 命令就把新记录追加到这个表中。如果表已在其他工作区中打开,则会自动转换到该工作区,待添加完毕后,在转回到原来的工作区。
[(FNAME1,[,FNAME2,…])]指定新记录的字段名,INSERT-SQL命令将向这些字段中插入字段值。Fname1所指的是第一个字段名,fname2所指的是第二个字段名。
VALUES (eExpression[,eExpression2,[…]])是要插入的记录的字段值。Eexpression为要插入字段的值,即将eExpression1的内容存入fname1中,将eExpression2的内容存入fname2中。如果省略了字段名,则必须按照表结构中定义字段的顺序来指定每个字段值。
FROM ARRAY ArrayName 指定插入到新记录中的数据来自一个数组。第一个数组元素的内容插入打破新记录的第一个字段,第二个元素的内容插入到第二个字段,一次类推。
FROM EMEVAR 表示插入字段的数据来自字段名同名的内存变量。如果与某一字段同名内存变量不存在,则该字段为空。
本例中的实例:
inser into patient values(inname,ingend,indate,indept,instat,indoct,inroom,inbedd)
具体参加“病人管理模块设计”中的“添加子页面”的设计。其中patient 为当前数据库中的表,inname,ingend,indate,indept,instat,indoct,inroom,inbedd 为要插入的新记录的各个字段的值,即eExpression1,eExpression2…….,用逗号(,)隔开。注意这里么有fname1,fname2…..等字段名,如果程序员要使用相似的命令,必须知道表的结构,严格按照顺序插入各字段值。本命令是结构化查询语言的一个重要命令。
6.SELECT-SQL命令
用来指定查询的条件,并且执行查询。该命令已成为Visual FoxPro固有的命令。它可在命令窗口中、Visual FoxPro程序(同其他Visual FoxPro命令一样)或者查询设计器中创建一个SELECT命令查询。
SELECT-SQL命令是最常用的,功能最多同时也是结构也最复杂的一个命令。程序员需要好好地了解它的用法。
基本语法:SELECT [ALL|DISTINCT][TOP nExpr[percent]]
[Alias.]Select_Item[As Column_Name][,[Alias.]Select_Item[As Column_Name]…]FROM [FORCE][DatabaseName!]Table[[As]Local_Alias]
[INNER|LEFT[OTER]|RIGHT[OUTER]|FULL[OUTER]JOINDatabaseName!]Table
[[As]Local_Alias]
[ON JoinCondition…]
[[INTO Destination]|[TO FILE FileName[ADDITIVE]|TO PRINTER[PROMPT]|TO SCREEN]]
[PREFERENCE PreferenceName][NOCONSOLE][PLAIN][NOWAIT]
[WHERE JoinCondition[AND JoinConditon…][AND|OR FilterCondition[AND|OR FilterCondition…]]]
[GROUP BY GroupColumn[,GroupColumn…]][HAVING FilterCodition]
[UNION[ALL]SELECTCommand][ORDER BY Order_Item[ASC|DESC][,Order_Item [ASC|DESC]…]]语法解析:
[ALL|DISTINCT]
[TOP nExpr[PERCENT]]
[Alias.]Select_Item[As Column_Name][,[Alias.Select_Item[As Column_name]….]
确定要在查询结果种显示的字段、常量和表达式。其中ALL是盖命令的默认参数,用来指定显示查询结果中的所有行,包括重复的值。
DISTINCT表示不显示查询结果中所有重复的行。注意一个SELECT命令只能使用一次参数DISTINCT.
TOP nExpr [PERCENT]用来选取在符合查询条件的所有记录中指定数量的记录或指定某一百分比的记录。参数TOP和参数ORDER BY必须一起使用。参数TOP根据此排列方式,选定最开始的nExpr个或nExpr%个的记录。
Alias.限定匹配项的名称。
Select_Item查询结果中所包括的项。Select_Item指定的每一项在查询结果中都对应于一列,通常为一个字段。除此以外,还可以使用一些字段函数;计算列中选定项的平均值AVG(Select_Item)HANSHU ;计算列中选定项的数目COUNT(Select_Item);确定列中Select_Item的最小值MIN(Select_Item)函数;确定列中Select_Item的最大值MAX(Select_Item)函数;计算列中数值和SUM(Select_Item)函数。以上字段不能嵌套使用。
As Column_Name指定查询结果中列的标题名。用来当Select_Item是一个表达式或一个字段函数时,给此列取一个名称。Column_Name可以是一个表达式,但不能包含那些不允许出现在表字段名称中的字符(如空格)。
FROM [FORCE][DatabaseName!]Table[[As]Local_Alias]用来列出所有从中检索数据的表。此表可以不必先打开,因为Visual FoxPro会自动查找该表是否打开。如果没有打开,则Visual FoxPro将显示一个打开对话框以便让用户指定一个文件。查询结束后表自动关闭。其中FORCE表示按FROM参数中出现的顺序连接表。如果省略参数FORCE 则Visual FoxPro将优化查询。
[As]Local_Alias为Table中的表指定一个临时名称。如果指定了本地别名Local_Alias,那么在整个SELECT命令中都必须用这个别名代替表名。
INNER JOIN表示查询结果只来自与其他表中一个或多个相匹配的行。LEFT [OUTER]JOIN表示查询结果来自JOIN左侧表中所有行及右侧表中与之匹配的行。参数中OUTER是可以不用的,加上参数OUTER 则强调这是一个外连接。
RIGHT[OUTER]JOIN表示查询结果来自JOIN右侧表中所有行及左侧表中与之匹配的行。
FULL[OUTER]JOIN表示查询结果来自与其他表中所有匹配和不匹配的行。
ON JoinCondition指定连接条件。
INTO Destination 用来指定查询结果保存位置。如果同一个查询中同时包含了INTO 参数和TO参数,则TO参数不起作用。如不加INTO参数,则在浏览窗口中显示查询结果。也可以使用TO参数将参数查询结果送到打印机或文件中。Destination参数可以是ARRAY ArrayName(变量数组)、CursorName(临时表)和DBF TableName|TABLE TableName(表)这3种。
TO FILE FileName如果命令中没有INTO参数,则查询结果直接送到名为FileName的ASCII码文件中。
ADDITIVE将查询结果追加到TO FILE FileName所指定的文本文件的内容的后面。
TO PRINTER [PROMPT]指定将查询结果直接送到打印机中打印。
TO SCREEN指定将查询结果显示在Visual FoxPro主窗口和用户活动的自定义窗口中。
[PREFERENCE PreferenceName]指定在浏览窗口中显示查询结果,这样就把特征属性或参数选项长期保存在FOXUSER的资源文件中,以备后用。
NOCONSOLE送文件、打印机或Visual FoxPro主窗口的查询结果不同步显示。不管有无TO参数,均可使用本参数。但如果使用了INTO 参数,则不使用本参数。
PLAIN指定不把列标题显示在查询结果中。不管有无TO参数均可使用本参数。但如果使用INTO参数,则不使用本参数。
NOWAIT指打开浏览窗口并将查询结果输出到这个窗口后继续运行程序,也就是说,程序不等浏览窗口关闭,而是立即执行SELECT命令后面的程序行。如果使用INTO 参数,则不使用本参数。
WHERE用来告知Visual FoxPro在查询结果中只包含满足条件的记录。从多个表中检索时必须加WHERE参数。
JoinCondition指定一个连接FROM参数的表字段。如果查询两个或两个以上的表,就应该为第一个表后的每一个表指定连接条件。
FilterCondition指定在查询结果中记录所必须满足的条件。筛选条件可以是多个,他们之间必须用AND或OR操作符连接,也可以使用操作符NOT对逻辑表达式取反,或使用EMPTY()函数检查字段市斗为空等。
FROUP BY GroupColumn[,GroupCOLUMN…]按列的值对查询结果的进行分组。
HAVING FilterCondition 指定在查询结果中的组必须满足的筛选条件。HAVING参数应和GROUP BY参数一起使用。如果在命令中使用了HAVING参数但没有使用GROUP BY参数,则它的作用与WHERE参数相同。
[UNION [ALL] SELECTCommand]把用SELECT命令得到的最后查询结果同另一个SELECT命令得到的最后查询结果组合起来。参数UNION是默认值,表示检查组合的结果并排除重复的行。要组合多个UNION子句时,可用括号。参数ALL可防止UNION删除组合结果中重复的行。
注意不能使用UNION来组合子查询。两个SELECT 命令的查询结果中的行列数必须相等,对应列必须有相同的数据类型和宽度。
[ORDER BY Order_Item[ASC|DESC][,Order_Item[ASC|DESC]…]]表示根据列的数据对查询结果进行排序。Order_Item必须对应查询结果中的一列。ASC和DESC指定查询结果根据排序项以升序和降序列记录。注意,可以使用多个排序标准。如果不加该参数,则查询结果不排序。
本例中的实例:实例1
select patient_name as 病人姓名,;patient_gender as 性别,;
patient_date_start as 入院时间,;patient_dept as 科室,;patient_state as 病症,;patient_doc as 主治医生,;patient_room as 病房号,;patient_bed as 病床号;from patient;
where patient_name=inname;and patient_date_start=indate;and patient_dept=indept;and patient_doc=indoct;and patient_room=inroom实例2
select patient_name as 病人姓名,;patient_room as 病房号,;
patient_bed as 病床号from patient where empty(patient_room)or empty
(patient_bed)
实例1具体可参见“病人管理模块设计”中的“简单查询”子页面设计。实例2具体可参加“病床管理模块设计”中的“列出所有无床病人”按钮的Click事件代码。注意,SELECT命令一般都较长,如果要换行,就必须加上分号(;),否则Visual FoxPro会认为该处程序断开,导致出错。
7.UPDATE-SQL命令更新一个表中的记录。
基本语法:UPDATE [DatebaseName!]TableName1 SET Column_Name1=eExpresssion1[,Column_name2=eExpression2…]WHERE FilterCondition1 [AND|OR FilterCondition2…]
语法解析:
UPDATE [DatebaseName!]TableName1其中TableName1用来指定要更新记录的表名。
SET Column_Name1=eExpresssion1[,Column_name2=eExpression2…]用表达式eExpression1的值来更新参数Column_Name1指定列的字段的数据。若不加WHERE参数,则用相同的值更新列中每一行字段的数据。
WHERE FilterCondition1 [AND|OR FilterCondition2…]指定要更新的记录的条件表达式。其中FilterCondition1指定要符合更新的记录的第一个条件表达式。多个表达式可用AND和OR连接。也可以用NOT操作符和EMPTY()函数。
本例中的实例:
update bed set patient_name-inpatient where room_number=inroom and bed_number=inbed
update patient set patient_room=inroom,patient_bed=inbed where patient_name=inpatient
实例具体参见“病床管理模块设计”中“病床分配“的设计。注意其中分隔号(,)和AND的使用。
5.4 Date 的使用
本实例中设计到了日期的用法,本例中的“入院时间”本应为Date类型数据,但是在设计数据库表时却将其设置为字符型。这样做时为什么呢?因为在为“入院时间”设计输入文本框时,发现如果设为Date类型,仍然可以输入不匹配的数据。因此为严格格式,采用了对Text(文本框)的输入类型进行限制的方法。如设定起InputMask及Format属性均为“9999/99/99:,表示时间为“年/月/日”。这样做会导致Text输入的数据类型为字符型,因为在作查询的时候,要求数据类型匹配,因此需要将“入院时间”设定为字符型。而同时其排列顺序根据数字字符的ASCII码进行排序,因此其派逊结果与Date排序结果相同。
6.6. 系统的编译的发行
上面我们已经完成了医院管理系统的编程和调试工作,最后一步就是该系统的编译和发行。这涉及到工程对象的创建、可执行应用程序的生成以及发行环境的配置等多方面问题。
注意,连编程序时要求将相关的Icon、jpg文件均加入到项目中的Other(其他)选项中的Other Files(其他文件)中,如图27所示。
图 27 其他文件
图28 系统主界面运行结果
7.7. 运行结果
图28、图29、图30、图31和图32为本系统各重要表单的运行结果,其他辅助表单这里没有列出。
图 29 住院部数据管理界面运行结果
图 30 药品仪器管理界面运行结果
图 31 病人管理界面运行结果
图 32 病床管理界面运行结果
8 小结
到此,一个完整的的医院管理系统就创建完毕了。在本例子中我们详细地讲述了该医院管理系统的系统设计部分,包括功能模块设计、数据库结构设计等。
本章详细讲解了查询命令SQL的用法,读者通过学习SQL语言,可以更充分、深入的了解Query Designer的使用原理,但由于Query Designer功能有限,有的时候还是需要程序员根据需要编写更复杂的程序。
因篇幅问题不能全部显示,请点此查看更多更全内容