仓库管理是整个物资供应管理系统的核心。本实例着重讲解仓库管理模块,给出数据库设计和程序实现过程。
1、系统设计
1、1系统设计目标
系统开发的总统任务是实现企业物资设备管理的系统化、规范化和自动化,从而达到仓库管理效率的目的。 1、2开发设计思想
在本系统的设计过程中,为了克服仓库管理信息处理量大的困难,满足计算机管理的需要,采取了下面的一些原则:
● ● 统一各种原始单据的格式,统一帐目和报表的格式。 ● ● 删除不必要的管理冗余,实现管理规范化、科学化。
● ● 程序代码标准化,软件统一化,确保软件的可维护性和实用性。
● ● 界面尽量简单化,做到实用、方便,尽量满足企业不同层次员工的需要。 ● ● 建立操作日志,系统自动记录所进行的各种操作。 1、3系统功能分析
本例中的仓库管理系统需要完成的功能主要有以下几点:
● ● 仓库管理各种信息的输入,包括入库、出库、还库、需求信息的输入等。 ● ● 仓库管理各种信息的查询、修改和维护。 ● ● 设备采购报表的生成。
● ● 在库存管理中加入最高储备和最低储备字段,对仓库中的物资设备实现监
控和报警。
● ● 企业各部门的物资需求的管理。 ● ● 操作日志的管理。
● ● 仓库管理系统的使用帮助。 1、4系统功能模块设计
在系统功能分析的基础上,结合Visual C++程序编制的特点,得到如图1-1所示的系统功能模块图。
仓库管理系统 系输维查报
统入护看表
模模模模模
块 块 块 块 块
入出还需 日 库库库求志
模模模模管 块块 块 块 理 图1-1 系统功能模块图
2、数据库设计
帮助模块 2、1数据库需求分析
在仔细调查企业仓库物资设备管理过程的基础上,得到本系统所处理的数据流程如图1-2所示:
仓库现有库存各部门需求 企业生产计划
汇总
设备采购 设备出库 图1-2 数据流程图 本实例设计的数据项和数据结构如下: 设备入库 设备还库 ● ● 设备代码信息,包括的数据项有设备号、设备名称。 ● ● 现有库存信息,包括的数据项有设备、现有数目、总数目、最大库存和最
小库存。
● ● 设备使用信息,包括的数据项有使用的设备、使用部门、数目、使用时间
和出库时状态等。
● ● 设备采购信息,包括的数据项有采购的设备、采购员、供应商、采购数目
和采购时间等。
● ● 设备归还信息,包括的数据项有归还设备、归还部门、归还数目、归还时
间和经手人等。
● ● 设备需求信息,包括的数据项有需求的部门、需求设备、需求数目和需求
时间等。
2、2数据库概念结构设计
本实例根据上面的设计规划出的实体有库存实体、入库实体、出库实体、采购实体、还库实体和需求实体,各实体的E-R图及其关系描述如下: 现有库存 设备号 现有库存 警戒库存 总数
图1-3 库存实体E-R图
入库
设备号 供应商信息 采购价格数量 采购员
图1-4 入库实体E-R图
设备号 使用部门 数量时间
图1-5 出库实体E-R图
经手人
出库
设备号 部门需求 需求部门 需求数量
图1-6 部门需求实体E-R图
设备还库 需求时间
设备号 还库时间、人 还库数量 经手人
图1-7 还库实体E-R图
设备号 计划采购 库存信息
供应信息 时间 图1-8计划采购实体E-R图
入库 现有库存 出库 还库
部门需求 设备采购 图1-9实体和实体之间的关系E-R图
2、3数据库逻辑结构设计
在上面的实体以及实体之间的关系的基础上,形成数据库中的表格和各个表格之间的关系。仓库管理系统数据库中各个表格的设计结果如下面的几个表格所示。每个表格表示在数据库中的一个表。
表1-1 设备代码表device_code 列名 数据类型 可否为空 说明 code VARCHAR2(6) NOTNULL 设备号(主键) 设备名称 说明 设备号 入库时间(主键) 供应商 供应商电话 入库数量 价格 采购员 说明 设备号 使用部门 出库时间(主键) 出库状态 经手人 出库数量 领取人 用途 说明 设备号(主键) 现有库存 最大库存 最少库存 name NULL VARCHAR2(20) 表1-2 设备入库表device_in 列名 数据类型 可否为空 code in_date provider teleno in_number price VARCHAR2(6) DATE VARCHAR2(20) VARCHAR2(10) NUMBER(6) NUMBER(6) NOTNULL NOTNULL NULL NULL NULL NULL buyer NULL VARCHAR2(10) 表1-3 设备出库表device_out 列名 数据类型 可否为空 code department out_date out_state out_person out _number taker VARCHAR2(6) VARCHAR2(20) DATE NUMBER(1) VARCHAR2(10) NUMBER(6) VARCHAR2(10) NOTNULL NULL NULL NULL NULL NOTNULL NULL usage NULL VARCHAR2(20) 表1-4 现有库存表device 列名 数据类型 可否为空 code now_number high _number low _number VARCHAR2(6) NUMBER(6) NUMBER(6) NUMBER(6) NOTNULL NULL NULL NULL total _number NULL NUMBER(6) 表1-5 部门需求表device_need 列名 数据类型 可否为空 code department need _number begin_date VARCHAR2(6) VARCHAR2(20) NUMBER(6) DATE NOTNULL NOTNULL NULL NULL 总数 说明 设备号 部门名称 需求数量 需求开始时间 需求结束时间 说明 设备号 还库时间(主键) 仓库管理员 归还数量 归还人 说明 操作员 操作内容 操作时间 说明 设备号 现有库存 总库存 最大库存 购买数量 供应商 价格 end_date DATE NULL 表1-6 设备还库表device_return 列名 数据类型 可否为空 code return_date keeper return_ number VARCHAR2(6) DATE VARCHAR2(20) NUMBER(6) NOTNULL NULL NULL NULL return_date NULL VARCHAR2(10) 表1-7 操作日志表 howdo 列名 数据类型 可否为空 do_user do_what VARCHAR2(10) VARCHAR2(40) NOTNULL NOTNULL do_date DATE NOTNULL 表1-8 设备采购计划表device_wantbuy 列名 数据类型 可否为空 code now_number total_number max_number buy_number provider price buy_date VARCHAR2(6) NUMBER(6) NUMBER(6) NUMBER(6) NUMBER(6) VARCHAR2(10) NUMBER(6) DATE NOTNULL NULL NULL NULL NULL NULL NULL NULL 计划采购时间(主键) 3、数据库结构的实现 4、创建应用程序
(1) (1) 选择“FileNew”中的“新建项目”选项卡中“MFC AppWizard
(exe)”,设置合适的目录和项目名,比如“E:\\Project”目录下的“DMS”项目。
(2) (2) 创建一个对话框应用程序(“Dialog Based”),单击“Next”按钮。 (3) (3) 由于在这个项目中将要使用ADO,所以在MFC AppWizard的第
二步,需要选中“Automation”选项,使应用程序能够支持自动化对象。如图1-10所示
(4) (4) 单击“Finish”按钮结束项目的创建。主对话框名为CDMSDlg。 (5) (5) 项目创建完毕后,在头文件stdafx.h中加入下面4行:
#import“c:\\programfiles\\commonfiles\\system\\ado\\msado15.dll”no_namespace(”EOF”,”adoEOF”) #include”icrsint.h”
inline void TESTHR(HRESULT x){if FAILED(x)_com_issue_error(x);}; #define DATEFMT Cstring(“’%s”’)
5、操作日志模块的设计
(1)写日志模块
图1-10 使应用程序支持自动化 先定义一个名为ClogMngr的类 //LogMngr.h
//定义一个Log管理器 class CLogMngr {
public: CLogMngr(); virtual ~CLogMngr(); public: bool AddLog(LPCSTR op); void Setup(_ConnectionPtr cnnt, CString& user) { m_DBCnt = cnnt; m_user = user; } protected: _ConnectionPtr m_DBCnt; CString m_user; };
下面是ClogMngr::AddLog内部实现详细过程。 //LogMngr.cpp
//向数据库中添加Log记录的代码。 bool CLogMngr::AddLog(LPCSTR op) { CTime tm = CTime::GetCurrentTime(); CString sql_;
sql_.Format(\"INSERT INTO HOWDO VALUES('%s','%s','%d-%d-%d %d:%d:%d')\ m_user, op, tm.GetYear(), tm.GetMonth(), tm.GetDay(), tm.GetHour(), tm.GetMinute(), tm.GetSecond()); _bstr_t sql = sql_; try { m_DBCnt->Execute(sql,NULL,adCmdText); } catch(_com_error& e) {
CString Error = e.ErrorMessage(); AfxMessageBox(e.ErrorMessage()); return false;
} return true; }
(2)读日志模块
(do_user,do_what,do_date)
图1-11 查看日志窗口
初始化界面代码如下:
BOOL CDlgViewLog::OnInitDialog() { CDialog::OnInitDialog(); m_list.InsertColumn(0,\"操作员\"); m_list.InsertColumn(1,\"操作日期\"); m_list.InsertColumn(2,\"操作内容\"); RECT rect; m_list.GetWindowRect(&rect); int wid = rect.right - rect.left; m_list.SetColumnWidth(0,wid/3); m_list.SetColumnWidth(1,wid/3); m_list.SetColumnWidth(2,wid/3); m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);
RefreshData(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
void CDlgViewLog::RefreshData() { m_list.DeleteAllItems(); m_list.SetRedraw(FALSE); _bstr_t strSQL(\"SELECT * FROM HOWDO\"); _RecordsetPtr MySet; int i = 0; try { MySet.CreateInstance(__uuidof(Recordset)); MySet = m_DBCnt->Execute(strSQL,NULL,adCmdText); _variant_t Holder; while(!MySet->adoEOF) { Holder = MySet->GetCollect(\"do_user\"); if(Holder.vt!=VT_NULL) m_list.InsertItem(i, (char*)(_bstr_t)Holder); Holder = MySet->GetCollect(\"do_date\"); if (Holder.vt!=VT_NULL) m_list.SetItemText(i, 1, (char*)(_bstr_t)Holder); Holder = MySet->GetCollect(\"do_what\"); if(Holder.vt!=VT_NULL) m_list.SetItemText(i, 2, (char*)(_bstr_t)Holder); MySet->MoveNext(); } MySet->Close(); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); m_list.SetRedraw(TRUE); return;
} m_list.SetRedraw(TRUE); }
void CDlgViewLog::OnClickListVllog(NMHDR* pNMHDR, LRESULT* pResult) { int i = m_list.GetSelectionMark(); m_opr = m_list.GetItemText(i,0); m_date = m_list.GetItemText(i,1); m_op = m_list.GetItemText(i,2); UpdateData(FALSE); *pResult = 0; }
//DlgViewLog.cpp
//删除所有日志记录的函数。
void CDlgViewLog::OnBtnVlrmall() { _bstr_t strSQL(\"TRUNCATE TABLE HOWDO\"); try { m_DBCnt->Execute(strSQL,NULL,adCmdText);
} catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); EndDialog(0);
} RefreshData(); }
6、登录窗口的设计和程序初始化
在CDMSDlg::OnInitDialog()中加入这样一段代码: //DMSDlg.cpp //弹出登录界面 CDlgLogIn dlg; do { if (!dlg.DoModal()) EndDialog(0); } while (dlg.m_UsrName.GetLength()==0);
它的目的是弹出图1-12所示的登录对话框,并从中获得一个有效的用户名。
图1-12 登录界面
得到有效用户名后,程序用如下代码: // DMSDlg.cpp
//建立数据库连接,初始化成员变量 //登录数据库,若失败,则关闭程序。 { m_DBCnt.CreateInstance(__uuidof(Connection)); CString sql_; sql_.Format(\"DSN=DMS;UID=%s;PWD=%s\ _bstr_t sql=sql_;//建立连接 m_DBCnt->Open(sql,\"\初始化日志管理器 m_logMngr.Setup(m_DBCnt,dlg.m_UsrName);//记录此次登录 m_logMngr.AddLog(\"登录数据库\"); } catch(_com_error& e) { AfxMessageBox(e.ErrorMessage()); this->EndDialog(0); }
在程序结束时关闭数据库连接。 // DMSDlg.cpp //关闭数据库连接
void CDMSDlg::OnDestroy()
{ }
CDialog::OnDestroy();
m_DBCnt->Close();
7、主对话框界面的设计
登录完成后,显示出主对话框。它的界面设计如图1-13所示,单击某个按钮就能弹出某个功能的界面。
图1-13 主对话框界面
以其中“设备代码”按钮为例,说明它的事件处理函数。代码如下: // DMSDlg.cpp
//显示设备代码管理界面
void CDMSDlg::OnBtnDevcode() { CDlgDevcode dlg; dlg.Setup(m_DBCnt,&m_logMngr); this->ShowWindow(SW_HIDE); dlg.DoModal(); this->ShowWindow(SW_SHOW); }
其他按钮的事件处理函数,代码与“设备代码”按钮的事件处理函数相同。
8、设备代码管理窗口的建立
对话框类名为CdlgDevcode设计如图1-14所示
图1-14 设备代码管理窗口
//DlgDevcode.cpp
//对话框的初始化
BOOL CDlgDevcode::OnInitDialog() { CDialog::OnInitDialog();//切分列表控件 m_list.InsertColumn(0,\"设备号\"); m_list.InsertColumn(1,\"设备名\"); RECT rect; m_list.GetWindowRect(&rect); int wid = rect.right - rect.left; m_list.SetColumnWidth(0,wid/2); m_list.SetColumnWidth(1,wid/2); m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);//读取已有数据 RefreshData(); return TRUE; }
// DlgDevcode.cpp //消息映射部分
BEGIN_MESSAGE_MAP(CDlgDevcode, CDialog) //{{AFX_MSG_MAP(CDlgDevcode) ON_NOTIFY(NM_CLICK, IDC_LIST_DEVCODE, OnClickListDevcode) //}}AFX_MSG_MAP END_MESSAGE_MAP() //事件处理部分
void CDlgDevcode::OnClickListDevcode(NMHDR* pNMHDR, LRESULT* pResult) { int i = m_list.GetSelectionMark(); m_code = m_list.GetItemText(i,0); m_name = m_list.GetItemText(i,1); UpdateData(FALSE); *pResult = 0; }
其余程序的清单如下:
// DlgDevcode.cpp : implementation file
//
#include \"stdafx.h\" #include \"DMS.h\"
#include \"DlgDevcode.h\"
#ifdef _DEBUG
#define new DEBUG_NEW #undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
//////////////////////////////////////////////////////////////////////////// // CDlgDevcode dialog
CDlgDevcode::CDlgDevcode(CWnd* pParent /*=NULL*/) : CDialog(CDlgDevcode::IDD, pParent) { //{{AFX_DATA_INIT(CDlgDevcode) m_code = _T(\"\"); m_name = _T(\"\"); //}}AFX_DATA_INIT m_DBCnt = NULL; m_log = NULL; }
void CDlgDevcode::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDlgDevcode) DDX_Control(pDX, IDC_LIST_DEVCODE, m_list); DDX_Text(pDX, IDC_EDIT_DCCODE, m_code); DDX_Text(pDX, IDC_EDIT_DCNAME, m_name); //}}AFX_DATA_MAP }
BEGIN_MESSAGE_MAP(CDlgDevcode, CDialog) //{{AFX_MSG_MAP(CDlgDevcode) ON_NOTIFY(NM_CLICK, IDC_LIST_DEVCODE, OnClickListDevcode) ON_BN_CLICKED(IDC_BTN_DCADD, OnBtnDcadd) ON_BN_CLICKED(IDC_BTN_DCDEL, OnBtnDcdel) ON_BN_CLICKED(IDC_BTN_DCUPD, OnBtnDcupd) //}}AFX_MSG_MAP END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////////// // CDlgDevcode message handlers //负责读取已有数据的函数
void CDlgDevcode::RefreshData() { m_list.DeleteAllItems(); m_list.SetRedraw(FALSE); _bstr_t strSQL(\"SELECT * FROM DEVICE_CODE\"); _RecordsetPtr MySet; int i = 0; try
{ MySet.CreateInstance(__uuidof(Recordset)); //执行SOL语句读取记录 MySet = m_DBCnt->Execute(strSQL,NULL,adCmdText); _variant_t Holder; while(!MySet->adoEOF) { //取出code字段的数据 Holder = MySet->GetCollect(\"code\"); if(Holder.vt!=VT_NULL) m_list.InsertItem(i, (char*)(_bstr_t)Holder); //取出name字段的数据 Holder = MySet->GetCollect(\"name\"); if(Holder.vt!=VT_NULL) m_list.SetItemText(i, 1, (char*)(_bstr_t)Holder); MySet->MoveNext(); } } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); m_list.SetRedraw(TRUE); return;
} m_list.SetRedraw(TRUE); }
//负责添加记录的函数
void CDlgDevcode::OnBtnDcadd() { UpdateData(); CString sql_; sql_.Format(\"INSERT INTO DEVICE_CODE (code,name) VALUES('%s','%s')\ _bstr_t sql = sql_; try { m_DBCnt->Execute(sql,NULL,adCmdText); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); return; } m_log->AddLog(\"添加设备记录。\"); RefreshData(); }
//负责删除记录的函数
void CDlgDevcode::OnBtnDcdel() { UpdateData(); CString sql_; sql_.Format(\"DELETE FROM DEVICE_CODE WHERE CODE='%s'\ _bstr_t sql = sql_; try { m_DBCnt->Execute(sql,NULL,adCmdText); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage());
return;
} m_log->AddLog(\"删除设备记录。\"); RefreshData(); }
//负责更新数据的函数
void CDlgDevcode::OnBtnDcupd() { UpdateData(); CString sql_; sql_.Format(\"UPDATE DEVICE_CODE SET NAME='%s' WHERE CODE='%s'\ _bstr_t sql = sql_; try { m_DBCnt->Execute(sql,NULL,adCmdText); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); return;
} m_log->AddLog(\"更新设备记录。\"); RefreshData(); }
9、库存信息管理窗口的创建
用户可以在此新增、修改、删除某种设备的记录。单击主对话框中的“库存信息”按钮,将出现图1-15所示的界面。新增记录时,用户在“设备号”组合框中选择一个设备号,在下面填入各种数量,之后单击“新增”按钮即可向表中增加记录。
修改记录时,用户单击列表中某一行,程序利用1、8提到的方法,在窗口下面把这一行记录的详细信息显示出来,用户即可对之修改。
“设备号”这个子窗口初始化的时候有如下代码: //DlgDev.cpp //对话框的初始化
BOOL CDlgDev::OnInitDialog() { CDialog::OnInitDialog(); //切分列表控件 m_list.InsertColumn(0,\"设备号\"); m_list.InsertColumn(1,\"现存数量\"); m_list.InsertColumn(2,\"最大数量\"); m_list.InsertColumn(3,\"最小数量\"); m_list.InsertColumn(4,\"总数\"); RECT rect; m_list.GetWindowRect(&rect); int wid = rect.right - rect.left; m_list.SetColumnWidth(0,wid/5); m_list.SetColumnWidth(1,wid/5); m_list.SetColumnWidth(2,wid/5); m_list.SetColumnWidth(3,wid/5); m_list.SetColumnWidth(4,wid/5); m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT); _RecordsetPtr pRst = NULL;
IADORecordBinding *picRs = NULL; //Interface Pointer declared.(VC++ Extensions)
CDevCodeRs rs; try { _bstr_t strSQL(\"SELECT * FROM DEVICE_CODE\"); TESTHR(pRst.CreateInstance(__uuidof(Recordset))); //读取所有的设备编号 pRst = m_DBCnt->Execute(strSQL, NULL, adCmdText); //数据绑定 TESTHR(pRst->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRs));
TESTHR(picRs->BindToRecordset(&rs)); int i = 0; while (!pRst->adoEOF) { //向组合框控件中添加所有的设备编号 m_devs.AddString(rs.m_sz_code); pRst->MoveNext(); } picRs->Release(); pRst->Close(); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); EndDialog(0); return TRUE; } RefreshData(); return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE }
图1-15 库存信息管理 10、设备入库信息管理
在主对话框中单击“入库信息”按钮就进入如图1-16所示的界面。
图1-16 设备入库信息管理界面 下面是修改和删除记录的代码:
void CDlgViewDevIn::OnBtnViupdate() { if (!UpdateData()) return; CString sql_; sql_.Format(CString(\"SELECT * FROM DEVICE_IN WHERE in_date=\")+DATEFMT, m_date); _bstr_t sql = sql_; _RecordsetPtr pRst = NULL; IADORecordBinding *picRs = NULL; //Interface Pointer declared.(VC++ Extensions) CDevInRs rs; try { TESTHR(pRst.CreateInstance(__uuidof(Recordset))); pRst->Open(sql,_variant_t((IDispatch *) m_DBCnt, true),adOpenKeyset,adLockOptimistic,adCmdText); //数据绑定 TESTHR(pRst->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRs));
TESTHR(picRs->BindToRecordset(&rs)); //填写需要修改的数据 strcpy(rs.m_sz_code,m_code); strcpy(rs.m_sz_date,m_date); strcpy(rs.m_sz_provider, m_provider); strcpy(rs.m_sz_tel, m_tel); rs.m_f_number = m_number; rs.m_f_price = m_price; strcpy(rs.m_sz_buyer, m_buyer); //开始更新数据 TESTHR(picRs->Update(&rs)); //释放ADO对象 picRs->Release(); pRst->Close(); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); return; } MessageBox(\"完成操作!\"); m_log->AddLog(\"修改入库信息\"); RefreshData(); }
void CDlgViewDevIn::OnBtnVidel() { if (!UpdateData()) return; CString sql_; sql_.Format(CString(\"DELETE FROM DEVICE_IN WHERE in_date=\")+DATEFMT, m_date); _bstr_t sql = sql_; try { //执行删除数据的SOL语句 m_DBCnt->Execute(sql, NULL, adCmdText); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); return; } MessageBox(\"完成操作!\"); m_log->AddLog(\"删除入库信息\"); RefreshData(); }
11、设备入库窗口
在主对话框中单击“设备入库”按钮就进入如图1-17所示的界面。
图1-17 设备入库登记界面
下面就是单击“确定”按钮之后,更新数据库操作的代码: //DlgDevIn.cpp //添加入库记录
void CDlgDevIn::OnBtnDiadd() { if (m_devs.GetCurSel()==CB_ERR) { MessageBox(\"请选择一个设备\"); return; } if (!UpdateData()) return; _RecordsetPtr pRst = NULL; CDevInRs rs; try { TESTHR(pRst.CreateInstance(__uuidof(Recordset))); //打开数据库表格到Recordest对象 pRst->Open(\"device_in\*) true),adOpenKeyset,adLockOptimistic,adCmdTable); //填写新数据 m_devs.GetWindowText(rs.m_sz_code,11); sprintf(rs.m_sz_date,\"%d-%d-%d %d:%d:%d\ m_date.GetYear(), m_date.GetMonth(), m_date.GetDay(), m_time.GetHour(), m_time.GetMinute(), m_time.GetSecond()); strcpy(rs.m_sz_provider, m_provider); strcpy(rs.m_sz_tel, m_tel); rs.m_f_number = m_number; rs.m_f_price = m_price; strcpy(rs.m_sz_buyer, m_buyer);
m_DBCnt,
COleSafeArray vaFieldlist, vaValuelist; rs.FillFieldsArray(vaFieldlist,vaValuelist); //开始一个事务 m_DBCnt->BeginTrans(); //添加新数据到device_in表 TESTHR(pRst->AddNew(vaFieldlist, vaValuelist)); pRst->Close(); //打开device表 CString sql_; sql_.Format(\"SELECT * FROM device WHERE code='%s'\ _bstr_t sql = sql_; pRst->Open(sql, _variant_t((IDispatch *) m_DBCnt, true),adOpenKeyset,adLockOptimistic,adCmdText); //若没有此设备的库存记录 if (pRst->GetRecordCount()==0) { CDevRs rsDev; strcpy(rsDev.m_sz_code, rs.m_sz_code); rsDev.m_f_cur = rs.m_f_number; rsDev.m_f_total = rs.m_f_number; rsDev.m_f_max = 1; rsDev.m_f_min = 1;
//创建一个设备库存记录 COleSafeArray vaFields, vaValues; rsDev.FillFieldsArray(vaFields,vaValues); TESTHR(pRst->AddNew(vaFields, vaValues)); } else//若有此设备的库存记录 { CDevRs rsDev; IADORecordBinding *picRs = NULL; //Interface Pointer declared.(VC++ Extensions) TESTHR(pRst->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRs)); TESTHR(picRs->BindToRecordset(&rsDev)); strcpy(rsDev.m_sz_code, rs.m_sz_code); rsDev.m_f_cur = rs.m_f_number + rsDev.m_f_cur; rsDev.m_f_total = rs.m_f_number + rsDev.m_f_total; //修改原有的设备库存记录 TESTHR(picRs->Update(&rsDev)); picRs->Release(); } pRst->Close(); //提交事务 m_DBCnt->CommitTrans(); } catch(_com_error& e) { AfxMessageBox(e.ErrorMessage()); m_DBCnt->RollbackTrans(); return; } MessageBox(\"完成操作!\");
}
m_log->AddLog(\"添加入库信息\"); EndDialog(0);
12、设备采购报表的管理
在主对话框中单击“生成设备采购计划报表”按钮就进入如图1-18所示的界面。 此时程序自动显示设备的名称、总库存、最大库存、现有库存等信息,待用户输入完其他数据之后,将生成一个设备采购计划报表,存入数据库中。
图1-18 设备采购计划报表界面 //DlgReport.cpp
//显示所选中设备的信息
void CDlgReport::OnCloseupComboRpdevs() { char buf[];
//读取用户所选的编号 m_devs.GetWindowText(buf,); if (strlen(buf)<=0) return; _RecordsetPtr pRst = NULL; IADORecordBinding *picRs = NULL; //Interface Pointer declared.(VC++ Extensions) CDevCodeRs rs1;
CDevRs rs2; _bstr_t strSQL; try { 生成所需的SQL语句 CString sql; sql.Format(\"SELECT * FROM DEVICE_CODE WHERE code='%s'\ strSQL = sql; TESTHR(pRst.CreateInstance(__uuidof(Recordset))); pRst = m_DBCnt->Execute(strSQL, NULL, adCmdText); //读取编号对应的设备名称 TESTHR(pRst->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRs)); TESTHR(picRs->BindToRecordset(&rs1)); m_name.Format(\"%s\ 结束操作 picRs->Release(); pRst->Close(); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); } try { CString sql; sql.Format(\"SELECT * FROM DEVICE WHERE code='%s'\ strSQL = sql; TESTHR(pRst.CreateInstance(__uuidof(Recordset))); pRst->Open(strSQL, _variant_t((IDispatch *) m_DBCnt, true), adOpenKeyset, adLockOptimistic, adCmdText); if (pRst->GetRecordCount()!=1) { m_max = 0; m_cur = 0; m_total = 0; } else {
TESTHR(pRst->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&pic
Rs)); TESTHR(picRs->BindToRecordset(&rs2)); //读取编号对应的库存情况 m_max = rs2.m_f_max; m_cur = rs2.m_f_cur; m_total = rs2.m_f_total; picRs->Release(); } pRst->Close(); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); }
}
UpdateData(FALSE);
13、库存报警窗口
在主对话框中单击“库存报警”按钮就进入如图1-19所示的界面。
图1-19 库存报警界面
检索记录的代码如下: //DlgDevAlert.cpp
//检索过多、过少库存
void CDlgDevAlert::SearchOver() { _RecordsetPtr pRst = NULL; IADORecordBinding *picRs = NULL; //Interface Pointer declared.(VC++ Extensions) CDevRs rs; try { _bstr_t strSQL(\"SELECT * FROM DEVICE WHERE now_number>high_number\"); TESTHR(pRst.CreateInstance(__uuidof(Recordset))); pRst = m_DBCnt->Execute(strSQL, NULL, adCmdText); TESTHR(pRst->QueryInterface(__uuidof(IADORecordBinding),(LPVOID*)&picRs)); TESTHR(picRs->BindToRecordset(&rs)); int i = 0; char buf[]; while (!pRst->adoEOF) { m_list.InsertItem(0, rs.m_sz_code); sprintf(buf,\"%f\ m_list.SetItemText(i, 1, buf); sprintf(buf,\"%f\m_list.SetItemText(i, 2, buf); sprintf(buf,\"%f\m_list.SetItemText(i, 3, buf); sprintf(buf,\"%f\m_list.SetItemText(i, 4, buf); pRst->MoveNext();
} picRs->Release(); pRst->Close(); } catch(_com_error& e) {
AfxMessageBox(e.ErrorMessage()); return; } }
void CDlgDevAlert::SearchBelow() { _RecordsetPtr pRst = NULL; IADORecordBinding *picRs = NULL; //Interface Pointer declared.(VC++ Extensions) CDevRs rs; try { _bstr_t strSQL(\"SELECT * FROM DEVICE WHERE now_number AfxMessageBox(e.ErrorMessage()); return; } } 14、帮助模块设计 本系统的帮助模块由两部分组成,一部分是本程序的About窗口,另一个是在外部编译好的chm格式的帮助文件。单击主对话框中的相应按钮可以分别激活这两部分功能。 下面是“帮助”和“关于”两个按钮的消息处理函数: //DMSDlg.cpp //激活“帮助”和“关于” void CDMSDlg::OnBtnAbout() { CAboutDlg dlg; dlg.DoModal(); } void CDMSDlg::OnBtnHelp() { WinExec(\"hh.exe dms.chm\} 第二个函数调用WinExec这个Win 32API激活了外部的chm帮助文件 图1-20是“关于”窗口的界面 图1-20 “关于”窗口的界面 15、小结 在运行程序之前,请将所附的数据库文件dms.mdb添加为数据源,并命名为DMS。密码为:111 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- pqdy.cn 版权所有 赣ICP备2024042791号-6
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务