Discussion:
Probleme mit Shape-Objekten
(zu alt für eine Antwort)
Manfred Gutacker
2007-10-21 07:26:38 UTC
Permalink
Hallo liebe Excel-Profis,

habe mal wieder ein Problem.

In einer großen XLS-Datei (7,5 MB), die ich von einem Kollegen zur Analyse
bekommen habe, befinden sich (sichtbar) eine mittelgroße Kalkulation und
ein paar Textboxen und 3 Autoformen.
Eine Untersuchung der Datei zeigte, dass sich hier über 40.000
Shapes-Objekte verbergen.
Ich habe diese per Makro alle gelöscht und dann im Vergleich mit der
Original-Datei die sichtbaren Shapes-Objekte wieder einzeln manuell
eingefügt. Ich konnte die Dateigröße so auf 50 kB reduzieren. Woher die
vielen "nutzlosen" Shapes kommen, müssen wir noch analysieren.

Nun meine Frage: Gibt es eine Möglichkeit, die unsichtbaren Shapes in der
Datei (selektierten Tabelle) zu löschen und die sichtbaren zu belassen.

Habe schon ein wenig experimentiert. Aber Excel straft mich mit
Fehlermeldungen wie" nicht genügend Speicher"...

Über einen erfolgreichen Tipp würde ich mich sehr freuen, da wir so
wertvollen Speicherplatz auf den Serverfestplatten sparen können.

Ich arbeite mit Windows XP Por SP2 und Excel 2003 SP2.

Viele Grüße
Manfred Gutacker
Lorenz Hölscher
2007-10-21 07:36:29 UTC
Permalink
Hallo Manfred,

ich hatte vor ein paar Jahren auch mal so eine Datei erhalten, auf der
"nur" 400 Shapes nutzlos herumlagen. Die waren allerdings nicht
unsichtbar, sondern (wegen eines aufgezeichneten Makros, bei dem
jemand dies Shape gemalt hatte) nur exakt aufeinander gestapelt. Wenn
Du Deine in sichtbare und unsichtbare unterteilen kannst, dann sollten
die sich eigentlich so löschen lassen:
___________________________
Sub UnsichtbareShapesLoeschen()
Dim shpDieses As Shape

For Each shpDieses In ActiveSheet.Shapes
If Not shpDieses.Visible Then
shpDieses.Delete
End If
Next
End Sub
__________________________________

Da ich hier keine 40.000 Shapes einrichten will, kann ich zum
Speicherüberlauf nix sagen.

tschö, Lorenz
Manfred Gutacker
2007-10-21 07:54:19 UTC
Permalink
Post by Lorenz Hölscher
Hallo Manfred,
ich hatte vor ein paar Jahren auch mal so eine Datei erhalten, auf der
"nur" 400 Shapes nutzlos herumlagen. Die waren allerdings nicht
unsichtbar, sondern (wegen eines aufgezeichneten Makros, bei dem
jemand dies Shape gemalt hatte) nur exakt aufeinander gestapelt. Wenn
Du Deine in sichtbare und unsichtbare unterteilen kannst, dann sollten
___________________________
Sub UnsichtbareShapesLoeschen()
Dim shpDieses As Shape
For Each shpDieses In ActiveSheet.Shapes
If Not shpDieses.Visible Then
shpDieses.Delete
End If
Next
End Sub
__________________________________
Da ich hier keine 40.000 Shapes einrichten will, kann ich zum
Speicherüberlauf nix sagen.
tschö, Lorenz
Hallo Lorenz,

danke für Deine schnelle Antwort.
Werde mal probieren, ob das mit dem Löschen der unsichtbaren Shapes so
funktioniert, dass die sichtbaren vorhanden bleiben.

Den Speicherüberlauf habe ich mit einer Testdatei erhalten, in der nur 2
Shapes von unsichtbar auf sichtbar geschaltet werden sollten.

mit dem kleine Makro

Sub test1()

Dim shp As Shapes
Dim sh As String

sh = ActiveSheet.Name
Set shp = Sheets(sh).Shapes

Sheets(sh).Shapes.SelectAll
Selection.Visible = msoFalse

End Sub

kann ich alle Shapes unsichtbar machen.

Im umgekehrten Fall
...
Selection.Visible = msoTrue
...

erhalte ich dann die besagte Fehlermeldung "Nicht genügend Speicher" ???

Ich nehme an, dass ich hier die Shapes einzeln in einer Schleife ansprechen
muss, damit der Fehler vermieden wird. Ist aber nich besonders logisch,
oder?

Viele Grüße
Manfred
Lorenz Hölscher
2007-10-21 08:12:14 UTC
Permalink
Hallo Manfred,

ja, mit Deinem Makro kriege ich auch einen Speicherüberlauf hin. Und
zwar nicht wegen des umgekehrten Falls, sondern schon beim zweiten
Aufruf! Es scheitert an der Zeile mit ".SelectAll".

Da hast Du auch einige überflüssige Zeilen drin. Was hälst Du von
folgender Version, die auch mehrfach läuft:
________________________________________

Sub ShapesSichtbarMachen()
Dim shpDieses As Shape

For Each shpDieses In ActiveSheet.Shapes
shpDieses.Visible = msoTrue
Next
End Sub

________________________________________

tschö, Lorenz
Manfred Gutacker
2007-10-21 08:49:18 UTC
Permalink
Post by Lorenz Hölscher
Hallo Manfred,
ja, mit Deinem Makro kriege ich auch einen Speicherüberlauf hin. Und
zwar nicht wegen des umgekehrten Falls, sondern schon beim zweiten
Aufruf! Es scheitert an der Zeile mit ".SelectAll".
Da hast Du auch einige überflüssige Zeilen drin. Was hälst Du von
________________________________________
Sub ShapesSichtbarMachen()
Dim shpDieses As Shape
For Each shpDieses In ActiveSheet.Shapes
shpDieses.Visible = msoTrue
Next
End Sub
________________________________________
tschö, Lorenz
Hallo Lorenz,

