VERSION 5.00
Object = "{5E9E78A0-531B-11CF-91F6-C2863C385E30}#1.0#0"; "MSFLXGRD.OCX"
Begin VB.UserControl ONSV_Report 
   ClientHeight    =   7665
   ClientLeft      =   0
   ClientTop       =   0
   ClientWidth     =   14685
   DrawWidth       =   5
   ScaleHeight     =   7665
   ScaleWidth      =   14685
   Begin VB.Frame fra_detail 
      Height          =   6180
      Left            =   3975
      TabIndex        =   1
      Tag             =   "frm_detail"
      Top             =   990
      Width           =   10485
      Begin MSFlexGridLib.MSFlexGrid grd_main 
         Height          =   4605
         Left            =   315
         TabIndex        =   4
         Tag             =   "grd_main"
         Top             =   270
         Visible         =   0   'False
         Width           =   7815
         _ExtentX        =   13785
         _ExtentY        =   8123
         _Version        =   393216
         Rows            =   6
         Cols            =   4
         FixedRows       =   5
         FixedCols       =   3
         AllowBigSelection=   0   'False
         FocusRect       =   2
         MergeCells      =   1
         AllowUserResizing=   3
      End
   End
   Begin VB.Frame fra_filter 
      Height          =   7440
      Left            =   75
      TabIndex        =   0
      Tag             =   "frm_filter"
      Top             =   15
      Width           =   3795
      Begin VB.CommandButton btn_refreshTreeview 
         Caption         =   "Reset treeview"
         Height          =   300
         Left            =   2265
         TabIndex        =   6
         Top             =   150
         Width           =   1365
      End
      Begin VB.CheckBox chk_autoGridLoad 
         Caption         =   "Automatic grid load"
         Height          =   255
         Left            =   150
         TabIndex        =   5
         Top             =   165
         Width           =   2040
      End
      Begin Project1.ArmTreeView tv_main 
         Height          =   6930
         Left            =   150
         TabIndex        =   2
         Top             =   465
         Width           =   3480
         _ExtentX        =   6138
         _ExtentY        =   12224
      End
   End
   Begin Project1.ToolbarControl tlb_main 
      Height          =   690
      Left            =   4155
      TabIndex        =   3
      Top             =   210
      Width           =   9840
      _ExtentX        =   17357
      _ExtentY        =   1217
   End
End
Attribute VB_Name = "ONSV_Report"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

' **************************************************************************************************
' ************************************* EXTERNAL DECLARATIONS **************************************
' **************************************************************************************************
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwnd As Long) As Long
' **************************************************************************************************

' **************************************************************************************************
' **************************************** TOOL CONSTANTS ******************************************
' **************************************************************************************************
Private Const CL_COLOR_ENABLED As Long = &H80000005
Private Const CL_COLOR_DISABLED As Long = &H8000000F
Private Const CL_Back1 As Long = &H80000018
Private Const CL_Back2 As Long = &HFFFFFF
Private Const CL_TOTAL As Long = vbGreen
Private Const CL_TOTAL_CONTINENTAL As Long = vbYellow
Private Const CL_TOTAL_SE_NE As Long = vbCyan

Private Const xlEdgeLeft = 7
Private Const xlEdgeTop = 8
Private Const xlEdgeBottom = 9
Private Const xlContinuous = 1
Private Const xlThin = 2
Private Const xlMedium = -4138 '(&HFFFFEFD6)
Private Const xlCenter = -4108 '(&HFFFFEFF4)
Private Const xlEdgeRight = 10

Private Const xlLandscape = 2
Private Const xlPaperA3 = 8

Private Const SEP1 As String = "®"
Private Const SEP2 As String = "©"
Private Const SEP As String = SEP1 + SEP2
Private Const C_APPNAME As String = "ONSV_REPORT"           ' for error log
Private Const C_SCREENNAME As String = "ONSV_Report"        ' for loading screen constants
Private Const C_SCREENMODE_STACK_SIZE As Long = 5           ' size of stack for active screens
Private Const C_TOOLBARFACE_ITEM_LST As String = "0"
Private Const C_TOOLBARFACE_ITEM_MTNC As String = "1"
Private Const C_TOOLBARFACE_ITEM_VIEW As String = "2"
Private Const C_TOOLBARFACE_ITEM_MTNC_DEL As String = "3"
Private Const SIFYB_CM_ERROR_MESSAGE = 2400                 ' const for base of error messages ids

Private Const C_MAIN_GRD_ID = 21
Private Const C_MAIN_TREEVIEW_ID = 11

' ****************************************** TOOL CONSTANTS ***************************************

Private Const MG_CODE_WOOL As String = "M004"

Private Type GRD_ColumnInfo
    Index As Long
    Name As String
    Format As String
    DB_Name As String
End Type

Private Type GRD_Info
    gTitle As String
    Cols() As GRD_ColumnInfo
    RowColBase() As Long
End Type

' **************************************************************************************************
' **************************************** USER DEFINED ERRORS *************************************
' **************************************************************************************************
Private Enum ArmErr
    DBCnxFailed = vbObjectError + 1 ' Unable to connect to the database
    CPTAlreadyInitialized = vbObjectError + 2   ' We try to initialize a component that is already initialized
    CPTNotInitialized = vbObjectError + 3       ' We try to use or free that is not initialized yet
    InvalidArgument = vbObjectError + 4
    PropertyNotSet = vbObjectError + 5
    CompFncFailed = vbObjectError + 6          ' when component function fail
    QuietException = vbObjectError + 7              ' do not display error message
    WarMsgSelectRow = vbObjectError + 8
    SQLBadRowAffectedCount = vbObjectError + 9   ' A SQL request has not affected the expected rowcount (ex: one Update do nothing)
    SQLBadRowExpectedCount = vbObjectError + 10  ' A SQL request does not return the expected rowcount : select an item return nothing...
End Enum

Dim ml_U_Code As Long               ' if this is user loging app, needed to log errors into A_Log
Dim ms_LoginName As String
Dim ms_Language_Code As String
Dim mb_Initialized As Boolean           ' True if the component is already initialized
Dim mb_Initializing As Boolean          ' Flag of initializing
Dim ms_Title As String                  ' title of user control - can be assigned as Caption to the parent form or title for printing

Private mc_ScreenLabels             As Long         'cursor containing screen constants for current component
Dim mo_grd_MainInfo As GRD_Info                     ' info for grd_main
Private ms_DecimalSeparator  As String

Private Enum ArmScreenMode
    smRefreshOnly
    smMain
    smAdd
    smUpdate
    smDelete
    smView
End Enum

#If LIVE = 1 Then
    Dim mo_Db As Object
#Else
    Dim mo_Db As ARMSYSCOMLib.ArmDb
#End If

' *************************************** CONTROL MEMBERS ******************************************
Public Event quit()


Private Type LevelDataNameS
    TVN_DataNames() As String
End Type


' **************************************************************************************************
' **************************************************************************************************
' **************************************************************************************************
' **************************************************************************************************
' **************************************************************************************************
' ** REMOVE WHEN INTEGRATE INTO SIFYB
Public gl_CodePage As Long
'convert code page into charset integer
Public Function GetCharSetFromCodePage(ByVal al_CodePage As Long) As Long

    On Error GoTo Trace_Err

    Select Case CStr(al_CodePage)
        Case 932 ' Japanese
            GetCharSetFromCodePage = 128
        Case 936 ' Simplified Chinese
            GetCharSetFromCodePage = 134
        Case 949 ' Korean
            GetCharSetFromCodePage = 129
        Case 950 ' Traditional Chinese
            GetCharSetFromCodePage = 136
        Case 1250 ' Eastern Europe
            GetCharSetFromCodePage = 238
        Case 1251 ' Russian
            GetCharSetFromCodePage = 204
        Case 1252 ' Western European Languages
            GetCharSetFromCodePage = 0
        Case 1253 ' Greek
            GetCharSetFromCodePage = 161
        Case 1254 ' Turkish
            GetCharSetFromCodePage = 162
        Case 1255 ' Hebrew
            GetCharSetFromCodePage = 177
        Case 1256 ' Arabic
            GetCharSetFromCodePage = 178
        Case 1257 ' Baltic
            GetCharSetFromCodePage = 186
        Case Else
            GetCharSetFromCodePage = 0
    End Select
    
    Exit Function
    
Trace_Err:
End Function
' **************************************************************************************************
' **************************************************************************************************
' **************************************************************************************************
' **************************************************************************************************
' **************************************************************************************************




' mb_Initialized is a read-only property, indicates the status of the component
Public Sub Move(ByVal aLeft As Single, ByVal aTop As Single, ByVal aWidth As Single, ByVal aHeight As Single)
    Call UserControl.Extender.Move(aLeft, aTop, aWidth, aHeight)
    Call Resize
End Sub

Public Sub Resize()
    Call InitCtrlSize
End Sub

Public Property Let Visible(ByVal aVisible As Boolean)
    UserControl.Extender.Visible = aVisible
End Property
Public Property Get Initialized() As Boolean
    Initialized = mb_Initialized
End Property

Public Property Let U_Code(ByVal al_U_Code As Long)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    
    ml_U_Code = al_U_Code
    Exit Property
ErrHandler:
    Call ErrorHandler("U_Code(Let)")
End Property

Public Property Let LoginName(ByVal as_loginName As String)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    
    ms_LoginName = as_loginName
    Exit Property
ErrHandler:
    Call ErrorHandler("LoginName(Let)")
End Property

Public Property Let Language_Code(as_Language_code As String)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    If Len(as_Language_code) <> 1 Then Call Err.Raise(ArmErr.InvalidArgument, "", "Language_code must contains only 1 char")
    
    ms_Language_Code = as_Language_code
    Exit Property
ErrHandler:
    Call ErrorHandler("Language(Let)")
End Property

Public Property Set ArmDb(ByRef ao_Db As ArmDb)
On Error GoTo ErrHandler
    
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    If ao_Db Is Nothing Then Call Err.Raise(ArmErr.InvalidArgument)
    
    Set mo_Db = ao_Db
    Exit Property
ErrHandler:
    Call ErrorHandler("ArmDb(Set)")
End Property


Public Sub Load_A_Com()
Dim lo_Control As Object
On Error GoTo ErrHandler
    If Initialized Then Call Err.Raise(ArmErr.CPTAlreadyInitialized)
    If mo_Db Is Nothing Then Call Err.Raise(ArmErr.PropertyNotSet, "", "mo_Db")
    If Len(ms_Language_Code) < 1 Then Call Err.Raise(ArmErr.PropertyNotSet, "", "ms_Language_Code")
    
    Debug.Assert (Not mo_Db Is Nothing)
    
    For Each lo_Control In UserControl.Controls
        Select Case UCase(TypeName(lo_Control))
        Case "ARMCOMBOBOX"
            Set lo_Control.ArmDb = mo_Db
            Call lo_Control.Load_A_Com
        Case "ARMPICKER"
            Set lo_Control.ArmDb = mo_Db
            Call lo_Control.Load_A_Com
        Case "TOOLBARCONTROL"
            lo_Control.Language = ms_Language_Code
            lo_Control.Load_A_Com
        Case "ARMGRID"
            Set lo_Control.ArmDb = mo_Db
            Call lo_Control.Load_A_Com
        Case "ARMTREEVIEW"
            Set lo_Control.ArmDb = mo_Db
            lo_Control.Language = ms_Language_Code
            Call lo_Control.Load_A_Com
        Case "ARMCHECKVIEW"
            Set lo_Control.ArmDb = mo_Db
            Call lo_Control.Load_A_Com
        Case "A_CALOCX"
            lo_Control.Language = ms_Language_Code
            Call lo_Control.reinit_cal
        End Select
    Next
    
    ms_DecimalSeparator = Format(0, ".")
    
    ' init controls
    Call LoadLabels(mo_Db, UserControl.Controls, C_SCREENNAME, ms_Language_Code)
    Call ChangeCharset(UserControl.Controls, gl_CodePage)
    Call InitComponents
    
    ' set layout
    Call InitCtrlSize
    
    mb_Initialized = True
    
    ' display starting face
    Call UpdateUI(ArmScreenMode.smMain)
    
    Exit Sub
ErrHandler:
    Call ErrorMessage("Load_A_Com()")
End Sub

Public Sub Unload_A_Com()
Dim lo_Control As Object
On Error GoTo ErrHandler
    If Not Initialized Then Call Err.Raise(ArmErr.CPTNotInitialized)
    
    For Each lo_Control In UserControl.Controls
        Select Case UCase(TypeName(lo_Control))
        Case "ARMCOMBOBOX", "TOOLBARCONTROL", "ARMGRID", "ARMTREEVIEW", "ARMCHECKVIEW", "ARMPICKER"
            Call lo_Control.Unload_A_Com
        End Select
    Next
    
    If mc_ScreenLabels <> 0 Then Call mo_Db.Close(mc_ScreenLabels)
    mc_ScreenLabels = 0
    
    Set mo_Db = Nothing
    Exit Sub
ErrHandler:
    Call ErrorMessage("Unload_A_Com()")
End Sub


