分享

入门必学 VBA批量合并拆分单元格

 郑广学老师 2021-10-31

本技巧的目的:掌握单元格合并,拆分,求和的方法。

  • 用代码合并单元格后的效果

  • 用代码拆分单元格后的效果

  • 如果需要在拆分后将原有的文字全部保留,在单元格中实现是很麻烦的一件事,但使用VBA代码形式很简单。

代码助手实现代码快速输入

  • 代码助手下载地址 http:///blog/archives/11297

  • 只要在代码区输入中文:合并+空格 就会弹出相应的代码 以供选择

  • 使用代码助手还能够随时收录自己需要的代码:

如何判断单元格区域是否存在合并单元格

  • 代码如下:

  • 注释:

  • 使用 Range.MergeCells 属性 检查 单元格中是否包含合并单元格

  • 可以使用立即窗口来测试一下三个不同的结果:

  • 当有合并单元格时,返回的结果为 True

  • 当没有合并单元格时,返回的结果为 False

  • 当混合二个不同类型的单元格时,返回的结果为 Null

  • 代码的书写就是根据三种不同的返回值来书写

  • Selection.MergeCells = True  '有合并单元格

  • IsNull(Selection.MergeCells)  '检查变量值是否为 Null ,即是否混合二种格式的单元格

  • Else '最后为无合并的单元格

  • IsNull 函数的 示例 1:

  • Dim 值, 检查结果

  • 检查结果 = IsNull(值)

  • '因为值是空值,则:检查结果 = False。

  • 示例 2:

  • 值 = ""

  • 检查结果 = IsNull(值)

  • '因为值设置为空值,则:检查结果= False。

  • 示例 3:

  • 值 = Null

  • 检查结果 = IsNull(值)

  • '值设置为:Null 则:检查结果 = True。

  • 将上面的代码修改一下就变成通用的函数了,这样可以方便随时调用

  • 注释:

  • 一般子函数, 只要不需要外部调用, 无论是否有返回值, 都可以使用 function 语句

  • 括号内的 r 为外部传入的参数,外部传入时可以不使用 r 这个变量, 可以任意名称, 只要类型与当前子函数相符即可

  • 参数传入后, 无论外部是什么名称, 当前过程会自动转换为 r 。参数 r 可以直接在当前过程中使用,不需要声明

  • 如果要返回结果, 函数名称需要写上等于哪个值, 即: 判断合并单元格 = s

  • 子函数写好后,直接调用就可以出来结果:

合并单元格时能够连接每个单元格的文本的方法

  • 合并前:

  • 合并单元格的代码:

  • 注释:

  • 先将原单元格的内容全部用连接的方式记录下来

  • 合并单元格:rng.Merge

  • s = s & "," & r  '第1次连接时 s 为空值, 结果变成 ,453, 后面的连接是正常的: ,453,189.... 如上图

  • rng = Mid(s, 2) '使用 Mid 去掉第1个 , 逗号

  • WrapText 属性:所有单元格中的文本都自动换行,返回 True;都不自动换行,返回 False;有些单元格中的文本自动换行,有些不自动换行,返回 Null

  • 同样的,修改成子函数,方便后续调用:

  • 执行前:

  • 执行后:

  • 注释:

  • 把三个地址放入数组:"A1:A4", "C3:C5", "E6:E8"

  • 调用子函数--合并单元格所有内容, 执行合并单元格的操作

  • Function 合并单元格所有内容(rng As Range),括号内的 rng 是外部传入的参数

  • 子函数的优点:主函数不需要每次都写一大段代码,可以通过传参数的方法在子函数中完成,子函数可以被多个过程调用。变量也可以相对减少很多。

  • rng = "'" & Mid(s, 2)

  • '加上"'"代表是以文本写入,因为有数字,可以防止写入到单元格中出错

合并内容相同的连续单元格

  • 合并前的格式:

  • 合并后的格式及代码:

  • 注释:

  • 加速语句,有关必须有开, 都是成对的。Application.DisplayAlerts = False  Application.DisplayAlerts = True

  • 位置语句开始后面,所有需要使用该位置的地址前面都要加上 .

  • ★★★ 注意:合并单元格,删除单元格,为了防止单元格的位置混乱,都必须是从下到上的循环, step 是 -1

  • .Range(.Cells(i - 1, "A"), .Cells(i, "A")).Merge '二个单元格合并,range(最上面单元格,最下面单元格)

拆分单元格时仍然保留每个单元格中的内容

  • 拆分前面已合并的单元格,代码如下:

  • 注释:

  • 取消合并单元格,从上到下即可

  • 先记录原值,再写入的过程

  • 循环行号需要变化:i = i + rng.Rows.Count - 1 即:循环行号(本行) + 包含本行内的单元格的行数 - 1 本行

  • MergeArea 属性:返回单元格对象。如果在合并区域,返回单元格的合并区域。如果不在合并区域内,返回该单元格

  • n = .Range("A1048576").End(xlUp).Row + _

  • .Range("A1048576").End(xlUp).MergeArea.Rows.Count - 1

  • '为了防止最后行为合并的单元格, 出现计算不准确情况。使用这个公式计算最大行: 最大行 + 最大行的合并区域的行数 - 1

合并单元格对应同行区域求和

  • 代码:

  • 注释:

  • Application.ThisCell:返回当前单元格, 如图为:C2 它的 MergeArea 合并区域:C2:C4

  • r.Resize(e.Rows.Count) '传入的参数 r 为: A2,它扩展 (C2:C4 的行数:3),即:A2:A4

  • Application.WorksheetFunction.Sum(e)  '对该区域调用工作表函数执行求和

  • 在选定区域中写入公式的代码:

  • 选定区域为: B2:B9

  • 注释:

  • 打断点逐步调试看结果, 方便理解

  • 第一次取出的 e 是 B2单元格

  • Set s = e.MergeArea '当前 B2 单元格 的合并区域地址为: $B$2:$B$4

  • If e.Address = s.Range("a1").Address Then '因为 B2 是 合并区域: $B$2:$B$4 中的第1个地址,则执行后面的代码

  • Split(s.Address, "$") '用 $ 拆分合并区域地址, 拆分后:

  • 求和区 = Replace(s.Address, 拆分(1), 替换列)

  • '原来的地址: $B$2:$B$4, 拆分(1)的值: B 见上图, 替换成之前输入的列号: A

  • 替换后的结果: $A$2:$A$4

  • e.Formula = "=sum(" & 求和区 & ")" 'e 即B2单元格 写入公式 =sum($a$2:$a$4)

  • 第二次取出的 e 是 B3单元格

  • If e.Address = s.Range("a1").Address Then '因为 B3 不是 合并区域: $B$2:$B$4 中的第1个地址,则不执行后面的代码

  • 就是通过这样一个循环,完成所有原生公式的写入,完成求和的目的


    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多