本文以设计一个进销存管理系统为例来说明如何通过VBA二次开发一个Excel应用程序。
1 系统描述进销存管理系统主要包括进货、销售、库存和数据管理等模块,如下图所示:
2 用户界面:表格设计或窗体设计
针对上面的模块的相应功能,可以通过输入、输出用户窗体或工作表作来用户界面来实现。
3 设计功能区的XML功能区可以通过使用XML代码进行精细设置。
3.7 在工作簿文件与xml文件建立关系:
在压缩文件的_rels文件夹内的.rles文件中添加以下内容(添加到最后一个Relationship标记前):
<Relationship Id="customUIRelID"
Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" Target="customUI/customUI.xml"/>
3.8 保存并关闭.rles文件;
3.9 将压缩文件改回到工作簿:将“进销存管理.xlsm.zip"重命名为“进销存管理.xlsm"即可。
3.10 打开“进销存管理.xlsm”,即可看到如下自定义选项卡的工作界面:
2 设计功能区各按钮代码
2.1 按快捷键Alt F11打开VBE环境;
2.2 增加一个标准模块:插入→模块;
2.3 定义一个全局变量:
Option Explicit
Public Const AppName As String = "进销存管理系统"
2.4 “进货”组中有两个按钮,用来操作进货录入和进化报表两个功能,具体的代码如下:
Sub btIN_INPUT_onAction(Control As IRibbonControl) '进货录入
Sheets("供货单").Select '选择"供货单"工作表
Range("b5").Select '选择B5单元格
End Sub
Sub btIN_REPORT_onAction(Control As IRibbonControl) '进货报报
Sheets("进货报表").Select '选择"进货报表"工作表
Range("C2").Select '选择C2单元格
End Sub
其它模块的按钮的代码按上述思想同样设置。
3 输入界面数据保存到工作表的代码设计在“进货”模块,可以使用工作表“供货单”录入进货数据,录入的数据保存到“供货”工作表中。
3.1 设计“供货单”工作表
此输入界面可以是用户窗体,也可以是工作表。
3.2 设计“保存”代码
当用户输入好供货商品信息后,单击“保存”控件即可将输入的数据保存到“供货”工作表中,代码如下:
Sub 保存供货信息()
Dim x As Integer, i As Integer, j As Integer
Call 手动计算
With Sheets("供货")
.Unprotect Password:="wyg"
x = 2 '从第2行开始
'判断第2列的最后一行(即空行的上一行)
Do While Not (IsEmpty(.Cells(x, 2).Value))
x = x 1 '在最后一行加一行即为空行
Loop
End With
With Sheets("供货单")
For i = 1 To 8
If Not IsEmpty(.Cells(5 i, 2)) Then
Sheets("供货").Cells(x, 1) = .Cells(3, 9) '时间
Sheets("供货").Cells(x, 1).NumberFormatLocal = "yyyy-m-d h:mm;@"
Sheets("供货").Cells(x, 11) = .Cells(3, 3) '供应商
For j = 2 To 10
Sheets("供货").Cells(x, j) = .Cells(5 i, j)
Next j
x = x 1
End If
Next i
'清除供货单中的数据
.Range("b6:b13") = ""
.Range("i6:i13") = ""
.Select
End With
Call 自动计算
With Sheets("供货").Range("A1").CurrentRegion
.Borders.LineStyle = xlContinuous
.Borders.Weight = xlThin
End With
Sheets("供货").Protect Password:="wyg"
End Sub
其它模块的保存的相应代码可以按上述思想分别设置。
4 报表输出代码设计当用户在功能区“进销存”选项卡的“进货”组中,单击“报表”按钮时,将显示进货报表。在该报表中由用户输入统计的起止日期,程序将按时间段统计所有进货的情况,生成进货报表。
为“生成报表”按钮指定宏,并编写宏代码如下:
Sub 进货报表()
Dim datStart As Date, datEnd As Date
If IsDate(Cells(2, 3)) Then
datStart = DateValue(Cells(2, 3))
Else
MsgBox "日期输入错误"
Exit Sub
End If
If IsDate(Cells(2, 5)) Then
datEnd = DateValue(Cells(2, 5))
Else
MsgBox "日期输入错误"
Exit Sub
End If
If datStart > datEnd Then
MsgBox "起始日期应小于或等于结束日期"
Else
生成进货报表
End If
End Sub
Sub 生成进货报表()
Dim x As Integer, j As Integer, rngTemp As Range
Dim intRow As Integer
Sheets("供货").Unprotect Password:="wyg"
Set rngTemp = Sheets("供货").Range("A2").CurrentRegion
rngTemp.Sort Key1:=Sheets("供货").Range("A2"), Order1:=xlAscending, Header:= _
xlGuess, OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
SortMethod:=xlPinYin, DataOption1:=xlSortNormal
Sheets("供货").Protect Password:="wyg"
With Sheets("进货报表")
.Activate
.Unprotect Password:="wyg"
intRow = .Range("A4").CurrentRegion.Rows.Count
.Range(.Cells(5, 1), .Cells(intRow 4, 10)).EntireRow.Delete
.Range("A5").Select
x = 2
j = 5
Do While Not (IsEmpty(Sheets("供货").Cells(x, 2).Value))
If DateValue(Sheets("供货").Cells(x, 1)) >= DateValue(.Cells(2, 3)) And _
DateValue(Sheets("供货").Cells(x, 1)) <= DateValue(.Cells(2, 5)) Then
.Cells(j, 1).NumberFormatLocal = "yyyy-m-d h:mm;@"
.Cells(j, 1) = Sheets("供货").Cells(x, 1) '日期
.Cells(j, 2) = Sheets("供货").Cells(x, 2) '货号
.Cells(j, 3) = Sheets("供货").Cells(x, 3) '名称
.Cells(j, 4) = Sheets("供货").Cells(x, 4) '型号
.Cells(j, 5) = Sheets("供货").Cells(x, 5) '产地
.Cells(j, 6) = Sheets("供货").Cells(x, 9) '数量
.Cells(j, 7).NumberFormatLocal = "#,##0.00_ "
.Cells(j, 7) = Sheets("供货").Cells(x, 6) '进价
.Cells(j, 8).NumberFormatLocal = "#,##0.00_ "
.Cells(j, 8) = .Cells(j, 6) * .Cells(j, 7) '金额
.Cells(j, 9).NumberFormatLocal = "#,##0.00_ "
.Cells(j, 9) = Sheets("供货").Cells(j, 7) '批发价
.Cells(j, 10).NumberFormatLocal = "#,##0.00_ "
.Cells(j, 10) = Sheets("供货").Cells(j, 8) '零售价
j = j 1
End If
x = x 1
Loop
.Cells(j, 1) = "合计"
.Cells(j, 8).NumberFormatLocal = "#,##0.00_ "
.Cells(j, 8).FormulaR1C1 = "=SUM(R[" & 5 - j & "]C:R[-1]C)"
.Range(.Cells(5, 1), .Cells(j, 10)).Select
设置边框
' .Select
.Range("A5").Select
.Protect Password:="wyg"
End With
End Sub
其它模块的报表的相应代码可以按上述思想分别设置。
-End-
,