habe Deinen Makro ausprobiert.
Die Erkenntnis ist, dass die Shapes in meiner Datei leider alle sichtbar
sind. Es handelt sich teilweise auch um übereinander gestapelte Linien mit
der Farbe weiß, wodurch sie nicht direkt sichtbar sind und viele Textboxen
ohne Inhalt und...

Kennst Du vielleicht eine Quelle, wo man Beispiele des Zugriffs auf die
möglichen Eigenschaften von Shape-Objekten finden kann?
Kenne mich hier noch nicht gut aus. Bin eben nur hobbymäßiger VBA-User...

Viele Grüße
Manfred
Lorenz Hölscher
2007-10-21 09:18:43 UTC
Permalink
Hallo Manfred,

wenn Du den Code aus meinem Beispiel (oder wenigstens diese eine
Zeile) schreibst und hinter "shpDiese" den Punkt machst, erscheint
automatisch die Liste aller (Methoden und) Eigenschaften eines Shapes.
Das ist gerade bei Shapes aber sehr verzwickt und wenig intuitiv.
Probier mal folgende Eigenschaften:

___________________________________________
Sub ShapesAuflisten()
Dim shpDieses As Shape

For Each shpDieses In ActiveSheet.Shapes
If shpDieses.Line.ForeColor = vbWhite Then
shpDieses.Select
MsgBox "ist weiß"
'shpDieses.Delete
End If

If shpDieses.Type = msoTextBox Then
If shpDieses.TextFrame.Characters.Count = 0 Then
shpDieses.Select
MsgBox "ist leer"
'shpDieses.Delete
End If
End If
Next
End Sub
___________________________________________

tschö, Lorenz
Alexander Wolff
2007-10-21 10:30:50 UTC
Permalink
Du könntest "in den Hintergrund" gerückte oder geratene Shapes löschen, da
diese unsichtbar sind, weil sie sich hinter den zu erhaltenden Shapes
(oberste Ebene) größengleich verbergen. Zeichne mal die Aktionen "rechte
Maustaste, in den Hintergrund" auf und behandle danach im Code die
entsprechenden Eigenschaften.
--
Moin+Gruss Alexander - MVP für MS Excel - www.xxcl.de - mso2000sp3 --7-2
Manfred Gutacker
2007-10-21 12:39:02 UTC
Permalink
Post by Alexander Wolff
Du könntest "in den Hintergrund" gerückte oder geratene Shapes löschen, da
diese unsichtbar sind, weil sie sich hinter den zu erhaltenden Shapes
(oberste Ebene) größengleich verbergen. Zeichne mal die Aktionen "rechte
Maustaste, in den Hintergrund" auf und behandle danach im Code die
entsprechenden Eigenschaften.
Hallo Alexander,

habe in einer Beispiel-Datei ein paar Shape-Objekte untergebracht.

Den Code für "in den Hintergrund" habe ich aufgezeichnet:

ActiveSheet.Shapes("Text Box 2").Select
Selection.ShapeRange.ZOrder msoSendToBack

Mir gelingt es aber nicht die "ZOrder-Eigenschaft" eines Shape-Objektes per
Makro abzufragen.
Kannst Du mir hier evtl. helfen?


Viele Grüße
Manfred
Lorenz Hölscher
2007-10-21 13:15:41 UTC
Permalink
Hallo Manfred,

die Eigenschaft heißt ZOrderPosition. Und Du kannst kürzer schreiben:

x = ActiveSheet.Shapes("Text Box 2").ShapeRange.ZOrderPosition

Immer wenn auf eine VBA-Zeile ".Select" in der nächsten "Selection."
folgt, kannst Du beides weglassen und zu einer zusammenfassen.
Selection ist ein "Pfui!"-Objekt, weil es - wie hier so schön zitiert
wurde - "den Cursor wie einen Hund Gassi führt". Das dauert unnötig
lange und irritiert bestenfalls den/die Benutzer/in. Für Dein Makro
bringt es keinen Vorteil.

tschö, Lorenz
Manfred Gutacker
2007-10-21 15:59:05 UTC
Permalink
Post by Lorenz Hölscher
Hallo Manfred,
x = ActiveSheet.Shapes("Text Box 2").ShapeRange.ZOrderPosition
Immer wenn auf eine VBA-Zeile ".Select" in der nächsten "Selection."
folgt, kannst Du beides weglassen und zu einer zusammenfassen.
Selection ist ein "Pfui!"-Objekt, weil es - wie hier so schön zitiert
wurde - "den Cursor wie einen Hund Gassi führt". Das dauert unnötig
lange und irritiert bestenfalls den/die Benutzer/in. Für Dein Makro
bringt es keinen Vorteil.
tschö, Lorenz
Hallo Lorenz,
vielen Dank für Deine Tipps.

Habe jetzt Tugriff auf die Eigenschaft ZOrderPosition. Das hilft aber nicht
wirklich, da jedes Shape eine andere ZOrderPosition hat. Wenn dabei
identische Kopien übereinander liegen, kann man nicht herausfiltern, welche
ZOrderPosition zum obersten Shape gehört.
M. E. bleibt mir nur das Löschen aller Shapes und das manuelle Kopieren der
sichtbaren und gewollten Shapes der Original-Datei in die bereinigte Datei.
(siehe Start dieses Threads).

Dennoch vielen Dank an alle.

Viele Grüße
Manfred

Loading...