Snap and Automate: A Guide to Screenshot Capturing in Process Automation

Lately, I've received numerous requests on how to capture screenshots within automation processes. While logs can provide a record of script actions and SAP system inputs, there's a growing need to provide visual proof of extracted parameters. This is where screenshot capturing comes in - a way to provide tangible evidence of the data extracted, beyond just log entries. In response to these requests, I'll be sharing a guide on how to perform screenshot capturing in automation processes using Visual Basic for Application (VBA).

The Screen Capturing Function

The first step is to import a keyboard event function that simulates a key press. This handy function allows us to trigger a screenshot with just a few lines of code. To take a screenshot, we will run the function with the print screen button, which has a hex code of "&H2C". Set all other parameters to zero, and you're good to go!

Private Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal _
  bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)

Sub PrintScreen()
   keybd_event &H2C, 0, 0, 0
End Sub

Once you trigger the keyboard event function, the screenshot is instantly copied to your clipboard, ready to be shared. Now, if we press Ctrl-V or use the paste command in any Windows application (could be Excel or Word), your screenshot will be inserted as a picture.

Now, here's a crucial detail to keep in mind: If you paste the screenshot immediately after triggering the keyboard event function, you might end up with the wrong image. That's because the screenshot takes a tiny moment to save to the clipboard.

To resolve this issue, just add a brief pause after the screenshot and before pasting. This allows the screenshot to fully save to the clipboard.

I've got a handy Pause function that does the trick, temporarily halting code execution for a specified time. In my case, a short delay of just 0.1 seconds was all it took to ensure the correct screenshot gets copied every time. Problem solved!

Private Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal _
  bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
  
Function Pause(sec As Single)
  Dim t As Single: t = Timer
  Do: DoEvents: Loop Until Timer > t + sec
End Function

Sub PrintScreen()
    keybd_event &H2C, 0, 0, 0
    Pause (0.1)
End Sub

Incorporating screenshots into SAP GUI Script

Take a look at this example of an SAP GUI script. When I run this script, it extracts data from the "KE5Z" tcode for a specific year and company. Then, it exports the table to a directory of my choice, with a customized filename with a timestamp.

Check out my previous article, where I share a step-by-step guide on getting started with SAP automation. It's a great resource to help you streamline your workflows and boost productivity!

Sub KE5ZExport()
    Dim SapGuiAuto, objGUI, objConn, session, CurrentTimeStamp As String, destinationDir As String, fileName As String, company As String, period As String, year As String
    
    CurrentTimeStamp = Format(Now, "yyyyMMddhhmmss")
    destinationDir = "C:\Users\joel_\Documents\SAP Exports\KE5Z\"
    company = "0KTE"
    period = "3"
    year = "2024"
    fileName = "KE5Z " & year & period & " " & CurrentTimeStamp & ".XLSX"
    
    Set SapGuiAuto = GetObject("SAPGUI")
    Set objGUI = SapGuiAuto.GetScriptingEngine
    Set objConn = objGUI.Children(0)
    Set session = objConn.Children(0)
    session.findbyid("wnd[0]/tbar[0]/okcd").Text = "/n"
    session.findbyid("wnd[0]").sendVKey 0
    session.findbyid("wnd[0]").maximize
    session.findbyid("wnd[0]/tbar[0]/okcd").Text = "/nke5z"
    session.findbyid("wnd[0]").sendVKey 0
    session.findbyid("wnd[0]/usr/ctxtBUKRS-LOW").Text = company
    session.findbyid("wnd[0]/usr/ctxtPOPER-LOW").Text = period
    session.findbyid("wnd[0]/usr/ctxtRYEAR-LOW").Text = year
    session.findbyid("wnd[0]").sendVKey 8
    
    session.findbyid("wnd[0]/tbar[1]/btn[16]").press
    session.findbyid("wnd[1]/tbar[0]/btn[0]").press
    session.findbyid("wnd[1]/usr/ctxtDY_PATH").Text = destinationDir
    session.findbyid("wnd[1]/usr/ctxtDY_FILENAME").Text = fileName
    session.findbyid("wnd[1]/usr/ctxtDY_FILENAME").caretPosition = 4
    session.findbyid("wnd[1]/tbar[0]/btn[0]").press    
End Sub

Before running the script, we need to make sure SAP GUI is currently in focus. This is crucial because we want to capture the right screenshot. If SAP GUI isn't in focus, we might end up with the wrong screenshot.

To ensure SAP GUI is in focus, we can use the following lines of code:

Sub KE5ZExport()
    'Other prior steps...
    Set session = objConn.Children(0)
    session.findbyid("wnd[0]/tbar[0]/okcd").Text = "/n"
    session.findbyid("wnd[0]").sendVKey 0
    Dim winTitle as String
    winTitle = session.findbyid("wnd[0]").Text
    AppActivate winTitle
    
    'Subsequent steps
End Sub

