当前位置: 首页 > news >正文

VBA 列方向合并单元格,左侧范围大于右侧范围

实现功能如下:
excel指定行列范围内的所有单元格
规则1:每一列的连续相同的值合并单元格
规则2:每一列的第一个非空单元格与其下方的所有空白单元格合并单元
规则3:优先左侧列合并单元格,合并后,右侧的单元格的合并范围的行上下限不能超过左侧的单元格范围。

如下图:
在这里插入图片描述

Sub MergeCellsBetweenNonEmpty()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Sheet1") ' 修改为你的工作表名称

    Dim startRow As Long, endRow As Long
    Dim startCol As Long, endCol As Long
    startRow = 1 ' 起始行号
    endRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row ' 动态获取结束行号
    startCol = 1 ' 起始列号
    endCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column ' 动态获取结束列号

    Dim i As Long, j As Long
    Dim firstNonEmptyRow As Long, secondNonEmptyRow As Long
    Dim hasNonEmptyCell As Boolean
    Dim mergeArea As Range

    ' 禁用屏幕更新和自动计算以提高性能
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    Application.DisplayAlerts = False ' 禁用警告提示

    ' 循环遍历每一列
    For j = startCol To endCol
        firstNonEmptyRow = 0
        secondNonEmptyRow = 0
        hasNonEmptyCell = False

        ' 循环遍历每一行,查找所有符合条件的第一对非空单元格
        For i = startRow To endRow
            If ws.Cells(i, j).Value <> "" Then
                If firstNonEmptyRow = 0 Then
                    firstNonEmptyRow = i ' 找到第一个非空单元格
                ElseIf secondNonEmptyRow = 0 Then
                    secondNonEmptyRow = i ' 找到第二个非空单元格

                    ' 如果两个非空单元格之间有其他单元格,则尝试合并
                    If secondNonEmptyRow - firstNonEmptyRow > 1 Then
                        ' 计算右侧列的合并范围
                        Dim rightMergeStart As Long, rightMergeEnd As Long
                        rightMergeStart = firstNonEmptyRow
                        rightMergeEnd = secondNonEmptyRow - 1

                        ' 检查左侧列的合并范围
                        Dim leftMergeStart As Long, leftMergeEnd As Long
                        If j > startCol Then
                            On Error Resume Next
                            Set mergeArea = ws.Cells(rightMergeStart, j - 1).MergeArea
                            On Error GoTo 0

                            If Not mergeArea Is Nothing Then
                                leftMergeStart = mergeArea.Row
                                leftMergeEnd = leftMergeStart + mergeArea.Rows.Count - 1
                            Else
                                leftMergeStart = ws.Cells(rightMergeStart, j - 1).Row
                                leftMergeEnd = leftMergeStart
                            End If

                            ' 计算重叠区域
                            Dim overlapStart As Long, overlapEnd As Long
                            overlapStart = WorksheetFunction.Max(rightMergeStart, leftMergeStart)
                            overlapEnd = WorksheetFunction.Min(rightMergeEnd, leftMergeEnd)

                            ' 如果存在重叠区域且行数大于1,则合并
                            If overlapStart <= overlapEnd And (overlapEnd - overlapStart + 1) > 1 Then
                                With ws.Range(ws.Cells(overlapStart, j), ws.Cells(overlapEnd, j))
                                    .Merge
                                    .HorizontalAlignment = xlCenter
                                    .VerticalAlignment = xlCenter
                                End With
                            End If
                        Else
                            ' 第一列直接合并(检查行数是否大于1)
                            If (rightMergeEnd - rightMergeStart + 1) > 1 Then
                                With ws.Range(ws.Cells(rightMergeStart, j), ws.Cells(rightMergeEnd, j))
                                    .Merge
                                    .HorizontalAlignment = xlCenter
                                    .VerticalAlignment = xlCenter
                                End With
                            End If
                        End If
                    End If

                    ' 重置 firstNonEmptyRow 和 secondNonEmptyRow,继续查找下一对
                    firstNonEmptyRow = secondNonEmptyRow
                    secondNonEmptyRow = 0
                End If
                hasNonEmptyCell = True
            End If
        Next i

        ' 如果找到第一个非空单元格但未找到第二个非空单元格,则尝试合并到最后一行的单元格
        If firstNonEmptyRow > 0 And secondNonEmptyRow = 0 Then
            If endRow - firstNonEmptyRow > 0 Then
                ' 计算右侧列的合并范围
                rightMergeStart = firstNonEmptyRow
                rightMergeEnd = endRow

                ' 检查左侧列的合并范围
                If j > startCol Then
                    On Error Resume Next
                    Set mergeArea = ws.Cells(rightMergeStart, j - 1).MergeArea
                    On Error GoTo 0

                    If Not mergeArea Is Nothing Then
                        leftMergeStart = mergeArea.Row
                        leftMergeEnd = leftMergeStart + mergeArea.Rows.Count - 1
                    Else
                        leftMergeStart = ws.Cells(rightMergeStart, j - 1).Row
                        leftMergeEnd = leftMergeStart
                    End If

                    ' 计算重叠区域
                    overlapStart = WorksheetFunction.Max(rightMergeStart, leftMergeStart)
                    overlapEnd = WorksheetFunction.Min(rightMergeEnd, leftMergeEnd)

                    ' 如果存在重叠区域且行数大于1,则合并
                    If overlapStart <= overlapEnd And (overlapEnd - overlapStart + 1) > 1 Then
                        With ws.Range(ws.Cells(overlapStart, j), ws.Cells(overlapEnd, j))
                            .Merge
                            .HorizontalAlignment = xlCenter
                            .VerticalAlignment = xlCenter
                        End With
                    End If
                Else
                    ' 第一列直接合并(检查行数是否大于1)
                    If (rightMergeEnd - rightMergeStart + 1) > 1 Then
                        With ws.Range(ws.Cells(rightMergeStart, j), ws.Cells(rightMergeEnd, j))
                            .Merge
                            .HorizontalAlignment = xlCenter
                            .VerticalAlignment = xlCenter
                        End With
                    End If
                End If
            End If
        End If

        ' 如果该列没有非空单元格或全部是非空单元格,则不合并
        If Not hasNonEmptyCell Or (firstNonEmptyRow = startRow And secondNonEmptyRow = 0) Then
            GoTo NextColumn
        End If

