Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1940to1944
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

Problem mit Private Sub Workbook_SheetChange

Problem mit Private Sub Workbook_SheetChange
09.08.2023 08:11:20
Stefan
Hallo zusammen, ich habe folgenden Code an dem ich gerade verzweifel:

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)

On Error Resume Next ' Fehlerbehandlung deaktivieren

Dim ws As Worksheet
Dim checkRange As Range
Dim checkRange1 As Range
Dim rowNum As Long
Dim OutlookApp As Object
Dim OutlookMail As Object
Dim mailSubject As String
Dim mailBody As String
Dim reminderDate As Date
Dim calendarEvent As Object ' Variable für den Kalendereintrag

' Definiere das Arbeitsblatt, auf dem die Tabelle liegt
Set ws = ThisWorkbook.Worksheets("Kapazitäts_Eingabe")
Set checkRange = Sh.Range("A:A")
Set checkRange1 = Sh.Range("D:D")

If Sh.Name = "Kapazitäts_Eingabe" Then
' Überprüfe, ob die geänderte Zelle innerhalb des überwachten Bereichs liegt
If Not Intersect(Target, checkRange) Is Nothing Then
' Ermittele die Zeilennummer der geänderten Zelle
rowNum = Target.Row

' Überprüfe, ob "Auftrag" in der geänderten Zelle steht
If StrComp(UCase(Target.Value), "AUFTRAG", vbTextCompare) = 0 Then ' vbTextCompare für die Groß-/Kleinschreibung-unabhängige Überprüfung
' Wenn "Auftrag" gefunden wurde, setze den Wert in der 3. Zeile auf 100%
ws.Cells(rowNum, 3).Value = "100%" ' 1 entspricht 100%
End If
End If
End If


If Sh.Name = "Kapazitäts_Eingabe" Then
' Überprüfe, ob die geänderte Zelle innerhalb des überwachten Bereichs liegt
If Not Intersect(Target, checkRange1) Is Nothing Then
' Ermittele die Zeilennummer der geänderten Zelle
rowNum = Target.Row

' Überprüfen, ob in derselben Zeile in Spalte A (1) das Wort "Angebot" steht
If Sh.Cells(Target.Row, 1).Value = "Angebot" Then
' Überprüfen, ob der geänderte Wert "verloren" oder "abgelehnt" ist
If LCase(Target.Value) = "verloren" Or LCase(Target.Value) = "abgelehnt" Then
' Popup-Fenster anzeigen
ws.Cells(rowNum, 3).Value = "0%" ' 1 entspricht 0%
answer = MsgBox("Angebot nicht mehr relevant? Eventuelle Planungsdaten löschen?", vbYesNo + vbQuestion, "Bestätigung")

' Handhabung der Antwort
If answer = vbYes Then
' Wenn Ja ausgewählt wurde, die Zeile von U an leeren
Set rng = Sh.Range("U" & Target.Row & ":XFD" & Target.Row)
rng.ClearContents
End If
End If
End If
End If
End If

If Sh.Name = "Kapazitäts_Eingabe" Then
' Überprüfen, ob die Änderung in der Spalte "Status" stattgefunden hat
If Not Intersect(Target, checkRange1) Is Nothing Then
' Ermittele die Zeilennummer der geänderten Zelle
rowNum = Target.Row

' Überprüfe, ob "erledigt" in der geänderten Zelle steht
If StrComp(UCase(Target.Value), "ERLEDIGT", vbTextCompare) = 0 Then ' vbTextCompare für die Groß-/Kleinschreibung-unabhängige Überprüfung wenn "erledigt" gefunden wurde

' E-Mail-Versand
Set OutlookApp = CreateObject("Outlook.Application")
Set OutlookMail = OutlookApp.CreateItem(0)

' Hier müssen Sie den Namen der E-Mail-Empfänger einsetzen (XXXXX)
OutlookMail.To = "xxx@xxx.com"

' Hier können Sie den E-Mail-Betreff anpassen
mailSubject = "Wartungsvertragsstatus prüfen " & ws.Cells(Target.Row, 6).Value & " "
OutlookMail.Subject = mailSubject

' Hier wird der E-Mail-Text zusammengesetzt, der die betroffenen Informationen enthält
mailBody = "Das Projekt " & ws.Cells(Target.Row, 5).Value & " (Auftr.Nr.: " & ws.Cells(Target.Row, 6).Value & ")" & _
" wurde als erledigt deklariert, bitte Status Wartungsvertrag überprüfen."
OutlookMail.Body = mailBody

' Kalendereintrag erstellen
reminderDate = DateAdd("ww", 3, Now()) ' Datum für die Erinnerung (3 Wochen später)
Set calendarEvent = OutlookApp.CreateItem(1) ' 1 für Kalendereintrag
With calendarEvent
.Subject = mailSubject
.Start = reminderDate
.End = reminderDate
.AllDayEvent = True
.ReminderSet = True
.ReminderMinutesBeforeStart = 15 ' Erinnerung 15 Minuten vorher
.Body = mailBody
.Save ' Speichern des Kalendereintrags
End With

' E-Mail-Anhang hinzufügen (den Kalendereintrag)
OutlookMail.Attachments.Add calendarEvent

' E-Mail senden
OutlookMail.Send

' Freigeben der Ressourcen
Set OutlookMail = Nothing
Set OutlookApp = Nothing
End If
End If
End If

On Error GoTo 0 ' Fehlerbehandlung wieder aktivieren
Exit Sub
End Sub


An für sich funktioniert alles einwandfrei, das Problem das ich habe ist das er jedes mal wenn eine Zeile gelöscht oder hinzugefügt wird ebenfalls ausgeführt wird. D.h. ich bekomme bei löschen oder hinzufügen eine Email. Kann mir jemand veraten wie ich das verhindern kann?

Würde mich hier sehr über Hilfestellung freuen, bin da schon länger dran und kläglich gescheitert.

5
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Problem mit Private Sub Workbook_SheetChange
09.08.2023 09:17:18
Rudi Maintaire
Hallo,
warum machst du das über Workbook_SheetChange und nicht über das Worksheet_Change-Event? Dann kannst du dir die Abfrage des Blatts sparen.

Zum Problem: Beim Einfügen oder Löschen von Zeilen ist Target.Count &gt 1
Ergo:
If Target.Count =1 Then

'Code
End If


Gruß
Rudi
AW: Problem mit Private Sub Workbook_SheetChange
09.08.2023 09:44:57
Ulf


Option Explicit

Const BlattName = "Kapazitäts_Eingabe"

Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
On Local Error GoTo Workbook_SheetChangeERR
Dim ws As Worksheet
Dim rng As Range
Dim checkRange As Range
Dim checkRange1 As Range
Dim rowNum As Long
Dim OutlookApp As Object
Dim OutlookMail As Object
Dim mailSubject As String
Dim mailBody As String
Dim reminderDate As Date
Dim calendarEvent As Object ' Variable für den Kalendereintrag
Dim bInRange1 As Boolean
Dim bInRange2 As Boolean
Dim bZeile As Boolean
Dim intAnswer As VbMsgBoxResult
' Definiere das Arbeitsblatt, auf dem die Tabelle liegt
Set ws = ThisWorkbook.Worksheets(BlattName) 'ThisWorkbook.Worksheets("Kapazitäts_Eingabe")
Set checkRange = Sh.Range("A:A")
Set checkRange1 = Sh.Range("D:D")
rowNum = Target.Row
If Sh.Name = BlattName Then '"Kapazitäts_Eingabe" Then
' Überprüfe, ob die geänderte Zelle innerhalb des überwachten Bereichs liegt
bInRange1 = TypeName(Intersect(Target, checkRange)) > "Nothing"
bInRange2 = TypeName(Intersect(Target, checkRange1)) > "Nothing"
bZeile = Target.Address > Target.EntireRow.Address
If bInRange1 And bZeile Then
' Ermittele die Zeilennummer der geänderten Zelle
' Überprüfe, ob "Auftrag" in der geänderten Zelle steht
If StrComp(UCase(Target.Value), "AUFTRAG", vbTextCompare) = 0 Then ' vbTextCompare für die Groß-/Kleinschreibung-unabhängige Überprüfung
' Wenn "Auftrag" gefunden wurde, setze den Wert in der 3. Zeile auf 100%
ws.Cells(rowNum, 3).Value = "100%" ' 1 entspricht 100%
End If
End If
' Überprüfe, ob die geänderte Zelle innerhalb des überwachten Bereichs liegt
If bInRange2 And bZeile Then
' Ermittele die Zeilennummer der geänderten Zelle
rowNum = Target.Row
' Überprüfen, ob in derselben Zeile in Spalte A (1) das Wort "Angebot" steht
If Sh.Cells(Target.Row, 1).Value = "Angebot" Then
' Überprüfen, ob der geänderte Wert "verloren" oder "abgelehnt" ist
If LCase(Target.Value) = "verloren" Or LCase(Target.Value) = "abgelehnt" Then
' Popup-Fenster anzeigen
ws.Cells(rowNum, 3).Value = "0%" ' 1 entspricht 0%
intAnswer = MsgBox("Angebot nicht mehr relevant? Eventuelle Planungsdaten löschen?", vbYesNo + vbQuestion, "Bestätigung")
' Handhabung der Antwort
If intAnswer = vbYes Then
' Wenn Ja ausgewählt wurde, die Zeile von U an leeren
Set rng = Sh.Range("U" & Target.Row & ":XFD" & Target.Row)
rng.ClearContents
End If
End If
End If
End If
' Überprüfen, ob die Änderung in der Spalte "Status" stattgefunden hat
If bInRange2 And bZeile Then
' Überprüfe, ob "erledigt" in der geänderten Zelle steht
If StrComp(UCase(Target.Value), "ERLEDIGT", vbTextCompare) = 0 Then ' vbTextCompare für die Groß-/Kleinschreibung-unabhängige Überprüfung wenn "erledigt" gefunden wurde
' E-Mail-Versand
Set OutlookApp = CreateObject("Outlook.Application")
Set OutlookMail = OutlookApp.CreateItem(0)
' Hier müssen Sie den Namen der E-Mail-Empfänger einsetzen (XXXXX)
OutlookMail.To = "xxx@xxx.com"
' Hier können Sie den E-Mail-Betreff anpassen
mailSubject = "Wartungsvertragsstatus prüfen " & ws.Cells(Target.Row, 6).Value & " "
OutlookMail.Subject = mailSubject
' Hier wird der E-Mail-Text zusammengesetzt, der die betroffenen Informationen enthält
mailBody = "Das Projekt " & ws.Cells(Target.Row, 5).Value & " (Auftr.Nr.: " & ws.Cells(Target.Row, 6).Value & ")" & _
" wurde als erledigt deklariert, bitte Status Wartungsvertrag überprüfen."
OutlookMail.Body = mailBody
' Kalendereintrag erstellen
reminderDate = DateAdd("ww", 3, Now()) ' Datum für die Erinnerung (3 Wochen später)
Set calendarEvent = OutlookApp.CreateItem(1) ' 1 für Kalendereintrag
With calendarEvent
.Subject = mailSubject
.Start = reminderDate
.End = reminderDate
.AllDayEvent = True
.ReminderSet = True
.ReminderMinutesBeforeStart = 15 ' Erinnerung 15 Minuten vorher
.Body = mailBody
.Save ' Speichern des Kalendereintrags
'.Display
End With
' E-Mail-Anhang hinzufügen (den Kalendereintrag)
OutlookMail.Attachments.Add calendarEvent
' E-Mail senden
'OutlookMail.Send
' Freigeben der Ressourcen
Set OutlookMail = Nothing
Set OutlookApp = Nothing
End If
End If
End If
Workbook_SheetChangeOUT:
Exit Sub
Workbook_SheetChangeERR:
Resume Workbook_SheetChangeOUT
End Sub
Anzeige
AW: Problem mit Private Sub Workbook_SheetChange
09.08.2023 09:53:08
Luschi
Hallo Stefan,

Dein Problem sind Befehle, die innerhalb von
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
und
Private Sub Worksheet_Change(ByVal Target As Range)
per Vba Zellwerte ändern: wie z.B.: ws.Cells(rowNum, 3).Value = "100%"
Bevor man das tut, muß man die Tabellen- und Arbeitsmappen-Events zu Beginn der
Prozedur abschalten mit: Application.EnableEvents = False
und zum Schluß wieder einschalten: Application.EnableEvents= True
Ansonsten drehen die Ereignisprozeduren ein paar Extrarunden (gut zu Verfolgen per Haltepunkt setzen und F8-Taste).

Gruß von Luschi
aus klein-Paris

PS: die Variable 'ws' ist überflüssig, den dafür gibt es ja den Übergabeparameter 'Ssh'
Sollte das Prozedere nur für das Tabellenblatt 'Kapazitäts_Eingabe' gelten, genügt die Ereignisprozedur
Private Sub Worksheet_Change(ByVal Target As Range)


Anzeige
AW: Problem mit Private Sub Workbook_SheetChange
09.08.2023 10:02:54
Stefan
Perfekt danke für eure Tatkräftige Hilfe, letzendlich konnte ich schon mit Rudis Antwort mein Problem beheben.
ICh werde mir die anderen Lösungswege später aber auch noch einmal anschauen.

Danke euch
AW: Problem mit Private Sub Workbook_SheetChange
09.08.2023 11:32:37
GerdL
If Target.CountLarge > 1 Then Exit Sub

Moin Stefan,
diese Codezeile an den Anfang gestellt, ist nicht ganz ohne Nebenwirkung.
Benutze künftig bitte den Code-Button des Forums.

Gruß Gerd

303 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige