Discussion:
Fragen zur Adressierung von Zellen
(zu alt für eine Antwort)
Gerald Aichholzer
2005-02-10 16:25:31 UTC
Permalink
Hallo NG,

ich kenne mit zwar mit VBA recht gut aus, hab jedoch
kaum Erfahrung mit Excel. Daher habe ich ein paar Fra-
gen, die hoffentlich nicht zu einfach erscheinen:


Eine Zelle kann man über Range() und Cells() ansprechen.
Gibt es einfache Umrechnungsmöglichkeiten, um aus einer
Adresse (z.B. B7) die Zeile und Spalte zu erhalten und
umgekehrt?


Welches ist die effizenteste Methode, um Zellen (kein
zusammenhängender Bereich) mit VBA zu füllen? Ich muss
mehrere hundert Werte von einer Datenbank per VBA in
Zellen laden und möchte das möglichst performant durch-
führen.


Wie heisst die Eigenschaft, um in VBA den Namen einer
benannten Zelle herauszukriegen?


Gibt es eine einfache Möglichkeit, die Namen aller be-
nannten Zellen in einem Bereich zu erhalten? (d.h. ohne
eine doppelte For-Schleife und Abfrage der Zellen)

Hintergrund: im Workbook_SheetChange()-Ereignis über-
wache ich die Änderung der Zellen. Sobald eine benannte
Zelle geändert wurde, soll diese in die Datenbank ge-
speichert werden.

Oder weiss jemand eine bessere Lösung für diese Problem-
stellung?


Herzlichen Dank für die Geduld :)

schöne Grüße,
Gerald
Robert Gelbmann
2005-02-10 16:57:04 UTC
Permalink
Hi Gerald!

Einfachkeitshalber habe ich die Antworten in deinen Text eingebaut.
(Sorry, falls es dadurch schlechter lesbar wird.)
Post by Gerald Aichholzer
Eine Zelle kann man über Range() und Cells() ansprechen.
Gibt es einfache Umrechnungsmöglichkeiten, um aus einer
Adresse (z.B. B7) die Zeile und Spalte zu erhalten und
umgekehrt?
Ich nehme an, die Eigenschaften Row und Column sollten dir dafür
reichen:

MsgBox Range("B7").Row ' liefert die Zahl 7
MsgBox Range("B7").Column ' liefert die Zahl 2
Post by Gerald Aichholzer
Welches ist die effizenteste Methode, um Zellen (kein
zusammenhängender Bereich) mit VBA zu füllen? Ich muss
mehrere hundert Werte von einer Datenbank per VBA in
Zellen laden und möchte das möglichst performant durch-
führen.
Wenn die Zellen nicht zusammenhängen, geht dies stark zur Lasten der
Performance.
Am "schlimmsten" ist es logischerweise, jede Zelle einzeln zu
behandeln. Also, wenn du wenigstens ein paar "Blöcke" hast, könnte man
da wesentlich mehr tun ...

Ansonsten, ganz allgemein:

(1) Bildschirmaktualisierung deaktivieren (bringt meist enorm viel):
Application.ScreenUpdating = False
' und nachher selbstverständlich wieder auf True setzen

(2) Vermutlich lohnt sich auch die vorübergehende Deaktivierung der
automatischen Neuberechnung, damit Excel nicht bei jeder einzigen
Eingabe alles neuberechnet:
Application.Calculation = xlCalculationManual
' und nachher wieder - je nachdem wie es in der betreffenden
' Arbeitsmappe war - auf xlCalculationAutomatic bzw.
xlCalculationSemiautomatic
Post by Gerald Aichholzer
Wie heisst die Eigenschaft, um in VBA den Namen einer
benannten Zelle herauszukriegen?
Name? ;-)

' Je nach Excel-Version entweder
MsgBox Range("B7").Name
' oder noch weiter konkretisiert (Der Name des Namens):
MsgBox Range("B7").Name.Name

