进销存管理系统的设计与实现龙大源

企业经营如逆水行舟不进则退。每一个努力发展的企业都明白,先进管理的重要作用,引进先进管理系统使企业经营变得规范、合理。进销存管理系统无论是在功能设计还是业务流程上都尽可能做到满足经营管理运作流程的需求,并且操作方便、功能强大,即使操作者对计算机知识一窍不通也能一用就会。它强化库存管理,规范业务流程,提高资金管理的透明度,加快商品资金周转,是企业经营管理中数据分析中必不可少的管理工具。

根据市场的需求,要求系统具有以下功能:

实现商品入库、入库退货操作。

实现商品销售、销售退货操作。

实现库存管理(调货、盘点)操作。

实现信息的查询、打印功能。

准确地进行账款记录、账款查询。

根据需求分析,设计系统框架。进销存管理系统由等8部分组成。设计各部分具体功能如下:

基础信息模块

基础信息模块包括药品信息、员工信息、供应商信息和客户信息4部分。

销售模块

销售模块由销售登记、销售退货、销售查询、销售退货查询4部分。

入库模块

入库模块主要由入库登记、入库退货、入库查询、入库退货查询4组成。

调货模块

调货模块包含调货登记和调货查询两部分。

库存模块

库存模块由库存盘点、库存查询、仓库管理3部分组成。

结账模块

结账模块主要包括销售结账、销售退货结账、入库结账、入库退货结账。

财务模块

财务模块由日结、月结、供应商往来账、客户往来账4部分组成。

系统管理模块

系统管理模块由修改用户密码、修改用户权限、修改用户3部分组成。

CPU:300MHz以上的处理器。

内存:128MB,推荐256MB。

硬盘:150MB以上剩余空间。

显示像素:最低800*600,最佳效果1024*768。

操作系统:Windows2000/NT/XP/CE。

数据库:SQLServer2000。

本系统采用SQLServer2000数据库,系统数据库名为ypgl,中共包含46个表,其中作为临时表的有20个,作为数据存储表的有26个。

临时表:lsdhinfo0、lsdhinfo1、lsgys0、lsgys1、lskcquery0、lskcquery1、lskh0、lskh1、lsrkquery0、lsrkquery1、lsrkthinfo0、lsrkthinfo1、lsxsquery0、lsxsquery1、lsxsthinfo0、lsxsthinfo1、lsyg0、lsyg1、lsypinfo0、lsypinfo1。

数据存储表:tabbf、tabck、tabdhdj、tabdhph、tabgys、tabjsfs、tabkc、tabkcpddj、tabkcpdph、tabkh、tabpurview、tabpurviewctrl、tabrkdj、tabrkjz、tabrkph、tabrkthdj、tabrkthjz、tabrkthph、tabxsdj、tabxsjz、tabxsph、tabxsthdj、tabxsthjz、tabxsthph、tabyginfo、tabypinfo。

图2所示的即为本系统中数据库的数据表结构图,该数据表结构图包含系统所有数据表。可以清晰地反应数据库信息。

数据库中的数据表请参见附录B。

进销存管理系统主窗口由菜单、工具栏、客户区域和状态栏四部分组成,效果如图3所示。

图3进销存管理系统主窗口

(1)在工具栏中单击按钮,或者从菜单中选择“View”/“Workspace”项,这时会弹出如图4所示的工作区窗口(Workspace窗口)。在工作区窗口中,能看到该程序所使用的资源,且每种资源都有一个资源符号,主窗体也使用了一个资源符号IDD_A1_DIALOG,这是VC缺省提供的。可以在这里添加或者删除各种资源。

图4Workspace窗口

(2)在工作区窗口(Workspace窗口)右键单击“a1resources”选项,在弹出菜单中选择“Insert...”选项,将弹出“InsertResource”对话框。在该对话框中选择“Menu”选项,然后单击“New”按钮,将生成如图5所示的菜单资源。

图5编辑菜单资源

