本文测试文档下载地址:百度文库

随着义教均衡发展工作的稳步推进,要求学校功能室实行规范化管理。若有报废或新增等仪器设备变动,则必须重新制作柜签等报表。Excel是微软公司Microsoft office办公软件的组件之一,它具有强大的制表功能且界面友好,可方便灵活地手工制作各式各样的柜签报表。也可使用Excel内置的系统开发工具VBA(Visual Basic for Application)对Excel对象直接编程,高效快速地制作柜签报表。
面对Excel工作表内动辄上万的数据行,通过手工多次复制粘贴数据制作柜签报表显然太麻烦了;而使用VBA编程,若直接通过代码向指定单元格写入数据,并控制生成的柜签报表样式(如字体、边框、行高列宽等),生成的柜签报表样式固定单一,修改报表,就要修改程序代码。能否把手工制表的方便灵活与VBA编程的高效快速统一起来呢?答案显然是肯定的。
本文结合自己的工作经验,介绍一种基于EXCEL模板生成样式可变的柜签报表的VBA编程方法。先手工制作柜签报表模板,通过编程复制粘贴所需数量的模板,并把数据写入模板指定单元格中。修改报表的样式,只需手工修改或添加新模板,几乎不需要改动代码,使用方便,操作简单,容易实现。

一、设计模板


图 1 数据表
图1是从广西教育装备平台下载到的数据(以下称数据表),第1行为字段,第2行起的每一行为1种仪器设备的相关信息。

图 2 柜签效果图
图2是柜签效果图,划分为页眉、正文和页脚三个区域。页眉区位于柜签的顶部,作为柜签的描述性信息,概括性的说明柜签报表的名称、存放房间、存放柜子等;页脚区位于柜签的底部,用于说明柜签的其它信息,如学校主管领导、制表人、制表时间等信息;正文区是柜签的主体部分,用于填充仪器设备的相关信息,如编号、名称、规格等信息。

图 3 原始模板
如图3所示,原始模板设计区可包含页眉、正文和页脚三个区,页眉区包含在4个“@”号界定的区域(即多行多列)或2个“@”号界定的区域(即一行多列);正文区包含在4个“#”号界定的区域(即多行多列)或2个“#”号界定的区域(即一行多列);页脚区包含在4个“&”号界定的区域(即多行多列)或2个“&”号界定的区域(即一行多列)。
可以在@、#、&号界定的区域内写入文字和字段,并设置单元格格式(如数字、对齐、字体及边框等)、行高和列宽等。字段是数据表中的字段,字段单独放在一个单元格或合并的单元格中并用“[ ]”号括住。因为每种仪器设备的制表样式都一样,所以正文区仅制作了1种仪器设备的样式。

二、复制粘贴模板

1、清除原始模板里的字段及界定符

为了原始模板的完整性,可以把该模板复制到新的工作表。为了保证粘贴的数据保留原有的格式(包括行高列宽都不能变)。可以先整行使用Copy方法进行复制粘贴,这样就可以保证行高一同被复制;使用PasteSpecial方法选择性粘贴,参数Paste设置为xlPasteColumnWidths即可保证列宽一同被复制。
代码如下:

 '粘贴全部(除列宽外):主要目的是为了粘贴行高Worksheets("模板").Rows("1:8").Copy Worksheets("临时").Rows(1)'复制模板设计区Worksheets("模板").Range("A1:I8").Copy'选择性粘贴--列宽Worksheets("临时").Range("A1:I8").PasteSpecial xlPasteColumnWidths

循环模板设计区所有单元格,对存放字段和界定符的单元格执行“清除内容”操作。

 '循环模板设计区内的每一个单元格For Each Rng In Worksheets("模板").Range("A1:I8")'清除字段If Left(Rng.Value, 1) & Right(Rng.Value, 1) = "[]" ThenRng.Value = ""End If'清除界定符If Rng.Value = "@" Or Rng.Value = "#" Or Rng.Value = "&" ThenRng.Value = ""End IfNext


图4清除字段及界定符后的原始模板效果图

2、重组原始模板生成完整的柜签模板


图 5 完整的柜签模板效果图
将清除了字段和界定符后的原始模板按页眉、正文和页脚的顺序依次复制粘贴组合成完整的柜签模板,可以按前述方法确保粘贴的数据保留原有格式。代码如下:

 '复制粘贴页眉区******************'粘贴全部(除列宽外):主要目的是为了粘贴行高Worksheets("临时").Rows("1:4").Copy Worksheets("报表").Rows(1)'********************************'复制粘贴正文区******************'用变量intTextCount记录用户输入的数量intTextCount = InputBox(Prompt:="请输入需复制正文区的数量", Title:="操作提示", Default:="10")'粘贴全部(除列宽外),行数由用户输入的正文区数量决定Worksheets("临时").Rows(5).Copy Worksheets("报表").Rows("5:" & 4 + intTextCount)'复制模板正文区Worksheets("临时").Range("B5:I5").Copy'选择性粘贴--列宽,扩展的行列数由正文区数量及模板正文区的行列数决定Worksheets("报表").Cells(5, "B").Resize(intTextCount, 7).PasteSpecial xlPasteColumnWidths'********************************'复制粘贴页脚区******************'粘贴全部(除列宽外):主要目的是为了粘贴行高Worksheets("临时").Rows("7:8").Copy Worksheets("报表").Rows(5 + intTextCount)'********************************

代码巧用InputBox函数实现人机交互,根据用户的输入准确选取粘贴区域,实现一次性复制多份正文区:粘贴区域的行数=模板正文区行数×行向份数,粘贴区域的列数=模板正文区列数×列向份数。比如本例正文区为1行7列,按图2柜签需要行向10份(用变量intTextCount表示)/列向1份共10份粘贴正文区,则粘贴区域应为1行×10份=10行、7列×1份=7列,即10行7列的区域,所以粘贴区域为Cells(5, “B”).Resize(intTextCount, 7)。生成完整的柜签模板如图5所示。

3、批量生成柜签模板


图 6 批量生成柜签模板效果图
如图6所示,可以参考仿照前述代码一次性复制粘贴多个柜签,并保证粘贴的数据保留原有格式,代码如下:

 '用变量intTemplateColumnCount记录用户输入的模板列向份数intTemplateColumnCount = InputBox(Prompt:="请输入需复制的模板列向份数", Title:="操作提示", Default:="2")'由程序自行统计(统计过程省略)并用变量intTemplateRowCount记录模板行向份数intTemplateRowCount = 5'粘贴行高,粘贴区域由变量intTemplateRowCount决定Worksheets("报表").Rows("1:16").Copy Worksheets("报表").Rows("1:" & 16 * intTemplateRowCount)'复制模板:单元格区域为A1:H16Worksheets("报表").Range("A1:H16").Copy'选择性粘贴--列宽,扩展的行列数由模板行、列向份数及模板行、列数决定Worksheets("报表").Cells(1, "A").Resize(16 * intTemplateRowCount, 8 * intTemplateColumnCount).PasteSpecial xlPasteColumnWidths

代码继续通过最简单的人机交互函数InputBox,在程序运行时弹窗提示输入“模板列向份数”,以适应不同的页面设置。同时把输入值赋值给变量intTemplateColumnCount,由程序自动统计的“模板行向份数”赋值给变量intTemplateRowCount,而本例柜签模板单元格区域(A1:H16)为16行8列(实际程序可用变量引用该行列数),所以粘贴区域为Cells(1, “A”).Resize(16 * intTemplateRowCount, 8 * intTemplateColumnCount)。

三、向报表里的柜签模板填充数据