Allerdings erhältst du einen Laufzeitfehler für Zellen bzw.
Zellbereiche, die keinen "Namen" haben.
(Eventuell hilft dir aber dann ein Blick in Hilfe zur Names-Liste des
Workbook-Objektes.)
Post by Gerald Aichholzer
Gibt es eine einfache Möglichkeit, die Namen aller be-
nannten Zellen in einem Bereich zu erhalten? (d.h. ohne
eine doppelte For-Schleife und Abfrage der Zellen)
Um die Abfrage der Namen auf einen bestimmten Bereich einzugrenzen,
gibt es keine eigene VBA-Funktion oder dergleichen.
Eventuell kannst du aber einfach umgekehrt (dh. nach den benannten
Zellen) fragen:

If Range("MeinName").Address = Target.Address Then
' Jetzt in die Datenbank schreiben ...
End If

Achte aber darauf, dass der jeweilige Name auch tatsächlich zum
entsprechenden Tabellenblatt gehört.
--
In der Hoffnung damit behilflich gewesen zu sein, verbleibe ich mit
einem leisen

Servus aus Wien,
-Robert Gelbmann-

---
Excel-FAQ's: http://www.roehrenbacher.at/erc/faq/
Gerald Aichholzer
2005-02-10 17:11:35 UTC
Permalink
Hallo Robert,

