3.日常的报表及数据查询
在报表文件及数据存储完成后,后台管理人员需要查询日常的报表文件及数据,系统的设计采用Web Browser组件将邮储前置系统下的报表文件以FILE STREAM方式转换为Windows平台下的纯文本格式文件,再在Web Browser组件中显示出来, 电子报表的可视效果将与纸质报表文件的效果完全一致。FILE STREAM格式转换函数如下设计:
CString CHDBBPRINT::WebStr2Str(LPCSTR lpBuf)
{
int nLen;
if(!lpBuf) nLen=0;
else nLen=::lstrlen(lpBuf);
CString s; int i=0;
while(i<nLen)
{
if(lpBuf[i]=='%')
{
BYTE c1=lpBuf[i+1];
BYTE c2=lpBuf[i+2];
i+=2;
if(c1>='0' && c1<='9') c1=(c1-'0')*16;
else if(c1>='A' && c1<='Z') c1=(c1-'A'+10)*16;
else if(c1>='a' && c1<='a') c1=(c1-'a'+10)*16;
if(c2>='0' && c2<='9') c2=c2-'0';
else if(c2>='A' && c2<='Z') c2=c2-'A'+10;
else if(c2>='a' && c2<='z') c2=c2-'a'+10;
char szStr[2]; szStr[0]=c1+c2; szStr[1]=0;
s+=szStr;
}
else if(lpBuf[i]=='+') s+=" ";
else s+=CString(&lpBuf[i],1);
i++;
}
return s;
}
采用Web Browser组件预览转换后的报表文件为防止格式转换后的乱符及无法打印现象, 将转换格式后文件再做过滤处理,如下函数设计:
void CHDBBPRINT::OnBeforeNavigate2Explorer(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel)
{
CString sURL(URL->bstrVal);
int id=sURL.ReverseFind('\\'); //反向查找"\和/"
if(id==-1) sURL.ReverseFind('/');
try
{
if(sURL.Mid(id+1).CompareNoCase("ToDialog"))
throw(0); //不是预定义的URL
if(((PostData->vt) & (VT_VARIANT | VT_BYREF))==0)
throw(0);
VARIANT * v=PostData->pvarVal;
if(((v->vt) & (VT_UI1 | VT_ARRAY))==0)
throw(0);
SAFEARRAY *pArr=v->parray;
CString sData=(LPCSTR)pArr->pvData; //至此,得到传送的数据流
// 数据流的结构
// 变量1=值1&变量2=值2&......变量n=值n
CStringArray arrPart;
while(TRUE) //按照 '&' 进行拆分
{
id=sData.Find('&');
if(id==-1){ arrPart.Add(sData); break; }
arrPart.Add(sData.Left(id));
sData=sData.Mid(id+1);
}
CString sResult;
for(int nPart=0;nPart<arrPart.GetSize();nPart++)
{ //循环处理每个“变量=值”的部分
CString sPart=arrPart.GetAt(nPart); //取出
id=sPart.Find('=');
ASSERT(id!=-1);
CString sName = sPart.Left(id); //变量名
CString sValue= sPart.Mid(id+1); //值
sName = WebStr2Str(sName); //转换Web字符串到标准字符串
sValue= WebStr2Str(sValue);
sResult += sName+" = "+sValue+"<br>";
}
//以下是演示使用DHTML
IHTMLDocument2 *pDoc=(IHTMLDocument2 *)m_explore.GetDocument();
VARIANT *param;
SAFEARRAY *sfArray;
BSTR bstr = sResult.AllocSysString();
sfArray = SafeArrayCreateVector(VT_VARIANT, 0, 1);
if(sfArray && pDoc)
{
if(S_OK == SafeArrayAccessData(sfArray,(LPVOID*) & param))
{
param->vt = VT_BSTR;
param->bstrVal = bstr;
SafeArrayUnaccessData(sfArray);
pDoc->write(sfArray);
}
SysFreeString(bstr);
if (sfArray) SafeArrayDestroy(sfArray);
}
pDoc->Release();
*Cancel=TRUE;
}
catch(...)
{
*Cancel=FALSE;
}
}
设计完成后可预览转换后的电子报表文件如同纸质报表一样的效果, 软件界面如图11所示。
图11 报表设计效果
4. 经营状况分析
现金收支日报可按自定义条件生成全区网点现金收支数据并计算每个网点的超限率状况;空白凭证统计报表按自定义条件可分析出全区网点的凭证领用状况;每日余额汇总报告实时统计出全区当日余额状况,平均余额汇总报告为按用户给定的时间段统计出各网点的平均余额状况,余额净增状况汇总为按用户给定的日期比较分析各网点及管理机构的余额相对净增及本年度累计净增状况;邮储余额趋势分析为用户提供指定年度全年或全月同时间段内的余额走势曲线图,可直观看出全区余额走势状况。
以余额走势曲线图模块为例,核心代码如下:
……
VARIANT var;
m_chart.GetPlot().GetAxis(1,var).GetValueScale().SetAuto(FALSE);//不自动标注y轴刻度
m_chart.GetPlot().GetAxis(1, var).GetValueScale().SetMaximum(y_nummax);//y轴最大刻度
m_chart.GetPlot().GetAxis(1, var).GetValueScale().SetMinimum(y_nummin);//y轴最小刻度
m_chart.GetPlot().GetAxis(1,var).GetValueScale().SetMajorDivision((y_nummax-y_nummin)/y_divynum);//y轴刻度等分
m_chart.GetPlot().GetAxis(1,var).GetValueScale().SetMinorDivision(1);//每刻度一个刻度线
m_chart.SetColumnCount(2); //两条曲线
m_chart.SetColumnLabelCount(1);
m_chart.GetPlot().GetSeriesCollection().GetItem(1).GetPen().GetVtColor().Set(0, 0, 255);//线色
m_chart.GetPlot().GetSeriesCollection().GetItem(1).GetPen().SetWidth(4);//线宽
m_chart.GetPlot().GetSeriesCollection().GetItem(1).SetLegendText(buffer_yearstart+buffer_month);//添加图例
m_chart.SetColumnLabelCount(2);
m_chart.GetPlot().GetSeriesCollection().GetItem(2).GetPen().GetVtColor().Set(255, 0, 0);//线色
m_chart.GetPlot().GetSeriesCollection().GetItem(2).GetPen().SetWidth(4);//线宽
m_chart.GetPlot().GetSeriesCollection().GetItem(2).SetLegendText(buffer_yearend+buffer_month);//添加图例
m_chart.SetRowCount(x_num);//x轴长度
m_chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetAuto(FALSE);//不自动标注x轴刻度
m_chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetDivisionsPerLabel(1);
//每时刻一个标注
m_chart.GetPlot().GetAxis(0,var).GetCategoryScale().SetDivisionsPerTick(1);//每时刻一个刻度线
……
m_chart.SetData("0");
m_chart.SetColumnLabelIndex(2);
m_chart.SetColumnLabel("0");
}
}
5. 报表的模糊查询与批量打印
报表文件按本系统设计的目录结构在存储到本地报表服务器后,由于日常的业务需求,需要查询历史记录及指定的信息,如果传统的纸质报表将面临检索困难及时间缓慢等问题,本系统中专门设计了模糊查询模块用于在大批量存档的电子报表中模糊检索含有指定字符串的报表文件,并将信息汇总出来。设计思想为:根据操作人员选择的报表检索范围,系统自动逐个读取该范围内的报表文件,并分析报表文件的逐行数据将操作人员录入的检索信息与数据比对,并列出含有该信息的报表文件.
此模块关键使用Win32的FILE OPR函数操作文件,逐行读取文件并检索比对信息的技术采用模式匹配方式类似于Windows的文件搜索技术.实现的核心代码如下:
//搜索包含字串的报表
……
CFileFind finder;
BOOL bWorking=finder.FindFile(stringfindrqml);
while(bWorking)
{
bWorking = finder.FindNextFile();
if(finder.IsDots())
continue;
if(finder.IsDirectory())
{
CString stringbbrq=finder.GetFileName();
if(stringbbrq>=string_startrq&&stringbbrq<=string_endrq)
{
for(int ibb=0;ibb<int_selbbcount;ibb++)
{
CString stringbbpath=stringbbzml;
stringbbpath+=stringbbrq;
stringbbpath+="\\";
stringbbpath+=string_bbmc[ibb];
// MessageBox(stringpath);
FILE* fp;
if(fp=fopen(stringbbpath,"r"))
{
CString ti="正在搜索";
ti+=stringbbpath;
m_ti.SetWindowText(ti);
char ch_linestring[500];
while(!feof(fp))
{
fgets(ch_linestring,500,fp);
CString str_linestring=ch_linestring;
if(str_linestring.Find(string_cxzc)!=-1)
{ m_bbcxlist.InsertItem(0,stringbbpath,ICI_FILE_ICON);
break;
}
}
fclose(fp);
}
}
}
}
}
}
m_ti.SetWindowText("报表文件搜索完毕!");
对于报表文件的批量打印,系统采用Web Browser组件的打印接口,并采用FILE STREAM重定向输出的技术将文件直接输出到打印机上,从而批量打印出报表文件,打印效果如同统版软件打印出的报表格式一样清晰,也可以提取指定的数据在打印机上输出。实现的核心代码如下:
for(int ibb=0;ibb<int_selbbcount;ibb++)
{
CString stringbbpath=stringbbzml;
stringbbpath+=stringbbrq;
stringbbpath+="\\";
stringbbpath+=string_bbmc[ibb];
FILE* fp;
if((fp=fopen(stringbbpath,"r"))!=NULL)
{
CString ti="正在预览/打印";
ti+=stringbbpath;
m_ti.SetWindowText(ti);
m_explore.Navigate(stringbbpath,NULL,NULL,NULL,NULL);
Sleep(1000); m_explore.ExecWB(OLECMDID_PRINT,OLECMDEXECOPT_DONTPROMPTUSER,NULL,NULL);
fclose(fp);
}
}
6. 报表文件备份刻录
由于报表服务器的空间有限,随着时间的推移,大量的历史数据需要保存,因此最好的方式是将存档的电子报表文件刻录到光盘上并分类保存到媒体库中,方便历史查询,也可有效地节约服务器空间。系统专门设计的报表备份刻录模块,根据操作人员选择的条件,系统将自动检索报表文件并写入外置的刻录机光盘中,此模块主要采用Win32的shell's ICDBurn接口函数开发。shell's ICDBurn接口函数是Windows 4.0版本以后的重要刻录机控制函数,目前市场上的刻录软件大多通过包装此函数完成刻录工作。本模块的刻录功能本质上与各刻录软件的功能是一致的.
设计思想如下: 用HasRecordableDrive扫描系统内可写的CD驱动器,找到的话返回TRUE。使用GetRecorderDriveLetter返回可写驱动器的盘符。最后刻录指令通知Windows从“集结区”向可写CD拷贝数据。“集结区”是一个专用的文件夹,通常是"%userprofile%\Local Settings\Application Data\Microsoft\CD Burning", 但还是应该调用SHGetFolderPath和参数CSIDL_CDBURN_AREA获得准确的目录名。本模块将需要刻录的报表文件集中写入指定临时目录并赋值给SHGetFolderPath,从而完成刻录工作。实现的核心代码如下:
CCDBurn burner_report;
if (!burner_report.HasRecordableDrive())
{
……
}
else
{
CString do_report = burner.GetRecorderDriveLetter();
……
//备份报表
……
FILE* fp;
if((fp=fopen(stringbbpath,"r"))!=NULL)
{
CString ti="正在备份存储";
ti+=stringbbpath;
m_ti.SetWindowText(ti);
fclose(fp);
}
CopyFile(stringbbpath,stringcdrompath,false);
}
……
7. 辅助功能设计
文件日志备份:可按给定时间段生成或清理邮储及后督报表文件的传输日志,以检查报表文件传输是否完全,对系统的各类生产文件进行详细备份。
电子报表备份:可按用户自定义的各类条件提取备份需要的报表文件到存储介质上,以电子文档的方式可长期保存历史数据,并通过模糊查询功能快速查询需要的报表资料。
运行设备监控:对邮政信息网的各类设备及终端网络进行跟踪监控,实时反映网内设备运行状况,方便数据分析。
辅助设置:其他辅助功能,如计算器、刻录工具链接等.
系统模块设计充分考虑可扩展性,所有的模块均可自由重组挂接第三方组件,由于篇幅原因不详细赘述各模块设计方法.
四、系统关键技术
结合我局的生产模式,本系统服务器安装Windows2003 Server操作系统,数据库选用Access2000或SQL Server 2000,并安装趋势科技杀毒软件及防火墙,采用Visual Studio 2005开发工具开发,客户端使用实达WT5000(Windows终端)自带的终端访问软件。服务器选用浪潮NP180服务器(配置P4 3.0,512M,2*SATA 80G,RAID1),客户端选用2台实达WT5000,并配置USB光盘刻录机.采用Windows终端实现多操作系统的访问,提高设备利用率,减少设备投资.
1. 软件的逻辑架构:在我局中心机房安装装一台服务器与统版集中服务器及事后监督服务器联网,自动或手动抓取上一日报表,并配备Windows终端3台分别部署在事后监督机房、会计办公室及储汇办公室内,通过权限设置,分别给事后监督员、会计及分局管理人员调阅相应报表。服务器的管理由事后监督档案管理员负责系统的日常监控及管理,对于需要打印的报表在后台选择打印,并定期(每月)将数据备份到存档介质上(光盘或移动硬盘),并保存到媒体存放库中。
2. 软件开发采用Visual C++ 2005 ,数据库设计采用Access 2000或SQL Server 2000,对于报表传输采用定时数据采集的方法用Scocket套接字提取Unix集中服务器上的报表文件,在传输报表文件的同时用FILE STREAM技术对于报表文件中的关键经营数据进行重定向存入后台的Access数据库表中,便于各类报表数据的统计分析。
3.对于历史报表文件传输后存放在磁盘的指定机构与日期目录下,软件中有专门模块对历史报表文件检索访问,报表文件从Unix系统传输到Windows服务器上时用MFC的FILE STREAM技术转换文件格式为纯流方式,这样在软件中可用Web Browser方便快捷地浏览到与纸质报表一样清晰的数据。
4.对于历史账户信息等较模糊条件的数据,软件中采用Windows的MFC文件字节流搜索的方法可帮助用户快速检索到所需信息,避免了人工查找历史数据的繁琐。
5.对于报表中提取的关键经营数据,根据业务部门需要,软件中采用aRes Report VC专用报表工具开发出各类经营分析报表供业务部门参考使用;对于余额等关键性数据软件中采用MS CHART专业图表组件开发出年月类比的曲线/柱状走势图,为经营提供直观的分析数据类比。
6.对于各级操作人员,软件采用MENU CONTROL方式界定了严格的操作权限,确保了设密数据访问的安全性。
7.服务器安装Windows 2003 Server操作系统,客户端采用实达万维终端通过终端服务软件连接到服务器,在Server端对每个客户终端的权限分配和操作都有严格的界定和监控,确保了数据传输和访问的安全与高效性。
8.对于历史报表文件与重要数据,软件中提供刻录功能,操作人员可灵活选择所需网点在指定时间段内的指定报表文件刻录成光盘存档,在需要查阅历史数据时,操作人员只需将光盘放入CD-ROM中,用软件提供的报表检索、模糊查询、经营数据提取等相关功能可快速提取所需信息。
9.软件提供了批量报表打印功能,可根据需要用后台的高速报表打印机批量打印光盘或磁盘中指定网点在指定时间段内的报表文件。
10.可扩展性:全省其余地市局只需改变软件中的参数设置就可直接使用本软件,目前省中心也可采用报表数据大集中的方式存储,只需将本软件的数据库后台用DCOM方式从Access 2000移植到Oracle并改变相应的参数设置即可使用。
11.软件为分布式应用运行模式,前台网点采用Unix下的客户端登录查询历史报表,后台有专门的报表自动传输机及管理分析平台,操作简便,维护方便,功能实用且强大,弥补了邮储统版软件地市局报表无存储管理的电子缺陷。
12.整体的网络结构部署如图12所示。
图12 网络结构部署
五、结语
随着邮储系统的不断升级完善,该系统将之不断修改而尽可能地满足我局的生产需要。以上是笔者运用Viusal C++平台开发的邮政储蓄银行报表电子存储及分析系统的设计概要,不足之处请各位同行批评指正。
|