' INIT FUNCTION
Private Sub InitTreeViewByID(ByRef ao_Tree As ArmTreeView, ByVal al_Id As Long)
On Error GoTo ErrHandler
Const C_TREEINIT_REQ As String = _
    "SELECT TVL.TVL_ID, TV.TV_FRLoadType, TV.TV_StartDemandLevel, TV.TV_AllowFind, TV.TV_AllowCheckBoxes, TV.TV_CheckBoxes, TV.TV_UseImages, TV.TV_UsePopup," & _
    "    TVL.TVL_AltGridRequest, GRD.GRD_Request, GRD.GRD_GridCountRequest, ISNULL( TVLT.TVL_Name, 'Level ' + CAST(TVL.TVL_Level AS varchar(5)) ) AS TVL_Name, TVL.TVL_Request, TVL.TVL_CountRequest, TVL.TVL_FindRequest, TVL.TVL_Image, TVL.TVL_SelectedImage, " & _
    "    ( SELECT COUNT(*) FROM A_Tree_Levels WHERE TV_ID=TV.TV_ID ) AS Levels, " & _
    "    ( SELECT COUNT(*) FROM A_Tree_Levels_DataNames WHERE TVL_ID=TVL.TVL_ID ) AS NodeDataSize, " & _
    "    TVN.TVN_Order, ISNULL(TVNT.TVN_Name, 'Data ' + CAST( TVN.TVN_Order AS VARCHAR(5) )) AS TVN_Name " & _
    "FROM A_Tree_Definitions TV " & _
    "   INNER JOIN A_Tree_Levels TVL ON TVL.TV_ID=TV.TV_ID " & _
    "       LEFT JOIN A_Tree_Levels_DataNames TVN ON TVN.TVL_ID=TVL.TVL_ID " & _
    "           LEFT JOIN A_Tree_Levels_DataNames_T TVNT ON TVN.TVN_ID=TVNT.TVN_ID AND TVNT.TVN_Language='$LANGUAGE$' " & _
    "       LEFT JOIN A_Tree_Levels_T TVLT ON TVLT.TVL_ID=TVL.TVL_ID AND TVLT.TVL_Language='$LANGUAGE$' " & _
    "   LEFT JOIN A_Grid_Definitions GRD ON GRD.GRD_ID=TVL.GRD_ID " & _
    "WHERE TV.TV_ID = $TV_ID$ " & _
    "ORDER BY TVL.TVL_Level"


    Dim ll_Cursor As Long
    Dim ls_Req As String
    
    ls_Req = Replace(C_TREEINIT_REQ, "$TV_ID$", al_Id)
    ls_Req = Replace(ls_Req, "$LANGUAGE$", ms_Language_Code)
    ll_Cursor = OpenSQLSafe(mo_Db, ls_Req)
    If mo_Db.RowCount(ll_Cursor) > 0 Then
    
        Dim lb_checkboxes As Boolean
        ' Initialize the tree
        ao_Tree.AllowFind = (mo_Db.GetFields(ll_Cursor, "TV_AllowFind") = "X")
        ao_Tree.AllowCheckboxes = (mo_Db.GetFields(ll_Cursor, "TV_AllowCheckBoxes") = "X")
        ao_Tree.UseImages = (mo_Db.GetFields(ll_Cursor, "TV_UseImages") = "X")
        ao_Tree.UsePopup = (mo_Db.GetFields(ll_Cursor, "TV_UsePopup") = "X")
        ao_Tree.RemoveNodeDuplicity = (mo_Db.GetFields(ll_Cursor, "TV_RemoveNodeDuplicity") = "X")
        ao_Tree.LoadType = mo_Db.GetFields(ll_Cursor, "TV_FRLoadType")
        lb_checkboxes = (mo_Db.GetFields(ll_Cursor, "TV_CheckBoxes") = "X")
        
        ao_Tree.StartDemandLevel = mo_Db.GetFields(ll_Cursor, "TV_StartDemandLevel")
        ao_Tree.Levels = mo_Db.GetFields(ll_Cursor, "Levels")
        
        Dim lla_Images() As Long
        Dim lla_SelectedImages() As Long
        Dim lsa_LevelNames() As String
        Dim lla_NodeDataSizes() As Long
        Dim lsa_NodeRequests() As String
        Dim lsa_CountRequests() As String
        Dim lsa_GridRequests() As String
        Dim lsa_GridRequestsCount() As String
        Dim lsa_FindRequests() As String
        
        ReDim lla_Images(ao_Tree.Levels - 1) As Long
        ReDim lla_SelectedImages(ao_Tree.Levels - 1) As Long
        ReDim lsa_LevelNames(ao_Tree.Levels - 1) As String
        ReDim lla_NodeDataSizes(ao_Tree.Levels - 1) As Long
        ReDim llv_NodeDataNames(ao_Tree.Levels - 1) As LevelDataNameS
        ReDim lsa_NodeRequests(ao_Tree.Levels - 1) As String
        ReDim lsa_CountRequests(ao_Tree.Levels - 1) As String
        ReDim lsa_GridRequests(ao_Tree.Levels - 1) As String
        ReDim lsa_GridRequestsCount(ao_Tree.Levels - 1) As String
        ReDim lsa_FindRequests(ao_Tree.Levels - 1) As String
    
        Dim ll_i As Long
        Dim ll_oldTVL_ID As Long
        ll_i = 0
        ll_oldTVL_ID = 0
        While Not mo_Db.EOF(ll_Cursor)
            If ll_oldTVL_ID <> mo_Db.GetFields(ll_Cursor, "TVL_ID") Then
                If ll_oldTVL_ID <> 0 Then
                    ao_Tree.NodeDataNames(ll_i) = Array("aa", "bb")
                End If
                ll_oldTVL_ID = mo_Db.GetFields(ll_Cursor, "TVL_ID")
                lla_Images(ll_i) = mo_Db.GetFields(ll_Cursor, "TVL_Image")
                lla_SelectedImages(ll_i) = mo_Db.GetFields(ll_Cursor, "TVL_SelectedImage")
                lsa_LevelNames(ll_i) = mo_Db.GetFields(ll_Cursor, "TVL_Name")
                lla_NodeDataSizes(ll_i) = mo_Db.GetFields(ll_Cursor, "NodeDataSize")
                If lla_NodeDataSizes(ll_i) > 0 Then
                    ReDim llv_NodeDataNames(ll_i).TVN_DataNames(0 To lla_NodeDataSizes(ll_i) - 1) As String
                Else
                    ReDim llv_NodeDataNames(ll_i).TVN_DataNames(-1 To -1) As String
                End If
                lsa_NodeRequests(ll_i) = ReplaceStdPlaceholders(mo_Db.GetFields(ll_Cursor, "TVL_Request"))
                lsa_CountRequests(ll_i) = ReplaceStdPlaceholders(mo_Db.GetFields(ll_Cursor, "TVL_CountRequest"))
                lsa_GridRequests(ll_i) = ReplaceStdPlaceholders(IIf(mo_Db.GetFields(ll_Cursor, "TVL_AltGridRequest") <> "", mo_Db.GetFields(ll_Cursor, "TVL_AltGridRequest"), mo_Db.GetFields(ll_Cursor, "GRD_Request")))
                lsa_GridRequestsCount(ll_i) = ReplaceStdPlaceholders(mo_Db.GetFields(ll_Cursor, "GRD_GridCountRequest"))
                lsa_FindRequests(ll_i) = ReplaceStdPlaceholders(mo_Db.GetFields(ll_Cursor, "TVL_FindRequest"))
                
            ll_i = ll_i + 1
            End If
            
            If lla_NodeDataSizes(ll_i - 1) > 0 Then
                llv_NodeDataNames(ll_i - 1).TVN_DataNames(mo_Db.GetFields(ll_Cursor, "TVN_Order")) = mo_Db.GetFields(ll_Cursor, "TVN_Name")
            End If
            Call mo_Db.Next(ll_Cursor)
        Wend
'        If ll_oldTVL_ID <> 0 Then
'            ao_tree.NodeDataNames(ll_i) = Array("aa", "bb")
'        End If
        
        ao_Tree.Images = lla_Images
        ao_Tree.SelectedImages = lla_SelectedImages
        ao_Tree.LevelNames = lsa_LevelNames
        ao_Tree.NodeDataSizes = lla_NodeDataSizes
        For ll_i = 0 To UBound(llv_NodeDataNames)
            ao_Tree.NodeDataNames(ll_i) = llv_NodeDataNames(ll_i).TVN_DataNames
        Next
        ao_Tree.NodeRequests = lsa_NodeRequests
        ao_Tree.CountRequests = lsa_CountRequests
        ao_Tree.GridRequests = lsa_GridRequests
        ao_Tree.GridCountRequests = lsa_GridRequestsCount
        ao_Tree.FindRequests = lsa_FindRequests

        If lb_checkboxes Then
            ao_Tree.Checkboxes = True
        End If
        
        If Not ao_Tree.LoadTree(ao_Tree.LoadType) Then
            Call Err.Raise(CompFncFailed, "ao_tree.LoadTree")
        End If
        
    Else
        Call Err.Raise(ArmErr.DBCnxFailed, "ao_tree", "TreeView missing. ID=" & al_Id)
    End If
    
    Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0

    Exit Sub
ErrHandler:
    If ll_Cursor <> 0 Then
        Call mo_Db.Close(ll_Cursor)
        ll_Cursor = 0
    End If
    Call ErrorHandler("InitTreeViewByID()")
End Sub

Private Sub InitComponents()
'Const CL_REQUEST_TB As String = "SELECT Info FROM Toolbars_Definitions WHERE ID=$id$"
Const CL_REQUEST_TB As String = "A_ToolbarDef_sel 1, null, null, $id$"

