You are here:Home»KB»Applications»Microsoft Office»Outlook 2016/2019 PayPal Receipt Printing - Only print pages 1 and 2
Tuesday, 13 July 2021 12:45

Outlook 2016/2019 PayPal Receipt Printing - Only print pages 1 and 2

Written by

This all started because I printout my PayPal receipts and because of their formatting can take several sheets of paper. Often the last sheet would just have 1 word on it.

I started by manually just printing the first 2 pages, but this is time consuming so I wrote a macro just to print the first 2 pages of the PayPal receipt to the default printer so I could achieve the same thing but with 1 button click which is what I will show you how to do below.

Then I moved on and configured my printer to print 2 pages on every sheet. So instead of an average of 3 A4 pages every receipt I now just use 1. This has the added advantage that some times a receipt is 1 page and sometimes it is 2 pages so no more paper that what is absolutely needed is used.

I then also created a memo style in Outlook with the margins reduced. (Optional)

This is best solution for printing PayPal Receipts.

See Print 2 full pages on single sheet of paper with HP a printer | QuantumWarp

 

Instructions

To get this to work there are several parts, building the macro (which is done for you), installing the macro and then creating a button in Quick Access Toolbar to run it.

  • To open the VBA manager, when in Outlook press: Alt+F11
  • What is causing NumLock to be toggled?
    • Most likely SendKeys "%{S}" is the culprit.
    • In the Print dialog, Alt+S may be triggering a shortcut or button that has some interaction with NumLock. The % (Alt key) combined with the dialog navigation could also be inadvertently affecting the NumLock state.
    • It’s also possible that the Print dialog itself is doing something to NumLock when it opens or receives focus—which would be outside your code’s control.

Macro with NumLock detection (2026)

A better approach is to detect the original state of NumLock and restore it only if needed.

Here’s the corrected code using Windows API to check NumLock’s actual state:

' Outlook 2016/2019 PayPal Receipt Printing - Only print pages 1 and 2
' With NumLock state preservation

Private Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
Private Const VK_NUMLOCK As Long = 144

Sub PayPal_Receipt_Printing()
    Dim originalNumLockState As Boolean
    
    ' Store the original NumLock state (True = ON, False = OFF)
    originalNumLockState = (GetKeyState(VK_NUMLOCK) And 1) = 1
    
    ' Perform the print operation
    SendKeys "%"
    SendKeys "FPR"
    SendKeys "%{S}"
    SendKeys "1-2"
    SendKeys "{ENTER}"
    DoEvents
    
    ' Restore NumLock to its original state
    Dim currentNumLockState As Boolean
    currentNumLockState = (GetKeyState(VK_NUMLOCK) And 1) = 1
    
    If currentNumLockState <> originalNumLockState Then
        SendKeys "{NUMLOCK}"
    End If
End Sub

How it works:

  1. GetKeyState(VK_NUMLOCK) checks if NumLock is currently ON (returns odd number) or OFF (returns even number)
  2. We store the original state before printing
  3. After printing, we check the current state
  4. If it changed, we press NumLock once to restore it

This is much more robust than blindly toggling twice, because it handles cases where the dialog might have affected NumLock unexpectedly.

Every time I start outlook it is now asking if i want to enable macros

  • I'd recommend Solution 1 (Startup folder) if you want to keep the robust API-based version without security prompts every time.

This is likely because the Windows API declaration (Declare PtrSafe Function) triggered Outlook's security policy. Outlook treats API calls more strictly than standard VBA and requires the macro to be in a trusted location.

Here are the solutions, in order of preference:

Solution 1: Save in Outlook's Startup Folder (Recommended)
  1. Press Win + R and type: shell:startup
  2. Navigate to: C:\Users\[YourUsername]\AppData\Roaming\Microsoft\Outlook\STARTUP
  3. Save your macro file as an .otm file (Outlook Macro-Enabled Template) in that folder
  4. Restart Outlook

Outlook will auto-load and trust macros from this location without prompting.

Solution 2: Trust the VBA Project in Outlook Settings
  1. In Outlook, go to File > Options > Trust Center > Trust Center Settings
  2. Click Macro Security
  3. Select Notifications for all macros or Enable all macros (depending on your security preference)
  4. Click OK

However, this may still prompt depending on your organization's policies.

Solution 3: Remove the API Dependency (If Acceptable)

If you want to avoid the API declaration altogether, you could use a simpler approach that doesn't require Windows API:

Sub PayPal_Receipt_Printing()
    ' Send NumLock once to toggle it before the operation
    SendKeys "{NUMLOCK}"
    
    SendKeys "%"
    SendKeys "FPR"
    SendKeys "%{S}"
    SendKeys "1-2"
    SendKeys "{ENTER}"
    DoEvents
    
    ' Toggle back
    SendKeys "{NUMLOCK}"
End Sub

This is less elegant but avoids the security warning.

The Basic Macro (2022)

This version toggles NumLock twice, which assumes nothing else in the macro changed it—but that’s unreliable.

' Outlook 2016/2019 PayPal Receipt Printing - Only print pages 1 and 2

