物流单据管理系统.docx
《物流单据管理系统.docx》由会员分享,可在线阅读,更多相关《物流单据管理系统.docx(42页珍藏版)》请在冰点文库上搜索。
物流单据管理系统
物流单据管理系统
1、案例预览
运行该系统,主界面如图一所示,有“开销售单”、“开进货单”、“查看单据”等业务,下面按业务依次说明最后实现的程序界面和操作方法。
图一
(1)开销售单。
单击程序主界面的【开销售单】按钮,弹出“销售单据”对话框,如图二所示。
填完单据的各项内容后,单击【保持】按钮。
如果程序提示保存成功,会返回主界面,单据列表中又增加了一张销售单据。
图二
(2)开进货单。
单击程序主界面的【开进货单】按钮,弹出“进货单据”对话框,如图三所示。
开单操作和销售单类似。
图三
(3)查看单据。
在主界面中,选择要查看的单据,然后单击【查看单据】按钮,弹出对应的单据,如图四所示。
此时单据不能被编辑,查看完后单击【关闭】按钮退出查看操作。
图四
二分析与创建数据库
本例采用Access2002作为数据库,使用ADO方式访问数据库。
首先创建一个数据库,命名为“bills.mdb”,并且将该数据库文件放在本实例应用程序的根目录中,便于访问。
从前面的分析知道。
本例需要两个数据表bill和goods。
表bill用来保持单据,包括进货单据和销售单据,单据类型用一个数字类型的字段type来区分,0表示进货单,1表示销售单。
表goods用来保持单据中填写的流通商品,通过字段billid来对应某张单据,字段index表示在该单据中的表格位置。
表结构如图五和图六所示。
id文本单据编号
type数字单据类型(0=进货单,1=销售单)
time日期/时间制单日期
storage文本交易时使用的仓库
client文本交易的客户名称
operator文本经手人
account文本交易时使用的银行帐户
comment文本单据的附加说明
字段名称数据类型说明
图五(bill表)
图六(goods表)
字段名称数据类型说明
name文本商品名称
unit文本商品的度量单位
account数字商品数量
price数字商品单价
comment文本商品说明
billid文本所在单据的编号
index数字所处单据表格的位置索引
三创建VC工程
创建给予对话框的应用程序,从第二步到第六步全部采用默认方式。
四引入控件
1、表格(Grid)控件
在用VC开发关于数据库的项目时,通常使用DataGrid作为数据库表格控件。
本例中介绍另外一个共享表格控件CGridCtrl,非常好用,也很美观,进货单据和销售单据显示商品时使用的就是CGridCtrl控件。
CGridCtrl和一般的GRID的不同之处在于,一般的GRID并不适合显示大的数据量,如果一个查询结果有上万条记录的话,如果都要插入到GRID中,这将是个很慢的过程,并且在GRID中移动滚动条的话,它的记录的滚动也是很慢的。
而CGridCtrl并不会真正把这些记录的数据全部插入到控件中,当CGridCtrl的滚动条滚动时,它会根据CGridCtrl的显示面积的大小和查询得到的总的记录数计算当前应该显示哪些行,然后会把那几行的记录数据插入到表格中,这样速度当然是很快的,而且没有数据量多少的限制。
将表格控件CGridCtrl引入本例工程中需要如下步骤。
(1)将光盘中的相关文件拷贝到创建的工程目录下,它们位于本例工程的gridctrl_src目录中。
(2)选择菜单【Project】->【AddToProject】->【Files】,打开“InsertFilesintoProject”对话框。
选中gridctrl_src目录下的所有文件,单击【OK】按钮,将表格控件CGridCtrlDE所有相关文件都加入到工程中。
引入表格控件完成后,可以看到新增了数个与该控件相关的类。
为了使工作区整洁,增加一个文件夹“grid”,将这些新增的文件拖入其中。
如下图所示:
2、位图按钮
VC提供的默认按钮形态比较单调,这里介绍一个共享按钮控件CTrackLookButton。
该按钮将图标和文字一起显示,并且呈flat形式。
将控件CTrackLookButton引入本例工程中需要如下步骤。
(1)将光盘中的文件TrackLookButton.h和TrackLookButton.cpp拷贝到创建的工程目录中。
(2)选择菜单【Project】->【AddToProject】->【Files】,打开“InsertFilesintoProject”对话框,将文件TrackLookButton.h和TrackLookButton.cpp加入工程中。
五使用ADO连接数据库
(1)VC中通过在程序中使用预编译指令#import来告诉编译器将此指令中指定的动态链接库引入工程中。
在应用程序的文件stdafx.h中加入如下语句:
#import"c:
\programfiles\commonfiles\system\ado\msado15.dll"no_namespacerename("EOF","adoEOF")
(2)在应用程序类CBillsManagerAPP的头文件中分别声明一个_ConnectionPtr和_RecordsetPtr类型的指针,访问类型为public。
其代码如下:
public:
_ConnectionPtrm_pConnection;
_RecordsetPtrm_pRecordset;
(3)在CBillsManagerApp:
:
InitInstance()成员函数里,初始化OLE/COM库环境,创建连接对象,打开与数据源的连接,以及创建记录集对象。
其代码如下:
BOOLCBillsManagerApp:
:
InitInstance()
{
AfxEnableControlContainer();
//Standardinitialization
//Ifyouarenotusingthesefeaturesandwishtoreducethesize
//ofyourfinalexecutable,youshouldremovefromthefollowing
//thespecificinitializationroutinesyoudonotneed.
#ifdef_AFXDLL
Enable3dControls();//CallthiswhenusingMFCinasharedDLL
#else
Enable3dControlsStatic();//CallthiswhenlinkingtoMFCstatically
#endif
//初始化com环境
:
:
CoInitialize(NULL);
//创建连接对象和记录集对象
HRESULThr;
try
{
hr=m_pConnection.CreateInstance("ADODB.Connection");//创建Connection对象
if(SUCCEEDED(hr))
{
hr=m_pConnection->Open(
"Provider=Microsoft.Jet.OLEDB.4.0;DataSource=bills.mdb",
"","",adModeUnknown);///连接数据库
///上面一句中连接字串中的Provider是针对ACCESS2000环境的,
//对于ACCESS97,需要改为:
Provider=Microsoft.Jet.OLEDB.3.51
}
}
catch(_com_errore)///捕捉异常
{
CStringerrormessage;
errormessage.Format("连接数据库失败!
\r\n错误信息:
%s",e.ErrorMessage());
AfxMessageBox(errormessage);///显示错误信息
}
m_pRecordset.CreateInstance(__uuidof(Recordset));
CBillsManagerDlgdlg;
m_pMainWnd=&dlg;
intnResponse=dlg.DoModal();
if(nResponse==IDOK)
{
//TODO:
Placecodeheretohandlewhenthedialogis
//dismissedwithOK
}
elseif(nResponse==IDCANCEL)
{
//TODO:
Placecodeheretohandlewhenthedialogis
//dismissedwithCancel
}
//Sincethedialoghasbeenclosed,returnFALSEsothatweexitthe
//application,ratherthanstarttheapplication'smessagepump.
returnFALSE;
}
(4)通过ClassWizard为类CBillsManagerApp增加ExitInstance()成员函数,该函数在退出系统时被调用。
在其中关闭数据库连接,并且还原OLE/COM库环境。
其代码如下:
intCBillsManagerApp:
:
ExitInstance()
{
m_pConnection->Close();
//还原com环境
:
:
CoUninitialize();
returnCWinApp:
:
ExitInstance();
}
六实现单据对话框功能
该对话框用来开销售单、开进货单、查看单据。
(1)制作对话框
(1)为对话框添加控件,最后效果如下:
其中2个按钮都还只是普通按钮,但我们要重画它们,所以设置它们的“Ownerdraw”属性。
灰色部分是CustomControl控件。
就是控件工具栏中的人头控件
。
其具体设置如下所示:
这里MFCGridCtrl是前面加入工程的表格控件CGridCtrl的窗口类,在GridCtrl.h中有定义。
(2)为单据对话框新建一个对话框类,命名为CBillDlg。
(3)为CBillDlg类作变量关联。
相关的变量设置如下:
上面的有些错误,其中保存和退出按钮的关联变量m_btSave和m_btExit都是CButton型的,而不是CTrackLookButton型。
(2)定义成员变量
(1)为了使用前面引入的图标按钮CTrackLookButton和表格控件CGridCtrl,在BillDlg.h中的类CBillDlg定义前加入如下头文件,代码如下:
#include"GridCtrl_src/GridCtrl.h"
#include"TrackLookButton.h"
(2)在BillDlg.h中更改已经定义的变量m_btSave和m_btExit的类型,由原来的CButton型变为CTrackLookButton型:
CTrackLookButtonm_btExit;
CTrackLookButtonm_btSave;
(3)在BillDlg.h中定义CGridCtrl类型的变量m_Grid,然后在voidCBillDlg:
:
DoDataExchange(CDataExchange*pDX)中使其与对话框资源中的ID为IDC_GRID的CustomControl控件关联,代码分别如下:
voidCBillDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBillDlg)
//}}AFX_DATA_MAP
DDX_GridControl(pDX,IDC_GRID,m_Grid);
}
(4)在BillDlg.h中定义表示表格控件m_Grid的行数、列数、固定行数和固定列数,便用在程序中用代码灵活控制这些参数,定义如下:
protected:
intm_nRows,m_nCols,m_nFixRows,m_nFixCols;
(5)在BillDlg.h中定义表格控件中商品名称、计量单位、数量、单价、金额和备注等所处的列,基数为0:
//定义商品信息处于grid中的位置
intm_nNameCol,m_nUnitCol,m_nAmountCol,m_nPriceCol,m_nMoneyCol,m_nCommentCol;
(6)由于对话框CBillDlg既用来开销售单,又用来开进货单,因此为了区分开它们,在BillDlg.h中定义表示单据类型的变量m_nBillType,并且是public类型的:
intm_nBillType;//0表示进货单,1表示销售单
(7)由于对话框类CBillDlg既用来开单据,又用来查看单据,而且查看单据时编辑框和网格控件都是不能操作的。
为了区分开来,在BillDlg.h中定义表示状态的变量m_bShowBill,并且是public类型的:
BOOLm_bShowBill;//TRUE表示查看单据,FALSE表示是开进货单或者销售单
(8)在构造函数CBillDlg(CWnd*pParent)中初始化前面定义的所有变量,其代码如下:
CBillDlg:
:
CBillDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CBillDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CBillDlg)
m_strAccount=_T("");
m_strBillID=_T("");
m_strClient=_T("");
m_strComment=_T("");
m_strStorage=_T("");
m_tTime=CTime:
:
GetCurrentTime();;
m_strOperator=_T("");
//}}AFX_DATA_INIT
m_nRows=16;
m_nCols=6;
m_nFixRows=1;
m_nFixCols=0;
m_nNameCol=0;
m_nUnitCol=1;
m_nAmountCol=2;
m_nPriceCol=3;
m_nMoneyCol=4;
m_nCommentCol=5;
m_nBillType=1;//销售单
m_bShowBill=FALSE;
}
(3)在BOOLCBillDlg:
:
OnInitDialog()函数中初始化对话框
通过ClassWizard引入对话框的OnInitDialog()函数,在该函数中加入一些初始化的代码,包括:
根据单据类型设置窗口标题,设置图标按钮的风格,初始化表格控件的风格,设置表格控件的行数、列数、固定行数、固定列数等参数,设置列表控件的表头和列宽,如果是查看单据的话还显示要查看的单据。
其完整的代码如下:
BOOLCBillDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//根据单据类型,设置对话框的标题
if(m_nBillType==0)
SetWindowText("进货单据");
else
SetWindowText("销售单据");
//设置按钮风格
m_btSave.LoadBitmaps(IDB_SAVE,IDB_SAVE,IDB_SAVE);
m_btSave.SetTextAlignment(CTrackLookButton:
:
AlignRight);
m_btExit.LoadBitmaps(IDB_EXIT,IDB_EXIT,IDB_EXIT);
m_btExit.SetTextAlignment(CTrackLookButton:
:
AlignRight);
//初始化grid并设置其风格
m_Grid.EnableDragAndDrop(TRUE);
m_Grid.SetTextBkColor(RGB(0xFF,0xFF,0xE0));
//设置grid的行数、列数、固定行数、固定列数
m_Grid.SetRowCount(m_nRows);
m_Grid.SetColumnCount(m_nCols);
m_Grid.SetFixedRowCount(m_nFixRows);
m_Grid.SetFixedColumnCount(m_nFixCols);
chargridHeader[6][10]={"商品名称","单位","数量","单价","金额","备注"};
//填充表格的表头,并且设置列宽
for(intcol=0;col{
GV_ITEMItem;
Item.mask=GVIF_TEXT|GVIF_FORMAT;
Item.row=0;
Item.col=col;
Item.nFormat=DT_LEFT|DT_WORDBREAK|DT_NOPREFIX;
Item.strText=gridHeader[col];
m_Grid.SetItem(&Item);
m_Grid.SetColumnWidth(col,78);
}
//如果是查看单据,则显示该单据
if(m_bShowBill)
ShowBill();
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
//EXCEPTION:
OCXPropertyPagesshouldreturnFALSE
}
上面的代码中调用了函数ShowBill()来显示要查看的单据,于是需要给类CBillDlg增加该成员函数,在BillDlg.h中声明为Protected类型,在BillDlg.cpp中实现。
由于是在查看单据时调用该函数,需要实现的功能包括:
使编辑框等都无效:
在【保存】按钮隐藏,并且将【退出】按钮的Caption变为“关闭”;让表格中的商品名称、编号等列不能编辑;根据单据编号查询数据表bill,返回一条记录,填充表格外的记录(录单日期、客户、银行帐户、仓库、附加说明、经手人等);根据单据编号查询数据表goods,返回多条对应的记录,填充表格内的数据;调用函数UpdateData(FALSE)更新单据的显示。
其完整代码如下:
voidCBillDlg:
:
ShowBill()
{
//使编辑框都无效
CWnd*pWnd=GetDlgItem(IDC_TIME);
pWnd->EnableWindow(FALSE);
pWnd=GetDlgItem(IDC_BILL_ID);
pWnd->EnableWindow(FALSE);
pWnd=GetDlgItem(IDC_COMMENT);
pWnd->EnableWindow(FALSE);
pWnd=GetDlgItem(IDC_CLIENT);
pWnd->EnableWindow(FALSE);
pWnd=GetDlgItem(IDC_ACCOUNT);
pWnd->EnableWindow(FALSE);
pWnd=GetDlgItem(IDC_STORAGE);
pWnd->EnableWindow(FALSE);
pWnd=GetDlgItem(IDC_OPERATOR);
pWnd->EnableWindow(FALSE);
//将“Save”按钮隐藏,并且将“退出”按钮的Caption变为“关闭”
pWnd=GetDlgItem(IDC_SAVE);
pWnd->ShowWindow(FALSE);
pWnd=GetDlgItem(IDC_EXIT);
pWnd->SetWindowText("关闭");
//让商品名称,编号等列不能编辑
for(introw=m_Grid.GetFixedRowCount();row{
for(intcol=m_Grid.GetFixedColumnCount();col{
m_Grid.SetItemState(row,col,m_Grid.GetItemState(row,col)|GVIS_READONLY);
}
}
CStringstrSql,str;
CBillsManagerApp*pApp=(CBillsManagerApp*)AfxGetApp();
//填充表格外的数据
strSql.Format("SELECT*FROMbillwhereid='%s'",m_strBillID);
HRESULThr=pApp->m_pRecordset->Open(strSql.AllocSysString(),
pApp->m_pConnection.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
if(!
SUCCEEDED(hr))
{
AfxMessageBox("打开bill表出错");
return;
}
if(pApp->m_pRecordset->adoEOF)
{
AfxMessageBox("错误的单据编号");
pApp->m_pRecordset->Close();
return;
}
m_strBillID=(char*)(_bstr_t)pApp->m_pRecordset->GetCollect(_variant_t("id"));
str=(char*)(_bstr_t)pApp->m_pRecordset->GetCollect(_variant_t("time"));
GetTimeFromStr(str,m_tTime);
m_strClient=(char*)(_bstr_t)pApp->m_pRecordset->GetCollect(_variant_t("client"));
m_strAccount=(char*)(_bstr_t)pApp->m_pRecordset->GetCollect(_variant_t("account"));
m_strStorage=