进销存管理系统的设计与实现HackerVirus

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

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

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

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

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

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

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

根据需求分析,设计系统框架。进销存管理系统由等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.进销存系统,采购系统,供应商管理系统之间的区别在哪?(一)什么是进销存系统? 进销存系统作为企业运营管理的核心工具之一,是一套全面整合采购、销售与库存管理的信息化解决方案。它以数字化的方式记录和处理商品在企业内部流转的全过程,从原材料或商品的采购入库,到库存的存储、调配与监控,再到销售出库以及与之相关的财务收支核算等,构建起一个完整的业务循环体系,确保企业https://blog.csdn.net/jdyzzy/article/details/144379750
2.进销存平台下载2024安卓最新版手机app官方版免费安装下载集会员管理、商品进销存、微商城、分销拓客等功能于一体。解决店铺信息化管理,赋能新零售。让天下没有难做的生意!【会员】顾客扫码即为会员,方便省事;【商城】让您的生意随时随地都在进行;【分销拓客】发动全民来做你的销售员;【营销】消费通知,自助查询,电子优惠券;【商品管理】手机扫一扫秒级完成销售、盘点、库存查https://m.wandoujia.com/apps/8103050
3.通用Excel库存管理系统,最好用的Excel出入库管理表格库管易网站的表格版块有很多实用出入库管理表格,得到广大仓库管理同行的支持,经过分析与提取各个表格中的实用功能,专门制作了本套《通用Excel库存管理系统》表格。包含仓库货物做账用到的入库、出库、汇总、报表等全部功能,适合绝大部分的仓库、商铺、网店的出入库管理。 http://www.360doc.com/content/18/0124/17/52031427_724765825.shtml
4.商品进销存管理系统的设计与实现20240613101715.doc本系统是商品进销存管理系统。主要目地是完成对信息量比较大的商品按照一定的规则规范的进行管理,并且对其进行分类,进销主管可以实时的添加库存信息以及查看库存信息,也可以及时的向销售员与采购员发送销售单或者采购单,极大的提高了企业的管理效率,降低了企业的管理成本。系统应用模型采用MVC三层结构模型。系统采用Jsp+Strhttps://max.book118.com/html/2024/0613/8066121043006100.shtm
5.商品进销存管理10篇(全文)市面上商品管理系统很少有做到这种程度的。具体设计如下, 设计“日汇总管理”, 设计程序把前面的入库汇总记录, 销售汇总记录, 还前一天的库存记录, 进行相应的汇总核算, 最后计算出今日的库存。并把有关信息保存下来。要设计一个开关, 每天只能汇总一次, 来防止对日汇总一天进行多次汇总, 多次汇会倒致数据发生错误https://www.99xueshu.com/w/ikeyqbqvlihf.html
6.库管易仓库管理软件仓库管理系统进销存软件库管易仓库管理软件与库管易进销存软件官方网站,回复仓库管理软件的使用问题,收集进销存软件改进建议,发布库管易仓库管理系统官方使用教程,提供库管易进销存系统最新版本下载。https://www.kuguanyi.com/soft/?mobile=2
7.简单进销存库存管理软件下载官方版app2024免费下载安装最新版3、追踪商品的进销记录4、商品的二级分类5、[适用对象]批发商、零售商、微商、超市、个体户、有理想有梦想的年轻人[开发者信息]微信:18798809437手机号:18798809437 开发者:贵州亚虎科技有限公司备案号:黔ICP备19012108号-2A 简单进销存库存管理下载安装失败或使用异常,请 -> 一键举报 查看更多 v1.3.8版更新https://m.iuuu9.com/app/com.cunzaizhe.jxcdisturb
8.观麦进销存系统怎么样零代码企业数字化知识站观麦进销存系统是一款功能强大的管理软件,适用于各种规模的企业。它具有高效的库存管理、详细的进销记录、用户友好的界面、可靠的数据安全性。其中,高效的库存管理尤为重要,能够帮助企业实时掌握库存动态,避免因库存过多或缺货而造成的损失。通过精确的库存管理,企业可以优化采购和销售策略,从而提高运营效率和盈利能力。https://www.jiandaoyun.com/blog/article/908925/
9.进销库存管理系统进销库存管理系统可以帮助企业实现对库存的全面管理。它可以记录每一种商品的库存数量、库存价格等信息。进销库存管理系统还可以帮助企业实现对库存的预警管理,当库存数量低于一定数量时,系统会自动发出预警信息,提醒企业及时补货。 4. 报表分析 进销库存管理系统可以帮助企业生成各种报表,包括进货报表、销售报表、库存报表https://www.dugusoft.com/zixun/zixun4475.html
10.java仓库信息管理系统基于java仓库管理系统为了能及时结清每笔业务,盘点库存和货物流动情况,保证企业能及时进货以及不出现货物积压 ,库存管理人员要花费大量人力物力和时间来做数据记录统计工作。为了能改善企业管理上的缺陷,所以需要开发一套完整的、全面的仓库管理系统就成为各企业发展的必然要求。本课题的选择和研究实现正是基于这样的情况,有其重要的现实意义https://blog.51cto.com/u_14224/6781252
11.门店商品库存管理制度(通用8篇)门店商品库存管理制度 1、上货验收商品时,应按照上货单上的品名、数量逐一进行核对保证质量符合本店的(二) 库存管理系统不完善 目前, 便利店的库存管理普遍存在专业化不足, 管理技术水平低下, 人员素质对于库存商品的进销业务,应实时更新数据,存入数据库并进行数据备份,防止出现统计漏洞,杜绝弄虚作假行为https://www.360wenmi.com/f/fileyytfw5k8.html
12.凌云进销存管理系统食品版免费食品进销存软件支持远程查询,通过食品进销存管理软件随时掌握商品库存、进销业务等情况; 自动统计商品进出数量、金额,进行各种报表统计,业务数据清晰明了; 库存盘点管理,实现表格导入对比,轻松盘点库存; 管理应收、应付账款,可设置优惠金额,灵活处理收付款。 凌云进销存系统食品版功能模块 http://www.china-saas.com/spjxc/index.jhtml
13.C#WINFORM进销存系统开发(内涵免费源码+部分实操视频讲解一、 系统功能介绍 二、 系统详情 三、系统成品详情 互联网的时代,电商火爆,大家都开始进行线上销售货品,那你是如何管理你的商品库存和进销问题?软积木--小敏用的是C# WINFORM进销存系统来管理我的数据,给我带来了很多便利。它是高频需求项目,很多小店都需要,可是自己全新开发一套C# WINFORM进销存系统不划算而且花https://cloud.tencent.com/developer/article/1900688
14.简单进销存库存管理APP下载3、追踪商品的进销记录 4、商品的二级分类 5、 [适用对象] 批发商、零售商、微商、超市、个体户、有理想有梦想的年轻人 [开发者信息] 软件厂商:贵州亚虎科技有限公司开发者及隐私协议使用权限 软件图集 更多软件图集介绍 提示:软件图集是通过简单进销存库存管理官网或软件客户端截图获取,主要用于分享软件价值,如https://mydown.yesky.com/sjsoft/725761462.html
15.进销库存管理系统excel版下载在商业贸易的过程中商家一般都需要对货物的进销存进行管理,如果想让自己的工作效率更高管理更方便,可以试试小编今天带来的这款进销库存管理系统excel版软件,这款软件能够帮助用户对商品的信息进行详细的记录和管理,包括出入库和财务数据等等,还支持用户随时查询哦! https://www.crsky.com/soft/455273.html
16.零售商店进销存管理制度在实际核算中采用“实际差价率法”虽然会导致工作量过大、违背库存商品的一些原则等缺点, 但是, 该方法可以纠正账面登记的进销差价数额与实际进销差价数额不一致的情况, 对商店调整库存、销售收入是不可缺少的。 商品进销差价科目审计的难点在于零售商品销售收入的确认以及如何正确地结转成本。因此, 一般的审计过程是https://www.mingkanw.com/w/filewe6ckjs8.html
17.简单进销存库存管理app3、追踪商品的进销记录4、商品的二级分类5、[适用对象]批发商、零售商、微商、超市、个体户、有理想有梦想的年轻人[开发者信息]微信:18798809437手机号:18798809437 开发者:贵州亚虎科技有限公司 备案号:黔ICP备19012108号-2A 简单进销存库存管理下载安装失败或使用异常,请 -> 一键举报猜你喜欢 进销存 进销存https://m.liqucn.com/rj/9879966821724.wml
18.进销库存管理系统(WMS)低成本高效升级版2. 进销管理 进销库存管理系统可以实时记录销售、采购和现有库存,并自动更新库存数据。随时跟踪订单状态和库存状况,避免订单出错和库存报废损失。管理人员还可以及时获取销售报告和数据分析,更好地制定营销策略和销售计划。 3. 供应链管理 进销库存管理系统可以帮助整合供应链的交互,优化物流和流程。通过提供实时数据管http://guangzhou.11467.com/info/19474261.htm
19.进销库存管理系统excel版.zip进销库存管理系统excel版,简单的出入库管理软件,小型企业足够使用 进销存 出入库软件 库存管理软件2019-05-31 上传大小:712KB 所需:50积分/C币 进销存管理系统(Excel VBA实现).zip 进销存管理系统(Excel VBA实现).zip 进销存管理系统(Excel VBA实现).zip https://www.iteye.com/resource/cici520114-11217949
20.简体通用进销存系统v2023.1下载《简体通用进销存系统》是一款可以帮助企业管理进销的软件,软件可以实时跟踪和管理库存情况。它能够自动记录和更新产品库存信息,提供准确的库存余量和预警提示,避免库存过多或不足的问题,支持订单管理和销售管理的操作,方便我们实时查看所需数据,更好地经营企业各项业务。 https://soft.3dmgame.com/down/262333.html
21.AppStore上的“简单进销存库存管理”7、商品销售数据统计分析 8、商品材料购买和使用记录 9、其它支出和收入记录 10、员工管理和权限管理 11、多仓库管理 12、 [特有功能] 1、界面简单,操作简单、性价比高 2、记录不同客户的不同价格,可以根据不同客户显示不同的价格 3、追踪商品的进销记录 https://apps.apple.com/cn/app/id1489809850
22.天意汽车维修管理系统天意软件官网,汽车维修软件,汽车维修进销管理:包括采购进货、采购退货、配件销售、顾客退货。 库存管理:包括库存调拨、报损报溢、库存盘点、库存报警。 营业查询:包括采购单据查询、销售单据查询、当前库存查询、供货商供货统计、客户销售统计、销售商品排行等。 系统设置:包括配件资料、供货商设置、客户设置、员工设置、仓库设置。 http://www.chle828.com/help/saf/readme.htm