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.
The Macro (2022)
' 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.
- SendKeys "%FPR" is now broken into 2 lines. For some reason the code on one line was not longer accepted.
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
- Outlook 2010 Macro to print first page of email - YouTube - This video shows you how to set everything up, however you should use my script above.
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
- Using VBA Editor in Outlook
- To run the macro from Outlook 2007 or older, go to Tools --> Macro --> Macros and select the macro.
- In Outlook 2010, you need to show the Developer ribbon first (File --> Options --> Customize Ribbon --> check Developer ribbon on the right).
- In Outlook pressing Alt+F11 opens the Microsoft Visual Basic for Applications editor
- You can also open the Macros dialog using Alt+F8 (all versions).
- How to use Outlook's VBA Editor
- Multiple Printers in Windows
- Print Selected Pages
- Various Outlook VBA
- Print Emails Automatically - VBOffice
- Print Attachments Automatically - VBOffice
- How to print emails and attachments from Outlook: the basic useful facts | MAPILab blog - Various printing issues with Outlook discussed here with solutions with such topics as automatically printing attachments.
- Outlook VBA Macros - VBOffice - Free VBA macros for Microsoft® Outlook®. Get more than 100 ready-to-use scripts, or use the samples as a template for your own programming.
- Macros not working
- Macros not working after you restart Outlook this will be because of macro security and there are 2 options
- change this setting :: Trust Centre -> Macro Settings --> Notifications for all macros
- self sign the VBA script (not sure how to do this)
- Outlook Macro Stops Working (or Doesn't Work to Begin With)? - jmerrell.com
- Outlook macros are not enabled - Microsoft Community
- Macros disabled and can't enable them to run - Microsoft Community
- Outlook 2016 - Macros no longer work after upgrading from Outlook 2013 - Microsoft Community
- Outlook 2019/365: Enable or Disable Macros | technipages
- How to create Outlook macros in Office 2016 & 2019? | EasyTweaks.com
- Outlook macro blocked since update 1902 + other bugs - Microsoft Community
- Macros not working after you restart Outlook this will be because of macro security and there are 2 options
- Self Sign Macro
- Outlook Macro Stops Working (or Doesn't Work to Begin With)? - jmerrell.com - I remembered when I originally created the macros several years ago (on my previous computer) I had to create a digital signature and sign the macros in order to get past the Trust Center security settings. Luckily doing so isn’t that complicated.
- Signing your own macros with SelfCert.exe - HowTo-Outlook - Sign your own macros with SelfCert.exe so there is no more need to lower your security settings to get rid of VBA macro security prompts.
- Digitally sign your macro project - Use a certificate to digitally sign your macro project.
- Misc
- Outlook macro blocked since update 1902 + other bugs | Microsoft Forums
- After countless hours of investigation time and productivity loss, I finally found the problem: for an unknown reason my file vbaproject.otm was corrupt: although I was still able to view it, edit it and save it, any attempt to run a macro returned the error "macro in this project are disabled" although the macro settings were set to "Notifications for all macros"!
- To fix the issue, I copied my macro to a text file (luckily I only had code!) then deleted the file. Outlook created a new blank file at startup where I just had to paste the copied code.
- Outlook macro blocked since update 1902 + other bugs | Microsoft Forums
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.
- see BUG: Multiple SendKeys Statement Turns Off NumLock Key | Microsoft Support - This gives the follow work arounds:
- Send all the characters in a single SendKeys statement. -or-
- Execute a DoEvents function between each SendKeys statement. However, depending on the complexity of the key strokes, this may not work in all cases. -or-
- Determine the setting of the NumLock key prior to using SendKeys. Then, turn off the NumLock before using SendKeys. After using SendKeys, reset the NumLock to its previous setting. This is accomplished using the GetKeyboardState, keybd_event and SetKeyboardState API functions. See the REFERENCES section below for more information. -or-
- Use API functions instead of SendKeys. See the REFERENCES section below for more information,
- See: How To Toggle the NUM LOCK, CAPS LOCK, and SCROLL LOCK Keys | Microsoft Support
- Backup of the article: Microsoft KB Archive/179987 - BetaArchive Wiki
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
- General
- VB (Visual Basic) is NOT the same as VB.net , there are also similaritwes with C++ and C#
- VBA (Visual Basic for Applications) it is a crippled version of VB and not everything works or is available (perhaps context of application only)
- Adding `True` on to the end of `SendKeys` commands does not seem to make any difference
- People say dont use SendKeys because of these issues and use something like keyboard events instead.
- PtrSafe keyword must be used on 64-Bit systems. Don't know why
- VBA Printing Scripts
- ff
- General Example Scripts (to overcome NumLock getting turn off)
- SendKeys is messing with my NumLock key via VBA code in Access form - Stack Overflow
- number lock turns off intermittently - Microsoft Community
- Turning on the "Num Lock" key-VBForums
- vb.net - Why GetAsyncKeyState not work on MS Excel - Stack Overflow
- vba - Turning NUMLOCK on at the end of a macro run - Stack Overflow
- How can Excel vba detect if Caps Lock or Num Lock is on?
- detecting the keyboard scroll lock state (example)-VBForums
- [CC++] - about GetKeyState() - Gives the following descriptions
- GetKeyState tells you only the state of the keyboard now. If someone presses a key and release it while your loop is executing, that won't be detected.
- GetKeyState works based on Keypress/release messages already retrieved. If' you're in the main window thread and you've not made any provision in your loop to process messages, the state reflected won't change.
- GetAsyncKeyState may work better for you. First, it bypasses the message processing so it reflects the actual state of the keyboard. Second, it has a features where it tells you via the low order bit if the key was pressed between calls to GetAsyncKeyState. This is still problematic because any application on the system calling GetAsyncKeyState will reset that value.
- determine if a key has been pressed using GetAsyncKeyState() - This has a script worth looking at
- Outlook 2010 - macro "Print 1st page" - Problem with Num Lock turning off
- Example Keyboard event scripts
- vba - Send Keys is Disabling NumLock - Stack Overflow - An extensive keyboard event script
- FreeVBCode code snippet: Toggle NumLock Key - Keyboard event
- [RESOLVED] Caps Lock/Num lock on or off?-VBForums - Keyboard event
- VB Helper: HowTo: Turn CapsLock on and off
- Activating CapsLock, NumLock, ScrollLock and PrintScreen on NT-Based Systems | Visual Basic Developers Resource Centre
- Turning on the "Num Lock" key-VBForums
- Significant Bits
- VS 2010 Stop GetAsyncKeyState repeating-VBForums - If we read the documentation, we see that GetAsyncKeyState() already tells us if the key's been pressed again or if it's a "repeat":
- 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.
- Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the pre-emptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application. The behavior of the least significant bit of the return value is retained strictly for compatibility with 16-bit Windows applications (which are non-preemptive) and should not be relied upon.
- c# - What are these numbers in the code GetAsyncKeyState(VK_SHIFT) & 0x8000 ? Are they essential? - Stack Overflow
- First and Last Bit of GetAsyncKeyState
- VS 2010 Stop GetAsyncKeyState repeating-VBForums - If we read the documentation, we see that GetAsyncKeyState() already tells us if the key's been pressed again or if it's a "repeat":
- SendKeys
- GetKeyState()
- This gets a snapshot of the message que and not the live keyboard
- GetKeyState function (winuser.h) - Win32 apps | Microsoft Docs
- [RESOLVED] simple question - getkeystate api-VBForums
- VBA Remember Numlock State | MrExcel Message Board - Very simple code that uses <>
- GetAsyncKeyState()
- This get the live position of the keys. I cannot get this to get the NumLock state.
- GetAsyncKeyState function (winuser.h) - Win32 apps | Microsoft Docs
- GetAsyncKeyState - Some scripts to look at
- vb.net - How can I use GetAsyncKeyState to implement a global hotkey? - Stack Overflow
- VS 2010 GetAsyncKeyState-VBForums
- c# - GetAsyncKeyState Explanation required - Stack Overflow
- Wait Until a Key is Pressed with GetAsyncKeyState VBA - wellsr.com
- Return Values Of GetAsyncKeyState() - C# | Dream.In.Code
- GetKeyboardState()
- This might allow you to access the NumLock toggle status.
- GetKeyboardState function (winuser.h) - Win32 apps | Microsoft Docs
- Visual Basic General
- Only comments may appear after End Sub, End Function, or End Property | Microsoft Docs
- Virtual-Key Codes (Winuser.h) - Win32 apps | Microsoft Docs - The page shows the symbolic constant names, hexadecimal values, and mouse or keyboard equivalents for the virtual-key codes used by the system. The codes are listed in numeric order.
- Keycode constants | Microsoft Docs - The following constants can be used anywhere in your code in place of the actual values.
- VBA Boolean Data Type | Examples to Use Excel VBA Boolean Operator - How to set a variable
- Boolean Data Type - Visual Basic | Microsoft Docs
- VBA: Sub vs Function - Overview, Key Differences, How To Write
- The usage and difference of getkeystate and getasynckeystate and Getkeyboardstate functions | alibabacloud
- c++ - GetKeyState() vs. GetAsyncKeyState() vs. getch()? - Stack Overflow
- What are &H1, &H8000, etc.? - Visual Basic (Classic) - Tek-Tips
- What does the 0x80 code mean when referring to keyboard controls - Genera Codice
- The code in this project must be updated for use on 64-bit systems | Microsoft Docs