Object Required error at seemingly random locations - vba

I get this error only in specific spots, where it doesn't seem it should matter. For instance, In the first case, where I set timevals, the program runs fine. In the second case, where I set timevals again, I get the 424 Error.
I tried moving the Set timevals = time(mrCell.column) outside of my Select, as it does not need to be inside, calling the function for every single case (it can call it once, that's all that's needed..) but I am greeted with the error there as well. It only seems to work inside the Select, and only in certain areas.
'MsgBox .Value
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
'MsgBox .Value
Case Is = "VM554 SAAnesSx - PtCare (Groups 12-14)"
MsgBox .Value
MsgBox mrCell.column
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
MsgBox .Value
Here is the majority of the code.
Set Selected = Selection.Cells
Dim timevals As Collection
Dim time_start As String
Dim time_stop As String
For Each mrCell In Selected
With mrCell
Select Case .Value
' Here, we'll have to manually input the names (from the other macro that labeled everything..)
Case Is = "VM569 AgAn Lab G 12-14"
'MsgBox .Value
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
Case Is = "VM570 AgAn2"
'MsgBox .Value
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
' MsgBox .Value
Case Is = "VM571 Therio"
'MsgBox .Value
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
'MsgBox .Value
Case Is = "VM552 SAM2"
'MsgBox .Value
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
'MsgBox .Value
Case Is = "VM597.3 PopTherio Lec"
'MsgBox .Value
Set timevals = time(mrCell.column)
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
'MsgBox .Value
Case Is = "VM554 SAAnesSx - PtCare (Groups 12-14)"
MsgBox .Value
MsgBox mrCell.column
Set timevals = time(mrCell.column) ' Error here
time_start = timevals.item("start")
MsgBox time_start
time_stop = timevals.item("stop")
MsgBox time_stop
MsgBox .Value
End Select
End With
Next
And here is the time function:
Function time(column As Long)
'Delcare Variables
Dim c As New Collection
Dim item As Variant
Dim key As String
Dim eg_start As String
Dim eg_stop As String
Dim ni_start As String
Dim ni_stop As String
Dim te_start As String
Dim te_stop As String
Dim el_start As String
Dim el_stop As String
'instantiate them
'8-9
eg_start = "8:09AM"
eg_stop = "9:02AM"
'9-10
ni_start = "9:09AM"
ni_stop = "10:02AM"
'10-11
te_start = "10:09AM"
te_stop = "11:02AM"
'11-12
el_start = "11:09AM"
el_stop = "12:02PM"
Select Case column
Case Is = 8
key = "start"
item = eg_start
c.Add item, key
key = "stop"
item = eg_stop
c.Add item, key
Set time = c
Case Is = 9
key = "start"
item = ni_start
c.Add item, key
key = "stop"
item = ni_stop
c.Add item, key
Set time = c
Case Is = 10
key = "start"
item = te_start
c.Add item, key
key = "stop"
item = te_stop
c.Add item, key
Set time = c
Case Is = 11
key = "start"
item = el_start
c.Add item, key
key = "stop"
item = el_stop
c.Add item, key
Set time = c
Case Else
key = "start"
item = "N/A"
c.Add item, key
key = "stop"
item = "N/A"
c.Add item, key
End Select
MsgBox "goodbye"
End Function