herzlichen Dank für deine Antwort - du hast mir wirklich sehr
geholfen. Ist ja richtig schön, wie einfach manche Sachen sind ;)
Post by Robert Gelbmann
Einfachkeitshalber habe ich die Antworten in deinen Text eingebaut.
(Sorry, falls es dadurch schlechter lesbar wird.)
Eigentlich ist es genau das, was in einer NG unter korrektem
Zitieren verstanden wird - zumindest mir hat man es so beige-
bracht :)
Post by Robert Gelbmann
Post by Gerald Aichholzer
Welches ist die effizenteste Methode, um Zellen (kein
zusammenhängender Bereich) mit VBA zu füllen? Ich muss
mehrere hundert Werte von einer Datenbank per VBA in
Zellen laden und möchte das möglichst performant durch-
führen.
Wenn die Zellen nicht zusammenhängen, geht dies stark zur Lasten der
Performance.
Am "schlimmsten" ist es logischerweise, jede Zelle einzeln zu behandeln.
Also, wenn du wenigstens ein paar "Blöcke" hast, könnte man da
wesentlich mehr tun ...
Eigentlich gibt es viele Blöcke zu ca. 5-10 Zellen. Was für
Möglichkeiten würden sich da ergeben, die du leicht angedeu-
tet hast?
Post by Robert Gelbmann
Application.ScreenUpdating = False
' und nachher selbstverständlich wieder auf True setzen
(2) Vermutlich lohnt sich auch die vorübergehende Deaktivierung der
automatischen Neuberechnung, damit Excel nicht bei jeder einzigen
Application.Calculation = xlCalculationManual
' und nachher wieder - je nachdem wie es in der betreffenden
' Arbeitsmappe war - auf xlCalculationAutomatic bzw.
xlCalculationSemiautomatic
Danke - auf das Abschalten der Neuberechnung habe ich fast
vergessen. In meinem Fall wird es sicher sehr viel bringen,
da von jedem einzulesenden Wert mehrere berechnete Zellen
abhängen.
Post by Robert Gelbmann
Post by Gerald Aichholzer
Wie heisst die Eigenschaft, um in VBA den Namen einer
benannten Zelle herauszukriegen?
Name? ;-)
' Je nach Excel-Version entweder
MsgBox Range("B7").Name
MsgBox Range("B7").Name.Name
Kann ich eine der beiden Variante ab Excel 97 verwenden
oder muss ich zwei separate Versionen erstellen?
Post by Robert Gelbmann
Post by Gerald Aichholzer
Gibt es eine einfache Möglichkeit, die Namen aller be-
nannten Zellen in einem Bereich zu erhalten? (d.h. ohne
eine doppelte For-Schleife und Abfrage der Zellen)
Um die Abfrage der Namen auf einen bestimmten Bereich einzugrenzen, gibt
es keine eigene VBA-Funktion oder dergleichen.
Eventuell kannst du aber einfach umgekehrt (dh. nach den benannten
If Range("MeinName").Address = Target.Address Then
' Jetzt in die Datenbank schreiben ...
End If
Achte aber darauf, dass der jeweilige Name auch tatsächlich zum
entsprechenden Tabellenblatt gehört.
Ein guter Vorschlag. Wenn Target.Address auch ein Bereich
sein kann (ich verwende das Worksheet_Change-Ereignis),
dann muss ich wohl so vorgehen:

For lIndex = 1 to lNameCount
If Not Intersect( Range(asName(lIndex)).Address,
Target.Address) Is Nothing Then
' ...
' hier mach ich meine Arbeit
'
End If
Next

Oder gibt es da eine einfachere Variante? Mit = darf ich
nicht vergleichen, da im Worksheet_Change-Ereignis Target
auch mehrere Zellen umfassen kann.

danke und schöne Grüße,
Gerald
Robert Gelbmann
2005-02-10 17:35:20 UTC
Permalink
Hi Gerald!
Post by Gerald Aichholzer
[...]
Eigentlich gibt es viele Blöcke zu ca. 5-10 Zellen. Was für
Möglichkeiten würden sich da ergeben, die du leicht angedeu-
tet hast?
(1) Allgemein:
Copy/Paste bzw. PasteSpecial von Zellbereich ist in der Regel
wesentlich schneller als das Adressieren einzelner Zellen.
Aber das bringt dir nur dann etwas, wenn du die gesammelten Daten in
einem großen Block nach Excel bekommen kannst und sie erst dann
aufteilst.

(2) Feldvariablen
Erfahrungsgemäß ist es wesentlich effizienter (schneller) die Daten
zunächst in eine Feldvariable zu schreiben und dann in einem Block in
den Zellbereich zu übertragen. Dazu ein Minibeispiel:


' Passend dimensionieren:
Dim varMeinBereich(1 To 2, 1 To 3) 'zuerst Zeilen, dann Spalten

' Zunächst werden von mir Dummy-Werte
' in die Variable gefüttert:
' (Stattdessen müsstest du hier die Werte aus
' der Datenbank abfragen und einfüttern.)
For i = 1 To 2
For j = 1 To 3
varMeinBereich(i, j) = i * j
Next
Next

' Und jetzt alles auf einmal übertragen:
Range("A2:C3").Value = varMeinBereich()
Post by Gerald Aichholzer
Kann ich eine der beiden Variante ab Excel 97 verwenden
oder muss ich zwei separate Versionen erstellen?
Ich habe früher immer die erste Variante verwendet:
MsgBox Range("B7").Name

Diese scheint jedoch zumindest ab Excel 2003 nicht mehr zuverlässig zu
funktionieren.
Ich habe es zwar in älteren Versionen noch nicht ausprobiert, aber ich
denke, die zweite Variante sollte eigentlich immer funktionieren:
MsgBox Range("B7").Name.Name
Post by Gerald Aichholzer
Ein guter Vorschlag. Wenn Target.Address auch ein Bereich
sein kann (ich verwende das Worksheet_Change-Ereignis),
For lIndex = 1 to lNameCount
If Not Intersect( Range(asName(lIndex)).Address,
Target.Address) Is Nothing Then
' ...
' hier mach ich meine Arbeit
'
End If
Next
(1) Intersect verlangt als Parameter Range-Objekte (und nicht die von
Address gelieferten Strings):

If Not Intersect( Range(asName(lIndex)), _
Target) Is Nothing Then
' usw.


(2) Eventuell kannst du die verschiedenen Namen zu einem großen
Range-Objekt zusammenfügen:

Dim rng as Range
Set rng = Range(asName(1))
For lIndex = 2 to lNameCount
Set rng = Range(Rng, Range(asName(lIndex)))
Next

If Not Intersect(rng, Target) Is Nothing Then
' ...
' hier mach ich meine Arbeit
'
End If

Set rng = Nothing


So sollte es eigentlich schneller sein ...
--
In der Hoffnung damit behilflich gewesen zu sein, verbleibe ich mit
einem leisen

Servus aus Wien,
-Robert Gelbmann-

---
Excel-FAQ's: http://www.roehrenbacher.at/erc/faq/
Gerald Aichholzer
2005-02-10 19:25:23 UTC
Permalink
Hallo Robert,
Post by Gerald Aichholzer
[...]
Eigentlich gibt es viele Blöcke zu ca. 5-10 Zellen. Was für
Möglichkeiten würden sich da ergeben, die du leicht angedeu-
tet hast?
Copy/Paste bzw. PasteSpecial von Zellbereich ist in der Regel wesentlich
schneller als das Adressieren einzelner Zellen.
Aber das bringt dir nur dann etwas, wenn du die gesammelten Daten in
einem großen Block nach Excel bekommen kannst und sie erst dann aufteilst.
(2) Feldvariablen
Erfahrungsgemäß ist es wesentlich effizienter (schneller) die Daten
zunächst in eine Feldvariable zu schreiben und dann in einem Block in
[snip]
Range("A2:C3").Value = varMeinBereich()
danke für die beiden Tipps - vor allem von Zweiterem habe ich
nicht gewusst, dass es so überhaupt funktioniert.
(2) Eventuell kannst du die verschiedenen Namen zu einem großen
Dim rng as Range
Set rng = Range(asName(1))
For lIndex = 2 to lNameCount
Set rng = Range(Rng, Range(asName(lIndex)))
Next
If Not Intersect(rng, Target) Is Nothing Then
' ...
' hier mach ich meine Arbeit
'
End If
Set rng = Nothing
So sollte es eigentlich schneller sein ...
Das schon, aber ich habe mir gedacht, dass ich nur jene Werte
bearbeite (d.h. in die Datenbank schreibe), die sich geändert
haben. Wenn ich die zweite Variante verwende, dann muss ich
erst wieder prüfen, welches Feld sich geändert hat (oder ich
speichere immer alle Werte ab - könnte ich auch machen, wenn
die Performance in diesem Fall gleich gut oder besser ist).


Mit 99% Wahrscheinlichkeit (Auge-mal-Pi-Abschätzung) ändert
sich nur eine Zelle, da der Anwender die Werte manuell eingibt.

Dennoch muss ich den Fall berücksichtigen, dass mehrere Zellen
zugleich geändert werden (z.B. beim Kopieren von der Zwischen-
ablage wird Worksheet_Change() nur 1x aufgerufen).


danke und schöne Grüße,
Gerald
Gerald Aichholzer
2005-02-11 07:06:18 UTC
Permalink
Hallo Robert,
Post by Robert Gelbmann
Post by Gerald Aichholzer
Wie heisst die Eigenschaft, um in VBA den Namen einer
benannten Zelle herauszukriegen?
Name? ;-)
' Je nach Excel-Version entweder
MsgBox Range("B7").Name
MsgBox Range("B7").Name.Name
Allerdings erhältst du einen Laufzeitfehler für Zellen bzw.
Zellbereiche, die keinen "Namen" haben.
(Eventuell hilft dir aber dann ein Blick in Hilfe zur Names-Liste des
Workbook-Objektes.)
ich habe gestern noch schnell einen Prototyp gebastelt, dabei
ist mir aufgefallen, dass es die Names-Liste nur für das Work-
book-Objekt gibt.