NextColumn:
    Next j

    ' 新增规则:合并相邻相同内容的单元格
    For j = startCol To endCol
        For i = startRow To endRow
            If ws.Cells(i, j).Value <> "" Then
                Dim mergeStart As Long
                mergeStart = i

                ' 检查当前单元格与下一行单元格内容是否相同
                Do While i < endRow And ws.Cells(i + 1, j).Value = ws.Cells(mergeStart, j).Value
                    i = i + 1
                Loop

                ' 如果合并范围的行数大于1,则合并
                If i > mergeStart Then
                    With ws.Range(ws.Cells(mergeStart, j), ws.Cells(i, j))
                        .Merge
                        .HorizontalAlignment = xlCenter
                        .VerticalAlignment = xlCenter
                    End With
                End If
            End If
        Next i
    Next j

    ' 恢复屏幕更新和自动计算
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic
    Application.DisplayAlerts = True ' 恢复警告提示

    MsgBox "合并完成!"
End Sub

相关文章:

  • python: DDD+ORM using oracle 21c
  • Ollama本地部署大模型(Mac M1 )
  • 生物电阻抗技术:精准洞察人体营养的“智能窗口”
  • 安固软件上网行为管理软件:提升企业效率与安全的双重保障
  • MongoDB用户管理和复制组
  • 基于multisim的自动干手器设计与仿真
  • GitHub神秘组织3小时极速复刻Manus
  • 【C++多线程】std::async和std::future
  • 《从零构建企业级容器镜像生态:Harbor与Registry双星架构实战手记》
  • 【redis】布隆过滤器的Java实现
  • DR和BDR的选举规则
  • 蓝桥-找到最多的数-oj3227
  • Android Telephony 四大服务和数据网络控制面数据面介绍
  • Denoising Diffusion Probabilistic Models
  • HTML单页在线自适应拟态影院源码
  • java2025年常见设计模式面试题
  • 我的三维引擎独立开发之路:坚持与迷茫
  • 通领科技冲刺北交所
  • 计算机网络:计算机网络的概念
  • 【JavaScript】09-构造函数+数据常用函数
  • 佛山专业做淘宝网站/网络营销专业代码
  • 什么才是网络营销/北京网站快速排名优化
  • 泰安软件公司 泰安网站建设/线下推广团队
  • 做淘宝客网站必须备案吗/深圳网络推广解决方案
  • 广州市萝岗区做网站设计服务/大学生网页设计主题
  • 大连网站建设开源/百度网盘首页