This site doesn't offer proof-reading services for faulty code. Therefore your code is too voluminous to be handled properly here. Some errors have been pointed out in the comments above. I want to address the volume of your misnamed and faulty function Time. Here is a version of it cut down to the required length.
Function GetTimes(Clm As Long) As Times
' 232
' Start and End will both be 0 if Clm <8 or >11
Dim StartTime As Double
If (Clm >= 8) And (Clm <= 11) Then
StartTime = TimeSerial(Clm, 0, 0)
End If
With GetTimes
.Start = StartTime
If StartTime Then .End = TimeSerial(Clm + 1, 2, 0)
End With
End Function
It takes the column number in the argument as the start hour and then adds an hour and 2 minutes to that for the end time. If the column (hour) < 8 or > 11 both start and end will be 0.
Your Collection doesn't work with Key and Item like a Dictionary but what you want is a Type. The Type must be declared at the top of the module, before any procedure (but after Option Explicit). This is the code.
Option Explicit
Private Type Times
Start As Double
End As Double
End Type
The function GetTimes uses this Type. Therefore it won't work without the above declaration. For testing purposes use the little procedure below. You can assign different numbers to the variable Clm and read the return values in the Immediate pane. The code also shows you how to convert hours (Long data type) and minutes (integers) to Double and then read the Double as time. Paste this procedure below the Type declaration.
Private Sub Test()
Const TimeFormat As String = "hh:mm"
Dim MyTime As Times
Dim Clm As Long ' Test column
Clm = 10 ' change for testing
MyTime = GetTimes(Clm)
With MyTime
If .Start Then
Debug.Print "Start = "; Format(.Start, TimeFormat) & Chr(13) & _
" End = "; Format(.End, TimeFormat)
Else
Debug.Print "Start = Stop" & Chr(13) & " End = N/A"
End If
End With
End Sub

I didn't have a "Default" Set for my variable "time". Adding Set time = c after the End Select solved my issue.
Also changing the name of the function away from time as it can be confusing with the default function Time. (Was no part of the issue, but, hey.)

Related

Excel VBA code only works in debug mode

I've already searched in a bunch of topics and no solution seemed to work for me.
I've an Excel macro file that sometimes works fine, but sometimes only works in stepping mode.
This is a sub inside a main sub that passes a value (message) to a spreadsheet from an Outlook Calendar by category (key). (for this code I adapted from Script to total hours by calendar category in Outlook) .The value goes into the row with the same name as the category and the week value in the column. I've tried the DoEvents and I thought it had worked, but when I tried to run it in a different computer it failed again.
Any ideas?
Option Explicit
Public keyArray
Sub totalCategories()
Dim app As New Outlook.Application
Dim namespace As Outlook.namespace
Dim calendar As Outlook.Folder
Dim appt As Outlook.AppointmentItem
Dim apptList As Outlook.Items
Dim apptListFiltered As Outlook.Items
Dim startDate As String
Dim endDate As String
Dim category As String
Dim duration As Integer
Dim outMsg As String
Dim firstDayOfTheYear As Date
'Going to be used to get start and end date
firstDayOfTheYear = Date
firstDayOfTheYear = "01/01/" & Right(firstDayOfTheYear, 4)
' Access appointment list
Set namespace = app.GetNamespace("MAPI")
Set calendar = namespace.GetDefaultFolder(olFolderCalendar)
Set apptList = calendar.Items
' Include recurring appointments and sort the list
apptList.IncludeRecurrences = True
apptList.Sort "[Start]"
' Get selected date
startDate = firstDayOfTheYear + 7 * (CInt(SelectWeek.week) - 1)
endDate = firstDayOfTheYear + 7 * (CInt(SelectWeek.week) - 1) + 6
startDate = Format(startDate, "dd/MM/yyyy") & " 00:01"
endDate = Format(endDate, "dd/MM/yyyy") & " 11:59 PM"
' Filter the appointment list
Dim strFilter As String
strFilter = "[Start] >= '" & startDate & "'" & " AND [End] <= '" & endDate & "'"
Set apptListFiltered = apptList.Restrict(strFilter)
' Loop through the appointments and total for each category
Dim catHours
Set catHours = CreateObject("Scripting.Dictionary")
For Each appt In apptListFiltered
category = appt.Categories
duration = appt.duration
If catHours.Exists(category) Then
catHours(category) = catHours(category) + duration
Else
catHours.Add category, duration
End If
Next
' Loop through the categories
Dim key
keyArray = catHours.Keys
DoEvents 'prevents a bug from happening --> in some cases the total hours weren't divided by categories
For Each key In keyArray
outMsg = catHours(key) / 60
'Print in Realizado sheet --> activities must be in range (name manager) as "atividades"
writeReport SelectWeek.week, outMsg, key
Next
' Clean up objects
Set app = Nothing
Set namespace = Nothing
Set calendar = Nothing
Set appt = Nothing
Set apptList = Nothing
Set apptListFiltered = Nothing
End Sub
Sub writeReport(week, message As String, key)
Dim ws As Worksheet
Dim i As Integer
Dim Activities, nActivities As Integer
Set ws = Sheets("5")
Activities = Range("activities")
nActivities = UBound(Activities)
DoEvents
For i = 1 To nActivities
DoEvents
If key = Cells(i + 8, 2).Value Then
ws.Cells(i + 8, week + 3).Value = CDbl(message)
Exit For
End If
Next i
End Sub
You need to handle errors explicitly so you know exactly what is going on. Trust me that this will save you HEAPS of time troubleshooting your own code, especially in VBA.
Common practice is something like "try, catch, finally".
Dim position as string
Sub foo()
position = "sub function short description"
On Error GoTo catch
Err.Clear
'do stuff
finally:
On Error Resume Next
'do cleanup stuff
Exit Sub
catch:
Debug.Print Right(ThisWorkbook.FullName, Len(ThisWorkbook.FullName) - 3) & ", _
Position: " & errorPosition & " , Error Code: [ " & Hex(Err.number) & "], _
Description: " & Err.Description & ""
Resume finally
End Sub
Problem solved!
From this:
If key = Cells(i + 8, 2).Value Then
ws.Cells(i + 8, week + 3).Value = CDbl(message)
Exit For
End If
To this:
If key = Activities(i, 1) Then
ws.Cells(i + 8, week + 3).Value = CDbl(message)
Exit For
End If

