Excel VBA:一键复制、连续生成打印模板与代码提速

admin 办公 2023-12-19 10:17 137

本文于2023年7月21日首发于本人同名公众号:Excel活学活用,更多文章案例请搜索关注!

内容提要

  • 数据批量填充打印模板
  • 提高代码运行速度

大家好,我是冷水泡茶,今天在EXCELHOME论坛上看到一个网友求助贴:

他的原表是这样:

他的要求这样:

希望做成这样,下面顺序排列,把所有记录都按相同的格式填充进打印模板:

关于批量打印问题,我们在前期文章中分享过凭证打印、收费单打印,并且在中医诊所收费系统中也有打印的方法!

我们分享的方法是直接循环打印单据,而今天楼主的需求是把需要打印的数据集中到一张EXCEL表上,然后再打印。

我看了一下数据,感觉应该不是很难搞,但由于这两天比较忙,加之看到有好几位网友都发了结果,也就没有动手。

虽然我没做,但不防碍我下载他们的成果学习学习,于是下了几个看了一下,基本逻辑都差不多,都是复制模板,粘贴,再填写数据。这里复制粘贴是为了保持每一条记录的打印格式相同。

本来准备就这样算完,但看到楼主发贴说,结果是不错,但就是运行速度有点慢!

这引起了我的注意,我仔细分析了一下,感觉可能就是这种不断地复制、粘贴比较花时间,我试着运行了一下他们的代码,大多要10几秒。

于是,我就想,要不我来想办法看能不能提高一下运行速度?

捣鼓了半天,终于将运行速度缩短到1秒多点,我觉得也是有那么一点借鉴的意义的,我们一起来看一下吧:

基本思路

1、设置模板格式:

设置打印表的第一行到第13行格式,作为模板格式以备复制,以保持格式统一。

2、复制格式:

原来他们是采用每条记录复制、粘贴一次,我改为一次性复制、粘贴。

3、调整行高:

复制、粘贴保持了大部分格式,但是行高改变了。我把模板第1~13行的行高存到数据arrHeight里,通过循环把所有对应模板的行高设置成一样。

4、写入数据,这里的代码我基本没有改动。

模块代码

Sub 打印()

Public Sub 打印()    t = Timer    Dim arr    Dim ws As Worksheet    Dim i As Integer, j As Integer, lastRow As Integer    Dim sourceRange As Range    Dim targetRange As Range    Dim arrHeight()    Application.ScreenUpdating = False    Set ws = Sheets("打印")    ws.Activate    Set sourceRange = ws.Range(Cells(1, 2), Cells(13, 4))    ReDim arrHeight(1 To 13)    sourceRange.ClearContents    For i = 1 To sourceRange.Rows.Count        arrHeight(i) = sourceRange.Rows(i).RowHeight    Next    ws.Range("14:" & ws.UsedRange.Rows.Count).Clear    lastRow = Sheets("汇总表").Range("A" & Rows.Count).End(3).Row - 1    Set targetRange = ws.Range(Cells(14, 2), Cells(lastRow * 13 - 13, 4))    sourceRange.Copy    targetRange.PasteSpecial xlPasteFormats    For i = 1 To targetRange.Rows.Count        targetRange.Rows(i).RowHeight = arrHeight(((i - 1) Mod 13) + 1)    Next    arr = Sheets("汇总表").Range("A1:Q" & lastRow).Value    For i = 2 To lastRow        ws.Cells((i - 2) * 13 + 1, "B").Value = arr(i, 1) '车次列        r = 2        For j = 1 To 8            If arr(i, 3 + j) > 0 Then                ws.Cells((i - 2) * 13 + r, "B") = arr(1, j + 3) '产品名称                ws.Cells((i - 2) * 13 + r, "C") = arr(i, j + 3) '产品数量                r = r + 1            End If        Next        ws.Cells((i - 2) * 13 + 2, "D").Value = arr(i, 16)  '新旧库        ws.Cells((i - 2) * 13 + 6, "D").Value = arr(i, 2)  '发生时间        ws.Cells((i - 2) * 13 + 10, "B").Value = "箱数:" & arr(i, 14) & "/" & arr(i, 15) '箱号/箱数        ws.Cells((i - 2) * 13 + 11, "B").Value = "日期:" & Format(arr(i, 17), "m/d/yyyy") '日期    Next    [A1].Select    ThisWorkbook.Save    Application.ScreenUpdating = True    MsgBox "耗时:" & Timer - tEnd Sub

代码解析:

1、line6~8:我设置了三个变量sourceRange源区域,用来复制模板格式targetRange目标区域,用来表示从第14行到结束的打印区域,arrHeight存放模板行高。

2、line12:设定源区域,也就是打印模板区域。

3、line14:把源区域的内容先清空。

4、line15~17:把模板的行高存起来。

5、line20~25:设置目标区域,把源区域复制到目标区域。设置目标区域的行高,至此,打印模板的格式基本统一了。

6、下面就通过循环,把数据写入工作表。

总结

1、频繁复制、粘贴会影响代码运行速度,我们要设法一次性复制、粘贴,这就是我今天采用的方法。

2、大量的写入单元格也很耗时,应尽量采用数组一次性写入工作表。本来今天我是想用数组一次性写入的,但由于打印模板中有合并单元格,没法搞,就算了。

正文完

喜欢就点个赞、点在看、留个言呗!

本文于2023年7月21日首发于本人同名公众号:Excel活学活用,更多文章案例请搜索关注!

相关推荐
关闭

用微信“扫一扫”