使用AdvancedFilter方法筛选数据(比如以存放柜子为条件筛选),在报表中明确填充该数据的单元格区域,通过For循环,用筛选出的相应数据替换“[ ]”号括住的字段。以填充正文区数据为例,代码如下:

 '记录字段:写入模板的单元格行列号及数据表中的列号'字段:物品编号Arr(1, 1) = 1 '写入模板正文区的行号Arr(2, 1) = 2 '写入模板正文区的列号Arr(3, 1) = 1 '数据表中的列号'字段:名称Arr(1, 2) = 1 '写入模板正文区的行号Arr(2, 2) = 3 '写入模板正文区的列号Arr(3, 2) = 2 '数据表中的列号……'记录筛选条件Worksheets("临时").Range("M1").Value = "存放柜子"Worksheets("临时").Range("M2").Value = "柜子20"'高级筛选出所需要的数据Worksheets("数据表").UsedRange.AdvancedFilter Action:=xlFilterCopy, _CriteriaRange:=Worksheets("临时").Range("M1:M2"), _CopyToRange:=Worksheets("临时").Range("A1"), Unique:=False'统计并得出要写入上述筛选数据的柜签模板数量intCount = 3'向数量为intCount的柜签模板所在的单元格区域写入数据R = ((intCount - 1) \ intTemplateColumnCount) * 16 + 1 '起始行号L = ((intCount - 1) Mod intTemplateColumnCount) * 8 + 1 '起始列号With Worksheets("报表").Cells(R, L).Resize(16, 8)For j = 1 To intTextCountFor i = 1 To UBound(Arr, 2).Cells(j + 3 + Arr(1, i), Arr(2, i)).Value = Worksheets("临时").Cells(j + 1, Arr(3, i)).ValueNext iNextEnd With

代码用数组Arr记录字段在柜签模板中的行列号及数据表中的列号,巧借字段架起柜签模板与数据表之间交互数据的桥梁,向柜签模板里填充数据时,根据数组Arr记录的行列号,可以很方便的把“[ ]”号括住的字段用数据表中同名字段对应行的数据进行替换。

图 7 巧用数学方法确定单元格行列号
代码还巧用数学方法确定填充数据的单元格区域。为方便说明问题,我把报表中的柜签模板简化为只占用一个单元格并按图7所示顺序编号,则其行列号可用公式计算:行号=(单元格编号-1)\ 列向份数 + 1、列号=(单元格编号 - 1) Mod 列向份数 + 1。如编号为18的单元格,其行号=(18-1)\ 5 + 1 = 4,列号=(18-1) Mod 5 + 1 =3,与实际吻合。根据柜签模板区的行列数(16行8列,实际程序中用变量调用)相应扩展即可计算编号为intCount柜签模板起始行列号:行号R = ((intCount - 1) \ intTemplateColumnCount) * 16 + 1 、列号L = ((intCount - 1) Mod intTemplateColumnCount) * 8 + 1。

四、修改柜签报表样式

柜签报表的样式不可能永恒不变,随着时间的推移、不同人员审美的差异,我们总是希望柜签报表的样式也能随之而改变。可以随时手工修改或添加模板并保证模板里的字段与数据表字段相对应,同时配合修改“模板列向份数”和“正文区份数”即可修改柜签报表的样式,而无须修改程序代码。
打印纸已设置了表格边框及标题,只需把数据套打到打印纸上,可以按图8所示设计模板。把正文区份数设置为1,可利用二维码控件(如QRMaker)生成包含二维码的物签(定位签)报表,如图9所示,“{}”号括住的字段用数据表中同名字段对应行的数据生成二维码。

图 8 生成柜签套打报表效果图

图 9 物签(定位签)报表效果图
不管是柜签报表还是物签(定位签)报表,生成报表的编程代码是相同的,不同之处在于模板的设计。使程序员从繁琐的编程工作中解放出来,把柜签等报表的样式决定权交给使用者,即把复杂的编程工作变成简便灵活的模板制作。既满足了我们对柜签、物签等报表样式多样化的需求,又大大减少了工作量,非常实用。

