pblacky
Goto Top

Geburtstagsliste per Batch versenden

Hi Leute,

Ich möchte gerne aus einer Geburtstagsliste die im CSV Format vorliegt eine Email generieren, die mir alle Geburtstage von HEUTE schickt.
Dazu habe ich diesen Beitrag gefunden, der von @bastla elegant gelöst wurde: Geburtstags-Mails an alle Mitarbeiter versenden.

Nun konnte ich rausfinden, dass ich aus meiner Adressdatenbank eine CSV Liste in folgendem Format rausbekommen kann:

19.04.1981;Nachname;Vorname
10.11.1973;Nachname;Vorname


Nun ist es grundsätzlich kein Problem die Felder innerhalb der Delimiter in der DO Schleife auszulesen, wie in dem Beitrag beschrieben!
Die Selektion
set "heute=%date:~,6%"  
for /f "tokens=1-3 delims=;" %%a in ('findstr "%heute%;" "%WorkDir%\GebListe.txt"') do >>"%WorkDir%\Geburtstage.txt" echo %%c%%b am %%a  

funktioniert aber nur, wenn ich das Jahr aus der CSV rauslösche oder die Punkte des Datims gegen Semikolons ersetzte.
Das funktioniert zwar ist nun nicht besonders elegant!
Kann mir eventuell jemand helfen wie ich das Datum und das Jahr aus dem CSV in getrennte Variablen INNERHALB der Schleife bekomme ohne mein CSV File verändern zu müssen?

Content-Key: 972418647

Url: https://administrator.de/contentid/972418647

Printed on: April 25, 2024 at 08:04 o'clock

Member: em-pie
em-pie Jul 11, 2021 updated at 13:53:16 (UTC)
Goto Top
Moin,

wenn es auch eine Powershell sein darf:

birthday.csv
Date;Firstname;Lastname;Aggreed
11.07.1954;Gretel;Müller;1
25.05.1984;Michael;Mustermann;0
31.12.2000;Max;Meier;1
30.09.1997;Laura;Schmitt;1
11.07.1881;Wilhelm;Kayser;0


doBirthday.ps1
$list = "C:\tmp\birthday.csv"  

$bdtoday = Import-Csv -Path $list -Delimiter ";" |   
    Select-Object -Property *, @{label = "Age"; expression = {(Get-Date -Format "yyyy") - (Get-Date ($_.Date) -Format "yyyy") - 1}} |   
    Where-Object {(Get-Date ($_.Date) -Format "dd.MM") -match (Get-Date -Format "dd.MM") -and $_.Agreed -eq 1}  

Ergebnis:
Date       Firstname Lastname Agreed Age
----       --------- -------- ------ ---
11.07.1954 Gretel    Müller   1       66


Mit dem Powershell CmdLet Send-MailMessage() kannst du dann deine Ergebnisliste - wie auch immer aufbereitet - per Mail versenden.

Vermutlich geht das auch etwas eleganter...


<edit>
Ich habe mal noch einen Datenschutz-Aspekt oben ergänzt "Spalte Agreed". Wenn eine Person der Verteilung zugestimmt hat (=1), wird diese in der Ausgabe berücksichtigt.
Wenn das für dein Vorhaben irrelevant ist, lasse einfach in der CSV die letzte "Spalte" weg und entferne us dem PS-Befehl oben
 -and $_.Agreed -eq 1


Hier eine Hilfe, um aus obigem dann direkt eine schöne Mail zu versenden:
https://social.technet.microsoft.com/Forums/windows/en-US/95e3abab-289a- ...

Das könnte ich zwar oben einarbeiten, aber ein wenig Spaß am Lernen möchte ich dir,@pblacky, ja auch nicht nehmen face-smile
</edit>

Gruß
em-pie
Member: pblacky
pblacky Jul 11, 2021 updated at 13:49:57 (UTC)
Goto Top
Zitat von @em-pie:

wenn es auch eine Powershell sein darf:
Grundsätzlich freue ich mich über jede Lösung die funktioniert, danke dafür!
Auch wenn ein Lerneffekt damit verbunden ist face-wink