On Error GoTo ErrHandler
    Dim lo_ctrl As Object
    Dim ll_Cursor As Long
    Dim ll_i As Long
    mb_Initializing = True
    ' init toolbar
    ll_Cursor = mo_Db.OpenSQL(Replace(CL_REQUEST_TB, "$id$", 2985))
    Call tlb_main.SetToolbarInfoStringParameters(mo_Db.GetFields(ll_Cursor, "info"), "336")
    Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    
    Call InitTreeViewByID(tv_main, 11)
    
    ' Initialize the grids
    
    Call GRD_SetHeader(grd_main, mo_grd_MainInfo, _
       Array(Array("", " ", " ", GetLabel("e_ORDER_MNGM", "#ORDER MANAGEMENT"), 3, 3, 3, 3, 3, 3, 3, 3, 3, _
                    GetLabel("e_SALES_BASELINES", "#SALES BASELINES"), 13, 13, 13, GetLabel("e_RESULT", "#RESULT"), 17, 17, 17, 17, GetLabel("e_LOAD_PERFORM", "#LOAD PERFORMANCE"), 22, 22, 22, 22), _
             Array("", " ", 1, "  ", 3, GetLabel("e_ORDER_BALANCE", "#ORDER BALANCE"), 5, 5, 5, 5, 5, 5, 5, _
                    "  ", 13, 13, 13, " ", 17, 17, 17, 17, GetLabel("e_SALES_AND_ORDERS1", "#Sales + Orders for Month - Months Budget"), GetLabel("e_SALES_AND_ORDERS2", "#Sales + Orders for Month as  % of Budget"), GetLabel("e_SALES_AND_ORDERS3", "#Sales + Orders for Month as % of Last Year"), GetLabel("e_SALES_AND_ORDERS4", "#Sales + Orders for Month  as  % of Estimate ABPE"), GetLabel("e_SALES_AND_ORDERS5", "#Sales + Orders for Month  as  % of Corporate Estimate")), _
             Array("", " ", 1, "  ", 3, " ", 5, "  ", 7, GetLabel("e_ORDERS_DATED", "#Orders dated for"), 9, 9, 9, _
                    "JUN", 13, 13, 13, GetLabel("e_SALES_ACTUAL", "#SALES ACTUAL MTD"), GetLabel("e_COMPARED_TO_MTD_BDG", "#COMPARED TO MTD BUDGET $REPORT_YEAR$"), GetLabel("e_COMPARED_TO_MTD", "#COMPARED TO MTD ACTUAL LAST YEAR"), GetLabel("e_COMPARED_TO_MONTH_EST", "#COMPARED TO MTD $MONTH_NAME$ Estimate ABPE"), GetLabel("e_COMPARED_TO_MONTH_CORP", "#COMPARED TO MTD $MONTH_NAME$ Corporate Est"), GetLabel("e_SALES_AND_ORDERS1", "#Sales + Orders for Month - Months Budget"), GetLabel("e_SALES_AND_ORDERS2", "#Sales + Orders for Month as  % of Budget"), GetLabel("e_SALES_AND_ORDERS3", "#Sales + Orders for Month as % of Last Year"), GetLabel("e_SALES_AND_ORDERS4", "#Sales + Orders for Month  as  % of Estimate ABPE"), GetLabel("e_SALES_AND_ORDERS5", "#Sales + Orders for Month  as  % of Corporate Estimate")), _
             Array("", " ", 1, GetLabel("e_INTAKE", "#INTAKE MTD"), 3, GetLabel("e_BEGGINNING", "#BEGINNING"), 5, GetLabel("e_MTD", "#MTD"), 7, GetLabel("e_THIS_MONTH", "#This month"), 9, GetLabel("e_NEXT_MONTH", "#Next month"), 11, _
                    "YEAR", "YEAR ", "YEAR", "YEAR ", GetLabel("e_SALES_ACTUAL", "#SALES ACTUAL MTD"), GetLabel("e_COMPARED_TO_MTD_BDG", "#COMPARED TO MTD BUDGET $REPORT_YEAR$"), GetLabel("e_COMPARED_TO_MTD", "#COMPARED TO MTD ACTUAL LAST YEAR"), GetLabel("e_COMPARED_TO_MONTH_EST", "#COMPARED TO MTD $MONTH_NAME$ Estimate ABPE"), GetLabel("e_COMPARED_TO_MONTH_CORP", "#COMPARED TO MTD $MONTH_NAME$ Corporate Est"), GetLabel("e_SALES_AND_ORDERS1", "#Sales + Orders for Month - Months Budget"), GetLabel("e_SALES_AND_ORDERS2", "#Sales + Orders for Month as  % of Budget"), GetLabel("e_SALES_AND_ORDERS3", "#Sales + Orders for Month as % of Last Year"), GetLabel("e_SALES_AND_ORDERS4", "#Sales + Orders for Month  as  % of Estimate ABPE"), GetLabel("e_SALES_AND_ORDERS5", "#Sales + Orders for Month  as  % of Corporate Estimate")), _
             Array(Array("ROW_ID", "record_id", 0, "record_id"), Array("MG_DESC", " ", 1500, "MG_Desc", flexAlignCenterCenter), Array("BMK_DESC", " ", 1900, "BMK_Desc", flexAlignCenterCenter), _
                    Array("C1", "YEAR", 1500, "C1", flexAlignCenterCenter, "0.0"), Array("C2", GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"), 1500, "C2", flexAlignCenterCenter, "0.0%"), _
                    Array("C3", "YEAR", 1500, "C3", flexAlignCenterCenter, "0.0"), Array("C4", GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"), 1500, "C4", flexAlignCenterCenter, "0.0%"), _
                    Array("C5", "YEAR", 1500, "C5", flexAlignCenterCenter, "0.0"), Array("C6", GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"), 1500, "C6", flexAlignCenterCenter, "0.0%"), _
                    Array("C7", "YEAR", 1500, "C7", flexAlignCenterCenter, "0.0"), Array("C8", GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"), 1500, "C8", flexAlignCenterCenter, "0.0%"), _
                    Array("C9", "YEAR", 1500, "C9", flexAlignCenterCenter, "0.0"), Array("C10", GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"), 1500, "C10", flexAlignCenterCenter, "0.0%"), _
                    Array("C11", GetLabel("e_BUDGET", "#BUDGET"), 1500, "C11", flexAlignCenterCenter, "0.0"), Array("C12", GetLabel("e_ACTUAL", "#ACTUAL"), 1500, "C12", flexAlignCenterCenter, "0.0"), _
                    Array("C13", GetLabel("e_ESTIMATE", "#ESTIMATE  ABPE"), 1500, "C13", flexAlignCenterCenter, "0.0"), Array("C14", GetLabel("e_ESTIMATE_CORP", "#Corporate Estimate"), 1500, "C14", flexAlignCenterCenter, "0.0"), Array("C15", GetLabel("e_SALES_ACTUAL", "#SALES ACTUAL MTD"), 1500, "C15", flexAlignCenterCenter, "0.0"), Array("C16", GetLabel("e_COMPARED_TO_MTD_BDG", "#COMPARED TO MTD BUDGET $REPORT_YEAR$"), 1500, "C16", flexAlignCenterCenter, "0.0%"), _
                    Array("C17", GetLabel("e_COMPARED_TO_MTD", "#COMPARED TO MTD ACTUAL LAST YEAR"), 1500, "C17", flexAlignCenterCenter, "0.0%"), Array("C18", GetLabel("e_COMPARED_TO_MONTH_EST", "#COMPARED TO MTD $MONTH_NAME$ Estimate ABPE"), 1500, "C18", flexAlignCenterCenter, "0.0%"), Array("C19", GetLabel("e_COMPARED_TO_MONTH_CORP", "#COMPARED TO MTD $MONTH_NAME$ Corporate Est"), 1500, "C19", flexAlignCenterCenter, "0.0%"), Array("C20", GetLabel("e_SALES_AND_ORDERS1", "#Sales + Orders for Month - Months Budget"), 1500, "C20", flexAlignCenterCenter, "0.0"), Array("C21", GetLabel("e_SALES_AND_ORDERS2", "#Sales + Orders for Month as  % of Budget"), 1500, "C21", flexAlignCenterCenter, "0.0%"), Array("C22", GetLabel("e_SALES_AND_ORDERS3", "#Sales + Orders for Month as % of Last Year"), 1500, "C22", flexAlignCenterCenter, "0.0%"), _
                    Array("C23", GetLabel("e_SALES_AND_ORDERS4", "#Sales + Orders for Month  as  % of Estimate ABPE"), 1500, "C23", flexAlignCenterCenter, "0.0%"), Array("C24", GetLabel("e_SALES_AND_ORDERS5", "#Sales + Orders for Month  as  % of Corporate Estimate"), 1500, "C24", flexAlignCenterCenter, "0.0%"))))

              

    mo_grd_MainInfo.gTitle = GetLabel("grd_sales_rep_Title", "#Sales by rep")
    
    grd_main.RowHeight(4) = 500
    grd_main.WordWrap = True
    
    grd_main.MergeCol(2) = True
    grd_main.MergeCol(17) = True
    grd_main.MergeCol(18) = True
    grd_main.MergeCol(19) = True
    grd_main.MergeCol(20) = True
    grd_main.MergeCol(21) = True
    grd_main.MergeCol(22) = True
    grd_main.MergeCol(23) = True
    grd_main.MergeCol(24) = True
    grd_main.MergeCol(25) = True
    grd_main.MergeCol(26) = True
    
        



'    Call grd_main.SetColumns(Array( _
'          Join(Array("BU_CODE", 0, 1, "BU_CODE", "#BU_CODE", "String", "", "Left"), SEP) _
'        , Join(Array("MG_CODE", 0, 1, "MG_CODE", "#MG_CODE", "String", "", "Left"), SEP) _
'        , Join(Array("BMK_ORDER", 0, 1, "BMK_ORDER", "#BMK_ORDER", "Number", "", "Left"), SEP) _
'        , Join(Array("BU_GRP", 2500, 0, "Bu_Grp", "#BU_GRP", "String", "", "Left"), SEP) _
'        , Join(Array("MG_DESC", 2100, 0, "MG_Desc", "#Material", "String", "", "Left"), SEP) _
'        , Join(Array("BMK_DESC", 2100, 0, "BMK_Desc", "#Market", "String", "", "Left"), SEP) _
'        , Join(Array("EML_Attachements", 500, 0, "EML_Attachements", "#Attachements", "Number", "", "Left"), SEP) _
'        , Join(Array("EML_CreationTime", 1200, 0, "EML_CreationTime", "#Creation time", "Date", "", "Left"), SEP) _
'        , Join(Array("iConcurrency", 0, 0, "iConcurrency", "", "Number", "", "Left"), SEP) _
'        , Join(Array("EmailInfoIconc", 0, 0, "EmailInfoIconc", "", "Number", "", "Left"), SEP) _
'        ))
    
    mb_Initializing = False
    Exit Sub
ErrHandler:
    If ll_Cursor <> 0 Then
        Call mo_Db.Close(ll_Cursor)
        ll_Cursor = 0
    End If
    mb_Initializing = False
    Call ErrorHandler("InitComponents()")
End Sub

Private Function InitGridByID(ByRef ao_grid As ArmGrid, ByVal al_Id As Long) As Variant
On Error GoTo ErrHandler
Const C_GRIDINIT_REQ As String = _
    "SELECT GRD.GRD_Request, GRD.GRD_GridCountRequest, GRD.GRD_MasterDetailRequest, GRD.GRD_FetchAll, GRD.GRD_UseReloadIcon, ISNULL( GRDT.GRD_Title, '#Title ' + CAST(GRD.GRD_ID AS varchar(5)) ) AS GRD_Title, GAL.RF_Desc AS TitleAlignment, GRD.GRD_FreeSelect, GRD.GRD_MultiSelect, GRD.GRD_ExportTitles, GRD.GRD_AllowExcelExport, GRD.GRD_AllowSort, GRD.GRD_AllowMultisort, GRD.GRD_AutoColumns, GRD.GRD_AutoColumnWidth, GRD.GRD_FiltersEnabled, GRD.GRD_WordWrap, COL.COL_Order, COL.COL_ColumnName, COL.COL_ColumnWidth, COL.COL_Key, COL.COL_ColumnFieldName, ISNULL( COLT.COL_ColumnTitle, 'Column ' + CAST(COL.COL_Order AS varchar(5)) ) AS COL_ColumnTitle, CFT.RF_Desc AS FieldType, COL.COL_FormatString, CAL.RF_Desc AS Alignment, COL.COL_Group, COL.COL_TotalVisible, CME.RF_Desc AS Measure, COL.COL_LinkedDataRequest " & _
    "FROM A_Grid_Definitions GRD " & _
    "   LEFT JOIN A_Grid_Definitions_T GRDT ON GRDT.GRD_ID=GRD.GRD_ID AND GRDT.GRD_Language='$LANGUAGE$' " & _
    "   INNER JOIN A_References GAL ON GAL.GR_code=GRD_GRTitleAlign AND GAL.RF_code=GRD.GRD_RFTitleAlign " & _
    "   INNER JOIN A_Grid_Columns COL ON COL.GRD_ID=GRD.GRD_ID " & _
    "       LEFT JOIN A_Grid_Columns_T COLT ON COLT.COL_ID=COL.COL_ID AND COLT.COL_Language='$LANGUAGE$' " & _
    "       LEFT JOIN A_References CFT ON CFT.GR_code=COL.COL_GRFT_code AND CFT.RF_code=COL.COL_RFFieldType " & _
    "       LEFT JOIN A_References CAL ON CAL.GR_code=COL.COL_GRAL_code AND CAL.RF_code=COL.COL_RFAlignment " & _
    "       LEFT JOIN A_References CME ON CME.GR_code=COL.COL_GRME_code AND CME.RF_code=COL.COL_RFMeasure " & _
    "WHERE GRD.GRD_ID = $GRD_ID$ " & _
    "ORDER BY COL.COL_Order"


    Dim ll_Cursor As Long
    Dim ls_Req As String
    Dim lv_retVal As Variant
    
    ao_grid.UnBound = False
    ls_Req = Replace(C_GRIDINIT_REQ, "$GRD_ID$", al_Id)
    ls_Req = Replace(ls_Req, "$LANGUAGE$", ms_Language_Code)
    ll_Cursor = OpenSQLSafe(mo_Db, ls_Req)
    If mo_Db.RowCount(ll_Cursor) > 0 Then
    
        ' Initialize the grid
        ao_grid.FetchAll = (mo_Db.GetFields(ll_Cursor, "GRD_FetchAll") = "X")
        ao_grid.FreeSelect = (mo_Db.GetFields(ll_Cursor, "GRD_FreeSelect") = "X")
        ao_grid.MultiSelect = (mo_Db.GetFields(ll_Cursor, "GRD_MultiSelect") = "X")
        ao_grid.ExportTitles = (mo_Db.GetFields(ll_Cursor, "GRD_ExportTitles") = "X")
        ao_grid.AllowExcelExport = (mo_Db.GetFields(ll_Cursor, "AllowExcelExport") = "X")
        ao_grid.AllowSort = (mo_Db.GetFields(ll_Cursor, "GRD_AllowSort") = "X")
        ao_grid.AllowMultiSort = (mo_Db.GetFields(ll_Cursor, "GRD_AllowMultisort") = "X")
        ao_grid.AutoColumns = (mo_Db.GetFields(ll_Cursor, "GRD_AutoColumns") = "X")
        ao_grid.AutoColumnWidth = mo_Db.GetFields(ll_Cursor, "GRD_AutoColumnWidth")
        ao_grid.FiltersEnabled = (mo_Db.GetFields(ll_Cursor, "GRD_FiltersEnabled") = "X")
        ao_grid.WordWrap = (mo_Db.GetFields(ll_Cursor, "GRD_WordWrap") = "X")
        
        ao_grid.Title = mo_Db.GetFields(ll_Cursor, "GRD_Title")
        
        lv_retVal = CVar(Array(mo_Db.GetFields(ll_Cursor, "GRD_Request"), _
                               mo_Db.GetFields(ll_Cursor, "GRD_GridCountRequest"), _
                               mo_Db.GetFields(ll_Cursor, "GRD_MasterDetailRequest")))
        
        Dim ls_columnDef() As String
        ReDim ls_columnDef(mo_Db.RowCount(ll_Cursor) - 1) As String
        
        Dim ll_i As Long
        ll_i = 0
        While Not mo_Db.EOF(ll_Cursor)
            ls_columnDef(ll_i) = Join(Array(mo_Db.GetFields(ll_Cursor, "COL_ColumnName"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_ColumnWidth"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_Key"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_ColumnFieldName"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_ColumnTitle"), _
                                            mo_Db.GetFields(ll_Cursor, "FieldType"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_FormatString"), _
                                            mo_Db.GetFields(ll_Cursor, "Alignemnt"), _
                                            IIf(mo_Db.GetFields(ll_Cursor, "COL_Group") = "X", "TRUE", "FALSE"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_TotalVisible"), _
                                            mo_Db.GetFields(ll_Cursor, "Measure"), _
                                            mo_Db.GetFields(ll_Cursor, "COL_LinkedDataRequest") _
                                    ), SEP)
            Call mo_Db.Next(ll_Cursor)
            ll_i = ll_i + 1
        Wend
        
        If Not ao_grid.SetColumns(ls_columnDef) Then
            Call Err.Raise(CompFncFailed, "ao_grid.SetColumns")
        End If
    Else
        Call Err.Raise(ArmErr.DBCnxFailed, "ao_grid", "Grid missing or column definition. ID=" & al_Id)
    End If
    
    Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    InitGridByID = lv_retVal
    Exit Function
ErrHandler:
    If ll_Cursor <> 0 Then
        Call mo_Db.Close(ll_Cursor)
        ll_Cursor = 0
    End If
    Call ErrorHandler("InitGridByID()")
End Function



' ************************************************************************************
' **************************** DB-ACCESS FUNCTIONS ***********************************
' ************************************************************************************
#If LIVE = 1 Then
Private Sub ExecuteSQLSafe(ByVal ao_Db As Object, ByVal as_Request As String, Optional ByVal al_RowAffectedCount = -1)
#Else
Private Sub ExecuteSQLSafe(ByVal ao_Db As ARMSYSCOMLib.ArmDb, ByVal as_Request As String, Optional ByVal al_RowAffectedCount = -1)
#End If
On Error GoTo ErrHandler
    ' First execute the request
    If Not ao_Db.ExecuteSQL(as_Request) Then
        Call Err.Raise(CompFncFailed, "ao_Db.ExecuteSQL", "SQL Error: " & GetDbError(ao_Db))
    End If

    If al_RowAffectedCount <> -1 Then
        ' Then check the rowcount
        If (ao_Db.SQLRowsAffected <> al_RowAffectedCount) Then
            If al_RowAffectedCount = 100 Then
                ' test on zero
                If ao_Db.SQLRowsAffected = 0 Then
                    Call Err.Raise(SQLBadRowAffectedCount, "SQL : " & as_Request, al_RowAffectedCount & "<>" & ao_Db.SQLRowsAffected)
                End If
            Else
                Call Err.Raise(SQLBadRowAffectedCount, "SQL : " & as_Request, al_RowAffectedCount & "<>" & ao_Db.SQLRowsAffected)
            End If
        End If
    End If
    Exit Sub
ErrHandler:
    Call ErrorHandler(Extender.Name & ".ExecuteSQLSafe")
End Sub

#If LIVE = 1 Then
Private Function OpenSQLSafe(ByVal ao_Db As Object, ByVal as_Request As String, Optional ByVal al_RowExpectedCount = -1) As Long
#Else
Private Function OpenSQLSafe(ByVal ao_Db As ARMSYSCOMLib.ArmDb, ByVal as_Request As String, Optional ByVal al_RowExpectedCount = -1) As Long
#End If
On Error GoTo ErrHandler
    Dim lc_Data As Long
    lc_Data = ao_Db.OpenSQL(as_Request)
    If lc_Data = 0 Then
        Call Err.Raise(CompFncFailed, "ao_Db.OpenSQL", "SQL Error: " & GetDbError(ao_Db))
    End If
    
    If al_RowExpectedCount <> -1 Then
        ' Then check the rowcount
        If ao_Db.RowCount(lc_Data) <> al_RowExpectedCount Then
            Call Err.Raise(SQLBadRowExpectedCount, "SQL : " & as_Request, al_RowExpectedCount & "<>" & ao_Db.RowCount(lc_Data))
        End If
    End If
    OpenSQLSafe = lc_Data
    Exit Function
ErrHandler:
    Call ErrorHandler(Extender.Name & ".OpenSQLSafe")
End Function

Private Function SqlStr(ByVal as_str As String, Optional ByVal al_MaxLen As Long = 8000) As String
    SqlStr = Replace(Left(as_str, IIf(Len(as_str) <= al_MaxLen, Len(as_str), al_MaxLen)), "'", "''")
End Function

Private Function SqlDate(ByVal as_Date As String) As String
  SqlDate = "'" & Format$(as_Date, "YYYY-MM-DD") & "'"
End Function


' ************************************************************************************
' ********************** ERROR-HANDLING SUPPORT FUNCTIONS ****************************
' ************************************************************************************
#If LIVE = 1 Then
Private Function GetDbError(ByVal lo_Db As Object) As String
#Else
Private Function GetDbError(ByVal lo_Db As ARMSYSCOMLib.ArmDb) As String
#End If
On Error GoTo ErrHandler
    If IsArray(lo_Db.SQLErrorMessages) Then
        Debug.Assert (IsArray(lo_Db.SQLErrorCodes))
        ' Display errors msgBox
        GetDbError = Join(lo_Db.SQLErrorCodes, ",") & vbCrLf & Join(lo_Db.SQLErrorMessages, vbCrLf)
    Else
        ' ExecuteSQL failed but no error message?
        GetDbError = "Unknown error"
    End If
    Exit Function
ErrHandler:
    Call ErrorHandler("GetDbError()")
End Function

' Standard error handler
Private Sub ErrorHandler(ByVal as_Fct As String)
    Call Err.Raise(Err.Number, as_Fct & SEP1 & Err.Source, Err.Description)
End Sub

' display standard error message
Private Sub ErrorMessage(ByVal as_Fct As String)
    If Err.Number = QuietException Then Exit Sub
    Dim ll_oldMP As MousePointerConstants
    
    'save mouse pointer
    ll_oldMP = Screen.MousePointer
    Screen.MousePointer = vbDefault
    
    Dim ls_ErrSource As String
    Dim ls_errDescription As String
    ls_ErrSource = as_Fct & SEP1 & Err.Source
    ls_errDescription = Err.Description
    
    Call LogMessage(App.ProductName & " exception raised. Err.Number:" & Err.Number & ", Err.Source:" & ls_ErrSource & ", Err.Description " & ls_errDescription & ".", "E", False)
    Call MsgBox("Error occured, please contact IT" & vbCrLf & ls_ErrSource & vbCrLf & "Description: " & ls_errDescription, , "Error message: " & as_Fct)
    
    'restore mouse pointer
    Screen.MousePointer = ll_oldMP
End Sub

Private Function MsgText(ByVal ai_MsgID As Integer, ByVal as_LanguageCode As String, ByVal as_defaultMsg As String) As String
'------------------------------------------------------------------
' Name : MsgText
'
' Purpose : Read the message in the database with the login
'           language
'
' Parameters :
'       ai_MsgId            Code of the message to find in the
'                               database
'       as_LanguageCode     Language Code to use to find the text
'
' Return :
'       The message in the good language
'
' review : Mar/20/2000 by AD
'------------------------------------------------------------------
On Error GoTo ErrHandler
Const C_REQ As String = "SELECT message_text FROM error_message WHERE msgid=$MSGID$ AND Language_code='$LANG_CODE$'"
    Dim ls_Req As String, ls_ret As String
    Dim ll_Cursor As Long
    
    ls_Req = Replace(C_REQ, "$MSGID$", ai_MsgID)
    ls_Req = Replace(ls_Req, "$LANG_CODE$", as_LanguageCode)
    
    ll_Cursor = OpenSQLSafe(mo_Db, ls_Req)
    Debug.Assert (ll_Cursor <> 0)
    
    Call mo_Db.First(ll_Cursor)
    While Not mo_Db.EOF(ll_Cursor)
        ls_ret = IIf(ls_ret = "", "", ls_ret & vbCrLf) & mo_Db.GetFields(ll_Cursor, "message_text")
        Call mo_Db.Next(ll_Cursor)
    Wend
    Call mo_Db.Close(ll_Cursor)
    If ls_Req = "" Then
        MsgText = as_defaultMsg
    Else
        MsgText = ls_ret
    End If
    Exit Function
ErrHandler:
    If ll_Cursor <> 0 Then Call mo_Db.Close(ll_Cursor)
    Call ErrorHandler("MsgText()")
End Function

Private Sub LogMessage(ByVal as_LogMsg As String, Optional ByVal as_LogType As String = "I", Optional ab_throwException As Boolean = True)
On Error GoTo ErrHandler
Const InsertReq As String = "INSERT INTO A_Log (U_code, Z_creation_date, Source , Log_type, Log_Msg ) VALUES ($UCODE$, GETDATE(), '$APP$', '$LOGTYPE$', '$MSG$')"
    Dim ls_Req As String
    Dim ll_Cursor As Long
    
    ls_Req = Replace(InsertReq, "$UCODE$", CStr(ml_U_Code))
    ls_Req = Replace(ls_Req, "$APP$", SqlStr(C_APPNAME & " " & App.Title & " " & App.Major & "." & App.Minor & "." & App.Revision, 50))
    ls_Req = Replace(ls_Req, "$MSG$", SqlStr(as_LogMsg, 4000))
    ls_Req = Replace(ls_Req, "$LOGTYPE$", SqlStr(as_LogType), 1)
    
    Call ExecuteSQLSafe(mo_Db, ls_Req)
    
    Exit Sub
ErrHandler:
    If ab_throwException Then Call ErrorHandler("LogMessage()")
End Sub

' procedure save/restore err object
Private Sub UpdateError(Optional ab_saveError As Boolean = False)
Static ls_ErrDesc As String
Static ls_ErrSource As String
Static ll_errNum As Long
    
    If ab_saveError Then
        ls_ErrDesc = Err.Description
        ls_ErrSource = Err.Source
        ll_errNum = Err.Number
    Else
        Err.Description = ls_ErrDesc
        Err.Source = ls_ErrSource
        Err.Number = ll_errNum
    End If
End Sub

Private Function SendMessage(ByVal as_msg As String, Optional Buttons As VbMsgBoxStyle = vbOKOnly) As VbMsgBoxResult
On Error GoTo ErrHandler
    Call LockScreen(True)
    SendMessage = MsgBox(as_msg, Buttons)
    Call LockScreen(False)
    Exit Function
ErrHandler:
    Call LockScreen(False)
    Call ErrorMessage(Extender.Name & ".SendMessage")
End Function


Private Function ReplaceStdPlaceholders(ByVal as_str As String) As String
On Error GoTo ErrHandler
    as_str = Replace(as_str, "$LANG$", ms_Language_Code, , , vbTextCompare)
    as_str = Replace(as_str, "$U_CODE$", ml_U_Code, , , vbTextCompare)
    ReplaceStdPlaceholders = as_str
    Exit Function
ErrHandler:
     Call ErrorHandler("ReplaceStdPlaceholders()")
End Function




Private Sub LockScreen(ByVal ab_lock As Boolean)

    Dim ll_errNumber As Long, ls_ErrSrc As String, ls_ErrDesc As String
    ll_errNumber = Err.Number
    ls_ErrSrc = Err.Source
    ls_ErrDesc = Err.Description

On Error GoTo ErrHandler
    Static ll_Count As Long
    Static ll_Mousepointer As Long
    Static lb_Locked As Boolean
      
    ll_Count = ll_Count + IIf(ab_lock, 1, -1)
    Debug.Assert (ll_Count >= 0)
    
    ' First lock
    If Not lb_Locked And ab_lock Then
        ll_Mousepointer = Screen.MousePointer
        Screen.MousePointer = vbHourglass
        LockWindowUpdate UserControl.hwnd
        lb_Locked = True
    End If
    
    ' Unlock
    If ll_Count = 0 Then
        DoEvents ' Flush events
        LockWindowUpdate 0
        UserControl.Refresh ' Repaint immediately
        Screen.MousePointer = ll_Mousepointer
        lb_Locked = False
    End If
    
    Err.Number = ll_errNumber
    Err.Source = ls_ErrSrc
    Err.Description = ls_ErrDesc
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("LockScreen")
End Sub

Private Sub InitCtrlSize()
On Error GoTo ErrHandler
Const c_margin As Long = 60

    Dim lLeft As Long, lTop As Long, lWidth As Long, lHeight As Long
    
    If UserControl.Extender.Height < 560 Then Exit Sub
    
    
    Call fra_filter.Move(c_margin, c_margin, fra_filter.Width, UserControl.Extender.Height)
    
    lLeft = fra_filter.Width + 2 * c_margin
    lTop = tlb_main.Height + c_margin
    lWidth = UserControl.Extender.Width - lLeft - 2 * c_margin
    lHeight = fra_filter.Height - lTop
    
    If lWidth < 4 * c_margin Or lHeight < (tv_main.Top + c_margin + 2 * c_margin + 120) Then Exit Sub
    
    Call tv_main.Move(c_margin, tv_main.Top, fra_filter.Width - 2 * c_margin, fra_filter.Height - tv_main.Top - c_margin)
    
    btn_refreshTreeview.Left = tv_main.Left + tv_main.Width - btn_refreshTreeview.Width
    
    Call tlb_main.Move(lLeft, fra_filter.Top, lWidth)
    Call fra_detail.Move(lLeft, tlb_main.Top + tlb_main.Height + c_margin, lWidth, lHeight)
    
    ' grid
    Call grd_main.Move(c_margin, c_margin + 120, fra_detail.Width - 2 * c_margin, fra_detail.Height - 2 * c_margin - 120)
    
    Exit Sub
ErrHandler:
    Call ErrorHandler("InitCtrlSize()")
End Sub

' Load the labels of a containers
Private Sub LoadLabels(ByRef ao_Armdb As ArmDb, ByRef ao_Container As Object, ByVal as_ScreenName As String, ByVal as_Language As String)
Dim lo_Control As Control   ' A control of the container
Dim li_idx As Integer, li_Count As Integer
Dim li_Label As Integer      ' A label idx
Dim ls_Request As String
Dim lc_Labels As Long
Dim lsa_ControlTag() As String
    
    On Error GoTo Trace_Err

    If mc_ScreenLabels = 0 Then
        ls_Request = "exec screen_csts '" & as_ScreenName & "','" & as_Language & "'"
        mc_ScreenLabels = OpenSQLSafe(ao_Armdb, ls_Request)
    End If
    lc_Labels = mc_ScreenLabels
    
    If lc_Labels = 0 Then
        Exit Sub
    End If
    
    On Error GoTo WithoutTag
    If ao_Container.Tag <> "" Then
        li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", ao_Container.Tag, , 1)
        If li_Label >= 0 Then
            ao_Container.Caption = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
        End If
    End If
WithoutTag:
    
    On Error GoTo Trace_Err
    
    ' Iterate the container for loading the label of each element which has defined a tag
    For Each lo_Control In UserControl.Controls
        
        If HasContainer(lo_Control, ao_Container) Or _
          ((ao_Container Is Me) And (UCase(TypeName(lo_Control)) = "MENU")) Then
            Select Case UCase(TypeName(lo_Control))
                Case UCase("TabStrip") ' Component is a tabstrip, we load the caption of each tab defined
                    Dim lo_Tbs
                    Set lo_Tbs = lo_Control ' Cast for use of intellisense
                    li_Count = lo_Tbs.Tabs.Count
                    For li_idx = 1 To li_Count
                        If lo_Tbs.Tabs(li_idx).Tag <> "" Then
                            li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lo_Tbs.Tabs(li_idx).Tag, , 1)
                            If li_Label >= 0 Then
                                lo_Tbs.Tabs(li_idx).Caption = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
                            End If
                        End If
                    Next
                    Set lo_Tbs = Nothing
                
                Case UCase("ListView") ' Component is a listview, we load the caption of each columns
                    Dim lo_ListView As ListView
                    Set lo_ListView = lo_Control
                    li_Count = lo_ListView.ColumnHeaders.Count
                    For li_idx = 1 To li_Count
                        If lo_ListView.ColumnHeaders(li_idx).Tag <> "" Then
                            li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lo_ListView.ColumnHeaders(li_idx).Tag, , 1)
                            If li_Label >= 0 Then
                                lo_ListView.ColumnHeaders(li_idx).Text = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
                            End If
                        End If
                    Next
                    Set lo_ListView = Nothing
            
                Case UCase("TextBox")  ' Component is a textbox
                    Dim lo_TextBox As TextBox
                    Set lo_TextBox = lo_Control
                    If lo_TextBox.Tag <> "" Then
                        lsa_ControlTag = Split(lo_Control.Tag, SEP)
                        li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lsa_ControlTag(0), , 1)
                        If li_Label >= 0 Then
                            lo_TextBox.Text = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
                        End If
                    End If
                    Set lo_TextBox = Nothing
                
                Case UCase("Label"), UCase("Frame"), UCase("CommandButton"), UCase("CheckBox"), UCase("OptionButton")
                    If lo_Control.Tag <> "" Then
                        lsa_ControlTag = Split(lo_Control.Tag, SEP)
                        li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lsa_ControlTag(0), , 1)
                        If li_Label >= 0 Then
                            lo_Control.Caption = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
                        End If
                    End If
                Case UCase("ArmGrid")
                    li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lo_Control.Tag, , 1)
                    If li_Label >= 0 Then
                      Call lo_Control.LoadConstants(ptStatic, ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT"), ctColumns)
                    End If
                    li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lo_Control.Tag & "_Title", , 1)
                    If li_Label >= 0 Then
                      lo_Control.Title = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
                    End If
                Case UCase("Menu")
                    If lo_Control.Tag <> "" Then
                        li_Label = ao_Armdb.Find(lc_Labels, "FIELD_NAME", lo_Control.Tag, , 1)
                        If li_Label >= 0 Then
                            lo_Control.Caption = ao_Armdb.GetFields(lc_Labels, "LOCAL_TEXT")
                        End If
                    End If
            End Select
        End If
    Next
        
Trace_End:
    Exit Sub
    
Trace_Err:
      
End Sub

Private Sub ChangeCharset(ByRef ao_Container As Object, Optional ByVal aCodePage As Long)

On Error GoTo ErrHandler
   
    Dim lc_Control As Control
    Dim ll_Charset As Long
    
    On Error Resume Next
    ll_Charset = GetCharSetFromCodePage(aCodePage)
    
    For Each lc_Control In ao_Container
        Select Case UCase(TypeName(lc_Control))
        Case "TABSTRIP", "TEXTBOX", "LABEL", "FRAME", "COMMANDBUTTON", _
              "LISTVIEW", "CHECKBOX", "OPTIONBUTTON", _
              "ARMCHECKVIEW", "ARMTREEVIEW", "ARMGRID", "ARMCOMBOBOX", "ARMCHECKVIEW0"
            lc_Control.Font.Name = "Arial"
            lc_Control.Font.Charset = ll_Charset
        Case "A_SEEK", "A_SRCHTXT"
            lc_Control.Charset = ll_Charset
        End Select
    Next
    
    Exit Sub

ErrHandler:
    Call ErrorHandler("ChangeCharset")
End Sub


Private Sub UpdateUI(Optional ByVal au_mode As ArmScreenMode)
On Error GoTo ErrHandler

    ' set active face
    tlb_main.Redraw = False

    ' apply face
    Dim lo_ctrl As Object

    ' hide all frames
    fra_detail.Visible = True
    grd_main.Visible = False

    ' we have clean screen we can display proper controls
    Select Case au_mode
        Case smMain
            grd_main.Visible = True
            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_LST)
        Case smUpdate, smAdd
            ' we are in Update section
            fra_detail.Visible = True

            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_MTNC)
        Case smView
            ' we are in PreView section
            fra_detail.Visible = True
            
            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_VIEW)
        Case smDelete
            ' we are in PreView section
            fra_detail.Visible = True
            
            Call tlb_main.DisplayFace(C_TOOLBARFACE_ITEM_MTNC_DEL)
        Case Else
            Debug.Assert (False)
    End Select
    
