3

Was trying to write two macros to print attachments automatically upon receipt of new emails and only print the first page of the email. code looks like below:

Private Declare Function ShellExecute Lib "shell32.dll" Alias _
  "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
  ByVal lpFile As String, ByVal lpParameters As String, _
  ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long

Private WithEvents Items As Outlook.Items

Private Sub Application_Startup()
  Dim Ns As Outlook.NameSpace
  Dim Folder As Outlook.MAPIFolder

  Set Ns = Application.GetNamespace("MAPI")
  Set Folder = Ns.GetDefaultFolder(olFolderInbox)
  Set Items = Folder.Items
End Sub

Private Sub Items_ItemAdd(ByVal Item As Object)
  If TypeOf Item Is Outlook.MailItem Then
    Printattachments Item
  End If
End Sub

Private Sub Printattachments(oMail As Outlook.MailItem)
  On Error Resume Next
  Dim colAtts As Outlook.Attachments
  Dim oAtt As Outlook.Attachment
  Dim sFile As String
  Dim sDirectory As String
  Dim sFileType As String

  sDirectory = "D:\Attachments\"

  Set colAtts = oMail.Attachments

  If colAtts.Count Then
    For Each oAtt In colAtts

' This code looks at the last 4 characters in a filename
      sFileType = LCase$(Right$(oAtt.FileName, 4))

      Select Case sFileType

' Add additional file types below
      Case "xlsx", "docx", ".pdf", ".doc", ".xls"


        sFile = sDirectory & oAtt.FileName
        oAtt.SaveAsFile sFile
        ShellExecute 0, "print", sFile, vbNullString, vbNullString, 0
      End Select
    Next
  End If
End Sub

Sub PrintOnePage()
    SendKeys "%F", False
    SendKeys "P"
    SendKeys "{TAB 2}", True
    SendKeys "{DOWN}", True
    SendKeys "1"
    SendKeys "{ENTER}"
End Sub

Sub RunAll()
    Call Printattachments
    Call PrintOnePage
End Sub

I then clicked General and Run-all and ran into Compile Error: Argument not optional.

Any input will be much appreciated!

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Ming Lian
  • 65
  • 7
  • `Printattachments` gets `oMail` as an argument. You are supposed to pass it to the Sub when calling it. If you want to run it over incoming emails, it needs to be modified for that. – M-- Apr 03 '17 at 23:35
  • What are you trying to do? run it rather than automatically? – 0m3r Apr 04 '17 at 00:11
  • 1
    Let me know if this works for you. It is important to follow up after asking a question to let everyone use the answer to an already asked question. – M-- Apr 04 '17 at 00:24
  • Hi Masoud thanks for the prompt reply! I'm pretty noob with code. I tried replace Sub RunAll part with the codes you provided below and got another Compile error: Invalid attribute in sub or function – Ming Lian Apr 04 '17 at 00:30
  • I created rule to print any incoming email that has an attachment. the printattachment codes works fine on its own yet meanwhile I want outlook to only print the first page of any incoming email with an attachment. – Ming Lian Apr 04 '17 at 00:45
  • I'm not fan of send key but see my answer and let me know... – 0m3r Apr 04 '17 at 02:04
  • @0m3r so with this method i assume the macro will automatically run upon the restart of the program? – Ming Lian Apr 04 '17 at 15:45
  • Yes and when you receive an email it should print – 0m3r Apr 04 '17 at 17:11
  • @0m3r Would this conflicts with rules in case in the future i want to make an exemption from printing emails with attachments sent from certain people. – Ming Lian Apr 04 '17 at 17:25
  • The rule is always run before item add event. If you only wanna use rule then let me know- what the code is doing is as soon as you receive email it will print first page. – 0m3r Apr 04 '17 at 17:32
  • @0m3r the codes worked and printed only first page of the email body. I had a rule setup so outlook will only print any incoming emails with attachment. Meanwhile I exempt my coworkers' emails from printing. It looks like the rule and macro will work independently. the rule let any incoming emails with attachment print in full body and the macro will repeat the process but only the first page of any email and accompanying attachments. Is there a way to add exemption to the macro code to achieve same result as the rule does? I hope this makes sense as English is not my primary language. – Ming Lian Apr 04 '17 at 17:47
  • @0m3r Can you recommend some good reads on the outlook vba? Thanks! Eager to know more. – Ming Lian Apr 04 '17 at 17:51
  • @0m3r I ran into a new problem. If i stop the rule the macro will not be working on its own but if the rule's enabled every email with attachment will be printed twice. one with every page and one with only the first page. Is there any way to work around this? Kindly assist – Ming Lian Apr 04 '17 at 19:09
  • I think the rule is printing one copy and the macro is printing the second copy-- the macro should work on its own no need for rule- how do you have the rule set up? what is the rule doing? – 0m3r Apr 04 '17 at 19:31
  • @0m3r Not really relevant to the topic but i noticed from time to time i got random 'PR1+Enter' across other windows programs that allow input. As i typed my last comment this happened twice. Assumably this has something to do with the print first page codes? – Ming Lian Apr 04 '17 at 19:41
  • @0m3r the rule is set up as follow: Apply this rule after message arrives which has an attachment print it except if from coworker1@xxx.com; coworker2@xxx.com; .... – Ming Lian Apr 04 '17 at 19:42
  • @0m3r I wanted the rule to print out emails with attachment upon receipt except for my own coworkers emails. However the limitation of Outlook rule made it impossible to print the attachment and define print range. If somehow it's possible to combine the rule's function into the macros it will resolve the problem – Ming Lian Apr 04 '17 at 21:43
  • Give some time I will post new code, one quick question, you only want to print the email body if it has attachment - any other emails received with no attachment to be ignore? and Of course to ignore coworker1@xxx.com; coworker2@xxx.com emails – 0m3r Apr 04 '17 at 22:02
  • Yes, quite exactly! Thanks 0m3r – Ming Lian Apr 04 '17 at 22:13
  • Dear 0m3r, any update with the new code? – Ming Lian Apr 05 '17 at 22:37
  • @0m3r thanks for your continuous help. im ready for some code s – Ming Lian Apr 07 '17 at 02:49
  • Can you post new quick question on how to filter items sendername from Items_ItemAdd Events? and I will answer- Thank you. – 0m3r Apr 07 '17 at 02:58
  • @0m3r posted. http://stackoverflow.com/questions/43268934/how-to-filter-items-sendername-from-items-itemadd-events – Ming Lian Apr 07 '17 at 03:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/140152/discussion-between-0m3r-and-ming-lian). – 0m3r Apr 07 '17 at 08:19

2 Answers2

1

What you need to do is change your PrintOnePage to

Public Sub PrintOnePage(ByVal Item As Object)
    SendKeys "%FPR"
    SendKeys "%S"
    SendKeys "1"
    SendKeys "{ENTER}"
End Sub

And then on your ItemAdd Events simply add

Private Sub Items_ItemAdd(ByVal Item As Object)
  If TypeOf Item Is Outlook.MailItem Then
    Printattachments Item
    PrintOnePage Item '<-------- add
  End If
End Sub

Remember Now as soon as you get an email it will print one page of the email body.


To Print only Items body with attachments then move PrintOnePage Item to

Example

Private Sub Printattachments(ByVal Item As Outlook.MailItem)
    Dim colAtts As Outlook.Attachments
    Dim oAtt As Outlook.Attachment
    Dim sFile As String
    Dim sDirectory As String
    Dim sFileType As String

    sDirectory = "D:\Attachments\"

    Set colAtts = Item.Attachments

    If colAtts.Count Then
        For Each oAtt In colAtts

            ' This code looks at the last 4 characters in a filename
            sFileType = LCase$(Right$(oAtt.FileName, 4))

            Select Case sFileType
                ' Add additional file types below
                Case "xlsx", "docx", ".pdf", ".doc", ".xls"

                sFile = sDirectory & oAtt.FileName
                oAtt.SaveAsFile sFile
                ShellExecute 0, "print", sFile, vbNullString, vbNullString, 0
            End Select
        Next
    End If

    PrintOnePage Item '<-------- add

End Sub

Items.ItemAdd Event Occurs when one or more Items are added to the specified collection. This event does not run when a large number of items are added to the folder at once.


0m3r
  • 12,286
  • 15
  • 35
  • 71
0

In reference to this post I would add your Subs to this code (It goes to the place of Sub RunAll):

Private WithEvents Items As Outlook.Items 
Private Sub Application_Startup() 
  Dim olApp As Outlook.Application 
  Dim objNS As Outlook.NameSpace 
  Set olApp = Outlook.Application 
  Set objNS = olApp.GetNamespace("MAPI") 
  ' default local Inbox
  Set Items = objNS.GetDefaultFolder(olFolderInbox).Items 
End Sub
Private Sub Items_ItemAdd(ByVal item As Object) 

  On Error Goto ErrorHandler 
  Dim Msg As Outlook.MailItem 
  If TypeName(item) = "MailItem" Then
    Set Msg = item 
    ' ******************
    Call Printattachments(Msg)
    Call PrintOnePage
    ' ******************
  End If
ProgramExit: 
  Exit Sub
ErrorHandler: 
  MsgBox Err.Number & " - " & Err.Description 
  Resume ProgramExit 
End Sub

IMPORTANT

Paste all of your code into ThisOutlookSession module.

This will run the macro after receiving any email (Need to restart Outlook).

Community
  • 1
  • 1
M--
  • 25,431
  • 8
  • 61
  • 93
  • I tried replace Sub RunAll part with the codes you provided below and got another Compile error: Invalid attribute in sub or function – Ming Lian Apr 04 '17 at 00:48
  • @MingLian It should go to `ThisOutlookSession` module and should not be run. Once you pasted everything in that module and restarted outlook, send a test email to the address and see if it works (Check if the printed files are in the directory). Also, try some debugging in reference to the post that I have provided, in case. – M-- Apr 04 '17 at 01:18
  • I'll give a try tomorrow morning. Thanks for the follow up. – Ming Lian Apr 04 '17 at 05:07