Ich würde gerne im Worksheet_Change-Ereignis alle Namen dieses
Arbeitsblattes durchgehen. Die gesamte Anwendung hat mehrere
hundert Namen, je Arbeitsblatt jedoch nur eine zweistellige
Anzahl.

Gibt es eine schnelle Methode, um nur zu den Namen eines Ar-
beitsblattes zu kommen?

Notfalls muss ich die relevanten Daten in einem Array oder
einer Collection speichern - nur muss ich dann beim Ändern
des Arbeitsblattes (Namen hinzu oder weg) auch den VBA-Code
anpassen.

danke und schöne Grüße,
Gerald
Robert Gelbmann
2005-02-11 09:18:27 UTC
Permalink
Hi Gerald!
Post by Gerald Aichholzer
[...]
ich habe gestern noch schnell einen Prototyp gebastelt, dabei
ist mir aufgefallen, dass es die Names-Liste nur für das Work-
book-Objekt gibt.
Korrekt, Namen "gehören" definitionsgemäß der Arbeitsmappe.
Oder wie MS gerne schreibt: "This is by design."
Post by Gerald Aichholzer
Ich würde gerne im Worksheet_Change-Ereignis alle Namen dieses
Arbeitsblattes durchgehen. Die gesamte Anwendung hat mehrere
hundert Namen, je Arbeitsblatt jedoch nur eine zweistellige
Anzahl.
Gibt es eine schnelle Methode, um nur zu den Namen eines Ar-
beitsblattes zu kommen?
Schnell? Nicht wirklich!
Ohne zu wissen, welche Namen/Zellen überhaupt relevant sind, bleibt dir
wohl nur noch die Names-Liste mittels einer For-Each-Schleife
abzuarbeiten und dabei die RefersTo-Eigenschaft des Name-Objektes auf
den jeweiligen Blattnamen hin zu prüfen. (Was für ein Satz! ;-))

