PowerBuilder Debugging – How to View Datawindow Data

The PowerBuilder Debugger doesn’t have a mechanism for viewing the underlying data while debugging an application.  This can be annoying at times; so I wrote some simple code that uses the SaveAs function and a Windows ShellExecute function to automatically display the underlying datawindow data using the correct program for the file type.

Typical Formats for Saving PowerBuilder Datawindow Data

  • Excel
  • Text
  • Csv
  • XML
  • PDF

Newer Formats for Saving PowerBuilder Datawindow Data

  • Ascii – A cross between SaveAs(HtmlTable!) and SaveAs(Text!) but displays data in a way more closely representing what is displayed in the datawindow including column headers and computed fields.
  • FormattedText – Even newer, just introduced in PowerBuilder version ten or eleven (I am not sure exactly), this saves column headers as they are displayed in datawindow instead of the column name. There are other display customization settings.

Who might benefit from the code for viewing buffer data for datawindows?

  • Developers for Debugging, Unit-Testing and Production Support
  • Quality Assurance Testers
  • Power Users
  • Help Desk Professionals

How to Instantly View Datawindow Data Throughout Your Applications

Add code to the clicked event of your datawindow control ancestor. If you don’t have a common ancestor, then you can add the code to any of your datawindow controls where you want the ability to view the underlying data.

The following PowerBuilder code looks for:

  1. control+alt+e and a mouse click on the datawindow to display data in excel format
  2. control+alt+t and a mouse click on the datawindow to display data in text format
  3. control+alt+a and a mouse click on the datawindow to display data in ascii format
  4. control+alt+x and a mouse click on the datawindow to display data in nearly any format (see full list at bottom of article) via a dialog prompt.
The basic logic saves the data, then opens it immediately using the windows ShellExecute function.
long ll_handle
string ls_filename, ls_null, ls_dir

if keydown(KeyControl!) and keydown(KeyAlt!) then

    // set work variables to be used in save
    SetNull(ls_null)

    // grab handle to MDI frame window for the ShellExecute function
    ll_handle = Handle(gwMdi)

    // construct the filename using dataobject and datetime
    ls_dir = "c:\temp"
    ls_filename = ls_dir + "\debug_dataobject_" + this.dataobject + &
 "_date_" + string(Today(),"mmddyyhhmmss")

    // determine if we are saving excel, text, csv, or prompting for filetype
    if keydown(keye!) then

        ls_filename =+ '.xls'
        dw_1.SaveAs(ls_filename, Excel!,True)

    elseif keydown(keyt!) then

        ls_filename =+ '.txt'
        dw_1.SaveAs(ls_filename, Text!,True)

    elseif keydown(keya!) then

        ls_filename =+ '.txt'
        dw_1.SaveAsAscii(ls_filename)  // special savaasascii function

    elseif keydown(keyx!) then

        ls_filename =+ ''
        dw_1.SaveAs(ls_filename) // empty string forces dialog open

    end if

    // now automatically open the file using default program // for the file type via Windows API function
    if fileexists(ls_filename) then
        gwMdi.ShellExecute(ll_handle, 'open', ls_filename, ls_null, ls_dir, 3)
    end if

end if

// Define ShellExcecute as Local External Function, I made it a local external to the mdi frame 
// for which I had a global handle for. You may also define this windows function as Global External Function:
Function Long ShellExecute (Long hWnd, String lpOperation, String lpFile, String lpParameters, &
        String lpDirectory, Long nShowCmd) Library "shell32.dll" Alias For "ShellExecuteA"
Once end-users saw me using the feature, they wanted to use it;  and Quality Assurance people really love to have the functionality because it lets them see all of the underlying data including data not shown on the screen.  In some scenarios I have deployed the code to production so that it can be used for production support and/or troubleshooting.  The sensitivity of the data is a big factor in deciding whether to leave the code active in the production or not. Sometimes I add a safety check and allow the viewing of underlying data for my userid in cases where data is sensitive.  In some cases we use more obscure key combinations that could never be guessed (e.g. Easter Egg)

Here is a full list of the supported PowerBuilder SaveAs Types:

Values

PowerBuilder enumerated value Web DataWindow Numeric value Meaning
Excel! Excel 0 Microsoft Excel format.
Text! Text 1 (Default) Tab-separated columns with a return at the end of each row
CSV! CSV 2 Comma-separated values
SYLK! SYLK 3 Microsoft Multiplan format
WKS! WKS 4 Lotus 1-2-3 format
WK1! WK1 5 Lotus 1-2-3 format
DIF! DIF 6 Data Interchange Format
dBASE2! dBASE2 7 dBASE-II format
dBASE3! dBASE3 8 dBASE-III format
SQLInsert! SQLInsert 9 SQL syntax
Clipboard! Clipboard 10 Save an image of the graph to the clipboard
PSReport! PSReport 11 Powersoft Report (PSR) format
WMF! WMF 12 Windows Metafile format
HTMLTable! HTMLTable 13 HTML TABLE, TR, and TD elements
Excel5! Excel5 14 Microsoft Excel Version 5 format
XML! XML 15 Extensible Markup Language (XML)
XSLFO! XSLFO 16 Extensible Stylesheet Language Formatting Objects (XSL-FO)
PDF! PDF 17 Portable Document Format (PDF)
Excel8! Excel8 18 Microsoft Excel Version 8 and higher format
EMF! EMF 19 Enhanced Metafile Format
XLSX! 24 Microsoft Excel 2007 format for XML data (requires .NET Framework 3.0 or later)
XLSB! 25 Microsoft Excel 2007 format for binary data (requires .NET Framework 3.0 or later)

NoteObsolete valuesThe following SaveAsType values are considered to be obsolete and will be removed in a future release: Excel!, WK1!, WKS!, SYLK!, dBase2!, WMF!. Use Excel8!, XLSB!, or XLSX! for current versions of Microsoft Excel!, and EMF! in

While this isn’t the same as viewing data in the debugger it is very useful. If you use a datawindow object ancestor one change can implement the functionality application wide.

If you have any comments or suggestions, please leave a comment!

 

Tags:

3 Responses

  1. Cool idea. There have been several times when I would have liked to see the data behind a datawindow.

    When I’ve added debugging code to my datawindow ancestor, I usually set it to only run if I’m running from the IDE.

Leave a Reply

Your email address will not be published. Required fields are marked *