VBA Macro Project A

Creation to Completion : 1 month

I developed a VBA macro to automate the creation and circulation of DIN letters for utility notifications, a process that previously required manually populating templates and sending each email individually. Each year, around 300 emails were sent, taking roughly 35 hours of repetitive work. The macro compiles project data, populates Word templates, exports PDFs, and generates draft emails with customized subjects and attachments in Outlook, eliminating manual data entry and ensuring consistency. This tool significantly reduces administrative workload, allowing the team to focus on design and coordination while saving dozens of hours annually.

				
					Sub compile_worktype()

Dim i As Integer
Dim j As Integer
Dim k As Integer

Dim worktype As String
Dim dummytext As String

dummytest = ""
worktype = ""
i = 0
j = 0
k = 1

Do While Worksheets("Projects").Range("C2").Offset(i, 0).Value <> ""
   ' Worksheets("Projects").Range("C2").Offset(i, 8).Value = ""
    i = i + 1
Loop

i = 0

Do While Worksheets("Projects").Range("C2").Offset(i, 0).Value <> ""


    Do While j < 9
    
        If Worksheets("Projects").Range("C2").Offset(i, j).Value = "" Or j = 9 Then
            ' next type
            j = j + 1
            
        ElseIf Worksheets("Projects").Range("C2").Offset(i, j).Value <> "" Then
        
            If worktype = "" Then
            
                ' first value
                worktype = Worksheets("Projects").Range("C2").Offset(i, j).Value
                j = j + 1
                
            Else
            
                Do While j + k < 9
                    ' looking for last value
                    
                    If Worksheets("Projects").Range("C2").Offset(i, j + k).Value <> "" Then
                        dummytext = dummytext + Worksheets("Projects").Range("C2").Offset(i, j + k).Value
                        ' if dummytext is not empty, then its not the last value
                        k = k + 1
                        
                    End If
                    
                    k = k + 1
                    
                Loop
                k = 1
               
                If dummytext = "" Then
                    worktype = worktype & " and " & Worksheets("Projects").Range("C2").Offset(i, j).Value
                    j = j + 1
                Else
                    worktype = worktype & ", " & Worksheets("Projects").Range("C2").Offset(i, j).Value
                    j = j + 1
                End If
                 dummytext = ""
                
            End If
            
            
        End If
        
    Loop
    
    

dummytext = ""

Worksheets("Projects").Range("C2").Offset(i, 8).Value = worktype
worktype = ""
i = i + 1
j = 0
k = 1
Loop



End Sub




Sub pop_template(TemplateLocation As String)

' load template

' Dim TemplateLocation As String
On Error Resume Next
' TemplateLocation = "C:\Documents and Settings\syue\Desktop\b\2.docx"

Dim wTApp As Word.Application
Dim wTDoc As Word.Document

Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim p As Integer
Dim filename As String



Dim StartCell As String
Dim cc As ContentControl
Dim docCCs As ContentControls
Dim ccTag As String




i = 2
j = 2
k = 1
p = 1


Set wTApp = CreateObject("Word.Application")
wTApp.Visible = False

Set wTDoc = wTApp.Documents.Open(TemplateLocation)

' populate template

Do While Worksheets("Contacts").Cells(i, 1).Value <> ""

     
     
     
     Do While Worksheets("Projects").Cells(j, 1).Value <> ""
     
        ' ====================================================================================
        Do While k <= wTDoc.ContentControls.Count
        
                If wTDoc.ContentControls(k).Tag = "PIN_Date" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Format(Date, "mmmm, d yyyy"))
                
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_recipient" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Contacts").Cells(i, 2).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Address1" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Contacts").Cells(i, 6).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Address2" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Contacts").Cells(i, 7).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Address3" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Contacts").Cells(i, 8).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Email" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Contacts").Cells(i, 4).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Company" Then
                    
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Contacts").Cells(i, 1).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Plan" Then
                
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Projects").Cells(j, 14).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Worktype" Then
                
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Projects").Cells(j, 11).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_Location" Then
                
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Worksheets("Projects").Cells(j, 2).Value)
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_TenderMonth" Then
                
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Format(Worksheets("Projects").Cells(j, 12).Value, "mmmm, d yyyy"))
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_ConstructionMonth" Then
                
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Format(Worksheets("Projects").Cells(j, 13).Value, "mmmm, d yyyy"))
                    
                ElseIf wTDoc.ContentControls(k).Tag = "PIN_ResponseDate" Then
                
                    Call wTDoc.ContentControls(k).SetPlaceholderText(, , Format(Date + 21, "mmmm d yyyy"))
                    
                        
                End If
                k = k + 1
                
             
            Loop
            k = 1
            
        
        
            Do While p < wTDoc.ContentControls.Count + 1
                                    
                                    If p > wTDoc.ContentControls.Count Then
                                    'nothing
                                    ElseIf wTDoc.ContentControls(p).Tag = "PIN_Date" Or _
                                            wTDoc.ContentControls(p).Tag = "PIN_Company" Or _
                                            wTDoc.ContentControls(p).Tag = "PIN_Address" Or _
                                            wTDoc.ContentControls(p).Tag = "PIN_Email" Or _
                                            wTDoc.ContentControls(p).Tag = "PIN_recipient" Then
                                            
                                            With wTDoc.ContentControls(p).Range.Font
                                                    .Name = "calibri"
                                                    .Size = 11
                                                    .Color = wdColorBlack
                                            End With
                        
                                    Else
                                    
                                            
                                            
                                            
                                    
                                        With wTDoc.ContentControls(p).Range.Font
                                            .Name = "calibri"
                                            .Size = 11
                                            .Color = wdColorBlack
                                            .Bold = True
                                            .Underline = wdUnderlineSingle
                                        
                                        End With
                                        
                                        
                                    End If
                            
                                    p = p + 1
                                      
                Loop
                p = 1
                
                            
            filename = "DIN for " & Worksheets("Contacts").Cells(i, 1).Value & " re " & Worksheets("Projects").Cells(j, 2).Value
            wTDoc.ExportAsFixedFormat OutputFileName:=wTDoc.Path & "\" & filename & ".pdf", ExportFormat:=17
        

        j = j + 1
     
    Loop
    
    j = 2
    i = i + 1
    
