Mrrrr's Forum (VIEW ONLY)
Un forum care ofera solutii pentru unele probleme legate in general de PC. Pe langa solutii, aici puteti gasi si alte lucruri interesante // A forum that offers solutions to some PC related issues. Besides these, here you can find more interesting stuff.
Lista Forumurilor Pe Tematici
Mrrrr's Forum (VIEW ONLY) | Reguli | Inregistrare | Login

POZE MRRRR'S FORUM (VIEW ONLY)

Nu sunteti logat.
Nou pe simpatie:
andreutza43 pe Simpatie.ro
Femeie
25 ani
Bacau
cauta Barbat
30 - 80 ani
Mrrrr's Forum (VIEW ONLY) / Tutoriale si Ghiduri Utile // Tutorials and useful guides / [EXCEL] Send Email when Date is Due & Run Periodically [VBA] Moderat de TRaP, TonyTzu
Autor
Mesaj Pagini: 1
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2386
The code below should work with no email software required for it to send the email. For more info and explanation and for the source of this code, check Ron de Bruin's page:
Similar, bit different:

The code below will require you to add your email and password. You can create an email specifically to send alert emails, so you won't use your main account's password in an excel file. But you can also protect the VBA code with a password from Visual Basic, so no one has access to the code and your email pass is protected. Here's how to do it:

IMPORTANT! If you change your email password, you must also change it in VBA, otherwise it will not work.


Sub EMAILALERTS()
    Dim iMsg, iConf As Object
    Dim Flds As Variant
    Dim cell As Range
    Dim LastRow As Long
   
    Application.DisplayAlerts = False
    Application.ScreenUpdating = False
   
    Set iConf = CreateObject("CDO.Configuration")
    LastRow = Sheets("emailALERTS").Cells(Rows.Count, "I").End(xlUp).Row
    iConf.Load -1    'CDO Source Defaults
    Set Flds = iConf.Fields

With Flds
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
    .Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "YOUREMAILADDRESS"
    .Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "YOUREMAILADDRESSPASSWORD"
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.mail.yahoo.com" 'for gmail use smtp.gmail.com
    .Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 465
    .Update
End With
               
