2.1k Aufrufe
Gefragt in Tabellenkalkulation von Mitglied (926 Punkte)
Hallo VBA-Helfer,
ich habe eine Reihe kleiner Makros erstellt, die der Reihe nach teils mehrfach ausgeführt werden können / sollen. Nur ist da irgendwie eine Endlosschleife eingebaut, aus der ich nur rauskomme indem ich Excel per Taskmanager beende.
Was muss ich ändern damit nach dem Makro "Prozent" tatsächlich Schluss ist?
Sub Leere_Spalte_loeschen()
Dim lngLastCol As Double
Dim leere_Spalte As Integer
lngLastCol = ActiveSheet.UsedRange.Columns.Count
For leere_Spalte = lngLastCol To 1 Step -1
If Application.CountA(Columns(leere_Spalte)) < 1 Then
Columns(leere_Spalte).Delete
End If
Next
Columns.AutoFit
Columns("A").ColumnWidth = 9
Application.ScreenUpdating = True
Call Spalte_1_Eintrag
End Sub
Sub Spalte_1_Eintrag()
Dim leere_Spalte As Integer
Dim varEingabe As Double
Dim VarSpalte As Integer
Dim lngLastCol As Double
Dim lngLastRow As Integer
Dim rngZelle As Range
For Each rngZelle In ActiveSheet.Cells.SpecialCells(xlCellTypeConstants)
If rngZelle = " " Then rngZelle.ClearContents
Next rngZelle
lngLastCol = ActiveSheet.UsedRange.Columns.Count
For leere_Spalte = lngLastCol To 1 Step -1
If Application.CountA(Columns(leere_Spalte)) = 1 Then
lngLastRow = ActiveSheet.Cells(Rows.Count, leere_Spalte).End(xlUp).Row
Cells(lngLastRow, leere_Spalte).Select
Selection.Interior.ColorIndex = 7
varEingabe = MsgBox("Diese Spalte enthält nur diesen Eintrag, löschen?", vbYesNoCancel + vbDefaultButton2 + vbQuestion, "Löschabfrage")
If varEingabe = 2 Then Selection.Interior.ColorIndex = xlNone: Call Spalte_löschen
If varEingabe = 6 Then Columns(leere_Spalte).Delete
If varEingabe = 7 Then Selection.Interior.ColorIndex = xlNone
End If
Next
Call Spalte_löschen
End Sub
Sub Spalte_löschen()
Dim varAntwort
varAntwort = Application.InputBox("Spalte löschen", Type:=2)
If varAntwort = 0 Then Call links
If Not varAntwort = "" Then
If varAntwort <> False Then
On Error Resume Next
Columns(varAntwort).Delete
End If
Call Spalte_löschen
Else: Call links
End If
End Sub

Sub links()
Dim varAntwort
varAntwort = Application.InputBox("links Spalte einfügen", Type:=2)
If varAntwort = 0 Then Call prozent
If Not varAntwort = "" Then
If varAntwort <> False Then
On Error Resume Next
Columns(varAntwort).Insert Shift:=xlToLeft
End If
Call links
Else: Call prozent
End If
End Sub

Sub prozent()
Dim varAntwort
Dim Zelle As Variant
varAntwort = Application.InputBox("Prozentformat Spalte?", Type:=2)
If varAntwort = 0 Then Exit Sub
If Not varAntwort = "" Then Exit Sub
If varAntwort <> False Then Exit Sub
On Error Resume Next
For Each Zelle In Columns(varAntwort).SpecialCells(xlCellTypeConstants, xlNumbers)
If Zelle.IsNumber Then
Zelle.Value = Zelle / 100
Zelle.NumberFormat = "0%"
End If
Next Zelle
Columns(varAntwort).EntireColumn.AutoFit
End If
Call prozent
End If
End Sub[/code]
Vielen Dank im Voraus
mfg
Wolfgang

7 Antworten

0 Punkte
Beantwortet von hajo_zi Experte (9.1k Punkte)
lösche die Zeile
Call prozent

Gruß hajo
0 Punkte
Beantwortet von Mitglied (926 Punkte)
Hallo Hajo und alle anderen,

