2016-03-22 5 views
4

Ich weiß, ich weiß, fusionierte Bereiche sind schrecklich, mit zu arbeiten. Aber trotzdem:Excel - Warum unterscheidet sich die Benennung eines zusammengeschlossenen Bereichs von der Zusammenführung eines Bereichs und der anschließenden Benennung?

Ich entdeckte ein witziges Verhalten, wobei ich einige zusammengefügte Bereiche kopieren und einfügen konnte, aber keine anderen. Also habe ich experimentiert.

Setup:

enter image description here

enter image description here

Schon ist es offensichtlich, dass diese Bereiche nicht das Gleiche. Die Bereiche, die nach dem Zusammenführen benannt wurden, bestehen nur aus der Referenz topLeftCell, während die nach der Benennung zusammengesetzten Bereiche einen Verweis auf alle Zellen enthalten.


Edit: Testcode

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 

Nach umfangreichen Tests, dies scheint die Schlussfolgerung zu sein:

Wenn Sie einen Bereich von Zellen einen Namen geben und sie dann zusammenführen, die dem Namen Bereich behält einen Verweis auf alle Zellen bei. Wenn Sie zuerst zusammenführen, bezieht sich der benannte Bereich nur auf die topLeftCell.

Wenn Sie versuchen, einen benannten Bereich zu kopieren, wird er so behandelt, als habe er die gleiche Größe wie seine Referenz. Es ist also in Ordnung, einen (dann zusammengesetzten) Satz von 5 Zellen in einen anderen Satz von verbundenen Zellen derselben Größe oder in eine einzelne Zelle zu kopieren.

Der (zusammengeschlossene und dann benannte) Bereich kann jedoch nur in eine einzelne Zelle kopiert werden. Wenn Sie versuchen, in einen Satz von fünf verbundenen Zellen zu kopieren, wird ein 1004-Fehler angezeigt.


Warum? Was passiert mit dem Umgang mit verbundenen Zellen und benannten Bereichen, die diese Diskrepanz verursachen?


Als Referenz ist das Office 365, Excel Version 15.0.4805.1003

+0

