以文本方式查看主题

-  Foxtable(狐表)  (http://foxtable.net/bbs/index.asp)
--  专家坐堂  (http://foxtable.net/bbs/list.asp?boardid=2)
----  [转帖]进销存实战  (http://foxtable.net/bbs/dispbbs.asp?boardid=2&id=6136)

--  作者:菜鸟foxtable
--  发布时间:2010/3/9 22:07:00
--  [转帖]进销存实战

进销存实战

如今企业管理软件种类繁多,从最初的财务软件到进销存财务一体,到现在的ERP(企业资源计划)、CRM(客户资源管理)等,单从技术来说,它的基础还是以数据为中心的,各种分析报告、财务报表等无不源于实际业务中产生的记录,所以本文考虑从初学者的角度出发来讲解进销存的初步知识,希望读者能从中总结出经验来。

一个项目的实施首先要做好前期规划,这是必需的,也是非常重要的,如果这个没做好,那么修改代码将是一件非常麻烦、痛苦的事。本例仅从技术的实现讲解,首先确定需要实现的功能,其次进行数据库的设计。
进销存实战

如今企业管理软件种类繁多,从最初的财务软件到进销存财务一体,到现在的ERP(企业资源计划)、CRM(客户资源管理)等,单从技术来说,它的基础还是以数据为中心的,各种分析报告、财务报表等无不源于实际业务中产生的记录,所以本文考虑从初学者的角度出发来讲解进销存的初步知识,希望读者能从中总结出经验来。

一个项目的实施首先要做好前期规划,这是必需的,也是非常重要的,如果这个没做好,那么修改代码将是一件非常麻烦、痛苦的事。本例仅从技术的实现讲解,首先确定需要实现的功能,其次进行数据库的设计。

主要模块如下:
(1) 初始化,也就是基本资料的录入,其中分为商品资料、供应商资料、客户、业务员、商品类别、
员工档案、支付方式、库房资料
(2)进货管理,包括进货单录入以及查询功能(按时间、商品编号、商品名称、数量、业务员、
供应商、支付方式等,应分为汇总及明细)
(3)销售管理,基本同上,不同的是供应商改为客户即可
(4)库存管理,包括即时库存明细(汇总)、查询、库存盘盈整(本文略)等。
(5)财务管理,包括销售收益、支出、销售额明细(汇总)、应收、应付、已付、应付、费用明细(汇总)等
(6)其他,包括定单管理、预测分析、整理数据、备份数据等功能(略)
(见数据库设计)

本文内容依次为:进货管理(frmjhgl)、销售管理(frmxsgl)、财务管理(frmcwgl)、查找商品(frmfindsp)、
查询记录及打印模块(modprint)。(如图一)

尾:怎么样,一个比较实用的进销存管理程序产生了。限于篇幅,笔者只能刊登几个基础模块,当然这个程序及思路可能另大型软件公司的程序员不屑一顾,这就需要读者们自行根据实际来添加所需功能了。


数据库设计

做这类程序其关键在于数据库的操作,下面列出本程序中的所用数据库的结构,以便大家阅读方便:

[表名]
col1=依次为字段名、字段类型、长度等。

数据库内容:

[仓库]

Col1=编号 Char Width 10
Col2=仓库名称 Char Width 8
Col3=所属类别 Char Width 8
Col4=备注 Char Width 20

[费用]

Col1=编号 Char Width 10
Col2=日期 Date
Col3=摘要 Char Width 40
Col4=金额 Currency
Col5=付款方式 Char Width 4
Col6=备注 Char Width 20

[付款方式]

Col1=编号 Char Width 10
Col2=付款方式 Char Width 4
Col3=备注 Char Width 20

[供应商]

Col1=编号 Char Width 10
Col2=名称 Char Width 20
Col3=联系人 Char Width 8
Col4=电话 Char Width 20
Col5=传真 Char Width 20
Col6=邮政编码 Char Width 12
Col7=地址 Char Width 50
Col8=Email Char Width 20
Col9=网址 Char Width 20
Col10=税号 Char Width 50
Col11=帐号 Char Width 50
Col12=开户行 Char Width 50
Col13=备注 Char Width 20

[进货记录]

Col1=商品编号 Char Width 10
Col2=商品名称 Char Width 20
Col3=单位 Char Width 4
Col4=存放仓库 Char Width 8
Col5=数量 Integer
Col6=单价 Currency
Col7=金额 Currency
Col8=业务员 Char Width 8
Col9=进货单号 Char Width 20
Col10=日期 Date
Col11=供应商 Char Width 30
Col12=付款方式 Char Width 10
Col13=备注 Char Width 20

[客户]

Col1=编号 Char Width 10
Col2=名称 Char Width 20
Col3=联系人 Char Width 8
Col4=电话 Char Width 20
Col5=传真 Char Width 20
Col6=邮政编码 Char Width 12
Col7=地址 Char Width 50
Col8=Email Char Width 30
Col9=网址 Char Width 30
Col10=税号 Char Width 50
Col11=帐号 Char Width 50
Col12=开户行 Char Width 50
Col13=信誉度 Char Width 10
Col14=备注 Char Width 20

[库存]

Col1=商品编号 Char Width 10
Col2=商品名称 Char Width 20
Col3=单位 Char Width 4
Col4=数量 Integer
Col5=仓库 Char Width 8

[类别]

Col1=编号 Char Width 10
Col2=类别名称 Char Width 20
Col3=备注 Char Width 20

[商品]

Col1=编号 Char Width 10
Col2=名称 Char Width 20
Col3=单位 Char Width 4
Col4=类别 Char Width 8
Col5=进货价 Currency
Col6=销售价 Currency
Col7=供应商 Char Width 20
Col8=备注 Char Width 20

[销售记录]

Col1=商品编号 Char Width 10
Col2=商品名称 Char Width 20
Col3=单位 Char Width 4
Col4=存放仓库 Char Width 8
Col5=数量 Integer
Col6=单价 Currency
Col7=金额 Currency
Col8=业务员 Char Width 8
Col9=出货单号 Char Width 20
Col10=日期 Date
Col11=客户 Char Width 20
Col12=付款方式 Char Width 4
Col13=备注 Char Width 20

[业务员]

Col1=编号 Char Width 10
Col2=姓名 Char Width 8
Col3=所属部门 Char Width 20
Col4=个人电话 Char Width 20
Col5=家庭住址 Char Width 20
Col6=身份证号码 Char Width 40
Col7=备注 Char Width 20

[员工档案]

Col1=编号 Char Width 10
Col2=姓名 Char Width 8
Col3=姓别 Char Width 2
Col4=所属部门 Char Width 20
Col5=工种 Char Width 10
Col6=上工时间 Char Width 20
Col7=身份证号码 Char Width 40
Col8=个人电话 Char Width 20
Col9=家庭住址 Char Width 40
Col10=Email Char Width 20
Col11=婚否 Bit
Col12=生日 Date
Col13=爱好 Char Width 10
Col14=忠诚度 Char Width 10
Col15=备注 Char Width 20

一:进货管理

此模块的技术关键是在保存记录上,在为“销售记录”表中存数据时应同时向“库存记录”表添加,如果有此商品则在原有的基础上进行加法运算,否则添加新记录。在销售管理中原理也是这样,不过如果库存里没有此类商品就不允许用户进行销售操作。

frmjhgl(进货管理)模块中所有控件的相关设置:
(1)TextBox:本模块共用8个文本框,其Name属性分别为:
txtname(商品名称)、txtliang(数量)、txtdanjia(单价)、txtbianhao(商品编号)、txtjhdata(操作日期)、txtjine(金额)、txtjine(金额)、txtshuiq(税前金额)、txtshui(税率)

datasource属性分别为:data1,datafield为空。
另添加三个combobox控件(cmbcj、cmbywy、 cmbjie), 用来显示厂家、业务员及结算方式(即结、欠付等)
(2)四个command控件,name属性分别为:cmdaddnew、cmdsave、cmdcancel、cmdquit。caption属性分别为:新单、保存、取消、退出

代码:
Dim zxh As Boolean ’判断用户输入数据是否为空
Private Sub addywy()’为combobox控件添加内容
Dim db As Database
Dim rs As Recordset
Set db = OpenDatabase(App.Path & "jxc.mdb")
Set rs = db.OpenRecordset("业务员")
While Not rs.EOF
cmbywy.AddItem rs.Fields("业务员名称").value
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
Private Sub addcj()
Dim db As Database
Dim rs As Recordset
Set db = OpenDatabase(App.Path & "jxc.mdb")
Set rs = db.OpenRecordset("厂家")
While Not rs.EOF
cmbcj.AddItem rs.Fields("厂家名称").value
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
Private Sub notnull()
If txtbianhao.Text = "" Then
zxh = True
MsgBox "商品编号不能为空", vbInformation, "试图添加空记录"
End If
If txtname.Text = "" Then
zxh = True
MsgBox "商品名称不能为空", vbInformation, "试图添加空记录"
End If
If txtliang.Text = "" Then
zxh = True
MsgBox "数量不能为空", vbInformation, "试图添加空记录"
End If
End Sub

Private Sub cmdaddnew_Click()
Data1.Recordset.AddNew
txtjhdata.Text = Date
cmdsave.Enabled = True
cmdcancel.Enabled = True
cmdaddnew.Enabled = False
End Sub

Private Sub cmdcancel_Click()
Data1.Recordset.CancelUpdate
cmdaddnew.Enabled = True
cmdsave.Enabled = False
cmdcancel.Enabled = False
End Sub

Private Sub cmdsave_Click()
Dim field_value$, txtliang_value$
Dim jhbh$, ccbh$, jhna$
cmdaddnew.Enabled = True
cmdsave.Enabled = False
cmdcancel.Enabled = False
On Error GoTo err
txtliang_value = txtliang.Text
jhbh = txtbianhao.Text
jhna = txtname.Text
Call notnull
If zxh = True Then
Data1.Recordset.CancelUpdate
Else ’执行
Me.MousePointer = 11
Data1.Recordset.Update
’必须初始化绑定字段
txtdanjia.datafield = ""
txtjhdata.datafield = ""
txtjine.datafield = ""
cmbcj.datafield = ""
cmbywy.datafield = ""
cmbjie.datafield = ""
’向库存添加
Data1.RecordSource = "即时库存"
Data1.Refresh
Data1.Recordset.MoveFirst
While ccbh <> jhbh And Not Data1.Recordset.EOF
ccbh = Data1.Recordset.Fields("商品编号").value
If ccbh = jhbh Then
ccbh = Data1.Recordset.Fields("商品编号").value
Else
Data1.Recordset.MoveNext
End If
Wend
If ccbh = jhbh Then
Data1.Recordset.Edit
field_value = Data1.Recordset.Fields("数量").value
Data1.Recordset.Fields("数量").value = field_value + txtliang_value
Data1.Recordset.Update
Else ’添加新记录
With Data1.Recordset
.AddNew
.Fields("商品编号").value = jhbh
.Fields("商品名称").value = jhna
.Fields("数量").value = txtliang_value
.Update
vs.Refresh
End With
End If
’返回开单,重新绑定字段
Data1.RecordSource = "进货记录"
Data1.Refresh
txtname.datafield = "商品名称"
txtliang.datafield = "数量"
txtdanjia.datafield = "单价"
txtbianhao.datafield = "商品编号"
txtjhdata.datafield = "操作日期"
txtjine.datafield = "金额"
cmbcj.datafield = "厂家名称"
cmbywy.datafield = "业务员名称"
Data1.Recordset.MoveLast
Me.MousePointer = 0
End If
Exit Sub
err:
Me.MousePointer = 0
MsgBox err.Description
End Sub
Private Sub cmdquit_Click()
Unload Me
End Sub

Private Sub Form_Load()
With Data1
.DatabaseName = App.Path & "jxc.mdb"
.RecordSource = "进货记录"
End With
’数据库"jxc.mdb"中表"进货记录"中的内容如下
txtname.datafield = "商品名称"
txtliang.datafield = "数量"
txtdanjia.datafield = "单价"
txtbianhao.datafield = "商品编号"
txtjhdata.datafield = "操作日期"
txtjine.datafield = "金额"
cmbcj.datafield = "厂家名称"
cmbywy.datafield = "业务员名称"
cmbjie.datafield = "支付方式"
Call addcj ’添加厂家名称
Call addywy ’添加业务员名称
End Sub

Private Sub txtdanjia_GotFocus()
With txtdanjia
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub

Private Sub txtdanjia_KeyPress(KeyAscii As Integer)
’只能输入数字
If (KeyAscii < 48 Or KeyAscii > 57) And KeyAscii >= 32 _
And KeyAscii <> Asc(".") Then
KeyAscii = 0
Beep
End If
End Sub

Private Sub txtliang_GotFocus()
With txtliang
.SelStart = 0
.SelLength = Len(.Text)
End With
End Sub

Private Sub txtliang_KeyPress(KeyAscii As Integer)
If (KeyAscii < 48 Or KeyAscii > 57) And KeyAscii >= 32 _
And KeyAscii <> Asc(".") Then
KeyAscii = 0
Beep
End Sub

Private Sub txtliang_LostFocus()
On Error GoTo err
If txtdanjia <> "" And txtliang <> "" Then
txtjine.Text = txtdanjia * txtliang
Else
MsgBox "字段不能为空", vbExclamation, "Error"
End If
Exit Sub
err:
MsgBox "请确认数据的正确性", vbCritical, "错误"
End Sub

Private Sub txtshui_LostFocus()
Dim shui ’计算税额
If txtjine <> "" And txtshui <> "" Then
shui = 1 - (txtshui.Text / 100)
txtshuiq.Text = shui * txtjine
End If
End Sub


二:销售管理
销售管理与进货管理模块中记录的操作大体一致,所不同的是库存的增减,还要添加两个功能:查找商品(见frmfindsp)及检测库存量

说明:此处textbox控件:txtspbh 显示商品编号、txtstore 显示当前库存量

Private Sub Cmdfindsp_Click()
’查找商品,代码请参考“查找商品”
frmfindsp.Show 1
End Sub

Private Sub Cmdkc_Click()
’检测库存量
Dim db As Database
Dim rs As Recordset
Dim fieldspbh_value
Set db = OpenDatabase(App.Path & "jxc.mdb")
Set rs = db.OpenRecordset("即时库存")
While txtspbh <> fieldspbh_value And Not rs.EOF
fieldspbh_value = rs.Fields("商品编号").value
If fieldspbh_value = txtspbh Then
fieldspbh_value = rs.Fields("商品编号").value
Else
rs.MoveNext
End If
Wend
If fieldspbh_value = txtspbh Then
txtstore.Text = rs.Fields("数量").value
Else
MsgBox "库存中没有此类商品", vbInformation, "检测结果"
End If
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub


三:查找商品
.在销售管理中查找某商品的信息(frmfindsp),不应让用户手工输入商品的信息
.添加treeview控件,name属性为:tv
.添加textbox控件数组,name属性为:text1(0)-text(6),用来分别显示商品编号、商品名称、单价(元)、单位 、类别、质保期等必要的商品信息
.treeview.nodes.add(relative,relationship,key,text,image,selectedimage)参数解释如下:
relative,可选,node的索引或键值;
relationship,node的相应位置关系;
key,用item方法提取node的唯一字符串;
text,node显示的字符串;
image,图像索引(注:本例没有图像索引);
selectedimage,被选中时,与image控件相关联的图像索引。

relationship的值:
tvwfirst,0,第一个对象,该节点放在所有同级节点的前面;
tvwlast,1,最后一个;
tvwnext,2,(缺省)下一个,该节点放在relative命名的节点之后;
tvwprevious,3,前一个,该节点放在relative命名的节点之前;
tvwchild,4,子节点,为relative命名节点的子节点。

代码如下:

Dim db As Database, rs As Recordset, rs1 As Recordset, mynode As Node, newnode As Node
Private Sub Command1_Click()’此过程与销售管理呼应,将编号、名称及单价传递给frmxsgl窗体中。
frmxsgl.txtspbh.Text = Text1(0).Text
frmxsgl.txtspname.Text = Text1(1).Text
frmxsgl.txtdanjia.Text = Text1(2).Text
Unload Me
End Sub

Private Sub Form_Load()
’加载窗体后,根据商品表中的“类别”标记,将商品名称显示在treeview中,其它字段显示在textbox数组中,使用户能够清楚地查看需要出售的商品相关信息
Dim mysql$, mysqlone$
Set db = OpenDatabase(App.Path & "jxc.mdb")
mysql = "select * from 类别"
Set rs = db.OpenRecordset(mysql)
Set mynode = tv.Nodes.Add(, , "root", "商品分类")
While Not rs.EOF
Set newnode = tv.Nodes.Add("root", tvwChild, rs.Fields(1).value, rs.Fields(1).value)
mysql & "’" & newnode.Text & "’"
Set rs1 = db.OpenRecordset(mysqlone)
While Not rs1.EOF
Set newnode = tv.Nodes.Add(rs.Fields(1).value, tvwChild, rs1!商品名称, rs1!商品名称)
rs1.MoveNext
Wend
rs.MoveNext
Wend
tv.Nodes("root").Expanded = True
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
rs1.Close
Set rs1 = Nothing
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub

Private Sub tv_NodeClick(ByVal Node As MSComctlLib.Node)
On Error GoTo err
If Node.Children = 0 Then
mysql = "select * from 商品 where 商品名称 =" & "’" & Node.Text & "’"
Set rs = db.OpenRecordset(mysql)
For i = 0 To rs.Fields.Count - 1
If TypeName(rs.Fields(i).value) <> "" Then
Text1(i).Text = rs.Fields(i).value
End If
Next
End If
Exit Sub
err:
MsgBox err.Description
End Sub

四:查询记录(图二)
在进销存管理中,还应设有查询功能,包括进货、销售记录,现仅就查询进货记录为例,其它依此类推,还可进行更为复杂的查询。

添加控件:
data(data1)、msflexgrid(绑定至data1控件);
txtfind(文本框控件,用来保存SQL语句,visible属性为false)
三个combobox控件:name属性分别为:cmbfield、cmbcompare、cmbdata 作用为:欲查询的字段(如商品名称、进货时间等)、比较符号( >、<、=、like等);
四个按钮控件,name属性分别为:cmdjians(检索字段)、cmdfindnow(执行SQL语句)、cmdback(重画)cmdprint(打印记录集)

代码如下:
Public Sub makefind()
’添加此过程主要是为了解决SQL语句中的引号问题
txtfind = cmbfield & cmbcompare
Select Case Data1.Recordset.Fields(cmbfield.Text).Type
Case 10 ’ 文本
txtfind = txtfind & " ’" & txtdata & "’"
Case 8 ’ 日期
txtfind = txtfind & " #" & txtdata & "#"
Case Else
txtfind = txtfind & " " & txtdata
End Select
End Sub
Private Sub cmbcompare_Click()
makefind
End Sub

Private Sub cmbfield_Click()
makefind
End Sub

Private Sub cmdfindnow_Click()
If cmbfield.Text <> "" And cmbcompare <> "" And txtdata <> "" Then
Data1.RecordSource = "select * from 进货记录 where" & " " & txtfind.Text
Data1.Refresh
End If
End Sub

Private Sub cmdjinas_Click()
cmbfield.Clear
For i = 0 To Data1.Recordset.Fields.Count - 1
cmbfield.AddItem Data1.Recordset.Fields(i).Name
Next
cmbfield.ListIndex = 0
cmbcompare.Enabled = True
End Sub

Private Sub Cmdback_Click()
Data1.RecordSource = "进货记录"
Data1.Refresh
End Sub

Private Sub Form_Load()
Data1.DatabaseName = App.Path & "jxc.mdb"
Data1.RecordSource = "进货记录"
End Sub

Private Sub Form_Unload(Cancel As Integer)
Data1.Database.Close
Set Data1.Recordset = Nothing
End Sub

Private Sub txtdata_Change()
makefind
End Sub
private sub cmdprint()
Prnrecord(data1.recordset As Recordset)
’请见打印模块modprint
end sub

五:打印模块

.新建一标准模块modprint,以便其它窗体可以共享其过程,此模块只适用于DAO,特此说明:
Public Sub Prnrecord(recRecordset As Recordset)
On Error GoTo err
Dim LeftMargin As Integer
Dim HeadTopPosition As Integer
Dim FieldNum As Integer
Dim PageCounter As Integer
Dim MyRecordset As Recordset
Const FooterTopPosition = 24

Set MyRecordset = recRecordset
PageCounter = 1
Printer.ScaleMode = vbCentimeters
LeftMargin = 1.5
HeadTopPosition = 2
Printer.ScaleLeft = -LeftMargin
Printer.ScaleTop = -HeadTopPosition
Printer.Font.Name = "Times New Roman"
Printer.Font.Size = 12
Printer.Print "打印记录"
Printer.Print ""
If MyRecordset.EOF And MyRecordset.BOF Then
MsgBox "记录为空!", vbCritical + vbOKOnly, "打印错误,请核实后继续"
Exit Sub
End If
MyRecordset.MoveFirst
Do Until Printer.CurrentY > FooterTopPosition
For FieldNum = 0 To MyRecordset.Fields.Count - 1
Printer.Print MyRecordset.Fields(FieldNum).Name & ": " & _
MyRecordset.Fields(FieldNum).value
If Printer.CurrentY > FooterTopPosition Then
Printer.CurrentX = 8
Printer.Print "Page: " & PageCounter
Printer.NewPage
PageCounter = PageCounter + 1
End If
Next FieldNum
MyRecordset.MoveNext
If MyRecordset.EOF Then Exit Do
Printer.Print ""
Loop
Printer.CurrentX = 8
Printer.CurrentY = FooterTopPosition
Printer.Print "页: " & PageCounter
Printer.EndDoc

Exit Sub
err:
MsgBox err.Description
err.Clear
End Sub

六:财务管理(如图三)

我们根据统计出来的进货和销售记录可以进行简单的财务处理。如:在窗体上画三个DATA控件、MSFLEXGRID控件并依次进行绑定,用来显示一些基本数据。读者可以根据实际需要自行添加功能,当然前提是你精通SQL语句了。

Data1.DatabaseName = App.Path & "jxc.mdb"
Data1.RecordSource = "select count(商品名称)as 交易次数,sum(金额)as 进货金额, min(金额)as 最小金额,max(金额)as 最大金额 from 进货记录"
Data1.Refresh

Data2.DatabaseName = App.Path & "jxc.mdb"
Data2.RecordSource = "select count(商品名称)as 交易次数,sum(金额) as 销售金额, min(金额)as 最小金额,max(金额)as 最大金额 from 销售记录"
Data2.Refresh

Data3.DatabaseName = App.Path & "jxc.mdb"
Data3.RecordSource = "select sum(金额)as 应收 from 销售记录 where 支付方式=’欠付’"
Data3.Refresh

Data3.RecordSource = "select sum(金额)as 应收 from 进货记录 where 支付方式=’欠付’"
Data3.Refresh

Data3.RecordSource = "select sum(数量)as 总量 from 库存记录"
Data3.Refresh


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yyilin/archive/2005/09/20/485337.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yyilin/archive/2005/09/20/485337.aspx

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yyilin/archive/2005/09/20/485337.aspx


--  作者:yangming
--  发布时间:2010/3/9 22:19:00
--  
收藏,谢谢楼主!
--  作者:dm168
--  发布时间:2012/10/21 22:48:00
--  
好东丝,感谢
--  作者:zajhappy
--  发布时间:2012/10/22 8:29:00
--  
要是把实例也添加进来就更好了
--  作者:tbggbt
--  发布时间:2013/11/20 22:06:00
--  
要是哪位把这个实例转成foxtable就好了。
--  作者:zm6096
--  发布时间:2024/7/1 16:28:00
--  
感谢提供,学习下