I have a sub on a form which is intended to allow users to report bugs and suggest improvements to the form. I have it pretty much ready to go, but keep running into issues with adding attachments.
Sub Submit()
Dim OutApp As Object
Dim OutMail As Object
Dim Item
Dim STR As String, AdminOnly As String, TruncBox As String, STRAttachments As String
For Each cCont In Me.MultiPage1.SelectedItem.Controls
Select Case TypeName(cCont)
Case "TextBox"
If cCont.value = "Please enter a short description here." Or _
cCont.value = "Please enter a short description here." Then
MsgBox ("Please enter all information.")
Exit Sub
ElseIf cCont.value = "" Then
MsgBox ("Please enter all information.")
Exit Sub
End If
Case "ComboBox"
If cCont.value = "" Then
MsgBox ("Please enter all information.")
Exit Sub
ElseIf InStr(cCont.value, "Report") Then
TruncBox = "BUG"
Else
TruncBox = "SUGGESTION"
End If
End Select
Next
STR = "{email address redacted}"
If RecipientsListBox.ListCount = 0 Then
AdminOnly = MsgBox("Only admin will receive updates!", _
vbOKCancel + vbExclamation, "No Users on Watch List")
If AdminOnly = vbCancel Then
Exit Sub
Else
STR = STR
End If
Else
For Each Item In RecipientsListBox.List
STR = STR & ";" & Item
Next Item
End If
Application.ScreenUpdating = False
Set OutApp = CreateObject("Outlook.Application")
On Error GoTo cleanup
Set OutMail = OutApp.CreateItem(0)
On Error Resume Next
With OutMail
.to = STR
Call .Recipients.resolveall
.Subject = TruncBox & ": " & ActiveWorkbook.Name & ": " & ShortDescriptionTextBox
.Body = LongDescriptionTextBox
If AttachmentsListBox.ListCount = 0 Then
Else
For Each Item In AttachmentsListBox.List
STRAttachments = Item
.Attachments.Add STRAttachments
Next Item
End If
'.Send 'Or use Display
.Display
End With
On Error GoTo 0
Set OutMail = Nothing
cleanup:
Set OutApp = Nothing
Application.ScreenUpdating = True
End Sub
I have run through various attempts at looping through each item on the AttachmentsListBox control, and ready to ask for help. This latest attempt produced Run-time error '94': Invalid use of Null with the line STRAttachments = Item returning null in the highlighted section. Looking at what I already have, and comparing to other searches on the internet, I don't understand. I returned variant Item to STR in the line STR = STR & ";" & Item above, and I've seen other examples of strings being returned as attachments. What am I missing?
So, this is a problem that I have identified in the past, but I haven't thoroughly researched the root cause. ListBox.List returns a multi-dimensional array of ListObjects. So, even though you have a ListBox with 1 column, the List array has multiple columns. When you loop over with a For Each loop, it tries to access values in these other columns, which just result in a Null value. Try using a For loop with a counter, such as:
Private Sub UserFormButton_Click()
For i = 0 To Me.ListBox1.ListCount - 1
MsgBox Me.ListBox1.List(i)
Next i
End Sub
Related
So my code loops through a range of cells and triggers an email on the condition that, in this example, N150 = F150. This works, the email is sent. But what I'm finding difficult is referencing the changed cell in the email body. You can see within the xMailBody variable I have tried cll.Offset(0, -12) so when N150 = F150 I am given the cell value 12 columns to the left which should be B150. Instead I am getting the value of B145 which is correct in that it's the right column but obviously the incorrect row. My target range is N145:N160 so I think it's only referecing the first row in my range. Any help would be greatly appreciated been trying to figure this out for days!
Dim target As Range
Dim cll As Range
Private Sub Worksheet_Calculate()
Set target = Range("N145:N160")
For Each cll In target
If (Range("N150") = Range("F150"))
Call Mail_small_Text_Outlook(target)
Exit For
End If
Next
End Sub
Sub Mail_small_Text_Outlook()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Hi there" & vbNewLine & vbNewLine & _
cll.Offset(0, -12) & " has reached its target"
On Error Resume Next
With xOutMail
.To = "email"
.CC = ""
.BCC = ""
.Subject = "Target Reached"
.Body = xMailBody
.Send 'or use .Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
You are looping from N145:N160 but only checking if Range("N150") = Range("F150"). If that check is true it will be true on the first iteration when cll is N145 so the email is sent and the loop exits so no other cll is processed.
...
Set target = Range("N145:N160")
For Each cll In target
If cll = cll.offset(0, -12) then
'cll is public, no need to pass it or target across
Mail_small_Text_Outlook
Exit For
End If
Next
...
Instead of using a global variable, pass the value you want in the email as a parameter for your Mail_small_Text_Outlook function.
Dim target As Range
Private Sub Worksheet_Calculate()
Dim FoundCell as String
Set target = Range("N145:N160")
For Each cll In target
If (Range("N150") = Range("F150"))
FoundCell = Cstr(cll.Offset(0, -12).Value2)
Call Mail_small_Text_Outlook(FoundCell)
Exit For
End If
Next
End Sub
Sub Mail_small_Text_Outlook(FoundCell as String)
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Hi there" & vbNewLine & vbNewLine & _
FoundCell & " has reached its target"
On Error Resume Next
With xOutMail
.To = "email"
.CC = ""
.BCC = ""
.Subject = "Target Reached"
.Body = xMailBody
.Send 'or use .Display
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
Now you can watch the value of FoundCell prior to passing it into the function, making your debugging process far easier.
I have looked through multiple posts to send an email if a value in a range of cells changes and adapted the code I found in those posts to suit my needs, but for some reason the email is not being sent when the value in any cell of the range defined changes, and I am a little lost at why. Any guidance is greatly appreciated. Please see code below (please note that for confidentiality purposes the emails and names are fake).
Private Sub Workbook_Change(ByVal Target As Range)
' Uses early binding
' Requires a reference to the Outlook Object Library
Dim RgSel As Range, RgCell As Range
Dim OutlookApp As Object, MItem As Object
Dim Subj As String, EmailAddr As String, Recipient As String
Dim CustName As String, Msg As String
Dim pEmail As String
On Error GoTo NX
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set RgCell = Range("C2:C100")
Set RgSel = Intersect(Target, RgCell)
If Not RgSel Is Nothing Then
Set OutlookApp = CreateObject("Outlook.Application")
Set MItem = OutlookApp.CreateItem(0)
For Each cell In RgCell
If cell.Value = "Bob" Then 'Fake Name for posting question
pEmail = "BobT#SomethingBlahBlahBlah.com" 'Fake email address used for posting question
CustName = cell.Offset(0, -1).Value
Subj = "***NEW ITEM ASSIGNED***" & " - " & UCase(CustName)
Recipient = "Bob T. Builder" 'Fake name for posting question
EmailAddr = pEmail
' Compose Message
Msg = "Dear, " & Recipient & vbCrLf & vbCrLf
Msg = Msg & "I have assigned " & CustName & "'s" & " item to you." & vbCrLf
Msg = Msg & "Please review the information in their customer folder in the L: Drive." & vbCrLf & vbCrLf
Msg = Msg & "Sincerely," & vbCrLf & vbCrLf & vbCrLf
Msg = Msg & "Bob's Boss" & vbCrLf 'Fake name for posting question
Msg = Msg & "Vice President"
' Create Mail Item and send
With MItem
.to = EmailAddr
.Subject = Subj
.body = Msg
.Save 'This will change to .send after testing is complete
End With
Set RgSel = Nothing
Set OutlookApp = Nothing
Set MItem = Nothing
End If
Next cell
Application.DisplayAlerts = True
Application.ScreenUpdating = True
NX:
Resume Next
End Sub
I think you've intended to use the Worksheet_Change event but have Private Sub Workbook_Change... instead.
Additional issues:
For Each cell In RgCell should probably be For Each cell in RgSel, or For Each cell in Target - otherwise the code runs through each cell in C2:C100, and not just the cell(s) changed, or Target.
There is no need to Set RgSel = Nothing
With Set MItem = OutlookApp.CreateItem(0), you create an email message before you've checked If cell.Value = "Bob". Move this line within the If statement.
Set OutlookApp = Nothing should be outside the For Each loop, i.e. it should be done after you've finished looping.
On Error GoTo NX, and then NX: Resume Next, is equivalent to On Error Resume Next, which doesn't handle any errors, but rather ignores them.
You may be missing a closing End If, or it is not included in this snippet.
Im making a new excel template where the managers can add info so that we can make a quote based on their template. The meaning is that if they are clicking on the submit button that depending on the value segment gos to the correct excel file (follow up list) and that the customer name, customer id and general info put in the follow up list.
This is de code that i have until now, only thing is the submit button that i need to have.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Intersect(Target, Range("B7")) Is Nothing Then
If Range("B7") <> "Server & Storage" And Range("B7") <> "Power" And Range("B7") <> "Networking" And Range("B7") <> "Software" And Range("B7") <> "Printing" Then
MsgBox "Selecteer een value segment!"
End If
Else
Exit Sub
End If
End Sub
'E-mail knop
Private Sub CommandButton1_Click()
Dim xOutApp As Object
Dim xOutMail As Object
Dim xMailBody As String
Dim srtEmail As String
On Error Resume Next
Set xOutApp = CreateObject("Outlook.Application")
Set xOutMail = xOutApp.CreateItem(0)
xMailBody = "Hi Team," & vbNewLine & vbNewLine & _
"Dit is een nieuwe request voor " & Range("B8")
If Range("B7") = "Server & Storage" Then
srtEmail = "hardware#bechtle.be"
Else
If Range("B7") = "Power" Then
srtEmail = "hardware#bechtle.be"
Else
If Range("B7") = "Networking" Then
srtEmail = "networking#bechtle.be"
Else
If Range("B7") = "Software" Then
srtEmail = "software#bechtle.be"
Else
If Range("B7") = "Printing" Then
srtEmail = "kristof.neubauer#bechtle.com"
Else
MsgBox "Geen value segment geselecteerd!"
End If
End If
End If
End If
End If
On Error Resume Next
With xOutMail
.To = srtEmail
.CC = "berty.vaneijgen#bechtle.com"
.BCC = ""
.Subject = "Value Request voor " & Range("B9") & Range("B8")
.Body = xMailBody
If Range("B7") <> "" Then
.Display 'or use .Send
End If
End With
On Error GoTo 0
Set xOutMail = Nothing
Set xOutApp = Nothing
End Sub
'Reset knop
Private Sub CommandButton2_Click()
Sheets("VRT").Range("B7:B33") = ""
MsgBox "Velden zijn gewist!"
End Sub
'Save as knop
Private Sub CommandButton3_Click()
Dim nom As String
nom = Day(Date) & "-" & Month(Date) & "-" & Year(Date) & " " & Range("B8")
ActiveWorkbook.SaveCopyAs ActiveWorkbook.Path & "\" & nom & ".xlsm"
rep = MsgBox("Je bestand is opgeslagen! ", vbYes + vbInformation, "Copy of spreadsheet")
'MsgBox(You database has been saved : " & Name, vbYes + vbInformation, "Copy of spreadsheet")
End Sub
'print
Private Sub Workbook_BeforePrint(Cancel As Boolean)
Cancel = (ActiveSheet.Name = "VRT")
If Cancel = True Then MsgBox "Gebruik de print knop."
End Sub
'print knop
Private Sub CommandButton4_Click()
On Error Resume Next
Application.EnableEvents = False
With ActiveWorkbook.Sheets("VRT")
.Range("A1:F33").PrintOut
End With
Application.EnableEvents = True
On Error GoTo 0
End Sub
Private Sub CommandButton5_Click()
End Sub
You can open the developer tab and create a button. How to show developer tab on the ribbon MSDN.
Create an ActiveX button, by clicking the Developer Tab > Insert > Command Button:
Then make sure that the name of the button is CommandButton1, to be compatible with your code. This is where to rename the name of the button:
Since you mentioned that you have the code, and only need to add the button, these steps may be what you need to follow.
-Add a button from the 'Developer' tab using the Insert group
-Right-click on the button to 'Assign macro..'. You will see a list of subs
present in the workbook to select from.
-For the code use something like this
Dim src, dst as Workbook
dst= ThisWorkbook 'Destination is your current workbook
'Define the src inside your IF-ELSE tree based on 'B7' cell value
'Use the statement below for each cell value with address in the 'Range' quotes
dst.Range("").Value= src.Range("").Value
Here's the code:
currently I have a spreadsheet that will send emails if a value in the table goes above 200, I want to make it so that it will send a reminder email saying "You have a program due NEXT Wednesday" 9 days before, and one saying "You have a program due THIS Wednesday" 2 days before. Any help is appreciated!
Option Explicit
Private Sub Worksheet_Calculate()
Dim FormulaRange As Range
Dim NotSentMsg As String
Dim MyMsg As String
Dim SentMsg As String
Dim MyLimit As Double
NotSentMsg = "Not Sent"
SentMsg = "Sent"
'Above the MyLimit value it will run the macro
MyLimit = 200
'Set the range with Formulas that you want to check
Set FormulaRange = Me.Range("B3:B7")
On Error GoTo EndMacro:
For Each FormulaCell In FormulaRange.Cells
With FormulaCell
If IsNumeric(.Value) = False Then
MyMsg = "Not numeric"
Else
If .Value > MyLimit Then
MyMsg = SentMsg
If .Offset(0, 1).Value = NotSentMsg Then
Call Mail_with_outlook2
End If
Else
MyMsg = NotSentMsg
End If
End If
Application.EnableEvents = False
.Offset(0, 1).Value = MyMsg
Application.EnableEvents = True
End With
Next FormulaCell
ExitMacro:
Exit Sub
EndMacro:
Application.EnableEvents = True
MsgBox "Some Error occurred." _
& vbLf & Err.Number _
& vbLf & Err.Description
End Sub
I am trying to enter the value of cell C4, which is gotten from an input box which assigns the value to the cell, into the search box after submitting at the first page but I am not able to as I keep getting an error 438. Is there something wrong with my codes after the input box?
And is there a way that I can have the codes wait until cell C4 is assigned with the value in the input box then continue with filling in the 2nd page?
Also, I am using Internet Explorer 11, what should my objItem.FullName Like be if I want to use the opened browser to work on?
Option Explicit
Const word1 As String = "C2"
Const word2 As String = "C3"
Const word3 As String = "C4"
Public Sub Test()
Dim objWindow As Object
Dim objIEApp As Object
Dim objShell As Object
Dim objItem As Object
Dim wordthree As String
On Error GoTo Fin
Set objShell = CreateObject("Shell.Application")
Set objWindow = objShell.Windows()
For Each objItem In objWindow
If LCase(objItem.FullName Like "*iexplore*") Then
Set objIEApp = objItem
End If
Next objItem
If objIEApp Is Nothing Then
Set objIEApp = CreateObject("InternetExplorer.Application")
objIEApp.Visible = True
End If
With objIEApp
.Visible = True
.Navigate "google.com"
While Not .ReadyState = 4
DoEvents
Wend
.Document.all.q.Value = Range(word1).Value
'.Document.all.q.Value = Range(word2).Value
.Document.forms(0).submit
End With
3word = InputBox("Enter 3rd word: ")
Range("C4").Value = wordthree
With objIEApp
.Visible = True
While Not .ReadyState = 4
DoEvents
Wend
.Document.all.q.Value = Range(word3).Value
.Document.forms(0).submit
End With
Fin:
If Err.Number <> 0 Then MsgBox "Error: " & _
Err.Number & " " & Err.Description
Set objWindow = Nothing
Set objShell = Nothing
End Sub
The first thing I can spot here is that you're attempting to name your variables starting with a number. In the VB world (VBA, VB.Net etc. all included), this is not valid & your code won't work.
Please see https://msdn.microsoft.com/en-us/library/office/gg264773.aspx for more info on variable naming rules.
Update:
The next thing & reason you're getting the error, is that you need to include a call to exit the method before the error handling routine code is called. Your code above now worked correctly for me with this "exit sub" statement added.
.Document.all.q.Value = Range(word3).Value
.Document.forms(0).submit
End With
**Exit Sub**
Fin:
If Err.Number <> 0 Then MsgBox "Error: " & _