'    tlb_main.ButtonVisible("C") = mb_haveRights
    tlb_main.Redraw = True

    ' to display face immidiatelly
    UserControl.Refresh
    Exit Sub
ErrHandler:
    Call ErrorHandler("UpdateUI()")
End Sub

Private Function CustomReplacePlaceholder(ByRef as_Request As String, ByVal as_PlaceHolder As String, ByVal as_DefaultValue As String) As Boolean
On Error GoTo ErrHandler

    CustomReplacePlaceholder = False
    Exit Function
ErrHandler:
    Call ErrorHandler("CustomReplacePlaceholder")
End Function

Private Function ReplacePlaceHolder(ByVal as_Request As String, ByVal as_PlaceHolder As String, ByVal as_DefaultValue As String) As String
On Error GoTo ErrHandler
    
    If Not CustomReplacePlaceholder(as_Request, as_PlaceHolder, as_DefaultValue) Then
        as_Request = Replace(as_Request, as_PlaceHolder, as_DefaultValue, , , vbTextCompare)
    End If
    ReplacePlaceHolder = as_Request
    Exit Function
ErrHandler:
    Call ErrorHandler("ReplacePlaceholder")
End Function


Private Sub ShowReport_Grid(ByVal al_ReportID As Long, ByVal as_BU_Code As String, ByVal as_selectionGroupDesc As String)
On Error GoTo ErrorHandler

    Const C_REQ As String = "EXEC ONSV_Print_lst $REPORT_ID$, '$BU_GRP$', $LEVEL$"
    
    Dim ll_Cursor As Long
    Dim ll_cursorTotal As Long
    Dim ll_cursorTotalG As Long
    Dim ll_cursorTotalAll As Long
    Dim ll_cursorTotalG_Continental As Long
    Dim ll_cursorTotalAll_continental As Long
    Dim ll_cursorTotalG_SE As Long
    Dim ll_cursorTotalAll_SE As Long
    Dim ll_cursorTotalG_NE As Long
    Dim ll_cursorTotalAll_NE As Long
    
    Dim ls_reqTmp As String
        
    Call LockScreen(True)
    
    ' select report details
    ll_Cursor = OpenSQLSafe(mo_Db, "EXEC ONSV_Report_Header_sel " & al_ReportID)
    
    Dim ld_ReportDate As Date
    Dim ld_RunDate As Date
    Dim ls_Caption As String
    
    ld_ReportDate = mo_Db.GetFields(ll_Cursor, "Report_Date")
    ld_RunDate = mo_Db.GetFields(ll_Cursor, "Run_date")
    ls_Caption = mo_Db.GetFields(ll_Cursor, "Report_title")
    
    Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    
    
    ls_reqTmp = ReplacePlaceHolder(C_REQ, "$REPORT_ID$", al_ReportID)
    ls_reqTmp = ReplacePlaceHolder(ls_reqTmp, "$BU_GRP$", SqlStr(as_BU_Code))
    
    Debug.Print ls_reqTmp
    ll_Cursor = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "1"))
    Debug.Print mo_Db.RowCount(ll_Cursor)
    
    ll_cursorTotal = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "2"))                ' apear only for non VOL measure
    Debug.Print mo_Db.RowCount(ll_cursorTotal)
    
    ll_cursorTotalG = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "3"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG)
    
    ll_cursorTotalAll = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "4"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll)
    
    ll_cursorTotalG_Continental = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "5"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG_Continental)
    
    ll_cursorTotalAll_continental = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "6"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll_continental)

    ll_cursorTotalG_SE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "7"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG_SE)
    
    ll_cursorTotalAll_SE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "8"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll_SE)
    
    ll_cursorTotalG_NE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "9"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG_NE)
    
    ll_cursorTotalAll_NE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "10"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll_NE)
    
    ls_Caption = ls_Caption & vbCrLf & vbCrLf & "Report ID: " & al_ReportID & vbCrLf
    ls_Caption = ls_Caption & Format(ld_ReportDate, "\Date: MM/DD/YYYY ") & Format(ld_RunDate, "ra\n o\n MM/DD/YYYY") & vbCrLf & "Selection: " & as_selectionGroupDesc
    
    Call FillGrid_ONSV(ll_Cursor, ll_cursorTotal, ll_cursorTotalG, _
                    ll_cursorTotalG_SE, ll_cursorTotalG_NE, ll_cursorTotalG_Continental, _
                    ll_cursorTotalAll, ll_cursorTotalAll_SE, ll_cursorTotalAll_NE, ll_cursorTotalAll_continental, _
                    ls_Caption, Year(ld_ReportDate), Month(ld_ReportDate), False)
    
    If ll_cursorTotalAll_SE <> 0 Then Call mo_Db.Close(ll_cursorTotalAll_SE)
    ll_cursorTotalAll_SE = 0
    
    If ll_cursorTotalG_SE <> 0 Then Call mo_Db.Close(ll_cursorTotalG_SE)
    ll_cursorTotalG_SE = 0
    
    If ll_cursorTotalAll_NE <> 0 Then Call mo_Db.Close(ll_cursorTotalAll_NE)
    ll_cursorTotalAll_NE = 0
    
    If ll_cursorTotalG_NE <> 0 Then Call mo_Db.Close(ll_cursorTotalG_NE)
    ll_cursorTotalG_NE = 0
    
    If ll_cursorTotalAll_continental <> 0 Then Call mo_Db.Close(ll_cursorTotalAll_continental)
    ll_cursorTotalAll_continental = 0
    
    If ll_cursorTotalG_Continental <> 0 Then Call mo_Db.Close(ll_cursorTotalG_Continental)
    ll_cursorTotalG_Continental = 0
    
    If ll_Cursor <> 0 Then Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    
    If ll_cursorTotal <> 0 Then Call mo_Db.Close(ll_cursorTotal)
    ll_cursorTotal = 0
    
    If ll_cursorTotalG <> 0 Then Call mo_Db.Close(ll_cursorTotalG)
    ll_cursorTotalG = 0
    
    If ll_cursorTotalAll <> 0 Then Call mo_Db.Close(ll_cursorTotalAll)
    ll_cursorTotalAll = 0
    
    Call LockScreen(False)
    Exit Sub