Array insertion of Duplicated and not duplicated data to different column in VBA

Good day! in my worksheet i have (1) textbox as TextBox1 and 1 button for submit button. I have here sample code that gives splitted text as an output. I just want that if there's duplicated word in textbox1 and the user enters the submit button it will saves to worksheet(DatabaseStorage) and categorize the output from No Duplicated Word and With duplicated Word. Because this two different fields will be needed for some function of the system.
Private Sub CommandButton1_Click()
Call SplitText
End Sub
Sub SplitText()
Dim WArray As Variant
Dim TextString As String
TextString = TextBox1
WArray = Split(TextBox1, " ")
If (TextString = "") Then
MsgBox ("Error: Pls Enter your data")
Else
With Sheets("DatabaseStorage")
.Cells(.Rows.Count, 1).End(xlUp).Offset(1, 0).Resize(UBound(WArray) + IIf(LBound(WArray) = 0, 1, 0)) = Application.Transpose(WArray)
End With
MsgBox ("Successfully inserted")
End If
End Sub
This should accomplish what you need. I loop through the array to check if the given value exists in the "No Duplicates" column. If not, don't print it there.
Any time I encounter a situation where I need to check a single value against a list (ex. check for duplicates, GT/LT, etc.), I consider looping.
Sub SplitText()
Dim WArray As Variant
Dim TextString As String
Dim col_no_dup As Long
Dim col_dup As Long
Dim counter As Integer
Dim sht_database As Worksheet
With ThisWorkbook
Set sht_database = .Sheets("DatabaseStorage")
TextString = LCase(.Sheets("Sheet1").Shapes("Textbox1").DrawingObject.Text)
End With
WArray = Split(TextString, " ") 'load array
If (TextString = "") Then
MsgBox ("Error: Pls Enter your data")
End
Else: End If
'set column locations for duplicates/no duplicates
col_no_dup = 1
col_dup = 2
With sht_database
.Range("A2:B10000").ClearContents 'clear existing data. Change this as needed
'Print whole array into duplicates column
.Cells(Cells.Rows.Count, col_dup).End(xlUp).Offset(1, 0).Resize(UBound(WArray) + IIf(LBound(WArray) = 0, 1, 0)) = Application.Transpose(WArray)
'Loop through array
For i = LBound(WArray) To UBound(WArray)
counter = 0
lrow_no_dup = .Cells(Cells.Rows.Count, col_no_dup).End(xlUp).Row
For n = 1 To lrow_no_dup 'loop through and check each existing value in the no dup column
If .Cells(n, col_no_dup).Value = WArray(i) Then
counter = counter + 1 'account for each occurence
Else: End If
Next n
If counter = 0 Then 'counter = 0 implies the value doesn't exist in the "No Duplicates" column
.Cells(lrow_no_dup + 1, col_no_dup).Value = WArray(i)
Else: End If
Next i
End With
MsgBox ("Successfully inserted")
End Sub

How to get the MS Word Form Fields Check box associated text and their value using VBA?

How to get the MS word document checkbox form element associated text value. I am able to extract the value of the checkbox. I tried with bookmark and name properties and found that there is no value associated with bookmark filed of the checkbox. I got the following output. Any thoughts?
Form Fields:
Code:
Sub Test()
Dim strCheckBoxName As String
Dim strCheckBoxValue As String
For i = 1 To ActiveDocument.FormFields.Count
If ActiveDocument.FormFields(i).CheckBox Then
strCheckBoxName = ActiveDocument.FormFields(i).Name
strCheckBoxValue = ActiveDocument.FormFields(i).CheckBox.Value
Debug.Print strCheckBoxName & " = " & strCheckBoxValue
End If
Next
End Sub
Output:
Check1 = True
Check1 = True
Check1 = True
Check1 = False
Check1 = False
Check1 = False
Solution looking for:
A = True
B = True
C = True
D = False
E = False
F = False
EDIT:
By default, when a FormField Check Box is added, it has a Bookmark (name) of Check# where # is sequential starting at 1 until n. Copy and Paste are your friends with FormFields, so one of two things will occur if you go that route to get, say your 1000 FormFields:
1: If you do not alter the value of Bookmark (e.g. default to Check1) and copy and paste that say 1000 times, you end up with 1000 FormFields of Bookmark Check1.
2: If you alter the value of Bookmark (e.g. to A) and copy and past that say 1000 times, only the first FormField retains the Bookmark of A while the rest have a Bookmark that is empty.
You can alter the Check Box default bookmark value (in this case Check1 as a result from copy and paste over and over) to a sequential value such as A1, A2, A3, A4 or Check1, Check2, Check3, etc... by using the following:
Sub Test()
Dim strCheckBoxName As String
Dim strCheckBoxValue As String
For i = 1 To ActiveDocument.formFields.Count
If ActiveDocument.formFields(i).CheckBox Then
strCheckBoxName = ActiveDocument.formFields(i).Name
strCheckBoxValue = ActiveDocument.formFields(i).CheckBox.Value
Debug.Print strCheckBoxName & " = " & strCheckBoxValue
End If
Next
End Sub
Sub RenameCheckBox()
Dim oFields As formFields
Dim oVar As Variant
Dim i As Long
Dim x As Long
x = 0
i = 0
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect
End If
Set oFields = ActiveDocument.formFields
For x = 1 To oFields.Count
oFields(x).Select
Select Case oFields(x).Type
Case wdFieldFormCheckBox
oVar = oFields(x).CheckBox.Value
i = i + 1
With Dialogs(wdDialogFormFieldOptions)
.Name = "Check" & i
.Execute
End With
oFields(x).CheckBox.Value = oVar
Case Else
'Do Nothing
End Select
Next x
ActiveDocument.Protect Type:=wdAllowOnlyFormFields, NoReset:=True
Call Test
End Sub

Subroutine unexpectedly ends when a Workbook is closed

my problem today is a part of a subroutine that inexplicably breaks its execution when a Workbook is closed.
I have written the following code:
Public Const Pi As Double = 3.14159265358979
Public Const Rad As Double = Pi / 180
Public CalcBook As Workbook
Public FilePath As String, Files() As String
Public FreqArray() As Integer
Sub Main()
Dim ChooseFolder As Object, FilePath As String, StrFile As String
Dim i As Integer, j As Integer, k As Integer, x As Integer
Dim DirNum As Integer, HNum As Integer, VNum As Integer
Dim DirColShift As Integer, HColShift As Integer, VColShift As Integer
Dim TheStart As Date, TheEnd As Date, TotalTime As Date
Set ChooseFolder = Application.FileDialog(msoFileDialogFolderPicker)
With ChooseFolder
.AllowMultiSelect = False
.Title = "Please choose a folder containing .txt files"
If .Show = -1 Then
FilePath = .SelectedItems(1) & "\"
Else
Set ChooseFolder = Nothing
Exit Sub
End If
End With
Set ChooseFolder = Nothing
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayStatusBar = False
' Stores only files containing an AntennaName + "_T" + any number of characters + "_?_?45.xls" string
' (where "?" is a single character and "*" is any number). Checks if the number of files is correct too.
StrFile = Dir(FilePath & "*_T*_?_?45.txt")
Do While Len(StrFile) > 0
ReDim Preserve Files(i)
Files(i) = FilePath & StrFile
i = i + 1
StrFile = Dir
Loop
If Not (UBound(Files) + 1) / 6 = Int((UBound(Files) + 1) / 6) Then GoTo FileError
For i = 0 To UBound(Files)
Select Case Right(Files(i), 9)
Case "D_+45.txt", "D_-45.txt"
DirNum = DirNum + 1
Case "H_+45.txt", "H_-45.txt"
HNum = HNum + 1
Case "V_+45.txt", "V_-45.txt"
VNum = VNum + 1
End Select
Next
If Not (DirNum / 2 = Int(DirNum / 2) And HNum / 2 = Int(HNum / 2) And VNum / 2 = Int(VNum / 2) And DirNum = HNum And HNum = VNum) Then
FileError:
MsgBox "Failed to properly load files. Looks like a wrong number of them is at dispose", vbCritical, "Check the import-files"
Exit Sub
End If
' Imports files in Excel for better data access
Set CalcBook = Application.Workbooks.Add
' FROM HERE ON THE DATA IS PROCESSED IN ORDER TO OBTAIN AN EXCEL WORKBOOK WITH 3 SHEETS CALLED "Directivity", "Horizontal" and "Vertical".
Application.ScreenUpdating = True
Options.Show
TheStart = Now
Application.ScreenUpdating = False
If Options.OnlyEval = False Then PolarCharts
If Options.OnlyCharts = False Then Auswertung
Application.DisplayAlerts = False
CalcBook.Close savechanges:=False
Application.DisplayAlerts = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Set CalcBook = Nothing
TheEnd = Now
TotalTime = TheEnd - TheStart
MsgBox Format(TotalTime, "HH:MM:SS"), vbInformation, "Computing Time"
Unload Options
End Sub
Options is a form which I need in order to access data for the PolarCharts and Auswertung. These Subs are correctly executed (I know that because the data they save is correct too).
I tried deleting the .ScreenUpdating and .DisplayAlerts commands, as well as the Unload thinking that they could bugging something, but the result hasn't changed.
Know also that the Workbook I'm closing contains NO CODE at all (and nothing else addresses a ".Close" so it's impossible that something is executed on the .Close event).
Below my "Options" code:
Private Sub Cancel_Click()
End
End Sub
Private Sub UserForm_Terminate()
End
End Sub
Private Sub Ok_Click()
If Me.OnlyCharts = False Then
ReDim SubFreq(4)
If Not (Me.Start1.ListIndex = -1 And Me.Stop1.ListIndex = -1) Then SubFreq(0) = Me.Start1.List(Me.Start1.ListIndex) & "-" & Me.Stop1.List(Me.Stop1.ListIndex)
If Not (Me.Start2.ListIndex = -1 And Me.Stop2.ListIndex = -1) Then SubFreq(1) = Me.Start2.List(Me.Start2.ListIndex) & "-" & Me.Stop2.List(Me.Stop2.ListIndex)
If Not (Me.Start3.ListIndex = -1 And Me.Stop3.ListIndex = -1) Then SubFreq(2) = Me.Start3.List(Me.Start3.ListIndex) & "-" & Me.Stop3.List(Me.Stop3.ListIndex)
If Not (Me.Start4.ListIndex = -1 And Me.Stop4.ListIndex = -1) Then SubFreq(3) = Me.Start4.List(Me.Start4.ListIndex) & "-" & Me.Stop4.List(Me.Stop4.ListIndex)
If Not (Me.Start5.ListIndex = -1 And Me.Stop5.ListIndex = -1) Then SubFreq(4) = Me.Start5.List(Me.Start5.ListIndex) & "-" & Me.Stop5.List(Me.Stop5.ListIndex)
If (Me.Start1 = "" And Me.Start2 = "" And Me.Start3 = "" And Me.Start4 = "" And Me.Start5 = "" And Me.Stop1 = "" And Me.Stop2 = "" And Me.Stop3 = "" And Me.Stop4 = "" And Me.Stop5 = "") _
Or Me.Start1.Value > Me.Stop1.Value Or Me.Start2.Value > Me.Stop2.Value Or Me.Start3.Value > Me.Stop3.Value Or Me.Start4.Value > Me.Stop4.Value Or Me.Start5.Value > Me.Stop5.Value _
Or (Me.Start1.ListIndex = -1 And Me.Stop1.ListIndex >= 0) Or (Me.Start2.ListIndex = -1 And Me.Stop2.ListIndex >= 0) Or (Me.Start3.ListIndex = -1 And Me.Stop3.ListIndex >= 0) Or (Me.Start4.ListIndex = -1 And Me.Stop4.ListIndex >= 0) Or (Me.Start5.ListIndex = -1 And Me.Stop5.ListIndex >= 0) _
Or (Me.Start1.ListIndex >= 0 And Me.Stop1.ListIndex = -1) Or (Me.Start2.ListIndex >= 0 And Me.Stop2.ListIndex = -1) Or (Me.Start3.ListIndex >= 0 And Me.Stop3.ListIndex = -1) Or (Me.Start4.ListIndex >= 0 And Me.Stop4.ListIndex = -1) Or (Me.Start5.ListIndex >= 0 And Me.Stop5.ListIndex = -1) Then
MsgBox("Please select correctly the frequency ranges - Maybe Start > Stop, one of those was not properly inserted, or the fields are blank", vbExclamation, "Frequency choice error")
GoTo hell
End If
For i = 0 To 4
If Not SubFreq(i) = "" Then j = j + 1
Next i
j = j - 1
ReDim Preserve SubFreq(j)
End If
Me.Hide
hell:
End Sub
Private Sub UserForm_Initialize()
Dim i As Byte
Me.StartMeas = Date
Me.StopMeas = Date
Me.Worker.AddItem "lol"
Me.Worker.AddItem "rofl"
Me.Worker.ListIndex = 0
For i = LBound(FreqArray) To UBound(FreqArray)
Me.Start1.AddItem FreqArray(i)
Me.Start2.AddItem FreqArray(i)
Me.Start3.AddItem FreqArray(i)
Me.Start4.AddItem FreqArray(i)
Me.Start5.AddItem FreqArray(i)
Me.Stop1.AddItem FreqArray(i)
Me.Stop2.AddItem FreqArray(i)
Me.Stop3.AddItem FreqArray(i)
Me.Stop4.AddItem FreqArray(i)
Me.Stop5.AddItem FreqArray(i)
Next i
Me.Start1.ListIndex = 0
Me.Stop1.ListIndex = Me.Stop1.ListCount - 1
End Sub
Apparently when I Close CalcBook, it triggers the UserForm_Terminate event from Options which Ends all the code! How do I avoid this?
Just remove the statement End bacause End causes the abrupt end of code execution.
I see End in the Cancel and Terminate event handlers. If you have it on other places, remove it es well.
If you need exit from a method then use Exit Sub.
Why: because End work that way. Read e.g. this post: http://www.vbforums.com/showthread.php?511766-Classic-VB-Why-is-using-the-End-statement-(or-VB-s-quot-stop-quot-button)-a-bad-idea.
If you need stop code from execution use If-condition or even Exit Sub but avoid using End for it.
Try
Workbooks("CalcBook").Close savechanges:=False
I suspect that both error alerts and indications of an error on the screen are being suppressed