Loop
    



Set wTApp = Nothing
Set wTDoc = Nothing

End Sub

				
			

The compile_worktype macro automatically consolidates multiple work types listed across columns in the Projects sheet into a single, readable string for each project, ensuring that each DIN letter accurately reflects all relevant work. The pop_template macro then takes this data along with contact information, opens a Word DIN letter template, populates all placeholders (like date, recipient, address, work type, and project details), applies consistent formatting, and exports each letter as a PDF. Together, these macros eliminate the manual, repetitive process of creating letters, ensure accuracy and formatting consistency, and save significant time in preparing documentation for utility circulation during the initial design phase.

				
					
Sub CreateDraftEmails_OneEmailPerPDF_WithCustomSubject()
    Dim OutlookApp As Object, OutlookMail As Object
    Dim ws As Worksheet
    Dim i As Long
    Dim pdfFolder As String, templatePath As String, companyName As String
    Dim pdfFile As String, roadName As String, subjectText As String
    
    ' Paths
    templatePath = "C:\Users\jlauan\Downloads\Justen Files\Utility Circulation\2027 CWP\DIN Road Name City of Toronto.oft"
    pdfFolder = "C:\Users\jlauan\Downloads\Justen Files\Utility Circulation\2027 CWP\"
    
    ' Initialize Outlook
    Set OutlookApp = CreateObject("Outlook.Application")
    Set ws = ThisWorkbook.Sheets("Contacts")
    
    i = 2
    Do While ws.Cells(i, 1).Value <> ""
        companyName = ws.Cells(i, 1).Value
        
        ' Find first matching PDF
        pdfFile = Dir(pdfFolder & "DIN for " & companyName & "*.pdf")
        
        If pdfFile = "" Then
            MsgBox "No PDF found for " & companyName
        Else
            ' Loop through all PDFs for this company
            Do While pdfFile <> ""
                ' Extract road name from PDF filename
                ' Example filename: DIN for Bell Canada re Rampart Rd from Martin Grove Rd to cul-de-sac.pdf
                If InStr(pdfFile, "re ") > 0 Then
                    roadName = Trim(Split(Mid(pdfFile, InStr(pdfFile, "re ") + 3), " from")(0))
                Else
                    roadName = "Road Name" ' fallback if pattern not found
                End If
                
                ' Build subject line
                subjectText = "DIN – " & roadName & " – City of Toronto"
                
                ' Create email from template
                Set OutlookMail = OutlookApp.CreateItemFromTemplate(templatePath)
                With OutlookMail
                    .To = ws.Cells(i, 4).Value
                    .Subject = subjectText
                    .Attachments.Add pdfFolder & pdfFile
                    .Save ' Save to Drafts
                End With
                
                ' Get next PDF
                pdfFile = Dir()
            Loop
        End If
        
        i = i + 1
    Loop
    
    MsgBox "Draft emails created successfully!"
End Sub


				
			

The CreateDraftEmails_OneEmailPerPDF_WithCustomSubject macro automates the creation of draft emails in Outlook for each PDF DIN letter, eliminating the need to manually attach files and write email subjects. It loops through all contacts in Excel, finds the corresponding PDF for each company, extracts the relevant road name from the filename to generate a clear, standardized subject line, and then creates an Outlook draft using a predefined email template with the PDF attached. This automation ensures consistency, reduces human error, and saves significant time when sending hundreds of utility circulation emails each year, allowing staff to focus on higher-value design and coordination tasks.

The CreateDraftEmails_OneEmailPerPDF

_WithCustomSubject macro automates the creation of draft emails in Outlook for each PDF DIN letter, eliminating the need to manually attach files and write email subjects. It loops through all contacts in Excel, finds the corresponding PDF for each company, extracts the relevant road name from the filename to generate a clear, standardized subject line, and then creates an Outlook draft using a predefined email template with the PDF attached. This automation ensures consistency, reduces human error, and saves significant time when sending hundreds of utility circulation emails each year, allowing staff to focus on higher-value design and coordination tasks.

Road Engineering

Cookbook

Referrals

Resources

Contact