Allerdings habe ich Powershell noch nie verwendet, da ich ein ein sehr komplexes automatisches System über Batch auf meinem Rechner laufen habe.
Muss mich erst schlau machen ob und wie ich Powershell skripte darüber automatisch ausführen kann....

Kann dein PScript das was du mir als Ergebnis hier darstellst in eine TXT Datei abspeichern?
Denn für das Senden habe ich bereits ein Modul, das textdateien.txt verschicken kann und bereits fertig ist face-wink
Member: em-pie
em-pie Jul 11, 2021 updated at 14:03:20 (UTC)
Goto Top
Zitat von @pblacky:
Zitat von @em-pie:
wenn es auch eine Powershell sein darf:
Grundsätzlich freue ich mich über jede Lösung die funktioniert, danke dafür!
Auch wenn ein Lerneffekt damit verbunden ist face-wink
Nie schlecht face-smile

Allerdings habe ich Powershell noch nie verwendet, da ich ein ein sehr komplexes automatisches System über Batch auf meinem Rechner laufen habe.
Muss mich erst schlau machen ob und wie ich Powershell skripte darüber automatisch ausführen kann....
alles nicht so schwer:
Powershell.exe "c:\tmp\doBirthday.ps1"  
Zu Beginn ggf. eher so, wobei das die Gefahr birgt, dass jemand die doBirthday.ps1 inhaltlich ersetzt und das dann böse ausgehen kann:
Powershell.exe -executionpolicy bypass -File "c:\tmp\doBirthday.ps1"  

Kann dein PScript das was du mir als Ergebnis hier darstellst in eine TXT Datei abspeichern?
Geht
Denn für das Senden habe ich bereits ein Modul, das textdateien.txt verschicken kann und bereits fertig ist face-wink

$list = "C:\tmp\birthday.csv"  
$outfile = "c:\tmp\result.txt"  

Import-Csv -Path $list -Delimiter ";" |   
    Select-Object -Property *, @{label="Age"; expression = {(Get-Date -Format "yyyy") - (Get-Date ($_.Date) -Format "yyyy") - 1}} |   
    Where-Object {(Get-Date ($_.Date) -Format "dd.MM") -match (Get-Date -Format "dd.MM") -and $_.Agreed -eq 1}  |   
    Format-Table | 
    Out-File -FilePath $outfile

Beachte meine obige Änderung noch, bzgl. der Agreed-Spalte!
Member: pblacky
pblacky Jul 11, 2021 updated at 14:29:34 (UTC)
Goto Top
Kann es leider nicht ausführen, es blitzt kurz ein Fenster auf und verschwindet dann wieder!

Wenn ich das Skript direkt in der gestarteten Powershell ausführe, dann kommt das:

