一、引言
最近接到业务部门的编程需求,给了一张图1所示的Excel表格(税负调查分析户数统计表),共有99行。程序设计好后让基层税务机关进行表格数据的录入,此表格在数据库中每个单位只存一份,发生变动在其上更改即可。其中的要求就是将表格中标有灰色部分的单元格进行屏蔽不允许进行录入。

图1 税负调查分析户数
二、需求分析
通常意义上的屏蔽一般是通过在Datawindow的设计器中将某列的tab属性的值设为0,然后将此字段的背景颜色设置为灰色即可,如图2所示。

图2 属性设置放法
也可以通过程序代码在脚本中进行动态的修改,语法格式如下:
<DW Control Name>.Object.<Columnname>.Protect='<0 - False, 1 - True>'
<DW Control Name>.Object.<Columnname>.Background.Color='<a long>'
命令的具体使用方法这里就不详细介绍了。
如用上面的传统方法进行单元格的屏蔽,在程序设计上是好控制,但要求为每个录入项建立一个字段。我们是不可能为每一个录入项目建立一个字段,像图1所示的表格如果要为每个录入项设计成一个字段则需要使用800多个字段,任何人看到这样的项目都不会愿意这样去进行数据库的设计。显然通过在数据表中一条记录保存一张表格的做法是行不通的。可以将数据库结构设计成下表形式:
表 数据库结构
字段名称 |
字段代码 |
字段类型 |
业务类型代码 |
YWLX_DM |
char(2) |
业务类型名称 |
YWLX_MC |
varchar(30) |
调查项目代码 |
DCXM_DM |
char(4) |
调查项目名称 |
DCXM_MC |
varchar(100) |
2005年列入户数 |
LRHS2005 |
numeric(6,0) |
2004年列入户数 |
LRHS2004 |
numeric(6,0) |
2005年已调查户数 |
YDCHS2005 |
numeric(6,0) |
2004年已调查户数 |
YDCHS2004 |
numeric(6,0) |
操作人员代码 |
CZRY_DM |
varchar(20) |
税务机构代码 |
SWJG_DM |
varchar(11) |
这种设计让图1表格的每一行变成了数据表中的一条记录。数据库存储的设计问题已经解决,但对于表格中的单元格的屏蔽就不那么好控制了,用上面讲的传统方法就不能进行有效的控制。这是交流和讨论的关键所在。
三、数据库表介绍
我们介绍两个主要表的结构,一个是税负调查分析户数统计表的模板表(BB_SFDCHS_MB);一个是税负调查分析户数统计表(BB_SFDCHS)。这两个表的结构一样但使用的用途不一样。建表脚本如下:
if exists (select 1
from sysobjects
where id = object_id('dbo.BB_SFDCHS_MB')
and type = 'U')
drop table dbo.BB_SFDCHS_MB
go
PRINT "BB_SFDCHS_MB"
GO
CREATE TABLE dbo.BB_SFDCHS_MB --税负调查分析户数统计表模板
(
YWLX_DM char(2) NOT NULL, --业务类型代码
YWLX_MC varchar(30) NULL, --业务类型名称
DCXM_DM char(4) NOT NULL, --业务类型代码
DCXM_MC varchar(100) NULL, --业务类型名称
LRHS2005 numeric(6,0) NULL, --列入户数2005
LRHS2004 numeric(6,0) NULL, --列入户数2004
YDCHS2005 numeric(6,0) NULL, --已调查户数2005
YDCHS2004 numeric(6,0) NULL, --已调查户数2004
CZRY_DM varchar(20) NULL, --操作人员代码
SWJG_DM varchar(11) NULL, --税务机构代码
CONSTRAINT K_BB_SFDCHS_MB
PRIMARY KEY NONCLUSTERED (YWLX_DM,DCXM_DM)
)
go
if exists (select 1
from sysobjects
where id = object_id('dbo.BB_SFDCHS')
and type = 'U')
drop table dbo.BB_SFDCHS
go
PRINT "BB_SFDCHS"
GO
CREATE TABLE dbo.BB_SFDCHS --税负调查分析户数统计表
(
YWLX_DM char(2) NOT NULL, --业务类型代码
YWLX_MC varchar(30) NULL, --业务类型名称
DCXM_DM char(4) NOT NULL, --业务类型代码
DCXM_MC varchar(100) NULL, --业务类型名称
LRHS2005 numeric(6,0) NULL, --列入户数2005
LRHS2004 numeric(6,0) NULL, --列入户数2004
YDCHS2005 numeric(6,0) NULL, --已调查户数2005
YDCHS2004 numeric(6,0) NULL, --已调查户数2004
CZRY_DM varchar(20) NULL, --操作人员代码
SWJG_DM varchar(11) NOT NULL, --税务机构代码
CONSTRAINT K_BB_SFDCHS
PRIMARY KEY NONCLUSTERED (SWJG_DM,YWLX_DM,DCXM_DM)
)
Go
这两个表的用途:BB_SFDCHS表存放客户端录入的数据;BB_SFDCHS_MB存放Excel表格的内容。
在图1所示的表格中,将需要屏蔽的单元格的值设置为“888888”(做个标记),注意这里的Excel表格列的顺序一直要和BB_SFDCHS_MB表的结构顺序保持一致,然后将此Excel表格数据另存为文本文件,以使数据快速导入到BB_SFDCHS_MB表中。
四、程序设计
创建窗口:w_bb_sfdchs_lr
此窗口主要放置三个数据窗口控件:dw_baobiao、dw_mb、dw_ylr。
对应datawindow名称:d_bb_sfdchs、d_bb_sfdchs_mb、d_bb_sfdchs。
窗口布局如图3所示。

