
本文于2023年9月11日首发于本人同名公众号:Excel活学活用,更多文章案例请搜索关注!
内容提要
销货小票批量打印代码解析
VBA代码
1、在UserForm1里,UserForm_Initialize窗体初始化:
Dim arr()Dim LvItem As ListItemDim tbTitle()Dim arrPrice()Private Sub UserForm_Initialize() Dim ws As Worksheet Dim lastRow As Integer, lastCol As Integer Dim iWidth() Set ws = ThisWorkbook.Sheets("打印数据") With ws .Activate lastRow = .UsedRange.Rows.Count lastCol = .UsedRange.Columns.Count arr = ws.Range(Cells(2, 3), Cells(lastRow, lastCol)).Value End With k = 0: m = 0 For i = 1 To UBound(arr, 2) If arr(1, i) <> "" Then ReDim Preserve tbTitle(k) tbTitle(k) = arr(1, i) k = k + 1 End If If arr(2, i) <> "" Then ReDim Preserve arrPrice(m) arrPrice(m) = arr(2, i) m = m + 1 End If Next tbTitle(0) = "下单时间" tbTitle(1) = "下单地区" tbTitle(4) = "送货地址" tbTitle(10) = "商品总价" tbTitle(11) = "备注说明" tbTitle(12) = "支付状态" iWidth = Array(60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 30) For i = 0 To UBound(tbTitle) Me.LvDetail.ColumnHeaders.Add , , tbTitle(i), iWidth(i) Next With Me.LvDetail .View = lvwReport .Gridlines = True '.Sorted = True .CheckBoxes = True .LabelEdit = lvwManual .FullRowSelect = True .ForeColor = vbBlue End With For i = 3 To UBound(arr) If arr(i, 1) <> "" Then Set LvItem = Me.LvDetail.ListItems.Add LvItem.Text = arr(i, 1) For j = 1 To Me.LvDetail.ColumnHeaders.Count - 1 LvItem.SubItems(j) = arr(i, j + 1) Next End If NextEnd Sub
代码解析:
(1)Line1~4,定义模块级数组arr,tbTitle,arrPrice用来存放明细订单、表头字段、单价。
(2)line10~15,把“打印数据”表存入数组arr。
(3)line17~28,循环数组arr,把表头字段存入tbTitle,单价存入arrPrice。
(4)line29~34,“打印数据”表字段与“小票模板”字段不一致,进行调整。
(5)line35,一个设置宽度数值的数组,要改变ListView字段的显示宽度,在这里调整。
(6)line36~38,设置ListView的表头字段。
(7)line39~47,设置ListView的属性。
(8)line48~56,把arr中的数据添加到ListView。
2、在UserForm1里,CmdPrint打印按钮点击事件:
Private Sub CmdPrint_Click() On Error Resume Next Dim pos1 As Integer, pos2 As Integer Dim num As Integer, arrStr() Dim ws As Worksheet, wsPrint As Worksheet Set ws = ThisWorkbook.Sheets("小票模板") Set wsPrint = ThisWorkbook.Sheets("Print") pos1 = Pxy(tbTitle, "主机") pos2 = Pxy(tbTitle, "音箱") With Me.LvDetail For i = 1 To .ListItems.Count If .ListItems(i).Checked Then k = k + 1 End If Next If k = 0 Then MsgBox "未勾选任何小票!" Exit Sub End If If Not wContinue("即将打印所选小票!") Then Exit Sub If Application.Dialogs(xlDialogPrinterSetup).Show = False Then Exit Sub End If For i = 1 To .ListItems.Count If .ListItems(i).Checked Then num = 0 For j = pos1 To pos2 If Len(.ListItems(i).SubItems(j - 1)) > 0 Then num = num + 1 End If Next memo = .ListItems(i).SubItems(Pxy(tbTitle, "备注说明") - 1) wsPrint.Cells.Clear ws.Range("B2:D14").Copy Destination:=wsPrint.Range("B1") wsPrint.Cells(3, 3) = .ListItems(i).Text For j = 2 To 13 itemname = Replace(wsPrint.Cells(j, 2), ":", "") ipos = Pxy(tbTitle, itemname) If j <> 3 And j <> 8 And j <> 9 Then wsPrint.Cells(j, 3) = .ListItems(i).SubItems(ipos - 1) End If Next If num > 0 Then If num > 1 Then wsPrint.Rows(10 & ":" & 10 + num - 2).Insert Shift:=xlDown End If k = 0 For j = pos1 To pos2 If Len(.ListItems(i).SubItems(j - 1)) > 0 Then wsPrint.Cells(9 + k, 2) = tbTitle(j - 1) wsPrint.Cells(9 + k, 3) = arrPrice(j - pos1) wsPrint.Cells(9 + k, 4) = .ListItems(i).SubItems(j - 1) k = k + 1 End If Next wsPrint.PrintOut Copies:=1 Application.Wait Now + TimeSerial(0, 0, 0.5) ElseIf Len(memo) > 0 Then For j = pos1 To pos2 If InStr(memo, tbTitle(j - 1)) Then ReDim Preserve arrStr(num) arrStr(num) = tbTitle(j - 1) num = num + 1 End If Next If num > 1 Then wsPrint.Rows(10 & ":" & 10 + num - 2).Insert Shift:=xlDown End If For j = LBound(arrStr) To UBound(arrStr) wsPrint.Cells(9 + j, 2) = arrStr(j) wsPrint.Cells(9 + j, 3) = arrPrice(Pxy(tbTitle, arrStr(j)) - pos1) Next wsPrint.PrintOut Copies:=1 Application.Wait Now + TimeSerial(0, 0, 0.5) End If End If Next End With MsgBox "打印完毕!" Unload MeEnd Sub
代码解析:
(1)Line3~5,定义一些变量、数组、工作表对象等。
(2)line8~9,取得第一个与最后一个商品名称的位置。
(3)line11~19,判断是否勾选订单记录。
(4)line21~23,选择打印机,如果取消则退出程序。
(5)line27~31,统计订单商品的种类数。
(6)line32,备注字段的值。
(7)line33~42,清除工作表“Print”的内容,根据小票模板中的字段,把当前订单的相应字段值填入打印模板。
(8)line43~57,如果订单有数量,如果商品种类数大于1,则插入行。再循环商品名称,查找有数量的记录,把商品名称、单价、数量填入打印模板。打印。
(9)line58~74,如果订单商品的种类数为0,但备注有内容,则检查备注字段中商品名称的种类数,写入一个数组arrStr。如果商品种类数大于1,同样地,需要插入记录。循环arrStr,把商品名称写入打印模板,把其对应的单价写入打印模板。打印。
3、在UserForm1里,全选、退出按钮及两个自定义函数:
Private Sub CmdSelectAll_Click() With Me.LvDetail If Me.CmdSelectAll.Caption = "全选" Then For i = 1 To .ListItems.Count .ListItems(i).Checked = True Next Me.CmdSelectAll.Caption = "全消" Me.CmdSelectAll.BackColor = RGB(176, 224, 230) Else For i = 1 To .ListItems.Count .ListItems(i).Checked = False Next Me.CmdSelectAll.Caption = "全选" Me.CmdSelectAll.BackColor = RGB(143, 188, 143) End If End WithEnd SubPrivate Sub CmdExit_Click() Unload MeEnd SubFunction Pxy(arr() As Variant, searchValue As Variant) As Long t = LBound(arr) t = 1 - t For i = LBound(arr) To UBound(arr) If arr(i) = searchValue Then Pxy = i + t Exit Function End If Next Pxy = -1 ' 如果未找到值,则返回 -1End FunctionFunction wContinue(Msg) As Boolean '确认继续函数 Dim Config As Long Config = vbYesNo + vbDefaultButton2 + vbQuestion Ans = MsgBox(Msg & Chr(10) & "是(Y)继续?" & Chr(10) _ & "否(N)返回!", Config, "请确认操作!") wContinue = Ans = vbYesEnd Function
代码解析:
(1)Line1~17,CmdSelectAll按钮点击事件,按钮的Caption在“全选“、”全消“,之间切换,同时ListView的Listitems也相应地在“全部不选”和“全部选中”的状态之间切换,方便选择。这段代码直接复制以前案例中的代码,修改一个Listview的Name即可。
(2)line19~21,退出用户窗体。
(3)line23~33,数组元素字段定位函数,这个函数在我们的案例中使用得也非常多,直接复制过来。这个函数的方便之处是,我们可以根据字段名称取得其位置,作为数组、ListView的Subitems的下标,不用到表格中去数数,另外,即便表格字段的位置发生变化,我们的程序代码也可以不用修改。
(4)line35~42,确认继续函数,防止误操作,给一个反悔的机会。这个函数本身没有太大的实质性作用,但是增加的程序的灵活性。这个函数我们也用得比较多。
4、在工作表“打印数据”里,打印命令按钮:
Private Sub CmdPrint_Click() UserForm1.ShowEnd Sub
代码解析:启动用户窗体。
~~~~~~End~~~~~~
喜欢就点个赞、点在看、留个言、分享呗!感谢!