• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • BASS: Build A Spreadsheet

    December 12, 2012 Ted Holt

    Note: The code accompanying this article is available for download here. This code was updated on 12/22/14.

    Everybody needs a project–something to putter with in order to relieve stress and deal with the vicissitudes of life. I would like to tell you about a project that I’ve been working on for the past few months. I only wrote it for the fun of it, but it has already come in handy.

    It seems that not a week goes by without someone asking me to stop providing them a report as a PDF and give it to them in Excel format instead. It would be nice if I could flip a switch and an RPG program would quit building a spool file and build something they could open in Excel, but of course, such a change requires a good deal of reprogramming.

    My First Effort

    My first effort to address this void was to write a service program that would create an IFS file of data in comma-separated values form. I call the service program Write CSV (WRTCSV). We’ve retrofitted it into several programs in my shop, and it works well.

    WRTCSV consists of the following subprocedures:




    Subprocedure

    Subprocedure

    Description

    SetCSVSep

    Establish the group
    of four or fewer characters that separates the values. (The default is one
    comma.)

    OpenCSVFile

    Open a CSV file.
    (Create a new file or overwrite an existing one.)

    WriteCSVData

    Write a line with up
    to 35 character data values to a CSV file.

    CloseCSVFile

    Close a CSV file

    Changing a program to build a CSV file is not difficult.

    • Define variables for a file handle and a status (return) code.
    • Change the program to open the CSV file.
    • Identify the places where the program writes to a printer file, and where appropriate, issue calls to WriteCSVData. Disable the printer operations, or redirect the report into a garbage output queue.
    • Close the CSV file before shutting down the program.

    Here’s an example in RPG. Assume the part in black is the original program, which builds a report. The code I added to build the CSV file is in red. (Notice that I did not include error-handling code, but only left comments to show where it goes.)

    H option(*srcstmt: *nodebugio)
    H dftactgrp(*no) actgrp(*caller)
    H bnddir('SOMEBNDDIR')
    
    Fqcustcdt  if   e             disk    usropn
    Fqad3330p  o    e             printer usropn
    
    D FileStatus      s             10i 0
    D FileHandle      s             10i 0
    
     /copy prototypes,wrtcsv
    
     /free
         *inlr = *on;
    
         open qcustcdt;
         open qad3330p;
         FileStatus = OpenCSVFile ('CustBal.CSV': FileHandle);
         if FileStatus <> *zero;
            // add appropriate error handling
         endif;
    
         write Hdr;
         FileStatus = WriteCSVData (FileHandle:
                       'Name': 'Account': 'Balance');
         if FileStatus <> *zero;
            // add appropriate error handling
         endif;
         dow '1';
            read cusrec;
            if %eof();
               leave;
            endif;
            write Dtl;
            FileStatus = WriteCSVData (FileHandle:
                          LstNam: %char(CusNum): %editc(BalDue: 'P'));
            if FileStatus <> *zero;
               // add appropriate error handling
            endif;
         enddo;
    
         close *all;
         FileStatus = CloseCSVFile (FileHandle);
         if FileStatus <> *zero;
            // add appropriate error handling
         endif;
    
         return;
    

    Notice that the calls to WriteCSVData follow the output operations to the printer file. This isn’t a requirement, but it’s the typical way you would convert the program.

    If you want to use WRTCSV, you’re welcome to it. You’ll find the source code and service program object (compiled at V5R4) in the downloadable code.

    My Second Effort

    WRTCSV was not my piddling project. I wrote WRTCSV on company time because I needed it. But I never stopped thinking that there must be an even better way to build CSV files. I wanted a method that was faster to implement than embedding calls to WRTCSV routines. I also wanted a method that I could use with any report, even those produced by the Famous ERP Package used to run the factory where I work.

    I finally decided to create a scripting language that would let me tell the computer how to copy data from spooled files into IFS files. I know there are products on the market that do that already, but I needed something to tinker with, and this seemed like a good challenge.

    I call my scripting language BASS. (I pronounce it like a type of fish, not like a low-voiced male singer.) BASS stands for Build A Spreadsheet. Does it build a spreadsheet? No, it builds a CSV file, which users can open into a spreadsheet. But BACSVF was too hard to pronounce.

    I began by writing a grammar for my language. You can read the grammar. It’s the Word document in the downloadable files. It took me about a month to define the syntax of the language. (Remember, I only worked on this outside of working hours, and I didn’t work on it every day.) I considered a lot of possibilities, and came up with a very simple language. By keeping it simple, the language would be easier to learn and easier to write an interpreter for than it would have been had I gotten too fancy in my aspirations.

    Once the grammar was to my liking, I began the process of programming it. These are the objects that make up the utility:




    Object

    Object

    Type

    Description

    GOBASS

    *CMD

    The BASS command
    interface

    GOBASSH

    *PNLGRP

    Help text for GOBASS
    command

    BASSMSGF

    *MSGF

    Messages

    BASSMAINC

    *PGM

    CPP for the GOBASS
    command

    BASSMAIN

    *PGM

    The BASS interpreter

    WRTCSV

    *SRVPGM

    Output to a stream
    file in CSV format.

    Did you notice that BASS uses WRTCSV? No sense re-inventing the wheel, eh?

    Not that it matters, but I will also mention that BASSMAIN is built from six modules, each of which has one task. For example, one module handles conditions. Another one handles assignment statements. Modular programming is wonderful.

    Here’s a simple BASS script. You could put it into member DSPLIBL in some source physical file member.

    # Convert output of Display Library List report to CSV
    
    var $HeadersAreComplete = FALSE
    var $LibraryType
    
    / $input == ' ' / exit                    # skip blank lines
    
    # Generate the column headings only once
    / $input (4:10) == Library /  goto 100
    
    # Select libraries
    $LibraryType = ''
    / $input (16:3) == SYS /  $LibraryType = System
    / $input (16:3) == PRD /  $LibraryType = Product
    / $input (16:3) == CUR /  $LibraryType = Current
    / $input (16:3) == USR /  $LibraryType = User
    / $LibraryType  <> '' /  goto 200
    
    / $input (27:1) == * / stop     # End of listing found
    exit                            # ignore other lines
    
    100 # column header routine
        / $HeadersAreComplete == TRUE / exit
        $a = 'Library List'
        addrow
        addrow
        $a = Library
        $b = Description
        $c = Type
        addrow
        $HeadersAreComplete = TRUE
        exit
    
    200 # extract data for one library
        $a = $input ( 4: 10)     # library name
        $b = $input (39: 50)     # description
        $c = $LibraryType
        addrow
        exit
    

    What does this mean?

    • The first line begins with a pound sign (#). It’s a comment.
    • Next come two variable declarations, the first of which is given an initial value.
    • Ignore blank lines in the input.
    • Build the column headings only once.
    • If the input line contains library info, convert the cryptic abbreviation into a word and continue at label 200.
    • Check for the end of the listing and shut down when found.
    • If an unidentified line is found, skip it.
    • The routine at label 100 adds a row of column headings.
    • The routine at label 200 adds a row of library data.

    Here are the commands to make it run. (Fill in the library and source physical file names with appropriate values.)

    DSPLIBL OUTPUT(*PRINT)
    
    GOBASS FILE(QPRTLIBL) +
       SPLNBR(*LAST) +
       SCRIPT(<lib>/<srcpf> DSPLIBL) +
       STMF(DSLIBL.CSV)    
    
    DSPF STMF(dsplibl.csv)
    

    If you use this utility, please tell me about your experience with it.

    So far BASS seems to be adequate for the job, but I plan to make two more enhancements. (I may think of other enhancements later, but I’ll cross that bridge when I come to it.) I am going to make the enhancements for the same reason I wrote BASS–for the fun of it. If they work out, I’ll tell you about them later.

    That’s my project. What’s yours?



                         Post this story to del.icio.us
                   Post this story to Digg
        Post this story to Slashdot

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    Maxava

    Migrate IBM i with Confidence

    Tired of costly and risky migrations? Maxava Migrate Live minimizes disruption with seamless transitions. Upgrading to Power10 or cloud hosted system, Maxava has you covered!

    Learn More

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Sponsored Links

    Rocket Software:  Set yourself free from fees with Rocket iCluster! Complimentary trial!
    Bytware:  Protect your IBM Power Systems from security threats. Download the IFS security bundle!
    New Generation Software:  Read the new White Paper: BI for IBM i Customers

    IT Jungle Store Top Book Picks

    Bookstore Blowout! Up to 50% off all titles!

    The iSeries Express Web Implementer's Guide: Save 50%, Sale Price $29.50
    The iSeries Pocket Database Guide: Save 50%, Sale Price $29.50
    Easy Steps to Internet Programming for the System i: Save 50%, Sale Price $24.97
    The iSeries Pocket WebFacing Primer: Save 50%, Sale Price $19.50
    Migrating to WebSphere Express for iSeries: Save 50%, Sale Price $24.50
    Getting Started with WebSphere Express for iSeries: Save 50%, Sale Price $24.50
    The All-Everything Operating System: Save 50%, Sale Price $17.50
    The Best Joomla! Tutorial Ever!: Save 50%, Sale Price $9.98

    Trinium Keeps on Trucking with Mobile Interface from mrc What The Future Holds For IBM i Platforms In 2013

    Leave a Reply Cancel reply

Volume 12, Number 29 -- December 12, 2012
THIS ISSUE SPONSORED BY:

T.L. Ashford
WorksRight Software
PowerTech

Table of Contents

  • End-Of-Year Odds And Ends
  • BASS: Build A Spreadsheet
  • Admin Alert: Auditing Your IBM i Software Maintenance Bills

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • Meet The Next Gen Of IBMers Helping To Build IBM i
  • Looks Like IBM Is Building A Linux-Like PASE For IBM i After All
  • Will Independent IBM i Clouds Survive PowerVS?
  • Now, IBM Is Jacking Up Hardware Maintenance Prices
  • IBM i PTF Guide, Volume 27, Number 24
  • Big Blue Raises IBM i License Transfer Fees, Other Prices
  • Keep The IBM i Youth Movement Going With More Training, Better Tools
  • Remain Begins Migrating DevOps Tools To VS Code
  • IBM Readies LTO-10 Tape Drives And Libraries
  • IBM i PTF Guide, Volume 27, Number 23

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2025 IT Jungle