VBA outlook exception object, array index out of bound - arrays

The below codes are from Outlook 2010 developer reference, explaining the use of " Exception.AppointmentItem Property"
However while pasting and runing it, it pops up "array index out of bounds (run time error -2147352567(80020009) , and debug points to
Set myException = myRecurrPatt.Exceptions.item(1)
'Get the recurrence pattern for the master
'AppointmentItem. Access the collection of
'exceptions to the regular appointments.
Set myRecurrPatt = myApptItem.GetRecurrencePattern
Set myException = myRecurrPatt.Exceptions.item(1)
'Display the original date, time, and subject
'for this exception.
MsgBox myException.OriginalDate & ": " & saveSubject
The problem persists after I changed the index to 0. Please help, thank you!
Below is the full oringinal code:
Option Explicit
Public Sub cmdExample()
Dim myApptItem As Outlook.AppointmentItem
Dim myRecurrPatt As Outlook.RecurrencePattern
Dim myNameSpace As Outlook.NameSpace
Dim myFolder As Outlook.Folder
Dim myItems As Outlook.Items
Dim myDate As Date
Dim myOddApptItem As Outlook.AppointmentItem
Dim saveSubject As String
Dim newDate As Date
Dim myException As Outlook.Exception
Set myApptItem = Application.CreateItem(olAppointmentItem)
myApptItem.Start = #2/2/2003 3:00:00 PM#
myApptItem.End = #2/2/2003 4:00:00 PM#
myApptItem.Subject = "Meet with Boss"
'Get the recurrence pattern for this appointment
'and set it so that this is a daily appointment
'that begins on 2/2/03 and ends on 2/2/04
'and save it.
Set myRecurrPatt = myApptItem.GetRecurrencePattern
myRecurrPatt.RecurrenceType = olRecursDaily
myRecurrPatt.PatternStartDate = #2/2/2003#
myRecurrPatt.PatternEndDate = #2/2/2004#
myApptItem.Save
'Access the items in the Calendar folder to locate
'the master AppointmentItem for the new series.
Set myNameSpace = Application.GetNamespace("MAPI")
Set myFolder = myNameSpace.GetDefaultFolder(olFolderCalendar)
Set myItems = myFolder.Items
Set myApptItem = myItems("Meet with Boss")
'Get the recurrence pattern for this appointment
'and obtain the occurrence for 3/12/03.
myDate = #3/12/2003 3:00:00 PM#
Set myRecurrPatt = myApptItem.GetRecurrencePattern
Set myOddApptItem = myRecurrPatt.GetOccurrence(myDate)
'Save the existing subject. Change the subject and
'starting time for this particular appointment
'and save it.
saveSubject = myOddApptItem.Subject
myOddApptItem.Subject = "Meet NEW Boss"
newDate = #3/12/2003 3:30:00 PM#
myOddApptItem.Start = newDate
myOddApptItem.Save
'Get the recurrence pattern for the master
'AppointmentItem. Access the collection of
'exceptions to the regular appointments.
Set myRecurrPatt = myApptItem.GetRecurrencePattern
Set myException = myRecurrPatt.Exceptions.Item(1)
'Display the original date, time, and subject
'for this exception.
MsgBox myException.OriginalDate & ": " & saveSubject
'Display the current date, time, and subject
'for this exception.
MsgBox myException.AppointmentItem.Start & ": " & _
myException.AppointmentItem.Subject
End Sub

Simply, there are zero elements in the array. The online tutorial probably had an exception on that example recurring patterned appointment. You on the other hand do not on your Outlook calendar.
Consider wrapping the Exceptions.Item() in a loop. This way if the array is empty nothing will be processed:
Dim ItemIndex As Variant
...
For Each ItemIndex in myRecurrPatt.Exceptions.Items
Set myException = myRecurrPatt.Exceptions.Item(ItemIndex)
'Display the original date, time, and subject
'for this exception.
MsgBox myException.OriginalDate & ": " & saveSubject
'Display the current date, time, and subject
'for this exception.
MsgBox myException.AppointmentItem.Start & ": " & _
myException.AppointmentItem.Subject
Next ItemIndex

The Exceptions class provides the Count property which you may check out before trying to access any item in the collection.
I'd suggest breaking the chain of property and method calls and declaring each property or method on a single line of code. Thus, you will be able to find what property or method call causes the issue.
Finally, you may find the Getting Started with VBA in Outlook 2010 article in MSDN helpful.

Related

Excel VBA, suddenly can't find path?

I got this:
"vba runtime error, cannot save the attachment. path does not exist. verify the path is correct"
I use this:
Sub Save_Outlook_Attachements_Calls()
Dim ol As Outlook.Application
Dim ns As Outlook.Namespace
Dim callfol As Outlook.Folder
Dim salefol As Outlook.Folder
Dim i As Object
Dim mi As Outlook.MailItem
Dim at As Outlook.Attachment
Dim fPat As String
fPat = ThisWorkbook.Path
Set ol = New Outlook.Application
Set ns = ol.GetNamespace("MAPI")
Set FSO = CreateObject("Scripting.FileSystemObject")
Set callfol = ns.Folders("xxx.xxx#xxx.com").Folders("OutlookData").Folders("Calls")
For Each i In callfol.Items
If i.Class = olMail Then
Set mi = i
If mi.Attachments.Count > 0 And Format(mi.ReceivedTime, "yyyy-mm-dd") = Format(Date, "yyyy-mm-dd") Then
For Each at In mi.Attachments
'------------ ------------
at.SaveAsFile (fPat & "\Outlookdata\calls\" & Date & "." & FSO.GetExtensionName(fPat & "\Outlookdata\calls\" & at.Filename))
Next at
End If
End If
Next i
End Sub
It's the Row in the end that gets the error message:
Starting with "at.SaveAsFile (fPat &"
I have checked what the variabel "Fpat" contains, and its "H:\VBA"
So its like it always has been, and the server still called H:
All of that has been working perfect, but suddenly it doesn't?
Its a server map, but i can reach it in the file explorer like normal.
I have restarted the pc :) but error persists.
Any suggestions?
I solved it, i had changed the windows system language to English last week, not just the programs, in which already is in english.
That made the date variable im using to the format 2022/06/20, ie: "/" and that cannot be used in a file name..
i never thought i would find it by my self :)

Replace text in HTMLBody of an email template

I have been using the below code for years to generate communications. I am adapting it to new requirements.
The code grabs data from Sharepoint/MS Teams to filter then copy into a new tab. The code calls an email template that contains placeholders in multiple tables which includes a banner. By using strings it replaces the value of cells with the placeholder.
The data has bullet points and is in paragraphs. However when the email is generated, it has the data in one block as one continuous line.
I tried inserting line breaks but without success.
My latest iteration is to use a replace function, after the loop through the string arrays.
.HTMLBody = replace(.htmlBody, ";", "<BR>")
I put ";" at the end of a line when I want to go the next line.
However, whilst the <BR> does add the line break, it changes the font to Times New Roman and puts in a lot HTML garbage when the email is generated. I suspect is it is from the "<BR>".
The odd thing is when I add a debug.print onto .htmlbody it shows the font and line breaks are correct, with or without the second replace function.
I also tried to change "<BR>" with CHR(10) and vbnewline and other permutations.
I have not included the code that declares the outlook objects and the location of the email template as that works.
Sub ImportSPData() 'Source the Sharepoint data
Dim objMyList As ListObject
Dim objWksheet As Worksheet
Const strSPServer As String = "https://xxxx.xxxxx.xxx.com/teams/xxxx/_vti_bin" 'Sharepoint Url
Const LISTNAME As String = "{1574AC55-E21A-41D2-9EEC-891CFEC69BF6}" 'Sharepoint list code - where the data is inputted
Const VIEWNAME As String = "{34D4B58A-D4C6-4190-9248-896D062543C6}" 'Sharepoint View code - The specific view of the list
Set objWksheet = Worksheets("ImportData") 'Where the data is exported to
objWksheet.Select
If ActiveSheet.AutoFilterMode Then
ActiveSheet.Range("A1").AutoFilter
End If
objWksheet.Cells.Select
Selection.ClearContents
Range("A1").Select
Set objMyList = objWksheet.ListObjects.Add(xlSrcExternal, Array(strSPServer, LISTNAME, VIEWNAME), False, , Range("A1")) 'where the above export lands
Range("A1").Select
ActiveSheet.ListObjects(1).Unlist
If Not ActiveSheet.AutoFilterMode Then
ActiveSheet.Range("A1").AutoFilter
End If
Call applyAutoFilter 'sets up the stage. However when the "Import Data" tab is viewed, the line breaks and bullet points are missing.
End Sub
Sub Replace()
'Populate replacement strings from sharepoint. .Range("xx") corresponds to the column containing new text.
Dim repNumberText As String: repNumberText = dataSheet.Range("f2").Value
Dim repTitleText As String: repTitleText = dataSheet.Range("I2").Value
Dim repSummaryText As String: repSummaryText = dataSheet.Range("B2").Value
Dim repImpactText As String: repImpactText = dataSheet.Range("C2").Value
Dim repUnderwayText As String: repUnderwayText = dataSheet.Range("D2").Value
Dim repCompletedText As String: repCompletedText = dataSheet.Range("E2").Value
Dim repUpdateText As String: repUpdateText = dataSheet.Range("G2").Value
repSummaryText = "<p>" & repSummaryText & "</p>"
repCompletedText = "<p>" & repCompletedText & "</p>"
Dim replaceStrings() As Variant
Dim replaceWithStrings() As Variant
'Replacement Array, replaceStrings are the text placeholders in the email templates, replacewithstrings are the variables assigned above.
replaceStrings = Array("NumberText", "TitleText", "SummaryText", "ImpactText", "UnderwayText", "CompletedText", "UpdateText")
replaceWithStrings = Array(repNumberText, repTitleText, repSummaryText, repImpactText, repUnderwayText, repCompletedText, repUpdateText)
Dim currentItem As String
Dim currentReplaceItem As String
Dim i As Integer
i = UBound(replaceStrings)
Dim j As Integer
j = 0
With msgFile
Today = Format(Now(), "DDDD DD MMM yyyy")
'Dim HtmlBody As String
'Loop through arrays and replace text
Do Until j = i + 1
.HtmlBody = Replace(.HtmlBody, replaceStrings(j), replaceWithStrings(j))
j = j + 1
Loop
'Replace subject texts.\
' .Subject = "Communications"
' .Subject = Today
.Subject = Replace(.Subject, "NumberText", repNumberText)
.Subject = Replace(.Subject, "TitleText", repTitleText) & " " & "-" & " " & Today
.Display
It is not clear when and where all these customizations are made. Also it is not clear where the original item comes form. Anyway, keep in mind that you need to prepare a well-formed HTML document to be able to set up the HTMLBody property correctly. Even if Outlook handles cases where only some tags are provided, it is better to deal with a fully-formed HTML document.
The Outlook object model supports three main ways of customizing the message body:
The Body property returns or sets a string representing the clear-text body of the Outlook item.
The HTMLBody property of the MailItem class returns or sets a string representing the HTML body of the specified item. Setting the HTMLBody property will always update the Body property immediately. For example:
Sub CreateHTMLMail()
'Creates a new e-mail item and modifies its properties.
Dim objMail As Outlook.MailItem
'Create e-mail item
Set objMail = Application.CreateItem(olMailItem)
With objMail
'Set body format to HTML
.BodyFormat = olFormatHTML
.HTMLBody = "<HTML><BODY>Enter the message text here. </BODY></HTML>"
.Display
End With
End Sub
The Word object model can be used for dealing with message bodies. See Chapter 17: Working with Item Bodies for more information.
Note, the MailItem.BodyFormat property allows you to programmatically change the editor that is used for the body of an item.

Cannot insert value NULL into column 'intGolferEventYearID', table does not allow nulls

I have a dialog with a combobox listing the years an event was held.
Changing the year, changes the following list boxes
One list box 'called inEvent' shows all golfers the attended said event.
The other list box called 'available' that shows every golfer we have in our database that did not attend that years event
It has two buttons. One removes golfers from 'inEvent' and moves them to 'available'. This button works.
The other button does the opposite. It adds available golfers to the selected event year. But it gives me the error -
"The statement has been terminated. Cannot insert the value NULL into column 'intGolferEventYearID', table 'dbo.TGolferEventYears'; column does not allow nulls. INSERT fails."
Changing any line of code in VB results in a different error. So I think the error has to come from SQL itself which I don't know much about. Only other thing I can think of is the listbox is giving the wrong information.
Private Sub btnAddAuto_Click(sender As Object, e As EventArgs) Handles btnAddAuto.Click
Dim strInsert As String = ""
Dim cmdInsert As OleDb.OleDbCommand ' used for our Select statement
Dim dt As DataTable = New DataTable ' table we will load from our reader
Dim intRowsAffected As Integer
' open the DB
OpenDatabaseConnectionSQLServer()
' Build the select statement
strInsert = "INSERT INTO TGolferEventYears ( intGolferID, intEventYearID) Values (" & lstAvailable.SelectedValue & ", " & cboEvents.SelectedIndex + 1 & ")"
' Retrieve all the records
cmdInsert = New OleDb.OleDbCommand(strInsert, m_conAdministrator)
intRowsAffected = cmdInsert.ExecuteNonQuery()
' close the database connection and reload the form so the changes are shown
CloseDatabaseConnection()
frmEventsGolfers_Load(sender, e)
End Sub
I separated the data access code from the user interface. This will make it easy to remove data access entirely from the Form if you later desire.
Private Sub MoveGolfer(GolfID As Integer, YearID As Integer)
'If you keep your connections local you can be sure they are
'closed and disposed which is what the Using...End Using blocks do.
Using cn As New SqlConnection("Your connection string")
Using cmd As New SqlCommand("INSERT INTO TGolferEventYears ( intGolferID, intEventYearID) Values (#Golf, #Year;")
'Always use parameters to protect against Sql injection
cmd.Parameters.Add("#Golf", SqlDbType.Int).Value = GolfID
cmd.Parameters.Add("#Year", SqlDbType.Int).Value = YearID
cn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim GolferID As Integer = CInt(lstAvailable.SelectedValue)
Dim Year As Integer = cboEvents.SelectedIndex + 1
Try
MoveGolfer(GolferID, Year)
Catch ex As Exception
'Catch a more specific exception and handle accordingly
MessageBox.Show(ex.Message)
End Try
End Sub
Since I don't really understand SQL I didn't realize my PK didn't have the IDENTITY tag added in the table. Adding this fixed my issue.
Here is the code I added
Dim strSelect As String
Dim cmdSelect As OleDb.OleDbCommand
Dim drSourceTable As OleDb.OleDbDataReader
Dim intNextHighestRecordID As
strSelect = "SELECT MAX(intDealerAutos) + 1 AS intNextHighestRecordID " &
" FROM TDealerAutos"
'Excute command
cmdSelect = New OleDb.OleDbCommand(strSelect, m_conAdministrator)
drSourceTable = cmdSelect.ExecuteReader
'Read result( highest ID )
drSourceTable.Read()
'Null? (Empty Table)
If drSourceTable.IsDBNull(0) = True Then
'Yes, start numbering at 1
intNextHighestRecordID = 1
Else
'No, get the next highest ID
intNextHighestRecordID = CInt(drSourceTable.Item(0))
End If
'Build the select statement
strInsert = "INSERT INTO TDealerAutos ( intDealerAutos, intDealerID, intAutoID)" &
"Values (" & intNextHighestRecordID & ", " & cboDealers.SelectedValue & ", " & lstAvailable.SelectedValue & ")"

Storing Listbox Value Generated by a Row Source Query

I am trying to store the value of a listbox (Actual_Polygon_Area) that has been generated via row source query. Each time I run the script my message box tells me that the value of the listbox is null and I suspect it's caused by the row source. The suspected listbox is named Actual_Polygon_Area and the field I am trying to store it in is Polygon_Area within the table FS_Actual_Polygon.
Private Sub Actual_Polygon_Save_Click()
If IsNull(Actual_Polygon_Year) Then
MsgBox "Please enter a year in which this polygon received treatment"
Actual_Polygon_Year.SetFocus
ElseIf IsNull(Actual_Polygon_Season) Then
MsgBox "Please enter the season in which this polygon received treatment"
Actual_Polygon_Season.SetFocus
ElseIf IsNull(Actual_Polygon_Treatment) Then
MsgBox "Please select the treatment type that was completed in this polygon."
Actual_Polygon_Treatment.SetFocus
ElseIf IsNull(Actual_Polygon_Notes) Then
MsgBox "Please write a short summary regarding treatment goals and objectives."
Actual_Polygon_Notes.SetFocus
ElseIf IsNull(Actual_Polygon_Area) Then
MsgBox "Polygon Area is null, please enter a value"
Actual_Polygon_Area.SetFocus
Else
Dim MyConnection As ADODB.Connection
Set MyConnection = CurrentProject.Connection
Dim rsFS_Actual_Polygon As ADODB.Recordset
Set rsFS_Actual_Polygon = New ADODB.Recordset
If IsNull(PolygonNo) Then
'add
rsFS_Actual_Polygon.Open "select * from FS_Actual_Polygon where PolygonNo= " & Actual_Polygon_ID & " and Treatment_Season= '" & Actual_Polygon_Season & "' and Treatment_Type= '" & Actual_Polygon_Treatment & "' and Project_Name = '" & Actual_Polygon_Project_Name & "' and Polygon_Area = " & Actual_Polygon_Area.Value & " and Treatment_Year = " & Actual_Polygon_Year, _
MyConnection, adOpenDynamic, adLockOptimistic
If Not rsFS_Actual_Polygon.EOF Then
MsgBox "The combination of Polygon ID, treatment-year, treatment-season, and treatment type already exist. Please check the combination."
Actual_Polygon_Year.SetFocus
Else
With rsFS_Actual_Polygon
.AddNew
![PolygonID] = Actual_Polygon_ID
![Project_Name] = Actual_Polygon_Project_Name
![Polygon_Area] = Actual_Polygon_Area.Value
![Treatment_Year] = Actual_Polygon_Year
![Treatment_Season] = Actual_Polygon_Season
![Treatment_Type] = Actual_Polygon_Treatment
![Polygon_Notes] = Actual_Polygon_Notes
.Update
End With
Actual_Polygon_Record.Requery
Actual_Polygon_New_Click
End If
I can post the rest of the code if necessary, I just didn't want to post a huge chunk.
You can use the .ItemsSelected and .ItemData methods to find and pass the value of the selected row from the listbox to your table.
This is a fairly typical use of the listbox control, and is a little easier than dealing with a multi-select control, but is still a bit cumbersome. You will need to create a For Each...Next loop to collect the row number of the selected row in your listbox and save to a variable. Then use that variable as the argument of the .ItemData method to return the bound column value for that selected row.
This MSDN article should have everything you need.
EDIT: While the above solution works for multi and single select listboxes, there is a more expedient way for single select listboxes:
Dim i as Integer
i = Me!Actual_Polygon_Area.ListIndex
If i = -1 Then
MsgBox "No item has been selected"
Exit Sub
End If
'Do above prior to `WITH` loop
...'Then in your `WITH` loop:
![Polygon_Area] = Actual_Polygon_Area.ItemData(i)

Getting an error (3163) on MS Access 2003

The error says "The field is too small to accept the amount of data you attempted to add. Try inserting or pasting less data."
The database is supposed to pull in information from the Excel sheet that is passed through to it, and import the information into a recordset of the text field. However, the text field, somewhere down the line, has been limited to 50 characters. How can I change the maximum size of the text field? Thank you for any help
This is just part of the code, and the textfield I'm trying to make larger is "Idea_#", which is the last line of the code i posted
Sub Read_Recommendations()
On Error GoTo error_code
Dim FD As Office.FileDialog
Dim xlapp As Excel.Application
Dim xlsheet As Excel.Worksheet
Dim xlbook As Excel.Workbook
Dim db As Database
Dim rs As Recordset
Dim sql As String
Dim WP As String
Dim row As Integer
Dim File As String
Set db = CurrentDb
Set FD = Application.FileDialog(msoFileDialogOpen)
If FD.Show = True Then
File = FD.SelectedItems(1)
Set xlapp = CreateObject("Excel.Application")
Set xlbook = GetObject(File)
Set xlsheet = xlbook.Worksheets("Recommendation Approval Form")
Dim protection As Boolean
With xlsheet
'support unprotected worksheets
protection = xlsheet.ProtectContents
If protection Then xlsheet.Unprotect "veproject"
WP = .Range("WP_Number")
' Check that active WP and the WP of the uploading form is the same
' If WPs are different, awares users and prompts user whether or not to continue
Dim DifferentProject As String
If Not get_WP = WP Then
DifferentProject = MsgBox("You are uploading to the project with WP number: " & WP & " which is not the active project. Do you wish to continue?", vbYesNo)
If DifferentProject = 7 Then Exit Sub
End If
' Check that WP is correct by checking if it exists in the Record Information table
' delete the existing recomendations, we want to keep the most recent recomendations
' perhaps change this to a dialog in the future
sql = "DELETE * from tbl_recomendations WHERE WP_Number = '" & WP & "'"
db.Execute (sql)
row = 8
Set rs = db.OpenRecordset("tbl_recomendations")
Do While .Range("D" & row) <> ""
rs.AddNew
rs("WP_Number") = WP
rs("Idea_#") = (.Range("C" & row))
........
In Access, open tbl_recomendations in Design View. It sounds like the Field Size property for Idea_# is set at 50. You can change that up to 255.
If you need to store more than 255 characters in Idea_#, change its Data Type from Text to Memo.

Resources