For Each cell In Sheets("emailALERTS").Range("I3:I" & LastRow)
    If LCase(Sheets("emailALERTS").Cells(cell.Row, "I").Value) = "yes" Then

    Set iMsg = CreateObject("CDO.Message")
    With iMsg
        Set .Configuration = iConf
        .To = "YOUREMAILADDRESS"
        .CC = ""
        .BCC = ""
        .From = """YOURNAME"" <YOUREMAILADDRESS>"
        .Subject = "BLA BLA EMAIL SUBJECT " & _
                                    Sheets("emailALERTS").Cells(cell.Row, "B").Value
        .HTMLBody = "BLA, " & _
                                    Sheets("emailALERTS").Cells(cell.Row, "M").Value & "!<p></p><br></br>" & "<b>BLA BLA BLA BLA BLA <font color=red>" & _
                                    Sheets("emailALERTS").Cells(cell.Row, "B").Value & "</font> - <font color=blue>" & _
                                    Sheets("emailALERTS").Cells(cell.Row, "C").Value & "</font></b>BLA BLA BLA BLA BLA " & _
                                    Sheets("emailALERTS").Cells(cell.Row, "E").Value & "!<p></p><br></br>" & "BLA BLA BLA <b><font color=red>" & _
                                    Sheets("emailALERTS").Cells(cell.Row, "H").Value & "</font></b> BLA BLA BLA!" & "!<p></p><br></br>" & _
                        "BLA BLA BLA BLA BLA THE END."
        .Send
    End With

    Set iMsg = Nothing
   
    End If
Next cell

    Set iConf = Nothing
    Set Flds = Nothing

Application.DisplayAlerts = True
Application.ScreenUpdating = True

End Sub


_______________________________________


pus acum 8 ani
   
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2386
.vbs file:

Dim args, objExcel

Set args = WScript.Arguments
Set objExcel = CreateObject("Excel.Application")

objExcel.Workbooks.Open args(0)
objExcel.Visible = False

objExcel.Run "EMAILALERTS"

objExcel.ActiveWorkbook.Save
objExcel.ActiveWorkbook.Close(0)
objExcel.Quit


.bat file:

cscript "FULL PATH TO YOUR VBS FILE\file.vbs" "FULL PATH TO YOUR EXCEL FILE\file.xlsm"
exit


task scheduler set up for daily/weekly/monthly run of vba:
1. Create a new task
2. General TAB - name your task and add a description (optional, but useful)
3. Triggers TAB - click NEW: set frequency (daily, weekly, monthly), date to start, hour, minute, second. Click OK.
4. Actions TAB - click NEW: in the Program/script field insert: cmd
    in the Add arguments (optional) field insert: /c start "RUN ALERTS" /min "FULL PATH TO YOUR BAT FILE\file.bat"
    Click OK
5. Conditions TAB - If you have a laptop or UPS, you can check or uncheck "Start the task only if the computer is on AC power"and "Stop if the computer switches to battery power"
6. Settings TAB - check "Allow task to be run on demand"
    check "Run task as soon as possible after a scheduled start is missed"
    check "If the running task does not end when requested, force it to stop"
    select "Do not start a new instance" from the dropdown list under "If the task is already running, then the following rule applies:". Or you can select another option if you prefer.
7. Click OK

If you don't want to use task scheduler for some reason (eg. I had some problems with it and it would not send e-mails every time), then you can use a FREEWARE:

IMPORTANT: YOU WILL STILL USE THE BAT AND VBS FILES, YOU ARE JUST NOT USING TASK SCHEDULER ANYMORE, BUT A 3RD PARTY SOFTWARE (Schedule Manager)


_______________________________________


pus acum 8 ani
   
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2386
To add multiple conditions you can structure your code like this:


Sub EMAILALERTS()
    Dim iMsg, iConf As Object
    Dim Flds As Variant
    Dim cell As Range
    Dim LastRow As Long
   
    Application.DisplayAlerts = False
    Application.ScreenUpdating = False
   
    Set iConf = CreateObject("CDO.Configuration")
    LastRow = Sheets("SHEETNAME").Cells(Rows.Count, "L").End(xlUp).Row
    iConf.Load -1    'CDO Source Defaults
    Set Flds = iConf.Fields

With Flds
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = True
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
    .Item("http://schemas.microsoft.com/cdo/configuration/sendusername") = "YOUREMAILADDRESS"
    .Item("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "YOUREMAILADDRESSPASSWORD"
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.mail.yahoo.com" 'for gmail use smtp.gmail.com
    .Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    .Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 465
    .Update
End With

'#### CHECK CONDITIONS AND BUILD HTML BODY ####

    For Each cell In Sheets("SHEETNAME").Range("L3:L" & LastRow)
        If LCase(Sheets("SHEETNAME").Cells(cell.Row, "P").Value) = "yes" Then
            SHEETBody =SHEETBody & "<p></p>" & _
                        "<B><font color=BLUE>" & _
                                                "BLA BLA BLA" & _
                                                                    "</B></font> BLA <b><font color=BLUE>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "B").Value & "</b></font>, BLA BLA BLA: " & _
                                Sheets("SHEETNAME").Cells(cell.Row, "C").Value & " BLA BLA BLA: " & _
                                Sheets("SHEETNAME").Cells(cell.Row, "D").Value & ", BLA BLA BLA <b><font color=BLUE>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "F").Value & "</b></font>, BLA: <b><font color=RED>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "M").Value & " " & _
                                Sheets("SHEETNAME").Cells(cell.Row, "S").Value & "</b></font> <u>BLA BLA BLA:</u> <font color=RED><span style='background:yellow;mso-highlight:yellow'><b>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "I").Value & "</span></font></b>" & _
                        vbNewLine & vbNewLine
           End If
   
        If LCase(Sheets("SHEETNAME").Cells(cell.Row, "Q").Value) = "yes" Then
            SHEETBody = SHEETBody & "<p></p>" & _
                        "<B><font color=CHOCOLATE>" & _
                                                 "BLA BLA BLA" & _
                                                                           "</B></font> pentru <b><font color=CHOCOLATE>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "B").Value & "</b></font>, BLA BLA BLA: " & _
                                Sheets("SHEETNAME").Cells(cell.Row, "C").Value & " BLA BLA BLA: " & _
                                Sheets("SHEETNAME").Cells(cell.Row, "D").Value & ", BLA BLA BLA <b><font color=CHOCOLATE>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "G").Value & "</b></font>, BLA: <b><font color=RED>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "N").Value & " " & _
                                Sheets("SHEETNAME").Cells(cell.Row, "T").Value & "</b></font> <u>BLA BLA BLA:</u> <font color=RED><span style='background:yellow;mso-highlight:yellow'><b>" & _
                                Sheets("SHEETNAME").Cells(cell.Row, "I").Value & "</span></font></b>" & _
                        vbNewLine & vbNewLine
           End If

'#### AND SO ON... THEN CLOSE FOR LOOP:  ####

    Next cell

'#### CREATE FULL BODY CONTENT OUTSIDE THE LOOP, BUT WHICH INCLUDES THE LOOP RESULTS ####

         SHEETBody = "<b>ATTENTION!</b> <br></br> <br></br>" & vbNewLine & vbNewLine & _
                   SHEETBody & _
                        "<br></br> <br></br> BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA " & _
                        "BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA ." & _
                        vbNewLine & vbNewLine & _
                        "<br></br> <br></br> <b><font color=navy><u>BLA BLA BLA BLA BLA BLA </font></b></u>, " & _
                        "BLA <b>BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA </b> AND <u>BLA BLA BLA BLA BLA BLA BLA BLA BLA</u>.<p></p> " & _
                        "<b>BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA</b>, " & _
                        "BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA BLA."

'#### SEND EMAIL ####

    Set iMsg = CreateObject("CDO.Message")
    With iMsg
        Set .Configuration = iConf
        .To = "YOUREMAILADDRESS"
        .CC = ""
        .BCC = ""
        .From = """YOURNAME"" <YOUREMAILADDRESS>"
        .Subject = "BLA BLA BLA BLA SUBJECT"
        .HTMLBody = SHEETBody
        .Send
    End With

    Set iMsg = Nothing
    Set iConf = Nothing
    Set Flds = Nothing

