home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * Filename: RptToRepConv.CC *
- * Last Modified: 11/18/97 *
- * Author: Jim Sare *
- * *
- * Created under agreement with KSoft, Inc. for Borland International, Inc. *
- * *
- * Copyright (c) 1997 Borland International, Inc. All Rights Reserved. *
- * *
- ******************************************************************************/
- *
- /******************************************************************************
- * Assumptions: - CRW .RPT will be mapped to a single VdB PageTemplate. *
- * - CRW Band Line text will be streamed to VdB .REP file as HTML.*
- * - CRW Field objects will be streamed to VdB .REP file as VdB *
- * Text class instances. *
- * - CRW Line objects will be streamed to VdB .REP file as VdB *
- * Line class instances. *
- * - CRW Image objects will be streamed to VdB .REP file as VdB *
- * Image class instances. *
- * - CRW OLE objects will not be translated, but will be flagged *
- * as exceptions in the error log streamed to the VdB .REP *
- * header. *
- * - CRW .RPT comments (CRW menu Format|Report Title...) will be *
- * streamed as comments in the VdB .REP header. *
- * - CRW .RPT title (CRW menu Format|Report Title...) will be *
- * streamed to VdB .REP file. *
- * - Labels (standard and user-defined) and other multi-column *
- * reports are supported. *
- * Note: In most cases, it may be necessary to manually touch-up the resulting *
- * .REP file. A 100% conversion is not possible due to differences *
- * between .RPT and .REP capabilities, and ability to map .RPT elements *
- * to .REP elements during the conversion process. *
- ******************************************************************************/
- //
- // See RptToRepConv.H for associated Win32 API constants
- // and other constants and preprocessor macros used in this file.
- // All preprocessor labels used in this file are in upper case.
- //
- #include RptToRepConv.H
- //
- CLASS ReportConverter(oForm)
-
- // Prototype necessary Win32 API functions.
- If Type("BL_CreateFont") # "FP"
- extern CHANDLE BL_CreateFont(CINT, CINT, CINT, CINT, CINT,;
- CLOGICAL, CLOGICAL, CLOGICAL,;
- CINT, CINT, CINT, CINT, CINT, CPTR) GDI32;
- From "CreateFontA"
- EndIf
- If Type("BL_DeleteObject") # "FP"
- extern CLOGICAL BL_DeleteObject(CHANDLE) GDI32;
- From "DeleteObject"
- EndIf
- If Type("BL_GetDC") # "FP"
- extern CLONG BL_GetDC(CLONG) User32;
- From "GetDC"
- EndIf
- If Type("BL_GetDeviceCaps") # "FP"
- extern CINT BL_GetDeviceCaps(CHANDLE, CINT) GDI32;
- From "GetDeviceCaps"
- EndIf
- If Type("BL_GetTextExtentPoint32") # "FP"
- extern CLOGICAL BL_GetTextExtentPoint32(CHANDLE, CSTRING, CLONG, CPTR) gdi32;
- From "GetTextExtentPoint32A"
- EndIf
- If Type("BL_lReleaseDC") # "FP"
- extern CLOGICAL BL_lReleaseDC(CHANDLE, CHANDLE) User32;
- From "ReleaseDC"
- EndIf
- If Type("BL_SelectObject") # "FP"
- extern CHANDLE BL_SelectObject(CHANDLE, CHANDLE) GDI32;
- From "SelectObject"
- EndIf
- If Type("BL_SetMapMode") # "FP"
- extern CINT BL_SetMapMode(CHANDLE, CINT) GDI32;
- From "SetMapMode"
- EndIf
- If Type("BL_UpdateWindow") # "FP"
- extern CLOGICAL BL_UpdateWindow(CHANDLE) User32;
- From "UpdateWindow"
- EndIf
-
- this.CriticalError = False // Internal flag for critical erors
- this.oForm = oForm // Reference to wizard form
- this.aQBEFiles = oForm.oQuery // Reference to query parser array
- this.lRelatedTables = False // Flag for related tables
- this.ProgressObject = Null // oRef to Progress object on form
- this.ShowProgress = False // Flag to not show/show progress
- this.aErrors = New Array() // Conversion exception log
- this.oError = New RBException(oForm) // Exception status object
- this.InFilename = "" // Input .RPT/.RPL filename
- this.hInFile = 0 // Handle to input .RPT file
- this.nFSize = 0 // Input .RPT/.RPL file size
- this.nFPos = 0 // Input .RPT/.RPL file pointer
- this.RecID = 0 // Input record type
- this.RecTypeDescr = "Unknown Record" // Input record description
- this.RecLen = 0 // Input record length (variable)
- this.xREC = "" // Input record data
- this.xSIZE = SPACE(4) // Buffer Win32 API SIZE structure
- this.OutFilename = "" // Output .REP filename
- this.hOutFile = 0 // Handle to output .REP file
- this.hDC = 0 // Handle to printer DC
- this.ItemWidth = 0 // Width of text item
- this.ItemHeight = 0 // Height of text item
- this.oReport = Null // Main report array
- this.oPrinter = Null // Report Printer object
- this.oPageTemplate = Null // Report PageTemplate object
- this.ObjectCount = 0 // Count of objects in report + 1
- this.StreamCount = 0 // Count of objects streamed
- this.TextCount = 0 // Count of bandline text characters
- this.SaveVarHeight = 0 // Buffer for variable height indicator
-
- this.StreamAll = False // Diagnostic only!!!
- this.Debug = False // Diagnostic only!!!
-
- this.oDetailBand = Null // Reference to detail band object
- this.CurrentBand = Null // Reference to current band object
- this.CurrentLine = Null // Reference to current line object
- this.CurrentObject = Null // Reference to current object being built
- this.cStreamQuery = "" // Name of Query containing StreamSource.RowSet
- this.aGroups = New Array() // Array of report groups
- this.CurrentTable = "" // Temp buffer for table name
- this.OrderBy = "" // Order By field
- this.OrderByTable = "" // Order By table
- this.SortOrder = "ASC" // Default sort order
- this.GroupBy = "" // Group By field
- this.GroupByTable = "" // Group By table
-
- this.aCRWBands = New Array() // Array of CRW Band objects
- this.aLines = New Array() // Array of VdB Line objects
- this.aShapes = New Array() // Array of VdB Shape objects
- this.aQueries = New Array() // Array of VdB Query objects
-
- this.BandID = 0 // Band type identifier
- this.ReadingLine = False // Flag for reading CRWLine data
- this.RawHText = "" // Band Line text accumulator
- this.aaColors = New RGBTripleColors() // Color conversion array
- this.CurColor = HTML_DEFCOLOR // Current font color
- this.NewColor = 0 // New font color
- this.CurFName = HTML_DEFFACE // Current FontName
- this.NewFName = "" // New FontName
- this.CurFSize = HTML_DEFFNSZ // Current FontSize
- this.NewFSize = 0 // New FontSize
- this.CurFSizeTag = "0" // Current FontSize tag
- this.CurFBold = HTML_DEFBOLD // Current FontBold
- this.NewFBold = 0 // New FontBold
- this.CurFItal = HTML_DEFITAL // Current FontItalic
- this.NewFItal = False // New FontItalic
- this.CurFUnln = HTML_DEFUNLN // Current FontUnderline
- this.NewFUnln = False // New FontUnderline
-
- this.PreDefLabel = False // Flag pre-defined label type
- this.MultiColumn = False // Flag multi-columns (labels and user-defined)
- this.ColWidth = 0 // Column width
- this.ColHeight = 0 // Column height
- this.ColGapHorz = 0 // Horizontal gap between columns
- this.ColGapVert = 0 // Vertical gap between entries
- this.ColSequence = 0 // Rendering sequence (Across/Down)
-
- this.ReadingRptHeader = False // Flag for reading rpt header band
- this.ReadingGrpHeader = False // Flag for reading grp header band
- this.ReadingRptDetail = False // Flag for reading rpt detail band
- this.ReadingGrpFooter = False // Flag for reading grp footer band
- this.ReadingGrandTotal = False // Flag for reading grand total band
- this.ReadingRptFooter = False // Flag for reading rpt footer band
- this.ReadingGrpInfo = False // Flag for reading grp field
-
- this.lLogColorError = True // Prevent multiple color error logs
-
- this.FenceVersion = True // Fence .RPT/.RPL version range
- this.FenceLo = 3.0 // Low .RPT/.RPL version
- this.FenceHi = 3.1 // High .RPT/.RPL version
-
- // Protect unpublished custom property members
- PROTECT aaColors, aCRWBands, aGroups, aLines, aQBEFiles, aQueries, aShapes,;
- BandID, ColGapHorz, ColGapVert, ColHeight, ColSequence, ColWidth,;
- CriticalError, CurColor, CurFBold, CurFItal, CurFName, CurFSize,;
- CurFSizeTag, CurFUnLn, CurrentBand, CurrentLine, CurrentObject,;
- CurrentTable, Debug, FenceHi, FenceLo, FenceVersion
- PROTECT GroupBy, GroupByTable, HDC, hInFile, hOutFile, ItemHeight,;
- ItemWidth, lLogColorError, lRelatedTables, Multicolumn, NewColor,;
- NewFBold, NewFItal, NewFName, NewFSize, NewFUnLn, nFPos, nFSize,;
- ObjectCount, oDetailBand, oError, oForm, oGroup, oPageTemplate,;
- oPrinter, OrderBy, OrderByTable, oReport, PreDefLabel
- PROTECT RawHText, ReadingGrandTotal, ReadingGrpFooter, ReadingGrpHeader,;
- ReadingGrpInfo, ReadingLine, ReadingRptDetail, ReadingRptFooter,;
- ReadingRptHeader, RecID, RecLen, RecTypeDescr, SaveVarHeight,;
- SortOrder, StreamAll, StreamCount, xREC, xSIZE
-
- // Protect unpublished custom method members
- PROTECT AddToReport, ConvertFormula, ConvertField, GetItemSize, ReadRecord,;
- SkipNulls, StreamComments, StreamBannerLine, ArrangeZOrder;
- StreamHeader, StreamObject, UpdateProgress, FieldType
-
- FUNCTION BuildReport
- // Check .RPT file format and build in-memory image of report.
- // Returns: True if good .RPT file format and no fatal errors detected,
- // False if bad format or fatal error detected.
- LOCAL xRECHDR, aBands, aLines, cTemp, lTemp, nTemp, oTemp, nPQuality
- LOCAL nBandTop, DownCount, nTop, nLeft, nHorz, nVert
-
- BL_UpdateWindow(this.oForm.hWND)
- this.oError.ClearError() // Initialize error object
- Try
- this.hInFile = fOpen((this.InFilename), "R")
- Catch(Exception x) // Catch any error generated by fOpen and cancel run
- this.oError.OnError(x)
- RETURN False
- EndTry
- // Now the entire .RPT file is read. Errors are caught by the Catch clauses
- // at the end of this function, a message is displayed describing the error,
- // and the conversion run is cancelled.
- // Program-detected errors are Thrown to the RBException Catch clause.
- // VdB-detected hard errors are caught by the Exception Catch clause.
- //
- // Any modifications to this code should preserve this scheme to ensure
- // that the device context handle used during the conversion process is
- // released to avoid GDI loss, and to ensure that the file handle to the
- // .RPT file is closed.
- Try
- this.nFSize = FSize(this.InFilename)
- this.oError.Filename = Program()
- // Verify correct .RPT file format
- xRECHDR = fRead(this.hInFile, 4)
- // First 2 bytes should be 0x1000 (LSB/MSB order)
- this.oError.Code = 10014
- If MAKEU32(xRECHDR, 1) = HToI("E011CFD0") // Report contains OLE item
- this.oError.LineNo = LineNo() - 1
- Throw this.oError
- EndIf
- this.oError.Code = 10001
- If MAKEU16(xRECHDR, 1) # HToI("1000") // Invalid record type
- this.oError.LineNo = LineNo() - 1
- Throw this.oError
- EndIf
- this.RecLen = MAKEU16(xRECHDR, 3)
- If this.RecLen < 4 // Invalid record length
- this.oError.LineNo = LineNo() - 1
- Throw this.oError
- EndIf
- // Now read entire file and verify record length integrity
- fSeek(this.hInFile, 0) // Rewind input file to beginning
- this.nFPos = 0
- this.ObjectCount = 0
- // Update Wizard form progress display
- this.UpdateProgress((this.nFPos / this.nFSize) * 100)
- cTemp = this.OutFilename
- If RAt("\", cTemp) > 0
- cTemp = Right(cTemp, Len(cTemp) - RAt("\", cTemp))
- EndIf
- If RAt(".", cTemp) > 0
- cTemp = Left(cTemp, RAt(".", cTemp) - 1)
- EndIf
- // Obtain device context used during conversion to determine
- // item display sizes.
- this.hDC = BL_GetDC(_app.FrameWin.hWND)
- // The .RPT file specifies coordinates in twips.
- // We will write the .REP file specifying twips also.
- // So we need to map the device context to twips.
- BL_SetMapMode(this.hDC, MM_TWIPS)
- // The xReport template object is the main .REP array cluster into
- // which all other template objects are stored. Some of these template
- // objects are also containers for other template objects.
- this.oReport = New xReport(cTemp)
- // Instantiate basic template objects used in all .REP files. They will
- // be added to the oReport .REP array cluster later.
- this.oPrinter = New xPrinter()
- this.oStreamSource =;
- New xStreamSource(this.oReport.NextName("STREAMSOURCE"))
- this.oPageTemplate =;
- New xPageTemplate(this.oReport.NextName("PAGETEMPLATE"))
- this.oStreamFrame =;
- New xStreamFrame(this.oPageTemplate.NextName("STREAMFRAME"))
- this.oGroup = Null
- this.CurrentContainer = this.oReport
- this.CurrentBand = Null
- this.CurrentLine = Null
- this.CurrentObject = Null
- // Read entire .RPT file in DO...ENDDO loop.
- // The .RPT file contains variable-length records of the format:
- // XXXX - 2 bytes describing the record type (RecID)
- // YYYY - 2 bytes containing the record length (RecLen)
- // Z..Z - (RecLen) bytes of data.
- // Note that not all data in all records is used during the
- // conversion process. We only attempt to extract those data
- // elements that are critical to basic VdB report operation.
- Do While Not fEOF(this.hInFile)
- xRECHDR = fRead(this.hInFile, 4)
- this.nFPos += 4
- this.RecID = MAKEU16(xRECHDR, 1)
- this.RecLen = MAKEU16(xRECHDR, 3)
- Do Case
- Case this.RecID = 0 // Garbage Area
- this.SkipNulls()
-
- Case this.RecID = HToI("1000") // Report Descriptor
- this.RecTypeDescr = "Report Descriptor"
- this.ReadRecord()
- this.ReportDescriptor = this.xREC
- this.VersionRPT = CHARNUM(MAKEU16(this.xREC, 1)) +;
- "." +;
- CHARNUM(MAKEU16(this.xREC, 3))
- If this.FenceVersion And;
- (Val(this.VersionRPT) < this.FenceLo Or;
- Val(this.VersionRPT) > this.FenceHi)
- this.oError.LineNo = LineNo() - 1
- this.oError.Filename = Program()
- this.oError.Code = 10002
- Throw this.oError
- EndIf
-
- // Do NOT remove the following 2 lines!
- // Record Type 1001 has subrecords inside it.
- Case this.RecID = HToI("1001") // Data View Descriptor Block
- this.RecTypeDescr = "Data View Cluster"
-
- Case this.RecID = HToI("1002") // Band Descriptor (New band)
- // This case is encountered once for each report band.
- // The first time it occurs, all data table information in
- // RecID's 2xxx have previously been read. The first band to
- // occur in the .RPT file is the header band. So when the
- // header band is encountered (ReadingRptHeader), the data
- // table information from the .RPT can be synced with the
- // information from the .QBE file specified in the .RPT file
- // if any .QBE file was specified.
- this.RecTypeDescr = "Band Descriptor"
- // Add any previously extracted objects to .REP stream.
- this.AddToReport()
- this.ReadRecord()
- this.CurrentLine = Null
- this.ReadingLine = False
- // Add a new band container
- this.aCRWBands.Add(New CRWBand(this.xREC))
- this.BandID = MAKEU16(this.xREC, 3)
- this.ReadingRptHeader = this.BandID = CRWBAND_RPTHEADER
- // If the current band being read is the report header band
- If this.ReadingRptHeader
- // Verify formula count is correct. If not, corrupt file.
- If this.oReport.FormulaCount #;
- this.oReport.aaFormulas.Count()
- this.oError.LineNo = LineNo() - 1
- this.oError.Filename = Program()
- this.oError.Code = 10011
- Throw this.oError
- EndIf
- // Query objects are contained in the report class.
- this.CurrentContainer = this.oReport
- // Reading of data table information is now complete.
- // Now merge the data information from the report
- // with the information from the query (if any).
- //
- // If the report is based on a .QBE file
- If this.oReport.aTables.Size = this.aQBEFiles.Size / 8
- For nTemp = 1 To this.oReport.aTables.Size
- lTemp = (this.oReport.aTables.Size + 1) - nTemp
- this.oReport.aTables[lTemp].Alias =;
- this.aQBEFiles[nTemp, QALIAS]
- EndFor
- EndIf
- If this.aQBEFiles.Size > 6
- For nTemp = 1 To this.aQBEFiles.Size / 8
- For lTemp = 1 To this.oReport.aTables.Size
- If this.oReport.aTables[lTemp].Alias ==;
- this.aQBEFiles[nTemp, QALIAS]
- this.oReport.aTables[lTemp].TableName =;
- this.aQBEFiles[nTemp, QTABLENAME]
- this.oReport.aTables[lTemp].Alias =;
- this.aQBEFiles[nTemp, QALIAS]
- this.oReport.aTables[lTemp].ParentTable =;
- this.aQBEFiles[nTemp, QPARENTTABLE]
- this.oReport.aTables[lTemp].ParentField =;
- this.aQBEFiles[nTemp, QPARENTFIELD]
- this.oReport.aTables[lTemp].Order =;
- this.aQBEFiles[nTemp, QORDER]
- this.oReport.aTables[lTemp].Error =;
- this.aQBEFiles[nTemp, QERROR]
- this.oReport.aTables[lTemp].Tag =;
- this.aQBEFiles[nTemp, QTAG]
- EndIf
- EndFor
- EndFor
- EndIf
- // If the report is based on a single table (ie; .QBE not used)
- If this.oReport.aTables.Size = 1 And;
- Upper(Right(this.oReport.DataFile, 4)) # ".QBE"
- this.oReport.aTables[1].TableName = this.oReport.DataFile
- EndIf
- // Now set up the Query objects based on information
- // obtained from the .RPT and .QBE file (if any)
- For nTemp = this.oReport.aTables.Size To 1 Step -1
- If Len(this.oReport.aTables[nTemp].TableName) = 0
- this.oReport.aTables[nTemp].TableName =;
- this.oReport.DataPath +;
- this.oReport.aTables[nTemp].Alias
- EndIf
- // Create a new query template object
- this.CurrentObject =;
- New xQuery(this.oReport.NextName(;
- this.oReport.aTables[nTemp].Alias))
- // Save it in an array of queries for later reference
- this.aQueries.Add(this.CurrentObject)
- this.CurrentObject.TableName =;
- this.oReport.aTables[nTemp].TableName
- this.CurrentObject["Top"] = 50
- this.CurrentObject["Left"] = 50 +;
- ((this.oReport.aTables.Size - nTemp) * 500)
- this.CurrentObject["SQL"] = "'SELECT * FROM " + '"' +;
- this.oReport.aTables[nTemp].TableName + ["']
- oTemp = this.CurrentObject
- // Add the Query template to the .REP array cluster
- // as a child object of the report class.
- this.AddToReport()
- this.CurrentContainer = oTemp
- If Not IsBlank(this.oReport.aTables[nTemp].Tag)
- this.CurrentObject = New xRowSet()
- this.CurrentObject["IndexName"] = '"' +;
- this.oReport.aTables[nTemp].Tag + '"'
- this.oReport["AutoSort"] = False
- this.CurrentContainer.Indexed = True
- EndIf
- // If this table is a child table in a relation, set
- // the links in IndexName, MasterRowset and MasterFields.
- If Not IsBlank(this.oReport.aTables[nTemp].ParentTable)
- this.lRelatedTables = True
- For lTemp = 1 To this.aQueries.Size
- If this.oReport.aTables[nTemp].ParentTable $;
- this.aQueries[lTemp].xName
- If Type("this.CurrentObject") == "U"
- this.CurrentObject = New xRowSet()
- EndIf
- this.CurrentObject["MasterRowset"] = "form." +;
- this.oReport.aTables[nTemp].ParentTable +;
- "1.Rowset"
- this.CurrentObject["MasterFields"] = '"' +;
- this.oReport.aTables[nTemp].ParentField +;
- '"'
- Exit
- EndIf
- EndFor
- EndIf
- this.AddToReport()
- this.CurrentContainer = this.oReport
- EndFor // Repeat to create a Query template for each table
- // Message streamed to .REP header if related tables exist
- If this.lRelatedTables
- this.aErrors.Add(this.oForm.oLang.iText("TableRelations"))
- EndIf
- // Add the Printer template to the .REP array cluster
- // as a child object of the report class.
- this.CurrentObject = this.oPrinter
- this.AddToReport()
- // Add the PageTemplate template to the .REP array cluster
- // as a child object of the report class.
- this.CurrentObject = this.oPageTemplate
- this.AddToReport()
- // Make the PageTemplate the current container
- this.CurrentContainer = this.oPageTemplate
- // Report header is implemented at the top of
- // the PageTemplate.
- EndIf
- this.ReadingGrpHeader = this.BandID = CRWBAND_GRPHEADER
- // If the current band being read is a group header band
- If this.ReadingGrpHeader
- // Make the StreamSource the current container
- this.CurrentContainer = this.oStreamSource
- // Instantiate a Group template
- this.oGroup =;
- New xGroup(this.oStreamSource.NextName("GROUP"))
- this.oGroup["GroupBy"] = '"' + this.GroupBy + '"'
- this.aGroups.Add(this.oGroup) // Save for later reference
- this.aGroups.CurrentGroup = this.aGroups.Size
- // Add the Group to the .REP array cluster
- // as a child of the StreamSource
- this.CurrentObject = this.oGroup
- this.AddToReport()
- this.CurrentContainer = this.oGroup.HeaderBand
- EndIf
- this.ReadingRptDetail = this.BandID = CRWBAND_RPTDETAIL
- // If the current band being read is the report detail band
- If this.ReadingRptDetail
- // Time to add the StreamSource to the .REP array cluster
- this.CurrentContainer = this.oReport
- this.CurrentObject = this.oStreamSource
- this.AddToReport()
- this.CurrentContainer = this.oStreamSource
- // Add a detail band as a child of the StreamSource
- this.CurrentObject = New xBand("DETAIL")
- this.AddToReport()
- // Make the detail band the current container
- this.CurrentContainer = this.oStreamSource.Objects;
- [this.oStreamSource.Objects.Size]
- // Save a reference to the detail band for later use
- this.oDetailBand = this.CurrentContainer
- EndIf
- this.ReadingGrpFooter = this.BandID = CRWBAND_GRPFOOTER
- // If the current band being read is a group footer band
- If this.ReadingGrpFooter
- this.oGroup = this.aGroups[this.aGroups.CurrentGroup--]
- this.CurrentContainer = this.oGroup.FooterBand
- EndIf
- this.ReadingGrndTotal = this.BandID = CRWBAND_GRNDTOTAL
- // If the current band being read is a grand total band
- If this.ReadingGrndTotal
- // Implement grand total band as ReportGroup.FooterBand
- this.CurrentContainer = this.oReport
- this.oReportGroup = New xReportGroup()
- this.CurrentObject = this.oReportGroup
- this.AddToReport()
- this.CurrentContainer = this.oReportGroup.FooterBand
- EndIf
- this.ReadingRptFooter = this.BandID = CRWBAND_RPTFOOTER
- // If the current band being read is the report footer band
- If this.ReadingRptFooter
- // Report footer is implemented at the bottom of
- // the PageTemplate
- this.CurrentContainer = this.oPageTemplate
- EndIf
- this.CurrentBand = this.aCRWBands[this.aCRWBands.Size]
- this.CurrentBand.ID = this.BandID
- this.CurrentBand.Container = this.CurrentContainer
- this.CurrentObject = this.CurrentBand
-
- Case this.RecID = HToI("1003") // CRW BandLine
- // This case is encountered once for each .RPT band line
- // to indicate the start of a new line. After 1003, other
- // record types (100A, 1013, 102A, 1009, etc) are encountered
- // which further describe the band line and any text placed
- // directly on the band line. The end of the band line is
- // indicated by 1009.
- this.RecTypeDescr = "Band Line"
- // Add any previously constructed object to the .REP array cluster
- this.AddToReport()
- this.ReadRecord()
- this.ReadingLine = True
- aLines = this.aCRWBands[this.aCRWBands.Size]
- aLines.Add(New CRWLine())
- this.CurrentLine = aLines[aLines.Size]
- this.ObjectsLine = this.CurrentLine
- this.CurrentLine.BandID = this.CurrentBand.ID
- this.CurrentObject = this.CurrentLine
- // Initialize HTML tracking variables to defaults
- this.RawHText = ""
- this.CurColor = HTML_DEFCOLOR
- this.CurFName = HTML_DEFFACE
- this.CurFBold = HTML_DEFBOLD
- this.CurFItal = HTML_DEFITAL
- this.CurFUnln = HTML_DEFUNLN
-
- Case this.RecID = HToI("1004") // CRW Band Line Text Count
- // Indicates the number of characters (including spaces)
- // contained directly on the band line.
- this.RecTypeDescr = "Band Line Text Count"
- this.ReadRecord()
- // Save character count for case 1005
- this.TextCount = MAKEU16(this.xREC, 1)
-
- Case this.RecID = HToI("1005") // CRW BandLine Text
- // This is the actual text contained directly on the band line.
- this.RecTypeDescr = "Band Line Text"
- this.ReadRecord()
- cTemp = STRIPNULL(this.xREC)
- // If the length doesn't match, the .RPT file is corrupt.
- If Len(cTemp) # this.TextCount
- this.oError.LineNo = LineNo() - 1
- this.oError.Filename = Program()
- this.oError.Code = 10012
- Throw this.oError
- EndIf
- // Save the text
- this.RawHText += cTemp
- // Compute the height and width of the text.
- nTemp = this.GetItemSize(cTemp)
- // If the text height is greater than the line height
- If nTemp > this.CurrentLine.Height
- this.CurrentLine.Height = nTemp
- EndIf
- // Add the width of the text to the current line's width
- this.CurrentLine.Width += this.ItemWidth
- // Add the text to the current line's HTML text stream.
- this.CurrentLine.HTMLText += cTemp
-
- Case this.RecID = HToI("1006") // CRW Text Field
- this.RecTypeDescr = "Text Field"
- // Add any previously created template to the .REP array cluster
- this.AddToReport()
- this.ReadRecord()
- // Create a new Text template
- this.CurrentObject = New xText()
- nTemp = MAKEU16(this.xREC, 1)
- // If the text field's Left value is not equal to 0.
- If nTemp # 0
- this.CurrentObject["Left"] = nTemp
- EndIf
- // Extract the text field's width
- this.CurrentObject["Width"] = MAKEU16(this.xREC, 3)
- // Extract SuppressIfDuplicate
- lTemp = MAKEU16(this.xREC, 5) # 0
- If lTemp
- this.CurrentObject["SuppressIfDuplicate"] = True
- EndIf
- // Extract Hide When Printing
- If MAKEU16(this.xREC, 7) # 0
- this.CurrentObject["Visible"] = False
- EndIf
- // Extract horizontal alignment
- nTemp = MAKEU16(this.xREC, 9)
- If nTemp > 1
- this.CurrentObject["AlignHorizontal"] = Int(nTemp - 1)
- EndIf
- this.SaveVarHeight = MAKEU16(this.xREC, 77)
-
- Case this.RecID = HToI("1007") // Unknown
- // Associated to various objects.
- this.RecTypeDescr = "Unknown Record Type"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("1008") // CRW Text Field and Image DataLink
- // Text field is DataLinked to a table field
- // - OR -
- // an ORDER BY/GROUP BY specification.
- this.RecTypeDescr = "Text Field DataLink"
- this.ReadRecord()
- this.xREC = STRIPNULL(this.xREC)
- this.xREC = Right(this.xREC,;
- Len(this.xREC) - At(".", this.xREC))
- cTemp = SubStr(this.xREC, RAt(">", this.xREC) + 1)
- // Also see 1010 and 1012 for the following.
- If Type("this.CurrentObject") == "O" // Text field DataLink
- oTemp = this.CurrentObject
- // Assign a name to the object as 'TEXT' + table field name
- oTemp.xName =;
- this.CurrentContainer.NextName(oTemp.xClassName + cTemp)
- If oTemp.xClassName == "IMAGE"
- cTemp = this.ConvertField(this.xREC)
- cTemp = SubStr(cTemp, At("FORM.", Upper(cTemp)))
- oTemp["DataSource"] = Left(cTemp, At("]", cTemp))
- Else
- // Map the Text property using VdB RowSet syntax
- oTemp["Text"] = this.ConvertField(this.xREC)
- // Get field data type
- lTemp = this.FieldType(this.xREC)
- // If numeric data type, right-align it (CRW numeric default)
- // if the alignment was not specified in the .RPT
- If lTemp == "N" And Not oTemp.IsKey("AlignHorizontal")
- oTemp["AlignHorizontal"] = 2
- EndIf
- // If memo field and print on multiple lines
- If lTemp == "M" And this.SaveVarHeight = 0
- this.SaveVarHeight = 1
- EndIf
- // If print on multiple lines
- If this.SaveVarHeight > 0
- oTemp["VariableHeight"] = True
- Else
- oTemp["Wrap"] = False
- EndIf
- // If this is an aggregate text field (See 1010), then
- // remap the Text property for aggregate computation.
- If Not IsBlank(oTemp.AgType)
- If Left(oTemp.AgType, 2) # "UN"
- cTemp = this.ConvertField(this.xREC)
- If this.ReadingGrpHeader Or this.ReadingGrpFooter
- Do While At("THIS.FORM.", Upper(cTemp)) > 0
- cTemp = Stuff(cTemp,;
- At("THIS.FORM.", Upper(cTemp)),;
- 10, "this.parent.parent.")
- EndDo
- oTemp["Text"] = "{|| this.Parent.Parent." +;
- oTemp.AgType + "(" + cTemp + ")}"
- ElseIf this.ReadingGrndTotal
- Do While At("THIS.FORM.", Upper(cTemp)) > 0
- cTemp = Stuff(cTemp,;
- At("THIS.FORM.", Upper(cTemp)),;
- 10, "this.parent.")
- EndDo
- oTemp["Text"] = "{|| this.Parent.Parent." +;
- oTemp.AgType + "(" + cTemp + ")}"
- EndIf
- Else // Unsupported aggregate function
- // Place error msg in Text property
- oTemp["Text"] = '"' + oTemp.AgError + '"'
- // and in messages streamed to report header.
- this.aErrors.Add(oTemp.AgError + " - " + oTemp.xName)
- EndIf
- EndIf
- oTemp.SetFont((this))
- EndIf
- ElseIf this.ReadingOrdInfo // Order By/Group By (Also see 1011)
- this.OrderBy = cTemp
- cTemp = Left(this.xREC, At("->", this.xREC) - 1)
- // Add the OrderBy field to the correct table field array
- For nTemp = 1 To this.oReport.aTables.Size
- If this.oReport.aTables[nTemp].Alias == cTemp
- this.oReport.aTables[nTemp].aOrders.Add(this.OrderBy,;
- this.SortOrder)
- If this.ReadingGrpInfo // See 1012
- this.oReport.aTables[nTemp].aGroups.Add(this.OrderBy)
- this.GroupBy = this.OrderBy
- this.cStreamQuery =;
- Left(this.xREC, At("->", this.xREC) - 1) + "1"
- EndIf
- Exit
- EndIf
- EndFor
- this.ReadingOrdInfo = False
- this.ReadingGrpInfo = False
- EndIf
-
- Case this.RecID = HToI("1009") // Band Line End
- // As 1003 indicates the start of a band line, 1009 indicates
- // the end of the band line. It is now necessary to assemble
- // the elements needed to construct a Text template and assign
- // the HTML text stream to the Text property.
- this.RecTypeDescr = "Band Line End"
- this.ReadRecord()
- this.ReadingLine = False
- // If there is actual text other than just white space
- If Len(Trim(this.RawHText)) > 0
- // Create a new Text template to carry the band line text
- // to the .REP array cluster.
- this.CurrentObject = New xText()
- this.CurrentObject.xName =;
- this.CurrentContainer.NextName("TEXT")
- // Set the Height to the greatest height of the text
- // elements on the band line.
- this.CurrentObject["Height"] = this.CurrentLine.Height
- // Set the Width to the accumulated width of the text
- // elements on the band line.
- this.CurrentObject["Width"] = this.CurrentLine.Width
- // Set the default color.
- this.CurrentObject["ColorNormal"] = '"BtnText"'
- // Turn off wrap
- this.CurrentObject["Wrap"] = False
- // Now close the HTML text tags as necessary.
- If this.CurColor # HTML_DEFCOLOR
- this.CurrentLine.HTMLText += '</font>'
- EndIf
- If this.CurFUnln # HTML_DEFUNLN
- this.CurrentLine.HTMLText += '</u>'
- EndIf
- If this.CurFItal # HTML_DEFITAL
- this.CurrentLine.HTMLText += '</i>'
- EndIf
- If this.CurFBold # HTML_DEFBOLD
- this.CurrentLine.HTMLText += '</b>'
- EndIf
- If this.CurFSize # HTML_DEFFNSZ
- this.CurrentLine.HTMLText += '</font>'
- EndIf
- If this.CurFName # HTML_DEFFACE
- this.CurrentLine.HTMLText += '</font>'
- EndIf
- this.CurrentObject["Text"] = this.CurrentLine.HTMLText +;
- "</pre>'"
- // Add the new Text template to the .REP array cluster.
- this.AddToReport()
- Else // No real text on the line
- // Setup a Blank to take up vertical space.
- this.CurrentObject =;
- New xBlank(this.CurrentContainer.NextName("BLANK"))
- EndIf
- this.RawHText = ""
-
- Case this.RecID = HToI("100A") // Font descriptor
- // This case is used to describe the font attributes
- // (name, size, bold, italic, underline, strikeout) for
- // text fields and band line text.
- this.RecTypeDescr = "Font Descriptor"
- this.ReadRecord()
- this.FontRec = this.xREC
- // Extract required font information
- this.FontName = Left(this.xREC, At(Chr(0), this.xREC) - 1)
- this.FontSize = MAKEU16(this.xREC, 39)
- this.FontBold = MAKEU16(this.xREC, 42)
- nTemp = MAKE8(this.xREC, 41)
- this.FontItalic = BitSet(nTemp, 0)
- this.FontUnderline = BitSet(nTemp, 1)
- this.FontStrikeout = BitSet(nTemp, 2)
- // Compute text height using the font settings
- nTemp = this.GetItemSize("H")
- If nTemp > this.CurrentLine.Height
- // Adjust line height accordingly
- this.CurrentLine.Height = nTemp
- EndIf
- // If currently reading a band line (ie; 1003 but no 1009 yet),
- // then adjust HTML stream for any font changes from current
- // font settings.
- If this.ReadingLine
- If this.CurFName # this.FontName And;
- this.CurFName # HTML_DEFFACE
- this.CurrentLine.HTMLText += '</font>'
- this.CurFName = HTML_DEFFACE
- EndIf
- If this.CurFName = HTML_DEFFACE And;
- this.FontName # this.CurFName
- this.CurrentLine.HTMLText += '<font face="' +;
- this.FontName + '">'
- EndIf
- this.CurFName = this.FontName
- Do Case
- Case this.FontSize > 33
- cTemp = "+4"
- Case this.FontSize > 21
- cTemp = "+3"
- Case this.FontSize > 15
- cTemp = "+2"
- Case this.FontSize > 11
- cTemp = "+1"
- Case this.FontSize > 9
- cTemp = "0"
- Case this.FontSize > 7
- cTemp = "-1"
- Otherwise
- cTemp = "-2"
- EndCase
- If this.CurFSizeTag # cTemp And this.CurFSizeTag # "0"
- this.CurrentLine.HTMLText += '</font>'
- this.CurFSizeTag = "0"
- EndIf
- If this.CurFSizeTag = "0" And cTemp # this.CurFSizeTag
- this.CurrentLine.HTMLText += '<font size=' + cTemp + '>'
- EndIf
- this.CurFSizeTag = cTemp
-
- If this.CurFBold # this.FontBold And;
- this.CurFBold # HTML_DEFBOLD
- this.CurrentLine.HTMLText += '</b>'
- this.CurFBold = HTML_DEFBOLD
- EndIf
- If this.CurFBold = HTML_DEFBOLD And;
- this.FontBold # this.CurFBold
- this.CurrentLine.HTMLText += '<b>'
- EndIf
- this.CurFBold = this.FontBold
-
- If this.CurFItal # this.FontItalic And;
- this.CurFItal # HTML_DEFITAL
- this.CurrentLine.HTMLText += '</i>'
- this.CurFItal = HTML_DEFITAL
- EndIf
- If this.CurFItal = HTML_DEFITAL And;
- this.FontItalic # this.CurFItal
- this.CurrentLine.HTMLText += '<i>'
- EndIf
- this.CurFItal = this.FontItalic
-
- If this.CurFUnln # this.FontUnderline And;
- this.CurFUnln # HTML_DEFUNLN
- this.CurrentLine.HTMLText += '</u>'
- this.CurFUnln = HTML_DEFUNLN
- EndIf
- If this.CurFUnln = HTML_DEFUNLN And;
- this.FontUnderline # this.CurFUnln
- this.CurrentLine.HTMLText += '<u>'
- EndIf
- this.CurFUnln = this.FontUnderline
- EndIf
-
- Case this.RecID = HToI("100B") // Formula count
- this.RecTypeDescr = "Formula Count"
- this.ReadRecord()
- // Save formula count for later verification after
- // all formulas are read from .RPT file.
- this.oReport.FormulaCount = MAKEU16(this.xREC, 1)
-
- Case this.RecID = HToI("100C") // Formula descriptor
- // We can skip this. We only need the formula name and formula.
- this.RecTypeDescr = "Formula Descriptor"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("100D") // Formula name
- // Record ID 100D is used to identify the formula name.
- // It is also used later to associate the formula name to
- // a text object.
- this.RecTypeDescr = "Formula Name"
- this.ReadRecord()
- cTemp = Left(this.xREC, Len(this.xREC) - 1)
- // Drop extraneous carriage returns and linefeeds.
- Do While Right(cTemp, 1) = LF Or;
- Right(cTemp, 1) = CR
- cTemp = Left(cTemp, Len(cTemp) - 1)
- EndDo
- If this.oReport.aaFormulas.Count() # this.oReport.FormulaCount
- // If we are still reading formulas
- this.FormulaName = cTemp
- ElseIf Type("this.CurrentObject") # "U"
- // This formula name is linking a formula to a text field
- oTemp = this.CurrentObject
- // Now that we know the current Text template will not be
- // linked to a table field, assign a name to it using
- // 'TEXT' + next available number.
- oTemp.xName = this.CurrentContainer.NextName("TEXT")
- // Assign the Text property to the actual formula.
- oTemp["Text"] = this.oReport.aaFormulas[cTemp]
- // Stream a formula message to .REP header.
- this.aErrors.Add(this.oForm.oLang.iText("HasFormulas") +;
- " - " + oTemp.xName)
- // If this is an aggregate field based on a formula (See 1010)
- // then remap the Text property to the aggregate operation.
- If Not IsBlank(oTemp.AgType)
- If Left(oTemp.AgType, 2) # "UN"
- cTemp = oTemp["Text"]
- If this.ReadingGrpHeader Or this.ReadingGrpFooter
- Do While At("THIS.FORM.", Upper(cTemp)) > 0
- cTemp = Stuff(cTemp,;
- At("THIS.FORM.", Upper(cTemp)),;
- 10, "this.parent.parent.")
- EndDo
- oTemp["Text"] = "{|| this.Parent.Parent." +;
- oTemp.AgType + "(" + cTemp + ")}"
- ElseIf this.ReadingGrndTotal
- Do While At("THIS.FORM.", Upper(cTemp)) > 0
- cTemp = Stuff(cTemp,;
- At("THIS.FORM.", Upper(cTemp)),;
- 10, "this.parent.")
- EndDo
- oTemp["Text"] = "{|| this.Parent.Parent." +;
- oTemp.AgType + "(" + cTemp + ")}"
- EndIf
- Else
- oTemp["Text"] = '"' + oTemp.AgError + '"'
- EndIf
- EndIf
- // Set the font attributes and height for the Text template.
- // See the class RepObjBase::SetFont method
- oTemp.SetFont((this))
- // If print on multiple lines
- If this.SaveVarHeight > 0
- oTemp["VariableHeight"] = True
- Else
- oTemp["Wrap"] = False
- EndIf
- Else
- this.aErrors.Add(this.oForm.oLang.iText("HasGroupFormula") +;
- " - " + cTemp)
- EndIf
-
- Case this.RecID = HToI("100E") // Formula
- // This is the actual formula referenced by the name
- // specified in record ID 100D. These formulas are saved
- // in an array (oReport.aaFormulas) for later use when
- // linking to objects in the report.
- this.RecTypeDescr = "Formula"
- this.ReadRecord()
- cTemp = Left(this.xREC, Len(this.xREC) - 1)
- // Drop extraneous carriage returns and linefeeds.
- Do While Right(cTemp, 1) = LF Or;
- Right(cTemp, 1) = CR
- cTemp = Left(cTemp, Len(cTemp) - 1)
- EndDo
- // Save the formula for later use.
- this.oReport.aaFormulas[this.FormulaName] =;
- this.ConvertField(this.ConvertFormula(cTemp))
-
- Case this.RecID = HToI("100F") // Record selection criteria
- // This case describes any record selection criteria
- // specified in the .RPT file.
- this.RecTypeDescr = "Record Selection Criteria"
- this.ReadRecord()
- cTemp = STRIPNULL(this.xREC)
- If Not Empty(cTemp)
- this.aErrors.Add(this.oForm.oLang.iText("RecSelCrit"))
- this.aErrors.Add(" " + cTemp)
- EndIf
-
- Case this.RecID = HToI("1010") // Aggregate Summary Operation Type
- // This case specifies an aggregate operation type to be
- // applied to a table field or formula linked to a Text field.
- this.RecTypeDescr = "Aggregate Summary Operation Type"
- this.ReadRecord()
- nTemp = MAKEU16(this.xREC, 1)
- Do Case
- Case nTemp = 0 // Sum
- this.CurrentObject.AgType = "agSum"
- Case nTemp = 1 // Average
- this.CurrentObject.AgType = "agAverage"
- Case nTemp = 2 // Sample Variance
- this.CurrentObject.AgType = "agVariance"
- Case nTemp = 3 // Sample Standard Deviation
- this.CurrentObject.AgType = "agStdDeviation"
- Case nTemp = 4 // Max
- this.CurrentObject.AgType = "agMax"
- Case nTemp = 5 // Min
- this.CurrentObject.AgType = "agMin"
- Case nTemp = 6 // Count
- this.CurrentObject.AgType = "agCount"
- // These CRW aggregates are not supported
- Case nTemp = 7 // Population Variance
- this.CurrentObject.AgType = "UNSUPPORTED"
- this.CurrentObject.AgError =;
- this.oForm.oLang.iText("agPopVar")
- Case nTemp = 8 // Population Standard Deviation
- this.CurrentObject.AgType = "UNSUPPORTED"
- this.CurrentObject.AgError =;
- this.oForm.oLang.iText("agPopDev")
- Case nTemp = 9 // Distinct Count
- this.CurrentObject.AgType = "UNSUPPORTED"
- this.CurrentObject.AgError =;
- this.oForm.oLang.iText("agDisCnt")
- Otherwise // I have no idea.
- this.CurrentObject.AgType = "UNKNOWN"
- this.CurrentObject.AgError =;
- this.oForm.oLang.iText("agUnknown")
- EndCase
-
- Case this.RecID = HToI("1011") // Report Fields Sort Direction
- // This case specifies the sort direction.
- // (Also see 1008)
- this.RecTypeDescr = "Report Fields Sort Direction"
- this.ReadRecord()
- this.ReadingOrdInfo = True
- this.SortOrder = IIf(MAKEU16(this.xREC, 1) = 0, "ASC", "DESC")
-
- Case this.RecID = HToI("1012") // Group Section Sort Direction
- // This case specifies the sort direction for a group.
- // (Also see 1008)
- this.RecTypeDescr = "Group Section Sort Direction"
- this.AddToReport()
- this.ReadRecord()
- this.ReadingOrdInfo = True
- this.ReadingGrpInfo = True
- this.SortOrder = IIf(MAKEU16(this.xREC, 7) = 0, "ASC", "DESC")
-
- Case this.RecID = HToI("1013") // CRW BandLine.Text Tab
- // Each occurrence of this case adds a tab character
- // to the current HTML text stream for the current
- // band line.
- this.RecTypeDescr = "Band Line.Text Tab"
- this.ReadRecord(True)
- this.CurrentLine.HTMLText += Chr(9)
- this.RawHText += Chr(9)
-
- Case this.RecID = HToI("1014") // Special Field Type
- // This case specifies special field types in the .RPT file.
- this.RecTypeDescr = "Special Field Type"
- this.ReadRecord()
- oTemp = this.CurrentObject
- // Now that we know the current Text template will not be
- // linked to a table field, assign a name to it using
- // 'TEXT' + next available number.
- oTemp.xName = this.CurrentContainer.NextName("TEXT")
- // Extract special field type and process based on type
- nTemp = MAKEU16(this.xREC, 1)
- Do Case
- Case nTemp = 0 // Date
- oTemp["Text"] = "{|| DToC(Date())}"
- Case nTemp = 4 // Record Number (unsupported)
- oTemp["Text"] = '"' +;
- this.oForm.oLang.iText("sfRecNo") + '"'
- this.aErrors.Add(this.oForm.oLang.iText("sfRecNo") +;
- " - " + oTemp.xName)
- Case nTemp = 5 // Page Number
- oTemp["Text"] = "{|| Str(form.reportPage, 5)}"
- Case nTemp = 6 // Group Number (unsupported)
- oTemp["Text"] = '"' +;
- this.oForm.oLang.iText("sfGrpNum") + '"'
- this.aErrors.Add(this.oForm.oLang.iText("sfGrpNum") +;
- " - " + oTemp.xName)
- Otherwise // (unknown special field)
- oTemp["Text"] = '"' +;
- this.oForm.oLang.iText("sfUnknown") + '"'
- this.aErrors.Add(this.oForm.oLang.iText("sfUnknown") +;
- " - " + oTemp.xName)
- EndCase
- // Set the font attributes and height for the Text template.
- // See the class RepObjBase::SetFont method
- oTemp.SetFont((this))
-
- Case this.RecID = HToI("1016") // Printer
- // This case specifies printer settings.
- // See the xPrinter class for additional information.
- // For Win API programmers, this data is in a DEVMODE
- // structure format. Consult Win API documentation.
- this.RecTypeDescr = "Printer DEVMODE"
- this.ReadRecord()
- // Extract printer settings and save to Printer template.
- nTemp = MAKEU16(this.xREC, IND_DMPRINTQUALITY)
- nPQuality = IIf(nTemp < 201, 1,;
- IIf(nTemp < 301, 2,;
- IIf(nTemp < 600, 3, 4)))
- nTemp = Int(MAKEU32(this.xREC, IND_DMFIELDS))
- this.oPrinter["Color"] =;
- IIf(BitAnd(nTemp, DM_COLOR) > 0,;
- MAKEU16(this.xREC, IND_DMCOLOR), 0)
- this.oPrinter["Copies"] =;
- IIf(BitAnd(nTemp, DM_COPIES) > 0,;
- MAKEU16(this.xREC, IND_DMCOPIES), 1)
- this.oPrinter["Duplex"] =;
- IIf(BitAnd(nTemp, DM_DUPLEX) > 0,;
- MAKEU16(this.xREC, IND_DMDUPLEX), 0)
- this.oPrinter["Orientation"] =;
- IIf(BitAnd(nTemp, DM_ORIENTATION) > 0,;
- MAKEU16(this.xREC, IND_DMORIENTATION), 0)
- this.oPrinter["PaperSize"] =;
- IIf(BitAnd(nTemp, DM_ORIENTATION) > 0,;
- MAKEU16(this.xREC, IND_DMPAPERSIZE),;
- DMPAPER_LETTER)
- this.oPrinter["PaperSource"] =;
- IIf(BitAnd(nTemp, DM_DEFAULTSOURCE) > 0,;
- MAKEU16(this.xREC, IND_DMDEFAULTSOURCE),;
- DMBIN_MANUAL)
- this.oPrinter["PrinterName"] = '"' +;
- Left(this.xREC, At(Chr(0), this.xREC) - 1) + '"'
- this.oPrinter["PrinterSource"] = 2
- this.oPrinter["Resolution"] =;
- IIf(BitAnd(nTemp, DM_PRINTQUALITY) > 0,;
- nPQuality, 0)
- this.oPrinter["TrueTypeFonts"] =;
- IIf(BitAnd(nTemp, DM_TTOPTION) > 0,;
- MAKEU16(this.xREC, IND_DMTTOPTION), 0)
-
- Case this.RecID = HToI("1017") // Text Field border style BG color
- // This case describes a Text field's border style and
- // background color.
- this.RecTypeDescr = "Border Style and BG Color"
- this.ReadRecord()
- // Extract and process border style.
- nTemp = 0
- If MAKEU16(this.xREC, 13) = 1
- cStyle = "6" // Drop Shadow
- Else
- For x = 1 To 8 Step 2
- nTemp = BitOr(nTemp, MAKEU16(this.xREC, x))
- EndFor
- Do Case
- Case (nTemp = 1) Or (nTemp = 3) Or (nTemp = 4)
- cStyle = "4" // Single
- Case nTemp = 2
- cStyle = "5" // Double
- Otherwise
- cStyle = "0" // Default
- EndCase
- EndIf
- If Type("this.CurrentObject") == "O"
- // Assign border style to current Text template.
- this.CurrentObject["BorderStyle"] = cStyle
- // VdB Text.ColorNormal is for font color,
- // not for background color. VdB report Text
- // class does not implement background colors.
- // So pass message to .REP file header.
- nTemp = RGBTriple(this.xREC, 19)
- If nTemp # HToI("FFFFFF") And this.lLogColorError
- this.aErrors.Add(this.oForm.oLang.iText("BkColorNotSupported"))
- this.lLogColorError = False
- EndIf
- EndIf
-
- Case this.RecID = HToI("1018") // Text Field Text
- // This case specifies the text to be displayed in
- // a Text field (ie; a text label)
- this.RecTypeDescr = "Text Field Text"
- this.ReadRecord()
- cTemp = STRIPNULL(this.xREC)
- // Drop extraneous carriage returns and line feeds from text end
- Do While (Asc(Right(cTemp, 1)) = 10) Or;
- (Asc(Right(cTemp, 1)) = 13)
- cTemp = Left(cTemp, Len(cTemp) - 1)
- EndDo
- oTemp = this.CurrentObject
- // Now that we know the current Text template will not be
- // linked to a table field, assign a name to it using
- // 'TEXT' + next available number.
- oTemp.xName = this.CurrentContainer.NextName("TEXT")
- oTemp["Text"] = '"' + cTemp + '"'
- // Set the font attributes and height for the Text template.
- // See the class RepObjBase::SetFont method
- oTemp.SetFont((this))
- // If print on multiple lines
- If this.SaveVarHeight > 0
- oTemp["VariableHeight"] = True
- Else
- oTemp["Wrap"] = False
- EndIf
-
- Case this.RecID = HToI("1019") // Report Title
- // This case specifies the report title.
- this.RecTypeDescr = "Report Title"
- this.ReadRecord()
- this.oReport["Title"] = '"' + STRIPNULL(this.xREC) + '"'
-
- Case this.RecID = HToI("101A") // Report Comments
- // This case specifies the report comments.
- // These comments will be streamed to the .REP file header.
- this.RecTypeDescr = "Report Comments"
- this.ReadRecord()
- this.oReport.Comments = STRIPNULL(this.xREC)
-
- Case this.RecID = HToI("101B") // Image Object
- // This case describes an Image object in the .RPT file.
- this.RecTypeDescr = "Image Object"
- this.AddToReport()
- this.ReadRecord()
- // Create a new Image template.
- this.CurrentObject =;
- New xImage(this.CurrentContainer.NextName("IMAGE"))
- // Extract properties and assign to Image template.
- nTemp = MAKEU16(this.xREC, 23)
- If nTemp # 0
- this.CurrentObject["Left"] = nTemp
- EndIf
- this.CurrentObject["Width"] = MAKEU16(this.xREC, 11)
- nTemp = MAKEU16(this.xREC, 25)
- If nTemp # 0
- this.CurrentObject["Top"] = nTemp
- EndIf
- this.CurrentObject["Height"] = MAKEU16(this.xREC, 13)
- this.CurrentObject["Alignment"] = 0
-
- Case this.RecID = HToI("101C") // Image related
- // Don't need this. Already have necessary items.
- this.RecTypeDescr = "Image Related"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("101D") // Image DataSource file
- // This case specifies the image file to be associated
- // with an image object.
- this.RecTypeDescr = "Image DataSource"
- this.ReadRecord()
- If Type("this.CurrentObject") == "O"
- cTemp = STRIPNULL(this.xREC)
- If Not File(cTemp) // If file does not exist
- If RAt("\", cTemp) > 0
- cTemp = Right(cTemp, Len(cTemp) - RAt("\", cTemp))
- EndIf
- cTemp = this.oReport.DataPath + cTemp
- EndIf
- If Not File(cTemp) // If file does not exist in data path
- If RAt("\", cTemp) > 0
- cTemp = Right(cTemp, Len(cTemp) - RAt("\", cTemp))
- EndIf
- cTemp = ALLTRIM(this.oForm.SourcePathField.Value) +;
- cTemp
- EndIf
- If Not File(cTemp) // If file does not exist in .RPT path
- cTemp = STRIPNULL(this.xREC) // Let developer reconcile
- this.aErrors.Add(this.oForm.oLang.iText("NoImageFile") +;
- " - " + this.CurrentObject.xName)
- EndIf
- this.CurrentObject["Datasource"] = '"FILENAME ' +;
- cTemp + '"'
- EndIf
-
- Case this.RecID = HToI("101E") // Image Bits
- // This case is an internal store of the actual image in the .RPT
- this.RecTypeDescr = "Image Bits"
- this.ReadRecord(True, True)
- this.xREC = ""
-
- Case this.RecID = HToI("1020") // Image as OLE - Object ID
- // This case should not be encountered because
- // .RPT files containing OLE are screened at the beginning.
- this.RecTypeDescr = "Image as OLE - Object ID"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("1022") // Page Margins
- // This case specifies the page margins
- this.RecTypeDescr = "Page Margins"
- this.ReadRecord()
- this.oPageTemplate["MarginLeft"] = MAKEU16(this.xREC, 1)
- this.oPageTemplate["MarginRight"] = MAKEU16(this.xREC, 3)
- this.oPageTemplate["MarginTop"] = MAKEU16(this.xREC, 5)
- this.oPageTemplate["MarginBottom"] = MAKEU16(this.xREC, 7)
-
- Case this.RecID = HToI("1023") // Column Dimensions
- // This case specifies the dimensions used to
- // create a multi-column report (ie; labels).
- this.RecTypeDescr = "Column Dimensions"
- this.ReadRecord()
- this.MultiColumn = True
- this.ColWidth = MAKEU16(this.xREC, 1)
- this.ColHeight = MAKEU16(this.xREC, 3)
- this.ColGapHorz = MAKEU16(this.xREC, 5)
- this.ColGapVert = MAKEU16(this.xREC, 7)
- // 0 = Across/Down, otherwise Down/Across.
- this.ColSequence = MAKEU16(this.xREC, 9)
-
- Case this.RecID = HToI("1024") // Line related
- // Don't need this. Already have necessary items.
- this.RecTypeDescr = "Line Related"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("1025") // Box related
- // Don't need this. Already have necessary items.
- this.RecTypeDescr = "Box Related"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("1027") // Label Descriptor
- // This case specifies the predefined label type
- // (ie; 5160, etc) or user-defined labels.
- this.RecTypeDescr = "Label Descriptor"
- this.ReadRecord()
- cTemp = Left(this.xREC, this.RecLen - 1)
- If (Len(cTemp) = 0) Or (At(Chr(0), cTemp) = 0)
- cTemp = "User Defined Label" + Chr(0)
- EndIf
- this.oReport.LabelType = Left(cTemp, At(Chr(0), cTemp) - 1)
- this.oReport.LabelStyle = Right(cTemp, Len(cTemp) -;
- At(Chr(0), cTemp))
-
- Case this.RecID = HToI("1028") // Line Object
- // This case adds a Line to the report.
- this.RecTypeDescr = "Line Object"
- this.AddToReport()
- this.ReadRecord()
- // Create a Line template.
- oTemp = New xLine("")
- // Extract and process the pen style.
- nTemp = MAKEU16(this.xREC, 5)
- Do Case
- Case nTemp = 1
- oTemp["Pen"] = 0
- Case nTemp = 3
- oTemp["Pen"] = 1
- Case nTemp = 4
- oTemp["Pen"] = 2
- Otherwise
- this.aErrors.Add(this.oForm.oLang.iText("PenTypeNotSupported"))
- EndCase
- // Extract and process remaining properties
- oTemp["Width"] = MAKEU16(this.xREC, 7)
- cTemp = RGBTRIPLE(this.xREC, 9)
- // Use JavaScript color tag if available or hexadecimal if not
- oTemp["ColorNormal"] = '"' + IIf(this.aaColors.IsKey(cTemp),;
- this.aaColors[cTemp],;
- '0x' + cTemp) + '"'
- oTemp.TopBandIndex = MAKEU16(this.xREC, 13) + 1
- oTemp.TopLineIndex = MAKEU16(this.xREC, 15) + 1
- oTemp["Left"] = MAKEU16(this.xREC, 17)
- oTemp["Top"] = MAKEU16(this.xREC, 19)
-
- oTemp.BotBandIndex = MAKEU16(this.xREC, 21) + 1
- oTemp.BotLineIndex = MAKEU16(this.xREC, 23) + 1
- oTemp["Right"] = MAKEU16(this.xREC, 25)
- oTemp["Bottom"] = MAKEU16(this.xREC, 27)
- // Save a reference to the Line template. It will be used
- // later to assign the Line to the correct container after
- // the report band heights are justified.
- this.aLines.Add(oTemp)
-
- Case this.RecID = HToI("1029") // Box Object (shape)
- // This case adds a box object (Shape) to the report.
- this.RecTypeDescr = "Box Object (shape)"
- this.AddToReport()
- this.ReadRecord()
- // Create a Shape template.
- oTemp = New xShape("")
- // Extract and process the pen style.
- nTemp = MAKEU16(this.xREC, 5)
- Do Case
- Case nTemp = 1
- oTemp["PenStyle"] = 0
- Case nTemp = 3
- oTemp["PenStyle"] = 1
- Case nTemp = 4
- oTemp["PenStyle"] = 2
- Otherwise
- this.aErrors.Add(this.oForm.oLang.iText("PenTypeNotSupported"))
- EndCase
- // Extract and process remaining properties
- oTemp["PenWidth"] = MAKEU16(this.xREC, 7)
- cTemp = RGBTRIPLE(this.xREC, 9)
- lTemp = RGBTRIPLE(this.xREC, 39)
- If Not (cTemp == "000000" And lTemp == "000000")
- // Use JavaScript color tag if available or hexadecimal if not
- oTemp["ColorNormal"] = '"' + IIf(this.aaColors.IsKey(cTemp),;
- this.aaColors[cTemp],;
- '0x' + cTemp) + "/" +;
- IIf(this.aaColors.IsKey(lTemp),;
- this.aaColors[lTemp],;
- '0x' + lTemp) + '"'
- EndIf
- oTemp.TopBandIndex = MAKEU16(this.xREC, 45) + 1
- oTemp.TopLineIndex = MAKEU16(this.xREC, 47) + 1
- oTemp["Left"] = MAKEU16(this.xREC, 49)
- oTemp["Top"] = MAKEU16(this.xREC, 51)
-
- oTemp.BotBandIndex = MAKEU16(this.xREC, 53) + 1
- oTemp.BotLineIndex = MAKEU16(this.xREC, 55) + 1
- oTemp["Width"] = MAKEU16(this.xREC, 57) - oTemp["Left"]
- oTemp["Height"] = MAKEU16(this.xREC, 59)
- // Save a reference to the Shape template. It will be used
- // later to assign the Shape to the correct container after
- // the report band heights are justified.
- this.aShapes.Add(oTemp)
-
- Case this.RecID = HToI("102A") // Item Color
- // This case is used to specify the color used for the current
- // font, or the current line, or the current shape, etc.
- this.RecTypeDescr = "Item Color"
- this.ReadRecord()
- nTemp = MAKEU24(this.xREC, 1)
- cTemp = RGBTRIPLE(this.xREC, 1)
- If this.ReadingLine
- If this.CurColor # nTemp And this.CurColor # HTML_DEFCOLOR
- this.CurrentLine.HTMLText += '</font>'
- this.CurColor = HTML_DEFCOLOR
- EndIf
- If this.CurColor = HTML_DEFCOLOR And nTemp # this.CurColor
- // Use JavaScript color tag if available or hexadecimal if not
- this.CurrentLine.HTMLText += '<font color="' +;
- IIf(this.aaColors.IsKey(cTemp),;
- this.aaColors[cTemp],;
- "#" + cTemp) + '">'
- EndIf
- this.CurColor = nTemp
- ElseIf Type("this.CurrentObject") == "O"
- // Use JavaScript color tag if available or hexadecimal if not
- this.CurrentObject["ColorNormal"] = '"' +;
- IIf(this.aaColors.IsKey(cTemp),;
- this.aaColors[cTemp],;
- '0x' + cTemp) + '"'
- EndIf
-
- Case this.RecID = HToI("102B") // Image as OLE - Formatting
- // This case should not be encountered because
- // .RPT files containing OLE are screened at the beginning.
- this.RecTypeDescr = "Image as OLE - Formatting"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("2003") // ?? and Database|Verify Before Printing
- // This case contains no significant information
- this.RecTypeDescr = "?? and Database|Verify Before Printing"
- this.ReadRecord(True)
-
- Case this.RecID = HToI("2004") // Data File
- // If the .RPT is single-table based, this is the table filename.
- // If the .RPT is .QBE based, this is the .QBE filename.
- this.RecTypeDescr = "Data File"
- this.ReadRecord()
- this.oReport.DataFile = STRIPNULL(this.xREC)
-
- Case this.RecID = HToI("2005") // Data Path
- // This is the data path used with 2004
- this.RecTypeDescr = "Data Path"
- this.ReadRecord()
- cTemp = ""
- If this.RecLen > 1
- cTemp = STRIPNULL(this.xREC)
- ElseIf At("\", this.oForm.SourcePathField.Value) > 0
- cTemp = this.oForm.SourcePathField.Value
- cTemp = Left(cTemp, RAt("\", cTemp))
- EndIf
- this.oReport.DataPath = cTemp
- this.aQBEFiles.cDefaultPath = cTemp
- this.oReport.DataFile = cTemp + this.oReport.DataFile
- If Upper(Right(this.oReport.DataFile, 4)) == ".QBE" And;
- File(this.oReport.DataFile)
- this.aQBEFiles.Parse(this.oReport.DataFile)
- EndIf
-
- Case this.RecID = HToI("2006") // DLL File
- // This is the CRW .DLL file used to render the report.
- // Currently not used in report conversions.
- this.RecTypeDescr = "DLL File"
- this.ReadRecord()
- this.oReport.DLLFile = Left(this.xREC, this.RecLen - 1)
-
- Case this.RecID = HToI("2007") // Table Field Count
- // This is a total table field count for all tables in .RPT file.
- // This is unreliable and is not used for verification during
- // conversion.
- this.RecTypeDescr = "Table Field Count"
- this.ReadRecord()
-
- Case this.RecID = HToI("2008") // Table Field Name
- // This is a table name and table field name in
- // TABLE->FIELD format.
- this.RecTypeDescr = "Table Field Name"
- this.ReadRecord()
- this.xREC = STRIPNULL(this.xREC)
- cTemp = Left(this.xREC, At("->", this.xREC) - 1)
- this.FieldName = Right(this.xREC,;
- (Len(this.xREC) - At("->", this.xREC)) - 1)
- If Not this.CurrentTable == cTemp Or;
- this.oReport.aTables[this.oReport.aTables.Size].IsKey(this.FieldName)
- this.oReport.aTables.Add(New DataTable())
- this.oReport.aTables[this.oReport.aTables.Size].Alias =;
- cTemp
- this.CurrentTable = cTemp
- EndIf
-
- Case this.RecID = HToI("2009") // Table Field Data Type
- // This is the table field data type for 2008.
- // The data type is currently not used for report conversions.
- this.RecTypeDescr = "Table Field Data Type"
- this.ReadRecord()
- nTemp = MAKE8(this.xREC, 1)
- Do Case
- Case nTemp = 6 Or nTemp = 4 Or nTemp = 2 Or nTemp = 7
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "N"
- Case nTemp = 8
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "L"
- Case nTemp = 9
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "D"
- Case nTemp = 11
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "C"
- Case nTemp = 13
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "M"
- Case nTemp = 14
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "B"
- Otherwise
- this.oReport.aTables[this.oReport.aTables.Size];
- [this.FieldName] = "U"
- EndCase
-
- Case this.RecID = HToI("2011") // Database Name
- // This is a database name field.
- this.RecTypeDescr = "Database Name"
- this.ReadRecord()
- this.oReport.Database = STRIPNULL(this.xREC)
-
- Otherwise // Unknown/unneeded record type
- this.RecTypeDescr = "Unknown/unnecessary Record Type"
- this.ReadRecord(Not this.StreamAll)
- If Not this.StreamAll And this.Debug
- this.CurrentContainer.Objects.Add (New RecordStream(;
- this.nFPos, this.RecID, this.RecTypeDescr, this.xREC))
- EndIf
-
- EndCase
- If this.StreamAll And this.RecID # HToI("101E") // Image bits
- this.CurrentContainer.Objects.Add(New RecordStream(this.nFPos,;
- this.RecID, this.RecTypeDescr, this.xREC))
- EndIf
- this.UpdateProgress((this.nFPos / this.nFSize) * 100)
- EndDo
- // Ensure that the last object constructed is added to the array cluster
- this.AddToReport()
- this.ReadingRptFooter = False
-
- // Add the StreamFrame template to the .REP array cluster
- // as a child object of the PageTemplate.
- this.CurrentContainer = this.oPageTemplate
- this.CurrentObject = this.oStreamFrame
- this.AddToReport()
-
- If this.nFPos # this.nFSize
- this.oError.LineNo = LineNo() - 1
- this.oError.Filename = Program()
- this.oError.Code = 10003
- Throw this.oError
- EndIf
-
- // Update SQL statements with ORDER BY...
- For nTemp = 1 To this.oReport.aTables.Size
- If this.oReport.aTables[nTemp].aOrders.Size > 0 Or;
- this.oReport.aTables[nTemp].aGroups.Size > 0
- For lTemp = 1 To this.aQueries.Size
- If this.aQueries[lTemp].TableName ==;
- this.oReport.aTables[nTemp].TableName And;
- Not this.aQueries[lTemp].Indexed
- cTemp = Left(this.aQueries[lTemp]["SQL"],;
- Len(this.aQueries[lTemp]["SQL"]) - 1)
- For oTemp = 1 To this.oReport.aTables[nTemp].aOrders.Size;
- Step 2
- // check for expressions in Order By fields
- cOrderby = this.oReport.aTables[nTemp].aOrders[oTemp]
- if at('(',cOrderBy) > 0
- cOrderBy = substr(cOrderby,at('(',cOrderBy)+1)
- endif
- if at(')',cOrderBy) > 0
- cOrderBy = substr(cOrderBy, 1,at(')',cOrderBy) -1)
- endif
-
- cTemp += IIf(oTemp = 1, " ORDER BY ", ", ") +cOrderBy+" "+;
- this.oReport.aTables[nTemp].aOrders[oTemp + 1]
- EndFor
- this.aQueries[lTemp]["SQL"] = cTemp + "'"
- Exit
- EndIf
- EndFor
- EndIf
- EndFor
- If Len(this.cStreamQuery) = 0
- this.cStreamQuery = this.aQueries[1].xName
- EndIf
-
- // Order the CRW print bands in the proper sequence
- aTemp = New Array()
- For nTemp = 2000 To 7000 Step 1000
- For nTop = 1 To this.aCRWBands.Size
- If this.aCRWBands[nTop].ID = nTemp
- aTemp.Add(this.aCRWBands[nTop])
- EndIf
- EndFor
- EndFor
- this.aCRWBands = aTemp
-
- // Up to this point, many positions/sizes were relative
- // coming from the .RPT file. We now need to justify the
- // position and/or size of various report objects.
- //
- // Justify the Top/Height values for the report bands and objects.
- nBandTop = 0
- nHorz = Int(this.oPageTemplate["Width"] -;
- this.oPageTemplate["MarginLeft"] -;
- this.oPageTemplate["MarginRight"])
-
- For nTemp = 1 To this.aCRWBands.Size
- aLines = this.aCRWBands[nTemp]
- aLines.Top = nBandTop
- aLines.Height = 0
- For lTemp = 1 To aLines.Size
- aLines[lTemp].Top = aLines.Height
- aLines[lTemp].PositionObjectsToBaseline(nHorz)
- If this.MultiColumn And;
- this.aCRWBands[nTemp].ID = CRWBAND_RPTDETAIL
- aLines[lTemp].SetSuppressIfBlank()
- EndIf
- aLines.Height += aLines[lTemp].Height
- EndFor
- nBandTop += aLines.Height
- If aLines.ID = CRWBAND_RPTDETAIL Or;
- aLines.ID = CRWBAND_GRPHEADER Or;
- aLines.ID = CRWBAND_GRPFOOTER Or;
- aLines.ID = CRWBAND_GRNDTOTAL
- aLines.Container["Height"] = aLines.Height
- EndIf
- EndFor
- this.oReport.aStreamFrames.Add(this.oStreamFrame)
-
- // Now that the above is accomplished, the .REP PageTemplate,
- // StreamFrame(s), etc need to be sized and positioned.
- If this.MultiColumn // Label or user-defined label report
- // Setup the detail band
- this.oDetailBand["Expandable"] = False
- this.oDetailBand["BeginNewFrame"] = True
- this.oDetailBand["Height"] = this.ColHeight
- this.oStreamFrame["Height"] = this.ColHeight
- this.oStreamFrame["Width"] = this.ColWidth
- AcrossCount = Int((this.oPageTemplate["Width"] -;
- this.oPageTemplate["MarginLeft"] -;
- this.oPageTemplate["MarginRight"] -;
- this.ColWidth) /;
- (this.ColWidth + this.ColGapHorz))
- DownCount = Int((this.oPageTemplate["Height"] -;
- this.oPageTemplate["MarginTop"] -;
- this.oPageTemplate["MarginBottom"] -;
- this.ColHeight) /;
- (this.ColHeight + this.ColGapVert))
- this.CurrentContainer = this.oPageTemplate
- nTop = 0
- nLeft = 0
- If this.ColSequence = 0 // Across/Down
- For nVert = 1 To DownCount + 1
- For nHorz = 1 To AcrossCount + 1
- If nVert # 1 Or nHorz # 1 // If not the first StreamFrame
- // Create multiple StreamFrames - 1 for each label on sheet
- this.CurrentObject = New xStreamFrame(;
- this.oPageTemplate.NextName("STREAMFRAME"))
- this.oReport.aStreamFrames.Add(this.CurrentObject)
- this.CurrentObject["Metric"] = 1
- If nLeft # 0
- this.CurrentObject["Left"] = nLeft
- EndIf
- If nTop # 0
- this.CurrentObject["Top"] = nTop
- EndIf
- this.CurrentObject["Width"] = this.ColWidth
- this.CurrentObject["Height"] = this.ColHeight
- this.AddToReport()
- EndIf
- nLeft += this.ColWidth + this.ColGapHorz
- EndFor
- nLeft = 0
- nTop += this.ColHeight + this.ColGapVert
- EndFor
- Else // Down/Across
- For nHorz = 1 To AcrossCount + 1
- For nVert = 1 To DownCount + 1
- If nVert # 1 Or nHorz # 1 // If not the first StreamFrame
- // Create multiple StreamFrames - 1 for each label on sheet
- this.CurrentObject = New xStreamFrame(;
- this.oPageTemplate.NextName("STREAMFRAME"))
- this.oReport.aStreamFrames.Add(this.CurrentObject)
- this.CurrentObject["Metric"] = 1
- If nLeft # 0
- this.CurrentObject["Left"] = nLeft
- EndIf
- If nTop # 0
- this.CurrentObject["Top"] = nTop
- EndIf
- this.CurrentObject["Width"] = this.ColWidth
- this.CurrentObject["Height"] = this.ColHeight
- this.AddToReport()
- EndIf
- nTop += this.ColHeight + this.ColGapVert
- EndFor
- nTop = 0
- nLeft += this.ColWidth + this.ColGapHorz
- EndFor
- EndIf
- Else // Non-label report
- If this.aCRWBands[1].Height # 0
- this.oStreamFrame["Top"] = this.aCRWBands[1].Height
- EndIf
- this.oStreamFrame["Height"] = this.oPageTemplate["Height"] -;
- this.oPageTemplate["MarginTop"] -;
- this.oPageTemplate["MarginBottom"] -;
- this.aCRWBands[1].Height -;
- this.aCRWBands[this.aCRWBands.Size].Height
- this.aCRWBands[this.aCRWBands.Size].Top = this.oStreamFrame["Top"] +;
- this.oStreamFrame["Height"]
- this.oStreamFrame["Width"] = this.oPageTemplate["Width"] -;
- this.oPageTemplate["MarginLeft"] -;
- this.oPageTemplate["MarginRight"]
- For nTemp = 1 To this.oPageTemplate.Objects.Size
- If this.oPageTemplate.Objects[nTemp].RptFooterObject And;
- Not this.oPageTemplate.Objects[nTemp].xClassName == "BLANK"
- If this.oPageTemplate.Objects[nTemp].IsKey("Top")
- this.oPageTemplate.Objects[nTemp]["Top"] +=;
- this.oStreamFrame["Top"] +;
- this.oStreamFrame["Height"]
- Else
- this.oPageTemplate.Objects[nTemp]["Top"] =;
- this.oStreamFrame["Top"] +;
- this.oStreamFrame["Height"]
- EndIf
- EndIf
- EndFor
- EndIf
-
- // Justify Shapes to their respective bands
- For nTemp = 1 To this.aShapes.Size
- aTemp = this.aCRWBands[this.aShapes[nTemp].TopBandIndex]
- this.aShapes[nTemp]["Top"] +=;
- aTemp[this.aShapes[nTemp].TopLineIndex].Top
- aTemp = this.aCRWBands[this.aShapes[nTemp].BotBandIndex]
- this.aShapes[nTemp]["Height"] +=;
- aTemp[this.aShapes[nTemp].BotLineIndex].Top
- If this.aShapes[nTemp].TopBandIndex #;
- this.aShapes[nTemp].BotBandIndex
- this.aShapes[nTemp]["Height"] +=;
- (aTemp.Top - this.aShapes[nTemp]["Top"])
- EndIf
- If this.aShapes[nTemp].TopBandIndex = this.aCRWBands.Size
- this.aShapes[nTemp]["Top"] += aTemp.Top
- EndIf
- // Now add the Shape to the .REP array cluster
- this.CurrentContainer =;
- this.aCRWBands[this.aShapes[nTemp].TopBandIndex].Container
- this.CurrentObject = this.aShapes[nTemp]
- this.CurrentObject.xName = this.CurrentContainer.NextName("SHAPE")
- this.AddToReport()
- EndFor
-
- // Justify Lines to their respective bands or to the PageTemplate
- For nTemp = 1 To this.aLines.Size
- aLinesTop = this.aCRWBands[this.aLines[nTemp].TopBandIndex]
- aLinesBot = this.aCRWBands[this.aLines[nTemp].BotBandIndex]
- If this.aLines[nTemp]["Top"] > 32766
- this.aLines[nTemp]["Top"] = aLinesTop.Height - 1
- Else
- // Compute line top relative to the top of the CRW band line
- // containing the top of the line
- this.aLines[nTemp]["Top"] +=;
- aLinesTop[this.aLines[nTemp].TopLineIndex].Top
- EndIf
- // If the top of the line is contained in the CRW report footer...
- If this.aLines[nTemp].TopBandIndex = this.aCRWBands.Size
- // Compute the top of the line relative to the top of the
- // CRW report footer
- this.aLines[nTemp]["Top"] += aLinesTop.Top
- EndIf
- If this.aLines[nTemp]["Bottom"] > 32766
- this.aLines[nTemp]["Bottom"] = aLinesBot.Height - 1
- Else
- // Compute line bottom relative to the top of the CRW band line
- // containing the bottom of the line
- this.aLines[nTemp]["Bottom"] +=;
- aLinesBot[this.aLines[nTemp].BotLineIndex].Top
- EndIf
- If this.aLines[nTemp].BotBandIndex = this.aCRWBands.Size Or;
- this.aLines[nTemp].BotBandIndex #;
- this.aLines[nTemp].TopBandIndex
- // ...Then compute the bottom of the line relative to the
- // top of the CRW band which contains the bottom of the line
- this.aLines[nTemp]["Bottom"] += aLinesBot.Top
- EndIf
- If this.aLines[nTemp]["Left"] > this.oStreamFrame["Width"] - 1
- this.aLines[nTemp]["Left"] = this.oStreamFrame["Width"] - 1
- EndIf
- If this.aLines[nTemp]["Right"] > this.oStreamFrame["Width"] - 1
- this.aLines[nTemp]["Right"] = this.oStreamFrame["Width"] - 1
- EndIf
- nTop = this.oPageTemplate["Height"] -;
- this.oPageTemplate["MarginTop"] -;
- this.oPageTemplate["MarginBottom"] - 1
- If this.aLines[nTemp]["Top"] > nTop
- this.aLines[nTemp]["Top"] = nTop
- EndIf
- If this.aLines[nTemp]["Bottom"] > nTop
- this.aLines[nTemp]["Bottom"] = nTop
- EndIf
- // Now add the Line to the .REP array cluster
- this.CurrentContainer =;
- this.aCRWBands[this.aLines[nTemp].TopBandIndex].Container
- this.CurrentObject = this.aLines[nTemp]
- this.CurrentObject.xName = this.CurrentContainer.NextName("LINE")
- this.AddToReport()
- EndFor
-
- Catch(RBException x) // Program-detected errors are caught here
- this.oError.OnError(x)
- this.CriticalError = True
- Catch(Exception x) // VdB-detected errors are caught here
- this.oError.OnError(x)
- this.CriticalError = True
- Finally // Release device context and close file handle
- BL_lReleaseDC(_app.FrameWin.hWND, this.hDC)
- fClose(this.hInFile)
- this.hInFile = 0
- EndTry
- RETURN Not this.CriticalError // True if no error, False if error
-
- FUNCTION FieldType(cFldRef)
- LOCAL cAlias, cField, nTable, nField, cTemp
-
- cAlias = Left(cFldRef, At("->", cFldRef) - 1)
- cField = SubStr(cFldRef, At("->", cFldRef) + 2)
- For nTable = 1 To this.oReport.aTables.Size
- If this.oReport.aTables[nTable].Alias == cAlias
- RETURN IIf(this.oReport.aTables[nTable].IsKey(cField),;
- this.oReport.aTables[nTable][cField], "U")
- EndIf
- EndFor
- RETURN "U"
-
- FUNCTION ConvertFormula(c)
- // Convert field references in FIELD format to TABLE->FIELD format
- LOCAL nInd, cTemp, nStart, cResult, nHits
-
- cResult = c
- For nInd = this.oReport.aTables.Size To 1 Step -1
- cTemp = this.oReport.aTables[nInd].FirstKey
- Do While Not Empty(cTemp)
- nHits = 1
- nStart = At(cTemp, Upper(cResult), nHits)
- Do While nStart > 0
- If SubStr(cResult, nStart - 2, 2) # "->" And;
- (SubStr(cResult, nStart - 1, 1) $;
- Chr(9) + " ,+-*/$=#<>^'(" Or;
- nStart = 1) And;
- SubStr(cResult, nStart + Len(cTemp), 2) # "->" And;
- (SubStr(cResult, nStart + Len(cTemp), 1) $;
- Chr(9) + " ,+-*/$=#<>^')" Or;
- nStart + (Len(cTemp) - 1) = Len(cResult)) And;
- Not this.IsInString(cTemp, Upper(cResult), nHits)
- cResult = Stuff(cResult, nStart, 0,;
- this.oReport.aTables[nInd].Alias + "->")
- EndIf
- nStart = At(cTemp, Upper(cResult), ++nHits)
- EndDo
- cTemp = this.oReport.aTables[nInd].NextKey(cTemp)
- EndDo
- EndFor
- RETURN cResult
-
- FUNCTION IsInString(cSub, cString, nCnt)
- LOCAL lDQuote, lSQuote, lBracket, nEnd, nInd, cChar
-
- lDQuote = False
- lSQuote = False
- lBracket = False
- nEnd = At(cSub, cString, nCnt) - 1
- For nInd = 1 To nEnd
- cChar = SubStr(cString, nInd, 1)
- If cChar == "[" And Not lSQuote And Not lDQuote
- lBracket = True
- ElseIf cChar == "]" And lBracket
- lBracket = False
- ElseIf cChar == '"' And Not lSQuote And Not lBracket
- lDQuote = Not lDQuote
- ElseIf cChar == "'" And Not lDQuote And Not lBracket
- lSQuote = Not lSQuote
- EndIf
- EndFor
- RETURN lDQuote Or lSQuote Or lBracket
-
- FUNCTION ConvertField(c)
- // Convert field references in TABLE->FIELD format to
- // QueryName.RowSet.Fields["FIELD"].Value syntax.
- LOCAL nTemp, nInd, cTemp, cTable, cField, nStart, nEnd, cResult
-
- cResult = c
- Do While True
- nTemp = At("->", cResult)
- If nTemp = 0
- Exit
- EndIf
- cTable = ""
- For nInd = nTemp - 1 To 1 Step -1
- If SubStr(cResult, nInd, 1) $ '(",+-*/<>=[]'
- Exit
- EndIf
- cTable = SubStr(cResult, nInd, 1) + cTable
- EndFor
- cTable = ALLTRIM(cTable) + "1"
- nStart = nInd + 1
- cField = ""
- For nInd = nTemp + 2 To Len(cResult)
- If SubStr(cResult, nInd, 1) $ ')",+-*/<>=[]'
- Exit
- EndIf
- cField += SubStr(cResult, nInd, 1)
- EndFor
- cField = ALLTRIM(cField)
- nEnd = nInd
- cResult = Stuff(cResult, nStart, nEnd - nStart,;
- 'this.Form.' + cTable + '.RowSet.Fields["' +;
- cField + '"].Value ')
- EndDo
- RETURN "{|| " + cResult + "}"
-
- PROCEDURE AddToReport
- // Adds the current object to the .REP array cluster
-
- If Type("this.CurrentObject") $ "O|A"
- If this.CurrentObject.VdBReportObject
- this.CurrentObject.RptFooterObject = this.ReadingRptFooter
- this.CurrentContainer.Objects.Add(this.CurrentObject)
- If this.CurrentObject.xClassName # "BLANK"
- ++ this.ObjectCount
- Else
- this.CurrentObject["Height"] = this.CurrentLine.Height
- EndIf
- If this.CurrentObject.xClassName == "TEXT" Or;
- this.CurrentObject.xClassName == "BLANK"
- this.ObjectsLine.Add(this.CurrentObject)
- EndIf
- EndIf
- EndIf
- this.CurrentObject = Null
-
- PROCEDURE ReadRecord(lSkip, lForce)
- // Reads next record in .RPT file.
- // If lSkip = True, moves file pointer without actually reading.
- // If lForce = True, forces file pointer movement without reading
- // (necessary when encountering stored image bits and this.StreamAll = True)
-
- this.nFPos += this.RecLen
- If lSkip And (Not this.StreamAll Or lForce)
- fSeek(this.hInFile, this.RecLen, 1)
- RETURN
- EndIf
- this.xREC = fRead(this.hInFile, this.RecLen)
- If Len(this.xREC) = this.RecLen
- RETURN
- EndIf
- this.oError.LineNo = LineNo - 1
- this.oError.Filename = Program()
- this.oError.Code = 10004
- Throw this.oError
-
- FUNCTION SkipNulls
- // Reads through garbage nulls which are sometimes encountered
- // in .RPT file.
- LOCAL xTemp
-
- fSeek(this.hInFile, -4, 1)
- this.nFPos -= 4
- Do
- xTemp = fRead(this.hInFile, 1)
- ++ this.nFPos
- Until xTemp # Chr(0)
- fSeek(this.hInFile, -1, 1)
- -- this.nFPos
-
- FUNCTION GetItemSize(cText)
- // Computes cText height and width based on length of text
- // and current font attributes.
- LOCAL hOrgFont, hFont, nTemp
- PRIVATE xSIZE, hDC
-
- hFont = BL_CreateFont(;
- Int(((this.FontSize *;
- BL_GetDeviceCaps(this.hDC, LOGPIXELSY)) / 72) * 17.7),;// Height
- 0,; // Width (Defaulted based on height)
- 0,; // Incline
- 0,; // Rotation
- this.FontBold,; // Font weight
- this.FontItalic,; // Italic
- this.FontUnderline,; // Underline
- this.FontStrikeout,; // Strikeout
- ANSI_CHARSET,; // Character set
- OUT_DEFAULT_PRECIS,; // Output precision
- CLIP_DEFAULT_PRECIS,; // Clipping precision
- DEFAULT_QUALITY,; // Output quality
- DEFAULT_PITCH,; // Pitch and Family
- this.FontName + Chr(0)) // Font name
- hOrgFont = BL_SelectObject(this.hDC, hFont)
- BL_GetTextExtentPoint32(this.hDC, cText, Len(cText), this.xSIZE)
- this.ItemWidth = GETU32(this.xSIZE, 0)
- this.ItemHeight = GETU32(this.xSIZE, 4)
- BL_DeleteObject(BL_SelectObject(this.hDC, hOrgFont))
- RETURN this.ItemHeight
-
- PROCEDURE UpdateProgress(nProgress)
- // Update the progress indicator on the Wizard form
-
- If this.ShowProgress
- this.ProgressObject.Value = nProgress
- BL_UpdateWindow(this.ProgressObject.hWND)
- EndIf
-
- FUNCTION StreamReport
- // Main .REP streaming function. Calls other Stream... functions.
- LOCAL nIndex, oTemp
-
- If this.CriticalError // If critical error on last BuildReport run.
- RETURN False
- EndIf
- this.StreamCount = 0
- this.UpdateProgress((++this.StreamCount / this.ObjectCount) * 100)
- If Type("this.oReport") # "O"
- RETURN False
- EndIf
- Try
- this.hOutFile = fCreate((this.OutFilename), "W")
- Catch(Exception x)
- this.oError.OnError(x)
- this.CriticalError = True
- RETURN False
- EndTry
- If this.hOutFile < 0
- MsgBox(this.oForm.oLang.iText("NoFileCreate") + CR + CR +;
- this.OutFilename, this.oForm.oLang.iText("WIZARDNAME"), 48)
- this.CriticalError = True
- RETURN False
- EndIf
- Try
- If Not this.StreamHeader()
- RETURN False
- EndIf
- this.UpdateProgress((++this.StreamCount / this.ObjectCount) * 100)
- // oTemp is a temporary object used to support drill-down streaming
- // from the report class level.
- oTemp = New AssocArray()
- oTemp.xName = ""
- oTemp.Objects = New Array()
- oTemp.Objects.Add(this.oReport)
- // Now stream the entire .REP array cluster
- If Not this.StreamObject(oTemp, "")
- RETURN False
- EndIf
- // Stream trailing object references to end of .REP file
- fWrite(this.hOutFile, Space(3) +;
- "this.FirstPageTemplate = this.form." +;
- this.oPageTemplate.xName + NEWLINE)
- fWrite(this.hOutFile, Space(3) +;
- "this.form." +;
- this.oPageTemplate.xName +;
- ".NextPageTemplate = this.form." +;
- this.oPageTemplate.xName + NEWLINE)
- For nTemp = 1 To this.oReport.aStreamFrames.Size
- fWrite(this.hOutFile, Space(3) + "this.form." +;
- this.oPageTemplate.xName +;
- "." + this.oReport.aStreamFrames[nTemp].xName +;
- ".StreamSource = this.form." +;
- this.oStreamSource.xName + NEWLINE)
- EndFor
- fWrite(this.hOutFile, Space(3) + "this.form." +;
- this.oStreamSource.xName +;
- ".RowSet = this.form." +;
- this.cStreamQuery + ".RowSet" + NEWLINE)
- fWrite(this.hOutFile, "ENDCLASS" + NEWLINE + NEWLINE)
- this.UpdateProgress((++this.StreamCount / this.ObjectCount) * 100)
- Catch(RBException x) // Program-detected errors caught here
- this.oError.OnError(x)
- this.CriticalError = True
- Catch(Exception x) // VdB-detected errors caught here
- this.oError.OnError(x)
- this.CriticalError = True
- Finally
- fClose(this.hOutFile) // Close output file handle
- this.oForm = Null
- this.aQBEFiles = Null
- this.ProgressObject = Null
- EndTry
- RETURN Not this.CriticalError
-
- FUNCTION StreamHeader
- // Streams header comment blocks, report rendering bootstrap, and
- // class declaration statement to output file.
- LOCAL cTemp, nLen
-
- nTemp = Len(this.oForm.oLang.iText("Filename"))
- nLen = Len(this.oForm.oLang.iText("CreatedBy"))
- nTemp = IIf(nLen > nTemp, nLen, nTemp)
- nLen = Len(this.oForm.oLang.iText("CreatedFrom"))
- nTemp = IIf(nLen > nTemp, nLen, nTemp)
- nLen = Len(this.oForm.oLang.iText("CreatedOn"))
- nTemp = IIf(nLen > nTemp, nLen, nTemp)
- nLen = Len(this.oForm.oLang.iText("DataFile"))
- nTemp ++ = IIf(nLen > nTemp, nLen, nTemp)
- cTemp = this.OutFilename
- If RAt("\", cTemp) > 0
- cTemp = Right(cTemp, Len(cTemp) - RAt("\", cTemp))
- EndIf
- this.StreamComments(this.oForm.oLang.iText("Filename") + ":" +;
- Space(nTemp - Len(this.oForm.oLang.iText("Filename"))) +;
- cTemp + NEWLINE +;
- this.oForm.oLang.iText("CreatedBy") + ":" +;
- Space(nTemp - Len(this.oForm.oLang.iText("CreatedBy"))) +;
- this.oForm.oLang.iText("WIZARDNAME") + NEWLINE +;
- this.oForm.oLang.iText("CreatedFrom") + ":" +;
- Space(nTemp - Len(this.oForm.oLang.iText("CreatedFrom"))) +;
- ALLTRIM(this.inFilename) + NEWLINE +;
- this.oForm.oLang.iText("DataFile") + ":" +;
- Space(nTemp - Len(this.oForm.oLang.iText("DataFile"))) +;
- ALLTRIM(this.oReport.DataFile) + NEWLINE +;
- this.oForm.oLang.iText("CreatedOn") + ":" +;
- Space(nTemp - Len(this.oForm.oLang.iText("CreatedOn"))) +;
- DToC(Date()) + " " +;
- this.oForm.oLang.iText("CreatedAt") + " " + Time(),;
- True, True)
- fWrite(this.hOutFile, "//" + NEWLINE)
-
- If Not IsBlank(this.oReport.LabelType) Or;
- Not IsBlank(this.oReport.LabelStyle)
- this.StreamComments(this.oForm.oLang.iText("LabelType") + ": " +;
- this.oReport.LabelType + NEWLINE +;
- this.oForm.oLang.iText("LabelStyle") + ": " +;
- this.oReport.LabelStyle + NEWLINE,;
- True, True)
- fWrite(this.hOutFile, "//" + NEWLINE)
- EndIf
-
- If Not IsBlank(this.oReport.Comments)
- this.StreamComments(this.oForm.oLang.iText("CommentsFrom") + ": " +;
- this.InFilename + NEWLINE +;
- this.oReport.Comments, True, True)
- fWrite(this.hOutFile, "//" + NEWLINE)
- EndIf
-
- If this.aErrors.Size > 0
- this.StreamComments(this.oForm.oLang.iText("ExceptionLog") + ":" +;
- NEWLINE, True, False)
- For nTemp = 1 To this.aErrors.Size
- this.StreamComments(this.aErrors[nTemp], False,;
- nTemp = this.aErrors.Size)
- EndFor
- fWrite(this.hOutFile, "//" + NEWLINE)
- EndIf
-
- fWrite(this.hOutFile,;
- "** END HEADER -- " + this.oForm.oLang.iText("NoRemoveLine") +;
- NEWLINE +;
- "//" + NEWLINE +;
- "// " + this.oForm.oLang.iText("ConvertedOn") + " " +;
- DToC(Date()) + NEWLINE +;
- "//" + NEWLINE)
-
- fWrite(this.hOutFile,;
- "LOCAL r" + NEWLINE +;
- "r = new " + this.oReport.xClassName + "()" + NEWLINE +;
- "r.render()" + NEWLINE +;
- "CLASS " + this.oReport.xClassName + " OF REPORT" + NEWLINE)
- fWrite(this.hOutFile, NEWLINE)
- RETURN True
-
- FUNCTION StreamComments(cComm, lCommentStart, lCommentEnd)
- // Streams comment lines and
- // optionally (lCommentStart) an asterisk line before the comment block, and
- // optionally (lCommentEnd) an asterisk line after the comment block.
- // Comment line length is limited to MAXLINELEN in RptToRepConv.H
- LOCAL nLineEnd, cLine, cComments
-
- If lCommentStart
- this.StreamBannerLine()
- EndIf
- cComments = cComm
- Do While Not IsBlank(cComments)
- nLineEnd = At(LF, cComments)
- If nLineEnd > 0
- cLine = Left(cComments, nLineEnd)
- Else
- cLine = Left(cComments, MAXLINELEN)
- EndIf
- Do While (RAt(" ", cLine) > MAXLINELEN - 5)
- cLine = Left(cLine, RAt(" ", cLine, 2) - 1)
- EndDo
- If (Len(cLine) > MAXLINELEN - 5) And (RAt(" ", cLine) > 0)
- cLine = Left(cLine, RAt(" ", cLine) - 1)
- Else
- cLine = Left(cLine, MAXLINELEN - 5)
- EndIf
- cComments = LTrim(Right(cComments, Len(cComments) - Len(cLine)))
- Do While RAt(LF, cLine) > 0
- cLine = Left(cLine, RAt(CR, cLine) - 1)
- EndDo
- fWrite(this.hOutFile,;
- "// " + cLine +;
- Space((MAXLINELEN - 5) - Len(cLine)) + "//" + NEWLINE)
- EndDo
- If lCommentEnd
- this.StreamBannerLine()
- EndIf
- RETURN .T.
-
- FUNCTION StreamBannerLine
-
- RETURN fWrite(this.hOutFile, Replicate("/", MAXLINELEN) + NEWLINE)
-
- FUNCTION StreamObject(oRef, cRefChain)
- // Streams all objects in .REP array cluster.
- // Uses recursive calls to itself to support drill-down
- // streaming of contained objects and maintain the object
- // reference chain text.
- LOCAL cProperty, nIndex, nTemp, lAnyStream, lPropertyStreamed
-
- For nIndex = 1 To oRef.Objects.Size
- If Not oRef.Objects[nIndex].xClassName $ "UNKNOWN|BLANK"
- lAnyStream = False
- lPropertyStreamed = False
- If oRef.Objects[nIndex].Define
- lAnyStream = True
- fWrite(this.hOutFile, Space(3) +;
- cRefChain + "." + oRef.Objects[nIndex].xName +;
- " = new " + oRef.Objects[nIndex].xClassName +;
- "(")
- If Not oRef.Objects[nIndex].AddParentRef
- fWrite(this.hOutFile, cRefChain)
- EndIf
- fWrite(this.hOutFile, ")" + NEWLINE)
- EndIf
- If oRef.Objects[nIndex].AddParentRef
- lAnyStream = True
- fWrite(this.hOutFile, Space(3) +;
- cRefChain + "." + oRef.Objects[nIndex].xName +;
- ".Parent = " + cRefChain + NEWLINE)
- EndIf
-
- If oRef.Objects[nIndex].Count() # 0
- lAnyStream = True
- lPropertyStreamed = True
- fWrite(this.hOutFile, Space(3) +;
- "With (" +;
- IIf(Not IsBlank(cRefChain), cRefChain + ".", "") +;
- oRef.Objects[nIndex].xName + ")" + NEWLINE)
- cProperty = oRef.Objects[nIndex].FirstKey
- Do While Not Empty(cProperty)
- fWrite(this.hOutFile,;
- Space(6) + cProperty + " = " +;
- Transform(oRef.Objects[nIndex][cProperty], "@T"))
- cProperty = oRef.Objects[nIndex].NextKey(cProperty)
- fWrite(this.hOutFile, NEWLINE)
- EndDo
- // This is a workaround to prevent streaming the
- // Query.Active property before streaming the other
- // Query properties which VdB can't handle.
- // Also, see the xQuery class where the Active
- // property is commented out.
- If oRef.Objects[nIndex].xClassName == "QUERY" And;
- lPropertyStreamed
- fWrite(this.hOutFile, Space(6) + "Active = true" + NEWLINE)
- EndIf
- fWrite(this.hOutFile, Space(3) +;
- "EndWith" + NEWLINE)
- EndIf
- If lAnyStream
- fWrite(this.hOutFile, NEWLINE)
- EndIf
-
- this.UpdateProgress((++this.StreamCount / this.ObjectCount) * 100)
- If oRef.Objects[nIndex].Objects.Size > 0
- oRef.Objects[nIndex].Objects =;
- this.ArrangeZOrder(oRef.Objects[nIndex].Objects)
- If Not IsBlank(cRefChain)
- cRefChain += "."
- EndIf
- cRefChain += oRef.Objects[nIndex].xName
- this.StreamObject(oRef.ObJects[nIndex], cRefChain)
- cRefChain = Left(cRefChain, RAt(".", cRefChain) - 1)
- EndIf
- ElseIf (this.Debug Or this.StreamAll) And;
- (Not oRef.Objects[nIndex].xClassName == "BLANK")
- For nTemp = 1 To oRef.Objects[nIndex].aComments.Size
- fWrite(this.hOutFile, "// " +;
- oRef.Objects[nIndex].aComments[nTemp] +;
- NEWLINE)
- EndFor
- fWrite(this.hOutFile, NEWLINE)
- EndIf
- EndFor
- RETURN True
-
- FUNCTION ArrangeZOrder(aRef)
- LOCAL nInd, aTarget
-
- aTarget = New Array()
- For nInd = 1 To aRef.Size
- If aRef[nInd].xClassName $ "SHAPE|IMAGE"
- aTarget.Add(aRef[nInd])
- EndIf
- EndFor
- For nInd = 1 To aRef.Size
- If Not aRef[nInd].xClassName $ "SHAPE|IMAGE"
- aTarget.Add(aRef[nInd])
- EndIf
- EndFor
- RETURN aTarget
-
- ENDCLASS // ReportConverter
-
-
- CLASS RBException(oParent) Of Exception
- // One instance of this class handles all errors during report
- // conversion and streaming.
-
- this.Filename = Program()
- this.TitleText = oParent.oLang.iText("WIZARDNAME")
-
- this.aMessage = New Array(0)
- this.aMessage.Add(oParent.oLang.iText("InvalidInput")) // 10001
- this.aMessage.Add(oParent.oLang.iText("UnsupportedVersion")) // 10002
- this.aMessage.Add(oParent.oLang.iText("OrDamagedFile")) // 10003
- this.aMessage.Add(oParent.oLang.iText("BadRecordLength")) // 10004
- this.aMessage.Add(oParent.oLang.iText("GenIOError")) // 10005
- this.aMessage.Add(oParent.oLang.iText("NoPrintDC")) // 10006
- this.aMessage.Add(oParent.oLang.iText("NoPrintMapMode")) // 10007
- this.aMessage.Add(oParent.oLang.iText("NoFontGDI")) // 10008
- this.aMessage.Add(oParent.oLang.iText("NoFontDataGDI")) // 10009
- this.aMessage.Add(oParent.oLang.iText("FieldCtMismatch")) // 10010
- this.aMessage.Add(oParent.oLang.iText("FormulaCtMismatch")) // 10011
- this.aMessage.Add(oParent.oLang.iText("TextCtMismatch")) // 10012
- this.aMessage.Add(oParent.oLang.iText("NoQueryFile")) // 10013
- this.aMessage.Add(oParent.oLang.iText("HasOLEItem")) // 10014
-
- PROCEDURE ClearError
- this.Code = 0
- this.Message = ""
- this.Filename = ""
- this.LineNo = 0
- this.Filename = Program()
-
- PROCEDURE OnError(oX)
- If oX.Code > 10000
- oX.Message = oX.aMessage[oX.Code - 10000]
- EndIf
- this.Code = oX.Code
- this.Message = oX.Message
- this.LineNo = oX.LineNo
- this.Filename = oX.Filename
- MsgBox(oX.Message + Chr(13) +;
- "Code: " + CHARNUM(oX.Code) + ": " + Chr(13) +;
- "In file: " + oX.Filename + Chr(13) +;
- "Line: " + CHARNUM(oX.LineNo),;
- this.TitleText, 48)
-
- ENDCLASS // RBException Of Exception
-
-
- CLASS RepObjBase Of AssocArray
- // Base class used by all templates streamed to .REP file
-
- this.VdBReportObject = True
- this.RptFooterObject = False
- this.Define = True
- this.AddParentRef = False
- this.Objects = New Array()
- this.aaObjNums = New AssocArray()
-
- FUNCTION NextName(cName)
- LOCAL cTemp
-
- cTemp = cName
- Do While At(" ", cTemp) > 0
- cTemp = Stuff(cTemp, At(" ", cTemp), 1, "_")
- EndDo
- If Not this.aaObjNums.IsKey(cTemp)
- this.aaObjNums[cTemp] = 1
- EndIf
- RETURN cTemp + CHARNUM(this.aaObjNums[cTemp]++)
-
- PROCEDURE SetFont(oRef)
-
- If Upper(oRef.FontName) # Upper(HTML_DEFFACE)
- this["FontName"] = '"' + oRef.FontName + '"'
- EndIf
- If oRef.FontSize # HTML_DEFFNSZ
- this["FontSize"] = oRef.FontSize
- EndIf
- If oRef.FontBold # HTML_DEFBOLD
- this["FontBold"] = oRef.FontBold > 401
- EndIf
- If oRef.FontItalic # HTML_DEFITAL
- this["FontItalic"] = oRef.FontItalic
- EndIf
- If oRef.FontUnderline # HTML_DEFUNLN
- this["FontUnderline"] = oRef.FontUnderline
- EndIf
- If oRef.FontStrikeout # HTML_DEFSTRK
- this["FontStrikeout"] = oRef.FontStrikeout
- EndIf
- this["Height"] = oRef.GetItemSize("H")
- If this.IsKey("BorderStyle") And this["BorderStyle"] == "6"
- this["Height"] += 90
- EndIf
-
- ENDCLASS // RepObjBase Of AssocArray
-
-
- CLASS xReport(cName) Of RepObjBase
- // Main report class template
-
- this.xClassName = cName + "REPORT"
- this.xName = "this"
- this.Define = False
-
- this.Title = ""
- this.Comments = ""
-
- this.DLLFile = ""
- this.DataPath = ""
- this.DataFile = ""
- this.aTables = New Array()
- this.aaFormulas = New AssocArray() // FormulaName/Formula
- this.FormulaCount = 0
- this.aCRWBands = New Array() // Container for CRWBand objects
- this.aStreamFrames = New Array() // Container for StreamFrames
-
- this.LabelType = ""
- this.LabelStyle = ""
-
- ENDCLASS // xReport Of RepObjBase
-
-
- CLASS xQuery(cName) Of RepObjBase
- // Table query object template
-
- this.xClassName = "QUERY"
- this.xName = cName
-
- this.AddParentRef = True
-
- this.Indexed = False
-
- this["SQL"] = ""
- this["RequestLive"] = False
- // See workaround comments in StreamObject method.
- // this["Active"] = True
-
- ENDCLASS // xQuery Of RepObjBase
-
-
- CLASS xRowSet Of RepObjBase
- // Query.Rowset object template
-
- this.xClassName = "ROWSET"
- this.xName = this.xClassName
- this.Define = False
-
- ENDCLASS // xRowSet Of RepObjBase
-
-
- CLASS xPrinter Of RepObjBase
- // Report Printer object template
-
- this.xClassName = "PRINTER"
- this.xName = this.xClassName
- this.Define = False
-
- // Set printer defaults.
- // .RPT does not specify printer settings unless
- // File|Printer Setup is used while in design mode.
- this["Color"] = _app.Printer.Color
- this["Duplex"] = _app.Printer.Duplex
- this["Orientation"] = _app.Printer.Orientation
- this["PaperSize"] = _app.Printer.PaperSize
- this["PaperSource"] = _app.Printer.PaperSource
- this["Resolution"] = _app.Printer.Resolution
- this["TrueTypeFonts"] = _app.Printer.TrueTypeFonts
-
- ENDCLASS // xPrinter Of RepObjBase
-
-
- CLASS xPageTemplate(cName) Of RepObjBase
- // Report PageTemplate object template
-
- this.xClassName = "PAGETEMPLATE"
- this.xName = cName
-
- this["Width"] = Int(8.5 * 1440)
- this["Height"] = Int(11 * 1440)
- // CRW defaults to .25" margins and does not stream to .RPT unless changed
- this["MarginTop"] = Int(.25 * 1440)
- this["MarginLeft"] = Int(.25 * 1440)
- this["MarginRight"] = Int(.25 * 1440)
- this["MarginBottom"] = Int(.25 * 1440)
- this["GridLineWidth"] = 0
-
- ENDCLASS // xPageTemplate() Of RepObjBase
-
-
- CLASS xStreamFrame(cName) Of RepObjBase
- // Report StreamFrame object template
-
- this.xClassName = "STREAMFRAME"
- this.xName = cName
-
- this["Metric"] = 1
- this["Width"] = 0
- this["Height"] = 0
-
- ENDCLASS // xStreamFrame Of RepObjBase
-
-
- CLASS xStreamSource(cName) Of RepObjBase
- // Report StreamSource object template
-
- this.xClassName = "STREAMSOURCE"
- this.xName = cName
-
- ENDCLASS // xStreamSource Of RepObjBase
-
-
- CLASS xGroup(cName) Of RepObjBase
- // Group object template
-
- this.xClassName = "GROUP"
- this.xName = cName
-
- this.HeaderBand = New xBand("HEADER")
- this.Objects.Add(this.HeaderBand)
- this.FooterBand = New xBand("FOOTER")
- this.Objects.Add(this.FooterBand)
-
- ENDCLASS // xGroup Of RepObjBase
-
- CLASS xReportGroup Of RepObjBase
- // ReportGroup object template
-
- this.xClassName = "REPORTGROUP"
- this.xName = this.xClassName
-
- this.Define = False
-
- this.HeaderBand = New xBand("HEADER")
- this.Objects.Add(this.HeaderBand)
- this.FooterBand = New xBand("FOOTER")
- this.Objects.Add(this.FooterBand)
-
- ENDCLASS // xReportGroup Of xGroup
-
-
- CLASS xBand(cName) Of RepObjBase
- // Band object template
- // Used for all bands in .REP file
-
- this.xClassName = "BAND"
- this.xName = cName + this.xClassName
-
- this.Define = False
-
- ENDCLASS // xBand Of RepObjBase
-
-
- CLASS xText Of RepObjBase
- // Text object template
-
- this.xClassName = "TEXT"
- this.xName = ""
- this.AgType = ""
- this.AgError = ""
-
- this["ColorNormal"] = '"BtnText"'
- this["Metric"] = 1
- this["Text"] = ""
-
- ENDCLASS // xText Of RepObjBase
-
-
- CLASS xLine(cName) Of RepObjBase
- // Line object template
-
- this.xClassName = "LINE"
- this.xName = cName
-
- this["Metric"] = 1
-
- ENDCLASS // xLine Of RepObjBase
-
-
- CLASS xShape(cName) Of RepObjBase
- // Shape object template
-
- this.xClassName = "SHAPE"
- this.xName = cName
-
- this["ShapeStyle"] = 1
-
- ENDCLASS // xShape Of RepObjBase
-
-
- CLASS xImage(cName) Of RepObjBase
- // Image object template
-
- this.xClassName = "IMAGE"
- this.xName = cName
-
- this["Metric"] = 1
-
- ENDCLASS // xImage Of RepObjBase
-
-
- CLASS xBlank(cName) Of RepObjBase
- // Special template used to occupy blank vertical
- // space which is used when vertically justifying
- // the report objects (Top/Height properties) after
- // the full .RPT file has been read.
- // This template is not streamed to the .REP file.
-
- this.xClassName = "BLANK"
- this.xName = cName
- this.AgType = ""
-
- ENDCLASS // xBlank Of RepObjBase
-
-
- CLASS RecordStream(nWhere, nID, cDesc, xHEX) Of RepObjBase
- // Special template used to stream .RPT file information to
- // the .REP file in the form of comments when in Debug or
- // StreamAll mode.
- LOCAL xTemp, cChars, cHex, x, cSpace, x
-
- this.xClassName = "UNKNOWN"
- this.xName = this.xClassName
-
-
- this.aComments = New Array()
- this.aComments.Add(cDesc + " [x" + IToH(nID, 4) + "]" +;
- " At: x" + IToH((nWhere - 4) - Len(xHEX), 4) +;
- " Length: x" + IToH(Len(xHEX), 4))
- cChars = ""
- cHex = ""
- For x = 1 To Len(xHex)
- cChars += IIf((Asc(SubStr(xHEX, x, 1)) < 32) Or;
- (Asc(SubStr(xHEX, x, 1)) > 127),;
- ".", SubStr(xHEX, x, 1))
- cHex += IToH(Asc(SubStr(xHEX, x, 1)), 2) + " "
- If Mod(x, 16) = 0
- this.aComments.Add(cHex + " " + cChars)
- cChars = ""
- cHex = ""
- ElseIf Mod(x, 8) = 0
- cChars += " "
- cHex += " "
- EndIf
- EndFor
- x = IIf(Len(cChars) < 9, Len(cChars), Len(cChars) - 1)
- cSpace = Space((16 - x) * 3) + IIf(x < 8, " ", " ")
- this.aComments.Add(cHex + cSpace + cChars)
-
- ENDCLASS // RecordStream Of RepObjBase
-
-
- CLASS DataTable Of AssocArray()
- // Special class used to hold information items
- // regarding data tables used by report.
- // The AssocArray elements are indexed by data
- // field name, and the contents are the data
- // field data type.
- // Not streamed to .REP file.
-
- this.TableName = ""
- this.Alias = ""
- this.ParentTable = ""
- this.ParentField = ""
- this.Order = ""
- this.Error = ""
- this.Tag = ""
- this.aOrders = New OrderArray() // Storage for field sorts
- this.aGroups = New Array() // Storage for group fields
-
- ENDCLASS // DataTable Of AssocArray
-
-
- CLASS OrderArray Of Array()
- // Array class used to accumulate SET ORDER TO...
- // information used to stream SQL ORDER BY...
- // Not streamed to .REP file.
-
- PROCEDURE Add(cExpr, cOrder)
- LOCAL nInd
-
- For nInd = 1 To this.Size / 2
- If this[nInd, 1] == cExpr
- RETURN
- EndIf
- EndFor
- SUPER::Add(cExpr)
- SUPER::Add(cOrder)
-
- ENDCLASS // OrderArray Of Array
-
-
- CLASS CRWBase Of Array
- // Base class used by following classes which
- // accumulate various information elements while
- // the .RPT file is being read.
- // Not streamed to .REP file.
-
-
- this.VdBReportObject = False
- this.Top = 0
- this.Height = 0
- this.Width = 0
-
- ENDCLASS // CRWBase Of Array
-
-
- CLASS CRWBand(xTEMP) Of CRWBase
- // .RPT report band information.
- // Not streamed to .REP file.
-
- this.ID = MAKEU16(xTEMP, 3)
- this.Visible = Not MAKEU16(xTEMP, 5) = 0
- this.NewPageBefore = Not MAKEU16(xTEMP, 7) = 0
- this.NewPageAfter = Not MAKEU16(xTEMP, 9) = 0
- this.KeepSectionTogether = Not MAKEU16(xTEMP, 11) = 0
- this.SuppressBlankLines = Not MAKEU16(xTEMP, 13) = 0
- this.ResetPageNumberAfter = Not MAKEU16(xTEMP, 15) = 0
- this.PrintAtBottomOfPage = Not MAKEU16(xTEMP, 17) = 0
- this.FormatWithMultColumns = Not MAKEU16(xTEMP, 19) = 0
-
- ENDCLASS // CRWBand Of CRWBase
-
-
- CLASS CRWLine Of CRWBase
- // .RPT band line information
- // Not streamed to .REP file.
-
- this.HTMLText = "'<pre>"
-
- PROCEDURE PositionObjectsToBaseline(nMaxWidth)
- LOCAL nIndex, nTemp
-
- For nIndex = 1 To this.Size
- nTemp = this.Top + this.Height - this[nIndex]["Height"]
- If nTemp # 0
- this[nIndex]["Top"] = this.Top + this.Height -;
- this[nIndex]["Height"]
- EndIf
- If this[nIndex].IsKey("Left") And this[nIndex].IsKey("Width")
- If this[nIndex]["Left"] + this[nIndex]["Width"] > nMaxWidth
- this[nIndex]["Left"] = nMaxWidth - this[nIndex]["Width"]
- EndIf
- EndIf
- EndFor
-
- PROCEDURE SetSuppressIfBlank
- LOCAL nIndex
- For nIndex = 1 To this.Size
- this[nIndex]["SuppressIfBlank"] = True
- EndFor
-
- ENDCLASS // CRWLine Of CRWBase
-
-
- CLASS RGBTripleColors Of AssocArray
- // Array used to convert RGB Triple color values
- // in the .RPT file to JavaScript color tags.
- //
- // Note: The hexadecimal values used as the array
- // index are in BBGGRR order which is the order
- // that they are stored in the .RPT file.
- // This template is not streamed to the .REP file.
- // However, the color tags retrieved from this
- // class are streamed to the ColorNormal properties
- // of objects if a match is found. If a match is
- // not found, the hexadecimal BBGGRR value is
- // streamed.
- //
- // For more information regarding JavaScript color
- // tags and hexadecimal color values, see the VdB 7
- // online help 'ColorNormal' topic.
-
- this["FFF8F0"] = "aliceblue"
- this["D7EBFA"] = "antiquewhite"
- this["FFFF00"] = "aqua"
- this["D4FF7F"] = "aquamarine"
- this["FFFFF0"] = "azure"
- this["DCF5F5"] = "beige"
- this["C4E4FF"] = "bisque"
- this["000000"] = "black"
- this["CDEBFF"] = "blanchedalmond"
- this["FF0000"] = "blue"
- this["E22B8A"] = "blueviolet"
- this["2A2AA5"] = "brown"
- this["87B8DE"] = "burlywood"
- this["A09E5F"] = "cadetblue"
- this["00FF7F"] = "chartreuse"
- this["1E69D2"] = "chocolate"
- this["507FFF"] = "coral"
- this["ED9564"] = "cornflowerblue"
- this["DCF8FF"] = "cornsilk"
- this["3C14DC"] = "crimson"
- this["FFFF00"] = "cyan"
- this["8B0000"] = "darkblue"
- this["8B8B00"] = "darkcyan"
- this["0B86B8"] = "darkgoldenrod"
- this["A9A9A9"] = "darkgray"
- this["006400"] = "darkgreen"
- this["6BB7BD"] = "darkkhaki"
- this["8B008B"] = "darkmagenta"
- this["2F6B55"] = "darkolivegreen"
- this["008CFF"] = "darkorange"
- this["CC3299"] = "darkorchid"
- this["00008B"] = "darkred"
- this["7A96E9"] = "darksalmon"
- this["8FBC8F"] = "darkseagreen"
- this["8B3D48"] = "darkslateblue"
- this["4F4F2F"] = "darkslategray"
- this["D1CE00"] = "darkturquoise"
- this["D30094"] = "darkviolet"
- this["9314FF"] = "deeppink"
- this["FFBF00"] = "deepskyblue"
- this["696969"] = "dimgray"
- this["FF901E"] = "dodgerblue"
- this["2222B2"] = "firebrick"
- this["F0FAFF"] = "floralwhite"
- this["228B22"] = "forestgreen"
- this["FF00FF"] = "fuchsia"
- this["DCDCDC"] = "gainsboro"
- this["FFF8F8"] = "ghostwhite"
- this["00D7FF"] = "gold"
- this["20A5DA"] = "goldenrod"
- this["808080"] = "gray"
- this["008000"] = "green"
- this["2FFFAD"] = "greenyellow"
- this["F0FFF0"] = "honeydew"
- this["B469FF"] = "hotpink"
- this["5C5CCD"] = "indianred"
- this["82004B"] = "indigo"
- this["F0FFFF"] = "ivory"
- this["8CE6F0"] = "khaki"
- this["FAE6E6"] = "lavender"
- this["F5F0FF"] = "lavenderblush"
- this["00FC7C"] = "lawngreen"
- this["CDFAFF"] = "lemonchiffon"
- this["E6D8AD"] = "lightblue"
- this["8080F0"] = "lightcoral"
- this["FFFFE0"] = "lightcyan"
- this["D2FAFA"] = "lightgoldenrodyellow"
- this["90EE90"] = "lightgreen"
- this["D3D3D3"] = "lightgrey"
- this["C1B6FF"] = "lightpink"
- this["7AA0FF"] = "lightsalmon"
- this["AAB220"] = "lightseagreen"
- this["FACE87"] = "lightskyblue"
- this["998877"] = "lightslategray"
- this["DEC4B0"] = "lightsteelblue"
- this["E0FFFF"] = "lightyellow"
- this["00FF00"] = "lime"
- this["32CD32"] = "limegreen"
- this["E6F0FA"] = "linen"
- this["FF00FF"] = "magenta"
- this["000080"] = "maroon"
- this["AACD66"] = "mediumaquamarine"
- this["CD0000"] = "mediumblue"
- this["D355BA"] = "mediumorchid"
- this["DB7093"] = "mediumpurple"
- this["71B33C"] = "mediumseagreen"
- this["EE687B"] = "mediumslateblue"
- this["9AFA00"] = "mediumspringgreen"
- this["CCD148"] = "mediumturquoise"
- this["8515C7"] = "mediumvioletred"
- this["701919"] = "midnightblue"
- this["FAFFF5"] = "mintcream"
- this["E1E4FF"] = "mistyrose"
- this["B5E4FF"] = "moccasin"
- this["ADDEFF"] = "navajowhite"
- this["800000"] = "navy"
- this["E6F5FD"] = "oldlace"
- this["008080"] = "olive"
- this["238E6B"] = "olivedrab"
- this["00A5FF"] = "orange"
- this["0045FF"] = "orangered"
- this["D670DA"] = "orchid"
- this["AAE8EE"] = "palegoldenrod"
- this["98FB98"] = "palegreen"
- this["EEEEAF"] = "paleturquoise"
- this["9370DB"] = "palevioletred"
- this["D5EFFF"] = "papayawhip"
- this["B9DAFF"] = "peachpuff"
- this["3F85CD"] = "peru"
- this["CBC0FF"] = "pink"
- this["DDA0DD"] = "plum"
- this["E6E0B0"] = "powderblue"
- this["800080"] = "purple"
- this["0000FF"] = "red"
- this["8F8FBC"] = "rosybrown"
- this["E16941"] = "royalblue"
- this["13458B"] = "saddlebrown"
- this["7280FA"] = "salmon"
- this["60A4F4"] = "sandybrown"
- this["578B2E"] = "seagreen"
- this["EEF5FF"] = "seashell"
- this["2D52A0"] = "sienna"
- this["C0C0C0"] = "silver"
- this["EBCE87"] = "skyblue"
- this["CD5A6A"] = "slateblue"
- this["908070"] = "slategray"
- this["FAFAFF"] = "snow"
- this["7FFF00"] = "springgreen"
- this["B48246"] = "steelblue"
- this["8CB4D2"] = "tan"
- this["808000"] = "teal"
- this["D8BFD8"] = "thistle"
- this["4763FF"] = "tomato"
- this["D0E040"] = "turquoise"
- this["EE82EE"] = "violet"
- this["B3DEF5"] = "wheat"
- this["FFFFFF"] = "white"
- this["F5F5F5"] = "whitesmoke"
- this["00FFFF"] = "yellow"
- this["32CD9A"] = "yellowgreen"
-
- ENDCLASS // RGBTripleColors Of AssocArray
-
- // EOF: RepBuild.CC
-
-