ErrorHandler:
    If ll_Cursor > 0 Then
        Call mo_Db.Close(ll_Cursor)
        ll_Cursor = 0
    End If
    If ll_cursorTotal > 0 Then
        Call mo_Db.Close(ll_cursorTotal)
        ll_cursorTotal = 0
    End If
    If ll_cursorTotalG > 0 Then
        Call mo_Db.Close(ll_cursorTotalG)
        ll_cursorTotalG = 0
    End If
    If ll_cursorTotalAll > 0 Then
        Call mo_Db.Close(ll_cursorTotalAll)
        ll_cursorTotalAll = 0
    End If
    Call LockScreen(False)
    Call ErrorMessage(Extender.Name & ".ShowReport_Grid")
End Sub


Private Sub ShowReport_Excell(ByVal al_ReportID As Long, ByVal as_BU_Code As String, ByVal as_selectionGroupDesc As String, ByVal lb_PDF As Boolean)
On Error GoTo ErrorHandler

    Const C_REQ As String = "EXEC ONSV_Print_lst $REPORT_ID$, '$BU_GRP$', $LEVEL$"
    
    Dim ll_Cursor As Long
    Dim ll_cursorTotal As Long
    Dim ll_cursorTotalG As Long
    Dim ll_cursorTotalG_Continental As Long
    Dim ll_cursorTotalAll As Long
    Dim ll_cursorTotalAll_continental As Long
    Dim ll_cursorTotalAll_SE As Long
    Dim ll_cursorTotalG_SE As Long
    Dim ll_cursorTotalAll_NE As Long
    Dim ll_cursorTotalG_NE As Long
    
    Dim ls_reqTmp As String
        
    Call LockScreen(True)
    
    ' select report details
    ll_Cursor = OpenSQLSafe(mo_Db, "EXEC ONSV_Report_Header_sel " & al_ReportID)
    
    Dim ld_ReportDate As Date
    Dim ld_RunDate As Date
    Dim ls_Caption As String
    Dim ls_report_title As String
    Dim ls_measure As String
    
    ld_ReportDate = mo_Db.GetFields(ll_Cursor, "Report_Date")
    ld_RunDate = mo_Db.GetFields(ll_Cursor, "Run_date")
    ls_report_title = mo_Db.GetFields(ll_Cursor, "Report_title")
    ls_measure = mo_Db.GetFields(ll_Cursor, "Report_measure")
    
    Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    
    
    ls_reqTmp = ReplacePlaceHolder(C_REQ, "$REPORT_ID$", al_ReportID)
    ls_reqTmp = ReplacePlaceHolder(ls_reqTmp, "$BU_GRP$", SqlStr(as_BU_Code))
    
    Debug.Print ls_reqTmp
    ll_Cursor = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "1"))
    Debug.Print mo_Db.RowCount(ll_Cursor)
    
    ll_cursorTotal = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "2"))                  ' apear only for non VOL measure
    Debug.Print mo_Db.RowCount(ll_cursorTotal)
    
    ll_cursorTotalG = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "3"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG)
    
    ll_cursorTotalAll = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "4"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll)
    
    ll_cursorTotalG_Continental = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "5"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll)
    
    ll_cursorTotalAll_continental = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "6"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll_continental)
    
    ll_cursorTotalG_SE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "7"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG_SE)
    
    ll_cursorTotalAll_SE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "8"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll_SE)
    
    ll_cursorTotalG_NE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "9"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalG_NE)
    
    ll_cursorTotalAll_NE = OpenSQLSafe(mo_Db, ReplacePlaceHolder(ls_reqTmp, "$LEVEL$", "10"))
    Debug.Print mo_Db.RowCount(ll_cursorTotalAll_NE)

    ls_Caption = ls_report_title & vbCrLf & vbCrLf & "Report ID: " & al_ReportID & vbCrLf
    ls_Caption = ls_Caption & Format(ld_ReportDate, "\Date: MM/DD/YYYY ") & Format(ld_RunDate, "ra\n o\n MM/DD/YYYY") & vbCrLf & "Selection: " & as_selectionGroupDesc
    
    Call Export_Excell_ONSV(ll_Cursor, _
                            Array("BMK_Desc", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "C11", "C12", "C13", "C14", "C15", "C16", "C17", "C18", "C19", "C20", "C21", "C22", "C23", "C24"), _
                            ll_cursorTotal, ll_cursorTotalG, _
                            ll_cursorTotalG_SE, ll_cursorTotalG_NE, ll_cursorTotalG_Continental, ll_cursorTotalAll, _
                            ll_cursorTotalAll_SE, ll_cursorTotalAll_NE, ll_cursorTotalAll_continental, _
                            ls_Caption, Year(ld_ReportDate), Month(ld_ReportDate), ls_report_title, False, lb_PDF)
    
    If ll_cursorTotalAll_SE <> 0 Then Call mo_Db.Close(ll_cursorTotalAll_SE)
    ll_cursorTotalAll_SE = 0
    
    If ll_cursorTotalG_SE <> 0 Then Call mo_Db.Close(ll_cursorTotalG_SE)
    ll_cursorTotalG_SE = 0
    
    If ll_cursorTotalAll_NE <> 0 Then Call mo_Db.Close(ll_cursorTotalAll_NE)
    ll_cursorTotalAll_NE = 0
    
    If ll_cursorTotalG_NE <> 0 Then Call mo_Db.Close(ll_cursorTotalG_NE)
    ll_cursorTotalG_NE = 0
    
    If ll_Cursor <> 0 Then Call mo_Db.Close(ll_Cursor)
    ll_Cursor = 0
    
    If ll_cursorTotal <> 0 Then Call mo_Db.Close(ll_cursorTotal)
    ll_cursorTotal = 0
    
    If ll_cursorTotalG <> 0 Then Call mo_Db.Close(ll_cursorTotalG)
    ll_cursorTotalG = 0
    
    If ll_cursorTotalAll <> 0 Then Call mo_Db.Close(ll_cursorTotalAll)
    ll_cursorTotalAll = 0
    
    If ll_cursorTotalG_Continental <> 0 Then Call mo_Db.Close(ll_cursorTotalG_Continental)
    ll_cursorTotalG_Continental = 0
    
    If ll_cursorTotalAll_continental <> 0 Then Call mo_Db.Close(ll_cursorTotalAll_continental)
    ll_cursorTotalAll_continental = 0
    
    Call LockScreen(False)
    Exit Sub
ErrorHandler:
    If ll_Cursor > 0 Then
        Call mo_Db.Close(ll_Cursor)
        ll_Cursor = 0
    End If
    If ll_cursorTotal > 0 Then
        Call mo_Db.Close(ll_cursorTotal)
        ll_cursorTotal = 0
    End If
    If ll_cursorTotalG > 0 Then
        Call mo_Db.Close(ll_cursorTotalG)
        ll_cursorTotalG = 0
    End If
    If ll_cursorTotalAll > 0 Then
        Call mo_Db.Close(ll_cursorTotalAll)
        ll_cursorTotalAll = 0
    End If
    If ll_cursorTotalG_Continental > 0 Then
        Call mo_Db.Close(ll_cursorTotalG_Continental)
        ll_cursorTotalG_Continental = 0
    End If
    If ll_cursorTotalAll_continental > 0 Then
        Call mo_Db.Close(ll_cursorTotalAll_continental)
        ll_cursorTotalAll_continental = 0
    End If

    Call LockScreen(False)
    Call ErrorMessage(Extender.Name & ".ShowReport_Excell")
End Sub

Private Function GetPeriodDesc(ByVal al_month As Long) As String
    Select Case al_month
        Case 1, 2, 3
            GetPeriodDesc = ""
        Case 4, 5, 6
            GetPeriodDesc = "2+10"
        Case 7, 8, 9
            GetPeriodDesc = "5+7"
        Case 10, 11, 12
            GetPeriodDesc = "8+4"
    End Select
End Function

Private Sub Export_Excell_ONSV(ByVal al_Cursor As Long, ByVal av_DataFields As Variant, ByVal al_cursorTotal As Long, ByVal al_cursorTotalG As Long, _
                    ByVal al_cursorTotalG_SE As Long, ByVal al_cursorTotalG_NE As Long, ByVal al_cursorTotalG_continental As Long, _
                    ByVal al_cursorTotalAll As Long, _
                    ByVal al_cursorTotalAll_SE As Long, ByVal al_cursorTotalAll_NE As Long, ByVal al_cursorTotalAll_continental As Long, _
                    ByVal as_reporCaption As String, ByVal al_YearOfReport As Long, ByVal al_monthOfReport As Long, ByVal as_report_title As String, ByVal ab_excludeZero As Boolean, ByVal ab_PDF As Boolean)