Here's what's happening: we first return to the SAP main menu. Then, we're using the AppActivate function to put an application in focus based on its title. However, SAP's title dynamically changes, so we need to get creative. We're using the Text property to retrieve the current window title and store it in the winTitle variable. This way, we can accurately bring SAP GUI into focus and capture the screenshot we need.

Whenever I run this script, I want to capture a screenshot of the parameter page to keep a record of the parameters used. To achieve this, I'll use the debugging process to identify the exact point in the script where the screenshot should be taken.

At that point, we'll trigger the print screen function we created earlier, and the script will continue executing until the data is extracted into Excel.

Sub KE5ZExport()
    'Other prior steps...
    session.findbyid("wnd[0]/usr/ctxtBUKRS-LOW").Text = company
    session.findbyid("wnd[0]/usr/ctxtPOPER-LOW").Text = period
    session.findbyid("wnd[0]/usr/ctxtRYEAR-LOW").Text = year
    Call PrintScreen
    session.findbyid("wnd[0]").sendVKey 8
    'Subsequent steps...
End Sub

Pasting Screenshot into Excel

Once the extraction is complete, I want to paste the screenshot into a new sheet in the same workbook. This way, we'll have a clear visual record of how the data was extracted, making it easier for others to follow the same steps and ensuring transparency and accountability in our workflow.

You can refer to the VBA code below on the detailed steps:

Sub KE5ZExport()
    'Other prior steps...
    session.findbyid("wnd[1]/usr/ctxtDY_FILENAME").caretPosition = 4
    session.findbyid("wnd[1]/tbar[0]/btn[0]").press
    Dim wb As Workbook
    Set wb = Workbooks.Open(destinationDir & fileName)
    Dim ws As Worksheet
    Set ws = wb.Worksheets.Add(after:=wb.Worksheets(wb.Worksheets.Count))
    ws.Range("A1").Activate
    ws.Paste
End Sub

Here's what's happening:

We open an Excel workbook using the file path and name stored in the variables destinationDir and fileName, which is our newly exported file. This will allow us to paste our screenshot into the workbook.

Next, we're adding a new worksheet to the workbook. This will give us a new worksheet to paste our screenshot into.

Then, we activate cell A1 in the new worksheet and this will be where we paste our screenshot.

CaptureDualScreen

Cropping and Resizing Screenshot

Now that our screenshot is pasted, let's get it looking just right! As you can see in the screenshot, it's a bit too large for our needs, and since I'm working with a dual-screen setup, I only need the screenshot from the smaller screen. I can only see the full image at 40% zoom.

Here's how we can refine specify our screenshot using VBA:

Sub KE5ZExport()
    'Other prior steps...
    Dim wb As Workbook
    Set wb = Workbooks.Open(destinationDir & fileName)
    Dim ws As Worksheet
    Set ws = wb.Worksheets.Add(after:=wb.Worksheets(wb.Worksheets.Count))
    ws.Range("A1").Activate
    ws.Paste

    numShapes = ws.Shapes.Count
    Dim mypic As Shape
    Set mypic = ws.Shapes(numShapes)
    
    mypic.LockAspectRatio = True
    mypic.PictureFormat.CropLeft = 1920
    mypic.PictureFormat.CropBottom = 425
    mypic.Height = 250
    
    mypic.Top = ws.Range("A1").Top
    mypic.Left = ws.Range("A1").Left
End Sub

First, we need to identify the screenshot object so we can work with it.

We can do this by counting the shapes on the worksheet and grabbing the last one, which is our screenshot. Why is it the last one? That's because we just pasted it in, so it becomes the most recent addition to the worksheet's shape collection. By targeting the last shape, we can confidently grab our freshly pasted screenshot and work with it.

Next, we'll lock the aspect ratio to prevent our screenshot from getting distorted when we resize it.

Then, we'll crop it to get just the part we want. In my case, I'll trim off 1920 pixels from the left and 425 pixels from the bottom. Feel free to experiment with those numbers to get the crop just right!

Next, we'll resize the screenshot to a nice size. I'll set the height to 250 pixels, and since the aspect ratio is locked, the width will adjust accordingly.

Finally, we'll move the screenshot to cell "A1".

And here's the result! After we've refined the screenshot, it now looks like this:

FinalScreenCapture

As you can see, the refinement process has successfully cropped and resized the screenshot to fit our needs. The image is now crisp, clear, and perfectly sized for our Excel workbook.

And there you have it! With this script, you've successfully automated screen capturing with VBA. You've learned how to:

1) Capture a screenshot using the keyboard event function

2) Paste the screenshot into an Excel worksheet

3) Crop and resize the screenshot to fit your needs

If you are eager to unlock the power of SAP GUI Scripting, I've got you covered! I've written a comprehensive eBook that covers everything you need to know to get started.

With this eBook, you'll gain a complete understanding of the SAP GUI object model and get access to practical code snippets that will help you hit the ground running.

Get your copy now and start your SAP GUI Scripting journey today!

SAP GUI Scripting: Understanding the Basics