Developing Script Log Analyzers
In this chapter, you will learn how to write a collection of report and log analyzer scripts, each of which is designed to process a uniquely formatted file. In doing so, you will continue to expand your understanding of the techniques involved in reading and processing files. In addition, you will learn the basic techniques involved in creating output files and reports. This chapter will also introduce you to a number of VBScript functions and methods.
Reading Report and Log Files
In the previous chapter, you learned how to apply a number of methods belonging to the FileSystemObject in order to read the contents of report and log files. In this chapter, you will continue to expand upon your knowledge of file I/O scripting techniques as you learn how to develop this project's report and log analyzer scripts. You will also learn how to use the SkipLine() method. This method allows you to skip lines, such as headers, within input files and to develop more streamlined techniques for processing input files.
The syntax of the SkipLine() method is shown below.
ObjectReference.SkipLine()
ObjectReference is the variable representing the instance of the file that is being processed.
Note |
SkipLine() will not permit you to traverse backwards through a file and is only applicable when the input file is opened for reading. |
The SkipLine method does not accept any arguments and is limited to skipping a single line at a time. However, by wrapping it inside a loop, you can execute the method repeatedly to skip as many lines as necessary, as demonstrated below.
Set FsoObject = CreateObject("Scripting.FileSystemObject") Set SampleRpt = FsoObject.OpenTextFile("d:VBScriptsDemoSampleRpt.txt", 1) For i = 1 to 3 SampleRpt.SkipLine() Next
In this example, a file named SampleRpt.txt is opened and the first three lines are skipped. As a result, the next operation performed on the file would occur on the fourth line of the file.
Writing to Files
In order to complete the development of the report and log analyzer scripts you will need to know how to write text output to files in order to generate the summary report. To perform this task, you will need to learn to work with the FileSystemObject object's WriteLine() method, which has the following syntax:
ObjectReference. WriteLine([TextMsg])
ObjectReference is the variable representing the instance of the FileSystemObject. TextMsg is an optional parameter that represents a text string to be written as the next line in the file.
Note |
WriteLine() automatically appends a newline character to the end of each text string that it writes to a file. Another way to write text data to a file is with the Write() method, which writes a text string to a file without appending a newline character, thus allowing you to create a single line of text in a file using multiple write operations. |
The following example demonstrates how to use the WriteLine() method to append a text string to the end of a report file.
Set FsoObject = CreateObject("Scripting.FileSystemObject") Set SampleRpt = FsoObject.OpenTextFile("d:VBScriptsDemoSampleRpt.txt", 8) SampleRpt.WriteLine("--- Account Summary Report ---") SampleRpt.Close()
If you call the WriteLine() method without supplying a text string, it will write a blank line. You will need to add blank lines in order to improve the presentation of the text output in the summary report. However, the preferred way to write blank lines is using the WriteBlankLines() method, which has the following syntax.
ObjectReference. WriteBlankLines(NoOfLines)
ObjectReference is the variable representing the instance of the FileSystemObject. NoOfLines represents the number of blank lines to be written.
The following example demonstrates how to use the WriteBlankLines() method to append two blank lines to the end of a report file.
Set FsoObject = CreateObject("Scripting.FileSystemObject") Set SampleRpt = FsoObject.OpenTextFile("d:VBScriptsDemoSampleRpt.txt", 8) SampleRpt.WriteLine("--- Account Summary Report ---") SampleRpt.WriteBlankLines(2) SampleRpt.Close()
Creating the Error Log Analyzer
The first report and log analyzer script that Molly will tackle is the ErrorAnalyzer.vbs, which will be responsible for performing the following tasks:
- Setting up script configuration setting defaults in case the RptLog.ini file is missing certain key=value pairs or has been removed from the Windows 2000 server
- Reading and processing the INI file
- Creating a new summary report
- Recording a message to the Windows application event log
- Reading and parsing the Error.Log log file looking for level 3 or higher event messages
- Writing the Errors: section of the summary report file
ErrorAnalyzer.vbs will need to read the RptLog.ini file, which will reside in D:VBScriptsAnalyzers, and process the key=value pair entries from the [ErrorRpt] section, as shown in the following example.
[ErrorRpt] SourDir=d:Order_InventoryLogsError.log ReportOn=3 EventLog=True DestFile=d:Order_InventorySummaryRpts Debug=False
In addition, ErrorAnalyzer.vbs will have to read and process the Error.log file located in D:Order_InventoryLogs on the Windows 2000 Server. A copy of this file is shown below.
******************************************************************************* Error Report 3/15/03 ******************************************************************************* Date TimeCode Description 12:15:44 3/15/03 001 Unable to access card reader on device wkstn442 12:26:43 3/15/03 005 Invalid application password supplied by AMAT01 14:00:14 3/15/03 001 No inventory for part # 58694 - unable to fill order 39312 15:05:02 3/15/03 005 Invalid application password supplied by MJLF01 16:16:46 3/15/03 003 Unable to print summary rpt on master printer (no paper) ------------------------------------------------------------------------------- Total number of errors reported = 5
The Initialization Section
The script's Initialization Section, shown on the following page, begins by defining variables, constants, and objects needed globally by the script. This includes setting up a single dimension array called astrReportArray that will be used to hold selected lines of text from the Error.log file as it is being read.
Three constants are also defined to make the script easier to read. These constants are called cForReading, cForWriting, and cForAppending. Each represents a different type of file I/O mode. The FileSystemObject is also instantiated globally since it will be used by multiple procedures within the script. Lastly, the variable strSourceFile is assigned the name and path of the script's INI file.
'************************************************************************* 'Script Name: Script 18.3.vbs 'Author: Jerry Ford 'Created: 03/22/03 'Description: This script retrieves configuration settings from an INI file, 'processes a Report file and creates a Summary Report file. '************************************************************************* 'Initialization Section Option Explicit Dim FsoObject, strSourceFile, OpenFile, strInputLine, intCounter Dim strSourDir, strReportOn, strEventLog, strDestFile, strDebug ReDim astrReportArray(0) Const cForReading = 1 Const cForWriting = 2 Const cForAppending = 8 Set FsoObject = WScript.CreateObject("Scripting.FileSystemObject") strSourceFile = "d:VBScriptsAnalyzersRptLog.ini"
The Main Processing Section
The Main Processing Section, shown on the following page, makes six procedure calls and then executes the WScript object's Quit() method. SetUpDefault() calls a subroutine that establishes default configuration settings for the script. ProcessIniFile() opens the RptLog.ini file, extracts the key=value pairs from the [ErrorRpt] section, and assigns them to local variables, overriding any matching default variable settings. RefineOutputFileName() uses the VBScript Date() and Replace() functions to create a date-stamped file name for the summary report that the script will create and write output to.
Next, an If statement is set up to determine whether or not the script should write an event message to the Windows application event log, by checking the value of the strEventLog variable and calling the WriteToEvenLog() subroutine if appropriate. The ProcessReportFile() subroutine is called next. It reads the Error.log file, parsing out lines of text that contain level 3 or higher error messages and storing them as entries in astrReportArray. Next the RecordSummaryData() subroutine is called. It creates a new summary report and writes the Errors: section, retrieving report data from astrReportArray. Finally, the WScript object's Quit() method is used to terminate the script's execution.
'Main Processing Section SetUpDefaults() ProcessIniFile() RefineOutputFileName() If strEventLog = "True" Then WriteToEventLog() End If ProcessReportFile() RecordSummaryData() 'Terminate script execution WScript.Quit()
The SetUpDefaults() Subroutine
The SetUpDefaults() subroutine assigns default values to the following five global variables, each of which represents a default configuration setting for the script.
- strSourDir. Specifies the location of the Error.log file.
- strReportOn. Specifies the minimum level of message event errors to report on.
- strEventLog. Specifies whether or not the script should record a message to the Windows application event log.
- strDestFile. Specifies the folder where the summary report is to be saved.
- strDebug. Specifies whether or not the script is run in debug mode. When run in debug mode, pop-up dialog boxes display intermediate variable values and identify when various procedures execute in order to track the progress of the script when it executes.
'Procedure Section Sub SetUpDefaults() strSourDir = "d:Order_InventoryLogsError.log" strReportOn = 3 strEventLog = "True" strDestFile = "d:Order_InventorySummaryRpts" strDebug = "False" End Sub
The ProcessIniFile() Subroutine
The ProcessIniFile() subroutine, shown below, adapts the logic developed from the sample INI processing script in Chapter 17, "Using Configuration Files to Control Script Execution." It processes the RptLog.ini files and extracts the key=value pairs located in the [ErrorRpt] section.
Sub ProcessIniFile() Dim strKeyName, intGetEqualsPosition If (FsoObject.FileExists(strSourceFile)) Then Set OpenFile = FsoObject.OpenTextFile(strSourceFile, cForReading) Do Until Mid(strInputLine, 1, 10) = "[ErrorRpt]" strInputLine = OpenFile.ReadLine Loop Do Until OpenFile.AtEndOfStream = "True" strInputLine = OpenFile.ReadLine If Mid(strInputLine, 1, 1) = "[" Then Exit do End If If Len(strInputLine) <> 0 Then intGetEqualsPosition = Instr(strInputLine, "=") strKeyName = Mid(strInputLine, 1, intGetEqualsPosition - 1) Select Case strKeyName Case "SourDir" strSourDir = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "ReportOn" strReportOn = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "EventLog" strEventLog = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "DestFile" strDestFile = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "Debug" strDebug = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) End Select End If Loop OpenFile.Close() End If If strDebug = "True" Then MsgBox "strSourDir = " & strSourDir MsgBox "strReportOn = " & strReportOn MsgBox "strEventLog = " & strEventLog MsgBox "strDestFile = " & strDestFile MsgBox "strDebug = " & strDebug End If End Sub
As key=value pairs are parsed out, a Select Case statement is set up in order to assign script configuration settings to local variables, thus overriding any matching default settings.
At the end of this subroutine, an If statement is set up to check the value assigned to the strDebug variable in order to determine whether the script is being run in debug mode. If it is, then the value of each of these variables is displayed in order to show the state of the script's configuration settings.
The RefineOutputFileName() Subroutine
The RefineOutputFileName() subroutine, shown on the next page, is responsible for determining the file name under which the summary report is to be saved. In order to facilitate the maintenance of an archive of summary reports, each report is assigned a unique file name that includes a date stamp. This subroutine uses the Date() function to retrieve the current date in the format of mm/dd/yyyy. It then uses the Replace() function to replace each instance of the backslash (/) character with the dash (–) character.
Note |
Windows does not permit the backslash (/) character to be used in file names. Therefore the dash (–) character is used as a replacement character to separate the month, day, and year components of the date. |
Sub RefineOutputFileName() Dim DataString DataString = Replace(Date(), "/", "-") strDestFile = strDestFile & DataString & "_SumRpt.txt" End Sub
The ProcessReportFile() Subroutine
The ProcessReportFile() subroutine, shown below, opens the Error.log file for reading, establishes a Do…Loop that locates the line that begins with the word Date, and then sets up a second loop to process the remainder of the file. During each iteration of the second loop, the Instr() function is used to determine the location of the 00 characters (each error event number begins with two leading zeros) and then uses the Mid() function to determine the error message's event error level. Messages with a level 3 or higher error event level are added to a dynamic array called astrReportArray.
If the script is being executed in debug mode, the MsgBox() function is used to display each error message that is added to the array. The second Do…Loop continues to iterate until all remaining error messages have been examined. Finally the Error.log file is closed.
Sub ProcessReportFile() Dim FileRef, strRptLine, intGetFirstBlankPosition, OutPutFile Dim intArrayCounter, IntErrLevel intArrayCounter = 0 If (FsoObject.FileExists(strSourDir)) Then Set FileRef = FsoObject.OpenTextFile(strSourDir, cForReading) Do Until Mid(strRptLine, 1, 4) = "Date" strRptLine = FileRef.ReadLine() Loop Do Until FileRef.AtEndOfStream FileRef.SkipLine() strRptLine = FileRef.ReadLine() If Left(strRptLine, 1) = "-" Then Exit Do End If intGetFirstBlankPosition = Instr(strRptLine, " 00") intErrLevel = Mid(strRptLine, intGetFirstBlankPosition + 3, 1) If intErrLevel <= 3 Then ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine End If If strDebug = "True" Then MsgBox "Storing '" & strRptLine & "' in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop FileRef.Close() Else astrReportArray(intArrayCounter) = "Error.log file was not available." End If End Sub
The RecordSummaryData() Subroutine
The RecordSummaryData() subroutine, shown on the next page, creates a new summary report file and writes its top-level header, followed by the Errors: section using the WriteLine() and WriteBlankLines() functions. A For…Each loop is then set up that processes the text strings stored in the astrReportArray and writes them to the Errors: section of the summary report file. The summary report file is then closed. Finally, if the script is run in debug mode, the MsgBox() function is used to display a pop-up message showing that this procedure has executed.
Sub RecordSummaryData() Dim intArrayCounter, OutPutFile, strMessage intArrayCounter = 0 Set OutPutFile = FsoObject.OpenTextFile(strDestFile, 2, "True") If strDebug = "True" Then MsgBox "Now writing to the Summary Report" End If OutPutFile.WriteLine "*******************************************************************************" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Consolidated Summary report for " & Date() OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "*******************************************************************************" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Errors:" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Date Time Code Description" For Each intArrayCounter In astrReportArray If Len(intArrayCounter) <> 0 Then OutPutFile.WriteLine intArrayCounter End If Next OutPutFile.Close() If strDebug = "True" Then MsgBox "Done writing to the Summary Report" End If End Sub
The WriteToEventLog() Subroutine
The WriteToEventLog() subroutine, shown below, instantiates the WshShell object and uses its LogEvent() method to record a message to the Windows application event log. The message is assigned a value of 4, making it an informational message. Finally, if the script is run in debug mode, the MsgBox() function is used to display a pop-up message showing that this procedure has executed.
Sub WriteToEventLog() Dim WshShl Set WshShl = WScript.CreateObject("WScript.Shell") '4 indicates an information message WshShl.LogEvent 4, "The Daily Error Log Analyzer Script is now running." If strDebug = "True" Then MsgBox "Event log message has been recorded" End If End Sub
Note |
To write error messages to the Windows application event log, you need to know how to work with the WshShell object's LogEvent() method. While this chapter uses this method to demonstrate how to write event log messages, it is not covered in great detail. For detailed instructions on how to work with the LogEvent() method, read Chapter 20, "Maintaining a 30-Day Log Archive." |
Creating the Daily Sales Report Analyzer
Like the Error log analyzer script, the Daily Sales report analyzer script reads the RptLog.ini file located in D:VBScriptsAnalyzers. Specifically, it processes the [DailySales] section as shown in the following example.
[DailySales] SourDir=d:Order_InventoryLogsDailySales.txt ReportOn=SummaryOnly EventLog=True DestFile=d:Order_InventorySummaryRpts Debug=False
Once its configuration settings have been read, the script processes the DailySales.txt file located in D:Order_InventoryLogs, as shown below.
******************************************************************************* Daily Sales 3/15/03 ******************************************************************************* Raw Sales: Part # Qty Description Cust # 1. 58694 12 Cordless temp reader 10034 2. 45643 2 200hp magnetic pump 10055 3. 17443 5 20 lb box of pump clips 10105 4. 10344 10 48 ounce solvent bottle 10003 5. 45643 1 200hp magnetic pump 10003 6. 17443 10 20 lb box of pump clips 10003 7. 58694 5 Cordless temp reader 10111 8. 10344 25 48 ounce solvent bottle 10054 9. 19365 2 3 speed electric drill 10034 10. 58694 2 Cordless temp reader 10103 Total number of sales orders = 10 ------------------------------------------------------------------------------- Sales summary by part number: Part # Qty Description 1. 58694 19 Cordless temp reader 2. 45643 3 200hp magnetic pump 3. 17443 15 20 lb box of pump clips 4. 10344 35 48 ounce solvent bottle 5. 19365 2 3-speed electric drill
The Daily Sales report analyzer script, shown below, is structured very similarly to the Error log analyzer script.
'************************************************************************* 'Script Name: Script 18.2.vbs 'Author: Jerry Ford 'Created: 03/22/03 'Description: This script retrieves configuration settings from an INI file, 'processes a Report file, and creates a Summary Report file. '************************************************************************* 'Initialization Section Option Explicit Dim FsoObject, strSourceFile, OpenFile, strInputLine, intCounter Dim strSourDir, strReportOn, strEventLog, strDestFile, strDebug ReDim astrReportArray(0) Const cForReading = 1 Const cForWriting = 2 Const cForAppending = 8 Set FsoObject = WScript.CreateObject("Scripting.FileSystemObject") strSourceFile = "d:VBScriptsAnalyzersRptLog.ini" 'Main Processing Section SetUpDefaults() ProcessIniFile() RefineOutputFileName() If strEventLog = "True" Then WriteToEventLog() End If ProcessReportFile() RecordSummaryData() 'Terminate script execution WScript.Quit() 'Procedure Section Sub SetUpDefaults() strSourDir = "d:Order_InventoryLogsDailySales.txt" strReportOn = "All" strEventLog = "False" strDestFile = "d:Order_InventorySummaryRpts" strDebug = "False" End Sub Sub ProcessIniFile() Dim strKeyName, intGetEqualsPosition If (FsoObject.FileExists(strSourceFile)) Then Set OpenFile = FsoObject.OpenTextFile(strSourceFile, cForReading) Do Until Mid(strInputLine, 1, 15) = "[DailySales]" strInputLine = OpenFile.ReadLine Loop Do Until OpenFile.AtEndOfStream = "True" strInputLine = OpenFile.ReadLine If Mid(strInputLine, 1, 1) = "[" Then Exit do End If If Len(strInputLine) <> 0 Then intGetEqualsPosition = Instr(strInputLine, "=") strKeyName = Mid(strInputLine, 1, intGetEqualsPosition - 1) Select Case strKeyName Case "SourDir" strSourDir = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "ReportOn" strReportOn = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "EventLog" strEventLog = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "DestFile" strDestFile = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "Debug" strDebug = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) End Select End If Loop OpenFile.Close() End If If strDebug = "True" Then MsgBox "strSourDir = " & strSourDir MsgBox "strReportOn = " & strReportOn MsgBox "strEventLog = " & strEventLog MsgBox "strDestFile = " & strDestFile MsgBox "strDebug = " & strDebug End If End Sub Sub RefineOutputFileName() Dim DataString DataString = Replace(Date(), "/", "-") strDestFile = strDestFile & DataString & "_SumRpt.txt" End Sub Sub ProcessReportFile() Dim FileRef, strRptLine, intGetFirstBlankPosition, OutPutFile Dim intArrayCounter intArrayCounter = 0 If (FsoObject.FileExists(strSourDir)) Then Set FileRef = FsoObject.OpenTextFile(strSourDir, cForReading) Do While False = FileRef.AtEndOfStream If strReportOn = "SummaryOnly" Then Do Until Mid(strRptLine, 1, 13) = "Sales summary" strRptLine = FileRef.ReadLine() Loop FileRef.SkipLine() FileRef.SkipLine() FileRef.SkipLine() Do Until FileRef.AtEndOfStream strRptLine = FileRef.ReadLine() intGetFirstBlankPosition = Instr(strRptLine, " ") strRptLine = Mid(strRptLine, intGetFirstBlankPosition + 1) ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine If strDebug = "True" Then MsgBox "Storing '" & strRptLine & "' in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop Else Do Until FileRef.AtEndOfStream strRptLine = FileRef.ReadLine() ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine If strDebug = "True" Then MsgBox "Storing " & strRptLine & " in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop End If Loop FileRef.Close() Else astrReportArray(intArrayCounter) = "DailySales.txt file was not available." End If End Sub Sub RecordSummaryData() Dim intArrayCounter, OutPutFile, strMessage intArrayCounter = 0 Set OutPutFile = FsoObject.OpenTextFile(strDestFile, 8) If strDebug = "True" Then MsgBox "Now writing to the Summary Report" End If OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "---------------------------------------------" & _ "----------------------------------" OutPutFile.WriteBlankLines(1) If strReportOn = "SummaryOnly" Then OutPutFile.WriteLine "Sales summary:" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Part # Qty Description" OutPutFile.WriteBlankLines(1) End If For Each intArrayCounter In astrReportArray OutPutFile.WriteLine intArrayCounter Next OutPutFile.Close() If strDebug = "True" Then MsgBox "Done writing to the Summary Report" End If End Sub Sub WriteToEventLog() Dim WshShl Set WshShl = WScript.CreateObject("WScript.Shell") '4 indicates an information message WshShl.LogEvent 4, "The Daily Sales Report Analyzer Script is now running." If strDebug = "True" Then MsgBox "Event log message has been recorded" End If End Sub
One of the areas where the Daily Sales report analyzer script differs from the Error log analyzer scripts is in its default variable settings, which are specified in the SetUpDefaults() subroutine. Also, the ProcessIniFile() subroutine has been modified to look for the [DailySales] header. In addition, the ProcessReportFile() subroutine has been modified to look for the Sales Summary section of the Daily Sales report and to process all of the entries in that section. One final significant difference between the two analyzers is in the RecordSummaryData() subroutine, where the summary report is opened in ForAppending mode instead of in ForWriting mode.
Creating the Daily Returns Report Analyzer
The Daily Returns report analyzer script is nearly identical to the Daily Sales report analyzer script. Both read the RptLog.ini file located in D:VBScriptsAnalyzers. However, the Daily Returns report analyzer script processes the [DailyReturns] section, as shown below.
[DailyReturns] SourDir=d:Order_InventoryLogsDailyReturns.txt ReportOn=SummaryOnly EventLog=True DestFile=d:Order_InventorySummaryRpts Debug=False
Once its configuration settings have been read, the script processes the DailyReturns.txt file, located in D:Order_InventoryLogs as shown below.
******************************************************************************* Daily Returns 3/15/03 ******************************************************************************* Raw Returns: Part # Qty Description Cust # 1. 58694 1 Cordless temp reader 10045 2. 17443 2 20 lb box of pump clips 10103 3. 10344 4 48 ounce solvent bottle 10111 4. 45643 1 200hp magnetic pump 10056 5. 19365 1 3 speed electric drill 10092 6. 58694 1 Cordless temp reader 10007 7. 17443 3 20 lb box of pump clips 10007 8. 17443 2 20 lb box of pump clips 10150 Total number of return orders = 8 ------------------------------------------------------------------------------- Return summary by part number: Part # Qty Description 1. 58694 2 Cordless temp reader 2. 17443 7 20 lb box of pump clips 3. 10344 4 48 ounce solvent bottle 4. 45643 1 200hp magnetic pump 5. 19365 1 3 speed electric drill
The Daily Returns report analyzer script, shown on the following page, is structured very similarly to the Daily Sales report analyzer script.
'************************************************************************* 'Script Name: Script 18.1.vbs 'Author: Jerry Ford 'Created: 03/22/03 'Description: This script retrieves configuration settings from an INI file, 'processes a Report file, and creates a Summary Report file. '************************************************************************* 'Initialization Section Option Explicit Dim FsoObject, strSourceFile, OpenFile, strInputLine, intCounter Dim strSourDir, strReportOn, strEventLog, strDestFile, strDebug ReDim astrReportArray(0) Const cForReading = 1 Const cForWriting = 2 Const cForAppending = 8 Set FsoObject = WScript.CreateObject("Scripting.FileSystemObject") strSourceFile = "d:VBScriptsAnalyzersRptLog.ini" 'Main Processing Section SetUpDefaults() ProcessIniFile() RefineOutputFileName() If strEventLog = "True" Then WriteToEventLog() End If ProcessReportFile() RecordSummaryData() 'Terminate script execution WScript.Quit() 'Procedure Section Sub SetUpDefaults() strSourDir = "d:Order_InventoryLogsDailyReturns.txt" strReportOn = "All" strEventLog = "False" strDestFile = "d:Order_InventorySummaryRpts" strDebug = "False" End Sub Sub ProcessIniFile() Dim strKeyName, intGetEqualsPosition If (FsoObject.FileExists(strSourceFile)) Then Set OpenFile = FsoObject.OpenTextFile(strSourceFile, cForReading) Do Until Mid(strInputLine, 1, 15) = "[DailyReturns]" strInputLine = OpenFile.ReadLine Loop Do Until OpenFile.AtEndOfStream = "True" strInputLine = OpenFile.ReadLine If Mid(strInputLine, 1, 1) = "[" Then Exit do End If If Len(strInputLine) <> 0 Then intGetEqualsPosition = Instr(strInputLine, "=") strKeyName = Mid(strInputLine, 1, intGetEqualsPosition - 1) Select Case strKeyName Case "SourDir" strSourDir = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "ReportOn" strReportOn = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "EventLog" strEventLog = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "DestFile" strDestFile = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "Debug" strDebug = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) End Select End If Loop OpenFile.Close() End If If strDebug = "True" Then MsgBox "strSourDir = " & strSourDir MsgBox "strReportOn = " & strReportOn MsgBox "strEventLog = " & strEventLog MsgBox "strDestFile = " & strDestFile MsgBox "strDebug = " & strDebug End If End Sub Sub RefineOutputFileName() Dim DataString DataString = Replace(Date(), "/", "-") strDestFile = strDestFile & DataString & "_SumRpt.txt" End Sub Sub ProcessReportFile() Dim FileRef, strRptLine, intGetFirstBlankPosition, OutPutFile Dim intArrayCounter intArrayCounter = 0 If (FsoObject.FileExists(strSourDir)) Then Set FileRef = FsoObject.OpenTextFile(strSourDir, cForReading) Do While False = FileRef.AtEndOfStream If strReportOn = "SummaryOnly" Then Do Until Mid(strRptLine, 1, 14) = "Return summary" strRptLine = FileRef.ReadLine() Loop FileRef.SkipLine() FileRef.SkipLine() FileRef.SkipLine() Do Until FileRef.AtEndOfStream strRptLine = FileRef.ReadLine() intGetFirstBlankPosition = Instr(strRptLine, " ") strRptLine = Mid(strRptLine, intGetFirstBlankPosition + 1) ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine If strDebug = "True" Then MsgBox "Storing '" & strRptLine & "' in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop Else Do Until FileRef.AtEndOfStream strRptLine = FileRef.ReadLine() ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine If strDebug = "True" Then MsgBox "Storing " & strRptLine & " in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop End If Loop FileRef.Close() Else astrReportArray(intArrayCounter) = "DailyReturns.txt file was not available." End If End Sub Sub RecordSummaryData() Dim intArrayCounter, OutPutFile, strMessage intArrayCounter = 0 Set OutPutFile = FsoObject.OpenTextFile(strDestFile, 8) If strDebug = "True" Then MsgBox "Now writing to the Summary Report" End If OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "--------------------------------------------" & _ "-----------------------------------" OutPutFile.WriteBlankLines(1) If strReportOn = "SummaryOnly" Then OutPutFile.WriteLine "Return summary:" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Part # Qty Description" OutPutFile.WriteBlankLines(1) End If For Each intArrayCounter In astrReportArray OutPutFile.WriteLine intArrayCounter Next OutPutFile.Close() If strDebug = "True" Then MsgBox "Done writing to the Summary Report" End If End Sub Sub WriteToEventLog() Dim WshShl Set WshShl = WScript.CreateObject("WScript.Shell") '4 indicates an information message WshShl.LogEvent 4, "The Daily Returns Report Analyzer Script is now running." If strDebug = "True" Then MsgBox "Event log message has been recorded" End If End Sub
The main differences between the Daily Sales and Daily Returns report analyzer scripts are as follows:
- Variable settings in the SetUpDefaults() subroutine have been modified.
- The ProcessIniFile() subroutine is set up to process the key=pair items located in the [DailyReturns] section.
Creating the Daily Production Report Analyzer
The Daily Production report analyzer is very similar to the Daily Sales and Daily Returns report analyzer scripts. All three read the RptLog.ini file located in D:VBScriptsAnalyzers. However, the Daily Production report analyzer processes the [DailyProduction] section, as shown below.
[DailyProduction] SourDir=d:Order_InventoryLogsDailyProduction.txt EventLog=True ReportOn=HardAndSupl DestFile=d:Order_InventorySummaryRpts Debug=False
Once its configuration settings have been read, the script processes the DailyProduction.txt file located in D:Order_InventoryLogs as shown below.
******************************************************************************* Daily Production 3/15/03 ******************************************************************************* Hardware: Part # Qty Description In Stock 1. 58694 10 Cordless temp reader 25 2. 45643 2 200hp magnetic pump 10 3. 19365 5 3 speed electric drill 10 ------------------------------------------------------------------------------- Supplies: Part # Qty Description In Stock 1. 17443 20 20 lb box of pump clips 100 2. 10344 100 48 ounce solvent bottle 250
The Daily Production report analyzer script, shown below, is structured very similarly to the Daily Sales and Daily Returns report analyzer scripts.
'************************************************************************* 'Script Name: Script 18.4.vbs 'Author: Jerry Ford 'Created: 03/22/03 'Description: This script retrieves configuration settings from an INI file, 'processes a Report file, and creates a Summary Report file. '************************************************************************* 'Initialization Section Option Explicit Dim FsoObject, strSourceFile, OpenFile, strInputLine, intCounter Dim strSourDir, strReportOn, strEventLog, strDestFile, strDebug ReDim astrReportArray(0) Const cForReading = 1 Const cForWriting = 2 Const cForAppending = 8 Set FsoObject = WScript.CreateObject("Scripting.FileSystemObject") strSourceFile = "d:VBScriptsAnalyzersRptLog.ini" 'Main Processing Section SetUpDefaults() ProcessIniFile() RefineOutputFileName() If strEventLog = "True" Then WriteToEventLog() End If ProcessReportFile() RecordSummaryData() 'Terminate script execution WScript.Quit() 'Procedure Section Sub SetUpDefaults() strSourDir = "d:Order_InventoryLogsDailyProduction.txt" strReportOn = "HardAndSupl" strEventLog = "False" strDestFile = "d:Order_InventorySummaryRpts" strDebug = "False" End Sub Sub ProcessIniFile() Dim strKeyName, intGetEqualsPosition If (FsoObject.FileExists(strSourceFile)) Then Set OpenFile = FsoObject.OpenTextFile(strSourceFile, cForReading) Do Until Mid(strInputLine, 1, 17) = "[DailyProduction]" strInputLine = OpenFile.ReadLine Loop Do Until OpenFile.AtEndOfStream = "True" strInputLine = OpenFile.ReadLine If Mid(strInputLine, 1, 1) = "[" Then Exit do End If If Len(strInputLine) <> 0 Then intGetEqualsPosition = Instr(strInputLine, "=") strKeyName = Mid(strInputLine, 1, intGetEqualsPosition - 1) Select Case strKeyName Case "SourDir" strSourDir = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "ReportOn" strReportOn = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "EventLog" strEventLog = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "DestFile" strDestFile = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) Case "Debug" strDebug = Mid(strInputLine, intGetEqualsPosition + 1, _ Len(strInputLine)) End Select End If Loop OpenFile.Close() End If If strDebug = "True" Then MsgBox "strSourDir = " & strSourDir MsgBox "strReportOn = " & strReportOn MsgBox "strEventLog = " & strEventLog MsgBox "strDestFile = " & strDestFile MsgBox "strDebug = " & strDebug End If End Sub Sub RefineOutputFileName() Dim DataString DataString = Replace(Date(), "/", "-") strDestFile = strDestFile & DataString & "_SumRpt.txt" End Sub Sub ProcessReportFile() Dim FileRef, strRptLine, intGetFirstBlankPosition, OutPutFile Dim intArrayCounter intArrayCounter = 0 If (FsoObject.FileExists(strSourDir)) Then Set FileRef = FsoObject.OpenTextFile(strSourDir, cForReading) 'Do While False = FileRef.AtEndOfStream If Instr(1, strReportOn, "Hard") Then Do Until Mid(strRptLine, 1, 8) = "Hardware" strRptLine = FileRef.ReadLine() Loop FileRef.SkipLine() FileRef.SkipLine() FileRef.SkipLine() Do Until FileRef.AtEndOfStream strRptLine = FileRef.ReadLine() intGetFirstBlankPosition = Instr(strRptLine, " ") strRptLine = Mid(strRptLine, intGetFirstBlankPosition + 2) If Left(strRptLine, 1) = "-" Then Exit Do End If ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine If strDebug = "True" Then MsgBox "Storing '" & strRptLine & "' in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop End If If Instr(1, strReportOn, "Supl") Then Do Until Mid(strRptLine, 1, 8) = "Supplies" strRptLine = FileRef.ReadLine() Loop FileRef.SkipLine() FileRef.SkipLine() FileRef.SkipLine() Do Until FileRef.AtEndOfStream strRptLine = FileRef.ReadLine() intGetFirstBlankPosition = Instr(strRptLine, " ") strRptLine = Mid(strRptLine, intGetFirstBlankPosition + 2) If Left(strRptLine, 1) = "-" Then Exit Do End If ReDim Preserve astrReportArray(intArrayCounter) astrReportArray(intArrayCounter) = strRptLine If strDebug = "True" Then MsgBox "Storing '" & strRptLine & "' in the astrReportArray array" End If intArrayCounter = intArrayCounter + 1 Loop End If 'Loop FileRef.Close() Else astrReportArray(intArrayCounter) = "DailyProducton.txt file was not available." End If End Sub Sub RecordSummaryData() Dim intArrayCounter, OutPutFile, strMessage intArrayCounter = 0 Set OutPutFile = FsoObject.OpenTextFile(strDestFile, 8) If strDebug = "True" Then MsgBox "Now writing to the Summary Report" End If OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "--------------------------------------------" & _ "-----------------------------------" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Daily Production Summary" OutPutFile.WriteBlankLines(1) OutPutFile.WriteLine "Part # Qty Description In Stock" OutPutFile.WriteBlankLines(1) For Each intArrayCounter In astrReportArray If Len(intArrayCounter) <> 0 Then OutPutFile.WriteLine intArrayCounter End If Next OutPutFile.Close() If strDebug = "True" Then MsgBox "Done writing to the Summary Report" End If End Sub Sub WriteToEventLog() Dim WshShl Set WshShl = WScript.CreateObject("WScript.Shell") '4 indicates an information message WshShl.LogEvent 4, "The Daily Production Report Analyzer Script is now running." If strDebug = "True" Then MsgBox "Event log message has been recorded" End If End Sub
The main differences between the Daily Production and the Daily Sales and Daily Returns report analyzer scripts are as follows:
- Variable settings in the SetUpDefaults() subroutine have been modified.
- The ProcessIniFile() subroutine is set up to process the key=pair items located in the [DailyProduction] section.
- The ProcessReportFile() subroutine is designed to look for and process the Hardware and Software sections of the Daily Production report.
Examining the Order Inventory Summary Report
The four report and log analyzer scripts will ultimately be set up to run on an automated basis. The scripts will be run sequentially, with the Error report processed, first followed by the Daily Sales and Daily Returns reports and finally the Daily Production reports. The following sample summary report shows how a typical summary report will look once all the scripts have been run.
******************************************************************************* Consolidated Summary report for 3/23/2003 ******************************************************************************* Errors: Date Time Code Description 12:15:44 3/15/03 001 Unable to access card reader on device wkstn442 14:00:14 3/15/03 001 No inventory for part # 58694 - unable to fill order 39312 16:16:46 3/15/03 003 Unable to print summary rpt on master printer (no paper) ------------------------------------------------------------------------------- Sales summary: Part # Qty Description 58694 19 Cordless temp reader 45643 3 200hp magnetic pump 17443 15 20 lb box of pump clips 10344 35 48 ounce solvent bottle 19365 2 3 speed electric drill ------------------------------------------------------------------------------- Return summary: Part # Qty Description 58694 2 Cordless temp reader 17443 7 20 lb box of pump clips 10344 4 48 ounce solvent bottle 45643 1 200hp magnetic pump 19365 1 3 speed electric drill ------------------------------------------------------------------------------- Daily Production Summary Part # Qty Description In Stock 58694 10 Cordless temp reader 25 45643 2 200hp magnetic pump 10 19365 5 3 speed electric drill 10 17443 20 20 lb box of pump clips 100 10344 100 48 ounce solvent bottle 250
Summary
In this chapter, you learned how to read and process report and log files. You developed a collection of scripts that processed these report and log files based on settings stored in an INI file and then created a summary report, consolidating the information gathered from the report and log files. As a result, you have demonstrated an understanding of how to apply VBScript to solving a real-world problem that would have involved a great deal more effort to solve using a more traditional programming language.