Umgekehrt angedacht:
Gibt es wirklich eine unbegrenzte / vom Benutzer frei definierbare
Anzahl von relevanten Namen??
Wenn dem nämlich nicht so ist, wäre es sicherlich einfacher - z. B. auf
einem versteckten/ausgeblendeten Blatt - eine Liste der pro Blatt
relevanten Bereichsnamen zu führen und nur diese zu prüfen.
--
In der Hoffnung damit behilflich gewesen zu sein, verbleibe ich mit
einem leisen

Servus aus Wien,
-Robert Gelbmann-

---
Excel-FAQ's: http://www.roehrenbacher.at/erc/faq/
Gerald Aichholzer
2005-02-11 19:05:40 UTC
Permalink
Post by Robert Gelbmann
Post by Gerald Aichholzer
Ich würde gerne im Worksheet_Change-Ereignis alle Namen dieses
Arbeitsblattes durchgehen. Die gesamte Anwendung hat mehrere
hundert Namen, je Arbeitsblatt jedoch nur eine zweistellige
Anzahl.
Gibt es eine schnelle Methode, um nur zu den Namen eines Ar-
beitsblattes zu kommen?
Schnell? Nicht wirklich!
Ohne zu wissen, welche Namen/Zellen überhaupt relevant sind, bleibt dir
wohl nur noch die Names-Liste mittels einer For-Each-Schleife
abzuarbeiten und dabei die RefersTo-Eigenschaft des Name-Objektes auf
den jeweiligen Blattnamen hin zu prüfen. (Was für ein Satz! ;-))
Gibt es wirklich eine unbegrenzte / vom Benutzer frei definierbare
Anzahl von relevanten Namen??
Wenn dem nämlich nicht so ist, wäre es sicherlich einfacher - z. B. auf
einem versteckten/ausgeblendeten Blatt - eine Liste der pro Blatt
relevanten Bereichsnamen zu führen und nur diese zu prüfen.
Hallo Robert,

der Anwender hat eigentlich in meinem Anwendungsfall überhaupt
keinen Einfluss auf die Namen. Wir arbeiten zu zweit an diesem
Projekt: meine Kollegin ohne VBA-Kenntnisse, aber mit guten
Excel-Kenntnissen, und ich, der die VBA-Module beisteuert.

Ich wollte ein Modul schaffen, dass ich nicht bei jedem neuen
Namen anpassen muss.

In diesem Fall verwalte ich die in Frage kommenden Namen gleich
selbst in einer Collection (oder Array) pro Arbeitsblatt und er-
spare mir die von dir erwähnte Suche. In einem Modul gibt es
über 700 Namen, die auf sehr viele Arbeitsblätter verteilt sind.
Da wäre es Overkill, jedesmal die gesamte Liste durchzugehen ;)

danke und schöne Grüße,
Gerald
Thomas Ramel
2005-02-12 09:13:42 UTC
Permalink
Grüezi Gerald

