我知道,我知道,合并范围很难处理。但无论如何:
我发现了一些有趣的行为,我可以复制/粘贴一些Merged Ranges而不是其他人。所以我做了实验。
设定:
很明显,这些范围并不是一回事。合并后命名的范围仅由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
答案 0 :(得分:1)
我会对此进行一次尝试,因为我认为我已经对您的代码进行了足够的测试,以了解正在发生的事情。
让我们从Excel在执行您指定的操作时如何处理各种命名范围开始。您可以看到,在将copyRange
设置为MERGE_THEN_NAME
常量,并在新定义的.Copy
上使用copyRange
(用于测试目的)之后,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重新访问命名范围以提取值时,它通过字面解释地址来实现,即它仅考虑自其the merged cells' value is defined in the "top left"单元格地址以来的A2的单元格值。通过需要使用Range("A2:E2").Cells(1).Value
而不是简单Range("A2:E2").Value
之类的东西,通过VBA过程(在上面的超链接中解决)返回合并单元格的值的正确方法可以确认此逻辑。后一个选项返回一个数组,因为它正在考虑范围内每个单元格的值。
下一部分是为什么在整个代码中使用.Select
或.Activate
会很危险,同时也会说明如何获得您想要的行为。我们可以看到.Select
copyCell
选择整个合并单元格的时间A2
与.Copy
方法中的copyCell
进行比较(模仿用户与范围的交互方式)电子表格本身)。现在,如果我们选择Selection.Copy
然后使用A2
,则会复制整个合并的单元格,而不仅仅是PerformTests()
,因为Excel已被指示抓取整个阵列区域。 Excel也刚刚展示了选择一个项目然后使用选择的重要性可以大大改变其对范围的解释,而不是明确地使用该范围。
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
.Copy
范围适用于单个单元格和命名范围粘贴,主要原因之一;它包含多少占位符的值。当您执行Name_Then_Merge
的{{1}}方法时,它会选择整个合并的单元格,因为它的定义是指示 =wsPasteTest!$A$5:$E$5
。这很好,因为将它粘贴到相同大小的命名范围会起作用,因为它们匹配,并且粘贴到单个单元格中会起作用,因为只有一个非空白值。
摘要:命名范围由其初始单元格值定义,即使在合并单元格后也保留该数量的“位置”。因此,如果您命名范围,它将引用范围中每个单元格的值(在这种情况下为5个值),并且合并单元格不会更改命名范围的定义(但会在第一个更改后更改数组的所有值)单元格为“”作为占位符。如果合并单元格然后命名范围,则该值将保留在合并区域的左上角单元格中,因此将用作命名范围的合并单元格的定义。在这种情况下,如果您尝试将.Paste
或xlPasteAll
放入合并的单元格中,Excel会感到困惑,因为它会将源的值复制为单个单元格区域并尝试将其粘贴到目的地是一个五个小区。
通过选择它或使用不同的粘贴方法确保复制指定范围的整个区域来解决此问题,但要注意这些粘贴方法产生的内容。例如。 xlPasteAllUsingSourceTheme
将取消合并目标单元格,但仍满足命名范围定义。