Excel to create task in Outlook

I am relatively new to VBA and so I'm sure this is a basic mistake that I am making!
A1 contains valid date, A2 contains task information, A3 contains number of days before A1 date to trigger task reminder.
The problem is when I put =addtotasks(A1,A2,A3)
It just comes up with #NAME?
I have enabled the Microsoft Outlook 14.0 Object Library in the references.
I am based in the UK telling you for dates purposes.
This is the following code. I have included some extra code for setting a remainder only on a business day.
'Function NextBusinessDay(dateFrom As Date, _
Optional daysAhead As Long = 1) As Date
Dim currentDate As Date
Dim nextDate As Date
' convert neg to pos
If daysAhead < 0 Then
daysAhead = Abs(daysAhead)
End If
' determine next date
currentDate = dateFrom
nextDate = DateAdd("d", daysAhead, currentDate)
' is next date a weekend day?
Select Case Weekday(nextDate, vbUseSystemDayOfWeek)
Case vbSunday
nextDate = DateAdd("d", 1, nextDate)
Case vbSaturday
nextDate = DateAdd("d", 2, nextDate)
End Select
NextBusinessDay = CDate(Int(nextDate))
End Function
Dim bWeStartedOutlook As Boolean
Function AddToTasks(strDate As String, strText As String, DaysOut As Integer) As Boolean
' Adds a task reminder to Outlook Tasks a specific number of days before the date specified
' Returns TRUE if successful ' Will not trigger OMG because no protected properties are accessed
'
' Usage:
' =AddToTasks("12/31/2008", "Something to remember", 30)
' or:
' =AddToTasks(A1, A2, A3)
' where A1 contains valid date, A2 contains task information, A3 contains number of days before A1 date to trigger task reminder '
' can also be used in VBA :
'If AddToTasks("12/31/2008", "Christmas shopping", 30) Then
' MsgBox "ok!"
'End If
Dim intDaysBack As Integer
Dim dteDate As Date
Dim olApp As Object 'Outlook.Application
Dim objTask As Object ' Outlook.TaskItem
' make sure all fields were filled in
If (Not IsDate(strDate)) Or (strText = "") Or (DaysOut <= 0) Then
AddToTasks = False
GoTo ExitProc
End If
' We want the task reminder a certain number of days BEFORE the due date
' ex: if DaysOut = 120, then we want the due date to be -120 before the date specified
' we need to pass -120 to the NextBusinessDay function, so to go from 120 to -120,
' we subtract double the number (240) from the number provided (120).
' 120 - (120 * 2); 120 - 240 = -120
intDaysBack = DaysOut - (DaysOut * 2)
dteDate = NextBusinessDay(CDate(strDate), intDaysBack)
On Error Resume Next
Set olApp = GetOutlookApp
On Error GoTo 0
If Not olApp Is Nothing Then
Set objTask = olApp.CreateItem(3) ' task item
With objTask
.StartDate = dteDate
.Subject = strText & ", due on: " & strDate
.ReminderSet = True
.Save
End With
Else
AddToTasks = False
GoTo ExitProc
End If
' if we got this far, it must have worked
AddToTasks = True
ExitProc:
If bWeStartedOutlook Then
olApp.Quit
End If
Set olApp = Nothing
Set objTask = Nothing
End Function
Function GetOutlookApp() As Object
On Error Resume Next
Set GetOutlookApp = GetObject(, "Outlook.Application")
If Err.Number <> 0 Then
Set GetOutlookApp = CreateObject("Outlook.Application")
bWeStartedOutlook = True
End If
On Error GoTo 0
End Function
I have taken this code from this website, by the way:
http://www.jpsoftwaretech.com/get-previous-business-day-in-vba/
The #Name? error happens when you reference a function or variable unknown to the program. It's not sure where this function resides. Try using the "fx" button next to the formula bar and selecting user defined functions, it should be listed there.
My guess is you created this function in a different work book probably the personal.xlsb.
In order to use user defined functions you have to reference the full path to them. Try reading the last paragraph here:
http://office.microsoft.com/en-us/excel-help/creating-custom-functions-HA001111701.aspx