Application.DisplayAlerts = True
Application.ScreenUpdating = True

End Sub


_______________________________________


pus acum 8 ani
   
Mrrrr
AdMiN

Inregistrat: acum 19 ani
Postari: 2386
Updated - added alternative to Task Scheduler - in post #2

_______________________________________


pus acum 6 ani
   
TRaP
Moderator

Inregistrat: acum 8 ani
Postari: 951
Changed title from "Run Daily" to "Run Periodically"

*

I have an e-mail alert system set up for a colleague to run every month on the 1st. If he does not turn on the computer on the 1st of the month, the code will run the first time he will. This is set through both Excel VBA and the Task Scheduler.

This uses the New Outlook which will become mandatory in the near future. The New Outlook isn't linked directly to VBA so you cannot do a simple email.Send VBA command anymore. You require an additional helper, and I used an AutoHotkey script compiled as an executable ("send mail.exe"). Please see code at the end of this post. No admin rights are required to create and compile the code to .exe, you just need AutoHotkey Portable downloaded to local PC.

I included the 2 VBA codes below - MonthlyRun and Email_Alert_BVM_Send subroutines - in a blank excel file called ALERTE_MAIL.xlsm.

The code below contains a Subroutine called MonthlyRun which records an entry into the Windows Registry for the current user (no admin required) with the current year-month (yyyy-mm format) after the code in Subroutine Email_Alert_BVM_Send has ran. Task scheduler runs MonthlyRun daily on computer logon. MonthlyRun first checks if the registry key corresponds to the current month - meaning that the code has already ran this month - and exits. If it has not, it runs once.