On Error GoTo ErrorHandler
    If mo_Db.RowCount(al_Cursor) = 0 Then
        MsgBox ("Line is missing!!!")
        Exit Sub
    End If
    
    Dim a_ExcelApp                      As Object 'export_to_excel
    Dim a_ExcelWorkBook                 As Object 'export_to_excel
    Dim a_ExcelSheet1                   As Object  'export_to_excel 'Export_Grid
    Dim lb_ExcellOpenedNow As Boolean
    
    lb_ExcellOpenedNow = False
    Set a_ExcelApp = GetObject(, "Excel.Application")
    Set a_ExcelWorkBook = a_ExcelApp.Workbooks.Add
    While a_ExcelWorkBook.Sheets.Count > 1
        a_ExcelWorkBook.Sheets(1).Delete
    Wend
    Set a_ExcelSheet1 = a_ExcelWorkBook.Sheets(1)

    a_ExcelWorkBook.Activate
    a_ExcelSheet1.Activate
    
    If lb_ExcellOpenedNow Then
        a_ExcelApp.Application.Visible = False
    End If
    a_ExcelApp.ScreenUpdating = False
    
    With a_ExcelWorkBook.Styles("Normal").Font
        .Name = "Calibri"
        .Size = 9
    End With
    
    With a_ExcelSheet1
        .Range("A2:Z6").Interior.ColorIndex = 2
        
        .Columns("A").ColumnWidth = 7.34
        .Columns("B").ColumnWidth = 22
        .Columns("C").ColumnWidth = 10
        .Columns("D").ColumnWidth = 9.71
        .Columns("E").ColumnWidth = 10
        .Columns("F").ColumnWidth = 9.71
        .Columns("G").ColumnWidth = 10
        .Columns("H").ColumnWidth = 9.14
        .Columns("I").ColumnWidth = 10
        .Columns("J").ColumnWidth = 9.71
        .Columns("K").ColumnWidth = 10
        .Columns("L").ColumnWidth = 9.14
        .Columns("M").ColumnWidth = 10.5
        .Columns("N").ColumnWidth = 10.5
        .Columns("O").ColumnWidth = 10.5        ' 0
        .Columns("P").ColumnWidth = 10.5        ' 0
        .Columns("Q").ColumnWidth = 12.71
        .Columns("R").ColumnWidth = 12.71
        .Columns("S").ColumnWidth = 12.71
        .Columns("T").ColumnWidth = 12.71
        .Columns("U").ColumnWidth = 12.71
        .Columns("V").ColumnWidth = 10
        .Columns("W").ColumnWidth = 10
        .Columns("X").ColumnWidth = 10
        .Columns("Y").ColumnWidth = 10
        .Columns("Z").ColumnWidth = 10
        
        
        Dim ls_yearOfReport As String, ls_prevYearOfReport As String
        
        
        Dim ls_monthOfReport As String
        ls_monthOfReport = GetLabel("e_MONTH" & al_monthOfReport, al_monthOfReport)
        
        ReDim ms_MsgInfo(5, 1)
        ms_MsgInfo(0, 0) = "$REPORT_YEAR$"
        ms_MsgInfo(0, 1) = al_YearOfReport
        ms_MsgInfo(1, 0) = "$PERIOD_DESC$"
        ms_MsgInfo(1, 1) = GetPeriodDesc(al_monthOfReport)
        ms_MsgInfo(2, 0) = "$REPORT_PREV_YEAR$"
        ms_MsgInfo(2, 1) = al_YearOfReport - 1
        ms_MsgInfo(3, 0) = "$MONTH_NAME$"
        ms_MsgInfo(3, 1) = ls_monthOfReport
        ms_MsgInfo(4, 0) = "$XM1"
        ms_MsgInfo(5, 0) = "$XM2"
        If mo_Db.RowCount(al_cursorTotalAll) > 0 Then
            ms_MsgInfo(4, 1) = mo_Db.GetFields(al_cursorTotalAll, "C13") & " USD"
            ms_MsgInfo(5, 1) = mo_Db.GetFields(al_cursorTotalAll, "C14") & " USD"
        Else
            ms_MsgInfo(4, 1) = ""
            ms_MsgInfo(5, 1) = ""
        End If
                
        ls_prevYearOfReport = GetLabel("e_REPORT_PREV_YEAR", "$REPORT_PREV_YEAR$", ms_MsgInfo)
        ls_yearOfReport = GetLabel("e_REPORT_YEAR", "#$REPORT_YEAR$", ms_MsgInfo)
        
        Call SetRangeText(a_ExcelSheet1, 1, 2, 2, 6, as_reporCaption)
        .Cells(2, 1).Font.Bold = True
        Call SetRangeText(a_ExcelSheet1, 3, 2, 12, 2, GetLabel("e_ORDER_MNGM", "#ORDER MANAGEMENT"))
        Call SetRangeText(a_ExcelSheet1, 13, 2, 16, 3, GetLabel("e_SALES_BASELINES", "#SALES BASELINES"))
        Call SetRangeText(a_ExcelSheet1, 17, 2, 21, 4, GetLabel("e_RESULT", "#RESULT"))
        Call SetRangeText(a_ExcelSheet1, 22, 2, 26, 3, GetLabel("e_LOAD_PERFORM", "#LOAD PERFORMANCE"))
        
        Call SetRangeText(a_ExcelSheet1, 5, 3, 12, 3, GetLabel("e_ORDER_BALANCE", "#ORDER BALANCE"))
        
        Call SetRangeText(a_ExcelSheet1, 9, 4, 12, 4, GetLabel("e_ORDERS_DATED", "#Orders dated for"))
        Call SetRangeText(a_ExcelSheet1, 13, 4, 16, 4, GetLabel("e_MOTN_NAME", "$MONTH_NAME$", ms_MsgInfo))
        Call SetRangeText(a_ExcelSheet1, 22, 4, 22, 6, GetLabel("e_SALES_AND_ORDERS1", "#Sales + Orders for Month - Months Budget"))
        Call SetRangeText(a_ExcelSheet1, 23, 4, 23, 6, GetLabel("e_SALES_AND_ORDERS2", "#Sales + Orders for Month as  % of Budget"))
        Call SetRangeText(a_ExcelSheet1, 24, 4, 24, 6, GetLabel("e_SALES_AND_ORDERS3", "#Sales + Orders for Month as % of Last Year"))
        Call SetRangeText(a_ExcelSheet1, 25, 4, 25, 6, GetLabel("e_SALES_AND_ORDERS4", "#Sales + Orders for Month  as  % of FORECAST $XM1", ms_MsgInfo))
        Call SetRangeText(a_ExcelSheet1, 26, 4, 26, 6, GetLabel("e_SALES_AND_ORDERS5", "#Sales + Orders for Month  as  % of $PERIOD_DESC$ $XM2", ms_MsgInfo))
        
        Call SetRangeText(a_ExcelSheet1, 3, 5, 4, 5, GetLabel("e_INTAKE", "#INTAKE MTD"))
        Call SetRangeText(a_ExcelSheet1, 5, 5, 6, 5, GetLabel("e_BEGGINNING", "#BEGINNING"))
        Call SetRangeText(a_ExcelSheet1, 7, 5, 8, 5, GetLabel("e_MTD", "#MTD"))
        Call SetRangeText(a_ExcelSheet1, 9, 5, 10, 5, GetLabel("e_THIS_MONTH", "#This month"))
        Call SetRangeText(a_ExcelSheet1, 11, 5, 12, 5, GetLabel("e_NEXT_MONTH", "#Next month"))
        
        Call SetRangeText(a_ExcelSheet1, 13, 5, 13, 5, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 14, 5, 14, 5, ls_prevYearOfReport)
        Call SetRangeText(a_ExcelSheet1, 15, 5, 15, 5, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 16, 5, 16, 5, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 17, 5, 17, 6, GetLabel("e_SALES_ACTUAL", "#SALES ACTUAL MTD"))
        
        
        Call SetRangeText(a_ExcelSheet1, 18, 5, 18, 6, GetLabel("e_COMPARED_TO_MTD_BDG", "#COMPARED TO MTD BUDGET $REPORT_YEAR$", ms_MsgInfo))
        Call SetRangeText(a_ExcelSheet1, 19, 5, 19, 6, GetLabel("e_COMPARED_TO_MTD", "#COMPARED TO MTD ACTUAL LAST YEAR"))
        Call SetRangeText(a_ExcelSheet1, 20, 5, 20, 6, GetLabel("e_COMPARED_TO_MONTH_EST", "#COMPARED TO MTD $MONTH_NAME$ Estimate ABPE", ms_MsgInfo))
        Call SetRangeText(a_ExcelSheet1, 21, 5, 21, 6, GetLabel("e_COMPARED_TO_MONTH_CORP", "#COMPARED TO MTD $MONTH_NAME$ Corporate Est", ms_MsgInfo))
        
    
        Call SetRangeText(a_ExcelSheet1, 3, 6, 3, 6, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 4, 6, 4, 6, GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"))
        Call SetRangeText(a_ExcelSheet1, 5, 6, 5, 6, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 6, 6, 6, 6, GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"))
        Call SetRangeText(a_ExcelSheet1, 7, 6, 7, 6, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 8, 6, 8, 6, GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"))
        Call SetRangeText(a_ExcelSheet1, 9, 6, 9, 6, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 10, 6, 10, 6, GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"))
        Call SetRangeText(a_ExcelSheet1, 11, 6, 11, 6, ls_yearOfReport)
        Call SetRangeText(a_ExcelSheet1, 12, 6, 12, 6, GetLabel("e_COMPARED_TO_PY", "#Compared to PY %"))
        Call SetRangeText(a_ExcelSheet1, 13, 6, 13, 6, GetLabel("e_BUDGET", "#BUDGET"))
        Call SetRangeText(a_ExcelSheet1, 14, 6, 14, 6, GetLabel("e_ACTUAL", "#ACTUAL"))
        Call SetRangeText(a_ExcelSheet1, 15, 6, 15, 6, GetLabel("e_ESTIMATE", "#FORECAST"))
        Call SetRangeText(a_ExcelSheet1, 16, 6, 16, 6, GetLabel("e_ESTIMATE_CORP", "#$PERIOD_DESC$", ms_MsgInfo))
        
    End With
    
    
    Dim lIdxExcelRow As Long, lIdxExcelCol As Long
    
'    For lColIdx = 0 To 58
'        a_ExcelSheet1.cells(1, lColIdx + 1).Interior.ColorIndex = lColIdx
'        a_ExcelSheet1.cells(1, lColIdx + 1).value = lColIdx
'    Next
    
    lIdxExcelCol = 1
    lIdxExcelRow = 6
    

    With a_ExcelSheet1
        
        Dim lv_Data As Variant
        Dim lValue As Variant
        Dim lRangeTopLeft As String, lRangeBottomRight As String, lRange As String
        Dim ls_oldMG_Code As String
        Dim lb_isContinental_Old As Boolean
        
        ls_oldMG_Code = ""
        lb_isContinental_Old = True
        Call mo_Db.First(al_cursorTotalAll_continental)
        
        
        Dim ls_totalBUGrpTemplate As String
        ls_totalBUGrpTemplate = GetLabel("e_TOTALGRP", "#TOTAL $BU_GRP$")
        
        ' TOTAL FOR All Product groups
        lIdxExcelRow = lIdxExcelRow + 1
        ' insert empty line
        .Cells(lIdxExcelRow, 1).Value = GetLabel("e_ALL_GRP", "#TOTAL")
        lRange = "A" & lIdxExcelRow & ":Z" & lIdxExcelRow
        .Range(lRange).Interior.ColorIndex = 19
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        
        
        
        While Not mo_Db.EOF(al_cursorTotal)
            lIdxExcelRow = lIdxExcelRow + 1
        
            If mo_Db.GetFields(al_cursorTotal, "BMK_order") = 70 Then
                ' add total for South Europe
                If Not mo_Db.EOF(al_cursorTotalAll_SE) Then
                    lv_Data = mo_Db.GetFields(al_cursorTotalAll_SE, av_DataFields)
                    Call ReplaceNAValue(lv_Data)
                    .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    .Cells(lIdxExcelRow, 2).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "South Europe", , , vbTextCompare)
                    
                    lRange = "C" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                    .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
                    .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 24
                    lIdxExcelRow = lIdxExcelRow + 1
                End If
            End If
        
            If lb_isContinental_Old And mo_Db.GetFields(al_cursorTotal, "BMK_order") >= 100 Then
                lb_isContinental_Old = False
                
                ' total for North Europe
                If Not mo_Db.EOF(al_cursorTotalAll_NE) Then
                    lv_Data = mo_Db.GetFields(al_cursorTotalAll_NE, av_DataFields)
                    Call ReplaceNAValue(lv_Data)
                    .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    .Cells(lIdxExcelRow, 2).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "North Europe", , , vbTextCompare)
                    
                    lRange = "C" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                    .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
                    .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 24
                    lIdxExcelRow = lIdxExcelRow + 1
                End If
                
                ' add total for continental
                If Not mo_Db.EOF(al_cursorTotalAll_continental) Then
                    lv_Data = mo_Db.GetFields(al_cursorTotalAll_continental, av_DataFields)
                    Call ReplaceNAValue(lv_Data)
                    .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    .Cells(lIdxExcelRow, 2).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "CONTINENTAL", , , vbTextCompare)
                    
                    lRange = "C" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                    .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
                    .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 36
                    lIdxExcelRow = lIdxExcelRow + 1
                End If
                
            End If
        
        
            lv_Data = mo_Db.GetFields(al_cursorTotal, av_DataFields)
            If ab_excludeZero Then
                If IsZeroLine(lv_Data) Then
                    lIdxExcelRow = lIdxExcelRow - 1
                    GoTo NextLineTotal
                End If
            End If
            
            Call ReplaceNAValue(lv_Data)
            .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
            .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 2
NextLineTotal:
            Call mo_Db.Next(al_cursorTotal)
        Wend
        
        If mo_Db.RowCount(al_cursorTotalAll) > 0 Then
            ' insert empty line + total Line
            lIdxExcelRow = lIdxExcelRow + 2
            .Cells(lIdxExcelRow, 1).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", mo_Db.GetFields(al_Cursor, "BU_Grp"), , , vbTextCompare)
            .Range("A" & lIdxExcelRow - 1 & ":Z" & lIdxExcelRow - 1).Interior.ColorIndex = 19
            
            lv_Data = mo_Db.GetFields(al_cursorTotalAll, av_DataFields)
            Call ReplaceNAValue(lv_Data)
            .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
            
            lRange = "A" & lIdxExcelRow & ":Z" & lIdxExcelRow
            .Range(lRange).Interior.ColorIndex = 6
        End If
        
        
        lb_isContinental_Old = True
        ' CONTENTS
        While Not mo_Db.EOF(al_Cursor)
            If ls_oldMG_Code <> mo_Db.GetFields(al_Cursor, "MG_Code") Then
                If ls_oldMG_Code <> "" Then
                    ' insert empty line + total Line
                    lIdxExcelRow = lIdxExcelRow + 2
                    .Cells(lIdxExcelRow, 1).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", mo_Db.GetFields(al_Cursor, "BU_Grp"), , , vbTextCompare)
                    .Range("A" & lIdxExcelRow - 1 & ":Z" & lIdxExcelRow - 1).Interior.ColorIndex = 19
                    
                    If mo_Db.Find(al_cursorTotalG, "MG_Code", ls_oldMG_Code) >= 0 Then
                        lv_Data = mo_Db.GetFields(al_cursorTotalG, av_DataFields)
                        Call ReplaceNAValue(lv_Data)
                        .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    End If
                    
                    lRange = "A" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Interior.ColorIndex = 6
                   
                End If
                ' insert empty line
                lIdxExcelRow = lIdxExcelRow + 1
                .Cells(lIdxExcelRow, 1).Value = mo_Db.GetFields(al_Cursor, "MG_Desc")
                lRange = "A" & lIdxExcelRow & ":Z" & lIdxExcelRow
                .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
                .Range(lRange).Interior.ColorIndex = 19
                ls_oldMG_Code = mo_Db.GetFields(al_Cursor, "MG_Code")
                lb_isContinental_Old = True
                
            End If
            
            If mo_Db.GetFields(al_Cursor, "MG_Code") = MG_CODE_WOOL Then GoTo NextLine
            
            If mo_Db.GetFields(al_Cursor, "BMK_order") = 70 Then
                ' add total for South Europe
                If mo_Db.Find(al_cursorTotalG_SE, "MG_Code", ls_oldMG_Code) >= 0 Then
                    lIdxExcelRow = lIdxExcelRow + 1
                    lv_Data = mo_Db.GetFields(al_cursorTotalG_SE, av_DataFields)
                    Call ReplaceNAValue(lv_Data)
                    .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    .Cells(lIdxExcelRow, 2).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "South Europe", , , vbTextCompare)
                    
                    lRange = "C" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                    .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
                    .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 24
                End If
            End If


            If lb_isContinental_Old And mo_Db.GetFields(al_Cursor, "BMK_order") >= 100 Then
                lb_isContinental_Old = False
                
                ' add total for North Europe
                If mo_Db.Find(al_cursorTotalG_NE, "MG_Code", ls_oldMG_Code) >= 0 Then
                    lIdxExcelRow = lIdxExcelRow + 1
                    lv_Data = mo_Db.GetFields(al_cursorTotalG_NE, av_DataFields)
                    Call ReplaceNAValue(lv_Data)
                    .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    .Cells(lIdxExcelRow, 2).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "North Europe", , , vbTextCompare)
                    
                    lRange = "C" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                    .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
                    .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 24
                End If
                
                ' add total for continental
                If mo_Db.Find(al_cursorTotalG_continental, "MG_Code", ls_oldMG_Code) >= 0 Then
                    lIdxExcelRow = lIdxExcelRow + 1
                    lv_Data = mo_Db.GetFields(al_cursorTotalG_continental, av_DataFields)
                    Call ReplaceNAValue(lv_Data)
                    .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
                    .Cells(lIdxExcelRow, 2).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "CONTINENTAL", , , vbTextCompare)
                    
                    lRange = "C" & lIdxExcelRow & ":Z" & lIdxExcelRow
                    .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
                    .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
                    .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 36
                End If
                
            End If
            
            lv_Data = mo_Db.GetFields(al_Cursor, av_DataFields)
            If ab_excludeZero Then
                If IsZeroLine(lv_Data) Then
                    GoTo NextLine
                End If
            End If
            lIdxExcelRow = lIdxExcelRow + 1
            Call ReplaceNAValue(lv_Data)
            .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
            .Range("A" & lIdxExcelRow & ":Z" & lIdxExcelRow).Interior.ColorIndex = 2
NextLine:
            Call mo_Db.Next(al_Cursor)
        Wend
        
        If ls_oldMG_Code <> "" Then
            ' insert empty line + total Line
            lIdxExcelRow = lIdxExcelRow + 1
            .Cells(lIdxExcelRow, 1).Value = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", mo_Db.GetFields(al_Cursor, "BU_Grp"), , , vbTextCompare)
            If mo_Db.Find(al_cursorTotalG, "MG_Code", ls_oldMG_Code) >= 0 Then
                lv_Data = mo_Db.GetFields(al_cursorTotalG, av_DataFields)
                Call ReplaceNAValue(lv_Data)
                .Range(.Cells(lIdxExcelRow, 2), .Cells(lIdxExcelRow, UBound(lv_Data) + 2)) = lv_Data
            End If
            lRange = "A" & lIdxExcelRow & ":Z" & lIdxExcelRow
            .Range(lRange).Interior.ColorIndex = 6
        End If
        
        ' left two cols are bold
        lRange = "A2:B" & (lIdxExcelRow)
        .Range(lRange).Font.Bold = True
        
        ' ADD THE STYLE
        lRange = "C8:C" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "D8:D" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "E8:E" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "F8:F" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "G8:G" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "H8:H" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "I8:I" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "J8:J" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "K8:K" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "L8:L" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "M8:Q" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "R8:R" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "S8:S" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "T8:T" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "U8:U" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "V8:V" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "#,##0.0"
        lRange = "W8:W" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "X8:X" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "Y8:Y" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        lRange = "Z8:Z" & (lIdxExcelRow)
        .Range(lRange).NumberFormat = "0.0%"
        
        lRange = "C7:Z" & (lIdxExcelRow)
        .Range(lRange).HorizontalAlignment = xlCenter
        
        ' WHOLE DOCUMENT
        lRange = "A2:Z" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeLeft).Weight = xlThin
        .Range(lRange).Borders(xlEdgeLeft).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeBottom).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' HEADER BOTTOM LINE
         .Range("A2:Z6").Borders(xlEdgeBottom).Weight = xlMedium
         .Range("A2:Z6").Borders(xlEdgeBottom).LineStyle = xlContinuous
         
        
        ' ORDER MANAGEMENT
        lRange = "C2:L" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeLeft).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeLeft).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeBottom).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        
        ' SALES BASELINES
        lRange = "M2:P" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeLeft).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeLeft).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeBottom).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' RESULT
        lRange = "Q2:U" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeLeft).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeLeft).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeBottom).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' LOAD PERFORMANCE
        lRange = "V2:Z" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeLeft).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeLeft).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeBottom).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' ORDER BALANCE
        lRange = "E3:L" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeLeft).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeLeft).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeBottom).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeBottom).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        lRange = "C3:D3"
        .Range(lRange).Borders(xlEdgeTop).Weight = xlMedium
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        lRange = "I5:L5"
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        
        ' BEGINNING
        lRange = "E4:F" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' MTD
        lRange = "G4:H" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Orders dated for
        lRange = "I4:L" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        
        ' JUNE
        lRange = "M4:P" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
                
        ' Sales + Orders for Month - Months Budget
        lRange = "V4:V" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Sales + Orders for Month as  % of Budget
        lRange = "W4:W" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Sales + Orders for Month as % of Last Year
        lRange = "X4:X" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Sales + Orders for Month  as  % of Estimate ABPE
        lRange = "Y4:Y" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Sales + Orders for Month  as  % of Corporate Estimate
        lRange = "Z4:Z" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeTop).Weight = xlThin
        .Range(lRange).Borders(xlEdgeTop).LineStyle = xlContinuous
        
        ' INTAKE MTD for the year
        lRange = "C7:C" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' BEGGINING for the year
        lRange = "E7:E" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' BALANCE MTD for the year
        lRange = "G7:G" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Dated for this month
        lRange = "I7:I" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Dated for this month %
        lRange = "J7:J" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Dated for next month
        lRange = "K7:K" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' BUDGET ACTUAL 2014
        lRange = "M7:M" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' BUDGET ACTUAL 2013
        lRange = "N7:N" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' Forecast 2014
        lRange = "O7:O" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' SALES ACTUAL MTD
        lRange = "Q7:Q" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' COMPARED TO MTD BUDGET 2014
        lRange = "R7:R" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' COMPARED TO MTD ACTUAL LAST YEAR
        lRange = "S7:S" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        ' COMPARED TO MTD Forecast
        lRange = "T7:T" & (lIdxExcelRow)
        .Range(lRange).Borders(xlEdgeRight).Weight = xlThin
        .Range(lRange).Borders(xlEdgeRight).LineStyle = xlContinuous
        
        
    End With
    
    With a_ExcelSheet1.PageSetup
        .PrintTitleRows = a_ExcelSheet1.Range("A2:Z6").Address
        .PrintTitleColumns = a_ExcelSheet1.Columns("A:Z").Address
        .PrintArea = "$A$2:$Z$" & lIdxExcelRow
        .LeftHeader = ""
        .CenterHeader = ""
        .RightHeader = ""
        .LeftFooter = ""
        .CenterFooter = ""
        .RightFooter = ""
        .PrintHeadings = False
        .PrintGridlines = False
        .CenterHorizontally = True
        .CenterVertically = False
        .Orientation = xlLandscape
        .Draft = False
        .BlackAndWhite = False
        .Zoom = 70
        .FitToPagesWide = 1
        .FitToPagesTall = 1
        .PaperSize = xlPaperA3
        .LeftMargin = a_ExcelApp.CentimetersToPoints(0.4)
        .TopMargin = a_ExcelApp.CentimetersToPoints(0.4)
        .RightMargin = a_ExcelApp.CentimetersToPoints(0.4)
        .BottomMargin = a_ExcelApp.CentimetersToPoints(0.4)
    End With
    
    a_ExcelApp.Visible = True
    a_ExcelApp.ScreenUpdating = True


    Dim ls_Filename As String
    
    ls_Filename = Replace(as_report_title & "_" & al_YearOfReport & "_" & al_monthOfReport, " ", "_")
    a_ExcelSheet1.Name = ls_Filename
    
    If ab_PDF Then
        a_ExcelSheet1.ExportAsFixedFormat Type:=0, FileName:= _
                 ls_Filename & ".pdf", Quality:=0, _
                 IncludeDocProperties:=True, IgnorePrintAreas:=False, OpenAfterPublish:=True
        a_ExcelWorkBook.Close SaveChanges:=False
    End If
    
    If lb_ExcellOpenedNow Then
        a_ExcelApp.Application.Visible = True
        If ab_PDF Then
            ' close it
            a_ExcelApp.quit
        End If
    End If
    
    Set a_ExcelSheet1 = Nothing
    Set a_ExcelWorkBook = Nothing
    Set a_ExcelApp = Nothing
    Screen.MousePointer = 0
          
    MsgBox MsgText(108, ms_Language_Code, "#Press ALT+TAB to switch to the Excel application.")
    Exit Sub
    
