I have developed a Word document containing a macro that can transfer all Content Control Values to any other open Word document. I would like to expand on this so it can look through any emails that are open for editing. Is this even possible? My current code relies on SelectContentControlsByTag, but I think this is exclusive to the Word API.
Private Sub DumpData_Click()
Dim updated As Boolean
Dim doc_updated As Integer
Dim msg As String
'Dim content_controls_collection As Collection
msg = ""
Set source_doc = Application.ActiveDocument
'For each open document that is not the active document (the active document is the source file containing the macro button and this script)
For Each destination_doc In Documents
If destination_doc <> source_doc Then
updated = False
'Look at each content control in the destination doc
For Each content_control In destination_doc.ContentControls
'Set content_controls_collection = Nothing
CC_tag = content_control.Tag
'If the tags are not empty
If CC_tag <> "" Then
' msg = msg & vbNewLine & "Found tag " & CC_tag & " in " & destination_doc.Name
'find the corresponding content control, if it exists, in the source document
If source_doc.SelectContentControlsByTag(CC_tag).Count > 0 Then
'If the content control is the basic text type
If content_control.Type = wdContentControlText Or _
content_control.Type = wdContentControlDate Or _
content_control.Type = wdContentControlRichText Then
content_control.Range.Text = source_doc.SelectContentControlsByTag(CC_tag).Item(1).Range.Text
updated = True
' msg = msg & vbNewLine & "Content Control was updated!"
Else
msg = msg & vbNewLine & CC_tag & " tag is a less common type of content control which I have not bothered to progam to transfer. It's type is " & content_control.Type
End If
' Else
' msg = msg & vbNewLine & CC_tag & " tag not found in Project Form Data Source."
End If
End If
Next content_control
If updated = True Then
msg = msg & vbNewLine & " - " & destination_doc.Path & Application.PathSeparator & destination_doc.Name
doc_updated = doc_updated + 1
End If
End If
Next destination_doc
If doc_updated > 0 Then
msg = "Macro complete. The following open documents were found to contain matching Content Controls which are now updated:" & msg
Else
msg = "No open files were found to contain matching Content Control Tags."
End If
MsgBox msg
End Sub
Related
I have a code that returns various properties for mail items. I'm trying to add the "task status" to my report.
I get a run-time error '438' "Object doesn't support this property or method". I'm trying to extract whether the little flag in Outlook is completed (aka checked).
Here is what I have so far:
For Each currentTask In currentItem.Tasks
Debug.Print currentTask.Status
Report = Report & currentTask.Status
Next
It is part of this larger sub:
Private Sub GetAllEmailsInFolder(CurrentFolder As Outlook.Folder, Report As String)
Dim currentItem
Dim attachment As attachment
Dim currentMail As MailItem
Dim currenTask As TaskItem
Report = Report & "Folder Name: " & CurrentFolder.Name & " (Store: " & CurrentFolder.Store.DisplayName & ")" & " (Date of report: " _
& Date & ")" & vbCrLf & "Subject Name|Categories|Attachment Count|Task Status|Attachment Name(s)" & vbCrLf
For Each currentItem In CurrentFolder.Items
Report = Report & currentItem.Subject & "|"
Report = Report & currentItem.Categories & "|"
Report = Report & currentItem.Attachments.Count & "|"
'need help here
For Each currentTask In currentItem.Tasks
Debug.Print currentTask.Status
Report = Report & currentTask.Status
Next
'
For Each attachment In currentItem.Attachments
Debug.Print attachment.FileName
Report = Report & attachment.FileName & ","
Next
Report = Report & vbCrLf
Next
End Sub
A mailitem has a .FlagStatus property.
Option Explicit ' Consider this mandatory
' Tools | Options | Editor tab
' Require Variable Declaration
' If desperate declare as Variant
Private Sub GetAllEmailsInFolder(CurrentFolder As outlook.Folder, Report As String)
' Code for flags not reliable in IMAP accounts
Dim currentItem As Object
Dim attachment As attachment
Dim currentMail As MailItem
'Dim currenTask As TaskItem ' <--- missing Option Explicit?
Dim currentTask As TaskItem
Dim currentFolderItems As Items
Report = Report & "Folder Name: " & CurrentFolder.Name & " (Store: " & CurrentFolder.Store.DisplayName & ")" & " (Date of report: " _
& Date & ")" & vbCrLf & "Subject Name|Categories|Attachment Count|Task Status|Attachment Name(s)" & vbCrLf
Set currentFolderItems = CurrentFolder.Items
For Each currentItem In currentFolderItems
If currentItem.Class = olMail Then
Set currentMail = currentItem
With currentMail
Debug.Print .Subject
Report = Report & .Subject & "|"
Report = Report & .categories & "|"
Report = Report & .Attachments.Count & "|"
' No longer in current documentation
' https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2010/bb644164(v=office.14)
' Still could be good for decades
' 0 - olNoFlag
' 1 - olFlagComplete
' 2 - olFlagMarked
Debug.Print ".FlagStatus.: " & .FlagStatus
'https://learn.microsoft.com/en-us/office/vba/api/outlook.mailitem.flagrequest
Debug.Print ".FlagRequest: " & .FlagRequest
Report = Report & .FlagStatus
For Each attachment In .Attachments
Debug.Print attachment.Filename
Report = Report & attachment.Filename & ","
Next
End With
Report = Report & vbCrLf
Debug.Print Report
ElseIf currentItem.Class = olTask Then
Set currentTask = currentItem
With currentTask
Report = Report & .Subject & "|"
Report = Report & .categories & "|"
Report = Report & .Attachments.Count & "|"
Debug.Print ".Status.....: " & .Status
Report = Report & .Status
For Each attachment In .Attachments
Debug.Print attachment.Filename
Report = Report & attachment.Filename & ","
Next
End With
Report = Report & vbCrLf
Debug.Print Report
Else
Debug.Print "neither a mailitem nor a taskitem"
End If
Set currentItem = Nothing
Set currentTask = Nothing
Set currentMail = Nothing
Next
End Sub
Private Sub test()
Dim currFolder As Folder
Dim reportStr As String
Set currFolder = ActiveExplorer.CurrentFolder
reportStr = "FlagStaus on mailitems: "
GetAllEmailsInFolder currFolder, reportStr
End Sub
Use MailItem.FlagDueBy / FlagIcon / FlagRequest / FlagStatus / IsMarkedAsTask / TaskCompletedDate / TaskDueDate / TaskStartDate / TaskSubject / ToDoTaskOrdinal properties.
In absence of a better solution, you can use the PropertyAccessor for this purpose.
I cannot provide you with a code snippet right now, but you have ilustrative examples on the reference page [1].
The property tag that you are looking for is 0x8025, with DASL http://schemas.microsoft.com/mapi/id/{00062003-0000-0000-C000-000000000046}/81010003.
You can use OutlookSpy to determine property tags of actual properties (thanks to [2] for this tip).
[1] https://learn.microsoft.com/en-us/office/vba/api/outlook.propertyaccessor
[2] How can I get task-specific properties from a MailItem
Edit 1
Private Function GetStatus(objItem As Object) As OlTaskStatus
Dim oPA As Outlook.PropertyAccessor
' MAPI-level access required to get the "status" property of a Mail Item object.
Set oPA = objItem.PropertyAccessor
GetStatus = oPA.GetProperty("http://schemas.microsoft.com/mapi/id/{00062003-0000-0000-C000-000000000046}/81010003")
Set oPA = Nothing
End Function
For some reason, I can't get the selected item which would be an email from my inbox to attach as an attachment when I create a new mail from my macro. I'm using Windows 10 / Outlook 2016. I had this working in Windows 7 Office 2010, but I'm not sure why it's not working now. Any help would be greatly appreciated.
Sub SendEmail()
Dim Inbox As Object
Dim MyItem As Object
Dim AddEmail As Boolean
Dim i As Long
Dim iAnswer As VbMsgBoxResult
'Check if User wants to copy an existing email to new form
iAnswer = MsgBox(Prompt:=" Do you want to copy the selected email to new form? (If you select YES, Keep the current email selected - DO NOT SELECT ANOTHER EMAIL - Until you finish sending)", _
Buttons:=vbYesNo, Title:="Copy Selected Email")
If iAnswer = vbYes Then
AddEmail = True
End If
'Check Version of Outlook (2007 vs 2010)
If Outlook.Application.Version = "12.0.0.6680" Then
On Error GoTo FolderError:
Set Inbox = Outlook.Application.GetNamespace("MAPI").Folders("Mailbox - #Incoming_Workshare")
On Error Resume Next
Else
On Error GoTo FolderError:
Set Inbox = Outlook.Application.GetNamespace("MAPI").Folders("#Incoming_Workshare")
On Error Resume Next
End If
'Open Form From Folder (The Inbox =)
Set MyItem = Inbox.Items.Add("IPM.Note.Workflow Sharing 2016")
MyItem.Display
MyItem.Subject = "Automatically Generated Based on Job Information"
'Check Version of VBA and Form to make sure you are using latest macro
If Not MyItem.Mileage = 11 Then
'Check if User wants to copy an existing email to new form
iAnswer = MsgBox(Prompt:="ALERT - Macro has been updated - Select Yes to Update" & vbCrLf & "(Note: Outlook will be restarted)", _
Buttons:=vbYesNo, Title:="Automatic Macro Update")
If iAnswer = vbYes Then
Shell "wscript C:\Macro\UpdateOutlookMacro.vbs", vbNormalFocus
End If
End If
'Copy Selected Emails to New Email if you selected Yes
If AddEmail = True Then
'Check if a there is a reference to the long access time projects in the subject or body to add instructions to also send as attachment (LARGE PROJECTS)
If InStr(1, UCase(ActiveExplorer().Selection.Item(1).Subject), "TUCAN") > 0 Or _
InStr(1, UCase(ActiveExplorer().Selection.Item(1).Subject), "RUDY") > 0 Or _
InStr(1, UCase(ActiveExplorer().Selection.Item(1).Subject), "SARGENT") > 0 Then
MyItem.HTMLBody = "<b>Additional Instructions from Originating Location:</b>" & Chr(11) & "PLEASE SEND BACK HYPERLINKS AND ATTACHMENTS FOR ALL EDITED FILES" & Chr(11) & Chr(11) & Chr(11) & Chr(11) & "---------------------------------------------" & Chr(11) & "Original Banker Email:" & Chr(11)
Else
MyItem.HTMLBody = "<b>Additional Instructions from Originating Location:</b>" & Chr(11) & Chr(11) & Chr(11) & Chr(11) & Chr(11) & "---------------------------------------------" & Chr(11) & "Original Banker Email:" & Chr(11)
End If
MyItem.BodyFormat = olFormatRichText
'Check large job 15MB
If (ActiveExplorer().Selection.Item(1).Size >= 15728640) Then
MsgBox "Alert! The attached original email size is " & Format(ActiveExplorer().Selection.Item(1).Size / 1048576, 0#) & " MBs. There are errors when sending large emails. Please save attachments as links to reduce the filesize.", , Title:="Email Size Too Big"
End If
MyItem.Attachments.Add ActiveExplorer().Selection.Item(1)
'Check if Sender is an autoforward from a mailbox, alerting to be manually updated
MyItem.UserProperties("Clocker") = ActiveExplorer().Selection.Item(1).SenderName + "; " + ActiveExplorer().Selection.Item(1).CC
If MyItem.UserProperties("Clocker") = "OH Mail; " Or MyItem.UserProperties("Clocker") = "NO Mail; " Or MyItem.UserProperties("Clocker") = "LAV Mail; " Or MyItem.UserProperties("Clocker") = "OK Mail; " Or MyItem.UserProperties("Clocker") = "WY Mail; " Then
'MsgBox "Alert! Please populate the Requestor/Clocker field. It cannot be listed as the Advisory Presentation Mailbox"
'MyItem.UserProperties("Clocker") = "" ' Removed Q4
Dim CorrectedClocker1, CorrectedClocker2, CorrectedClocker3 As String
Correctedclocker1 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "From:", "Sent:"))
If InStr(ActiveExplorer().Selection.Item(1).body, "Cc:") > 0 Then
CorrectedClocker2 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "To:", "Cc:"))
CorrectedClocker3 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "Cc:", "Subject:"))
Else
CorrectedClocker2 = Trim(SuperMid(ActiveExplorer().Selection.Item(1).body, "To:", "Subject:"))
CorrectedClocker3 = ""
End If
CorrectedClocker2 = Replace(CorrectedClocker2, "#Completed", "")
CorrectedClocker3 = Replace(CorrectedClocker3, "#Completed", "")
MyItem.UserProperties("Clocker") = CorrectedClocker1 & "; " & CorrectedClocker2 & "; " & CorrectedClocker3
Else
If InStr(MyItem.UserProperties("Clocker"), "[Cvcs]") > 0 Then
Is this running inside Outlook VBA?. Should Attachments.Add line be the following?
MyItem.Attachments.Add Outlook.Application.ActiveExplorer.Selection.Item(1)
Get rid of the "On Error Resume Next" statements - they are hiding runtime errors.
If you want to add a mailbox item as an attachment to a new message.
You need to set the Outlook.OlAttachmentType property to olEmbeddeditem.
You can add a mail item as an attachment by referring to the code below.
Sub ResolveName()
Dim myItem As Object
Dim Item As Object
Dim myFolder As Folder
Set myNamespace = Application.GetNamespace("MAPI")
Set myFolder = myNamespace.GetDefaultFolder(olFolderInbox)
Set myItem = Application.CreateItem(olMailItem)
Set Item = myFolder.Items(2)
'Item.Display
myItem.Attachments.Add Item, Outlook.OlAttachmentType.olEmbeddeditem, 1, "first"
myItem.Display
End Sub
I am having trouble accessing the network folder from which I would like to copy certain files. I have put together the following code, which for now only prints out the specific files created today.
The issue I'm having is accessing the network folder, with the regular file path it works perfectly, but when I swap it for the network mapped folder it crashes.
Sub NetworkFiles()
Dim n As String, msg As String, d As Date
msg = ""
Set FSO = CreateObject("Scripting.FileSystemObject")
Set fils = FSO.GetFolder("\\corp-server\HostingFolder").Files '("C:\FILES") works perfectly
For Each fil In fils
n = fil.name
n = Left(n, 24)
d = fil.DateLastModified 'DateCreated
If n = "FILE_CHARACTERS_ARE_RANDOM_AFTER_THIS_POINT" Then
If d >= Date Then
msg = msg & n & vbTab & d & vbCrLf
End If
End If
Next fil
If msg = "" Then
MsgBox "No new files"
Else
MsgBox msg
End If
Set FSO = Nothing
End Sub
SOLVED - loops extremely quickly through an entire folder with 5k+ files
ANSWER
Sub LoopThroughFiles()
Dim file As Variant
Dim fso As Object
Source = "\\networkpath\test"
file = Dir(Source)
destloc = "C:\test\folder"
msg = ""
While (file <> "")
If InStr(file, "TEST_partOfTheFileString" & Format(Date, "YYYYMMDD")) > 0 Then
FileCopy Source & file, destloc & file
msg = msg & file & vbCrLf
End If
file = Dir
Wend
MsgBox msg & "Files Copied"
End Sub
I am new to Macro
By googling I coded this and I have changed some part for my use.
Problem is Runtime error is coming. And I don't know how to print all word documents in folder both .doc and .docx
My Requirement
Want to print all word document in folder A (both .doc and .docx).
Print active document ( Number of copies want to be get from User ).
Close active document.
Repeat 2 and 3 for all document in folder A
My code will get page number to print from case selected by the user
case 1 will print 1st two pages one by one.
case 2 will print 3rd to reset of the pages.
case 3 will print full document.
In my office duplex is default printer setup to print. But I will be using letter head. I need this macro to solve my issue. I tried simplex macro code to print but its not working.
Sub prnt()
Dim c As Integer
Dim i As Integer
Dim strName As String
'get print type
strName = InputBox(Prompt:="Choose Your Option" & vbNewLine & "" & vbNewLine & "1. Letter Head" & vbNewLine & "2. A4 Sheet" & vbNewLine & "3. Comp Plan" & vbNewLine & "", _
Title:="ENTER YOUR PRINT TYPE", Default:="Your Choice here")
If strName = "Your Choice here" Or strName = vbNullString Then
MsgBox "Sorry...! Choose Correct option"
Exit Sub
Else
'case to choose option
Select Case strName
Case "1"
Dim file
Dim path As String
Dim ans As String
'get number of copies from user
c = InputBox("Please enter number of copies")
ans = MsgBox("Are you sure you want to print " & _
c & "?", _
vbQuestion + vbYesNo, "Print pages")
If ans = vbNo Then
Exit Sub
Else
'path to the folder
path = "E:\print\"
file = Dir(path & "*.docx")
Do While file ""
Documents.Open Filename:=path & file
For i = 1 To 2 'loop 2 pages
ActiveDocument.PrintOut , Copies:=c, Range:=wdPrintRangeOfPages, Pages:=i
Next
ActiveDocument.Close
' set file to next in Dir
file = Dir()
Loop
End If
Case "2"
Case "3"
Case Else
MsgBox "Sorry...! Choose Correct option"
End Select
End If
End Sub
There's bad programming practice to work on strings instead of numbers.
See this:
Sub Test()
Dim noofcopies As Integer
noofcopies = GetNumberOfCopies()
MsgBox noofcopies
End Sub
Function GetNumberOfCopies() As Integer
Dim iRetVal As Integer
On Error GoTo Err_GetNumberOfCopies
iRetVal = CInt(InputBox("Enter no. of copies to print" & vbCr & vbCr & _
"Enter proper integer value between 1 and 3" & vbCr & _
"0 (zero) equals to Cancel", "No. of copies", "1"))
If iRetVal > 3 Then iRetVal = 3
Exit_GetNumberOfCopies:
GetNumberOfCopies = iRetVal
Exit Function
Err_GetNumberOfCopies:
Err.Clear
Resume 0
End Function
Use the same logic to get print option ;)
I have the following code, this code was written in VB6 but i can not open the form or check any references.
Private Sub PopulatePrinterCombo(cmbDestination As ComboBox)
Dim objPrinter As Printer 'a printer in the Printers collection object
'Add the printers to the combo box
For Each objPrinter In printers
cmbPrinter.AddItem objPrinter.DeviceName
Next
'Set current selection to the default printer
cmbDestination.Text = Printer.DeviceName
End Sub
I am currently copying the code onto Excel VBA macro, the problem is the Dim objPrinter As Printer code, i keep getting an error message saying "USER DEFINED TYPE NOT DEFINED", do i need a reference to add on VBA to be able to get the option of declaring a variable as a "Printer" or something?
My second question is that i do not fully understand the "Printers" in the line For Each objPrinter In printers, what is "Printers"? can someone please explain that to me.
Thank you
PART 2
I am now trying to print files, i have the following as my code:
'Initialize values
intDraftsPrinted = 0
If objDraftPaths.Count > 1 Then
Else
intSelectedDraftCount = CountSelectedDrafts
End If
'prompt user to make sure
intMsgBoxResponse = MsgBox("You selected " & intSelectedDraftCount & " part numbers. After removing duplicates" & vbNewLine & "there were " & objDraftPaths.Count & " unique draft files found." & vbNewLine & "Do you want to print these files?", vbYesNo, "TD Printer")
If intMsgBoxResponse <> vbYes Then
intSelectedDraftCount = 0 'So the following for loop will not entered
Else
intSelectedDraftCount = objDraftPaths.Count
End If
For i = 1 To intSelectedDraftCount
booSuccess = False
'open the draft file
Set objDraftDocument = OpenSolidEdgeDraft(objDraftPaths.Item(i))
If objDraftDocument Is Nothing Then
'could not open file
MsgBox "Could not open the following draft file:" & vbNewLine & _
objDraftPaths.Item(i), vbExclamation, "Solid Edge Error"
Else
'Print the draft file
For Each objSheet In objDraftDocument.Sheets
strSheetSize = DetermineSheetSize(objSheet)
If strSheetSize <> "" Then
'Determine orientation
If InStr(1, strSheetSize, "90") <> 0 Then
'Print as landscape
intOrientation = vbPRORLandscape
Else
'Print as portrait
intOrientation = vbPRORPortrait
End If
'Specify Sheet Size
Select Case Left(strSheetSize, 1)
Case "A"
intPaperSize = VBRUN.PrinterObjectConstants.vbPRPSLetter
Case "B"
intPaperSize = VBRUN.PrinterObjectConstants.vbPRPS11x17
Case "C"
intPaperSize = VBRUN.PrinterObjectConstants.vbPRPSCSheet
Case "D"
intPaperSize = VBRUN.PrinterObjectConstants.vbPRPSDSheet
Case "E"
intPaperSize = VBRUN.PrinterObjectConstants.vbPRPSESheet
Case Else
intPaperSize = VBRUN.PrinterObjectConstants.vbPRPSLetter
End Select
'Enable error handling
On Error Resume Next
'Activate the current sheet
objSheet.Activate
If Err Then
'Could not activate sheet
MsgBox "An error occurred while attempting to print: " & vbNewLine & objDraftPaths.Item(i) & vbNewLine & "The error was:" & vbNewLine & "Error Number: " & Err.Number & vbNewLine & "Error Description: " & Err.Description, vbExclamation, "Solid Edge Error"
Err.Clear
Else
'Print to the printer specified by the combo box
objDraftDocument.PrintOut cmbPrinter.Text, 1, intOrientation, intPaperSize, , , , igPrintSelected
If Err Then
'Could not print document
MsgBox "An error occurred while attempting to print: " & vbNewLine & objDraftPaths.Item(i) & vbNewLine & "The error was:" & vbNewLine & "Error Number: " & Err.Number & vbNewLine & "Error Description: " & Err.Description, vbExclamation, "Solid Edge Error"
Err.Clear
Else
booSuccess = True
End If
End If
'Disable error handling
On Error GoTo 0
End If
Next
'Close the file
objDraftDocument.Close False
intDraftsPrinted = intDraftsPrinted + 1
End If
Next i
'Dereference objects
Set objSheet = Nothing
Set objDraftDocument = Nothing
'Set objDraftPaths = Nothing
PrintSelectedDrafts = intDraftsPrinted
Now the problem comes when i hits the line that says: intOrientation = vbPRORLandscape
in excel VBA, it does not recognize "vbPRORLandscape" as well as the next line "vbPRORPortrait". Is there a way to fix that?
Also, i have a feeling that VBRUN.PrinterObjectConstants.vbPRPSLetter and the rest of those lines might not work out as well. It works in VB6 though.
Thank you
It appears the Printers Collection is available in the MS Access VBA environment but I do not believe it is intrinsic to the Excel VBA environment.
I use the WshNetwork object of Windows Script Host to list the available printers. I use the subroutine below to populate a ComboBox with the list of printers that are connected to the system. In order for this code to work you will need to add the "Windows Script Host Object Model" reference to your VBA project. (Menu: Tools > References [Select from list])
I added the (j) loop to alphabetize the list.
Sub populatePrintersList()
Dim nwo As New WshNetwork
Dim i As Integer
Dim j As Integer
Dim bAdd As Boolean
bAdd = True
cmbPrinter.Clear
For i = 0 To (nwo.EnumPrinterConnections.Count / 2) - 1
For j = 0 To cmbPrinter.ListCount - 1
If nwo.EnumPrinterConnections(i * 2 + 1) < cmbPrinter.List(j) Then
cmbPrinter.AddItem nwo.EnumPrinterConnections(i * 2 + 1), j
bAdd = False
Exit For
End If
Next j
If bAdd Then cmbPrinter.AddItem nwo.EnumPrinterConnections(i * 2 + 1): bAdd = True
Next i
cmbPrinter.ListIndex = 0
End Sub
Part 2:
MSDN contains reference material for the Worksheet.PrintOut method: Worksheet.PrintOut
In depth documentation for the methods and properties of the Worksheet.PageSetup object can also be found on MSDN: Worksheet.PageSetup
I suggest using these resources to find a plethora of answers.