(3)右键双击菜单资源编辑器的虚线空白框,在弹出的菜单中选择“Properties”选项,将弹出“MenuItemProperties”对话框,在“MenuItemProperties”对话框的“caption”(标题)编辑框中键入:“基础信息(&I)”(符号&可以使字母I有一个下划线,而且可以通过“Alt+I”访问该菜单项。此时关闭“MenuItemProperties”对话框,将在菜单编辑器中生成主菜单“基础信息”。双击“基础信息”菜单下的虚线空白框,在弹出的“MenuItemProperties”对话框中设计“药品信息(&M)”、“员工信息(&Y)”等菜单项。

(4)同上,可以设计其他主菜单及菜单项。最后得到如图6所示的菜单界面。

图6菜单界面

在应用程序中要经常使用工具栏,它是最常用的界面元素,对应着应用程序的最常用功能。主窗口共有9个工具栏按钮,分别是“销售登记”、“销售退货”、“销售结账”、“入库登记”、“入库退货”、“入库结账”、“调货登记”、“库存登记”、“退出”工具栏按钮。创建工具栏可使用MFC类库中的CToolBarCtrl类,该类用来生成工具条。本系统主窗体的工具栏将引用MSDN提供的类CStandardBar,该类派生自CToolBarCtrl。

操作步骤如下:

(1)从基类CToolBarCtrl中派生需要的类CstandardBar。选择“Insert”/“NewClass...”菜单项,在弹出来的“NewClass”对话框中设置“ClassType”为“MFCClass”,在“ClassInfomation”中的Name编辑框中键入“CstandardBar”,然后在“BaseClass”下拉列表框中选择“CtoolBarCtrl”,最后单击“OK”按钮。

(2)需要9个按钮,每个按钮有相应的文本和图片。所以,需要添加如图7所示的图片资源,资源长为288像素,高为32像素,资源符号为:IDR_STANDARDBAR。

(3)添加字符串资源(StringTable),如表1所示。

表1字符串资源

资源符号

字符串资源

IDSTR_XSDJ

102

销售登记

IDSTR_XSTH

103

销售退货

IDSTR_XSJZ

104

销售结账

IDSTR_RKDJ

105

入库登记

IDSTR_RKTH

106

入库退货

IDSTR_RKJZ

107

入库结账

IDSTR_DHDJ

108

调货登记

IDSTR_KCPD

109

库存盘点

IDSTR_OUT

110

退出

(4)程序中引入资源,创建工具栏按钮。

创建工具栏按钮需要重写Create函数,该函数创建工具栏的步骤如下:

SetBitmapSize(CSize(32,32));//设置单个位图的大小

VERIFY(AddBitmap(m_nButtonCount,IDR_STANDARDBAR)!=-1);//添加位图

m_nButtonCount是指按钮图片的个数,IDR_STANDARDBAR对应着相应的图片。

m_pTBButtons=newTBBUTTON[m_nButtonCount];//用来加入到工具栏里的按钮

……

m_pTBButtons[nIndex].iString=AddStrings(pString);

m_pTBButtons[nIndex].fsState=TBSTATE_ENABLED;

m_pTBButtons[nIndex].fsStyle=TBSTYLE_BUTTON;

m_pTBButtons[nIndex].dwData=0;

m_pTBButtons[nIndex].idCommand=nIndex+IDSTR_XSDJ;//用于命令消息传递

在步骤②中,要注意如下事项:

①AddStrings(pString)返回一个字符串的基于0的编号,该值用来连接字符串到按钮上,其中的字符串参数pString需要两个结束符来表示结尾,必须将字符串写成如下形式:pString="Onlyonestringtoadd\0";CString类不能提供这样的功能,因为不可能在CString中保存超过一个结束符的字符串。所以,将CString中的字符串取出,以char定义的字符串保存,再对该字符串添加一个结束符,做法如下:

CStringstring;

string.LoadString(nIndex+IDSTR_XSDJ);//装载字符串资源

//取得字符串的长度为了添加一个结束符,给长度加1

intnStringLength=string.GetLength()+1;

TCHAR*pString=string.GetBufferSetLength(nStringLength);//按增加后的长度返回字符串

pString[nStringLength]=0;

函数GetBufferSetLength的过程分配了nStringLength+1长度的内存空间,并在加上结束符'\0'之后,复制原字符串到这个新的内存空间中,同时将原字符串的结束符也复制到新的位置,于是,该函数结束后,字符串pString已经有两个结束符了,最后一个语句略显多余或不足。但为了保证该字符串确实有两个结束符,不能省略这两个结束符。

pString[nStringLength-1]=0;

②fsState确定按钮的状态,fsStyle确定按钮的风格。若给fsStyle赋值TBSTYLE_SEP,则该按钮表现为一个间隔。dwData可以是用户自定义的数据,可以将一个指针或句柄传递给它,可以在某些消息响应函数中使用。iBitmap是表示基于0的图像列表的编号。

③idCommand为与按钮连接的命令标识,当这个按钮被按下时,这个值将被放到WM_COMMAND中发送到父窗体。如果fsStyle被设置为TBSTYLE_SEP,该值必须为0。

用Create函数创建工具栏的代码如下:

BOOLCStandardBar::Create(DWORDdwStyle,constRECT&rect,CWnd*pParentWnd,UINTnID);

{

BOOLbRet=CToolBarCtrl::Create(dwStyle,rect,pParentWnd,nID);//记录基类的返回值

m_nButtonCount=IDSTR_OUT-IDSTR_XSDJ+1;

for(intnIndex=0;nIndex

//为每一个字符串再加一个'\0',用于向工具栏里加字符串

TCHAR*pString=string.GetBufferSetLength(nStringLength);

VERIFY((m_pTBButtons[nIndex].iString=AddStrings(pString))!=-1);//返回字符串的编号

string.ReleaseBuffer();

}

m_pTBButtons[m_nButtonCount-1].idCommand=IDOK;//用来响应退出消息

TBBUTTONsepButton;//用于分隔的按钮

sepButton.idCommand=0;

sepButton.fsStyle=TBSTYLE_SEP;

sepButton.fsState=TBSTATE_ENABLED;

sepButton.iString=0;

sepButton.iBitmap=0;

sepButton.dwData=0;

for(nIndex=0;nIndex

VERIFY(AddButtons(1,&m_pTBButtons[nIndex]));//循环添加按钮

if(!((nIndex+1)%3))

VERIFY(AddButtons(1,&sepButton));//每3个按钮为一组,两组间有一个分隔按钮

returnbRet;//返回CToolBarCtrl::Create的返回值

(5)调用工具栏类。先在类CA1Dlg中实例化CStandardBar的对象。

CStandardBarm_StandardBar;

#include"StandardBar.h"

(6)增加消息WM_CREATE的响应函数,为CStandardBar对象创建相应窗口。

intCA1Dlg::OnCreate(LPCREATESTRUCTlpCreateStruct)

if(CDialog::OnCreate(lpCreateStruct)==-1)

return-1;

m_StandardBar.Create(WS_BORDER|WS_VISIBLE|WS_CHILD

|TBSTYLE_WRAPABLE|CCS_TOP|CCS_ADJUSTABLE,

CRect(0,0,0,0),this,IDR_STANDARDBAR1);

m_StandardBar.AutoSize();//重新计算控件的大小

return0;

工具栏到这里就创建成功了。

在此之前,定义了菜单和工具栏界面,单击他们并没有实质的内容,现在为他们添加消息处理函数。

(1)单击菜单和工具栏按钮的两种消息都是命令消息,所以,只要让他们传递相同的消息,就能执行相同的消息处理函数。从代码中可以看到对于工具栏的按钮来说,按钮的命令消息值与字符串资源符号的值相同,而且是顺序的,而对于相应的菜单项来说,消息值是随机的顺序值。为了将两者对应起来,要修改菜单项的资源符号,将其改为相应的按钮的字符串资源符号。例如:将销售登记菜单项的资源符号改为IDSTR_XSDJ,并给它定义消息响应函数:voidCA1Dlg::OnXsdj()。这样,无论是单击“销售登记”菜单项,还是单击“销售登记”按钮都会执行这个函数。同理,完成其他的菜单项与按钮的对应。

(2)还有一个问题:别忘了,工具栏中有一个“退出”按钮。这个退出按钮与谁对应呢?当用户按下〈Enter〉键或〈Esc〉键时,对话框就会退出,这里触发的两个消息分别是IDOK和IDCANCEL。如果给“退出”按钮的命令消息值赋值为IDOK,那么单击该按钮时,对话框就会退出。代码如下:

①访问应用程序对象。

CA1App*app=(CA1App*)::AfxGetApp();

//app是应用程序对象指针,可以访问应用程序对象的成员变量,例如:

MessageBox(app->m_sUserName);

②访问资源字符串。

先在“Workspace”中的“ResourceView”选项中建立字符串资源,定义符号IDS_COMPANY,对应资源为“明日腾龙科技有限责任公司(www.mingrisoft.com)”。

在程序中使用如下代码:

CStringstr;

str.LoadString(IDS_COMPANY);

str保存相应的字符串资源。

CTimet=CTime::GetCurrentTime();

CStrings=t.Format("%H:%M:%S");

④OnTimer消息响应函数。

为实现每隔1秒刷新一次状态栏的显示内容,可以使用WM_TIMER的消息响应函数OnTimer。要创建主窗体的OnTimer函数,首先在“Workspace”工作区“ClassView”选项卡中右键单击“CA1Dlg”选项,在弹出菜单中选择“AddWindowsMessageHandle...”菜单项,将弹出“NewWindowsMessageandeventhandlesforclassCAIDlg”对话框。在该对话框中,可以选择要进行处理的消息句柄,并为其添加消息响应函数。步骤是从左边的列表框中双击

UINTSetTimer(UINTnIDEvent,UINTnElapse,void(CALLBACKEXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD));

参数说明:

nIDEvent:用来标识是哪一个Timer事件。

lpfnTimer:设置回调函数,用来响应事件的发生,相当于OnTimer函数。如果将其设为NULL,那么,WM_TIMER事件由窗口类来处理,即由OnTimer函数处理。

在本程序中,设定OnTimer函数1000毫秒响应一次。

SetTimer(12,1000,NULL);

⑤状态栏类CStatusBarCtrl的使用。

CRectrect;

this->GetClientRect(&rect);

intindicators[3];

indicators[0]=rect.Width()/2;

indicators[1]=rect.Width()*3/4;

indicators[2]=rect.Width();

m_StatusBarCtrl.SetParts(3,indicators);

以上代码用来初始化状态栏,函数SetParts用来设定该状态栏由几个面板组成,每个面板的宽度。实际上,该函数用整型数组作参数,数组元素的值代表面板的宽度。

函数SetText用来设定每个面板上显示的数据,代码如下:

lBOOLSetText(LPCTSTRlpszText,intnPane,intnType);

lpszText:是该面板的字符串。

nPane:是面板编号(基于0)。

nType:是面板风格,该参数一般为0。

(2)创建状态栏。

创建状态栏的操作步骤如下:

②在CA1Dlg的初始化函数中初始化状态栏对象,代码如下:

BOOLCA1Dlg::OnInitDialog()

CDialog::OnInitDialog();

SetIcon(m_hIcon,TRUE);//Setbigicon

SetIcon(m_hIcon,FALSE);//Setsmallicon

//为状态栏创建窗体

m_StatusBarCtrl.Create(WS_CHILD|WS_VISIBLE|CCS_BOTTOM,

rect,this,ID_STATUS_BAR_CTRL);

//设置状态栏的显示区间数,及相应宽度

//显示各区间文本

m_StatusBarCtrl.SetText(str,0,0);

m_StatusBarCtrl.SetText("当前操作员:"+app->m_sUserName,1,0);

m_StatusBarCtrl.SetText(s,2,0);

this->SetTimer(12,1000,NULL);

returnTRUE;//returnTRUEunlessyousetthefocustoacontrol

③处理WM_TIMER消息的消息响应函数OnTimer,代码如下:

voidCA1Dlg::OnTimer(UINTnIDEvent)

this->m_StatusBarCtrl.SetText(s,2,0);

CDialog::OnTimer(nIDEvent);

一个优秀的商业管理系统,不但要有实用的功能,还要有漂亮友好的界面。在本例中,设置窗体背景只需加入一个Bitmap资源,运行效果如图3.3所示,其操作步骤如下:

(1)在资源对话框上放一个Picture控件。

(2)然后加入一个需要的Bitmap资源,如果图片包含的颜色超过256种,那么它会提示该图片不能在资源编辑器里编辑,不用管它,除非真的想编辑它,加进来的图片的资源符号缺省为IDB_BITMAP1。

(3)设置Picture控件属性类型为Bitmap,图像为IDB_BITMAP1。

q输入密码的控件采用文本框。密码如果输入正确,取得用户权限并进入系统,否则,将提示错误,并返回密码输入框。

q记录错误次数,录入密码错误3次将自动退出系统。

q用户按下〈Enter〉键,控制焦点的移动。

(1)增加对话框资源,设计窗体资源符号为IDD_DIALOG_LOGIN。

(3)向窗口中添加图片、编辑框、静态文本、按钮等资源,设置主要资源属性,如表2所示。

资源名称

资源对应的变量

资源属性

Bitmap

JIEMIAN

来自于文件jiemian.bmp

Picture

IDC_STATIC

类型Bitmap,图像JIEMIAN

Button

IDOK

缺省

IDCANCEL

StaticBox

标题为:请输入用户名和密码:

标题为:用户名:

标题为:密码:

EditBox

IDC_EDIT_NAME

CEditm_editUserName

取消Border,选上【Staticedge”

IDC_EDIT_PASSWORD

CEditm_editPassWord

取消Border,选上【Staticedge”和【PassWord”

BOOLCMedApp::InitInstance()

......

LRunSql::InitConnectPtr();//初始化COM环境,进行数据库连接

CA1Dlg*pdlg=newCA1Dlg;//创建主窗体对象

m_pMainWnd=pdlg;

pdlg->DoModal();//显示主窗体

deletepdlg;

pdlg=NULL;

LRunSql::Close();//断开数据库连接

returnFALSE;

当用户单击“确定”按钮时,进行密码判断和次数判断。处理“确定“按钮的消息响应函数如下:

voidCDlgLogOn::OnOK()

BOOLbLogOn=FALSE;

CStringsUserPassWord,sPurview,sUserName,sInputPassWord;

LRunSqlm_runsql;

CStringsql;

_variant_tvalue;

CStringsError;

//更新数据变量

this->m_editPassWord.GetWindowText(sInputPassWord);

this->m_editUserName.GetWindowText(sUserName);

CA1App*App=(CA1App*)AfxGetApp();

sql.Format(

"selectadmi_password,admi_purviewfromtabpurviewwhereadmi_name='%s'",

sUserName);

if(m_runsql.CheckSQLResult(sql))

value=m_runsql.m_recordset->GetCollect("admi_password");

if(value.vt!=VT_NULL)

sUserPassWord=(char*)(_bstr_t)value;

value=m_runsql.m_recordset->GetCollect("admi_purview");

sPurview=(char*)(_bstr_t)value;

if(sUserPassWord==CCrypt::Encrypt(sInputPassWord,123))

App->m_sUserName=sUserName;

App->m_sPurview=sPurview;

bLogOn=TRUE;

else

sError="请重新输入密码。\n注意大小写!","密码错误";

this->m_editPassWord.SetFocus();

sError="请确认用户名大小写是否正确!","无此用户";

this->m_editUserName.SetFocus();

if(bLogOn)EndDialog(IDOK);

m_iLogOnCount++;

if(m_iLogOnCount>=3)

this->EndDialog(0);

MessageBox(sError);

进行焦点控制。定义控制焦点的函数,该函数定义了当用户单击〈Enter〉键时,焦点改变的顺序,当需要改变焦点时,调用此函数。

boolCDlgLogOn::SetTheFocus()

HWNDhwnd=::GetFocus();

UINTid=::GetDlgCtrlID(hwnd);

switch(id)

caseIDC_EDIT_NAME:

::PostMessage(m_editPassWord.GetSafeHwnd(),WM_KEYDOWN,VK_END,0);

returntrue;

caseIDC_EDIT_PASSWORD:

this->GetDlgItem(IDOK)->SetFocus();

caseIDOK:

this->OnOK();

caseIDCANCEL:

this->OnCancel();

returnfalse;

在消息预处理函数中调用此函数。

BOOLCDlgLogOn::PreTranslateMessage(MSG*pMsg)

if(pMsg->message==WM_KEYDOWN&&pMsg->wParam==13)

if(this->SetTheFocus())

returnCDialog::PreTranslateMessage(pMsg);

//该函数返回True,表示该消息已被处理

q自动生成销售日期及销售票号。

q确定用户输入数据完毕后,可提交数据给数据库。

q自动核算销售金额。

q支持打印功能。

销售登记模块运行结果如图9所示。

图9销售登记模块运行结果

(1)新建一个窗口类,名称为CDlgXSDJ,对话框资源ID为IDD_DIALOG_XSDJ。

(3)设置主要资源属性,如表3所示。

Dialog

IDD_DIALOG_XSDJ

CDlgXSDJdlg(true)

标题:销售登记

字体名称:楷体_GB2312

字体大小:12

ComboBox

IDC_COMBO1

CComboBoxm_comboJsfs

Type:DropList

IDC_COMBO2

CComboBoxm_comboJsr

IDC_EDIT_KHID

CGeneralEditm_editKhId

取消Border

IDC_EDIT_KHNAME

CGeneralEditm_editKhName

IDC_EDIT1

CStringm_strPh

CEditm_editPh

取消Border,选上ReadOnly

IDC_EDIT_SS

Type:Frame

Color:Black

IDC_STATIC_SS

标题为:实收:

标题为:总金额:

IDC_STATIC_ZJE

标题为:0.00

IDC_STATIC_PH

标题为:销售登记票号:

DateTimePicker

IDC_DATETIMEPICKER1

CDateTimeCtrlm_tcRq

格式:ShortDate

选上:Staticedge

IDC_BUTTON1

标题为:删除

IDC_BUTTON_OK

CButtonm_btnOk

标题为:确定

IDC_BUTTON_PRINT

标题为:打印...

标题为:退出

(1)创建左上角的标题信息。

①创建白色背景。

CWhiteFramem_whiteframe;

在OnCreate的成员函数中创建该对象对应的窗口。

intCDlgXSDJ::OnCreate(LPCREATESTRUCTlpCreateStruct)

rect.left+=10;

rect.right-=250;

rect.top+=10;

rect.bottom=200;

m_whiteframe.Create("",WS_CHILD|WS_TABSTOP|WS_VISIBLE,rect,this,700);

②创建标题部分的控件。

该部分的控件都以上述的白色背景窗口为父窗口,要注意以下几点:

在这个背景上创建静态文本,且文本背景是白色。对此,同样使用CWhiteFrame类,并用该类定义一组静态文本对象,要注意创建文本的位置,使其与相应的控件相配合。例如:确保静态文本“客户编号”与相应的编辑框在同一个水平高度;日期与日期控件在同一个高度。

由于入库与销售大部分内容是相同的,所以,用一个窗体来执行这两部分功能。为此,用Bool型的变量m_bXs来表示这两种区别,并在代码中要适时修改一些属性。

改变设计时添加的控件的父窗体要用到其成员函数SetParent。方式如下:

m_tcRq.SetParent(&m_whiteframe);

对于结算方式下拉列表框和经手人下拉列表框,需要从数据库中取得相应的数据来初始化这两个窗口,并在最后为这两个下拉列表框确定初值。

this->m_tcRq.SetTime(&m_dateRq);

创建和初始化标题部分的控件的代码如下:

boolCDlgXSDJ::InitBaseInfo()

CRectrect;CStringstr;

wf=newCWhiteFrame[5];

CStringstrs[5];//该字符串保存静态文本

if(m_bXs)//判断当前是销售登记,还是入库登记

strs[0]="客户编号:";

strs[1]="客户名称:";

this->GetDlgItem(IDC_STATIC_PH)->SetWindowText("入库登记票号:");

this->SetWindowText("入库登记:");

strs[0]="供应商编号:";

strs[1]="供应商名称:";

strs[2]="结算方式:";

strs[3]="经手人:";

strs[4]="日期:";

rect=CRect(10,40,80,55);//用来确定静态文本的位置

for(inti=0;i<5;i++)

{//创建静态文本

wf[i].Create(strs[i],WS_CHILD|WS_VISIBLE,rect,&m_whiteframe);

wf[i].Invalidate();

rect.OffsetRect(0,28);

m_tcRq.SetParent(&m_whiteframe);//改变标题控件的父窗口

m_comboJsr.SetParent(&m_whiteframe);

m_editKhName.SetParent(&m_whiteframe);

m_editKhId.SetParent(&m_whiteframe);

m_comboJsfs.SetParent(&m_whiteframe);

//inittime;

//initjsr;//初始化经手人下拉列表框

sql.Format("selectyg_namefromtabyginfo");

if(!m_runsql.CheckSQLResult(sql))returnfalse;

while(!m_runsql.m_recordset->adoEOF)//从数据库取值初始化员工下拉列表框

value=m_runsql.m_recordset->GetCollect("yg_name");

this->m_comboJsr.AddString((char*)(_bstr_t)value);

m_runsql.m_recordset->MoveNext();

//initjsfs;

sql.Format("selectjsfsfromtabjsfs");

this->m_runsql.RunSQL(sql);

while(!m_runsql.m_recordset->adoEOF)//从数据库取值初始化经手人下拉列表框

value=m_runsql.m_recordset->GetCollect("jsfs");

this->m_comboJsfs.AddString((char*)(_bstr_t)value);

this->m_comboJsfs.SetCurSel(0);

this->m_comboJsr.SetCurSel(0);

③为客户编号和客户名称编辑框连接自动提示窗口。

对于客户信息和供应商信息,这两者信息格式大部分是相同的,并且每次是用到其中的一组数据时都需要用到自动提示窗口,所以专门作出一个类CGeneralEdit来对应着两组信息,并包含对自动提示窗口的使用。该类派生自CEdit(参看类图2.12)。在此之前,请参看关键技术中的5.2.2关于显示自动提示窗口的介绍。

功能分析:

界面上看,需要有下划线和白色背景。

当把焦点移到某个编辑框上时原有弹出的自动提示窗口消失。

当在编辑框中进行编辑时引起EN_CHANGE事件时,弹出自动提示窗口。

焦点移走时,让自动提示窗口消失;但是如果焦点移动到了自动提示窗口上,则自动提示窗口不消失。

当父窗体移动时,自动提示窗口也跟着移动。

当在编辑框中进行编辑时,按〈↑〉、〈↓〉、〈PageUp〉、〈PageDown〉键,自动提示窗口会响应这些消息,且此时焦点还在编辑框中。

当用户在其中一个编辑框中按〈Enter〉键,表示确定了选择某一个客户(编号或名称),

那么另一个编辑框中的内容也随之改变。

当用户在其中一个编辑框中单击〈Esc〉键,表示用户放弃进行编辑,取消自动弹出对话框。

为了实现功能2,写消息WM_SETFOCUS的消息响应函数OnSetFocus。

voidCGeneralEdit::OnSetFocus(CWnd*pOldWnd)

ASSERT(this->m_poplist!=NULL);

m_poplist->ShowWindow(SW_HIDE);

CEdit::OnSetFocus(pOldWnd);

对于功能3,要写EN_CHANGE消息响应函数OnChange。

在编写EN_CHANGE消息响应函数OnChange时,需要注意:

客户编号编辑框和客户名称编辑框都是由一个类定义出来的,使用资源符号来区分这两个对象,如IDC_EDIT_KHID对应着客户编号编辑框,而IDC_EDIT_KHNAME则对应着客户名称编辑框对象。

当编辑编号时,直接用当前编辑框的字符串来刷新自动提示窗口,当编辑名称时,还需要参考编号编辑框的值,来显示自动提示窗口的内容。

如果自动提示窗口已经显示了,就没有必要重复计算显示。

代码如下:

voidCGeneralEdit::OnChange()

if(m_bSetValue)return;

this->GetWindowText(str);//取得当前编辑框的字符串

intiID=this->GetDlgCtrlID();//取得当前编辑框对象的资源符号的值

if(iID==IDC_EDIT_KHID)//判断是编号对象,还是名称对象

this->m_poplist->RefreshListCtrlView(0,str);//刷新自动提示窗口数据

elseif(iID==IDC_EDIT_KHNAME)

CStringid;

CWnd*editid;

editid=this->GetParent()->GetDlgItem(IDC_EDIT_KHID);

editid->GetWindowText(id);

m_poplist->RefreshListCtrlView(1,str,id,0);//根据两个字符串刷新自动提示窗口

if(!m_poplist->IsWindowVisible())//如果自动提示窗口已显示,就不用再设定位置、显示

this->GetWindowRect(&m_rectWindow);

this->m_poplist->SetShowPosition(this->m_rectWindow,this);

m_poplist->ShowListPop();

对于功能4、6、7、8,需要编写预解释函数PreTranslateMessage(MSG*pMsg)和WM_KILLFOCUS的消息响应函数OnKillFocus,功能分析如下:

编辑框失去焦点的时候,会调用函数OnKillFocus(CWnd*pNewWnd),此时,需要判断是否焦点转移到了自动提示窗口上,pNewWnd就是焦点转移到的窗口指针,判断这个指针是谁就行了。

当用户按〈Enter〉键,缺省情况下,对话框处理这个消息并最终执行OnOk函数,关闭对话框。需要在预解释函数中处理这个消息,并把它解释为WM_KILLFOCUS,并设定一个开关变量标识这个消息,在OnKillFocus函数中收到并处理这个消息。

当用户按〈Esc〉键时,需要让自动提示窗口消失,同时将〈Enter〉键解释为无关紧要的键如〈Ctrl〉键。

当用户按〈↑〉、〈↓〉、〈PageUp〉、〈PageDown〉键时,将这个消息原封不动地发送给自动提示窗口,自动提示窗口会响应这些消息(此时焦点还在编辑框中)。

BOOLCGeneralEdit::PreTranslateMessage(MSG*pMsg)

//TODO:Addyourspecializedcodehereand/orcallthebaseclass

if(pMsg->message==WM_KEYDOWN)//捕捉键盘某个键按下事件

switch(pMsg->wParam)

case13://捕捉〈Enter〉键

pMsg->message=WM_KILLFOCUS;//将该消息改为WM_KILLFOCUS消息

m_Kill=RETURNKILL;//设置开关变量,将在OnKillFocus中使用

break;

case27://捕捉〈Esc〉键

if(m_poplist->IsWindowVisible())//如果自动提示窗口处于显示状态,隐藏它

this->m_poplist->ShowWindow(false);

pMsg->wParam=VK_CONTROL;//将该消息改为〈Ctrl〉键

caseVK_UP://捕捉〈↑〉、〈↓〉、〈PageUp〉、〈PageDown〉键

caseVK_DOWN:

caseVK_NEXT:

caseVK_PRIOR:

{//将这些消息由自动提示窗口处理

this->m_poplist->SendTheUDNPMessage(pMsg->wParam);

pMsg->wParam=VK_CONTROL;//并将该消息解释为无用的键

returnCEdit::PreTranslateMessage(pMsg);

下面看看自动提示窗口是如何处理〈↑〉、〈↓〉、〈PageUp〉、〈PageDown〉键的。

voidCListCtrlPop::SendTheUDNPMessage(UINTKEY)

::SendMessage(this->m_listctrl->GetSafeHwnd(),WM_KEYDOWN,KEY,0);

m_listctrl->SetHotItem(m_listctrl->GetSelectionMark());

自动提示窗口将这些消息原封不动地发送给了其中的列表控件。

调用完消息与解释函数后,消息被预解释了,可以处理这些解释后的消息。

voidCGeneralEdit::OnKillFocus(CWnd*pNewWnd)

CEdit::OnKillFocus(pNewWnd);

intiID=this->GetDlgCtrlID();//取得当前编辑框对象的资源符号值

switch(m_Kill)//判断是不是经过处理的〈Enter〉键按下的消息

caseRETURNKILL://〈Enter〉键按下后

ASSERT(this->m_poplist!=NULL);//判断自动提示窗口对象指针有效

if(m_poplist->IsWindowVisible()&&m_poplist->GetSelectedMark()>=0)

{//判断自动提示窗口是可视的,并且有某个记录被选择

//接下来,进行从提示对话框中取值赋值给编辑框

this->m_poplist->ShowWindow(SW_HIDE);

CGeneralEdit*edit;

//根据资源编号取得对象指针

edit=(CGeneralEdit*)this->GetParent()->GetDlgItem(IDC_EDIT_KHNAME);

edit->SetValueUnOnChange(m_poplist->GetListCtrlSel(1));

edit->Invalidate();//刷新编辑框

edit=(CGeneralEdit*)this->GetParent()->GetDlgItem(IDC_EDIT_KHID);

edit->SetValueUnOnChange(m_poplist->GetListCtrlSel(0));

edit->Invalidate();

this->m_poplist->ShowWindow(SW_HIDE);//隐藏窗口

//让对话框窗口设定焦点该由谁获得

::PostMessage(this->GetParent()->GetParent()->GetSafeHwnd(),

MYMESSAGE_XSDJ_SETTHEFOCUS,0,0);

default:

//此时,需要判断是否焦点转移到了自动提示窗口或自动提示窗口中的列表上,如果是,就不隐藏

//自动提示窗口,否则,隐藏自动提示窗口

if(pNewWnd!=NULL)

if(pNewWnd->GetDlgCtrlID()==m_poplist->GetDlgCtrlID()||

pNewWnd->GetDlgCtrlID()==ID_POP_LISTCTRL);

elsethis->m_poplist->ShowWindow(SW_HIDE);

m_Kill=NORMALKILL;//恢复开关变量

//TODO:Addyourmessagehandlercodehere

(2)自动产生销售编号。

CStringCDlgXSDJ::ChanShengXSDJPH()

this->UpdateData();

_bstr_tsql_;

CStrings_value;

CStrings_date;

CStringph;

CTimem_tRq;

this->m_tcRq.GetTime(m_tRq);

this->m_tcRq.GetWindowText(s_date);

CStringy_date,m_date,d_date;

y_date=m_tRq.Format("%Y");

m_date.Format("%02d",m_tRq.GetMonth());

d_date.Format("%02d",m_tRq.GetDay());

ph=y_date+"-"+m_date+"-"+d_date;

if(this->m_bXs)//判断是销售登记还是入库登记

ph=ph+"xsd";

//从数据库中取得最大的编号

sql.Format("selectxs_phfromtabxsphwhererq=#%s#orderbyxs_phdesc",s_date);

value=m_runsql.m_recordset->GetCollect("xs_ph");

if(value.vt!=NULL)

svalue=(char*)(_bstr_t)value;

svalue=s_value.Mid(s_value.GetLength()-4,4);

svalue="0";

ph=ph+"rkd";

sql.Format("selectrk_phfromtabrkphwhererq=#%s#orderbyrk_phdesc",s_date);

value=m_runsql.m_recordset->GetCollect("rk_ph");

//格式化产生的新编号

longlvalue=atoi(s_value)+1;

s_value.Format("%04d",l_value);

ph=ph+s_value;

returnph;

(3)创建列表控件。

初始化列表控件,设置列表控件的大小、风格、列标题、可编辑的列号。读者可参看本章5.7节专题技术,其中详细介绍了功能强大的列表控件。

boolCDlgXSDJ::InitnListXSDJ()

CRectrect_nlist(10,300,700,650);

this->GetClientRect(&rect_nlist);

rect_nlist.top=210;

rect_nlist.bottom=480;

this->m_plistXSDJ=newCListXSDJ(m_bXs);

m_plistXSDJ->Create(WS_CHILD|WS_VISIBLE|LVS_REPORT|WS_BORDER,

rect_nlist,this,ID_NEWLISTLSXSDJ);

this->m_plistXSDJ->ModifyStyle(LVS_EDITLABELS,0L);//禁止标题编辑

m_plistXSDJ->ModifyStyle(0L,LVS_REPORT);//设为Report类型

m_plistXSDJ->ModifyStyle(0L,LVS_SHOWSELALWAYS);//始终高亮显示被选中的项

m_plistXSDJ->ModifyStyle(0L,LVS_NOSORTHEADER);

m_plistXSDJ->ModifyStyle(LVS_OWNERDRAWFIXED,0L);

m_plistXSDJ->SetExtendedStyle(LVS_EX_FULLROWSELECT|//允许整行选中

LVS_EX_GRIDLINES|//画出网格线

LVS_EX_FLATSB//扁平风格的滚动条

);

//1、先产生numTitle列

inti=0;

m_plistXSDJ->InsertColumn(i,"药品编号");

m_plistXSDJ->InsertColumn(1,"药品名称");

m_plistXSDJ->InsertColumn(2,"仓库名称");

m_plistXSDJ->InsertColumn(4,"数量");

m_plistXSDJ->InsertColumn(5,"总金额");

if(m_bXs)

m_plistXSDJ->InsertColumn(3,"单价");

m_plistXSDJ->InsertColumn(6,"实收");

m_plistXSDJ->InsertColumn(3,"进价");

m_plistXSDJ->InsertColumn(6,"实付");

//2、插入1行

m_plistXSDJ->InsertItem(0,"");

//3、调整列宽

RECTrect2;

m_plistXSDJ->GetWindowRect(&rect2);

intwid=rect2.right-rect2.left;

for(i=0;i<7;i++)

m_plistXSDJ->SetItemText(0,i,"");

m_plistXSDJ->SetColumnWidth(i,wid/7);

m_plistXSDJ->SetSubItemCanEdited(0);

m_plistXSDJ->SetSubItemCanEdited(1);

m_plistXSDJ->SetSubItemCanEdited(2);

m_plistXSDJ->SetSubItemCanEdited(3);

m_plistXSDJ->SetSubItemCanEdited(4);

m_plistXSDJ->SetSubItemCanEdited(5);

m_plistXSDJ->SetSubItemCanEdited(6);

m_plistXSDJ->Invalidate(false);

q确定用户输入数据完毕后,可提交给数据库。

q自动核算入库金额,支持打印功能。

q删除当前指针所对应的记录信息。

入库登记模块运行结果如图10所示。

图10入库登记模块运行结果

(1)新建一个对话框,对话框资源ID为IDD_DIALOG_RKDJ。

(3)设置对话框标题属性为“入库登记”,其他控件属性保持默认设置。

定义bool类型的变量m_bXs,在该类的构造函数中对这两个模块加以区分。

CDlgXSDJ::CDlgXSDJ(boolisxs,CWnd*pParent/*=NULL*/)

:CDialog(CDlgXSDJ::IDD,pParent)

this->m_bXs=isxs;

(2)创建左上角的标题信息。

①显示各种文本内容。

②为供应商编号和供应商名称编辑框连接自动提示窗口。

boolCDlgXSDJ::InitStringLists()

m_strlistKh=newCStringList[2];

m_strlistKh[0].AddTail("客户编号");

m_strlistKh[1].AddTail("客户全称");

sql.Format("selectDISTINCTkh_id,kh_namefromtabkhorderbykh_idasc");

if(!this->m_runsql.CheckSQLResult(sql))returnfalse;

while(!m_runsql.m_recordset->adoEOF)

value=m_runsql.m_recordset->GetCollect("kh_id");

this->m_strlistKh[0].AddTail((char*)(_bstr_t)value);

value=m_runsql.m_recordset->GetCollect("kh_name");

this->m_strlistKh[1].AddTail((char*)(_bstr_t)value);

m_strlistKh[0].AddTail("供应商编号");

m_strlistKh[1].AddTail("供应商全称");

sql.Format("selectDISTINCTgys_id,gys_namefromtabgysorderbygys_idasc");

value=m_runsql.m_recordset->GetCollect("gys_id");

value=m_runsql.m_recordset->GetCollect("gys_name");

this->m_popList.Create(this);

m_popList.SelectStringList(2,this->m_strlistKh);

this->m_editKhId.SelectPopList(&m_popList);

this->m_editKhName.SelectPopList(&m_popList);

(3)自动产生入库票号。

sql.Format("selectxs_phfromtabxsphwhererq=’%s’orderbyxs_phdesc",s_date);

sql.Format("selectrk_phfromtabrkphwhererq=’%s’orderbyrk_phdesc",s_date);

longlvalue=atoi(s_value)+1;//格式化产生的新编号

(4)创建列表控件。

对于列表控件,需要注意第3列标题不同。

(5)在对话框的初始化函数中进行数据初始化。

BOOLCDlgXSDJ::OnInitDialog()

InitStringLists();

InitnListXSDJ();

if(!this->InitBaseInfo())

MessageBox("初始化基本数据失败");

this->m_sXsPh=m_strPh=this->ChanShengXSDJPH();

this->UpdateData(false);

m_editKhId.SetFocus();

returnFALSE;//returnTRUEunlessyousetthefocustoacontrol

//EXCEPTION:OCXPropertyPagesshouldreturnFALSE

}//返回值是FALSE表示焦点已被确定

(6)实现按钮功能。

入库登记模块有4个功能按钮:确定、打印、删除、退出。其中,打印、退出按钮与销售模块相同,这里不再重复。

boolCListXSDJ::DeleteSelected()

if(this->m_poplist->IsWindowVisible())//隐藏不必要的窗口

if(this->m_edit.IsWindowVisible())

m_edit.ShowWindow(SW_HIDE);

LVITEM*item=newLVITEM;

intnumber=this->GetSelectedCount();

for(inti=this->GetItemCount()-1;i>=0;i--)//从最后一行开始判断是否被选上

this->m_nItem=i;

item->iItem=i;

item->mask=LVIF_STATE;

item->stateMask=LVIS_SELECTED;

GetItem(item);

if(item->state==LVIS_SELECTED)

CStrings_sl=this->GetItemText(i,4);

longl_sl=atoi(s_sl);

if(m_iYpKcSelected[i]<0||l_sl==0)continue;

longkc_number

=atoi(m_pstrlistKc[3].GetAt(this->m_pstrlistKc[3].FindIndex(this->m_iYpKcSelected[i])));

CStringleft;

left.Format("%d",kc_number+l_sl);

left.Format("%d",kc_number-l_sl);

this->m_pstrlistKc[3].SetAt(this->m_pstrlistKc[3].FindIndex(this->m_iYpKcSelected[i]),left);

DeleteItem(i);

this->m_iTheItemState[i]=NONE;

if(GetItemCount()==0)

InsertItem(0,"");

this->m_nItem=0;

Invalidate();

实现“”确定按钮,该按钮完成两个内容:检查用户输入数据是否有效及以事务形式提交数据库。提交数据库时,刷新的数据表不同,且刷新库存表时,算法不同。

voidCDlgXSDJ::OnButtonOk()

if(!CheckKh())

this->m_editKhId.SetFocus();

MessageBox("请输入客户信息","注意");

MessageBox("请输入供应商信息","注意");

return;

elseif(!this->m_plistXSDJ->CheckAllItem())

MessageBox("请输入完整客户登记信息","注意");

MessageBox("请输入完整供应商登记信息","注意");

this->m_plistXSDJ->m_edit.SetFocus();

CA1App*app=(CA1App*)AfxGetApp();

this->BeginWaitCursor();

CStringxs_ph=this->m_sXsPh;inti=0;

CStringkh_id;this->m_editKhId.GetWindowText(kh_id);

CStringkh_name;this->m_editKhName.GetWindowText(kh_name);

CStringczy=app->m_sUserName;

CStringjsr;this->m_comboJsr.GetWindowText(jsr);

CStringrq;this->m_tcRq.GetWindowText(rq);

CStringjsfs;this->m_comboJsfs.GetWindowText(jsfs);

CStringyp_id,yp_name,s_sl,ck_name,s_dj,s_je,sql;

longl_sl=0;

doubled_dj=0,d_je=0,ys=0,ss=0,ws=0;

longpzs=0;

boolis_jq=false;

CStringListslist;

intn=m_plistXSDJ->GetItemCount();

if(n<=0)

MessageBox("请输入登记信息","注意");

this->m_plistXSDJ->m_iEditedIndex=-1;

::PostMessage(m_plistXSDJ->GetSafeHwnd(),WM_SETFOCUS,0,0);

::PostMessage(m_plistXSDJ->GetSafeHwnd(),SETNEXTITEMPHFOCUS,0,0);

try{

m_runsql.m_recordset->Close();

LRunSql::BeginTrans();

catch(_com_errore)

MessageBox(e.ErrorMessage());

for(i=0;i

yp_id=this->m_plistXSDJ->GetItemText(i,0);

yp_name=this->m_plistXSDJ->GetItemText(i,1);

ck_name=this->m_plistXSDJ->GetItemText(i,2);

s_dj=this->m_plistXSDJ->GetItemText(i,3);

d_dj=atof(s_dj);

s_sl=this->m_plistXSDJ->GetItemText(i,4);

l_sl=atoi(s_sl);

s_je=this->m_plistXSDJ->GetItemText(i,5);

d_je=atof(s_je);

ys=d_je+ys;

ss=ss+atof(m_plistXSDJ->GetItemText(i,6));

//savedj;

if(slist.Find(yp_id)==NULL)slist.AddTail(yp_id);

doublejinjia=0;doubleprofit=0;

m_plistXSDJ->m_mapYpToJj.Lookup(yp_id,jinjia);profit=(d_dj-jinjia)*l_sl;

sql.Format("INSERTINTOtabxsdj(xs_ph,yp_id,ck_name,sl,dj,je,profit)\

VALUES('%s','%s','%s',%d,%f,%f,%f)"

,xs_ph,yp_id,ck_name,l_sl,d_dj,d_je,profit);

sql.Format("INSERTINTOtabrkdj(rk_ph,yp_id,ck_name,sl,dj,je)\

VALUES('%s','%s','%s',%d,%f,%f)"

,xs_ph,yp_id,ck_name,l_sl,d_dj,d_je);

sql.Format("updatetabkcsetkc_number=kc_number-%dwhereyp_id='%s'andck_name=\

'%s'",l_sl,yp_id,ck_name);

sql.Format("updatetabkcsetkc_number=kc_number+%dwhereyp_id='%s'andck_name=\

ws=ys-ss;

if(ws<=0.0)

ws=0.0;

is_jq=true;

pzs=slist.GetCount();

if(!m_bXs)

sql.Format("INSERTINTOtabrkph(rk_ph,gys_id,pzs,yf,sf,wf,is_jq,rq,czy,jsr,jsfs)\

VALUES('%s','%s',%d,%f,%f,%f,%d,#%s#,'%s','%s','%s')"

,xs_ph,kh_id,pzs,ys,ss,ws,is_jq,rq,czy,jsr,jsfs);

sql.Format("INSERTINTOtabxsph(xs_ph,kh_id,pzs,ys,ss,ws,is_jq,rq,czy,jsr,jsfs)\

this->EndWaitCursor();

if(!LRunSql::CommitTrans())

MessageBox("数据库事务提交错误","医药管理系统");

MessageBox("OK","医药管理系统");

(7)实现弹出提示窗口。

入库登记模块与销售登记模块实现弹出提示窗口的不同点是:修改临时库存的算法不同。主要表现在编辑框的EN_CHANGE消息处理函数上,当用户修改数量编辑框中数据时,要对临时数据库进行修改。

voidCListXSDJ::OnNewEditChange(constint&item,constint&sub_item)

switch(sub_item)

{……

case4://数量

l_left=m_edit.kc_number-atoi(str)+m_edit.m_dSetFocusValue;//-curshownumber+setfocusvalue=left

l_left=m_edit.kc_number+atoi(str)-m_edit.m_dSetFocusValue;//+curshownumber-setfocusvalue=left

1.《VisualBasic精彩编程200例》机械工业出版社赛奎春、高春艳等

2003年1月

2.《VisualBasic数据库开发实例解析》机械工业出版社刘志铭、高春艳等

2003年8月

3.《VisualFoxPro数据库开发实例解析》机械工业出版社王晶莹、王国辉等

2003年9月

4.《PowerBuilder数据库开发实例解析》机械工业出版社华传铭、张振坤等

5.《Delphi数据库开发实例解析》机械工业出版社赛奎春、郑骁鹏等

2004年2月

6.《PowerBuilder精彩编程200例》机械工业出版社张振坤、李文立等

2004年9月

7.《VisualFoxPro精彩编程200例》机械工业出版社王国辉、董韶华等

8.《ASP数据库开发实例解析》机械工业出版社李严、于亚芳、王国辉2004年12月

9.《Delphi工程应用与项目实践》机械工业出版社宋坤、赵智勇等

2005年1月

10.《VisualBasic工程应用与项目实践》机械工业出版社高春艳、李俊民等

11.《VisualC++工程应用与项目实践》机械工业出版社张雨、阮伟良等

12.《JSP工程应用与项目实践》机械工业出版社陈威、白伟明、李楠

2005年2月

13.《ASP工程应用与项目实践》机械工业出版社王国辉、牛强、李南南

2005年4月

2005年7月

17.《Visualfoxpro数据库开发关键技术与实例应用》人民邮电出版社周桓、张雨、王国辉

2004年5月

18.《PowerBuilder数据库开发关键技术与实例应用》人民邮电出版社刘志铭、张振坤、冯文萃2004年5月

19.《Delphi数据库开发关键技术与实例应用》人民邮电出版社赛奎春、陈紫鸿、宋昆

20.《Visualbasic数据库开发关键技术与实例应用》人民邮电出版社高春艳、李艳

21.《VisualC++管理信息系统完整项目实例剖析》人民邮电出版社明日科技

22.《VisualBasic管理信息系统完整项目实例剖析》人民邮电出版社明日科技

23.《PowerBuilder管理信息系统完整项目实例剖析》人民邮电出版社明日科技

24.《VisualFoxPro管理信息系统完整项目实例剖析》人民邮电出版社明日科技

25.《SQLServer数据库开发实例解析》机械工业出版社宋昆、李严等

2006年1月

26.《Access数据库开发实例解析》机械工业出版社李俊民、高春燕等

27.《VisualBasic数据库系统开发完全手册》人民邮电出版社明日科技王春才、高春艳、

李俊民2006年3月

28.《VisualC++数据库系统开发完全手册》人民邮电出版社明日科技王端、于速、张雨

2006年3月

29.《Delphi数据库系统开发完全手册》人民邮电出版社明日科技宋坤、邹天思

30.《JSP数据库系统开发完全手册》人民邮电出版社明日科技王国辉、李文立、杨亮

刘彬彬2006年5月

2006年5月

由于篇幅有限,只给出部分数据表。

下面分别介绍以下各个表的结构。(临时表是为了实现在查询结果中进行查询,在这里不做具体介绍)。

qtabdhdj表

tabdhdj表用于保存调货登记信息。tabdhdj表的结构如表4所示。

表4tabdhdj表的结构

字段名称

数据类型

字段大小

可否为空

说明

dh_ph

文本

20

NotNull

调货票号(主键)

out_ck

调出的库(外健)

in_ck

调入的库(外健)

yp_id

10

药品编号(外健)

sl

长整型

Null

数量

qtabpurview表

tabpurview表用于保存权限信息。tabpurview表的结构如表5所示。

THE END
1.java+mysql+61对于这么多不同的使用者,我想设计一个在传统设计方面与其他药品进销存方式相对不同的基于SSM的药品进销存平台,不仅会感觉到它的新颖,而且会在浏览、查找药品的时候更加简便迅速。 该系统基于SSM模式架构,利用J2EE设计的MVC模式,结合JDBC、Ajax等技术联合MySQL数据库来实现。面向的使用者主要包括管理员和用户,实现功能包括https://blog.csdn.net/wushuiyihua/article/details/144335705
2.提升药品出库管理效率的erp软件解决方案药品管理 库存管理 扫码出库 财务软件 发票管理 本视频探讨了如何通过先进的erp软件和扫码管理提升药品出库的准确性和效率,强调批号的重要性以及扫码录入的必要性,解决库存混乱问题。同时,介绍了系统与财务软件的无缝衔接,满足用户对发票管理的高需求,确保客户满意度并为未来的合作奠定基础。https://hyc.chanjet.com/tuijian/video-1866404243376095233.html
3.想做一套进销存全自动系统,Excel和低代码平台哪个好用?例如,一家服装零售店,通过分析过往不同季节、款式服装的销售情况以及当前库存数量,利用进销存系统制定出下一季度的服装采购计划,精准确定各类服装的进货量。2.供应商管理:对供应商的基本信息进行集中记录和管理,像供应商名称、联系方式、地址、供货能力、产品质量情况、历史合作记录等内容都涵盖在内。方便企业筛选https://baijiahao.baidu.com/s?id=1818014834122752481&wfr=spider&for=pc
4.数据流图实验报告(通用10篇)4.E-R 图 三:软件设计 1(实验室设备管理信息系统软件系统模块结构图 2.实验室设备管理信息系统软件数据设计(数据库的表) 报废注销统计表、设备修理信息表、新设备信息表 3(软件系统其中的 3 个模块的详细设计(画程序流程图或其他) 登录模块: 篇三:软件工程实验报告 实验报告 实验名称 实验一:可行性分析试验报https://www.360wenmi.com/f/fileylu5ry7p.html
5.[MySQL]数据库原理1,三大范式,E绘制E-R图,建立数据库概念模型; 将E-R图转换成关系模式进行数据模型的建立 一、了解实体之间的联系 二、熟悉概念模型表示方法E-R图 三、掌握E-R图的画法 认识数据库 常见的数据库管理系统应用案例。 1.留言板。 2.进销存管理系统。 3.ERP系统。 https://blog.51cto.com/u_16614028/9983687
6.论坛数据库系统ER图软件工程论坛系统的数据库E-R图,适合小型论坛的构建,及课程设计作业·https://www.iteye.com/resource/zcl_zcl-1936730
7.中学学生学籍管理系统e以下是关于中学学生学籍管理系统e-r图的文章详情内容供你参考,更多内容请访问[轻流]。轻量级、可自定义的管理系统搭建平台,无需代码开发即可如搭积木般快速、灵活地创造属于你的个性化管理系统,轻松实现多元业务场景的数字化管理。https://news.qingflow.com/plugin/zz/index.php?s=%E4%B8%AD%E5%AD%A6%E5%AD%A6%E7%94%9F%E5%AD%A6%E7%B1%8D%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9Fe-r%E5%9B%BE.html
8.进销存的e绘制进销存系统的E-R图需要明确业务流程、确定实体和属性、定义关系。在进销存系统中,涉及的关键实体包括商品、供应商、客户、订单等。首先,明确业务流程是指了解商品从采购(进)、库存管理(存)到销售(销)的整个流程。其次,确定实体和属性是指找出在系统中存在的主要实体,如商品、供应商等,并为每个实体定义其属性,如https://www.jiandaoyun.com/blog/article/910075/
9.java+mysql大数据的疾病种类统计系统的设计与实现(2)3.3 E-R图9 3.4 本章小结11 4 系统的详细设计与实现12 4.1 药品购买清单统计算法12 4.2 病人信息模块13 4.3疾病管理模块16 4.4本章小结17 5 系统运行及效果分析结论18 5.1 系统运行效果18 5.2 使用效益的统计与分析21 5.3 本章小结22 6 总结与展望23 http://www.youerw.com/jisuanji/lunwen_77672_2.html
10.枣庄软件开发,酒店管理软件,进销存(枣庄)专业的软件开发公司电话:0632-5271123 地址:枣庄市文化西路23号 E-mail:zzint@zzint.com 技术咨询: 业务咨询: 客户服务: 服务监督: 软件开发 您当前的位置:网站首页软件开发 酒店管理软件 北京泰能软件有限公司是专业从事酒店管理软件开发、销售和服务一体的高新技术企业,由北京中长石基信息技术股份有限公司与北京世纪泰能科技有限http://www.zzint.com/rjkf/jdgl.asp
11.用E用E - R 图来 描 述信息 结 构但不 涉 及信息 在计算 机中的表 示 ,这属 于 数据库 设 计的( ) 。 A. 需求分析阶段 B. 逻辑 设计阶段 C. 概 念设计阶段 D. 物理 设 计阶段 题目标签:数据库信息如何将EXCEL生成题库手机刷题 https://www.shuashuati.com/ti/1b25656bd6c24317868fb50d2cae3263.html?fm=bd32af3afa51530fcfd335a38884d255ae