Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1252to1256
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Funktion zur Bestimmung eines Bereichs

Funktion zur Bestimmung eines Bereichs
Hartmut
Hallo zusammen,
ich habe schon so manche Lösung bei euch gefunden. Ein wirkliches tolles Forum.
Zu folgendem Problem habe ich verschiedene VBA-Schnipsel kombiniert, aber leider funktioniert das Ganze nicht.
Ziel: Ich möchte für Funktionen, die einen Bereich brauchen, z.B. Min(), den Bereich nicht explizit eingeben, sondern über eine Funktion berechnen. Der Bereich wird über die Gliederung von Zeilen definiert. Da ich nicht weiss wie ich die Gliederungsebene auslese, habe ich eine Hilfsspalte (Spalte A) erstellt in der die Gliederung nachgebildet ist. 1 steht für Ebene 1, 2 für Ebene 2 usw.
Berechnet wird der Bereich ab der Zelle in der die Formel steht.
Die Funktion:

Function Bereich() As range
'Deklaration von Variablen
Dim lngStartSpalte As Long
Dim lngStartZeile As Long, lngEnde As Long
Application.Volatile
'Zeile ab der der Bereich berechnet wird
lngStartZeile = range(Application.Caller.Address).row
lngStartSpalte = range(Application.Caller.Address).Column
If ActiveSheet.Cells(lngStartZeile + 1, 1).Value > ActiveSheet.Cells(lngStartZeile, 1).Value   _
_
_
Then
lngEnde = lngStartZeile + 1
'Berechnet das Ende des gruppierten Bereichs.
Do While ActiveSheet.Cells(lngEnde, 1) > ActiveSheet.Cells(lngStartZeile, 1)
If ActiveSheet.Cells(lngEnde, 1) = 0 Then Exit Do
lngEnde = lngEnde + 1
Loop
Set Bereich = range(Cells(lngStartZeile, lngStartSpalte), Cells(lngEnde - 1,  _
lngStartSpalte))
End If
End Function

Das Problem:
00.01.1900 - hier steht die Formel =Min(Bereich())
14.02.2012 - 1. Zeile des Bereichs
17.02.2012 - 2. Zeile des Bereichs
Erwartetes Ergebnis: 14.02.2012
Ergebnis der Berechnung: #Wert
Wenn ich mit F2 die Formel editiere (keine Veränderung, einfach nur rein und wieder raus aus der Zelle), dann ändert sich das Ergebnis auf 00.01.1900
Fehlerhinweis: Ein in der Formel verwendeter Wert ist vom falschen Datentyp.
Ich bin am Ende meines VBA-Wissens angekommen.
Weiss einer der Experten Rat?
Gruß
Hartmut

7
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Benutzer
Anzeige
AW: Funktion zur Bestimmung eines Bereichs
26.02.2012 21:16:28
fcs
Hallo Hartmut,
deine Funktion führt zu einem Zirkelbezug, da ein Bereich zurückgegeben wird, der in der Zelle beginnt, in der die Formel mit "Bereich()" steht. Der zurückgegeben Bereich muss aber mit der Zelle unterhalb der Zelle mit der Formel beginnen.
Kleine Anpassung, große Wirkung:
        Set Bereich = Range(Cells(lngStartZeile + 1, lngStartSpalte), _
Cells(lngEnde - 1, lngStartSpalte))

Gruß
Franz
AW: Funktion zur Bestimmung eines Bereichs
27.02.2012 16:44:20
Hartmut
Hallo Franz,
danke für Deine Antwort. Das hatte ich doch glatt übersehen.
Ich habe jetzt die Funktion angepasst:
Function Bereich() As Range
'Deklaration von Variablen
Dim lngStartSpalte As Long
Dim lngStartZeile As Long, lngEnde As Long
Application.Volatile
'Gibt die Zelle an aus der die Funktion aufgerufen wird.
'Zeile ab der der Bereich berechnet wird
lngStartZeile = Range(Application.Caller.Address).Row
lngStartSpalte = Range(Application.Caller.Address).Column
lngEnde = lngStartZeile + 1
'Berechnet das Ende des gruppierten Bereichs.
Do While Cells(lngEnde, 1).Value > Cells(lngStartZeile, 1).Value
If Cells(lngEnde, 1) = 0 Then Exit Do
lngEnde = lngEnde + 1
Loop
Set Bereich = Range(Cells(lngStartZeile + 1, lngStartSpalte), Cells(lngEnde - 1,  _
lngStartSpalte))
End Function