c:\Temp\doBirthday.ps1 : Die Datei "C:\Temp\doBirthday.ps1" kann nicht geladen werden, da die Ausführung von Skripts
auf diesem System deaktiviert ist. Weitere Informationen finden Sie unter "about_Execution_Policies"
(https:/go.microsoft.com/fwlink/?LinkID=135170).
In Zeile:1 Zeichen:1
c:\Temp\doBirthday.ps1
~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : Sicherheitsfehler: (face-smile , PSSecurityException
FullyQualifiedErrorId : UnauthorizedAccess


Muss gestehen habe auf dem Rechner noch nie ein Powershell ausgeführt, habe auch keine Ahnung warum das nicht klappt !?
Member: em-pie
em-pie Jul 11, 2021 at 14:32:37 (UTC)
Goto Top
Zitat von @pblacky:

Kann es leider nicht ausführen, es blitzt kurz ein Fenster auf und verschwindet dann wieder!

Wenn ich das Skript direkt in der gestarteten Powershell ausführe, dann kommt das:

c:\Temp\doBirthday.ps1 : Die Datei "C:\Temp\doBirthday.ps1" kann nicht geladen werden, da die Ausführung von Skripts
auf diesem System deaktiviert ist. Weitere Informationen finden Sie unter "about_Execution_Policies"
(https:/go.microsoft.com/fwlink/?LinkID=135170).
In Zeile:1 Zeichen:1
c:\Temp\doBirthday.ps1
~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : Sicherheitsfehler: (face-smile , PSSecurityException
FullyQualifiedErrorId : UnauthorizedAccess


Muss gestehen habe auf dem Rechner noch nie ein Powershell ausgeführt, habe auch keine Ahnung warum das nicht klappt !?

Es geift - richtigerweise - eine Sicherheitsfunktion innerhalb von WIndows/ der Powershell, die verhindert, das jemand ein ps1-Script "im Hintergrund" "per Doppelklick" öffnen kann. Schaue dir daher oben meinen zweiten Funktionsaufruf an.
Wenn der klappt, lies dich in den Text hinter diesem Link ein:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ...
Member: pblacky
pblacky Jul 11, 2021 at 17:00:19 (UTC)
Goto Top
Zitat von @em-pie:
Es geift - richtigerweise - eine Sicherheitsfunktion innerhalb von WIndows/ der Powershell, die verhindert, das jemand ein ps1-Script "im Hintergrund" "per Doppelklick" öffnen kann. Schaue dir daher oben meinen zweiten Funktionsaufruf an.
Wenn der klappt, lies dich in den Text hinter diesem Link ein:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell. ...

Beide Funktionsaufrufe haben nicht geklappt, daher habe ich das Skript ja direkt IN der geöffneten Powershell gestartet.
Die Fehlermeldung habe ich dort bekommen.
Verstehe dass es nicht im "Hintergrund" ausgeführt werden kann, aber direkt in der geöffneten Powershell !?

Ich glaube ich bastel lieber noch etwas in meiner Batch rum, da kenn ich die Ausführungsmodalitäten und muss mich nicht um irgendwelche für meinen Ablauf unnötigen "Sicherheitsthematiken" kümmern face-wink
Member: pblacky
pblacky Jul 11, 2021 updated at 17:14:24 (UTC)
Goto Top
Nach mehr als 1 Stunde Powershell Try & Error (sorry @em-pie ich habs nicht geschnallt, wie ich das zum Laufen bringe!)
Hier das Ergebnis des heutigen Nachmittags in Batch.:

Bin jetzt schon mal soweit, dass ich die Geburtstage in der CSV Datei korrekt finde, in eine Geburtstage.txt speichere und per Mail über Blat verschicken kann. Klappt gut!

Die Basisdatei im CSV Format aus der Datenbank sieht so aus:
11.07.1973;Atester;Muster
11.07.1980;Ctester;Muster
12.07.1943;Btester;Muster

Der Auslese Batch:
set "heute=%date:~,2%%date:~2,4%"  
for /f "tokens=1-6 delims=;." %%a in ('findstr "%heute%." "%WorkDir%\GebListeAll.txt"') do >>"%WorkDir%\Geburtstage.txt" echo %%d %%e  -  %%a.%%b.%%c  

Ergebnis eine Textdatei für Heute:
Atester Muster - 11.07.1973
Ctester Muster - 11.07.1980

Die optionale Berechnung des Alters, werde ich vorerst als "zukünftige Aufgabe" für die V0.2 offen lassen face-wink
Member: em-pie
em-pie Jul 12, 2021 at 08:36:24 (UTC)
Goto Top
Moin,

in der Grafik siehst du, dass der Befehl ohne die Execution-Policy Anpassung nicht geht und den selben Fehler wie bei dir anzeigt.
Unter dem roten dann noch einmal der erweiterte Aufruf, welcher keinen Fehler mehr erzeugt:
unbenannt
Member: Scirca
Scirca Jul 12, 2021 at 13:36:59 (UTC)
Goto Top
Man könnte auch einen Eintrag in sein Email Kalender machen und sowas wie wiederholender Termin eintragen. Also jährlich dann braucht man sich dafür nicht so ein lustig Skript basteln.
Mitglied: 148656
148656 Jul 12, 2021 at 14:02:59 (UTC)
Goto Top
Zitat von @Scirca:

Man könnte auch einen Eintrag in sein Email Kalender machen und sowas wie wiederholender Termin eintragen. Also jährlich dann braucht man sich dafür nicht so ein lustig Skript basteln.

Solche Geburtstagskalender sind in Unternehmen kritisch zu betrachten, was die dsgvo betrifft.
Member: pblacky
pblacky Jul 12, 2021 updated at 15:27:23 (UTC)
Goto Top
Hallo @em-pie ,
Danke vorerst mal für deine Geduld mich zu Powershell zu überreden. Hast mich nun mal neugierig gemacht!
Habe jetzt mal einen Freund gebeten meine Einstiegshürde zu entfernen und mir zu zeigen, wie man die Powershell gruindlegend verwendet. Mir wurde dazu der ISE nahegelegt face-wink
Habe nun dein Skript dort ausgeführt und das erste Mal ist es offensichtlich auch gelaufen!!

Bekomme:
Get-Date : Der Parameter "Date" kann nicht an das Ziel gebunden werden. Ausnahme beim Festlegen von "Date": "NULL kann nicht in den Typ "System.DateTime"
konvertiert werden."
In P:\Geb.ps1:6 Zeichen:29
Where-Object {(Get-Date ($_.Date) -Format "dd.MM") -match (Get-Da ...
~~~~~~~~~
CategoryInfo : WriteError: (face-smile [Get-Date], ParameterBindingException
FullyQualifiedErrorId : ParameterBindingFailed,Microsoft.PowerShell.Commands.GetDateCommand


Da ich mich im Powershell noch so gar nicht auskenne, kann ich nur vermuten, dass irgendwas mit dem Format nicht passt.

Meine CSV Datei sieht so aus:
11.07.1973;Atester;Muster11
12.07.1973;Btester;Muster12
.
.
Hast du einen Tipp??
Member: em-pie
em-pie Jul 12, 2021 at 15:43:23 (UTC)
Goto Top
Wenn deine CSV so aussieht, fehlen dir die Spaltenüberschriften. Die habe ich in meinen Beispiel oben ja mit angegeben!

Ergänze mal den Befehl Import-CSV um den Parameter
Import-CSV … -Header 'Date', 'Firstname', 'Lastname'  
Member: em-pie
em-pie Jul 12, 2021 updated at 18:23:28 (UTC)
Goto Top
Hier noch mal komplett, sollte dir die Zeile 1 (die Spaltenüberschriften) fehlen:

birthday.csv
12.07.1954;Gretel;Müller;1
25.05.1984;Michael;Mustermann;0
31.12.2000;Max;Meier;1
30.09.1997;Laura;Schmitt;1
12.07.1881;Wilhelm;Kayser;0

doBirthday.ps1
$list = "C:\tmp\birthday.csv"  
$outfile = "c:\tmp\result.txt"  

Import-Csv -Path $list -Delimiter ";" -Header "Birthdate", "Firstname", "Lastname", "Agreed" |   
    Select Agreed,Firstname,Lastname,Birthdate,@{label="Age"; expression = {(Get-Date -Format "yyyy") - (Get-Date ($_.Birthdate) -Format "yyyy") - 1}} |   
    Where-Object {(Get-Date ($_.Birthdate) -Format "dd.MM") -match (Get-Date -Format "dd.MM") -and $_.Agreed -eq 1} |   
    Format-Table | 
    Out-File -FilePath $outfile

Ergebnis:
Date       Firstname Lastname Agreed Age
----       --------- -------- ------ ---
12.07.1954 Gretel    Müller   1       66
Member: Nebellicht
Nebellicht Jul 13, 2021 at 10:25:34 (UTC)
Goto Top
Hey, damit man Geburtstagsgeschenke besorgen kann oder eben der erste ist, der gratuliert -

sollte man ggf. 14 Tage vor dem Geburtstag erinnert werden, bzw. 14 Tage nach dem Geburtstag noch eine Meldung erhalten (man kann ja im Urlaub sein usw.) Jedenfalls berücksichtige ich soetwas bei der Programmierung... (Gut... gibt auch noch Tierkreiszeichen... die man mit ausgeben kann... aber das denke ich ist zu viel des guten.)

Gruß.
Member: pblacky
pblacky Jul 13, 2021 at 14:44:28 (UTC)
Goto Top
Zitat von @em-pie:

Hier noch mal komplett, sollte dir die Zeile 1 (die Spaltenüberschriften) fehlen:
Danke!!
Habe wieder einen Fehler bekommen:
Get-Date : Der Parameter "Date" kann nicht gebunden werden. Der Wert "00.00.0000" kann nicht in den Typ "System.DateTime" konvertiert werden. Fehler: "Die
Zeichenfolge wurde nicht als gültiges DateTime erkannt."
In P:\!ToDo\Geb_Erinnerung_PS\Geb_V02.ps1:6 Zeichen:29
Where-Object {(Get-Date ($_.Birthdate) -Format "dd.MM") -match (G ...
~~~~~~~~~~~~~~
CategoryInfo : InvalidArgument: (face-smile [Get-Date], ParameterBindingException
FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetDateCommand

Weiß nicht warum das bei mir nicht funktioniert ;-(
Member: em-pie
em-pie Jul 13, 2021 at 16:08:17 (UTC)
Goto Top
Du hast irgendwo einmal „Birthdate“ und einmal „Date“ verwendet.

Poste bitte mal dein Script.

Und versuche, mein PS-Script nachzuvollziehen, dann wird es klappen face-smile
Member: pblacky
pblacky Jul 13, 2021 at 16:29:14 (UTC)
Goto Top
Ich habe DEIN doBirthday.ps1 aus dem Post 12.07.2021 um 19:29:44 Uhr
1:1 übernommen!
Habe nur die Zielpfade geändert.

Habs jetzt nochmal versucht und NICHTS geändert, sondern den Zielpfad einfach mal erstellt.
JETZT ist es durchgelaufen, aber das results.txt ist leer ;-(
folgender Code:
$list = "C:\tmp\birthday.csv"  
$outfile = "c:\tmp\result.txt"  

Import-Csv -Path $list -Delimiter ";" -Header "Birthdate", "Firstname", "Lastname", "Agreed" |   
    Select Agreed,Firstname,Lastname,Birthdate,@{label="Age"; expression = {(Get-Date -Format "yyyy") - (Get-Date ($_.Birthdate) -Format "yyyy") - 1}} |   
    Where-Object {(Get-Date ($_.Birthdate) -Format "dd.MM") -match (Get-Date -Format "dd.MM") -and $_.Agreed -eq 1} |   
    Format-Table | 
    Out-File -FilePath $outfile

Allerdings hat mein CSV ein Feld weniger, vielleicht liegt es daran ...

Dein Beispiel:
12.07.1954;Gretel;Müller;1
25.05.1984;Michael;Mustermann;0
31.12.2000;Max;Meier;1
30.09.1997;Laura;Schmitt;1
12.07.1881;Wilhelm;Kayser;0

mein CSV:
12.07.1954;Gretel;Müller
25.05.1984;Michael;Mustermann
31.12.2000;Max;Meier
30.09.1997;Laura;Schmitt
12.07.1881;Wilhelm;Kayser

Kann das due Irsache sein?
Member: em-pie
em-pie Jul 13, 2021 at 17:38:50 (UTC)
Goto Top
Ja, schmeiße alles, was mit „Agreed“ zu tun hat raus…
Member: pblacky
Solution pblacky Jul 15, 2021 updated at 09:48:42 (UTC)
Goto Top
Tja, werd mal beizeiten mit dem "Rauschmeißen" beschäftigen.
Danke em-pie für die Inspiration!!

Hab nun doch noch eine Lösung gefunbden, das mit Batch zu lösen.
Hier das Ergebnis INKLUSIVE Altersberechnung face-wink
set "heute=%date:~,2%%date:~2,4%"  
set "Jahr=%date:~6,4%"  

SETLOCAL ENABLEDELAYEDEXPANSION
for /f "tokens=1-6 delims=;." %%a in ('findstr "%heute%." "%WorkDir%\GebListeAll.txt"') do (  
  set /a J=%Jahr%-%%c
  echo %%d %%e  -  %%a.%%b.%%c  - !J! Jahre
  echo %%d %%e  -  !J! Jahre    -   %%a.%%b.%%c>>"%WorkDir%\Geburtstage.txt"  
)

Das Ergebnis ist einen geburtstagsliste.txt mit folgendem Inhalt:

Max Mustermann - 49 Jahre - 15.07.1972
Petra Mustefrau - 38 Jahre - 15.07.1983

Projekt ist also abgeschlossen!