Gerald Aichholzer schrieb am 11.02.2005
Post by Gerald Aichholzer
Ich würde gerne im Worksheet_Change-Ereignis alle Namen dieses
Arbeitsblattes durchgehen. Die gesamte Anwendung hat mehrere
hundert Namen, je Arbeitsblatt jedoch nur eine zweistellige
Anzahl.
Gibt es eine schnelle Methode, um nur zu den Namen eines Ar-
beitsblattes zu kommen?
Mir fehlt noch ein wenig der Hintergrund deiner Anwendung.

Doch Du könntest einen Bereichsmanen verwenden, der alle zellen enthält,
die einen Namen haben.

Auf diese Weise kannst Du *einmal* prüfen, ob eine veränderte Zelle in
diesem Bereich liegt und dann entsrpechend reagieren.

Dazu müsstest Du den Geamt-Bereich jeweisl um die Adressen der neuen Namen
erweitern - wobei die Union()-Methode vermutlich behilflich sein könnte.

Ist es denn notwendig, dass die zellen alle einzelnen namen haben -
könntest Du nicht pro Tabellenblatt mir nur einem Bereichsnamen arbeiten?




Mit freundlichen Grüssen
Thomas Ramel
--
- MVP für Microsoft-Excel -
[Win XP Pro SP-2 / xl2000 SP-3]
Gerald Aichholzer
2005-02-12 09:52:32 UTC
Permalink
Post by Thomas Ramel
Gerald Aichholzer schrieb am 11.02.2005
Post by Gerald Aichholzer
Ich würde gerne im Worksheet_Change-Ereignis alle Namen dieses
Arbeitsblattes durchgehen. Die gesamte Anwendung hat mehrere
hundert Namen, je Arbeitsblatt jedoch nur eine zweistellige
Anzahl.
Gibt es eine schnelle Methode, um nur zu den Namen eines Ar-
beitsblattes zu kommen?
Mir fehlt noch ein wenig der Hintergrund deiner Anwendung.
Doch Du könntest einen Bereichsmanen verwenden, der alle zellen enthält,
die einen Namen haben.
Auf diese Weise kannst Du *einmal* prüfen, ob eine veränderte Zelle in
diesem Bereich liegt und dann entsrpechend reagieren.
Dazu müsstest Du den Geamt-Bereich jeweisl um die Adressen der neuen Namen
erweitern - wobei die Union()-Methode vermutlich behilflich sein könnte.
Ist es denn notwendig, dass die zellen alle einzelnen namen haben -
könntest Du nicht pro Tabellenblatt mir nur einem Bereichsnamen arbeiten?
Hallo Thomas,

es geht darum, dass eine bereits existierende Excel-Anwendung so
erweitert wird, dass die eingegebenen Werte in einer Datenbank
gespeichert werden und aus dieser wieder abrufbar sind.

Konkret geht es um ein Bilanzanalysetool, das aus mehreren Kom-
ponenten besteht. Bis jetzt wurden die Daten immer manuell ein-
gegeben. Nachdem alle Tools die selbe Datenbasis verwenden wird
zur Zeit über diese Erweiterung nachgedacht.

Die Namen sind bereits vergeben - meine Idee ist, einfach alle
Zellen, die einen Namen besitzen, im Worksheet_Change-Ereignis
zu überwachen und bei Änderung des Wertes in die Datenbank abzu-
legen.

Daher hilft mir die Information, eine der Zellen hat sich ge-
ändert, nichts, sondern ich muss wissen, welche Zelle sich ge-
ändert hat.

Es könnte sein, dass es performanter ist, bei Änderung einer
betroffenen Zelle, einfach alle in die Datenbank zu schreiben
(wenn das Prüfen auf Änderung langsamer ist als das Schreiben
in die Datenbank).

lg,
Gerald
Thomas Ramel
2005-02-12 11:54:04 UTC
Permalink
Grüezi Gerald

Gerald Aichholzer schrieb am 12.02.2005
Post by Gerald Aichholzer
Die Namen sind bereits vergeben - meine Idee ist, einfach alle
Zellen, die einen Namen besitzen, im Worksheet_Change-Ereignis
zu überwachen und bei Änderung des Wertes in die Datenbank abzu-
legen.
Daher hilft mir die Information, eine der Zellen hat sich ge-
ändert, nichts, sondern ich muss wissen, welche Zelle sich ge-
ändert hat.
Das könntest Du ev. so erledigen:

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo ErrorHandler
Application.EnableEvents = False

Dim rngZelle As Range
For Each rngZelle In Target

If Target.Address (0,0) = 'Deine Zellen'.Address(0,0) then
'Dein Code zur Bearbeitung der Zelle
End If

Next rngZelle
ErrorHandler:
Application.EnableEvents = True

End Sub





Mit freundlichen Grüssen
Thomas Ramel
--
- MVP für Microsoft-Excel -
[Win XP Pro SP-2 / xl2000 SP-3]
Gerald Aichholzer
2005-02-12 13:50:50 UTC
Permalink
Post by Thomas Ramel
Gerald Aichholzer schrieb am 12.02.2005
Post by Gerald Aichholzer
Die Namen sind bereits vergeben - meine Idee ist, einfach alle
Zellen, die einen Namen besitzen, im Worksheet_Change-Ereignis
zu überwachen und bei Änderung des Wertes in die Datenbank abzu-
legen.
Daher hilft mir die Information, eine der Zellen hat sich ge-
ändert, nichts, sondern ich muss wissen, welche Zelle sich ge-
ändert hat.
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Error GoTo ErrorHandler
Application.EnableEvents = False
Dim rngZelle As Range
For Each rngZelle In Target
If Target.Address (0,0) = 'Deine Zellen'.Address(0,0) then
'Dein Code zur Bearbeitung der Zelle
End If
Next rngZelle
Application.EnableEvents = True
End Sub
Hallo Thomas,

so ähnlich mache ich es zur Zeit auch - meine Ursprungsfrage war
so gemeint, ob ich nicht den Teil 'Meine Zellen' vereinfachen
kann. Gesucht wäre so etwas wie:

For Each singleCell in Target.Cells
For Each myCell in myCells
If singleCell.Address(0,0) = myCell.Address(0,0) Then
bSuccess = SaveCellToDatabase(myCell)
End If
Next myCell
Next singleCell

MyCells soll alle benannten Zellen des aktuellen Arbeitsblattes
beinhalten (ohne diese per Code initialisieren zu müssen). Wenn
es die Names-Auflistung pro Arbeitsblatt geben würde, dann wäre
es genau das, was ich suche. Leider gibt es die Names-Auflistung
nur pro Workbook (wie heißt das auf Deutsch? *g*).

Das Problem ist lösbar, ich muss halt die myCells-Auflistung pro
Arbeitsblatt per VBA initialisieren - das wollte ich mir halt er-
sparen, z.B. für jedes Arbeitsblatt (Pseudocode):

Dim myCells(Workbook.Worksheets.Count) As Collection

myCells(1).Add Worksheets(1).Range("Name1")
myCells(1).Add Worksheets(1).Range("Name2")
myCells(1).Add Worksheets(1).Range("Name3")
myCells(1).Add Worksheets(1).Range("Name4")
...
myCells(2).Add Worksheets(2).Range("Name5")
...

Da es in einem Modul über 700 Zellen mit Namen sind, ist das
irgendwie mühselig. Ich könnte einen Generator schreiben, der
mir den Code automatisch erzeugt - mal sehen, was weniger Auf-
wand ist ;)

schöne Grüße,
Gerald


BTW: darf ich das so schreiben wie oben oder muss ich doch fol-
genden Code verwenden:

For Each singleArea in Target.Areas
For Each singleCell in Target.Cells
....
Next
Next
Thomas Ramel
2005-02-14 06:29:58 UTC
Permalink
Grüezi Gerald

Gerald Aichholzer schrieb am 12.02.2005
Post by Gerald Aichholzer
Post by Thomas Ramel
Gerald Aichholzer schrieb am 12.02.2005
Post by Gerald Aichholzer
Die Namen sind bereits vergeben - meine Idee ist, einfach alle
Zellen, die einen Namen besitzen, im Worksheet_Change-Ereignis
zu überwachen und bei Änderung des Wertes in die Datenbank abzu-
legen.
Daher hilft mir die Information, eine der Zellen hat sich ge-
ändert, nichts, sondern ich muss wissen, welche Zelle sich ge-
ändert hat.
Hmmm, ja und da die Namen bereits vergebensind, kannst Du sie auch schlecht
in einen gemeinsamen Bereichs zusammenfassen...

