答案有了啊:
首先,你得先把那个“操作表”略微改一下结构,把需求另外建立三个字段(见下图桔色框部分),这样就能把正常数据写进正常字段中了;
其次,我在你给的数据中略微扩展了一下,符合各种需求,比如:只需单楼层,教学楼和节次可随意;只需教学楼+楼层,而节次可随意等等各种组合;
再次,我在程序中加入了指定需求无法安排的处理。我的处理是:将无法处理需求的人员加入到随机分配人员中(见下图大红色框部分)。你也可将代码改成指定需求无法安排时,不作安排。
好了,下面就是代码了。我在代码中写了大量的注释,以便向你传达代码的思路,再有看不懂的可跟帖问我。
SET TALK OFF
SET SAFETY OFF
SET COMPATIBLE FOXPLUS
SET DECIMALS TO 15
CLEAR ALL
=RAND(-1)
SELECT 1
USE (操作表)领导干部听课安排表 ALIAS 人员表
SELECT 2
USE 教学楼楼层使用状态 ALIAS 楼层表
************************
* 先处理有指定需求的人 *
************************
SELECT DISTINCT ALLTRIM(人员代码),"" 教学楼信息预留,0 楼层信息预留,"" 节次信息预留 ;
FROM 人员表 ;
WHERE !EMPTY(ALLTRIM(节次备注)) OR !EMPTY(ALLTRIM(教学楼备注)) OR ;
!EMPTY(ALLTRIM(楼层备注)) ;
INTO ARRAY 指定需求人员
指定需求人员数=ALEN(指定需求人员,1)
FOR AA=1 TO 指定需求人员数
当前人员代码=ALLTRIM(指定需求人员[AA,1])
SELECT ALLTRIM(教学楼备注), ALLTRIM(楼层备注), ALLTRIM(节次备注) FROM 人员表 ;
WHERE ALLTRIM(人员代码)==当前人员代码 ;
INTO ARRAY 人员信息
FOR BB=1 TO 3
IF !EMPTY(人员信息[BB]) THEN
起始双引号位置=ATCC('“',人员信息[BB])
DO CASE
CASE BB=1 &&如果是教学楼信息,就取备注双引号里的全部内容
终止双引号位置=ATCC('”',人员信息[BB])
指定需求人员[AA,2]=SUBSTRC(人员信息[BB],起始双引号位置+1,终止双引号位置-起始双引号位置-1)
CASE BB=2 &&如果是楼层信息,就转换成数字,方便后面对比
指定需求人员[AA,3]=VAL(SUBSTRC(人员信息[BB],起始双引号位置+1,2))
CASE BB=3 &&如果是节次信息,只取节次的数字
指定需求人员[AA,4]=SUBSTRC(人员信息[BB],起始双引号位置+1,2)
ENDCASE
ENDIF
NEXT
SELECT 楼层表
DO CASE
CASE 指定需求人员[AA,3]=0 AND EMPTY(指定需求人员[AA,4]) &&如果仅指定教学楼
LOCATE FOR ALLTRIM(教学楼名称)==指定需求人员[AA,2] AND ;
(ALLTRIM(状态(12))='是' OR ALLTRIM(状态(34))='是')
DO CASE
CASE ALLTRIM(状态(12))='是' AND ALLTRIM(状态(34))='是' &&如果1~4节都可听
指定需求人员[AA,4]=IIF(INT(RAND()*2+1)=1,'12','34') &&就随机指定两节
CASE ALLTRIM(状态(12))='是' &&如果只有1、2节可听
指定需求人员[AA,4]='12'
CASE ALLTRIM(状态(34))='是' &&如果只有3、4节可听
指定需求人员[AA,4]='34'
ENDCASE
CASE EMPTY(指定需求人员[AA,2]) AND EMPTY(指定需求人员[AA,4]) &&如果仅指定楼层
LOCATE FOR VAL(楼层)==指定需求人员[AA,3] AND ;
(ALLTRIM(状态(12))='是' OR ALLTRIM(状态(34))='是')
DO CASE
CASE ALLTRIM(状态(12))='是' AND ALLTRIM(状态(34))='是' &&如果1~4节都可听
指定需求人员[AA,4]=IIF(INT(RAND()*2+1)=1,'12','34') &&就随机指定两节
CASE ALLTRIM(状态(12))='是' &&如果只有1、2节可听
指定需求人员[AA,4]='12'
CASE ALLTRIM(状态(34))='是' &&如果只有3、4节可听
指定需求人员[AA,4]='34'
ENDCASE
CASE EMPTY(指定需求人员[AA,2]) AND 指定需求人员[AA,3]=0 &&如果仅指定节次
IF 指定需求人员[AA,4]='12' THEN
LOCATE FOR ALLTRIM(状态(12))='是'
ELSE
LOCATE FOR ALLTRIM(状态(34))='是'
ENDIF
CASE EMPTY(指定需求人员[AA,4]) &&如果指定了教学楼和楼层
LOCATE FOR ALLTRIM(教学楼名称)==指定需求人员[AA,2] AND VAL(楼层)==指定需求人员[AA,3] AND ;
(ALLTRIM(状态(12))='是' OR ALLTRIM(状态(34))='是')
DO CASE
CASE ALLTRIM(状态(12))='是' AND ALLTRIM(状态(34))='是' &&如果1~4节都可听
指定需求人员[AA,4]=IIF(INT(RAND()*2+1)=1,'12','34') &&就随机指定两节
CASE ALLTRIM(状态(12))='是' &&如果只有1、2节可听
指定需求人员[AA,4]='12'
CASE ALLTRIM(状态(34))='是' &&如果只有3、4节可听
指定需求人员[AA,4]='34'
ENDCASE
CASE 指定需求人员[AA,3]=0 &&如果指定了教学楼和节次
IF 指定需求人员[AA,4]='12' THEN &&1、2节
LOCATE FOR ALLTRIM(教学楼名称)==指定需求人员[AA,2] AND ALLTRIM(状态(12))='是'
ELSE &&3、4节
LOCATE FOR ALLTRIM(教学楼名称)==指定需求人员[AA,2] AND ALLTRIM(状态(34))='是'
ENDIF
CASE EMPTY(指定需求人员[AA,2]) &&如果指定了楼层和节次
IF 指定需求人员[AA,4]='12' THEN &&1、2节
LOCATE FOR VAL(楼层)==指定需求人员[AA,3] AND ALLTRIM(状态(12))='是'
ELSE &&3、4节
LOCATE FOR VAL(楼层)==指定需求人员[AA,3] AND ALLTRIM(状态(34))='是'
ENDIF
OTHERWISE &&如果全部都有指定
IF 指定需求人员[AA,4]='12' THEN &&1、2节
LOCATE FOR ALLTRIM(教学楼名称)==指定需求人员[AA,2] AND VAL(楼层)==指定需求人员[AA,3] AND ;
ALLTRIM(状态(12))='是'
ELSE &&3、4节
LOCATE FOR ALLTRIM(教学楼名称)==指定需求人员[AA,2] AND VAL(楼层)==指定需求人员[AA,3] AND ;
ALLTRIM(状态(34))='是'
ENDIF
ENDCASE
IF !FOUND() THEN &&如果没找到相应教学楼或楼层
=MESSAGEBOX('没有找到教学楼 '+指定需求人员[AA,2]+' 或楼层 '+STR(指定需求人员[AA,3],2)+CHR(13)+CHR(13);
+'无法安排 '+当前人员代码+' 的听课地点。请点击确定继续...',0,"提醒")
ELSE
***************************************************
* 如果找到听课地点,先在人员表中填上相应的信息... *
***************************************************
SELECT 人员表
LOCATE FOR ALLTRIM(人员代码)==当前人员代码
REPLACE 教学楼 WITH ALLTRIM(楼层表.教学楼名称),楼层 WITH ALLTRIM(楼层表.楼层), ;
听课节次 WITH 指定需求人员[AA,4] FOR ALLTRIM(人员代码)==当前人员代码
****************************************
* 再在楼层表相应地点的节次状态中“否” *
****************************************
SELECT 楼层表
IF 指定需求人员[AA,4]='12' THEN &&1、2节
REPLACE 状态(12) WITH '否'
ELSE &&3、4节
REPLACE 状态(34) WITH '否'
ENDIF
ENDIF
NEXT
************************
* 再处理无指定需求的人 *
************************
SELECT COUNT(DISTINCT 人员代码) 剩余人数 FROM 人员表 WHERE EMPTY(ALLTRIM(教学楼)) INTO ARRAY 剩余人数
SELECT COUNT(楼层) 一二节可听数 FROM 楼层表 WHERE ALLTRIM(状态(12))='是' INTO ARRAY 一二节可听数
SELECT COUNT(楼层) 三四节可听数 FROM 楼层表 WHERE ALLTRIM(状态(34))='是' INTO ARRAY 三四节可听数
IF 剩余人数[1]<一二节可听数[1]+三四节可听数[1] THEN &&如果剩下的人员不够分配
=MESSAGEBOX('当前可分配听课人员数为 '+STR(剩余人数[1],3)+',可供听课数为 '+STR(一二节可听数[1]+三四节可听数[1],3) ;
+CHR(13)+CHR(13)+'还缺 '+STR(一二节可听数[1]+三四节可听数[1]-剩余人数[1],3)+ ;
' 条任务无法安排。请增加人员...',0,"提醒")
ELSE
**********************************
* 取出可安排听课的无指定需求人员 *
**********************************
SELECT ALLTRIM(人员代码),RAND() FROM 人员表 WHERE EMPTY(ALLTRIM(教学楼)) ORDER BY 2 INTO ARRAY 随机人员 &&剩下人员按随机数升序排列
******************************
* 取出各节次可安排听课的楼层 *
******************************
SELECT '12' 节次,ALLTRIM(教学楼名称),ALLTRIM(楼层) FROM 楼层表 WHERE ALLTRIM(状态(12))='是' INTO ARRAY 一二节可听楼层
SELECT '34' 节次,ALLTRIM(教学楼名称),ALLTRIM(楼层) FROM 楼层表 WHERE ALLTRIM(状态(34))='是' INTO ARRAY 三四节可听楼层
********************************
* 开始安排各听课人员对应的楼层 *
********************************
一二节可听课数量=ALEN(一二节可听楼层,1)
三四节可听课数量=ALEN(三四节可听楼层,1)
FOR AA=1 TO ALEN(随机人员,1)
SELECT 人员表
LOCATE FOR ALLTRIM(人员代码)==ALLTRIM(随机人员[AA,1]) &&按随机数排好的顺序开始逐个查找定位
IF AA<=一二节可听课数量 THEN &&如果目前已安排听课的数量还在第1、2节的总数内,就分配第1、2节
REPLACE 听课节次 WITH 一二节可听楼层[AA,1],教学楼 WITH ALLTRIM(一二节可听楼层[AA,2]), ;
楼层 WITH ALLTRIM(一二节可听楼层[AA,3])
SELECT 楼层表 &&然后在楼层表中将已分配掉的课程节次注销掉
LOCATE FOR ALLTRIM(教学楼名称)==ALLTRIM(一二节可听楼层[AA,2]) AND ;
VAL(楼层)=VAL(一二节可听楼层[AA,3])
REPLACE 状态(12) WITH '否'
ELSE &&AA超出了第1、2节的总数,就开始安排第3、4节
IF AA<=一二节可听课数量+三四节可听课数量 THEN &&如果可听课数量未分配完,则继续分配。
REPLACE 听课节次 WITH 三四节可听楼层[AA-一二节可听课数量,1], ;
教学楼 WITH ALLTRIM(三四节可听楼层[AA-一二节可听课数量,2]), ;
楼层 WITH ALLTRIM(三四节可听楼层[AA-一二节可听课数量,3])
SELECT 楼层表 &&然后在楼层表中将已分配掉的课程节次注销掉
LOCATE FOR ALLTRIM(教学楼名称)==ALLTRIM(三四节可听楼层[AA-一二节可听课数量,2]) AND ;
VAL(楼层)=VAL(三四节可听楼层[AA-一二节可听课数量,3])
REPLACE 状态(34) WITH '否'
ENDIF
ENDIF
NEXT
ENDIF
SET TALK ON
SET SAFETY ON
SET DECIMALS TO 2
RETURN
图片附件: 游客没有浏览图片的权限,请
登录 或
注册