【问题标题】:Excel - Why is Naming a Merged Range different from Merging a Range and then Naming it?Excel - 为什么命名合并范围与合并范围然后命名不同?
【发布时间】:2016-07-09 11:38:58
【问题描述】:

我知道,我知道,合并范围很难使用。但无论如何:

我发现了一些有趣的行为,我可以复制/粘贴一些合并范围,但不能复制/粘贴其他范围。于是我试验了一下。

设置:

很明显,这些范围不是一回事。合并后命名的范围仅包含 topLeftCell 引用,而命名后合并的范围保留对所有单元格的引用。


编辑:测试代码

Option Explicit

Public Sub PerformTests()

    Const NAME_THEN_MERGE As String = "Name_Then_Merge"
    Const MERGE_THEN_NAME As String = "Merge_Then_Name"
    Const PASTE_NAME_THEN_MERGE As String = "Paste_Name_Then_Merge"
    Const PASTE_MERGE_THEN_NAME As String = "Paste_Merge_Then_Name"

    TestNames MERGE_THEN_NAME, PASTE_NAME_THEN_MERGE
    '/ Result: Error 1004, cannot do that to a merged cell


End Sub

Public Sub TestNames(ByVal copyName As String, ByVal pasteName As String)

    wsPasteTest.Activate

    Dim copyRange As Range, pasteRange As Range
    Set copyRange = wsPasteTest.Range(copyName)
    Set pasteRange = wsPasteTest.Range(pasteName)

    CopyPasteCell copyRange, pasteRange

End Sub

Public Sub CopyPasteCell(ByRef copyCell As Range, ByRef pasteCell As Range, Optional ByVal pasteRowHeights As Boolean = False)

    copyCell.Copy
    pasteCell.PasteSpecial xlPasteAll

    If pasteRowHeights Then
        Dim sourceRowHeight As Long
        sourceRowHeight = copyCell.rowHeight
        pasteCell.rowHeight = sourceRowHeight
    End If

End Sub

经过广泛的测试,这似乎是结论:

如果您命名一个单元格区域,然后将它们合并,则命名的 Range 保留对所有单元格的引用。如果先合并,则命名范围仅指 topLeftCell。

如果您尝试复制命名范围,则会将其视为与其引用相同的大小。因此,可以将一组(命名然后合并)5 个单元格复制到另一组相同大小的合并单元格或单个单元格。

但是,(合并然后命名)范围只能复制到单个单元格。尝试复制到一组 5 个合并单元格将导致 1004 错误。


为什么?导致这种差异的合并单元格和命名范围的处理方式是怎么回事?


供参考,这是 Office 365,Excel 版本 15.0.4805.1003

【问题讨论】:

  • 我责怪Joel
  • 遇到 1004 错误时的粘贴方法是什么?我在复制错误时遇到问题
  • @Dan 添加了测试代码

标签: vba excel named-ranges


【解决方案1】:

我将对此进行尝试,因为我认为我已经对您的代码进行了足够的测试以了解发生了什么。

让我们从 Excel 在执行您指定的操作时如何处理各种命名范围开始。您可以看到,在将copyRange 设置为MERGE_THEN_NAME 常量并在新定义的copyRange 上使用.Copy(用于测试目的)后,A2 单元格周围有移动的虚线。

Option Explicit

Public Sub PerformTests()

    Const NAME_THEN_MERGE As String = "Name_Then_Merge"
    Const MERGE_THEN_NAME As String = "Merge_Then_Name"
    Const PASTE_NAME_THEN_MERGE As String = "Paste_Name_Then_Merge"
    Const PASTE_MERGE_THEN_NAME As String = "Paste_Merge_Then_Name"

    TestNames MERGE_THEN_NAME, PASTE_MERGE_THEN_NAME
    '/ Result: Error 1004, cannot do that to a merged cell


End Sub

Public Sub TestNames(ByVal copyName As String, ByVal pasteName As String)

    Sheets("wsPasteTest").Activate

    Dim copyRange As Range, pasteRange As Range
    Set copyRange = Sheets("wsPasteTest").Range(copyName)
    copyRange.Copy    'This is the last step executed before error
    Set pasteRange = Sheets("wsPasteTest").Range(pasteName)

    CopyPasteCell copyRange, pasteRange

End Sub

这是预期的,因为定义的范围在名称管理器中被读取为 =wsPasteTest!$A$2