ich habe gerade festgestelt, das dies doch keine Endlosschleife ist, sondern die Anzahl der Durchläufe ist abhängig vom Makro:
"Sub Spalte_1_Eintrag()".
Konkret: Ich habe das Ganze jetzt per "F8" Schritt für Schritt ausgeführt.
Wenn das Makro "Spalte_1_Eintrag" bis zum Ende ausgeführt wird, ist nach dem Makro "Prozent" Schluß.
Wird das Makro "Spalte_1_Eintrag" per "Abbrechen" beendet, bevor die Zählschleife "For leere_Spalte = lngLastCol To 1 Step -1" bei 1 ist, dann wird nach End If, End Sub im Makro "Prozent" die Prozedur weiter ausgeführt mit
End If, End Sub im Makro "Spalte_löschen",
End If, End Sub im Makro "links",
dann die Zeile " If varEingabe = 6 Then Columns(leere_Spalte).Delete" im Makro "Spalte_1_Eintrag" solange angesprungen bis die Zählschleife auf 1 ist.
Deshalb dieses Makro ergänzt:
If varEingabe = 2 Then Selection.Interior.ColorIndex = xlNone: leere_Spalte = 1: Call Spalte_löschen[u]
Jetzt werden die letzten 3 Makro "nur" noch einmal erneut ausgeführt.
Das möchte ich aber auch noch unterbinden. Wie verhindere ich den Rücksprung ins Makro "Spalte_1_Eintrag"?
mfg
Wolfgang
0 Punkte
Beantwortet von ericmarch Experte (4.6k Punkte)
Hi!

Ich habe mal versucht den Code so aufzubereiten, dass ich ihn lesen kann.
Aber zuvor: Im Makro Prozent sind so weit zu erkennen ganz unten 3 Zeilen zu viel:
End If
Call prozent
End If

Die End If's sind obsolet und mit dem Call ruft sich das Makro selbst auf. Das kann nicht gut ausgehen.

Wie auch immer - wo hast du nur diesen Code her? Ich sehe genug unlogische Strukturen. Beispielsweise müsste man ein On Error auch wieder abschalten, oder aber, wenn man oben darüber/davor prüft, es gar nicht erst nötig haben.
Dann verlangst du per Type eine Eingabe als String, die Empfangsvariable ist aber als Typ Variant geDIMt (weil kein Typ angegeben wurde) - das ist schon ein Widerspruch. Diese Rückgabe dann noch auf Nummerisch-Null oder Logisch-Falsch zu prüfen ergibt auch keinen Schuh. Und mit was soll ich denn eine Frage "Prozentformat Spalte?" beantworten - Ja/Nein vermutlich? Dann wäre schon eine MsgBox ausreichend.

Ich müsste da mal zu viel Zeit übrig haben um das alles einzusortieren und zu verkürzen. Dann wird das wohl auch laufen. Aber dazu müsste man wissen was genau du da treiben willst. «ActiveSheet.UsedRange.Columns.Count» macht mir allein wegen des UsedRange schon Bauchschmerzen…

Eric March
0 Punkte
Beantwortet von Mitglied (926 Punkte)
Hallo Eric,
1. von Programmierung verstehe ich nicht wirklich was. Die Makros die ich nutze, sind teilweise auf Anfrage komplett hier für mich hier erstellt, zum größten Teil (siehe obiges) ist das "Patchwork", also Teile, die ich hier im Forum finde, kopiere und zu neuem zusammen füge.
2. Zum Sinn des obigen. Ich arbeite mit einem Buchhaltungsprogramm das Daten nach Excel exportieren kann, die Zahlen erkennt Excel zunächst nicht als solche, das wird von einem 1ten Makro bearbeitet. Dann kann mit obigen Makros weitergearbeitet werden.
Sub Leere_Spalte_loeschen() macht was der Name sagt.
Sub Spalte_1_Eintrag(): Oft gibt es eine Spalte im Export, wo der Inhalt der meisten Zellen aus 3 Leerstellen besteht, die werden hier als erstes gelöscht. Dann steht in einigen Spalten nur ein einziger (meist) überflüssiger Eintrag, diese Spalten sollen ggf. nach Rückfrage gelöscht werden. Damit der Nutzer überhaupt erkennt wo das Makro gerade ist:
Cells(lngLastRow, leere_Spalte).Select
Selection.Interior.ColorIndex = 7
Dann soll der Nutzer entscheiden können: Löschen, nicht löschen, Abbruch des Makros.
Die nächsten 3 Makros erwarten in
varAntwort = Application.InputBox("Spalte löschen", Type:=2)
die Eingabe eines (ggf 2) Buchstabens als Spaltenbezeichnung, dann werden die nächsten Schritte abgearbeitet und die Makros rufen sich erneut auf, das soll so sein, bis nichts eingegeben wird, und Enter gedrückt wird, dann folgt das nächste Makro. Das funktionierte bisher auch alles sehr gut. Nur ist das Makro "Sub Spalte_1_Eintrag()" neu erstellt und in den Ablauf eingebunden. Nun ist plötzlich nicht mehr Schluss, wenn im Makro "Sub Prozent()" keine gültige Eingabe erfolgt, sondern es geht zurück ins Makro "Sub Spalte_1_Eintrag()"
Das ist mir ein Rätsel. Ich habe hier jetzt erstmal "Call Spalte_löschen" gelöscht und den Start dieses Makros erfolgt (wenn gewünscht), über einen neunen Menübefehl.
mfg
Wolfgang
0 Punkte
Beantwortet von ericmarch Experte (4.6k Punkte)
Ich müsste mal die einkommenden Daten(strukturen) samt möglicher Unfälle sehen und dann nachvollziehen was da wer weswegen tun soll oder nicht.

Leere Spalten - und für mich meint das: innerhalb einer mir bekannten Zone, nicht aber per XL-Rückmeldung - zu löschen oder selbiges mit Einträgen die Leerzeichen enthalten kann man auch direkt abfangen und handhaben.

Mir ist nämlich gar nicht geheuer was der (tumbe) Anwender tun/machen/auslösen soll; ich meine - warum überhaupt solche Entscheidungen von ihm verlangen?

Noch ungeheuer ist mir die Vorstellung eine Art Aufgabensammlung zu betreiben die dann erst mit einem einzigen OK ausgelöst wird.

Wie erwähnt, ich müsste Zeit haben darüber zu brüten, und auch die neuen Informationen einzuflechten. Eines aber sei dir gewiss - rekursives programmieren, also Makros die sich selbst aufrufen, da lasse ich die Pfoten von: das ist alle ein Fall von Schleifenkonstruktionen.

Eric March
0 Punkte
Beantwortet von Mitglied (926 Punkte)
Hallo Eric,
es gibt keine bestimmten Datenstrukturen, die Exporte können sein: einzele Konten, Offene-Posten-Listen, Kostenstellenauswertungen, Summen- und Saldenliste usw.
Die Makros anwenden werden nur meine Chefin und ich.
Deinen Absatz ab: "Leere Spalten..." verstehe ich komplett gar nicht.
«ActiveSheet.UsedRange.Columns.Count» warum macht das Bauchschmerzen? Das habe ich hier des öfteren in Makros gesehen. Wie würde bei dir die Zeile lauten, die die letzte benutzte Spalte ermittelt?
"das ist alle ein Fall von Schleifenkonstruktionen.", wüsste ich wies geht, würde ich es machen. Wo finde ich hier ein Beispiel für eine einfache nachvollziehbare Schleife?
Ansonsten lohnt es sich im Moment nicht, lange über diese Makros zu brüten. Sie funktionieren.
Aus dem 1ten und dem 2ten Makro habe ich gerade eins gemacht.
mfg
Wolfgang
0 Punkte
Beantwortet von ericmarch Experte (4.6k Punkte)
«ActiveSheet.UsedRange.Columns.Count» warum macht das Bauchschmerzen?


Dazu müsstest du ein Makro haben, dass die den Wert anzeigt. Fülle mal ein paar Spalten und lass dir den Wert zurückgeben. Dann löschen daraus ganze (!) Spalten und lasse dir wieder den Wert geben. Nun leere manuell die Spalteninhalte von 1, 2 Spalten am rechten Endes des Spielfeldes - nur Inhalte, nicht ganze Spalten an sich löschen. Wenn du wieder den Wert abfragst solltest du wieder dne vorigen bekommen: die geleerten Spalten sind ‹used›, verwendet. Und das gibt falsche Rückgaben.

Wie würde bei dir die Zeile lauten, die die letzte benutzte Spalte ermittelt?

Falsche Frage: Es müsste »mit Werten besetze« Spalte heißen. Nur ist der Haken der, dass man eine Zeile braucht die durchgänig befüllt ist (ansonsten muss man es wie das Gehirn machen: gucken und Zelle um Zelle vergleichen..!) Ist es durchgängig befüllt läuft man von vorn los bis man auf eine leere Zelle trifft. Bei Lücken (das passt öfter auf Zeilen) muss man von rechts her zähen bis man einen Treffer landet. Klingt armselig, aber nur so ist der Wert sicher.

Für den Moment,
Eric March
...