Funktioniert eigentlich wie gewollt, aber es gibt einige seltsame Nebeneffekte.
Wenn Änderungen in anderen Zellen gemacht werden, dann funktioniert die Neuberechnung nicht richtig.
Vermutung: In der Do-Schleife muss explizit die Zelle aus der die Formel aufgerufen wird benannt werden.
Aber wie geht das? Die Zeile der Aufrufzelle wird ja über "Range(Application.Caller.Address).Row" ermittelt.
Ich hoffe Du kannst mir helfen.
Gruß Hartmut
Anzeige
Zu Caller
27.02.2012 18:57:05
Luc:-?
Hallo Hartmut,
interessant, interessant, was so alles versucht wird… ;-)
Da ich auch öfter mit .Caller arbeite, mal Folgendes:
1. Sofern der eigentl Auslöser eine Zelle ist, repräsentiert .Caller ein Range-Objekt
2. Ist der Auslöser ein anderes Objekt, zeigt .Caller seinen Namen an, ist also quasi nur String.
3. Trifft weder 1 noch 2 zu, liefert .Caller einen Fehler.
Daran kann man schon mal einiges unterscheiden. Im Fall1 macht man bspw Folgendes:
Dim ac As Range
With Application
If TypeName(.Caller) = "Range" Then
Set ac = .Caller
Else: Exit Sub
End If
End With
Jetzt hat man ein ordentl deklariertes Range-Objekt, auf das auch der IntelliSense des VBE wunschgemäß reagiert. Außerdem siehst du daran, dass du dir die Zwischenschritte mit Address sparen kannst.
Zum eigentl Problem:
4. Natürl benötigst du auch die Zelle, aus der die udF gerufen wird, denn die ist ja Bestandteil des Bereichs, der von ihr zurückgegeben wdn soll. Dabei entsteht natürl auch immer ein Zirkelbezug. Das ist unvermeidbar! Also bleibt dir nur übrig, Iterationen zuzulassen, dann wird daraus kein Fehler.
5. Bei AutoKalk kann es mit solchen Fktt in Fmln immer gewisse Probleme geben, egal, ob mit oder ohne Application.Volatile, das ohnehin meist herzlich wenig nutzt, hier sowieso.
6. Wahrscheinl wäre alles viel einfacher, wenn du den Bereich in gewünschter Größe gleich (ggf Optional) der Fkt als Argument mitgibst und, falls es sich um dynamische Bereiche handelt, außerdem noch Kriterien, an denen das Bereichsende erkannt wdn kann. Die Fkt würde dann immer von der letzten Zeile/Spalte des Arguments aus nach dem Bereichsende suchen. Ein Zirkelbezug wird aber trotzdem entstehen, weshalb es ggf günstiger wäre, eine solche Fkt nicht in ZellFmln einzusetzen, sondern sie zu …
6. …einer rein internen Fkt zu machen, die von anderen udFktt, die so etwas benötigen, angewendet wird. Die treten dann in ZellFmln idR ja in ganz anderen Zellen auf, so dass es zu keinem Zirkelbezug kommen wird. Natürl wird dann auch .Caller nicht benötigt (→weil durch FktsArg ersetzt, dass in diesem Fall von der anwendenden Fkt geliefert wird), womit eine weitere Stolperstelle vermieden wäre.
Gruß Luc :-?
Anzeige
AW: Zu Caller
03.03.2012 20:36:26
hartmut
Hallo Luc,
vielen Dank für die ausführliche Antwort. Das mit der Unterfunktion ist interessant, aber dazu müsste ich den Bereich ja vorher ermitteln.
Ich hab e viel gelernt, dafür hezlichen Dank.
Gruß Hartmut
Bitte sehr! ;-) Gruß+schöSo! owT
03.03.2012 20:43:58
Luc:-?
:-?
AW: Funktion zur Bestimmung eines Bereichs
27.02.2012 21:41:23
fcs
Hallo Hartmut,
unter Berücksichtigung von Luc's Hinweisen und der definition einer Variablen für das Tabellenblatt in dem die Funktion aufgerufen wird sollte es dann funktionieren.
Ich hatte nur in einem Tabellenblatt getestet, da gab es natürlichen keine Nebeneffekte.
Gruß
Franz
Function Bereich() As Range
'Deklaration von Variablen
Dim lngStartSpalte As Long
Dim lngStartZeile As Long, lngEnde As Long
Dim wks As Worksheet
Application.Volatile
If TypeName(Application.Caller) = "Range" Then
Set wks = Application.Caller.Parent
'Zeile ab der der Bereich berechnet wird
lngStartZeile = Application.Caller.Row
lngStartSpalte = Application.Caller.Column
With wks
If .Cells(lngStartZeile + 1, 1).Value > .Cells(lngStartZeile, 1).Value Then
lngEnde = lngStartZeile + 1
'Berechnet das Ende des gruppierten Bereichs.
Do While .Cells(lngEnde, 1) > .Cells(lngStartZeile, 1)
If .Cells(lngEnde, 1) = 0 Then Exit Do
lngEnde = lngEnde + 1
Loop
Set Bereich = .Range(.Cells(lngStartZeile + 1, lngStartSpalte), _
.Cells(lngEnde - 1, lngStartSpalte))
End If
End With
End If
End Function

Anzeige
AW: Funktion zur Bestimmung eines Bereichs
03.03.2012 20:42:44
hartmut
Hallo Franz,
ich war die Woche beruflich untwerwegs, sorry für die späte Rückmeldung.
Vielen Dank, dass Du die Infos von Luc gleich mit eingearbeitet hast. Jetzt funktioniert alles wie gewollt.
Ihr seid echt klasse.
Vielleicht hast Du ja eine Idee wie ich die Hilfsspalte in der die Gliederungsebene manuell gepflegt werden muss ersetzten kann. Dann könnte ich mir den manuelen Eintrag der Gliederungsebene auch noch sparen.
Gruß Hartmut

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige