Range automatisch verketten

Moin auch,

zur Abwechslung mal ein Excel VBA Problem von mir, nach langer Zeit mal wieder. Ich habe einige tausend Zellen, die verkettet werden sollen. Dabei steht in Spalte (n) ein Wert x, dann sollen alle Werte aus Spalte (n-1) in dieselbe Zeile verkettet werden, in der der Wert x steht. Als Trennzeichen sollte ein Semikolon benutzt werden. Etwas kompliziert zu erklären, deshalb upload unter http://www.file-upload.net/download-8483152/Beispiel….

Wichtig ist, dass immer dann eine neue Verkettung begonnen wird, wenn in Spalte (n) ein neuer Wert steht oder eine Reihe in Spalte (n-1) leer ist.

Es gibt etwas hilfreiches unter http://vbaexpress.com/kb/getarticle.php?kb_id=817, da müsste ich aber jeden zu verkettenden range manuell eingeben. Da ich davon ein paar tausend habe, ist das etwas mühselig. Dummerweise komme ich nicht auf den Trichter, wie ich die darin geschilderte Funktion automatisch aufrufen kann,

Für eure Hilfe bin ich wie immer dankbar.

Ralph

Corrigendum
Nochmal ich.

In der hochgeladenen Datei ist ein Schreibfehler. In Spalte D, Reihe 2 muss der erste Eintrag natürlich Satz 1 heißen, nicht Sart 1.

Ralph

Hallo Ralph,

probier es mal mit dm folgenden Makro.

Die Startzeile der For-Next-Schleife musst du ggf. noch anpassen.

Gruß
Franz

Sub aaTest()
  Dim wks As Worksheet
  Dim ZeileWert As Long, Zeile As Long, SpalteN As Long
  Dim strWert As String
  SpalteN = 2 ' Spalte B
  Set wks = ActiveSheet
  Application.ScreenUpdating = False
  With wks
    For Zeile = 2 To .Cells(.Rows.Count, SpalteN - 1).End(xlUp).Row
      If .Cells(Zeile, SpalteN).Value "" Then
        ZeileWert = Zeile
      ElseIf .Cells(Zeile, SpalteN - 1).Value = "" And .Cells(Zeile, SpalteN).Value = "" Then
        'do nothing
      Else
        With .Cells(ZeileWert, SpalteN - 1)
          .Value = .Value & ";" & wks.Cells(Zeile, SpalteN - 1).Value
        End With
        .Cells(Zeile, SpalteN - 1).ClearContents
      End If
    Next
  End With
  Application.ScreenUpdating = True
End Sub

Hallo Franz,

danke für den Tip. Ich habe es gelöst mit:

Sub rang()
Dim reihe As Integer, zaehler As Integer, runde As Integer, inhalt As String
For reihe = 4 To 535
 zaehler = 1
 Do Until Cells(reihe + zaehler, 32).Value ""
 zaehler = zaehler + 1
 Loop
 inhalt = Cells(reihe, 29).Value
 For runde = 1 To zaehler - 1
 inhalt = inhalt & ";" & Cells(reihe + runde, 29).Value
 Next
 Cells(reihe, 30).Value = inhalt
 reihe = reihe + zaehler - 1
Next
End Sub

Hat den kleinen Nachteil, dass nicht nach den leerzeilen geschaut wird. Im schlimmsten Fall hört also der neue Wert mit einem oder mehreren Semikolons auf. Die lösche ich dann hinterher.
Ralph

Ist das die Lösung?
Wäre schon gut ein Feedback zu schreiben.

Damit andere nicht unnötig nach einer weiteren Lösung suchen.

Hallo Max,

wie geschrieben habe ich eine andere Lösung gefunden. Ob die von Franz funktioniert habe ich nicht ausprobiert.

Ralph

Hallo franz,

das funktioniert so nicht, weil mit

.Value = .Value & ";" & wks.Cells(Zeile, SpalteN - 1).Value

der Wert der vorhergehenden Spalte eingelesen wird; das muss aber der Wert der folgenden Zeile sein. Da aber mehr als eine folgende Zeile kommen kann, muss m.M.n. doch über einen Loop erst festgestellt werden, woeviele folgende Zeilen kommen.

Ralph

Hallo Ralph,

völlig OT, Danke :smile:

danke für den Tip. Ich habe es gelöst mit:

Hat den kleinen Nachteil, dass nicht nach den leerzeilen
geschaut wird. Im schlimmsten Fall hört also der neue Wert mit
einem oder mehreren Semikolons auf. Die lösche ich dann
hinterher.

Wie löschst du die hinterher? Mit zusätzlichen Codezeilen?
Zeig doch bitte mal den Gesamtcode. May be man kann das Problem gar nicht erst auftreten lassen *vermut*

Zu deiner Variablendeklaration mal einen Tipp.
Du deklarierst Zeilen als Integer.
Das bedeutet dein Code versagt bei Tabellen mit mehr Zeilen als 32xxx.

Du benutzt Cells(Zei,Spa). Cells() benötigt Long-Werte, ergo, völlig egal wie du z.B. Zei deklariert hast (Byte, Interger) der Wert wird sowieso in einen Long-Wert gewandelt.
Was kostet dich diese Umwandlung? Etwas wichtiges: Zeit.

Diese Zeit wird dir Millionenfach fehlen bzw. den Vorgang verlängern wenn du Mal für Entschlüsselungscodes Schleifen hast die millionenfach duch laufen werden.

Im normalen Alltag merkste davon nichts.
ABER, jetzt kommt mein Argument waum ich seit Jahren Zeilenvariablen und auch Spaltenvariablen NUR als Long definiere.
Das ist sehr einfach zu merken, ich erspare es mir darüber nachzudenken, Byte, Integer.

Untermauerung, Nepu ist garantiert einer der weltbesten Vbaler:
http://www.herber.de/forum/archiv/952to956/954760_Da…

Gruß
Reinhard

Moin auch,

Wie löschst du die hinterher? Mit zusätzlichen Codezeilen?

Suchen und Ersetzen. Ersetze „;;“ durch „;“. Dann habe ich am Ende maximal ein Semikolon stehen. Dann weiter mit Code (Rudimentärer Code, ich habe das Makro inzwischen leider gelöscht):

for reihe=4 to 12345
if right(cells(reihe,5),1)=";" then
len(cells(reihe,5)=len(cells(reihe,5)-1)
endif
next

Zeig doch bitte mal den Gesamtcode. May be man kann das
Problem gar nicht erst auftreten lassen *vermut*

Habe ich doch in meinem anderen posting.

Zu deiner Variablendeklaration mal einen Tipp.
Du deklarierst Zeilen als Integer.
Das bedeutet dein Code versagt bei Tabellen mit mehr Zeilen
als 32xxx.

jupp. Reicht hier aber aus.

Du benutzt Cells(Zei,Spa). Cells() benötigt Long-Werte, ergo,
völlig egal wie du z.B. Zei deklariert hast (Byte, Interger)
der Wert wird sowieso in einen Long-Wert gewandelt.
Was kostet dich diese Umwandlung? Etwas wichtiges: Zeit.

Ohje, du legst deinen Finger in eine Wunde. Der Punkt ist: Ich spreche kein VBA, ich radebreche es. Dass Cells(x,y) einen long-Wert braucht wusste ich z.B. nicht. Auch die ganzen loops und Zeug, dass ich verwende, stört mich eigentlich sehr (aus ästhetischen Gründen :smile:). Mit einem range-Aufruf geht das sicherlich schneller und eleganter, aber ich weiß eben nicht, wie. Und wenn ich mal wieder ein makro brauche, fehlt mir einfach die Zeit, um zu lernen wie es besser wäre.

Ralph