Ich beschuldige [Joel] (http://stackoverflow.com/users/4/joel-spolsky). – Raystafarian

+0

Was ist die Einfügemethode, wenn Sie den Fehler 1004 erhalten? Ich habe Probleme beim Replizieren des Fehlers – Dan

+0

@Dan den Testcode hinzugefügt – Kaz

Antwort

1

Ich werde an diesem einen Stich nehmen, wie ich glaube, ich habe genug mit Ihrem Code getestet, um zu verstehen, was los ist .

Beginnen wir damit, wie Excel die verschiedenen benannten Bereiche behandelt, wenn die von Ihnen festgelegten Aktionen ausgeführt werden. Sie können sehen, dass nach der Einstellung copyRange auf die MERGE_THEN_NAME Konstante, und mit .Copy (für Testzwecke) auf der neu definierten copyRange, die A2 Zelle hat die beweglichen gestrichelten Linien um es herum.

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 

enter image description here

da der definierte Bereich als =wsPasteTest!$A$2 im Namen Manager lesen ist dies erwartet wird.

Name Manager Description

Diese Definition des Bereichs bedeutet, dass, wenn Excel den benannten Bereich erneut besucht Wert zu extrahieren, es tut dies, indem Sie die Adresse wörtlich zu interpretieren, dh sie berücksichtigt nur den Zellenwert von A2 seit the merged cells' value is defined in the "top left" Zelladresse selbst. Diese Logik kann durch das korrekte Verfahren zum Zurückgeben des Werts einer verbundenen Zelle durch VBA-Prozeduren (die in dem obigen Hyperlink adressiert sind) bestätigt werden, indem etwas wie Range("A2:E2").Cells(1).Value anstelle von einfach Range("A2:E2").Value verwendet werden muss. Die letztere Option gibt ein Array zurück, da es den Wert jeder einzelnen Zelle im Bereich berücksichtigt.


Der nächste Teil ist hier, warum es gefährlich sein kann .Select oder .Activate durch den ganzen Code zu verwenden, sondern zeigt auch, wie das Verhalten bekommen Sie möchten. Wir können sehen, wenn wir .Select die copyCell, dass es wählt die gesamte verbundene Zelle im Vergleich zu nur A2 in der .Copy-Methode (die imitiert, wie ein Benutzer mit dem Bereich in der Kalkulationstabelle selbst interagiert). Wenn wir jetzt copyCell auswählen und dann Selection.Copy verwenden, wird die gesamte verbundene Zelle kopiert und nicht nur A2, da Excel angewiesen wurde, den gesamten Array-Bereich zu erfassen. Excel hat auch gezeigt, wie wichtig die Auswahl eines Elements und die anschließende Verwendung der Auswahl ist, um die Interpretation eines Bereichs drastisch zu ändern, anstatt explizit mit dem Bereich zu arbeiten.

Der Code in PerformTests() und TestNames() zu Ihnen identisch ist, wurde die folgende Unter geändert:

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 

Hier ist das Ergebnis der copyCell ausgewählt wird, dann kopiert.

Selection.Copy result

Hier ist das Ergebnis der pasteCell ausgewählt wird, dann in eingefügt. Dies zeigt das gewünschte Ergebnis bei der Verwendung von Merge_Then_Name.

selection.PastSpecial result


Letztlich kann man sehen, dass, wenn Sie einen Namen Bereich siehe ausdrücklich, dass nach Verschmelzung definiert wurde, interpretiert er die Adresse des benannten Bereich buchstäblich (eine einzelne Zelle Wert mit Single geben Zellformatierung), die mit der vorgeschlagenen Kleistermethode nicht eindeutig in die gewünschte Flächengröße eingefügt werden kann. Wenn Sie Ihre Einfügemethode auf xlPasteValues ändern, können Sie vermeiden, .Select zu verwenden. Der Grund dafür ist, dass die Definition von Paste_Merge_Then_Name als =wsPasteTest!$A$8 beibehalten werden kann und gleichzeitig der Wert in einen einzelnen Zellenbereich übertragen werden kann. Diese Methode behält die Formatierung der Zielzelle bei und ersetzt nur den Wert. Es ist nicht genau das, was deine beabsichtigte Paste war, aber ziemlich nah.

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 

PasteSpecial Result


Der Name_Then_Merge Bereich arbeitet sowohl mit einzelner Zelle und die benannten Bereich Pasten für einen Hauptgrund; Wie viele Platzhalter enthält es für Werte.Wenn Sie die .Copy Methode von Name_Then_Merge tun, wählt es die gesamte verbundene Zelle aus, weil es nach seiner Definition angewiesen wird=wsPasteTest!$A$5:$E$5. Das ist gut, weil das Einfügen in einen gleichnamigen benannten Bereich funktioniert, weil sie übereinstimmen, und das Einfügen in eine einzelne Zelle würde funktionieren, weil es einen einzelnen, nicht leeren Wert gibt.

Zusammenfassung: Die benannten Bereiche sind durch ihre anfänglichen Zellenwerte definiert und enthalten die Anzahl der "Orte", selbst nachdem die Zellen zusammengeführt wurden. Wenn Sie also einen Bereich benennen, verweist er auf die Werte der einzelnen Zellen in einem Bereich (in diesem Fall 5 Werte), und das Zusammenführen der Zelle ändert nicht die Definition des benannten Bereichs (ändert jedoch alle Werte des Arrays nach dem ersten) Zelle zu "" als Platzhalter). Wenn Sie Zellen zusammenführen und dann den Bereich benennen, wird der Wert in der oberen linken Zelle des zusammengeführten Bereichs gespeichert und wird daher als Definition der verbundenen Zelle für den benannten Bereich verwendet. In diesem Fall wird Excel verwirrt, wenn Sie versuchen, nur .Paste oder xlPasteAll dies in eine verbundene Zelle, weil es den Wert der Quelle als einzelne Zelle Bereich kopiert und versuchen, es in das Ziel, das eine fünfzellige Bereich ist einfügen.

Lösen Sie dies, indem Sie sicherstellen, dass Sie den gesamten Bereich des benannten Bereichs kopieren, indem Sie ihn auswählen oder indem Sie eine andere Pastenmethode verwenden aber seien Sie vorsichtig, was diese Pastenmethoden produzieren. Z.B. xlPasteAllUsingSourceTheme wird die Zielzellen auflösen, erfüllt jedoch immer noch die angegebene Bereichsdefinition.