图3 窗体布局
1.d_bb_sfdchs_mb
数据源为表BB_SFDCHS_MB,对应的SQL:
SELECT BB_SFDCHS.YWLX_DM,
BB_SFDCHS.DCXM_DM,
BB_SFDCHS.YWLX_MC,
BB_SFDCHS.DCXM_MC,
BB_SFDCHS.LRHS2005,
BB_SFDCHS.LRHS2004,
BB_SFDCHS.YDCHS2005,
BB_SFDCHS.YDCHS2004,
BB_SFDCHS.SWJG_DM,
BB_SFDCHS.CZRY_DM
FROM BB_SFDCHS
WHERE BB_SFDCHS.SWJG_DM = :v_swjg_dm
2.d_bb_sfdchs
数据源为表BB_SFDCHS,对应的SQL:
SELECT BB_SFDCHS_MB.YWLX_DM,
BB_SFDCHS_MB.DCXM_DM,
BB_SFDCHS_MB.YWLX_MC,
BB_SFDCHS_MB.DCXM_MC,
BB_SFDCHS_MB.LRHS2005,
BB_SFDCHS_MB.LRHS2004,
BB_SFDCHS_MB.YDCHS2005,
BB_SFDCHS_MB.YDCHS2004,
BB_SFDCHS_MB.CZRY_DM,
BB_SFDCHS_MB.SWJG_DM
FROM BB_SFDCHS_MB
3.流程讲解
首先dw_mb (模板)数据窗口控件从BB_SFDCHS_MB表中取得数据,然后执行<DW Control Name>.rowscopy()命令将数据拷贝到dw_baobiao中。逐行检查数据列LRHS2005、LRHS2004 、YDCHS2005 、YDCHS2004。如果数据内容等于“888888”则屏蔽此单元格。
用税务机关作为参数,dw_ylr 提取数据表中已录入的数据,如果dw_ylr中存在数据则将数据替换到dw_baobiao中,如无数据则表示没有进行数据录入。
保存数据时,先删除BB_SFDCHS表中对应的数据,然后将dw_baobiao中的数据保存到数据库BB_SFDCHS表中。实现的核心代码及相关说明如下:
//窗口w_bb_sfdchs_lr中定义的Instance 变量:
string is_swjgdm
int LRHS2005[],LRHS2004[],YDCHS2005[],YDCHS2004[]
//窗口w_bb_sfdchs_lr的open事件脚本:
dw_mb.settransobject(sqlca)
dw_mb.retrieve()
dw_ylr.settransobject(sqlca)
dw_baobiao.settransobject(sqlca)
//“确定”按钮的clicked事件脚本:
//is_swjgdm 税务机构代码,此窗口定义的instance变量
is_swjgdm=ddlb_swjg_dm.text
if len(is_swjgdm)<1 then
messagebox("提示","请输入税务机构!")
return
end if
dw_baobiao.reset()
dw_mb.rowscopy(1,dw_mb.rowcount(),Primary!,dw_baobiao,1,Primary!)
//屏蔽单元格
dw_baobiao.setredraw(FALSE)
dw_baobiao.modify("LRHS2005.background.mode=0")
dw_baobiao.modify("LRHS2004.background.mode=0")
dw_baobiao.modify("#7.background.mode=0")
dw_baobiao.modify("#8.background.mode=0")
int i
int lr05=1,lr04=1,ydc05=1,ydc04=1
//LRHS2005[],LRHS2004[],YDCHS2005[],YDCHS2004[]
for i=1 to dw_baobiao.rowcount()
if dw_baobiao.GetItemNumber(i,"LRHS2005")=888888 then
LRHS2005[lr05]=i
lr05=lr05+1
dw_baobiao.setItem(i,"LRHS2005",0)
end if
if dw_baobiao.GetItemNumber(i,"LRHS2004")=888888 then
LRHS2004[lr04]=i
lr04=lr04+1
dw_baobiao.setItem(i,"LRHS2004",0)
end if
if dw_baobiao.GetItemNumber(i,"YDCHS2005")=888888 then
YDCHS2005[ydc05]=i
ydc05=ydc05+1
dw_baobiao.setItem(i,"YDCHS2005",0)
end if
if dw_baobiao.GetItemNumber(i,"YDCHS2004")=888888 then
YDCHS2004[ydc04]=i
ydc04=ydc04+1
dw_baobiao.setItem(i,"YDCHS2004",0)
end if
next
//屏蔽LRHS2005字段
string ls_p
string ls_g
ls_p="LRHS2005.protect='1~tif((getrow()= "
ls_g="LRHS2005.background.color='1000~tif((getrow()="
for i=1 to upperbound(lrhs2005[])
if i=1 then
ls_p=ls_p+string(lrhs2005[i])
ls_g=ls_g+string(lrhs2005[i])
else
ls_p=ls_p+" or getrow()="+string(lrhs2005[i])
ls_g=ls_g+" or getrow()="+string(lrhs2005[i])
end if
next
ls_p=ls_p+"),1,0)'"
ls_g=ls_g+ "),rgb(212,208,200),rgb(255,255,255))'"
dw_baobiao.modify(ls_p)
dw_baobiao.modify(ls_g)
//屏蔽LRHS2004字段
ls_p="LRHS2004.protect='1~tif((getrow()= "
ls_g="LRHS2004.background.color='1000~tif((getrow()="
for i=1 to upperbound(LRHS2004[])
if i=1 then
ls_p=ls_p+string(LRHS2004[i])
ls_g=ls_g+string(LRHS2004[i])
else
ls_p=ls_p+" or getrow()="+string(LRHS2004[i])
ls_g=ls_g+" or getrow()="+string(LRHS2004[i])
end if
next
ls_p=ls_p+"),1,0)'"
ls_g=ls_g+ "),rgb(212,208,200),rgb(255,255,255))'"
dw_baobiao.modify(ls_p)
dw_baobiao.modify(ls_g)
//屏蔽YDCHS2005字段
ls_p="YDCHS2005.protect='1~tif((getrow()= "
ls_g="#7.background.color='1000~tif((getrow()="
for i=1 to upperbound(YDCHS2005[])
if i=1 then
ls_p=ls_p+string(YDCHS2005[i])
ls_g=ls_g+string(YDCHS2005[i])
else
ls_p=ls_p+" or getrow()="+string(YDCHS2005[i])
ls_g=ls_g+" or getrow()="+string(YDCHS2005[i])
end if
next
ls_p=ls_p+"),1,0)'"
ls_g=ls_g+ "),rgb(212,208,200),rgb(255,255,255))'"
dw_baobiao.modify(ls_p)
dw_baobiao.modify(ls_g)
//屏蔽YDCHS2004字段
ls_p="YDCHS2004.protect='1~tif((getrow()= "
ls_g="#8.background.color='1000~tif((getrow()="
for i=1 to upperbound(YDCHS2004[])
if i=1 then
ls_p=ls_p+string(YDCHS2004[i])
ls_g=ls_g+string(YDCHS2004[i])
else
ls_p=ls_p+" or getrow()="+string(YDCHS2004[i])
ls_g=ls_g+" or getrow()="+string(YDCHS2004[i])
end if
next
ls_p=ls_p+"),1,0)'"
ls_g=ls_g+ "),rgb(212,208,200),rgb(255,255,255))'"
dw_baobiao.modify(ls_p)
dw_baobiao.modify(ls_g)
dw_baobiao.setredraw(true)
//屏蔽单元格
int li_rowcount
li_rowcount=dw_ylr.retrieve(is_swjgdm)
if dw_ylr.rowcount()<>0 then
for i=1 to li_rowcount
dw_baobiao.setitem(i,"lrhs2005",dw_ylr.GetItemNumber(i,"lrhs2005"))
dw_baobiao.setitem(i,"lrhs2004",dw_ylr.GetItemNumber(i,"lrhs2004"))
dw_baobiao.setitem(i,"ydchs2005",dw_ylr.GetItemNumber(i,"ydchs2005"))
dw_baobiao.setitem(i,"ydchs2004",dw_ylr.GetItemNumber(i,"ydchs2004"))
next
end if
//“保存”按钮的clicked事件脚本:
long ll_rowcount,ii
ll_rowcount=dw_baobiao.rowcount()
if ll_rowcount=0 then
return
end if
if dw_baobiao.ModifiedCount()>36 then
for ii=1 to ll_rowcount
dw_baobiao.setitem(ii,"swjg_dm",is_swjgdm)
dw_baobiao.setitem(ii,"czry_dm",gs_czry_dm)
next
delete from BB_SFDCHS WHERE SWJG_DM=:is_swjgdm using sqlca;
end if
if dw_baobiao.update()<>1 then
rollback;
messagebox('注意!','存盘未成功,'+sqlca.sqlerrtext,stopsign!)
return
else
commit;
messagebox('注意!','存盘成功!')
end if
保存时先为每一行数据加上单位代码和操作人员代码,删除BB_SFDCHS表中已存的该单位的数据,然后将新数据保存提交到数据库。
//“退出”按钮的clicked事件脚本:
close(parent)
程序代码设计完成后,将数据窗口控件dw_mb、dw_ylr的可见属性设置为隐藏。
其中,需要重点理解“确定”按钮的clicked事件的下列代码:
1.刷新设置
dw_baobiao.setredraw(FALSE)
在缺省情况下,PB中的控件在改变属性后,都会进行自动刷新,此代码将刷新设置为FALSE,关闭自动刷新功能。如执行成功则返回1,执行错误则返回-1。
2.修改数据窗口列属性
dw_baobiao.modify("LRHS2005.background.mode=0")
dw_baobiao.modify("LRHS2004.background.mode=0")
dw_baobiao.modify("#7.background.mode=0")
dw_baobiao.modify("#8.background.mode=0")
修改数据窗口列属性,将LRHS2005、LRHS2004列和第7、8列的背景模式设置为0,这里一定要设置为不透明模式,否则达不到预想效果。0表示背景为不透明,1表示透明。
也可以使用下面的命令进行修改:
<DW Control Name>.Object.<Columnname>.Background.Mode='<0 - Opaque, 1 - Transparent>'
3.判断单元格内容
//LRHS2005[],LRHS2004[],YDCHS2005[],YDCHS2004[]
for i=1 to dw_baobiao.rowcount()
if dw_baobiao.GetItemNumber(i,"LRHS2005")=888888 then
LRHS2005[lr05]=i
lr05=lr05+1
dw_baobiao.setItem(i,"LRHS2005",0)
end if
if dw_baobiao.GetItemNumber(i,"LRHS2004")=888888 then
LRHS2004[lr04]=i
lr04=lr04+1
dw_baobiao.setItem(i,"LRHS2004",0)
end if
if dw_baobiao.GetItemNumber(i,"YDCHS2005")=888888 then
YDCHS2005[ydc05]=i
ydc05=ydc05+1
dw_baobiao.setItem(i,"YDCHS2005",0)
end if
if dw_baobiao.GetItemNumber(i,"YDCHS2004")=888888 then
YDCHS2004[ydc04]=i
ydc04=ydc04+1
dw_baobiao.setItem(i,"YDCHS2004",0)
end if
next
这段代码使用四个数组LRHS2005[]、LRHS2004[]、YDCHS2005[]、YDCHS2004[],采用循环的方式判断单元格的内容是否为“888888”(“888888”是预备屏蔽标记),记录需要进行屏蔽的行号,同时将其值设置为零。
4.屏蔽相应单元格
//屏蔽LRHS2005字段
string ls_p
string ls_g
ls_p="LRHS2005.protect='1~tif((getrow()= "
ls_g="LRHS2005.background.color='1000~tif((getrow()="
for i=1 to upperbound(lrhs2005[])
if i=1 then
ls_p=ls_p+string(lrhs2005[i])
ls_g=ls_g+string(lrhs2005[i])
else
ls_p=ls_p+" or getrow()="+string(lrhs2005[i])
ls_g=ls_g+" or getrow()="+string(lrhs2005[i])
end if
next
ls_p=ls_p+"),1,0)'"
ls_g=ls_g+ "),rgb(212,208,200),rgb(255,255,255))'"
dw_baobiao.modify(ls_p)
dw_baobiao.modify(ls_g)
我们这里只取出了一个列LRHS2005的屏蔽代码。根据lrhs2005[]数组的记录,屏蔽LRHS2005列中相应的单元格,并将其背景颜色设置成灰色。ls_p变量存放的是屏蔽单元格的代码,ls_g变量存放的是设置单元格背景颜色的代码,通过在程序执行时捕捉到其内容分别为:
LRHS2005.protect='1 if((getrow()= 7 or getrow()=15 or getrow()=18 or getrow()=20 or getrow()=22 or getrow()=23 or getrow()=24 or getrow()=25 or getrow()=26 or getrow()=27 or getrow()=28 or getrow()=29 or getrow()=30 or getrow()=31 or getrow()=32 or getrow()=33 or getrow()=34 or getrow()=35 or getrow()=36 or getrow()=38 or getrow()=39 or getrow()=40 or getrow()=41 or getrow()=42 or getrow()=43 or getrow()=44 or getrow()=45 or getrow()=46 or getrow()=47 or getrow()=48 or getrow()=49 or getrow()=50 or getrow()=51 or getrow()=52 or getrow()=54 or getrow()=55 or getrow()=57 or getrow()=58 or getrow()=59 or getrow()=60 or getrow()=61 or getrow()=62 or getrow()=63 or getrow()=64 or getrow()=65 or getrow()=66 or getrow()=67 or getrow()=68 or getrow()=69 or getrow()=71 or getrow()=72 or getrow()=73 or getrow()=74 or getrow()=76 or getrow()=77 or getrow()=78 or getrow()=80 or getrow()=81 or getrow()=82 or getrow()=83 or getrow()=84 or getrow()=94 or getrow()=95),1,0)'
LRHS2005.background.color='1000 if((getrow()=7 or getrow()=15 or getrow()=18 or getrow()=20 or getrow()=22 or getrow()=23 or getrow()=24 or getrow()=25 or getrow()=26 or getrow()=27 or getrow()=28 or getrow()=29 or getrow()=30 or getrow()=31 or getrow()=32 or getrow()=33 or getrow()=34 or getrow()=35 or getrow()=36 or getrow()=38 or getrow()=39 or getrow()=40 or getrow()=41 or getrow()=42 or getrow()=43 or getrow()=44 or getrow()=45 or getrow()=46 or getrow()=47 or getrow()=48 or getrow()=49 or getrow()=50 or getrow()=51 or getrow()=52 or getrow()=54 or getrow()=55 or getrow()=57 or getrow()=58 or getrow()=59 or getrow()=60 or getrow()=61 or getrow()=62 or getrow()=63 or getrow()=64 or getrow()=65 or getrow()=66 or getrow()=67 or getrow()=68 or getrow()=69 or getrow()=71 or getrow()=72 or getrow()=73 or getrow()=74 or getrow()=76 or getrow()=77 or getrow()=78 or getrow()=80 or getrow()=81 or getrow()=82 or getrow()=83 or getrow()=84 or getrow()=94 or getrow()=95),rgb(212,208,200),rgb(255,255,255))'
最后通过dw_baobiao.modify(ls_p)、dw_baobiao.modify(ls_g)进行动态地修改。其他三列的代码大同小异不一一讲解了。但一定要记住屏蔽代码的最后一定要执行dw_baobiao.setredraw(true) 恢复刷新模式。
本程序在pb11.0 7549 和pb9.0下调试成功。
|