VERSION 5.00
Object = "{3A6F7F80-45E5-11D4-AC3E-ADBCE8B30410}#1.0#0"; "VSRpt7.ocx"
Object = "{A8561640-E93C-11D3-AC3B-CE6078F7B616}#1.0#0"; "VSPRINT7.ocx"
Begin VB.UserControl ArmPrint 
   ClientHeight    =   6630
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   7425
   ScaleHeight     =   6630
   ScaleWidth      =   7425
   Begin VSPrinter7LibCtl.VSPrinter Vp 
      Height          =   4995
      Left            =   840
      TabIndex        =   0
      Top             =   720
      Width           =   5175
      _cx             =   9128
      _cy             =   8811
      Appearance      =   1
      BorderStyle     =   1
      Enabled         =   -1  'True
      MousePointer    =   0
      BackColor       =   -2147483643
      BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} 
         Name            =   "Arial"
         Size            =   11.25
         Charset         =   0
         Weight          =   400
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      BeginProperty HdrFont {0BE35203-8F91-11CE-9DE3-00AA004BB851} 
         Name            =   "Courier New"
         Size            =   14.25
         Charset         =   0
         Weight          =   400
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      _ConvInfo       =   1
      AutoRTF         =   -1  'True
      Preview         =   -1  'True
      DefaultDevice   =   0   'False
      PhysicalPage    =   -1  'True
      AbortWindow     =   -1  'True
      AbortWindowPos  =   0
      AbortCaption    =   "Printing..."
      AbortTextButton =   "Cancel"
      AbortTextDevice =   "on the %s on %s"
      AbortTextPage   =   "Now printing Page %d of"
      FileName        =   ""
      MarginLeft      =   1440
      MarginTop       =   1440
      MarginRight     =   1440
      MarginBottom    =   1440
      MarginHeader    =   0
      MarginFooter    =   0
      IndentLeft      =   0
      IndentRight     =   0
      IndentFirst     =   0
      IndentTab       =   720
      SpaceBefore     =   0
      SpaceAfter      =   0
      LineSpacing     =   100
      Columns         =   1
      ColumnSpacing   =   180
      ShowGuides      =   1
      LargeChangeHorz =   300
      LargeChangeVert =   300
      SmallChangeHorz =   30
      SmallChangeVert =   30
      Track           =   0   'False
      ProportionalBars=   -1  'True
      Zoom            =   24.8441674087266
      ZoomMode        =   3
      ZoomMax         =   400
      ZoomMin         =   10
      ZoomStep        =   25
      EmptyColor      =   -2147483636
      TextColor       =   0
      HdrColor        =   0
      BrushColor      =   0
      BrushStyle      =   0
      PenColor        =   0
      PenStyle        =   0
      PenWidth        =   0
      PageBorder      =   0
      Header          =   ""
      Footer          =   ""
      TableSep        =   "|;"
      TableBorder     =   7
      TablePen        =   0
      TablePenLR      =   0
      TablePenTB      =   0
      NavBar          =   3
      NavBarColor     =   -2147483633
      ExportFormat    =   0
      URL             =   ""
      Navigation      =   3
      NavBarMenuText  =   "Whole &Page|Page &Width|&Two Pages|Thumb&nail"
   End
   Begin VSREPORTLibCtl.VSReport Report 
      Left            =   120
      Top             =   120
      _rv             =   700
      _rx             =   236958670
      ReportName      =   ""
      BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} 
         Name            =   "Arial"
         Size            =   9
         Charset         =   0
         Weight          =   400
         Underline       =   0   'False
         Italic          =   0   'False
         Strikethrough   =   0   'False
      EndProperty
      OnOpen          =   ""
      OnClose         =   ""
      OnNoData        =   ""
      OnPage          =   ""
      OnError         =   ""
      MaxPages        =   0
      DoEvents        =   -1  'True
      BeginProperty Layout {8F5A70A3-B6D3-11D3-9A1F-800A5BACB530} 
         Width           =   9114
         MarginLeft      =   1440
         MarginTop       =   1440
         MarginRight     =   1440
         MarginBottom    =   1440
         Columns         =   1
         ColumnLayout    =   0
         Orientation     =   1
         PageHeader      =   0
         PageFooter      =   0
         PictureAlign    =   7
         PictureShow     =   1
         PaperSize       =   0
      EndProperty
      BeginProperty DataSource {8F5A70A1-B6D3-11D3-9A1F-800A5BACB530} 
         ConnectionString=   ""
         RecordSource    =   ""
         Filter          =   ""
         MaxRecords      =   0
      EndProperty
      GroupCount      =   0
      SectionCount    =   5
      BeginProperty Section0 {E5849A61-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Detail"
         Visible         =   -1  'True
         Height          =   1335
         CanGrow         =   -1  'True
         CanShrink       =   0   'False
         KeepTogether    =   -1  'True
         ForcePageBreak  =   0
         BackColor       =   16777215
         Repeat          =   0   'False
         OnFormat        =   ""
         OnPrint         =   ""
      EndProperty
      BeginProperty Section1 {E5849A61-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Header"
         Visible         =   -1  'True
         Height          =   1000
         CanGrow         =   -1  'True
         CanShrink       =   0   'False
         KeepTogether    =   -1  'True
         ForcePageBreak  =   0
         BackColor       =   16777215
         Repeat          =   0   'False
         OnFormat        =   ""
         OnPrint         =   ""
      EndProperty
      BeginProperty Section2 {E5849A61-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Footer"
         Visible         =   0   'False
         Height          =   0
         CanGrow         =   -1  'True
         CanShrink       =   0   'False
         KeepTogether    =   -1  'True
         ForcePageBreak  =   0
         BackColor       =   16777215
         Repeat          =   0   'False
         OnFormat        =   ""
         OnPrint         =   ""
      EndProperty
      BeginProperty Section3 {E5849A61-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Page Header"
         Visible         =   0   'False
         Height          =   0
         CanGrow         =   -1  'True
         CanShrink       =   0   'False
         KeepTogether    =   -1  'True
         ForcePageBreak  =   0
         BackColor       =   16777215
         Repeat          =   0   'False
         OnFormat        =   ""
         OnPrint         =   ""
      EndProperty
      BeginProperty Section4 {E5849A61-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Page Footer"
         Visible         =   -1  'True
         Height          =   500
         CanGrow         =   -1  'True
         CanShrink       =   0   'False
         KeepTogether    =   -1  'True
         ForcePageBreak  =   0
         BackColor       =   16777215
         Repeat          =   0   'False
         OnFormat        =   ""
         OnPrint         =   ""
      EndProperty
      FieldCount      =   5
      BeginProperty Field0 {E5849A63-ADD9-11D3-BDEB-000000000000} 
         Name            =   "TitleLbl"
         Text            =   "New Report"
         Object.Left            =   0
         Object.Top             =   95
         Width           =   9024
         Height          =   600
         BackColor       =   16777215
         ForeColor       =   0
         BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} 
            Name            =   "Times New Roman"
            Size            =   24
            Charset         =   0
            Weight          =   400
            Underline       =   0   'False
            Italic          =   0   'False
            Strikethrough   =   0   'False
         EndProperty
         Align           =   6
         BackStyle       =   0
         BorderColor     =   0
         BorderStyle     =   0
         CanGrow         =   0   'False
         CanShrink       =   0   'False
         Visible         =   -1  'True
         HideDuplicates  =   0   'False
         RunningSum      =   0
         Format          =   ""
         LineSlant       =   0
         LineWidth       =   0
         PictureAlign    =   0
         MarginLeft      =   0
         MarginTop       =   0
         MarginRight     =   0
         MarginBottom    =   0
         Section         =   1
         ForcePageBreak  =   0
         Calculated      =   0   'False
         WordWrap        =   -1  'True
         LineSpacing     =   0
         CheckBox        =   0
         RTF             =   0   'False
      EndProperty
      BeginProperty Field1 {E5849A63-ADD9-11D3-BDEB-000000000000} 
         Name            =   "FooterLeft"
         Text            =   "Now()"
         Object.Left            =   0
         Object.Top             =   30
         Width           =   4512
         Height          =   300
         BackColor       =   16777215
         ForeColor       =   0
         BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} 
            Name            =   "Arial"
            Size            =   8.25
            Charset         =   0
            Weight          =   400
            Underline       =   0   'False
            Italic          =   0   'False
            Strikethrough   =   0   'False
         EndProperty
         Align           =   0
         BackStyle       =   0
         BorderColor     =   0
         BorderStyle     =   0
         CanGrow         =   0   'False
         CanShrink       =   0   'False
         Visible         =   -1  'True
         HideDuplicates  =   0   'False
         RunningSum      =   0
         Format          =   ""
         LineSlant       =   0
         LineWidth       =   0
         PictureAlign    =   0
         MarginLeft      =   0
         MarginTop       =   0
         MarginRight     =   0
         MarginBottom    =   0
         Section         =   4
         ForcePageBreak  =   0
         Calculated      =   -1  'True
         WordWrap        =   -1  'True
         LineSpacing     =   0
         CheckBox        =   0
         RTF             =   0   'False
      EndProperty
      BeginProperty Field2 {E5849A63-ADD9-11D3-BDEB-000000000000} 
         Name            =   "FooterRight"
         Text            =   """Page "" & [Page] & "" of "" & [Pages]"
         Object.Left            =   4512
         Object.Top             =   30
         Width           =   4512
         Height          =   300
         BackColor       =   16777215
         ForeColor       =   0
         BeginProperty Font {0BE35203-8F91-11CE-9DE3-00AA004BB851} 
            Name            =   "Arial"
            Size            =   8.25
            Charset         =   0
            Weight          =   400
            Underline       =   0   'False
            Italic          =   0   'False
            Strikethrough   =   0   'False
         EndProperty
         Align           =   2
         BackStyle       =   0
         BorderColor     =   0
         BorderStyle     =   0
         CanGrow         =   0   'False
         CanShrink       =   0   'False
         Visible         =   -1  'True
         HideDuplicates  =   0   'False
         RunningSum      =   0
         Format          =   ""
         LineSlant       =   0
         LineWidth       =   0
         PictureAlign    =   0
         MarginLeft      =   0
         MarginTop       =   0
         MarginRight     =   0
         MarginBottom    =   0
         Section         =   4
         ForcePageBreak  =   0
         Calculated      =   -1  'True
         WordWrap        =   -1  'True
         LineSpacing     =   0
         CheckBox        =   0
         RTF             =   0   'False
      EndProperty
      BeginProperty Field3 {E5849A63-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Label"
         Text            =   "Label"
         Object.Left            =   720
         Object.Top             =   450
         Width           =   1260
         Height          =   270
         BackColor       =   16777215
         ForeColor       =   0
         Align           =   -1
         BackStyle       =   0
         BorderColor     =   0
         BorderStyle     =   0
         CanGrow         =   0   'False
         CanShrink       =   0   'False
         Visible         =   -1  'True
         HideDuplicates  =   0   'False
         RunningSum      =   0
         Format          =   ""
         LineSlant       =   0
         LineWidth       =   0
         PictureAlign    =   0
         MarginLeft      =   0
         MarginTop       =   0
         MarginRight     =   0
         MarginBottom    =   0
         Section         =   0
         ForcePageBreak  =   0
         Calculated      =   0   'False
         WordWrap        =   -1  'True
         LineSpacing     =   0
         CheckBox        =   0
         RTF             =   0   'False
      EndProperty
      BeginProperty Field4 {E5849A63-ADD9-11D3-BDEB-000000000000} 
         Name            =   "Calculated Field"
         Text            =   "weqweqw"
         Object.Left            =   2610
         Object.Top             =   360
         Width           =   1170
         Height          =   360
         BackColor       =   16777215
         ForeColor       =   0
         Align           =   -1
         BackStyle       =   0
         BorderColor     =   0
         BorderStyle     =   0
         CanGrow         =   0   'False
         CanShrink       =   0   'False
         Visible         =   -1  'True
         HideDuplicates  =   0   'False
         RunningSum      =   0
         Format          =   ""
         LineSlant       =   0
         LineWidth       =   0
         PictureAlign    =   0
         MarginLeft      =   0
         MarginTop       =   0
         MarginRight     =   0
         MarginBottom    =   0
         Section         =   0
         ForcePageBreak  =   0
         Calculated      =   -1  'True
         WordWrap        =   -1  'True
         LineSpacing     =   0
         CheckBox        =   0
         RTF             =   0   'False
      EndProperty
   End
End
Attribute VB_Name = "ArmPrint"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Const SEP = "ой"                  'standard armstrong separator
Dim mo_Db As Object

'name of server when  creating internal connection
Private ms_Server As String
'name of database to connect
Private ms_Db As String
'user name when opening connection to sql server
Private ms_User As String
'user passwrod
Private ms_Pwd As String
'application name displayed in connection row in sql server manager
Private ms_App As String
'if component has created its own connection or got connected armdb instance
Private mb_InternalConnection As Boolean
'collection of internal reports
Private mo_Reports As Collection
'trace component reference
Private mo_Trace As Object
'cursor which contains dataset used by translating labels in reports
Private ml_LabelCursor As Long
'external request which will create label cursor
Private ms_LabelRequest As String
'name of field which contains label name in label cursor
Private ms_LabelField As String
'name of field which contains translated text
Private ms_TextField As String
'request used to insert keys into temporary key table
Private ms_InsertTempKeyRequest As String
'request to create temporary table
Private ms_CreateTempTableRequest As String
'request to drop temporary table
Private ms_DropTempTableRequest As String
'main request used to get records for report pages, each record starts new erport on new page
Private ms_Request As String
'number of key which are inserted into temporary key table in one go
Private ml_InsertTempKeyCount As Long
'array of keys
Private mv_MultiKey As Variant
'requests and field names array to get special fiedls values into report
Private mv_SpecialFields As Variant
'array of placeholders and their values
Private mv_Placeholders As Variant
'orientation of the report
Private mv_Orientation As OrientationSettings
'margins left and right
Private ml_MarginLeft As Long, ml_MarginRight As Long
'margins top and bottom
Private ml_MarginTop As Long, ml_MarginBottom As Long
'path and name of xml report builder template file
Private ms_XML_Path As String
'text which is printed in footer of each page
Private ms_FooterText As String
'this variable contains current page when printing footer
Private ml_CurrentPage As Long
'this variable contains total number of pages when printing footer
Private ml_TotalPages As Long
'this is font style of title for each detail title (header title or table title)
Private mo_TitleFont As StdFont
'this is font style of footer text
Private mo_FooterFont As StdFont
'charset number for report
Private mi_Charset As Integer

'******************************************************************************
' public properties
'******************************************************************************

'property to get or set armdb instance
Public Property Set ArmDb(ByRef lo_Db As Object)
  Set mo_Db = lo_Db
End Property

Public Property Get ArmDb() As Object
  Set ArmDb = mo_Db
End Property

'main trace component reference (needed when you set CompDebug or CompDebugPR values)
Public Property Set ArmTrace(ByVal lo_NewValue As Object)

  Set mo_Trace = lo_NewValue
End Property

Public Property Get ArmTrace() As Object
  Set ArmTrace = mo_Trace
End Property

'this allows to set orientation of report - portrait or landscape
Public Property Let Orientation(au_Value As OrientationSettings)

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Orientation_Let")
#End If
  
  mv_Orientation = au_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Orientation_Let")
#End If
End Property

'set margin of report
Public Property Let MarginLeft(al_Value As Long)

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:MarginLeft_Let")
#End If
  
  ml_MarginLeft = al_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:MarginLeft_Let")
#End If
End Property

'set margin of report
Public Property Let MarginRight(al_Value As Long)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:MarginRight_Let")
#End If
  
  ml_MarginRight = al_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:MarginRight_Let")
#End If
End Property

'set margin of report
Public Property Let MarginTop(al_Value As Long)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:MarginTop_Let")
#End If
  
  ml_MarginTop = al_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:MarginTop_Let")
#End If
End Property

'set margin of report
Public Property Let MarginBottom(al_Value As Long)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:MarginBottom_Let")
#End If
  
  ml_MarginBottom = al_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:MarginBottom_Let")
#End If
End Property

'set charset of report
Public Property Let Charset(ai_Value As Integer)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Charset_Let")
#End If
  
  mi_Charset = ai_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Charset_Let")
#End If
End Property

Public Property Get Charset() As Integer
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Charset_Get")
#End If
  
  Charset = mi_Charset

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Charset_Get")
#End If
End Property

'set font style of footer text
Public Property Get FooterFont() As StdFont
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:FooterFont_Let")
#End If
  
  Set FooterFont = mo_FooterFont

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:FooterFont_Let")
#End If
End Property

'set font style of header or table title text
Public Property Get TitleFont() As StdFont
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:TitleFont_Let")
#End If
  
  Set TitleFont = mo_TitleFont

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:TitleFont_Let")
#End If
End Property

'set footer text which is displayed on each page
Public Property Let FooterText(as_Value As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:FooterText_Let")
#End If
  ms_FooterText = as_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:FooterText_Let")
#End If
End Property

'set name of XML template report builder path vaild for entire report
Public Property Let XML_Path(as_Value As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:XML_Path_Let")
#End If
  
  ms_XML_Path = as_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:XML_Path_Let")
#End If
End Property

'sql request which insert many temporary keys into temp table in one go
Property Let InsertTempKeyRequest(as_Value As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:InsertTempKeyRequest_Let")
#End If
  
  ms_InsertTempKeyRequest = as_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:InsertTempKeyRequest_Let")
#End If
End Property

Property Get InsertTempKeyRequest() As String
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:InsertTempKeyRequest_Get")
#End If
  
  InsertTempKeyRequest = ms_InsertTempKeyRequest

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:InsertTempKeyRequest_Get")
#End If
End Property

Property Let CreateTempTableRequest(as_Value As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:CreateTempTableRequest_Let")
#End If
  
  ms_CreateTempTableRequest = as_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:CreateTempTableRequest_Let")
#End If
End Property

Property Get CreateTempTableRequest() As String
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:CreateTempTableRequest_Get")
#End If
  
  CreateTempTableRequest = ms_CreateTempTableRequest

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:CreateTempTableRequest_Get")
#End If
End Property

Property Let DropTempTableRequest(as_Value As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:DropTempTableRequest_Let")
#End If
  
  ms_DropTempTableRequest = as_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:DropTempTableRequest_Let")
#End If
End Property

Property Get DropTempTableRequest() As String
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:DropTempTableRequest_Get")
#End If
  
  DropTempTableRequest = ms_DropTempTableRequest

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:DropTempTableRequest_Get")
#End If
End Property

'number of keys inserted into temporary table in one go
Property Let InsertTempKeyCount(al_Value As Long)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:InsertTempKeyCount_Let")
#End If
  
  ml_InsertTempKeyCount = al_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:InsertTempKeyCount_Let")
#End If
End Property

Property Get InsertTempKeyCount() As Long
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:InsertTempKeyCount_Get")
#End If
  
  InsertTempKeyCount = ml_InsertTempKeyCount

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:InsertTempKeyCount_Get")
#End If
End Property

'main request responsible to load main report records - each record start erport on new page
Property Let Request(as_Value As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Request_Let")
#End If
  
  ms_Request = as_Value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Request_Let")
#End If
End Property

Property Get Request() As String
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Request_Get")
#End If
  
  Request = ms_Request

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Request_Get")
#End If
End Property

'access to internal collection of report definitions, you can access this before call of execute
Property Get ReportList(al_Index As Long) As ArmReport
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:ReportList_Get")
#End If
  
  Set ReportList = Nothing
  If (al_Index > 0) And (al_Index <= mo_Reports.Count) Then
    Set ReportList = mo_Reports(al_Index)
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:ReportList_Get")
#End If
End Property

'set array of key compatible to armgrid
Property Let MultiKey(av_Value As Variant)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:MultiKey_Let")
#End If
  
  If IsArray(av_Value) Then
    mv_MultiKey = av_Value
  Else
    mv_MultiKey = Array(av_Value)
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:MultiKey_Let")
#End If
End Property

Property Get MultiKey() As Variant
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:MultiKey_Get")
#End If
  
  MultiKey = mv_MultiKey

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:MultiKey_Get")
#End If
End Property

'set and get array of special field names and requests to get values for those fields into report
Property Let SpecialFields(av_Value As Variant)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:SpecialFields_Let")
#End If
  
  If IsArray(av_Value) Then
    mv_SpecialFields = av_Value
  Else
    mv_SpecialFields = Array(av_Value)
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:SpecialFields_Let")
#End If
End Property

Property Get SpecialFields() As Variant
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:SpecialFields_Get")
#End If
  
  SpecialFields = mv_SpecialFields

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:SpecialFields_Get")
#End If
End Property

'set and get array of placeholders and their values which helps to create requests
Property Let Placeholders(av_Value As Variant)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Placeholders_Let")
#End If
  
  If IsArray(av_Value) Then
    mv_Placeholders = av_Value
  Else
    mv_Placeholders = Array(av_Value)
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Placeholders_Let")
#End If
End Property

Property Get Placeholders() As Variant
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Placeholders_Get")
#End If
  
  Placeholders = mv_Placeholders

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Placeholders_Get")
#End If
End Property

'number of report definitions in ArmPrint instance
Property Let ReportCount(al_Value As Long)
Dim lo_Report As ArmReport
Dim ll_Index As Long
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:ReportCount_Let")
#End If
  
  Call Reset
  For ll_Index = 0 To al_Value - 1
    Set lo_Report = New ArmReport
    Call mo_Reports.Add(lo_Report)
  Next

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:ReportCount_Let")
#End If
End Property

Property Get ReportCount() As Long

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:ReportCount_Get")
#End If
  
  ReportCount = 0
  If Not (mo_Reports Is Nothing) Then
    ReportCount = mo_Reports.Count
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:ReportCount_Get")
#End If
End Property

'set values for connection to sql server. If there is not connected armdb instance, create its own internal connection
Property Let ConnectString(as_Value As String)
Dim la_Params() As String

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:ConnectString_Let")
#End If
  
  If (as_Value <> "") Then
    la_Params = Split(as_Value, SEP, 5)
    ms_Server = la_Params(0)
    ms_Db = la_Params(1)
    ms_User = la_Params(2)
    ms_Pwd = la_Params(3)
    If UBound(la_Params) >= 4 Then
      ms_App = la_Params(4)
    Else
      ms_App = "ArmPrint"
    End If
  Else
    ms_Server = ""
    ms_Db = ""
    ms_User = ""
    ms_Pwd = ""
  End If
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:ConnectString_Let")
#End If
  Exit Property
ErrorHandler:
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:ConnectString_Let", "as_Value=" & as_Value)
#End If
End Property

'******************************************************************************
' public methods
'******************************************************************************

Public Sub Load_A_Com()
  
  Set mo_Reports = New Collection
  Set mo_TitleFont = New StdFont
  mo_TitleFont.Name = "Arial"
  mo_TitleFont.Size = 10
  mo_TitleFont.Bold = True
  Set mo_FooterFont = New StdFont
  mo_FooterFont.Name = "Arial"
  mo_FooterFont.Size = 8
  mv_Orientation = orPortrait
  ml_MarginLeft = 800
  ml_MarginRight = 800
  ml_MarginTop = 800
  ml_MarginBottom = 800
End Sub

Public Sub Unload_A_Com()
  
  Call Reset
  Set mo_Reports = Nothing
  If mb_InternalConnection Then CloseConnection
  Set mo_Db = Nothing
  Set mo_TitleFont = Nothing
  Set mo_FooterFont = Nothing
  Set mo_Trace = Nothing
End Sub

Public Function Execute() As Boolean
Dim ll_Cursor As Long, ll_CursorTable As Long
Dim lo_Report As ArmReport

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Execute")
#End If
  Call SetMousePointer(False)
  'set basic report properties like margin, orientation
  Vp.Orientation = mv_Orientation
  Vp.PaperSize = pprA4
  Vp.MarginLeft = ml_MarginLeft
  Vp.MarginRight = ml_MarginRight
  Vp.MarginTop = ml_MarginTop
  Vp.MarginBottom = ml_MarginBottom
  ml_CurrentPage = 0
  ml_TotalPages = 0
  'start print document
  Vp.StartDoc
  'continue printing only if there is main request and non zero number of detail reports
  If (ReportCount > 0) And (ms_Request <> "") And (ms_CreateTempTableRequest <> "") And _
     (ms_DropTempTableRequest <> "") And (ms_InsertTempKeyRequest <> "") Then
    'create and fill temporary key table with keys from MultiKey property
    If FillTempKeyTable Then
      ml_LabelCursor = OpenCursor(ms_LabelRequest)
      ll_Cursor = OpenCursor(ms_Request)
      'we can drop table, data are already loaded and temp key table is not needed anymore
      Call DropTempTable
      If ll_Cursor <> 0 Then
        Call mo_Db.First(ll_Cursor)
        Do While Not mo_Db.EOF(ll_Cursor)
          'start new page on every new main record
          If mo_Db.Position(ll_Cursor) > 0 Then Vp.NewPage
          'set position of active cursor
          Vp.CurrentX = Vp.MarginLeft
          Vp.CurrentY = Vp.MarginTop
          'print all detail reports
          For Each lo_Report In mo_Reports
            If lo_Report.Display Then
              Call Report.Load(ms_XML_Path, lo_Report.Name)
              'print master header
              If lo_Report.ReportType = rptDetailHeader Then
                If lo_Report.Request = "" Then
                  Call PrintHeader(lo_Report.Title, Report, ll_Cursor)
                Else
                  ll_CursorTable = OpenCursor(lo_Report.Request, ll_Cursor)
                  'if cursor is zero, print header prints not initialized header
                  Call PrintHeader(lo_Report.Title, Report, ll_CursorTable)
                  Call CloseCursor(ll_CursorTable)
                End If
              ElseIf lo_Report.ReportType = rptDetailTable Then
                ll_CursorTable = OpenCursor(lo_Report.Request, ll_Cursor)
                'if cursor is zero, print header prints not initialized table
                'print detail tables
                Call PrintTable(lo_Report.Title, Report, ll_CursorTable)
                'close cursor
                Call CloseCursor(ll_CursorTable)
              End If
            End If
          Next
          Call mo_Db.Next(ll_Cursor)
        Loop
      End If
    End If
  End If
  Vp.EndDoc
  'ad page footer to each page
  Call AddPageFooter
  'close main and label translation cursor
  Call CloseCursor(ll_Cursor)
  Call CloseCursor(ml_LabelCursor)
  Call SetMousePointer(True)
  Execute = True
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Execute")
#End If
Exit Function
ErrorHandler:
  'close all unclosed cursor in case of exception
  Call CloseCursor(ll_Cursor)
  Call CloseCursor(ml_LabelCursor)
  Call CloseCursor(ll_CursorTable)
  Execute = False
  Call SetMousePointer(True)
#If CompDebug Then
    Call mo_Trace.WriteTraceError("ArmPrint:Execute", "ms_Request=" & ms_Request)
#End If
End Function

Public Function PrintReport() As Boolean

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:PrintReport")
#End If

  Call Vp.PrintDoc
  PrintReport = True

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:PrintReport")
#End If
  Exit Function
ErrorHandler:
#If CompDebug Then
    Call mo_Trace.WriteTraceError("ArmPrint:Execute")
#End If
End Function

Public Function IsConnected() As Boolean
Dim lb_Result As Boolean

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:IsConnected")
#End If
  
  IsConnected = False
  If Not mo_Db Is Nothing Then
    IsConnected = mo_Db.IsConnected
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:IsConnected")
#End If
End Function

Public Sub SetConstantRequest(as_Request As String, as_LabelField As String, as_TextField As String)
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:SetConstantRequest")
#End If
  
  ms_LabelRequest = as_Request
  ms_LabelField = as_LabelField
  ms_TextField = as_TextField

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:SetConstantRequest")
#End If
End Sub

Public Function SetReportList(av_Reports As Variant)
Dim lb_Result As Boolean
Dim ll_Index As Long
Dim lv_Report As Variant
Dim lo_Report As ArmReport

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:SetReportList")
#End If
  
  lb_Result = False
  
  If IsArray(av_Reports) Then
    
    If ReportCount <> UBound(av_Reports) + 1 Then GoTo ErrorHandler
    
    lb_Result = True
    For ll_Index = 0 To UBound(av_Reports)
      lv_Report = av_Reports(ll_Index)
      Set lo_Report = mo_Reports(ll_Index + 1)
      
      lo_Report.Name = lv_Report(0)
      lo_Report.Title = lv_Report(1)
      
      If StrComp(lv_Report(2), "HEADER", vbTextCompare) = 0 Then
        lo_Report.ReportType = rptDetailHeader
      ElseIf StrComp(lv_Report(2), "TABLE", vbTextCompare) = 0 Then
        lo_Report.ReportType = rptDetailTable
      Else
        GoTo ErrorHandler
      End If
      
      lo_Report.Request = lv_Report(3)
      lo_Report.Display = lv_Report(4)
    Next
  End If
  SetReportList = lb_Result

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:SetReportList")
#End If
  Exit Function
ErrorHandler:
  Call Reset
  SetReportList = False
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:SetReportList", "ll_Index=" & ll_Index)
#End If
End Function

'******************************************************************************
' private methods
'******************************************************************************

Private Function Reset() As Boolean

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:Reset")
#End If
  
  Call DeleteCollection
  Reset = True

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:Reset")
#End If
End Function

'open conection and create own instance of ArmDB if it was not passed through property
Private Function OpenConnection(as_Server As String, as_Db As String, as_User As String, _
    as_Pwd As String, as_App As String) As Boolean
Dim lb_Result As Boolean

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:OpenConnection")
#End If

  lb_Result = False
  If Not IsConnected Then
    mb_InternalConnection = True
    If mo_Db Is Nothing Then
      Set mo_Db = CreateObject("ARMSYSCOM.ArmDb")
    End If

    If (as_Server <> "") And (as_Db <> "") And (as_User <> "") Then
        If mo_Db.Connect(as_Server, as_Db, as_User, as_Pwd, as_App) Then
          lb_Result = mo_Db.IsConnected
        Else
#If CompDebug Then
          Call mo_Trace.WriteTraceSQLError(mo_Db, "ArmPrint:OpenConnectionn")
#End If
        End If
    End If
  End If
  OpenConnection = lb_Result

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:OpenConnection")
#End If
  Exit Function
ErrorHandler:
  OpenConnection = False
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:OpenConnection", "as_Server=" & as_Server, _
  "as_Db=" & as_Db, "as_User=" & as_User)
#End If
End Function

'close connection if connection was created with OpenConnection method and
Private Sub CloseConnection()

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:CloseConnection")
#End If
 
  If IsConnected Then
    Call mo_Db.Disconnect
    mb_InternalConnection = False
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:CloseConnection")
#End If
  Exit Sub
ErrorHandler:
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:CloseConnection")
#End If
End Sub

Private Sub UserControl_Resize()

  Vp.Left = 0
  Vp.Top = 0
  If UserControl.Height > 0 Then
    Vp.Height = UserControl.Height
  End If
  If UserControl.Width > 0 Then
    Vp.Width = UserControl.Width
  End If
End Sub

Private Function FindSpecialRequest(as_FieldName As String)
Dim ll_Index As Long
Dim ls_Request As String
Dim ls_Params() As String

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:FindSpecialRequest")
#End If
  
  ls_Request = ""
  If IsArray(mv_SpecialFields) Then
    For ll_Index = 0 To UBound(mv_SpecialFields)
      ls_Params = Split(mv_SpecialFields(ll_Index), SEP)
      If UBound(ls_Params) = 1 Then
        If StrComp(ls_Params(0), as_FieldName, vbTextCompare) = 0 Then
          ls_Request = ls_Params(1)
          Exit For
        End If
      End If
    Next
  End If
  FindSpecialRequest = ls_Request
  
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:FindSpecialRequest")
#End If
  Exit Function
ErrorHandler:
  FindSpecialRequest = ""
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:FindSpecialRequest", "as_FieldName=" & as_FieldName)
#End If
End Function

Private Function GetSeparatedDataFromSQL(as_Request As String, al_cursor As Long, as_Format As String) As String
Dim ll_Cursor As Long
Dim ls_value As String

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:GetSeparatedDataFromSQL")
#End If
  
  ls_value = ""
  ll_Cursor = OpenCursor(as_Request, al_cursor)
  
  If ll_Cursor Then
    Call mo_Db.First(ll_Cursor)
    While Not mo_Db.EOF(ll_Cursor)
      If mo_Db.Position(ll_Cursor) > 0 Then ls_value = ls_value & ","
      ls_value = ls_value & FormatDataString(mo_Db.GetFields(ll_Cursor, 0), as_Format)
      Call mo_Db.Next(ll_Cursor)
    Wend
  End If
  
  Call CloseCursor(ll_Cursor)
  GetSeparatedDataFromSQL = ls_value

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:GetSeparatedDataFromSQL")
#End If
  Exit Function
ErrorHandler:
  Call CloseCursor(ll_Cursor)
  GetSeparatedDataFromSQL = ""
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:GetSeparatedDataFromSQL", "as_Request=" & as_Request, _
    "ls_Value=" & ls_value, "al_Cursor=" & al_cursor)
#End If
End Function

Private Function TranslateLabel(ByVal as_LabelName As String) As String
Dim ls_Text As String
  
On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:TranslateLabel")
#End If
  
  ls_Text = as_LabelName
  If ml_LabelCursor Then
    If Left(as_LabelName, 1) = "#" Then
      as_LabelName = right(as_LabelName, Len(as_LabelName) - 1)
      If mo_Db.Find(ml_LabelCursor, ms_LabelField, as_LabelName, , 1) >= 0 Then
        ls_Text = mo_Db.GetFields(ml_LabelCursor, ms_TextField)
      End If
    End If
  End If
  TranslateLabel = ls_Text

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:TranslateLabel")
#End If
  Exit Function
ErrorHandler:
  TranslateLabel = ""
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:TranslateLabel", "as_LabelName=" & as_LabelName, _
    "ls_Text=" & ls_Text, "ml_LabelCursor=" & ml_LabelCursor)
#End If
End Function

Private Function GetFieldArray(as_FieldName As String) As Variant
Dim lv_FieldsStr As Variant, lv_FieldsVar As Variant
Dim ll_FieldIndex As Long

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:GetFieldArray")
#End If
  
  'split field names if they are concatenated
  lv_FieldsStr = Split(as_FieldName, "+")
  If IsArray(lv_FieldsStr) Then
    'this conversion from string array to variant array is needed because of
    'ArmDb cannot handle array of strings only variant array
    ReDim lv_FieldsVar(UBound(lv_FieldsStr))
    For ll_FieldIndex = 0 To UBound(lv_FieldsStr)
      lv_FieldsVar(ll_FieldIndex) = lv_FieldsStr(ll_FieldIndex)
    Next
  Else
    lv_FieldsVar = lv_FieldsStr
  End If
  GetFieldArray = lv_FieldsVar

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:GetFieldArray")
#End If
  Exit Function
ErrorHandler:
  GetFieldArray = ""
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:GetFieldArray", "as_FieldName=" & as_FieldName)
#End If
End Function

Private Function FormatDataString(ByVal as_Value As String, as_Format As String) As String
Dim ls_value As String
On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:FormatDataString")
#End If

  ls_value = Trim(as_Value)
  If as_Format <> "" Then
    Select Case UCase(as_Format)
    Case "DATE"
      ls_value = Format(ls_value, "dd.mm.yyyy")
    Case "TIME"
      ls_value = Format(ls_value, "HH:MM:SS")
    Case "PERCENTAGE"
      ls_value = Format(ls_value, "0.00%")
    Case Else
      ls_value = Format(ls_value, as_Format)
    End Select
  End If
  
  FormatDataString = ls_value
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:FormatDataString")
#End If
  Exit Function
ErrorHandler:
  FormatDataString = as_Value
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:FormatDataString", "as_Value=" & as_Value, "as_Format=" & as_Format)
#End If
End Function

Private Function GetDataString(av_Fields As Variant, ByVal as_Format As String, al_cursor As Long, al_Row As Long) As String
Dim ls_Data As String
Dim lv_Value As Variant
Dim ll_Index As Long

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:GetDataString")
#End If
  
  ls_Data = ""
  lv_Value = mo_Db.GetFieldsAt(al_cursor, al_Row, av_Fields)
  If IsArray(lv_Value) Then
    For ll_Index = 0 To UBound(lv_Value)
      If ll_Index > 0 Then ls_Data = ls_Data & " "
      ls_Data = ls_Data & FormatDataString(lv_Value(ll_Index), as_Format)
    Next
    ls_Data = Trim(ls_Data)
  Else
    ls_Data = FormatDataString(lv_Value, as_Format)
  End If
  GetDataString = ls_Data

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:GetDataString")
#End If
  Exit Function
ErrorHandler:
  GetDataString = ""
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:GetDataString", "ls_Data=" & ls_Data, "al_Cursor=" & al_cursor, "al_Row=" & al_Row)
#End If
End Function

Private Sub AddPageFooter()

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:AddPageFooter")
#End If
 
 ' pass 2: add the headers (not really a "pass"...)
  Vp.Font = mo_FooterFont
  ml_TotalPages = Vp.PageCount
  For ml_CurrentPage = 1 To ml_TotalPages
    Vp.StartOverlay ml_CurrentPage
    Vp.CurrentX = Vp.MarginLeft
    Vp.CurrentY = Vp.PageHeight - Vp.MarginBottom
    Vp.Text = ReplacePlaceholders(ms_FooterText)
    Vp.EndOverlay
  Next

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:AddPageFooter")
#End If
  Exit Sub
ErrorHandler:
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:AddPageFooter")
#End If
End Sub

'Print report header for main request or report request
Private Sub PrintHeader(ls_Title As String, lo_rpt As Object, ll_Cursor As Long)
Dim ll_RepField As Long
Dim ll_CurField As Long
Dim lo_Field As Object
Dim ll_CurX As Long, ll_CurY As Long, ll_X As Long, ll_Y As Long, ll_W As Long, ll_H As Long
Dim ld_ScaleX As Double
Dim ls_SpecialRequest As String

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:PrintHeader")
#End If
  
  Vp.Font = mo_TitleFont
  Vp.Font.Charset = mi_Charset
  
  Vp = TranslateLabel(ls_Title)
  ll_CurX = Vp.CurrentX
  ll_CurY = Vp.CurrentY
  
  ld_ScaleX = CDbl(Vp.PageWidth - Vp.MarginLeft - Vp.MarginRight) / CDbl(lo_rpt.Layout.Width)
  'replace texts in report to text from cursor
  For ll_RepField = 0 To lo_rpt.Sections(0).Fields.Count - 1
    Set lo_Field = lo_rpt.Sections(0).Fields(ll_RepField)
    ll_CurField = mo_Db.GetFieldIndex(ll_Cursor, lo_Field.Name)
    If ll_CurField >= 0 Then
      'field is found in cursor so set its value to report
      lo_Field.Text = FormatDataString(mo_Db.GetFields(ll_Cursor, ll_CurField), lo_Field.Format)
    Else
      'if field is not found in cursor, then look if we do not have custom procedure for it
      ls_SpecialRequest = FindSpecialRequest(lo_Field.Name)
      If ls_SpecialRequest = "" Then
        If Left(lo_Field.Name, 1) = "#" Then
        'special request not found, look like ordinary label, translate it
          lo_Field.Text = TranslateLabel(lo_Field.Name)
        Else
          'display text which is hardcoded in report
        End If
      Else
        'special request found, so execute it and fill with data
        lo_Field.Text = GetSeparatedDataFromSQL(ls_SpecialRequest, ll_Cursor, lo_Field.Format)
      End If
    End If
  Next
  
  'copy (render) report to page header
  For ll_RepField = 0 To lo_rpt.Sections(0).Fields.Count - 1
    Set lo_Field = lo_rpt.Sections(0).Fields(ll_RepField)
    'this line doesn't work don't know why, I have to copy all attributes manually
    'vp.Font = lo_rpt.Sections(0).Fields(ll_RepField).Font
    Vp.FontBold = lo_Field.FontBold
    Vp.FontItalic = lo_Field.FontItalic
    Vp.FontSize = lo_Field.FontSize
    Vp.FontName = lo_Field.FontName
    Vp.FontStrikethru = lo_Field.FontStrikethrough
    Vp.FontUnderline = lo_Field.FontUnderline
    'set field aligment
    Select Case lo_Field.ALIGN
    Case vsrGeneral
      Vp.TextAlign = taLeftMiddle
    Case vsrLeftTop  '0 Align to the left and to the top of the field box.
      Vp.TextAlign = taLeftTop
    Case vsrCenterTop '  1 Align to the center and to the top of the field box.
      Vp.TextAlign = taCenterTop
    Case vsrRightTop '2 Align to the right and to the top of the field box.
      Vp.TextAlign = taRightTop
    Case vsrLeftBottom '3 Align to the left and to the bottom of the field box.
      Vp.TextAlign = taLeftBottom
    Case vsrCenterBottom '4 Align to the center and to the bottom of the field box.
      Vp.TextAlign = taCenterBottom
    Case vsrRightBottom  '5 Align to the right and to the bottom of the field box.
      Vp.TextAlign = taRightBottom
    Case vsrLeftMiddle '6 Align to the left and to the middle of the field box.
      Vp.TextAlign = taLeftMiddle
    Case vsrCenterMiddle '7 Align to the center and to the middle of the field box.
      Vp.TextAlign = taCenterMiddle
    Case vsrRightMiddle  '8 Align to the right and to the middle of the field box.
      Vp.TextAlign = taRightMiddle
    Case vsrJustTop  '9 Justify and align to the top of the field box.
      Vp.TextAlign = taJustTop
    Case vsrJustBottom '10  Justify and align to the bottom of the field box.
      Vp.TextAlign = taJustBottom
    Case vsrJustMiddle '11  Justify and align to the middle of the field box.
      Vp.TextAlign = taJustMiddle
    End Select
    'here print the textbox into the report
    ll_X = lo_Field.Left * ld_ScaleX + ll_CurX
    ll_Y = lo_Field.Top + ll_CurY
    ll_W = lo_Field.Width * ld_ScaleX
    ll_H = lo_Field.Height
    
    Call Vp.TextBox(lo_Field.Text, ll_X, ll_Y, ll_W, 0, lo_Field.WordWrap, lo_Field.Calculated)
    'print line through field if needed
    If lo_Field.LineSlant Then
      Call Vp.DrawLine(ll_X, ll_Y, ll_X + ll_W, ll_Y + ll_H)
    End If
    'if a border around field should be drawn, then use default style and draw it
    If lo_Field.BorderStyle <> 0 Then
      Vp.BrushStyle = 1
      Vp.BorderStyle = bsSingle
      Call Vp.DrawRectangle(ll_X, ll_Y, ll_X + ll_W, ll_Y + ll_H)
    End If
  Next
  'move current position of cursor to print next header ot table
  Vp.CurrentX = ll_CurX
  Vp.CurrentY = ll_CurY + lo_rpt.Sections(0).Height

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:PrintHeader")
#End If
  Exit Sub
ErrorHandler:
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:PrintHeader")
#End If
End Sub

'print detail table according xml template and cursor
Private Sub PrintTable(ls_Title As String, lo_rpt As Object, ll_Cursor As Long)
Dim ll_FieldIndex As Long, ll_RowIndex As Long
Dim ll_Index As Long, ll_MinIndex As Long
Dim lv_Data As Variant, lv_Fields() As Variant, lv_Formats As Variant
Dim ls_Format As String, ls_Header As String, ls_value As String
Dim lo_Fields As New Collection
Dim lo_SortedFields As New Collection
Dim lo_Field As Object
Dim ld_Width As Double, ld_ScaleX As Double
Dim lo_FieldFont As New StdFont

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:PrintTable")
#End If
  
  ld_ScaleX = CDbl(Vp.PageWidth - Vp.MarginLeft - Vp.MarginRight) / CDbl(lo_rpt.Layout.Width)
  'create collection with all labels in section 0
  For ll_Index = 0 To lo_rpt.Sections(0).Fields.Count - 1
    Call lo_Fields.Add(lo_rpt.Sections(0).Fields(ll_Index))
  Next
  ' sorting labels according left position to new collection (crapy algorythm but no time to think something better)
  While lo_Fields.Count > 0
    ll_MinIndex = 1
    For ll_Index = 1 To lo_Fields.Count
      If (lo_Fields(ll_MinIndex).Left > lo_Fields(ll_Index).Left) Then
        ll_MinIndex = ll_Index
      End If
    Next
    Call lo_SortedFields.Add(lo_Fields(ll_MinIndex))
    Call lo_Fields.Remove(ll_MinIndex)
  Wend
  'print detail table name before we print table
  Vp.Font = mo_TitleFont
  Vp.Font.Charset = mi_Charset
  Vp = TranslateLabel(ls_Title)
  Vp.FontBold = False
  
  'if there are some fields to print then start table
  If (lo_SortedFields.Count > 0) Then
    ReDim lv_Fields(lo_SortedFields.Count - 1)
    ReDim lv_Formats(lo_SortedFields.Count - 1)
    ls_Format = ""
    ls_Header = ""
    'create format string for table and header
    For ll_Index = 1 To lo_SortedFields.Count
      If ll_Index > 1 Then
        ls_Format = ls_Format & "|"
        ls_Header = ls_Header & "|"
      End If
      Set lo_Field = lo_SortedFields(ll_Index)
      'split field names if they are concatenated
      'set field (fields) for print into column
      lv_Fields(ll_Index - 1) = GetFieldArray(lo_Field.Name)
      lv_Formats(ll_Index - 1) = lo_Field.Format
      'set header name - translate text of the field label
      ls_Header = ls_Header & TranslateLabel(lo_Field.Text)
    Next
    'fill variant array to data
    If mo_Db.RowCount(ll_Cursor) > 0 Then
      ReDim lv_Data(lo_SortedFields.Count - 1, mo_Db.RowCount(ll_Cursor) - 1)
      For ll_RowIndex = 0 To mo_Db.RowCount(ll_Cursor) - 1
        For ll_FieldIndex = 0 To UBound(lv_Fields)
          lv_Data(ll_FieldIndex, ll_RowIndex) = GetDataString(lv_Fields(ll_FieldIndex), lv_Formats(ll_FieldIndex), ll_Cursor, ll_RowIndex)
        Next
      Next
    Else
      'there is no data in the table, so create one empty row
      ReDim lv_Data(lo_SortedFields.Count - 1, 0)
    End If
    'start table
    Call Vp.StartTable
    'add data
    Call Vp.AddTableArray(ls_Format, ls_Header, lv_Data)
    'format table
    For ll_Index = 1 To lo_SortedFields.Count
      If ll_Index < lo_SortedFields.Count Then
        ld_Width = lo_SortedFields(ll_Index + 1).Left - lo_SortedFields(ll_Index).Left
      Else
        ld_Width = lo_SortedFields(ll_Index).Width
      End If
      'set columns width evenly so they take all page width
      Set lo_Field = lo_SortedFields(ll_Index)
      
      lo_FieldFont.Name = lo_Field.FontName
      lo_FieldFont.Size = lo_Field.FontSize
      lo_FieldFont.Bold = lo_Field.FontBold
      lo_FieldFont.Italic = lo_Field.FontItalic
      lo_FieldFont.Strikethrough = lo_Field.FontStrikethrough
      lo_FieldFont.Underline = lo_Field.FontUnderline
      lo_FieldFont.Charset = mi_Charset
      
      Vp.TableCell(tcColWidth, , ll_Index) = ld_Width * ld_ScaleX
      Vp.TableCell(tcAlign, , ll_Index) = lo_Field.ALIGN
      Vp.TableCell(tcFont, , ll_Index) = lo_FieldFont
      Vp.TableCell(tcColNoWrap, , ll_Index) = False
    Next
    'end table
    Call Vp.EndTable
  End If
  
  Set lo_Fields = Nothing
  Set lo_SortedFields = Nothing

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:PrintTable")
#End If
  Exit Sub
ErrorHandler:
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:PrintTable")
#End If
End Sub

Private Function DropTempTable() As Boolean

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:DropTempTable")
#End If
  
  DropTempTable = ExecuteRequest(ms_DropTempTableRequest)

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:DropTempTable")
#End If
End Function

Private Function CreateTempTable() As Boolean

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:CreateTempTable")
#End If
  
  CreateTempTable = ExecuteRequest(ms_CreateTempTableRequest)

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:CreateTempTable")
#End If
End Function

Private Function InsertTempKeys(ByRef al_Index As Long) As Boolean
Dim ll_KeyIndex As Long, ll_ColIndex As Long
Dim ls_TempRequest As String
Dim lv_Key As Variant

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:InsertTempKeys")
#End If
  
  ls_TempRequest = ms_InsertTempKeyRequest
  ll_KeyIndex = 0
  Do While (ll_KeyIndex < ml_InsertTempKeyCount) And (al_Index <= UBound(mv_MultiKey))
  
    lv_Key = mv_MultiKey(al_Index)
    
    If IsArray(lv_Key) Then
      For ll_ColIndex = 0 To UBound(lv_Key)
        ls_TempRequest = Replace(ls_TempRequest, "$" & ll_KeyIndex & "$", Replace(lv_Key(ll_ColIndex), "'", "''"))
        ll_KeyIndex = ll_KeyIndex + 1
      Next
    Else
      ls_TempRequest = Replace(ls_TempRequest, "$" & ll_KeyIndex & "$", Replace(lv_Key, "'", "''"))
      ll_KeyIndex = ll_KeyIndex + 1
    End If
    al_Index = al_Index + 1
  Loop
  
  Do While ll_KeyIndex < ml_InsertTempKeyCount
    ls_TempRequest = Replace(ls_TempRequest, "$" & ll_KeyIndex & "$", "")
    ll_KeyIndex = ll_KeyIndex + 1
  Loop
  InsertTempKeys = ExecuteRequest(ls_TempRequest)

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:InsertTempKeys")
#End If
  Exit Function
ErrorHandler:
  InsertTempKeys = False
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:InsertTempKeys")
#End If
End Function

Private Function FillTempKeyTable() As Boolean
Dim lb_Result As Boolean
Dim ll_RowIndex As Long

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:FillTempKeyTable")
#End If
  
  lb_Result = False
  Call DropTempTable
  If CreateTempTable Then
    If IsArray(mv_MultiKey) Then
      ll_RowIndex = 0
      Do While ll_RowIndex <= UBound(mv_MultiKey)
        lb_Result = InsertTempKeys(ll_RowIndex)
        If Not lb_Result Then Exit Do
      Loop
    End If
  End If
  FillTempKeyTable = lb_Result

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:FillTempKeyTable")
#End If
  Exit Function
ErrorHandler:
  FillTempKeyTable = False
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:FillTempKeyTable")
#End If
End Function

Private Function ReplacePlaceholders(ByVal as_Request As String) As String
Dim ll_Index As Long
Dim ls_Params() As String
Dim ls_value As String

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:ReplacePlaceholders")
#End If
  
  as_Request = Replace(as_Request, "$Now()$", Format(Date, "yyyy-mm-ddd"), , , vbTextCompare)
  as_Request = Replace(as_Request, "$CurrentPage()$", ml_CurrentPage, , , vbTextCompare)
  as_Request = Replace(as_Request, "$TotalPages()$", ml_TotalPages, , , vbTextCompare)
  
  If IsArray(mv_Placeholders) Then
    For ll_Index = 0 To UBound(mv_Placeholders)
      ls_Params = Split(mv_Placeholders(ll_Index), SEP)
      If UBound(ls_Params) = 1 Then
        If Left(ls_Params(1), 1) = "#" Then ls_Params(1) = TranslateLabel(ls_Params(1))
        as_Request = Replace(as_Request, "$" & ls_Params(0) & "$", ls_Params(1), , , vbTextCompare)
      End If
    Next
  End If
  ReplacePlaceholders = as_Request

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:ReplacePlaceholders")
#End If
  Exit Function
ErrorHandler:
  ReplacePlaceholders = as_Request
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:ReplacePlaceholders", "as_Request=" & as_Request)
#End If
End Function

'open cursor with request as_Request and return cursor
Private Function OpenCursor(ByVal as_Request As String, Optional al_cursor As Long = 0) As Long
Dim ll_Index As Long
Dim ls_value As String
  
On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:OpenCursor")
#End If
  
  Call SetMousePointer(False)
  OpenCursor = 0
  If Not IsConnected Then
    If Not OpenConnection(ms_Server, ms_Db, ms_User, ms_Pwd, ms_App) Then
#If CompDebug Then
        Call mo_Trace.WriteTraceSQLError(mo_Db, "ArmPrint:OpenCursor", "ms_Server=" & ms_Server, _
          "ms_Db=" & ms_Db, "ms_User=" & ms_User, "ms_Pwd=" & ms_Pwd)
#End If
    End If
  End If
  
  as_Request = ReplacePlaceholders(as_Request)
  If al_cursor Then
    For ll_Index = 0 To mo_Db.FieldCount(al_cursor) - 1
      ls_value = mo_Db.GetFields(al_cursor, ll_Index)
      as_Request = Replace(as_Request, "$" & ll_Index & "$", ls_value)
      as_Request = Replace(as_Request, "$" & mo_Db.GetFieldName(al_cursor, ll_Index) & "$", ls_value, , , vbTextCompare)
    Next
  End If
  
  OpenCursor = mo_Db.OpenSQL(as_Request)
  If OpenCursor = 0 Then
#If CompDebug Then
      Call mo_Trace.WriteTraceSQLError(mo_Db, "ArmPrint:OpenCursor", "as_Request=" & as_Request)
#End If
  End If
  Call SetMousePointer(True)

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:OpenCursor")
#End If
  Exit Function
ErrorHandler:
  Call SetMousePointer(True)
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:OpenCursor", "as_Request=" & as_Request)
#End If
End Function

Private Function CloseCursor(ByRef al_cursor As Long) As Boolean

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:CloseCursor")
#End If
  
  If al_cursor Then
    Call mo_Db.Close(al_cursor)
    al_cursor = 0
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:CloseCursor")
#End If
End Function

'execute SQL request on server
Private Function ExecuteRequest(ByVal as_Request As String) As Boolean
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:ExecuteRequest")
#End If
  
  as_Request = ReplacePlaceholders(as_Request)
  ExecuteRequest = mo_Db.ExecuteSQL(as_Request)
  If Not ExecuteRequest Then
#If CompDebug Then
    Call mo_Trace.WriteTraceSQLError(mo_Db, "ArmPrint:ExecuteRequest", "as_Request=" & as_Request)
#End If
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:ExecuteRequest")
#End If
End Function

'**************************************************************************************************************
'turn of on mouse pointer sand hour glass, use counter
Private Static Sub SetMousePointer(lb_Enable As Boolean)
Dim li_Count As Integer
Dim li_OldPointer As Integer

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:SetMousePointer")
#End If
  
  If lb_Enable Then
    If li_Count > 0 Then li_Count = li_Count - 1
    If li_Count <= 0 Then
      'set back old state
      Screen.MousePointer = li_OldPointer
    End If
  Else
    li_Count = li_Count + 1
    'remember state of pointer before first change
    If li_Count = 1 Then li_OldPointer = Screen.MousePointer
    Screen.MousePointer = vbHourglass
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:SetMousePointer")
#End If
End Sub

Private Sub DeleteCollection()

On Error GoTo ErrorHandler
#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(True, "ArmPrint:DeleteCollection")
#End If
  
  If Not (mo_Reports Is Nothing) Then
    While mo_Reports.Count > 0
      Call mo_Reports.Remove(1)
    Wend
  End If

#If CompDebugPR Then
  Call mo_Trace.WriteTraceProc(False, "ArmPrint:DeleteCollection")
#End If
  Exit Sub
ErrorHandler:
#If CompDebug Then
  Call mo_Trace.WriteTraceError("ArmPrint:DeleteCollection")
#End If
End Sub