在VBA编程中巧用EXCEL模板生成样式可变报表相关推荐

  1. Excel与VBA编程中的常用代码

    Excel与VBA编程中的常用代码 用过VB的人都应该知道如何声明变量,在VBA中声明变量和VB中是完全一样的! 使用Dim语句 Dim a as integer '声明A为整形变量 Dim a '声 ...

  2. JXls实现基于excel模板生成报表

    JXls实现基于excel模板生成报表 jxls是非常小巧方便生成excel报表的工具库.jxls在excel模板中使用特定标记,定义输出格式和数据布局.在很多应用中有报表功能需要生成excel. j ...

  3. SpringBoot中使用Freemarker邮件模板生成邮件

    SpringBoot中使用Freemarker邮件模板生成邮件 当邮件内容比较简单的时候,我们可能一行字符串就能表达所有意思了,但是大部分情况下,我们的邮件内容都比较复杂需要用HTML来组织邮件内容, ...

  4. vba 修改access表的链接地址_神奇的VBA编程:禁止修改Excel工作表名称

    职场中经常需要将做好的Excel表格/模板发给他人或者存放在公共路径上共享使用,此时需要禁止别人更改已经设定好的工作表名称.或者某些工作簿中有公式使用了对某些工作表的外部引用,如果工作表名称发生变化, ...

  5. VBA编程中常用过程代码

    VBA编程常用过程代码方案,供大家写代码参考,陆续发表: VBA过程代码6:返回当前单元格的位移 Sub MyNZ() on error resume next ActiveCell.Offset(0 ...

  6. python excel模板 生成excel表格_python制作简单excel统计报表3之将mysql数据库中的数据导入excel模板并生成统计图...

    python制作简单excel统计报表3之将mysql数据库中的数据导入excel模板并生成统计图 #coding=utf-8 from openpyxl importload_workbookfro ...

  7. C#根据word模板生成word表格报表文档

    主要功能为根据word模板生成word报表文档,注意引用Interop.Word.dll; 首先要生成word程序对象 Word.Application app = new Word.Applicat ...

  8. springboot中的下载excel模板

    文件放在resource下面 然后下载工具类代码: @Slf4j public class ExcelTemplateUtil {/*** 下载模板文件* @param response* @para ...

  9. VBA编程中的 sheet1 与 sheets(1)的区别

    [自己理解]sheet1是一个专有名词,不是任何对象的属性,只能单独使用,特指代码所在工作簿的那个sheet1(和顺序无关,是固定的一个表,sheets(1)则和顺序有关). 参考资料: 1.代码中一 ...

最新文章

  1. 顶尖学者加盟!两所C9高校,获强援!
  2. 为什么每个函数都要测试
  3. Spring Boot 2.0(七):Spring Boot 如何解决项目启动时初始化资源
  4. 记一次vue+vuex+vue-router+axios+elementUI开发(二)
  5. Unable to find required classes (javax.activation.DataHandler and javax.mail.internet.MimeMultipart)
  6. CentOS7.1下targetcli的使用
  7. 基于阿里云服务器使用宝塔面板搭建 Typecho 博客
  8. 【系统分析师之路】如何备考系统分析师与架构师(软件水平考试)
  9. Fragstats|单一土地利用类型景观格局指数
  10. 手机怎样刷机解锁android,安卓手机解锁是什么意思 安卓手机刷机知识介绍【图文】...
  11. LifecycleBeanPostProcessor的作用
  12. 如何在电脑上用Win11便签备忘录提醒重要工作
  13. 【设计模式】用英雄联盟来解释代理模式
  14. 7-40 奥运排行榜
  15. 【蓝牙sbc协议】sbc源码阅读笔记(三)——数据读写过程
  16. 马里兰大计算机专业学phd博士,亚利桑那州立大学计算机CS博士PHD全奖录取
  17. html模仿原生ios通讯录制作国家展示页(手机端)
  18. 【STM32】STM32F103ZE程序修改改为STM32F103C8步骤
  19. 毛毛雨的博客乐园—内容简介
  20. 避开有道云笔记的充值会员上传图片

热门文章

  1. 人脸识别之Face++
  2. 诚之和:5个目前最热门岗位的IT岗位,你是哪个?
  3. pandas 第十章 时序数据
  4. 美赛资源查找指南(内含看英文文献翻译利器)
  5. flex form formitem
  6. 改:如何基于开源项目做二次开发
  7. 【论文阅读】Progressive Image Deraining Networks: A Better and Simpler Baseline
  8. 怎么压缩PDF为目标大小?压缩方法介绍
  9. php竞彩足球源码,图书馆管理系统代码 足球联赛系统代码
  10. pthon核心编程-读书笔记:知识点摘录与总结(方便理解和快速记忆)