Sub MonthlyRun()

    Dim currentMonth As String
    Dim lastRunMonth As String

    currentMonth = Format(Date, "yyyy-mm")

    ' Get last run month from registry: HKEY_CURRENT_USER\Software\VB and VBA Program Settings\ALERTE_BVM\EmailAlert    string: LastRunMonth = "2025-04"
    On Error Resume Next
    lastRunMonth = GetSetting("ALERTE_BVM", "EmailAlert", "LastRunMonth", "")
    On Error GoTo 0

    ' Exit if already run this month
    If lastRunMonth = currentMonth Then Exit Sub

    ' >>> Run your actual logic here <<<
    Email_Alert_BVM_Send

    ' Save the current month so it doesn't run again
    SaveSetting "ALERTE_BVM", "EmailAlert", "LastRunMonth", currentMonth
End Sub


Main code of Email_Alert_BVM_Send:
"send mail.exe" is an executable created in AutoHotkey. Please see code at the bottom of this post.


' #### added AUG 2026 - too long e-mail
#If VBA7 Then
    Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
        ByVal hwnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
        ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
#Else
    Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
        ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _
        ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If
' #### added AUG 2026 - end

Sub Email_Alert_BVM_Send()

Dim emailTo, emailCC As String
Dim filePath, sendMail As String    ' cel mai bine ar fi sa fie LOCAL, pe laptop Daniel, intr-un folder care nu e cu share in OneDrive

    filePath = "\\SERVER_PATH_GOES_HERE\EXCEL_FILE_WITH_RULES_SHOWING_ALERT_IN_COLUMN_N.xlsx"
    sendMail = "FOLDER_ON_USER_PC_AND_NOT_ON_SERVER\send mail.exe"

    emailTo = "EMAIL_ADDRESS_HERE" 'user sends e-mail to himself

Dim wb As Workbook
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Dim subject, body, tmpBody As String
Dim mailtoLink As String

Set wb = Workbooks.Open(filePath, ReadOnly:=True)
Set ws = wb.Sheets(1) ' ia primul sheet dupa "code name" (Sheet1), nu dupa denumirea "prietenoasa" (EMM) care poate fi schimbata oricand de user
    lastRow = ws.Cells(ws.Rows.Count, "I").End(xlUp).Row

Dim counter As Long
    counter = Application.WorksheetFunction.CountIf(ws.Range("N3:N" & lastRow), "ALERT")

For i = 3 To lastRow
    alert = ws.Cells(i, "N").Value
   
        If alert = "ALERT" Then
            tmpBody = tmpBody & "- " & ws.Cells(i, "B").Value & " = " & ws.Cells(i, "C").Value & ", seria " & ws.Cells(i, "E").Value
                If counter > 1 Then
                    tmpBody = tmpBody & vbCrLf
                End If
        End If
Next i

' Creare subiect si corp e-mail
subject = "BVM care expira in luna in curs"
tmpBody = "BVM care expira in luna " & Format(Date, "mmmm") & " " & Format(Date, "yyyy") & " sunt:" & vbCrLf & _
            tmpBody
body = tmpBody

' Encode line breaks and spaces
subject = Replace(subject, " ", "%20")
body = Replace(body, vbCrLf, "%0D%0A")
body = Replace(body, " ", "%20")

' Email
    mailtoLink = "mailto:" & emailTo & "?subject=" & subject & "&body=" & body

' Launch default email client
    'ThisWorkbook.FollowHyperlink mailtoLink ' this did not work for longer e-mails