ErrorHandler:
    If Err.Number = 429 Then
        Set a_ExcelApp = CreateObject("Excel.Application")
        lb_ExcellOpenedNow = True
        Resume Next
    Else
        If Err.Number = 1004 Then
            'debug.print Err.Description
            Resume Next
        Else
            Screen.MousePointer = 0
            Set a_ExcelApp = Nothing
            Screen.MousePointer = 0
        End If
    End If

    Call ErrorHandler(Extender.Name & ".Export_Grid_StatPrj")
End Sub

Private Sub FillGrid_ONSV(ByVal al_Cursor As Long, ByVal al_cursorTotal As Long, ByVal al_cursorTotalG As Long, _
                    ByVal al_cursorTotalG_SE As Long, ByVal al_cursorTotalG_NE As Long, ByVal al_cursorTotalG_continental As Long, _
                    ByVal al_cursorTotalAll As Long, _
                    ByVal al_cursorTotalAll_SE As Long, ByVal al_cursorTotalAll_NE As Long, ByVal al_cursorTotalAll_continental As Long, _
                    ByVal as_reporCaption As String, ByVal al_YearOfReport As Long, ByVal al_monthOfReport As Long, ByVal ab_excludeZero As Boolean)
On Error GoTo ErrorHandler
    grd_main.Rows = 5
    If mo_Db.RowCount(al_Cursor) = 0 Then
'        MsgBox ("Total summ line is missing!!!")
        Exit Sub
    End If
    
        
        
    Dim ls_yearOfReport As String, ls_prevYearOfReport As String
    Dim ls_monthOfReport As String
    ls_monthOfReport = GetLabel("e_MONTH" & al_monthOfReport, al_monthOfReport)
    
    ReDim ms_MsgInfo(5, 1)
    ms_MsgInfo(0, 0) = "$REPORT_YEAR$"
    ms_MsgInfo(0, 1) = al_YearOfReport
    ms_MsgInfo(1, 0) = "$PERIOD_DESC$"
    ms_MsgInfo(1, 1) = GetPeriodDesc(al_monthOfReport)
    ms_MsgInfo(2, 0) = "$REPORT_PREV_YEAR$"
    ms_MsgInfo(2, 1) = al_YearOfReport - 1
    ms_MsgInfo(3, 0) = "$MONTH_NAME$"
    ms_MsgInfo(3, 1) = ls_monthOfReport
    ms_MsgInfo(4, 0) = "$XM1"
    ms_MsgInfo(5, 0) = "$XM2"
    If mo_Db.RowCount(al_cursorTotalAll) > 0 Then
        ms_MsgInfo(4, 1) = mo_Db.GetFields(al_cursorTotalAll, "C13") & " USD"
        ms_MsgInfo(5, 1) = mo_Db.GetFields(al_cursorTotalAll, "C14") & " USD"
    Else
        ms_MsgInfo(4, 1) = ""
        ms_MsgInfo(5, 1) = ""
    End If
    
    ls_prevYearOfReport = GetLabel("e_REPORT_PREV_YEAR", "$REPORT_PREV_YEAR$", ms_MsgInfo)
    ls_yearOfReport = GetLabel("e_REPORT_YEAR", "#$REPORT_YEAR$", ms_MsgInfo)
    
    
    Call SetRangeTextGrid(grd_main, 1, 0, 1, 4, as_reporCaption)
    
    Call SetRangeTextGrid(grd_main, 13, 2, 16, 2, Format("01/" & Format(al_monthOfReport, "0#") & "/2000", "MMM"))
    
    Call SetRangeTextGrid(grd_main, 13, 3, 13, 3, ls_yearOfReport)
    Call SetRangeTextGrid(grd_main, 14, 3, 14, 3, ls_prevYearOfReport)
    Call SetRangeTextGrid(grd_main, 15, 3, 15, 3, ls_yearOfReport)
    Call SetRangeTextGrid(grd_main, 16, 3, 16, 3, ls_yearOfReport)

    Call SetRangeTextGrid(grd_main, 25, 1, 25, 4, GetLabel("e_SALES_AND_ORDERS4", "#Sales + Orders for Month  as  % of FORECAST $XM1", ms_MsgInfo))
    Call SetRangeTextGrid(grd_main, 26, 1, 26, 4, GetLabel("e_SALES_AND_ORDERS5", "#Sales + Orders for Month  as  % of $PERIOD_DESC$ $XM2", ms_MsgInfo))

    
    Call SetRangeTextGrid(grd_main, 18, 2, 18, 4, GetLabel("e_COMPARED_TO_MTD_BDG", "#COMPARED TO MTD BUDGET $REPORT_YEAR$", ms_MsgInfo))
    Call SetRangeTextGrid(grd_main, 20, 2, 20, 4, GetLabel("e_COMPARED_TO_MONTH_EST", "#COMPARED TO MTD $MONTH_NAME$ Estimate ABPE", ms_MsgInfo))
    Call SetRangeTextGrid(grd_main, 21, 2, 21, 4, GetLabel("e_COMPARED_TO_MONTH_CORP", "#COMPARED TO MTD $MONTH_NAME$ Corporate Est", ms_MsgInfo))
    
    Call SetRangeTextGrid(grd_main, 3, 4, 3, 4, ls_yearOfReport)
    Call SetRangeTextGrid(grd_main, 5, 4, 5, 4, ls_yearOfReport)
    Call SetRangeTextGrid(grd_main, 7, 4, 7, 4, ls_yearOfReport)
    Call SetRangeTextGrid(grd_main, 9, 4, 9, 4, ls_yearOfReport)
    Call SetRangeTextGrid(grd_main, 11, 4, 11, 4, ls_yearOfReport)
    
    Call SetRangeTextGrid(grd_main, 16, 4, 16, 4, GetLabel("e_ESTIMATE_CORP", "#$PERIOD_DESC$", ms_MsgInfo))

    
    Dim lIdxExcelRow As Long, lIdxExcelCol As Long
    
'    For lColIdx = 0 To 58
'        a_ExcelSheet1.cells(1, lColIdx + 1).Interior.ColorIndex = lColIdx
'        a_ExcelSheet1.cells(1, lColIdx + 1).value = lColIdx
'    Next
    
    lIdxExcelCol = 1
    lIdxExcelRow = 4
    

    
    Dim lValue As Variant
    Dim lRangeTopLeft As String, lRangeBottomRight As String, lRange As String
    Dim ls_oldMG_Code As String
    
    Dim ll_bkgColor As OLE_COLOR
    ll_bkgColor = CL_Back1
    
    ls_oldMG_Code = ""
    Dim lb_isContinental_Old As Boolean

    Dim ls_totalBUGrpTemplate As String
    ls_totalBUGrpTemplate = GetLabel("e_TOTALGRP", "#TOTAL $BU_GRP$")
    
    
    ' TOTAL
    lb_isContinental_Old = True
    While Not mo_Db.EOF(al_cursorTotal)
        lIdxExcelRow = lIdxExcelRow + 1
        grd_main.Rows = lIdxExcelRow + 1
        
        If mo_Db.GetFields(al_cursorTotal, "BMK_order") = 70 Then
            ' add total for South Europe
            If Not mo_Db.EOF(al_cursorTotalAll_SE) Then
                Call FillGridLine(al_cursorTotalAll_SE, lIdxExcelRow, mo_grd_MainInfo)
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "South Europe", , , vbTextCompare)
                grd_main.TextMatrix(lIdxExcelRow, 1) = GetLabel("e_ALL_GRP", "#All Product Groups")
                Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL_SE_NE)
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
            End If
        End If

        If lb_isContinental_Old And mo_Db.GetFields(al_cursorTotal, "BMK_order") >= 100 Then
            lb_isContinental_Old = False
            ' add North Europe total
            If Not mo_Db.EOF(al_cursorTotalAll_NE) Then
                Call FillGridLine(al_cursorTotalAll_NE, lIdxExcelRow, mo_grd_MainInfo)
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "North Europe", , , vbTextCompare)
                grd_main.TextMatrix(lIdxExcelRow, 1) = GetLabel("e_ALL_GRP", "#All Product Groups")
                Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL_SE_NE)
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
            End If
            
            ' add total for continental
            If Not mo_Db.EOF(al_cursorTotalAll_continental) Then
                Call FillGridLine(al_cursorTotalAll_continental, lIdxExcelRow, mo_grd_MainInfo)
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "CONTINENTAL", , , vbTextCompare)
                grd_main.TextMatrix(lIdxExcelRow, 1) = GetLabel("e_ALL_GRP", "#All Product Groups")
                Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL_CONTINENTAL)
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
            End If
            
        End If

        If ab_excludeZero Then
            If IsZeroLineCursor(al_cursorTotal, mo_grd_MainInfo) Then
                lIdxExcelRow = lIdxExcelRow - 1
                grd_main.Rows = lIdxExcelRow + 1
                GoTo NextLineTotal
            End If
        End If
        
        Call FillGridLine(al_cursorTotal, lIdxExcelRow, mo_grd_MainInfo)
        grd_main.TextMatrix(lIdxExcelRow, 1) = GetLabel("e_ALL_GRP", "#All Product Groups")
NextLineTotal:
        Call mo_Db.Next(al_cursorTotal)
    Wend
    
    If mo_Db.RowCount(al_cursorTotalAll) > 0 Then
        ' insert empty line + total Line
        lIdxExcelRow = lIdxExcelRow + 1
        grd_main.Rows = lIdxExcelRow + 1
        
        Call FillGridLine(al_cursorTotalAll, lIdxExcelRow, mo_grd_MainInfo)
        grd_main.TextMatrix(lIdxExcelRow, 1) = GetLabel("e_ALL_GRP", "#All Product Groups")
        grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", mo_Db.GetFields(al_Cursor, "BU_Grp"), , , vbTextCompare)
        Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL)
    End If
    
    ' CONTENTS
    lb_isContinental_Old = True
    While Not mo_Db.EOF(al_Cursor)
        If ls_oldMG_Code <> mo_Db.GetFields(al_Cursor, "MG_Code") Then
            If ls_oldMG_Code <> "" Then
                ' insert total Line
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
                If mo_Db.Find(al_cursorTotalG, "MG_Code", ls_oldMG_Code) >= 0 Then
                    Call FillGridLine(al_cursorTotalG, lIdxExcelRow, mo_grd_MainInfo)
                    Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL)
                End If
                
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", mo_Db.GetFields(al_Cursor, "BU_Grp"), , , vbTextCompare)
                
            End If
            
            If ll_bkgColor = CL_Back1 Then ll_bkgColor = CL_Back2 Else ll_bkgColor = CL_Back1
            
            ls_oldMG_Code = mo_Db.GetFields(al_Cursor, "MG_Code")
            lb_isContinental_Old = True
        End If
        
        If mo_Db.GetFields(al_Cursor, "MG_Code") = MG_CODE_WOOL Then GoTo NextLine

        If mo_Db.GetFields(al_Cursor, "BMK_order") = 70 Then
            ' add total for South Europe
            If mo_Db.Find(al_cursorTotalG_SE, "MG_Code", ls_oldMG_Code) >= 0 Then
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
                
                Call FillGridLine(al_cursorTotalG_SE, lIdxExcelRow, mo_grd_MainInfo)
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "South Europe", , , vbTextCompare)
                Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL_SE_NE)
            End If
        End If

        If lb_isContinental_Old And mo_Db.GetFields(al_Cursor, "BMK_order") >= 100 Then
            lb_isContinental_Old = False
            
            ' add North Europe total
            If mo_Db.Find(al_cursorTotalG_NE, "MG_Code", ls_oldMG_Code) >= 0 Then
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
                
                Call FillGridLine(al_cursorTotalG_NE, lIdxExcelRow, mo_grd_MainInfo)
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "North Europe", , , vbTextCompare)
                Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL_SE_NE)
            End If
            
            ' add total for continental
            If mo_Db.Find(al_cursorTotalG_continental, "MG_Code", ls_oldMG_Code) >= 0 Then
                lIdxExcelRow = lIdxExcelRow + 1
                grd_main.Rows = lIdxExcelRow + 1
                
                Call FillGridLine(al_cursorTotalG_continental, lIdxExcelRow, mo_grd_MainInfo)
                grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate, "$BU_GRP$", "CONTINENTAL", , , vbTextCompare)
                Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL_CONTINENTAL)
            End If
            
        End If

        If ab_excludeZero Then
            If IsZeroLineCursor(al_Cursor, mo_grd_MainInfo) Then
                GoTo NextLine
            End If
        End If
        lIdxExcelRow = lIdxExcelRow + 1
        grd_main.Rows = lIdxExcelRow + 1
        Call FillGridLine(al_Cursor, lIdxExcelRow, mo_grd_MainInfo)
        Call SetGridBkgColor(lIdxExcelRow, 3, 26, ll_bkgColor)
NextLine:
        Call mo_Db.Next(al_Cursor)
    Wend
    
    If ls_oldMG_Code <> "" Then
        ' insert empty line + total Line
        lIdxExcelRow = lIdxExcelRow + 1
        grd_main.Rows = lIdxExcelRow + 1
        If mo_Db.Find(al_cursorTotalG, "MG_Code", ls_oldMG_Code) >= 0 Then
            Call FillGridLine(al_cursorTotalG, lIdxExcelRow, mo_grd_MainInfo)
        End If
        grd_main.TextMatrix(lIdxExcelRow, 2) = Replace(ls_totalBUGrpTemplate + " ", "$BU_GRP$", mo_Db.GetFields(al_Cursor, "BU_Grp"), , , vbTextCompare)
        Call SetGridBkgColor(lIdxExcelRow, 2, 26, CL_TOTAL)
    
    End If
    
    
Screen.MousePointer = 0
      
Exit Sub
    
ErrorHandler:
Resume Next
    Call ErrorHandler(Extender.Name & ".FillGrid_ONSV")
End Sub

Private Function IsZeroLineCursor(ByVal al_DataCursor As Long, ByRef ao_ColDef As GRD_Info) As Boolean
On Error GoTo ErrorHandler
    IsZeroLineCursor = False
    
    Dim ll_i As Long
    Dim ll_colBase As Long
    ll_colBase = ao_ColDef.RowColBase(UBound(ao_ColDef.RowColBase)) + 1     ' skip ID
    
    ' check if value is zero
    Dim fValue As Variant
    
    For ll_i = ll_colBase To UBound(ao_ColDef.Cols)
        If ao_ColDef.Cols(ll_i).DB_Name <> "" Then
            fValue = mo_Db.GetFields(al_DataCursor, ao_ColDef.Cols(ll_i).DB_Name)
            If IsNumeric(fValue) Then
                If fValue <> -9999999 And fValue <> 0 Then Exit Function
            End If
        End If
    Next ll_i
    
    IsZeroLineCursor = True
    Exit Function
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".IsZeroLineCursor")
End Function

Private Sub FillGridLine(ByVal al_DataCursor As Long, ByVal al_Row As Long, ByRef ao_ColDef As GRD_Info)
    Dim ll_i As Long
    Dim ll_colBase As Long
    Dim ls_Value As String
    ll_colBase = ao_ColDef.RowColBase(UBound(ao_ColDef.RowColBase))
     
    For ll_i = ll_colBase To UBound(ao_ColDef.Cols)
        If ao_ColDef.Cols(ll_i).DB_Name <> "" Then
            If ao_ColDef.Cols(ll_i).Format <> "" Then
                ls_Value = mo_Db.GetFields(al_DataCursor, ao_ColDef.Cols(ll_i).DB_Name)
                If IsNumeric(Replace(ls_Value, ".", ms_DecimalSeparator)) Then
                    grd_main.TextMatrix(al_Row, ao_ColDef.Cols(ll_i).Index) = Format(CDbl(Replace(ls_Value, ".", ms_DecimalSeparator)), ao_ColDef.Cols(ll_i).Format)
                Else
                    grd_main.TextMatrix(al_Row, ao_ColDef.Cols(ll_i).Index) = Format(ls_Value, ao_ColDef.Cols(ll_i).Format)
                End If
            Else
                grd_main.TextMatrix(al_Row, ao_ColDef.Cols(ll_i).Index) = mo_Db.GetFields(al_DataCursor, ao_ColDef.Cols(ll_i).DB_Name)
            End If
        End If
    Next ll_i
End Sub

Private Sub FillGridLine_X(ByRef av_Data As Variant, ByVal al_Row As Long, ByVal al_StartCol As Long, ByRef ao_ColDef As GRD_Info)
    Dim ll_i As Long
    Dim ll_colBase As Long
    ll_colBase = ao_ColDef.RowColBase(UBound(ao_ColDef.RowColBase))
     
    For ll_i = LBound(av_Data) To UBound(av_Data)
        If ao_ColDef.Cols(ll_colBase + ll_i).Format <> "" Then
            grd_main.TextMatrix(al_Row, ll_i + al_StartCol) = Format(av_Data(ll_i), ao_ColDef.Cols(ll_colBase + ll_i).Format)
        Else
            grd_main.TextMatrix(al_Row, ll_i + al_StartCol) = av_Data(ll_i)
        End If
    Next ll_i
End Sub

Private Sub SetGridBkgColor(ByVal al_Row As Long, ByVal al_startCell As Long, ByVal al_endCell As Long, ByVal al_Color As OLE_COLOR)
    Dim ll_i As Long
    grd_main.Row = al_Row
    For ll_i = al_startCell To al_endCell
        grd_main.Col = ll_i
        grd_main.CellBackColor = al_Color
    Next ll_i
End Sub

Private Function IsZeroLine(ByRef av_Data As Variant) As Boolean
On Error GoTo ErrorHandler
    IsZeroLine = False
    Dim ll_i As Long
    ' check if value is zero
    For ll_i = LBound(av_Data) + 1 To UBound(av_Data)
        If av_Data(ll_i) <> -9999999 And av_Data(ll_i) <> 0 Then Exit Function
    Next

    IsZeroLine = True
    Exit Function
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".IsZeroLine")
End Function

Private Sub ReplaceNAValue(ByRef av_Data As Variant)
On Error GoTo ErrorHandler
    Dim ll_i As Long
    ' replace -9999999 with N/A
    For ll_i = LBound(av_Data) To UBound(av_Data)
        If av_Data(ll_i) = -9999999 Then av_Data(ll_i) = "'N/A"
    Next
    Exit Sub
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".ReplaceNAValue")
End Sub

Private Function ConvertToRange(ByVal al_Col As Long, ByVal al_Row As Long) As String
On Error GoTo ErrorHandler
    Dim ls_retVal As String
    
    If al_Col > 26 Then
        ls_retVal = ls_retVal & ConvertToRange(al_Col / 26, al_Row)
    Else
        ls_retVal = Chr(64 + al_Col) & al_Row
    End If
    
    ConvertToRange = ls_retVal
    Exit Function
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".ConvertToRange")
End Function

Private Sub SetRangeText(ByRef ao_Sheet As Object, ByVal al_StartCol As Long, ByVal al_StartRow As Long, ByVal al_endCol As Long, ByVal al_EndRow As Long, ByVal as_Value As Variant)
On Error GoTo ErrorHandler
    With ao_Sheet
        .Cells(al_StartRow, al_StartCol).Value = as_Value
        ' do merge
        With .Range(.Cells(al_StartRow, al_StartCol), .Cells(al_EndRow, al_endCol))
            .VerticalAlignment = xlCenter
            .HorizontalAlignment = xlCenter
            .WrapText = True
            .MergeCells = True
        End With
    End With
    Exit Sub
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".SetRangeText")
End Sub

Private Sub SetRangeTextGrid(ByRef ao_grid As MSFlexGrid, ByVal al_StartCol As Long, ByVal al_StartRow As Long, ByVal al_endCol As Long, ByVal al_EndRow As Long, ByVal as_Value As Variant)
On Error GoTo ErrorHandler
    Dim ll_Row, ll_Col As Long
    With ao_grid
        For ll_Col = al_StartCol To al_endCol
            For ll_Row = al_StartRow To al_EndRow
                .TextMatrix(ll_Row, ll_Col) = as_Value
            Next ll_Row
        Next ll_Col
    End With
    
    If al_EndRow - al_StartRow > 0 Then
        For ll_Col = al_StartCol To al_endCol
            ao_grid.MergeCol(ll_Col) = True
        Next
    End If
    If al_endCol - al_StartCol > 0 Then
        For ll_Row = al_StartRow To al_EndRow
            ao_grid.MergeRow(ll_Row) = True
        Next
    End If
    Exit Sub
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".SetRangeText")
End Sub



Private Function GetLabel(ByVal as_Tag As String, ByVal as_DefaultValue As String, Optional ByVal aInfo As Variant) As String
On Error GoTo ErrorHandler

    If mo_Db.Find(mc_ScreenLabels, "FIELD_NAME", as_Tag, , 1) >= 0 Then
        as_DefaultValue = mo_Db.GetFields(mc_ScreenLabels, "LOCAL_TEXT")
    End If
    
    Dim li_idx As Integer
    If Not IsMissing(aInfo) Then
        For li_idx = 0 To UBound(aInfo)
            as_DefaultValue = Replace(as_DefaultValue, aInfo(li_idx, 0), aInfo(li_idx, 1), , , vbTextCompare)
        Next li_idx
    End If
    
    
    GetLabel = as_DefaultValue

    Exit Function
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".GetLabel")
End Function


Private Function HasContainer(ByVal lo_Control As Control, ByRef lo_Container As Object) As Boolean
    Dim ll_Index As Long
    Dim lo_Object As Object

    On Error GoTo CleanUp   'not all controls support Container property
    HasContainer = False
    While Not (lo_Control Is Nothing)
        If lo_Control.Container Is lo_Container Then
            HasContainer = True
            Exit Function
        End If
        Set lo_Control = lo_Control.Container
    Wend

CleanUp:

End Function

' initalize header of a grid
' 0 .. Name, 1.. label, 2.. width, 3... DB_Field_Name, 4... allign, 5... format
Private Sub GRD_SetHeader(ByRef ao_grid As MSFlexGrid, ByRef ao_GRDInfo As GRD_Info, ByRef av_colDef As Variant)
On Error GoTo ErrorHandler
    Debug.Assert (IsArray(av_colDef))
    
    Dim ll_ColIdx As Long
    Dim ll_colBase As Long
    Dim ll_RowIdx As Long
    
    ReDim ao_GRDInfo.Cols(0) As GRD_ColumnInfo
    
    If ao_grid.Rows <= UBound(av_colDef) Then ao_grid.Rows = UBound(av_colDef) + 1
    
    ll_colBase = 0
    ReDim ao_GRDInfo.RowColBase(UBound(av_colDef)) As Long
    
    For ll_RowIdx = LBound(av_colDef) To UBound(av_colDef)
        Debug.Assert (IsArray(av_colDef(ll_RowIdx)))
        
        ReDim Preserve ao_GRDInfo.Cols(ll_colBase + UBound(av_colDef(ll_RowIdx))) As GRD_ColumnInfo
        ao_GRDInfo.RowColBase(ll_RowIdx) = ll_colBase
        
        If ao_grid.Cols <= UBound(av_colDef(ll_RowIdx)) Then ao_grid.Cols = UBound(av_colDef(ll_RowIdx)) + 1

        For ll_ColIdx = LBound(av_colDef(ll_RowIdx)) To UBound(av_colDef(ll_RowIdx))
            ao_GRDInfo.Cols(ll_ColIdx + ll_colBase).Index = ll_ColIdx
            
            If IsArray(av_colDef(ll_RowIdx)(ll_ColIdx)) Then
                Debug.Assert (UBound(av_colDef(ll_RowIdx)(ll_ColIdx)) >= 1)        ' at least name and label must be specified
    
                ao_GRDInfo.Cols(ll_ColIdx + ll_colBase).Name = av_colDef(ll_RowIdx)(ll_ColIdx)(0)
                If TypeName(av_colDef(ll_RowIdx)(ll_ColIdx)(1)) = "String" Then
                    ao_grid.TextMatrix(ll_RowIdx, ll_ColIdx) = av_colDef(ll_RowIdx)(ll_ColIdx)(1)
                Else
                    ao_grid.TextMatrix(ll_RowIdx, ll_ColIdx) = av_colDef(ll_RowIdx)(ll_ColIdx)(av_colDef(ll_RowIdx)(ll_ColIdx)(1))(1)
                End If
                If UBound(av_colDef(ll_RowIdx)(ll_ColIdx)) >= 2 Then ao_grid.ColWidth(ll_ColIdx) = av_colDef(ll_RowIdx)(ll_ColIdx)(2)
                If UBound(av_colDef(ll_RowIdx)(ll_ColIdx)) >= 3 Then ao_GRDInfo.Cols(ll_ColIdx + ll_colBase).DB_Name = av_colDef(ll_RowIdx)(ll_ColIdx)(3)
                If UBound(av_colDef(ll_RowIdx)(ll_ColIdx)) >= 4 Then ao_grid.FixedAlignment(ll_ColIdx) = av_colDef(ll_RowIdx)(ll_ColIdx)(4)
                If UBound(av_colDef(ll_RowIdx)(ll_ColIdx)) >= 5 Then
                    ao_GRDInfo.Cols(ll_ColIdx + ll_colBase).Format = av_colDef(ll_RowIdx)(ll_ColIdx)(5)
                End If
            Else
                ' only label
                If TypeName(av_colDef(ll_RowIdx)(ll_ColIdx)) = "String" Then
                    ao_grid.TextMatrix(ll_RowIdx, ll_ColIdx) = av_colDef(ll_RowIdx)(ll_ColIdx)
                Else
                    If IsArray(av_colDef(ll_RowIdx)(av_colDef(ll_RowIdx)(ll_ColIdx))) Then
                        ao_grid.TextMatrix(ll_RowIdx, ll_ColIdx) = av_colDef(ll_RowIdx)(av_colDef(ll_RowIdx)(ll_ColIdx))(1)
                    Else
                        ao_grid.TextMatrix(ll_RowIdx, ll_ColIdx) = av_colDef(ll_RowIdx)(av_colDef(ll_RowIdx)(ll_ColIdx))
                    End If
                End If
                
            End If
            
        Next ll_ColIdx
        ll_colBase = ll_colBase + ll_ColIdx
        ao_grid.MergeRow(ll_RowIdx) = True
    Next ll_RowIdx
    
    Exit Sub
ErrorHandler:
    Call ErrorHandler(Extender.Name & ".GRD_SetColumns")
End Sub

Private Sub btn_refreshTreeview_Click()
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass

    If Not tv_main.LoadTree(tv_main.LoadType) Then
        Call Err.Raise(CompFncFailed, "tv_main.LoadTree")
    End If
        
    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
Screen.MousePointer = vbDefault
    Call ErrorMessage("btn_refreshTreeview_Click()")
End Sub

Private Sub tlb_Main_action(ByVal as_Role As String, as_Language As String)
On Error GoTo ErrHandler
    Screen.MousePointer = vbHourglass
    Dim lsa_id() As String
    Dim ls_bu As String
    Dim ls_buDesc As String
    Select Case as_Role
    Case "G"              ' EXPORT TO GRID
        If tv_main.NodeInfo(tv_main.SelectedItem).ml_Level >= tv_main.Levels - 2 Then
            lsa_id = Split(tv_main.SelectedItem.Tag.IDValue, "_")
            
            If UBound(lsa_id) <= 0 Then
                ls_bu = "B001"
                ls_buDesc = "All"
            Else
                ls_bu = lsa_id(1)
                ls_buDesc = tv_main.SelectedItem.Tag.TextValue
            End If
            
            Call ShowReport_Excell(lsa_id(0), ls_bu, ls_buDesc, False)
        End If
    Case "V"              ' EXPORT TO PDF
        If tv_main.NodeInfo(tv_main.SelectedItem).ml_Level >= tv_main.Levels - 2 Then
            lsa_id = Split(tv_main.SelectedItem.Tag.IDValue, "_")
            
            If UBound(lsa_id) <= 0 Then
                ls_bu = "B001"
                ls_buDesc = "All"
            Else
                ls_bu = lsa_id(1)
                ls_buDesc = tv_main.SelectedItem.Tag.TextValue
            End If
            
            Call ShowReport_Excell(lsa_id(0), ls_bu, ls_buDesc, True)
        End If
    Case "F"            ' refresh
        Call ShowGridFromNode(tv_main.NodeInfo(tv_main.SelectedItem))
    Case "T"              ' QUIT
      RaiseEvent quit
    End Select

    Screen.MousePointer = vbDefault
    Exit Sub
ErrHandler:
Screen.MousePointer = vbDefault
    Call ErrorMessage("tlb_main_Action()")
End Sub

Private Sub tv_main_NodeClick(ByVal Node As MSComctlLib.Node)
On Error GoTo ErrHandler
    If chk_autoGridLoad.Value = vbChecked Then
        Call ShowGridFromNode(tv_main.NodeInfo(Node))
'    Else
'        ' clean the grid
'        grd_main.Rows = 5
    End If
Exit Sub
ErrHandler:
    Call ErrorMessage("tv_main_NodeClick")
End Sub


' support only last two levels
Private Sub ShowGridFromNode(ByRef ao_nodeInfo As NodeInfo)
On Error GoTo ErrHandler
    If ao_nodeInfo Is Nothing Then Exit Sub
    
    If ao_nodeInfo.ml_Level >= tv_main.Levels - 2 Then
        Dim lsa_id() As String
        lsa_id = Split(ao_nodeInfo.IDValue, "_")
        Dim ls_bu As String
        Dim ls_buDesc As String
        
        If UBound(lsa_id) <= 0 Then
            ls_bu = "B001"
        Else
            ls_bu = lsa_id(1)
            ls_buDesc = ao_nodeInfo.TextValue
        End If
        Call ShowReport_Grid(lsa_id(0), ls_bu, ls_buDesc)
    Else
        ' clean the grid
        grd_main.Rows = 5
    End If
Exit Sub
ErrHandler:
    Call ErrorHandler("ShowGridFromNode")
End Sub