[Mein Code gesnippt]
Post by Gerald Aichholzer
so ähnlich mache ich es zur Zeit auch - meine Ursprungsfrage war
so gemeint, ob ich nicht den Teil 'Meine Zellen' vereinfachen
For Each singleCell in Target.Cells
For Each myCell in myCells
If singleCell.Address(0,0) = myCell.Address(0,0) Then
bSuccess = SaveCellToDatabase(myCell)
End If
Next myCell
Next singleCell
MyCells soll alle benannten Zellen des aktuellen Arbeitsblattes
beinhalten (ohne diese per Code initialisieren zu müssen). Wenn
es die Names-Auflistung pro Arbeitsblatt geben würde, dann wäre
es genau das, was ich suche. Leider gibt es die Names-Auflistung
nur pro Workbook (wie heißt das auf Deutsch? *g*).
Namen sind nun mal per Definition über die gesamte Mappe gültig....
...jedoch enthalten sie immer auch den Bezug zum Tabellenblatt im 'Refers
to'.
Du könntest also ein String-Array aufbauen (anstelle deiner Collection)
Und entsprechend beim Wechsel auf ein neues Tabellenblatt alle diese Bezüge
in ein zweites String-Array übertragen, das Du dann entsprechend
vergleichst. Dazu könntest Du die 'Filter()'-Methode verwenden.


Doch wenn Du dich entschliessen kannst, einen etwas ungewöhnlichen Weg zu
gehen, dann wäre ev. folgende eine Lösung:

Hast Du Gültigkeiten in einzelen Zellen der Mappe (nicht bloss in mit Nemen
versehenen) festgelegt?
Falls nein, dann lege für jede benannte Zelle eine Datengültigkeit fest
indem Du beim öffnen der Datei die folgende Sub laufen lässt:

Public Sub Name_Initialize()
Dim naName As Name
ReDim arNamen(ThisWorkbook.Names.Count)
For Each naName In ThisWorkbook.Names
With naName.RefersToRange.Validation
.Delete
.Add Type:=xlValidateList, Formula1:=" "
.InCellDropdown = False
.ShowError = False
End With
Next naName
End Sub

Jede benannte Zelle in der Mappe hat nun eine Gültigkeit mit einem
Leerzeichen erhalten, die aber bei einer anderen Eingabe keine
Fehlermeldung erzeugt.

Nun kannst Du im Workbook_SheetChange() wie folgt darauf reagieren:

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Set Target = Intersect(Target,
Sh.Cells.SpecialCells(xlCellTypeAllValidation))
If Target Is Nothing Then Exit Sub

On Error GoTo ErrorHandler
Application.EnableEvents = False
Dim rngZelle As Range
For Each rngZelle In Target
MsgBox rngZelle.Address(0, 0)
Next rngZelle

ErrorHandler:
Application.EnableEvents = True
End Sub
Post by Gerald Aichholzer
Da es in einem Modul über 700 Zellen mit Namen sind, ist das
irgendwie mühselig. Ich könnte einen Generator schreiben, der
mir den Code automatisch erzeugt - mal sehen, was weniger Auf-
wand ist ;)
Solange es nicht mehr als ca. 8000 unzusammenhängende Bereiche sind, greift
die SpecialCells-Methode ohne Probleme und du kannst auf die Erfassung der
einzelnen Namen verzichten.
Oder aber Du verwendest die For...Each Methode wie oben gezeigt und erfasst
so alle Namen, filterst dann aber die entsprechenden Tabellenblätter
heraus.




Mit freundlichen Grüssen
Thomas Ramel
--
- MVP für Microsoft-Excel -
[Win XP Pro SP-2 / xl2000 SP-3]
Lesen Sie weiter auf narkive:
Loading...