' #### added AUG 2026 - too long e-mail
    ShellExecute 0&, "open", mailtoLink, vbNullString, vbNullString, 1
' #### added AUG 2026 - end

' Inchide fisier excel fara a salva
Application.DisplayAlerts = False
    wb.Close savechanges:=False
Application.DisplayAlerts = True

' Wait a moment for New Outlook to bring the draft into focus
    Application.Wait Now + TimeValue("0:00:03") 'adjust if needed

' Activare programel de trimitere e-mail (exe facut in AutoHotkey care apasa butonul Send din New Outlook)
    Shell """" & sendMail & """", vbNormalFocus

End Sub


AutoHotkey code to compile "send mail.exe"
Compile with AutoHotkey compiler Ahk2Exe (included in the portable version of AHK).


SetTitleMatchMode, 2  ; Allows partial match in window title

If WinExist("BVM")
{
    WinActivate
    WinWaitActive, BVM, , 3  ; Wait up to 3 seconds for it to become active
    if WinActive("BVM")
    {
        Sleep, 1000
        Send, ^{Enter}  ; Ctrl+Enter to send
    }
    else
    {
        MsgBox, Email window found but could not be activated.
    }
}
else
{
    MsgBox, Email window with title containing 'BVM' not found.
}


There are 2 ways to run this:
1. RoboIntern (free portable sofware) - the simpler way
2. Task Scheduler - requires additional files (1 x BAT file + 1 VBS file) VBS is being deprecated so I'll have to find .JS alternative.

1. RoboIntern - the simpler way

Download RoboIntern and extract to the desired folder.
Set to run on computer startup.

Add Task

ACTIONS tab
Add action - Runn Office VBA Macro - Run Excel macro
Add description, browse the file path to the ALERTE_MAIL.xlsm
In Macro field add: MonthlyRun

TRIGGERS tab
Add trigger - Computer state changes - At computer startup

OPTIONS tab
Execute actions - enabled
Task scheduling - enabled
Delay actions - 180 seconds
Activate scheduling - date when this should start

2. Task Scheduler

This requires additional files, namely a .bat and a .vbs file.
The .bat file runs the .vbs file which calls the macro in the ALERTE_EMAIL.xlsm file. This is the setup required for Task Scheduler. I don't know of another reliable way at the moment.

BAT file:

cscript "LOCAL_PATH_TO_VBS_FILE\BVM_VBS.vbs" "LOCAL_PATH_TO_ALERTE_MAIL\ALERTE_MAIL.xlsm"
exit


VBS file - runs the MonthlyRun macro in the excel file:

Dim args, objExcel

Set args = WScript.Arguments
Set objExcel = CreateObject("Excel.Application")

objExcel.Workbooks.Open args(0)
objExcel.Visible = False

objExcel.Run "MonthlyRun"

objExcel.ActiveWorkbook.Save
objExcel.ActiveWorkbook.Close(0)
objExcel.Quit


Open Task Scheduler (taskschd.msc) and add a new task, add name and description.

TRIGGERS tab:

Code:

New
Begin the task:        At log on
Specific user:         the local user (should be preselected) 
Delay task for:        2 minutes
Enabled:        checked
OK

ACTIONS tab:

Code:

New
Action:            Start a program
Program/script:        cmd
Add arguments:        /c start "RED ALERT" /min "PATH_TO_THE_BAT_FILE\BVM_BAT.bat"
OK

CONDITIONS tab:

Code:

Stop if the computer switches to battery power                unchecked
Start the task only when the computer is on AC power            unchecked
Wake the computer to run this task                    checked

SETTINGS tab:

Code:

Allow task to be run on demand                        checked
Run task as soon as possible after a scheduled start is missed        checked
Stop the task if it runs longer than                    unchecked
If the running task does not end when requested, force it to stop    checked

GENERAL tab:

Code:

Run only when user is logged on                        checked

OK


pus acum 2 saptamani
   
Pagini: 1  

Mergi la