Sub PayPal_Receipt_Printing()

SendKeys "%"
SendKeys "FPR"
SendKeys "%{S}"
SendKeys "1-2"
SendKeys "{ENTER}"
DoEvents
SendKeys "{NUMLOCK}{NUMLOCK}"

End Sub

Old Version

The code below worked for a while but recently stopped working after a Windows update but I am leaving it here for reference because there might old versions of office this is needed for and I can see what I changed to get it to work.

' Outlook 2016/2019 PayPal Receipt Printing - Only print pages 1 and 2

Sub PayPal_Receipt_Printing()

SendKeys "%FPR"
SendKeys "%S"
SendKeys "1-2"
SendKeys "{ENTER}"
DoEvents
SendKeys "{NUMLOCK}{NUMLOCK}"

End Sub

How I fixed this

  • The error started occuring after a Windows/Office Update
  • When i run a macro in office it makes a noise/alert/bong and appears not to run
    • This alert was caused by incorrect keypresses generated by the macro caused by changes to how the code is interpreted after an update.
    • The macro is running correctly, but not as you expect.
    • Becasue the macro does not crash, there are no error to be generated.
  • I found the error by REMMING out all of the lines in the VBA and check each line/action until the issue is found.
    • I run each line one by one to see where the bong was generated.
    • I REMMED out all the lines except the first one, checked, then uncommented the second line and rechecked etc..
  • I fixed the script by appling these changes:
    • SendKeys "%FPR" is now broken into 2 lines. For some reason the code on one line was not longer accepted.
      • SendKeys "%"
      • SendKeys "FPR"
    • I have also changed SendKeys "%S" to SendKeys "%{s}" as there was a change in how the asset on the print dialogue box is selected or how this particular line was handled.

Code explained

  • SendKeys "%FPR"
    • Press the keys: Alt --> F --> P --> R
    • Use to work but stop working after a recent update.
  • SendKeys "%"
    • Press the keys: Alt
    • Works fine when it is on its own
  • SendKeys "%{FPR}"
    • While holding the ALT key press F --> P --> R
    • This should work

Install the Macro and create a Quick Access Toolbar button

Test Print

Remembering that this script will use your default printer, do a test print and then you are done.

The rest of this article is for reference.

Notes

 


Numlock gets turned off when using SendKeys

The NumLock would always turn off after running the script no matter what. These are my notes on resolving this issue.

When you use SendKeys the NumLock is turned off due to a bug in Visual Basic.

Solutions from Microsoft

I found these towards the end of my research and they pretty much the best way of fixing this issue.

Executing two or more SendKeys statements in a row results in turning off the NumLock key. This problem may also affect the CapsLock and ScrollLock keys.

My Solution 1 - DoEvents

If you look in the script above you can see the following code taken from SendKeys is messing with my NumLock key via VBA code in Access form - Stack Overflow

DoEvents
SendKeys "{NUMLOCK}{NUMLOCK}"

This solution seems to work really well and perhaps can be expanded for Caps Lock and Scroll Lock if needed.

My Solution 2 - Sense NumLock state and then restore after SendKeys (GetKeyState/GetAsyncKeyState)

I spent quite a bit of time trying this but could not get it to work so I am including my notes and research here for future reference.

The code below I managed to get to sense when a key was pressed down and shows how to use the High/Low bit thing by using Hex codes

' Get Numlock status

Private Const VK_NUMLOCK = &H90
Private Const VK_SCROLL = &H91
Private Const VK_CAPITAL = &H14

Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Long

Private Function KeyDown(ByVal vKey As Long) As Boolean
   KeyDown = GetAsyncKeyState(vKey) And &H8001
End Function

Sub Test_Key_down()

If KeyDown(vbKeyNumlock) Then MsgBox "The NumLock key is pressed down!"

End Sub

Notes

  • I can then get state before running the code and restore it aftewwards to fix bug.
  • I cannot get the live state of the NumLock using this method
  • All Declare Statements must now include the PtrSafe keyword when running in 64-bit versions of Microsoft Office. The PtrSafe keyword indicates a Declare statement is safe to run in 64-bit versions of Microsoft Office.
  • SendKeys is messing with my NumLock key via VBA code in Access form - Stack Overflow - Answers here.
  • &H8001 = checks if the key is down has been pressed in this process. it is not cleared until new process.
  • &H8000 = checks if the key is down
  • &H0001 / &H1 = checks if the key has been pressed in this process. it is not cleared until new process.
  • this only does keys, I cant get it to recognise the state of the numlock light
  • process/message que clears after about 5 seconds
  • 0x8001 = Low bit
  • 0x8001 = High bit
  • 0x8001 =  -32767
  • If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down.
  • If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState. However, you should not rely on this last behavior; for more information, see the Remarks.

My Solution 3 - Sense NumLock state and then restore after SendKeys (Keyboard Events)

I never tried this option as it looked very complicated and I do not want to learn VB.


Outlook VB General Notes

Read 2387 times Last modified on Sunday, 18 October 2026 13:57