该范围的定义意味着当 Excel 重新访问命名范围以提取值时,它通过按字面解释地址来实现,即它只考虑 A2 的单元格值,因为 the merged cells' value is defined in the "top left" 本身的单元格地址。通过需要使用类似Range("A2:E2").Cells(1).Value 而不是简单的Range("A2:E2").Value 的东西,可以通过VBA 过程(在上面的超链接中解决)返回合并单元格的值的正确方法来确认此逻辑。后一个选项返回一个数组,因为它考虑了范围内每个单元格的值。


这里的下一部分是为什么在整个代码中使用.Select.Activate 会很危险,同时也展示了如何获得你想要的行为。我们可以看到当我们.SelectcopyCell 时,它选择了整个合并的单元格,而.Copy 方法中的A2 只是模拟了用户如何与电子表格本身的范围进行交互。所以现在,如果我们选择copyCell,然后使用Selection.Copy,则复制整个合并的单元格,而不仅仅是A2,因为Excel 已被指示抓取整个数组区域。 Excel 还刚刚展示了选择一个项目然后使用该选择可以极大地改变其对范围的解释,而不是显式地使用范围。

PerformTests()TestNames()中的代码和你的一样,修改了以下子:

Public Sub CopyPasteCell(ByRef copyCell As Range, ByRef pasteCell As Range, Optional ByVal pasteRowHeights As Boolean = False)

    copyCell.Select
    Selection.Copy 'this step is shown in the first screenshot below
    pasteCell.Select
    Selection.PasteSpecial xlPasteAll 'this step is shown in the second screentshot below

    If pasteRowHeights Then
        Dim sourceRowHeight As Long
        sourceRowHeight = copyCell.RowHeight
        pasteCell.RowHeight = sourceRowHeight
    End If

End Sub

这是copyCell 被选中然后复制的结果。

这是pasteCell 被选中然后粘贴到的结果。这显示了您在使用 Merge_Then_Name 范围时所需的结果。


最终,您可以看到,当您显式引用已在 合并后定义的命名范围时,它会按字面意思解释命名范围的地址(给出具有单个单元格格式的单个单元格值),显然无法使用建议的粘贴方法将其粘贴到所需的区域大小。 如果您将粘贴方法更改为xlPasteValues,则可以避免使用.Select。这是因为它允许Paste_Merge_Then_Name 的定义保持为=wsPasteTest!$A$8,同时还允许将值传输到单个单元格区域。此方法在仅替换值的同时保持目标单元格的格式相同。这不是您想要的粘贴,但非常接近。

Public Sub CopyPasteCell(ByRef copyCell As Range, ByRef pasteCell As Range, Optional ByVal pasteRowHeights As Boolean = False)

    copyCell.Copy
    pasteCell.PasteSpecial xlPasteValues

    If pasteRowHeights Then
        Dim sourceRowHeight As Long
        sourceRowHeight = copyCell.RowHeight
        pasteCell.RowHeight = sourceRowHeight
    End If

End Sub


Name_Then_Merge 范围适用于单个单元格和命名范围粘贴,主要原因有一个;它包含多少个值的占位符。当您执行Name_Then_Merge.Copy 方法时,它会选择整个合并单元格因为它的定义指示它 =wsPasteTest!$A$5:$E$5。这很好,因为将其粘贴到大小相等的命名范围中会起作用,因为它们匹配,并且粘贴到单个单元格中会起作用,因为有一个非空白值。


总结:命名范围由它们的初始单元格值定义,并且即使在单元格合并后也保留该数量的“位置”。因此,如果您命名一个范围,它会引用一个范围内每个单元格的值(在这种情况下为 5 个值),并且合并单元格不会更改命名范围的定义(但会更改第一个之后的数组的所有值单元格以“”作为占位符)。如果合并单元格然后命名范围,则该值将保存在合并区域的左上角单元格中,因此用作命名范围的合并单元格的定义。在这种情况下,如果您尝试仅将 .PastexlPasteAll 这到合并单元格中,Excel 会感到困惑,因为它会将源的值复制为单个单元格区域并尝试将其粘贴到目标中,这是一个五格区域。

通过选择或使用不同的粘贴方法确保复制命名范围的整个区域来解决此问题但要小心这些粘贴方法产生的结果。例如。 xlPasteAllUsingSourceTheme 将取消合并目标单元格,但仍满足命名范围定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 2017-10-01
    • 2021-08-25
    • 2019-03-21
    • 2016-09-23
    • 1970-01-01
    相关资源
    最近更新 更多