// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
//	MovtosVtaProdCaractExcel.rpt
//	Nombre del reporte en el sistema: Movimientos de Venta por Producto y 
//                                    Características en Excel Detallado y
//                                    Resumen.  
//
//  Sistema: AdminPAQ v1.1
// 
//	Este reporte perteneciente al módulo de ventas,que despliega el los 
//  movimientos de venta de caracteristicas
//
//	Consideraciones especiales:
//  Este reporte aunque está programado como uno solo, representa en realidad
//  dos reportes en el ámbito del sistema:
//    Detallado
//    Resumen
//  
//	Elaboró:    César Iván López Aguilar
//	Fecha: 	    06 de Enero del 2003
//
//  Historia de revisiones:
//	06/01/2003  N.C. 286   CILA  Implementación Inicial del Reporte.
//  03/02/2003  N.D. 1745  RPC   Incluir variaciones en el orden de las 
//                               características
//  04/02/2003  RPC    N.D. 1770  El neto no debe incluir descuentos
// 29/04/2005   DRdA   N.D.3240   No saca los importes en la moneda del reporte. Se cambió el
//                                uso de la función fConvierteTipoCambio por el de la función
//                                fCambiarMonedaDoctoAReporte que está en LibAdminpaq.rpt
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// *****************************************************************************
// Funciones de librería
// *****************************************************************************
  Incluye LibAdminPAQ.Rpt

// *****************************************************************************
//	Parámetros del reporte:
// *****************************************************************************
  Parametro pFechaInicial      = '20050401'   // Fecha inicial del rango
  Parametro pFechaFinal        = '20050430'   // Fecha final del rango   
  Parametro pProductoInicial   = ' '          // Código del producto inicial del rango (' ' = Todos)
  Parametro pProductoFinal     = ' '          // Código del producto final del rango (' ' = Todos)
  Parametro pImprimirProductos = 0            // Productos a imprimir:
                                              // 0 = Todos
                                              // 1 = Solo productos con movimientos 
  Parametro pImprimirDetalles  = 0            // Detalles a imprimir:
                                              // 0 = Todos
                                              // 1 = Solo Detalles con movimientos 
  Parametro pEstadoProducto    = 0            // Incluir productos con estado:
                                              // 0 = Todos
                                              // 1 = Activos
                                              // 2 = Inactivos
  Parametro pTipoReporte       = 0            // Tipo de reporte
                                              // 0 = Detallado
                                              // 1 = Resumen
  Parametro pIdCaracteristica1 = 0            // Identificador del primer padre de características
  Parametro pIdValoresCarac1   = 0            // Lista de los identificadores de valores de la primera característica elegidos
  Parametro pIdCaracteristica2 = 0            // Identificador del segundo padre de características  
  Parametro pIdValoresCarac2   = 0            // Lista de los identificadores de valores de la segunda característica elegidos 
  Parametro pIdCaracteristica3 = 0            // Indentificador del tercer padre de características
  Parametro pIdValoresCarac3   = 0            // Lista de los identificadores de valores de la tercera característica elegidos'
  Parametro pIdClase1          = 0            // Clasificaciones del produto (0 = Ninguna)
  Parametro pIdClase2          = 0            // Estos seis parámetros corresponden a las seis clasificaciones
  Parametro pIdClase3          = 0            // del producto, y pueden contener una lista de IDs
  Parametro pIdClase4          = 0            // de clasificaciones separados por coma.
  Parametro pIdClase5          = 0
  Parametro pIdClase6          = 0
  Parametro pIdMoneda          = 1            // Id de la moneda a expresar el reporte
  Parametro pIdDocumentoDe     = 4            // Cosntante por el momento
            gListaIdDoctosDe   = '4,35'       // FBCS POS se genera una lista para agregar el 35 (nota de venta)

// *****************************************************************************
//	Tablas a utilizar e Indices de búsqueda por omisión
// *****************************************************************************
  UsaEmpresa tEmpresa;'ADMINPAQW'

  UsaTabla tParametros      = tEmpresa['MGW10000']                        // Parámetros
  tParametros.UsaIndice['']                                               // Indice Primario

  UsaTabla tAlmacen         = tEmpresa['MGW10003']                        // Almacen
  tAlmacen.UsaIndice['']                                                  // Indice Primario

  UsaTabla tDetalle         = tEmpresa['MGW10004']                        // Producto Identificador 
  tDetalle.UsaIndice['iProdPadreValoresCarac']                            // Indice: cIdProductoPadre+cIdValorCaracteristica1+cIdValorCaracteristica2+cIdValorCaracteristica3 

  UsaTabla tProducto        = tEmpresa['MGW10005']                        // Productos
  tProducto.UsaIndice['iCodigoTipo']                                      // Indice: cCodigoProducto+cTipoProducto

  UsaTabla tPaqComponente   = tEmpresa['MGW10005'] Alias 'PaqComponente'  // Productos - Solo Paquetes
  tPaqComponente.UsaIndice['']                                            // Indice Primario 

  UsaTabla tConcepto        = tEmpresa['MGW10006']                        // Conceptos
  tConcepto.UsaIndice['']                                                 // Indice Primario

  UsaTabla tDocumento       = tEmpresa['MGW10008']                        // Documentos
  tDocumento.UsaIndice['']                                                // Indice Primario

  UsaTabla tMovimiento      = tEmpresa['MGW10010'] Alias 'Movto'          // Movimientos 
  tMovimiento.UsaIndice['iProductoDoctoDeAfecFecha']                      // Indice: cIdProducto+cIdDoctoDe+cAfectadoInventarios+cFecha

  UsaTabla tMovtoOwner      = tEmpresa['MGW10010'] Alias 'MovtoOwner'     // Movimientos - Para MovtoOwner 
  tMovtoOwner.UsaIndice['']                                               // Indice Primario

  UsaTabla tMovtoPaquete    = tEmpresa['MGW10010'] Alias 'MovtoOwnerPaq'  // Movimientos - Para Movtos de Paquete
  tMovtoPaquete.UsaIndice['cIdMovtoOwner']                                // Inidice: cIdMovtoOwner

  UsaTabla tValoresDeClasif = tEmpresa['MGW10020']                        // Valores Clasificaciones
  tValoresDeClasif.UsaIndice['']                                          // Indice Primario

  UsaTabla tCaracteristicas = tEmpresa['MGW10021']                        // Caracteristicas
  tCaracteristicas.UsaIndice['']                                          // Indice Primario

  UsaTabla tValorCarac      = tEmpresa['MGW10022']                        // Valores Caracteristicas
  tValorCarac.UsaIndice['']                                               // Indice Primario

  UsaTabla tMoneda          = tEmpresa['MGW10034']                        // Monedas
  tMoneda.UsaIndice['']                                                   // Indice Primario

  UsaTabla tTipoCambio      = tEmpresa['MGW10035']                        // Tipo de Cambio
  tTipoCambio.UsaIndice['iMonedaFecha']                                   // Indice: cIdMoneda+cFecha

  UsaTabla tClientes = tEmpresa['mgw10002']
  tClientes.Usaindice['']

// *****************************************************************************
// Definiciones y asumidos globales para el reporte
// *****************************************************************************
  Columnas 18;1

  Usaletra 'Arial'
  Altura 9
  [C7..C12].Coma
  [C2,C4].Decimales 0
  [C2,C4].Blanco ''

// *****************************************************************************
// Variables de ámbito global:
// *****************************************************************************
  gRenglonesHoja   = 0
  gTotalDetalle    = 0
  gTotalProducto   = 0
  gTotal           = 0
  gProductoImpreso = False
  gValorCarac1     = 0
  gValorCarac2     = 0
  gValorCarac3     = 0
  gIdioma          = 0   // Idioma del reporte
                         // 0 = Español
                         // 1 = Inglés
  gNumDeClases     = 0 
  gClasesRecibidas = ''
  gDetalleImpreso  = False

// *****************************************************************************
// Definicion de constantes de Reporte
// *****************************************************************************
  // Constantes para el parametro pTipoRerporte
  Constante kReporteDetallado 0
  Constante kReporteResumen   1
  // Constantes para los parametros pImprimirProductos y pImprimirDetalles
  Constante kTodos            0
  Constante kSoloConMovtos    1

// *****************************************************************************
// Definicion de constantes de EXCEL
// *****************************************************************************
  Constante xlLineaSimple         1
  Constante xlBordeSuperior       8
  Constante xlBordeInferior       9
  Constante xlBordeIzquierda      7
  Constante xlCentrarEnSeleccion  7
  Constante xlBordeDerecha        10
  Constante xlAutomatico          -4105
  Constante xlInferior            -4107
  Constante xlCentro              -4108
  Constante xlSubrayadoDoble      -4119
  Constante xlIzquierda           -4131
  Constante xlManual              -4135
  Constante xlMediano             -4138
  Constante xlNinguno             -4142
  Constante xlNormal              -4143
  Constante xlDerecha             -4152
  Constante xlSuperior            -4160
  Constante xlHojaCalculo         -4167  

// *****************************************************************************
// Definicion de constantes para la columnas
// *****************************************************************************
  // Constantes para el Reporte Detallado
  Constante kColBlanco      'A'
  Constante kColFecha       'B'
  Constante kColConcepto    'C'
  Constante kColSerie       'D'
  Constante kColFolio       'E'
  Constante kColAlmacen     'F'
  Constante kColCantidad    'G'
  Constante kColPrecio      'H'
  Constante kColNeto        'I'
  Constante kColDescuentos  'J'
  Constante kColImpuestos   'K'
  Constante kColTotal       'L'
  // Constantes para el Reporte Resumen
  Constante kColBlancoR     'A'
  Constante kColProductoR   'B'
  Constante kColCantidadR   'C'
  Constante kColNetoR       'D'
  Constante kColDescuentosR 'E'
  Constante kColImpuestosR  'F'
  Constante kColTotalR      'G'

  // Por número de columna -----------------------------------------------------
  // Constantes para el Reporte Detallado
  Constante kNumColCero        0
  Constante kNumColBlanco      1
  Constante kNumColFecha       2
  Constante kNumColConcepto    3
  Constante kNumColSerie       4
  Constante kNumColFolio       5
  Constante kNumColAlmacen     6
  Constante kNumColCantidad    7
  Constante kNumColPrecio      8
  Constante kNumColNeto        9
  Constante kNumColDescuentos 10
  Constante kNumColImpuestos  11
  Constante kNumColTotal      12
  // Constantes para el Reporte Resumen
  Constante kNumColBlancoR     1
  Constante kNumColProductoR   2  
  Constante kNumColCantidadR   3  
  Constante kNumColNetoR       4
  Constante kNumColDescuentosR 5
  Constante kNumColImpuestosR  6
  Constante kNumColTotalR      7


// *****************************************************************************
// Inicializa EXCEL
// *****************************************************************************
  /* Accesa objetos de Excel. Crea un objeto de Excel con la funcion @CreaObjeto(). 
     A esta funcion se le pasa un identificador de OLE de la aplicacion que se 
     desea crear. En este caso el identificador es Excel.Application.5 */
  Objeto Excel = @CreaObjeto('Excel.Application')

  /* Invoca el metodo de EXCEL Libros y luego el metodo Agregar para crear un 
     libro de hoja de calculo representado por la constante de EXCEL (xlHojaCalculo).
     Es importante notar que estos metodos NO LOS EJECUTA EL REPORTEADOR sino 
     que los hace EXCEL y estan documentados en el Help de EXCEL. */
  Objeto wb = Excel.WorkBooks.Add(xlHojaCalculo)

  /* Accesa la hoja de calculo (HojasCalculo) numero 1 del Libro creado anterior-
     mente y representado por la variable wb, de la instruccion anterior. */
  Objeto ws = wb.Worksheets(1)

  // Hace visible a EXCEL. Para Excel, TRUE o VERDADERO es -1, FALSE o FALSO es 0
  Excel.ActiveWindow.DisplayGridlines = FALSE[C0]
  Excel.Visible = -1[C0]

  // Ajusta el tamaño de la hoja activa ----------------------------------------
  Excel.ActiveWindow.WindowState = xlNormal[C0]
  Excel.ActiveWindow.Top    = 1[C0]
  Excel.ActiveWindow.Left   = 1[C0]
  Excel.ActiveWindow.Height = Excel.Application.UsableHeight[C0]
  Excel.ActiveWindow.Width  = Excel.Application.UsableWidth[C0]

  // Inicializa el renglon activo en la hoja de EXCEL --------------------------
  RenActual = 1

// *****************************************************************************
// Pone la longitud de cada columna
// *****************************************************************************
  Si pTipoReporte = kReporteDetallado // ---------------------------------------
    ws.Columns(kNumColBlanco).ColumnWidth     =  1[C0] // Espacio en blanco
    ws.Columns(kNumColFecha).ColumnWidth      = 12[C0] // Fecha
    ws.Columns(kNumColConcepto).ColumnWidth   = 25[C0] // Concepto
    ws.Columns(kNumColSerie).ColumnWidth      =  8[C0] // Serie
    ws.Columns(kNumColFolio).ColumnWidth      = 15[C0] // Folio
    ws.Columns(kNumColAlmacen).ColumnWidth    = 12[C0] // Almacén
    ws.Columns(kNumColCantidad).ColumnWidth   = 15[C0] // Cantidad
    ws.Columns(kNumColPrecio).ColumnWidth     = 15[C0] // Precio
    ws.Columns(kNumColNeto).ColumnWidth       = 15[C0] // Neto
    ws.Columns(kNumColDescuentos).ColumnWidth = 15[C0] // Descuentos
    ws.Columns(kNumColImpuestos).ColumnWidth  = 15[C0] // Impuestos
    ws.Columns(kNumColTotal).ColumnWidth      = 15[C0] // Total
  SiNo // Reporte Resumen
    ws.Columns(kNumColBlancoR).ColumnWidth     =  1[C0] // Espacio en blanco
    ws.Columns(kNumColProductoR).ColumnWidth   = 25[C0] // Producto
    ws.Columns(kNumColCantidadR).ColumnWidth   = 18[C0] // Cantidad    
    ws.Columns(kNumColNetoR).ColumnWidth       = 18[C0] // Neto
    ws.Columns(kNumColDescuentosR).ColumnWidth = 18[C0] // Descuentos
    ws.Columns(kNumColImpuestosR).ColumnWidth  = 18[C0] // Impuestos
    ws.Columns(kNumColTotalR).ColumnWidth      = 18[C0] // Total
  FinSi

// *****************************************************************************
// FUNCIONES DEL REPORTE
// *****************************************************************************

// *****************************************************************************
//  fConfiguraDecimales
//
//  Configura el número de decimales de las columnas de importes, basado en
//  en los parámetros de la empresa.
//
//  Entradas: 
//
//  Salidas :
//
// Historia de modificaciones
// ****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// ----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// ****************************************************************************
DefFunc fConfiguraDecimales()
  LOCAL lDigDecimales, lDecs, lFormato

  lDigsDecimales = '0000000000'

  // Busca el registro de la empresa
  tParametros.Busca Primero
  Si tParametros->Encontro // Si lo encontró

    // Configura decimales para los campos de unidades ----------------------
    lDecs = @SubStr( lDigsDecimales; 1; tParametros(cDecimalesUnidades) )
    lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
    Si pTipoReporte = kReporteDetallado // -------------------------------------
      ws.Columns(kNumColCantidad).NumberFormat = lFormato[C0]   // Columna de Cantidad
    SiNo // Reporte Resumen ----------------------------------------------------
      ws.Columns(kNumColCantidadR).NumberFormat = lFormato[C0]   // Columna de Cantidad
    FinSi

    // Configura decimales para los campos de importes ----------------------
    lDecs = @SubStr(lDigsDecimales;1;tParametros(cDecimalesCostos))
    lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
    Si pTipoReporte = kReporteDetallado // -------------------------------------
      ws.Columns(kNumColPrecio).NumberFormat     = lFormato[C0]  // Columna de Precio
      ws.Columns(kNumColNeto).NumberFormat       = lFormato[C0]  // Columna de Neto
      ws.Columns(kNumColDescuentos).NumberFormat = lFormato[C0]  // Columna de Descuentos
      ws.Columns(kNumColImpuestos).NumberFormat  = lFormato[C0]  // Columna de Impuestos
      ws.Columns(kNumColTotal).NumberFormat      = lFormato[C0]  // Columna de Total
    SiNo // Reporte Resumen ----------------------------------------------------
      ws.Columns(kNumColNetoR).NumberFormat       = lFormato[C0]  // Columna de Neto
      ws.Columns(kNumColDescuentosR).NumberFormat = lFormato[C0]  // Columna de Descuentos
      ws.Columns(kNumColImpuestosR).NumberFormat  = lFormato[C0]  // Columna de Impuestos
      ws.Columns(kNumColTotalR).NumberFormat      = lFormato[C0]  // Columna de Total
    FinSi

    gMascarillaProducto = tParametros(cMascarillaProducto)  // mascarilla para el código del producto
  Sino // Si no encontró el registro de la empresa
    Si pTipoReporte = kReporteDetallado // -------------------------------------
      [C8..C12].Decimales 2
      ws.Columns(kNumColCantidad).NumberFormat   = '#,##0.00_);(#,##0.00)'[C0] // Columna de Cantidad
      ws.Columns(kNumColPrecio).NumberFormat     = '#,##0.00_);(#,##0.00)'[C0] // Columna de Precio
      ws.Columns(kNumColNeto).NumberFormat       = '#,##0.00_);(#,##0.00)'[C0] // Columna de Neto
      ws.Columns(kNumColDescuentos).NumberFormat = '#,##0.00_);(#,##0.00)'[C0] // Columna de Descuentos
      ws.Columns(kNumColImpuestos).NumberFormat  = '#,##0.00_);(#,##0.00)'[C0] // Columna de Impuestos
      ws.Columns(kNumColTotal).NumberFormat      = '#,##0.00_);(#,##0.00)'[C0] // Columna de Total
    SiNo
      [C2..C6].Decimales 2
      ws.Columns(kNumColCantidadR).NumberFormat   = '#,##0.00_);(#,##0.00)'[C0] // Columna de Cantidad
      ws.Columns(kNumColNetoR).NumberFormat       = '#,##0.00_);(#,##0.00)'[C0] // Columna de Neto
      ws.Columns(kNumColDescuentosR).NumberFormat = '#,##0.00_);(#,##0.00)'[C0] // Columna de Descuentos
      ws.Columns(kNumColImpuestosR).NumberFormat  = '#,##0.00_);(#,##0.00)'[C0] // Columna de Impuestos
      ws.Columns(kNumColTotalR).NumberFormat      = '#,##0.00_);(#,##0.00)'[C0] // Columna de Total
    FinSi
  FinSi
FinFunc

// *****************************************************************************
// Función fImprimeDatosProducto()
// Descripción: Imprime los datos del producto
// 
// Entradas: atProdcuto: Instancia de la tabla de productos
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeDatosProducto( atProducto: Tabla )

  // Imcrementa el contador de renglones de la hoja de Excel -------------------
  RenActual = RenActual + 1

  ws.Range( kColFecha & RenActual ).Font.FontStyle = 'Negrita'[C0]  

  Si pTipoReporte = kReporteResumen // -----------------------------------------
    ws.Range( kColProductoR  & RenActual & ':' & kColTotalR & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColFecha & RenActual ).Value = atProducto(cNombreProducto)
  SiNo
    ws.Range( kColFecha & RenActual ).Value = 'Producto: ' & atProducto(cNombreProducto)
  FinSi

  // Imcrementa el contador de renglones de la hoja de Excel -------------------
  RenActual = RenActual + 1

FinFunc


// *****************************************************************************
// Función fImprimeDatosValoresCaract()
// Descripción: Imprime los datos de los valores de caracteristica
// 
// Entradas: 
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeDatosValoresCaract( )
  Local lCaracteristicas

  // Inicializa variables locales
  lCaracteristicas = ''

  // Busca y arma la cadenda con la caracteristica 1
  Si gValorCarac1 != 0
    tValorCarac.Busca[ @Str(gValorCarac1; 0) ]
    Si tValorCarac->Encontro
      lCaracteristicas[0] = lCaracteristicas & tValorCarac( cValorCaracteristica )
    SiNo
      lCaracteristicas[0] = lCaracteristicas & 'Caracteritica 1'
    FinSi      
  FinSi

  // Busca y arma la cadenda con la caracteristica 2
  Si gValorCarac2 != 0
    lCaracteristicas[0] = lCaracteristicas & '-'

    tValorCarac.Busca[ @Str(gValorCarac2; 0) ]
    Si tValorCarac->Encontro
      lCaracteristicas[0] = lCaracteristicas & tValorCarac( cValorCaracteristica )
    SiNo
      lCaracteristicas[0] = lCaracteristicas & 'Caracteritica 2'
    FinSi      
  FinSi

  // Busca y arma la cadenda con la caracteristica 3
  Si gValorCarac3 != 0
    lCaracteristicas[0] = lCaracteristicas & '-'

    tValorCarac.Busca[ @Str(gValorCarac3; 0) ]
    Si tValorCarac->Encontro      
      lCaracteristicas[0] = lCaracteristicas & tValorCarac( cValorCaracteristica )
    SiNo
      lCaracteristicas[0] = lCaracteristicas & 'Caracteritica 3'
    FinSi
  FinSi

  Si pTipoReporte = kReporteDetallado // ---------------------------------------
    ws.Range( kColFecha & RenActual ).Font.FontStyle = 'Negrita'[C0]
    ws.Range( kColFecha & RenActual & ':' & kColTotal  & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]

    // Imprime las caracteristicas
    ws.Range( kColFecha & RenActual ).Value = @Col(lCaracteristicas;0)[C0]
  
    // Imcrementa el contador de renglones de la hoja de Excel -----------------
    RenActual = RenActual + 1
  SiNo  // Reporte Detalle -----------------------------------------------------
    gTotalDetalle[kNumColProductoR] = @Col(lCaracteristicas;0)
  FinSi

FinFunc

// *****************************************************************************
// Función fImprimeTotalesCarac()
// Descripción: Imprime los totales de una combinación de valores de 
//              característica.
// 
// Entradas: 
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeTotalesCarac()

  Si gDetalleImpreso = false
    Retorna
  FinSi

  // Define los bordes de las columnas de los subtotales
  ws.Range( kColCantidad & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range( kColCantidad & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
  ws.Range( kColCantidad & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]

  ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
  ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColFecha & RenActual & ':' & kColTotal & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColFecha & RenActual & ':' & kColTotal & RenActual ).Font.FontStyle = 'Negrita'[C0]

  // Imprimir totales de gValorCarac1-gValorCarac2-gValorCarac3 
  ws.Range( kColAlmacen    & RenActual ).HorizontalAlignment = xlDerecha[C0]
  ws.Range( kColAlmacen    & RenActual ).Value = 'Total:  '[C0]
  ws.Range( kColCantidad   & RenActual ).Value = @Col(gTotalDetalle; kNumColCantidad)[C0]
  ws.Range( kColPrecio     & RenActual ).Value = ''
  ws.Range( kColNeto       & RenActual ).Value = @Col(gTotalDetalle; kNumColNeto)[C0]
  ws.Range( kColDescuentos & RenActual ).Value = @Col(gTotalDetalle; kNumColDescuentos)[C0]
  ws.Range( kColImpuestos  & RenActual ).Value = @Col(gTotalDetalle; kNumColImpuestos)[C0]
  ws.Range( kColTotal      & RenActual ).Value = @Col(gTotalDetalle; kNumColTotal)[C0] 

  // Imcrementa el contador de renglones de la hoja de Excel -------------------
  RenActual = RenActual + 1
  
  // Actualiza el total por producto  
  gTotalProducto[kNumColCantidad]   = @Col(gTotalProducto;kNumColCantidad)   + @Col(gTotalDetalle;kNumColCantidad)
  gTotalProducto[kNumColPrecio]     = ''
  gTotalProducto[kNumColNeto]       = @Col(gTotalProducto;kNumColNeto)       + @Col(gTotalDetalle;kNumColNeto)
  gTotalProducto[kNumColDescuentos] = @Col(gTotalProducto;kNumColDescuentos) + @Col(gTotalDetalle;kNumColDescuentos)
  gTotalProducto[kNumColImpuestos]  = @Col(gTotalProducto;kNumColImpuestos)  + @Col(gTotalDetalle;kNumColImpuestos)
  gTotalProducto[kNumColTotal]      = @Col(gTotalProducto;kNumColTotal)      + @Col(gTotalDetalle;kNumColTotal)

  // Inicializa el total del detalle por caracteristica
  gTotalDetalle = 0

FinFunc

// *****************************************************************************
// Función fImprimeTotalesCaracRes()
// Descripción: Imprime los totales de una combinación de valores de 
//              característica.
// 
// Entradas: 
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 07/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeTotalesCaracRes()
  
  Si gDetalleImpreso = false 
    Retorna
  FinSi

  // Define los bordes de las columnas de los subtotales
  ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
  
  // Imprimir totales de gValorCarac1-gValorCarac2-gValorCarac3 
  ws.Range( kColProductoR   & RenActual ).Value = @Col(gTotalDetalle; kNumColProductoR)[C0]
  ws.Range( kColCantidadR   & RenActual ).Value = @Col(gTotalDetalle; kNumColCantidadR)[C0]  
  ws.Range( kColNetoR       & RenActual ).Value = @Col(gTotalDetalle; kNumColNetoR)[C0]
  ws.Range( kColDescuentosR & RenActual ).Value = @Col(gTotalDetalle; kNumColDescuentosR)[C0]
  ws.Range( kColImpuestosR  & RenActual ).Value = @Col(gTotalDetalle; kNumColImpuestosR)[C0]
  ws.Range( kColTotalR      & RenActual ).Value = @Col(gTotalDetalle; kNumColTotalR)[C0] 

  // Imcrementa el contador de renglones de la hoja de Excel -------------------
  RenActual = RenActual + 1
  
  // Actualiza el total por producto  
  gTotalProducto[kNumColCantidadR]   = @Col(gTotalProducto;kNumColCantidadR)   + @Col(gTotalDetalle;kNumColCantidadR)
  gTotalProducto[kNumColNetoR]       = @Col(gTotalProducto;kNumColNetoR)       + @Col(gTotalDetalle;kNumColNetoR)
  gTotalProducto[kNumColDescuentosR] = @Col(gTotalProducto;kNumColDescuentosR) + @Col(gTotalDetalle;kNumColDescuentosR)
  gTotalProducto[kNumColImpuestosR]  = @Col(gTotalProducto;kNumColImpuestosR)  + @Col(gTotalDetalle;kNumColImpuestosR)
  gTotalProducto[kNumColTotalR]      = @Col(gTotalProducto;kNumColTotalR)      + @Col(gTotalDetalle;kNumColTotalR)

  // Inicializa el total del detalle por caracteristica
  gTotalDetalle = 0

FinFunc

// *****************************************************************************
// Función fImprimeTotalesProducto()
// Descripción: Imprime un renglón del reporte con los totales de un producto.
// 
// Entradas: 
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeTotalesProducto()

  Si gProductoImpreso = True

    // Define los bordes de las columnas de los subtotales
    ws.Range( kColCantidad & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range( kColCantidad & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
    ws.Range( kColCantidad & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColCantidad & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]

    ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
    ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColNeto  & RenActual & ':' & kColTotal & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColFecha & RenActual & ':' & kColTotal & RenActual ).Font.FontStyle = 'Negrita'[C0]

    // Imprimir totales de producto 
    ws.Range( kColAlmacen    & RenActual ).HorizontalAlignment = xlDerecha[C0]
    ws.Range( kColAlmacen    & RenActual ).Value = 'Total Producto:  '[C0]
    ws.Range( kColCantidad   & RenActual ).Value = @Col(gTotalProducto; kNumColCantidad)[C0]
    ws.Range( kColPrecio     & RenActual ).Value = @Col(gTotalProducto; kNumColPrecio)[C0]
    ws.Range( kColNeto       & RenActual ).Value = @Col(gTotalProducto; kNumColNeto)[C0]
    ws.Range( kColDescuentos & RenActual ).Value = @Col(gTotalProducto; kNumColDescuentos)[C0]
    ws.Range( kColImpuestos  & RenActual ).Value = @Col(gTotalProducto; kNumColImpuestos)[C0]
    ws.Range( kColTotal      & RenActual ).Value = @Col(gTotalProducto; kNumColTotal)[C0] 

    // Imcrementa el contador de renglones de la hoja de Excel -----------------
    RenActual = RenActual + 1
  
    // Actualiza el total general
    gTotal[kNumColCantidad]   = @Col(gTotal;kNumColCantidad)   + @Col(gTotalProducto;kNumColCantidad)
    gTotal[kNumColPrecio]     = ''
    gTotal[kNumColNeto]       = @Col(gTotal;kNumColNeto)       + @Col(gTotalProducto;kNumColNeto)
    gTotal[kNumColDescuentos] = @Col(gTotal;kNumColDescuentos) + @Col(gTotalProducto;kNumColDescuentos)
    gTotal[kNumColImpuestos]  = @Col(gTotal;kNumColImpuestos)  + @Col(gTotalProducto;kNumColImpuestos)
    gTotal[kNumColTotal]      = @Col(gTotal;kNumColTotal)      + @Col(gTotalProducto;kNumColTotal)
  
    // Inicializa el total del detalle por producto
    gTotalProducto = 0 

  FinSi

FinFunc


// *****************************************************************************
// Función fImprimeTotalesProductoRes()
// Descripción: Imprime un renglón del reporte con los totales de un producto.
// 
// Entradas: 
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 07/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeTotalesProductoRes()

  Si gProductoImpreso = True

    // Define los bordes de las columnas de los subtotales
    ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
    ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle = 'Negrita'[C0]

    // Imprimir totales de producto 
    ws.Range( kColProductoR   & RenActual ).HorizontalAlignment = xlDerecha[C0]
    ws.Range( kColProductoR   & RenActual ).Value = 'Total Producto:  '[C0]
    ws.Range( kColCantidadR   & RenActual ).Value = @Col(gTotalProducto; kNumColCantidadR)[C0]
    ws.Range( kColNetoR       & RenActual ).Value = @Col(gTotalProducto; kNumColNetoR)[C0]
    ws.Range( kColDescuentosR & RenActual ).Value = @Col(gTotalProducto; kNumColDescuentosR)[C0]
    ws.Range( kColImpuestosR  & RenActual ).Value = @Col(gTotalProducto; kNumColImpuestosR)[C0]
    ws.Range( kColTotalR      & RenActual ).Value = @Col(gTotalProducto; kNumColTotalR)[C0] 

    // Imcrementa el contador de renglones de la hoja de Excel -----------------
    RenActual = RenActual + 1
  
    // Actualiza el total general
    gTotal[kNumColCantidadR]   = @Col(gTotal;kNumColCantidadR)   + @Col(gTotalProducto;kNumColCantidadR)
    gTotal[kNumColNetoR]       = @Col(gTotal;kNumColNetoR)       + @Col(gTotalProducto;kNumColNetoR)
    gTotal[kNumColDescuentosR] = @Col(gTotal;kNumColDescuentosR) + @Col(gTotalProducto;kNumColDescuentosR)
    gTotal[kNumColImpuestosR]  = @Col(gTotal;kNumColImpuestosR)  + @Col(gTotalProducto;kNumColImpuestosR)
    gTotal[kNumColTotalR]      = @Col(gTotal;kNumColTotalR)      + @Col(gTotalProducto;kNumColTotalR)
  
    // Inicializa el total del detalle por producto
    gTotalProducto = 0 

  FinSi

FinFunc


// ****************************************************************************
// Función fImprimeTotales()
//
// Descripción: Imprime los totales del reporte
// 
// Entradas:
//
// Salidas :
//
// Historia de modificaciones
// ****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// ----------------------------------------------------------------------------
// 06/01/2002  CILA    N.C. 286        Implementación Inicial
// ****************************************************************************
DefFunc fImprimeTotales()

  // Imcrementa el contador de renglones de la hoja de Excel --------------
  RenActual = RenActual + 1

  // Rango de la Columna 'A' a la 'M'
  ws.Range( kColCantidad & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range( kColCantidad & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
  ws.Range( kColCantidad & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColCantidad & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]

  ws.Range( kColNeto     & RenActual & ':' & kColTotal & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range( kColNeto     & RenActual & ':' & kColTotal & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
  ws.Range( kColNeto     & RenActual & ':' & kColTotal & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColNeto     & RenActual & ':' & kColTotal & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColAlmacen  & RenActual & ':' & kColTotal & RenActual ).Font.FontStyle = 'Negrita'[C0]

  // Imprime el total general del reporte ----------------------------------------
  ws.Range( kColAlmacen    & RenActual ).HorizontalAlignment = xlDerecha[C0]
  ws.Range( kColAlmacen    & RenActual ).Value = 'Total General:  '[C0]
  ws.Range( kColCantidad   & RenActual ).Value = @Col(gTotal; kNumColCantidad)[C0]
  ws.Range( kColPrecio     & RenActual ).Value = @Col(gTotal; kNumColPrecio)[C0]
  ws.Range( kColNeto       & RenActual ).Value = @Col(gTotal; kNumColNeto)[C0]
  ws.Range( kColDescuentos & RenActual ).Value = @Col(gTotal; kNumColDescuentos)[C0]
  ws.Range( kColImpuestos  & RenActual ).Value = @Col(gTotal; kNumColImpuestos)[C0]
  ws.Range( kColTotal      & RenActual ).Value = @Col(gTotal; kNumColTotal)[C0] 

FinFunc


// ****************************************************************************
// Función fImprimeTotalesRes()
//
// Descripción: Imprime los totales del reporte
// 
// Entradas:
//
// Salidas :
//
// Historia de modificaciones
// ****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// ----------------------------------------------------------------------------
// 06/01/2002  CILA    N.C. 286        Implementación Inicial
// ****************************************************************************
DefFunc fImprimeTotalesRes()

  // Imcrementa el contador de renglones de la hoja de Excel --------------
  RenActual = RenActual + 1

  // Rango de la Columna 'A' a la 'M'
  ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
  ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle = 'Negrita'[C0]

  // Imprime el total general del reporte ----------------------------------------
  ws.Range( kColProductoR   & RenActual ).HorizontalAlignment = xlDerecha[C0]
  ws.Range( kColProductoR   & RenActual ).Value = 'Total General:  '[C0]
  ws.Range( kColCantidadR   & RenActual ).Value = @Col(gTotal; kNumColCantidadR)[C0]
  ws.Range( kColNetoR       & RenActual ).Value = @Col(gTotal; kNumColNetoR)[C0]
  ws.Range( kColDescuentosR & RenActual ).Value = @Col(gTotal; kNumColDescuentosR)[C0]
  ws.Range( kColImpuestosR  & RenActual ).Value = @Col(gTotal; kNumColImpuestosR)[C0]
  ws.Range( kColTotalR      & RenActual ).Value = @Col(gTotal; kNumColTotalR)[C0] 

FinFunc


// *****************************************************************************
// Función fImprimeMovimientos()
// Descripción: Recorre e imprime los movimientos de un detalle de 
//              característica.
// 
// Entradas: - atDetalle = Tabla de producto identificador
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// 04/02/2003  RPC     N.D. 1770       El neto no debe incluir descuentos
// *****************************************************************************
DefFunc fImprimeMovimientos( atDetalle: Tabla ) 

  // Declara variables locales
  Local lFecha, lFechaEditada
  Local lNeto, lPrecio, lDescuentos, lImpuestos, lTotal, lPosicion
  Local lIdMonedaCte

  // Inicializa variables ------------------------------------------------------
  lFecha                 = pFechaInicial
  lNeto                  = 0 
  lPrecio                = 0
  lDescuentos            = 0
  lImpuestos             = 0 
  lTotal                 = 0

  // Si se imprimen todos los detalles y aun no se a impreso los valores de las
  // caracteristicas y si se imprimen todos los productos se imprime los valores
  // de las caracteristicas.
  Si pImprimirDetalles = kTodos Y gDetalleImpreso = False Y pImprimirProductos = kTodos
    //Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
    fImprimeDatosValoresCaract()

    gDetalleImpreso = True
  FinSi

  // Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
  // Buscar Movimientos en el rango de días
  Mientras lFecha <= pFechaFinal

    lPosicion = 0
    pIdDocumentoDe = @Escoge(gListaIdDoctosDe;lPosicion)
    Mientras pIdDocumentoDe != '' // FBCS POS, el se utiliza la lista gListaIdDoctosDe

      // Buscar los movimientos ocultos del detalle en el día     // FBCS POS
      Mientras[ tMovimiento.Busca[ @Str(atDetalle(cIdProducto);0) & ':' & pIdDocumentoDe & ':' & '1' & ':' & lFecha ]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4] ]

        // Sólo se incluyen productos con movtos y no se ha impreso el producto actual
        Si pImprimirProductos = kSoloConMovtos Y gProductoImpreso = False
          // Imprime nombre del producto
          fImprimeDatosProducto( tProducto )

          gProductoImpreso = True        
        FinSi

        // Se imprimen todos los detalles cuando se impriman solo los productos
        // con movimientos.
        Si pImprimirDetalles = kTodos Y gDetalleImpreso = False Y pImprimirProductos = kSoloConMovtos
          //Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
          fImprimeDatosValoresCaract()

          gDetalleImpreso = True
        FinSi

        // Se imprimen los detalles con solo movimientos
        Si pImprimirDetalles = kSoloConMovtos Y gDetalleImpreso = False
          //Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
          fImprimeDatosValoresCaract()

          gDetalleImpreso = True
        FinSi

        // Imprime 
        // Obtiene los valores de Neto, Precio, Impuestos, Descuentos y Total del movimiento
        lNeto = fNetoMovtoPaquete( tMovimiento; tMovtoOwner; tMovtoPaquete; tProducto; tPaqComponente; &lPrecio; &lDescuentos; &lImpuestos; &lTotal )
        // RPC - ND 1770 La función fNetoMovtoPaquete() regresa el neto con impuestos y lo queremos sin ellos
        lNeto = lNeto + lDescuentos
 
        lIdMonedaCte = 1
        // Busca el movimiento padre para obtener datos
        tMovtoOwner.Busca[ @Str(tMovimiento(cIdMovtoOwner);0) ]
        Si tMovtoOwner->Encontro

          // Busca el documento a partir del movimiento
          tDocumento.Busca[ @Str(tMovtoOwner(cIdDocumento);0) ]
          Si tDocumento->Encontro

            // Busca el concepto del documento
            tConcepto.Busca[ @Str(tDocumento(cIdConceptoDocumento);0) ]
          
            tClientes.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
            Si tClientes->Encontro
              lIdMonedaCte = tClientes(cIdMoneda)
            FinSi
          
          FinSi

          // Busca el almacen del movimiento
          tAlmacen.Busca[ @Str(tMovtoOwner(cIdAlmacen);0) ]

        FinSi

        // Convertir lPrecio, lNeto, lDescuentos, lImpuestos y lTotal a la moneda pIdMoneda
        lPrecio = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lPrecio; pIdMoneda; lIdMonedaCte)
        lNeto = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lNeto; pIdMoneda; lIdMonedaCte)
        lDescuentos = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lDescuentos; pIdMoneda; lIdMonedaCte)
        lImpuestos = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lImpuestos; pIdMoneda; lIdMonedaCte)
        lTotal = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lTotal; pIdMoneda; lIdMonedaCte)
      
        // Imprime el movimiento del producto      
        ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
        ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]

        lFechaEditada = fFormateaFecha( tMovimiento(cFecha); gIdioma )

        ws.Range( kColFecha      & RenActual ).Value = @Chr(39) & lFechaEditada[C0]
        ws.Range( kColConcepto   & RenActual ).Value = tConcepto(cNombreConcepto)[C0]
        ws.Range( kColSerie      & RenActual ).Value = tDocumento(cSerieDocumento)[C0]
        ws.Range( kColFolio      & RenActual ).Value = tDocumento(cFolio)[C0]
        ws.Range( kColAlmacen    & RenActual ).Value = tAlmacen(cNombreAlmacen)[C0]
        ws.Range( kColCantidad   & RenActual ).Value = tMovimiento(cUnidades)[C0]
        ws.Range( kColPrecio     & RenActual ).Value = lPrecio[C0]
        ws.Range( kColNeto       & RenActual ).Value = lNeto[C0]
        ws.Range( kColDescuentos & RenActual ).Value = lDescuentos[C0]
        ws.Range( kColImpuestos  & RenActual ).Value = lImpuestos[C0]
        ws.Range( kColTotal      & RenActual ).Value = lTotal[C0]

        RenActual = RenActual + 1

        // Actualiza el total del detalle ----------------------------------------
        gTotalDetalle[kNumColCantidad]   = @Col( gTotalDetalle; kNumColCantidad )   + tMovimiento(cUnidades)
        gTotalDetalle[kNumColPrecio]     = ''
        gTotalDetalle[kNumColNeto]       = @Col( gTotalDetalle; kNumColNeto )       + @Col( lNeto; kNumColCero )
        gTotalDetalle[kNumColDescuentos] = @Col( gTotalDetalle; kNumColDescuentos ) + @Col( lDescuentos; kNumColCero )
        gTotalDetalle[kNumColImpuestos]  = @Col( gTotalDetalle; kNumColImpuestos )  + @Col( lImpuestos; kNumColCero )
        gTotalDetalle[kNumColTotal]      = @Col( gTotalDetalle; kNumColTotal )      + @Col( lTotal; kNumColCero )

      FinMientras  // Hay movimientos del día

      lPosicion = lPosicion +1      
      pIdDocumentoDe = @Escoge(gListaIdDoctosDe;lPosicion)
    FinMientras // Recorre los tipos de documentos modelos pListaIdDoctosDe

    // Incrementa un día a la fecha
    lFecha = fFechaSiguiente(lFecha)

  FinMientras  //  Hay días en el rango  

  // Se imprimen todos los detalles solo cuando se a impreso el producto, esto 
  // para cuando el producto no tiene movimientos y se debe de imprimir todos.
  Si pImprimirDetalles = kTodos Y gDetalleImpreso = False Y gProductoImpreso = True
    //Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
    fImprimeDatosValoresCaract()

    gDetalleImpreso = True
  FinSi

FinFunc

// *****************************************************************************
// Función fSumaMovimientos()
// Descripción: Recorre e imprime los movimientos de un detalle de 
//              característica.
// 
// Entradas: - atDetalle = Tabla de producto identificador
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 07/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fSumaMovimientos( atDetalle: Tabla )
  Local lFecha
  Local lNeto, lPrecio, lDescuentos, lImpuestos, lTotal, lPosicion
  Local lIdMonedaCte

  // Inicializa variables ------------------------------------------------------
  lFecha                 = pFechaInicial
  lNeto                  = 0 
  lPrecio                = 0
  lDescuentos            = 0
  lImpuestos             = 0 
  lTotal                 = 0
  
  // Asigna los Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
  fImprimeDatosValoresCaract()

  Si pImprimirDetalles  = 0
    gDetalleImpreso = True      
  FinSi

  // Buscar Movimientos en el rango de días
  Mientras lFecha <= pFechaFinal

    lPosicion = 0
    pIdDocumentoDe = @Escoge(gListaIdDoctosDe;lPosicion)
    Mientras pIdDocumentoDe != '' // FBCS POS, el se utiliza la lista gListaIdDoctosDe

      // Buscar los movimientos ocultos del detalle en el día
      Mientras[ tMovimiento.Busca[ @Str(atDetalle(cIdProducto); 0) & ':' & pIdDocumentoDe & ':' & '1' & ':' & lFecha ]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4] ]

        // Verificar que el movimiento oculto no pertenece a un documento cancelado
        //   Sólo se incluyen productos con movtos y no se ha impreso el producto actual 
        Si pImprimirProductos = kSoloConMovtos Y gProductoImpreso = False
          // Imprime nombre del producto
          fImprimeDatosProducto( tProducto )
          gProductoImpreso = True
        FinSi  

        lNeto = fNetoMovtoPaquete( tMovimiento; tMovtoOwner; tMovtoPaquete; tProducto; tPaqComponente; &lPrecio; &lDescuentos; &lImpuestos; &lTotal )

        lIdMonedaCte = 1
        // Busca el movimiento padre para obtener datos
        tMovtoOwner.Busca[ @Str(tMovimiento(cIdMovtoOwner);0) ]
        Si tMovtoOwner->Encontro

          // Busca el documento a partir del movimiento
          tDocumento.Busca[ @Str(tMovtoOwner(cIdDocumento);0) ]
          Si tDocumento->Encontro

            tClientes.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
            Si tClientes->Encontro
              lIdMonedaCte = tClientes(cIdMoneda)
            FinSi
          
          FinSi

        FinSi

        // Convertir lPrecio, lNeto, lDescuentos, lImpuestos y lTotal a la moneda pIdMoneda
        lPrecio = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lPrecio; pIdMoneda; lIdMonedaCte)
        lNeto = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lNeto; pIdMoneda; lIdMonedaCte)
        lDescuentos = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lDescuentos; pIdMoneda; lIdMonedaCte)
        lImpuestos = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lImpuestos; pIdMoneda; lIdMonedaCte)
        lTotal = fCambiarMonedaDoctoAReporte(tDocumento; tTipoCambio; lTotal; pIdMoneda; lIdMonedaCte)

        // Actualiza los acumulados
        gTotalDetalle[kNumColCantidadR]   = @Col(gTotalDetalle; kNumColCantidadR)   + tMovimiento(cUnidades)
        gTotalDetalle[kNumColNetoR]       = @Col(gTotalDetalle; kNumColNetoR)       + @Col( lNeto; kNumColCero )
        gTotalDetalle[kNumColDescuentosR] = @Col(gTotalDetalle; kNumColDescuentosR) + @Col( lDescuentos; kNumColCero )
        gTotalDetalle[kNumColImpuestosR]  = @Col(gTotalDetalle; kNumColImpuestosR)  + @Col( lImpuestos; kNumColCero )
        gTotalDetalle[kNumColTotalR]      = @Col(gTotalDetalle; kNumColTotalR)      + @Col( lTotal; kNumColCero )
        gDetalleImpreso = True      
      FinMientras  // Hay movimientos del día

      lPosicion = lPosicion +1      
      pIdDocumentoDe = @Escoge(gListaIdDoctosDe;lPosicion)
    FinMientras // Recorre los tipos de documentos modelos pListaIdDoctosDe

    // Incrementa un día a la fecha
    lFecha = fFechaSiguiente(lFecha)

  FinMientras  //  Hay días en el rango  

FinFunc

// *****************************************************************************
// Función fRecorreDetallesCarac()
// Descripción: Recorre los detalles de carac. de un producto que pertenecen a 
//              combinaciones de valores de carac. seleccionadas. Luego llama a 
//              la función que imprime los movimientos de cada detalle.
// 
// Entradas: - atProducto = Tabla de productos
// 
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// 03/02/2003  RPC     N.D. 1745       Incluir variaciones en el orden de las 
//                                     características
// *****************************************************************************
DefFunc fRecorreDetallesCarac( atProducto:Tabla )
  // Define variables locales
  Local lAux1, lAux2, lAux3

  // Recorrer las combinaciones de valores de características seleccionadas
  // Si se usan las tres características =======================================
  Si pIdValoresCarac1 Y pIdValoresCarac2 Y pIdValoresCarac3

    // Recorrer todos los valores de la primera característica
    lAux1 = 0
    gValorCarac1 = @Val( @Escoge(pIdValoresCarac1; lAux1) )

    Mientras gValorCarac1 != 0
      // Recorrer todos los valores de la segunda característica
      lAux2 = 0
      gValorCarac2 = @Val( @Escoge(pIdValoresCarac2; lAux2) )

      Mientras gValorCarac2 != 0
        // Recorrer todos los valores de la tercera característica
        lAux3 = 0
        gValorCarac3 = @Val( @Escoge(pIdValoresCarac3; lAux3) )

        Mientras gValorCarac3 != 0
          gDetalleImpreso = False

// RPC - ND 1745 Cambiar la búsqueda de una combinación de características fija 
// por búsquedas con las variantes en el orden de los valores de característica
//          // Recorrer todos los detalles de características que usan la combinación de valores
//        Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]

          // Recorrer todos los detalles de características que usan la combinación de valores carac1, carac2, carac3
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
            Si pTipoReporte = kReporteDetallado // -----------------------------
              // Recorre e imprime los movimientos del detalle de características
              fImprimeMovimientos( tDetalle ) 
            SiNo // Reporte Resumen --------------------------------------------
              // Recorre y suma los movimientos del detalle de características
              fSumaMovimientos( tDetalle )
            FinSi
          FinMientras // Hay valores de características
  
          // Recorrer todos los detalles de características que usan la combinación de valores carac1, carac3, carac2
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac3;0) & ':' & @Str(gValorCarac2;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
            Si pTipoReporte = kReporteDetallado // -----------------------------
              // Recorre e imprime los movimientos del detalle de características
              fImprimeMovimientos( tDetalle ) 
            SiNo // Reporte Resumen --------------------------------------------
              // Recorre y suma los movimientos del detalle de características
              fSumaMovimientos( tDetalle )
            FinSi
          FinMientras // Hay valores de características
  
          // Recorrer todos los detalles de características que usan la combinación de valores carac2, carac1, carac3
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
            Si pTipoReporte = kReporteDetallado // -----------------------------
              // Recorre e imprime los movimientos del detalle de características
              fImprimeMovimientos( tDetalle ) 
            SiNo // Reporte Resumen --------------------------------------------
              // Recorre y suma los movimientos del detalle de características
              fSumaMovimientos( tDetalle )
            FinSi
          FinMientras // Hay valores de características
  
          // Recorrer todos los detalles de características que usan la combinación de valores carac2, carac3, carac1
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0) & ':' & @Str(gValorCarac1;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
            Si pTipoReporte = kReporteDetallado // -----------------------------
              // Recorre e imprime los movimientos del detalle de características
              fImprimeMovimientos( tDetalle ) 
            SiNo // Reporte Resumen --------------------------------------------
              // Recorre y suma los movimientos del detalle de características
              fSumaMovimientos( tDetalle )
            FinSi
          FinMientras // Hay valores de características
  
          // Recorrer todos los detalles de características que usan la combinación de valores carac3, carac1, carac2
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac3;0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
            Si pTipoReporte = kReporteDetallado // -----------------------------
              // Recorre e imprime los movimientos del detalle de características
              fImprimeMovimientos( tDetalle ) 
            SiNo // Reporte Resumen --------------------------------------------
              // Recorre y suma los movimientos del detalle de características
              fSumaMovimientos( tDetalle )
            FinSi
          FinMientras // Hay valores de características
  
          // Recorrer todos los detalles de características que usan la combinación de valores carac3, carac2, carac1
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac3;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac1;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
            Si pTipoReporte = kReporteDetallado // -----------------------------
              // Recorre e imprime los movimientos del detalle de características
              fImprimeMovimientos( tDetalle ) 
            SiNo // Reporte Resumen --------------------------------------------
              // Recorre y suma los movimientos del detalle de características
              fSumaMovimientos( tDetalle )
            FinSi
          FinMientras // Hay valores de características

          Si pTipoReporte = kReporteDetallado // -----------------------------
            fImprimeTotalesCarac()
          SiNo // Reporte Resumen --------------------------------------------
            fImprimeTotalesCaracRes()
          FinSi
// FIN RPC - ND 1745

          lAux3 = lAux3 + 1
          gValorCarac3 = @Val( @Escoge(pIdValoresCarac3; lAux3) )

        FinMientras  // Mientras hay valores de la tercera característica

        lAux2 = lAux2 + 1
        gValorCarac2 = @Val( @Escoge(pIdValoresCarac2; lAux2) )

      FinMientras  // Mientras hay valores de la segunda característica

      lAux1 = lAux1 + 1
      gValorCarac1 = @Val( @Escoge(pIdValoresCarac1; lAux1) )

    FinMientras  // Mientras hay valores de la primera característica

  // Si sólo se usan dos características =======================================
  SiNo

    Si pIdValoresCarac1 Y pIdValoresCarac2 
      // Recorrer todos los valores de característica de la primera característica
      lAux1 = 0
      gValorCarac1 = @Val( @Escoge(pIdValoresCarac1; lAux1) )

      Mientras gValorCarac1 != 0

        // Recorrer todos los valores de característica de la segunda característica
        lAux2 = 0
        gValorCarac2 = @Val( @Escoge(pIdValoresCarac2; lAux2) )

        Mientras gValorCarac2 != 0
          gDetalleImpreso = False

          // Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2
          // Recorrer todos los detalles de características que usan la combinación de valores
// RPC - ND 1745 Cambiar la búsqueda de una características fija por un barrido 
// de los detalles del producto buscando los que usan las características actuales. 
// Tiene que ser con un barrido porque no hay forma de buscar la carac. 3 sin 
// tener valores en las carac. 1 y 2
//          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) ]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) ]; tDetalle->Encontro; tDetalle.Busca Siguiente[1] ]
            Si tDetalle(cIdValorCaracteristica1) = gValorCarac1 Y tDetalle(cIdValorCaracteristica2) = gValorCarac2 
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica1) = gValorCarac2 Y tDetalle(cIdValorCaracteristica2) = gValorCarac1
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica2) = gValorCarac1 Y tDetalle(cIdValorCaracteristica3) = gValorCarac2 
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica2) = gValorCarac2 Y tDetalle(cIdValorCaracteristica3) = gValorCarac1
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica1) = gValorCarac1 Y tDetalle(cIdValorCaracteristica3) = gValorCarac2
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica1) = gValorCarac2 Y tDetalle(cIdValorCaracteristica3) = gValorCarac1
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
          FinMientras // Hay valores de características

          Si pTipoReporte = kReporteDetallado // -----------------------------
            fImprimeTotalesCarac()
          SiNo // Reporte Resumen --------------------------------------------
            fImprimeTotalesCaracRes()
          FinSi
// FIN RPC - ND 1745

          lAux2 = lAux2 + 1
          gValorCarac2 = @Val( @Escoge(pIdValoresCarac2; lAux2) )

        FinMientras  // Mientras hay valores de la segunda característica

        lAux1 = lAux1 + 1
        gValorCarac1 = @Val( @Escoge(pIdValoresCarac1; lAux1) )

      FinMientras  // Mientras hay valores de la primera característica
  
    // Si sólo se usa una característica =======================================
    SiNo

      Si pIdValoresCarac1
        // Recorrer todos los valores de característica de la primera característica
        lAux1 = 0
        gValorCarac1 = @Val( @Escoge(pIdValoresCarac1; lAux1) )

        Mientras gValorCarac1 != 0
          gDetalleImpreso = False

          // Imprimir el nombre de los valores de característica gValorCarac1
          // Recorrer todos los detalles de características que usan la combinación de valores
// RPC - ND 1745 Cambiar la búsqueda de una características fija por un barrido 
// de los detalles del producto buscando los que usan la característica actual. 
// Tiene que ser con un barrido porque no hay forma de buscar la carac. 3 sin 
// tener valores en las carac. 1 y 2
//          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[4] ]
          Mientras[ tDetalle.Busca[ @Str(atProducto(cIdProducto);0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[1] ]
            Si tDetalle(cIdValorCaracteristica1) = gValorCarac1 
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica2) = gValorCarac1
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
            Si tDetalle(cIdValorCaracteristica3) = gValorCarac1 
              Si pTipoReporte = kReporteDetallado // -----------------------------
                // Recorre e imprime los movimientos del detalle de características
                fImprimeMovimientos( tDetalle ) 
              SiNo // Reporte Resumen --------------------------------------------
                // Recorre y suma los movimientos del detalle de características
                fSumaMovimientos( tDetalle )
              FinSi
            FinSi
          FinMientras // Hay valores de características

          Si pTipoReporte = kReporteDetallado // -----------------------------
            fImprimeTotalesCarac()
          SiNo // Reporte Resumen --------------------------------------------
            fImprimeTotalesCaracRes()
          FinSi
// FIN RPC - ND 1745 

          lAux1 = lAux1 + 1
          gValorCarac1 = @Val( @Escoge(pIdValoresCarac1; lAux1) )

        FinMientras  // Mientras hay valores de la primera característica

      FinSi  // Si se usa sola característica

    FinSi  // Si se usan dos características

  FinSi  // Si se usan tres características

FinFunc


// ****************************************************************************
// Función fImprimeValoresCaracteristica()
// Descripción: Imprime los nombres de las carecteristicas justificados al centro
// 
// Entradas: - aCaracteristica = Id de la caracteristica a procesar e imprimir
// 
//           - aValoresCaracteristicas = Lista de valores de caracteristica que
//                                       Se recibieron por parametros y de los
//                                       cuales se van a imprimir en el encabe-
//                                       do del reporte.
//
// Salidas :
//
// Historia de modificaciones
// ****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// ----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// ****************************************************************************
DefFunc fImprimeValoresCaracteristica( aCaracteristica; aValoresCaracteristicas )

  Local lContador, lIdValorCaracteristica, lAImprimir, lSeAgregaComa

  // Inicializa variables locales
  lSeAgregaComa = False
  lAImprimir    = ''  

  tCaracteristicas.Busca[ @Str(aCaracteristica;0) ]
  Si tCaracteristicas->Encontro
    lAImprimir = laImprimir & tCaracteristicas(cNombreCaracteristica) & ': '
  Sino
    lAImprimir = lAImprimir & 'CARACTERISTICA: '
  FinSi

  lContador = 0
  lIdValorCaracteristica = @Val( @Escoge(aValoresCaracteristicas; lContador) )

  Mientras lIdValorCaracteristica != 0

    tValorCarac.Busca[ @Str(lIdValorCaracteristica;0) ]

    Si tValorCarac->Encontro

      // Agrega el valor de la caracteristica al texto a imprimir
      Si tValorCarac(cIdPadreCaracteristica) = aCaracteristica
        // Agrega la coma al final del valor caracteristica agregada al texto a imprimir
        Si lSeAgregaComa = True
          lAImprimir = lAImprimir & ', '
          lSeAgregaComa = False
        FinSi

        lAImprimir = lAImprimir & tValorCarac( cValorCaracteristica )
        lSeAgregaComa = True
      FinSi

    SiNo
      lAImprimir = lAImprimir & 'Valor Caract, '
    FinSi

    lContador = lContador + 1
    lIdValorCaracteristica = @Val( @Escoge(aValoresCaracteristicas; lContador) )

  FinMientras

  Si pTipoReporte = kReporteDetallado // ---------------------------------------

    // Imprime el texto con la caracteristica y sus valores
    ws.Range( kColBlanco & RenActual ).Value = lAImprimir[C0]
    // Lo centra en las columnas A a la M --------------------------------------
    ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Font.FontStyle = 'Negrita'[C0]

  SiNo // Reporte Resumen ------------------------------------------------------

    // Imprime el texto con la caracteristica y sus valores
    ws.Range( kColBlancoR & RenActual ).Value = lAImprimir[C0]
    // Lo centra en las columnas A a la G --------------------------------------
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle = 'Negrita'[C0]

  FinSi

  RenActual = RenActual + 1[C0]

FinFunc


// ****************************************************************************
// Función fImprimeCaracteristicasExcel()
// Descripción: Imprime los nombres de las carecteristicas justificados al centro
// 
// Entradas:
//
// Salidas :
//
// Historia de modificaciones
// ****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// ----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// ****************************************************************************
DefFunc fImprimeCaracteristicasExcel()

  Local lContador, lIdCaracteristica

  // Procesa las caracteristicas 1  
  Si pIdCaracteristica1 != 0

    lContador = 0
    lIdCaracteristica = @Val( @Escoge(pIdCaracteristica1; lContador) )

    Mientras lIdCaracteristica != 0

      fImprimeValoresCaracteristica( lIdCaracteristica; pIdValoresCarac1 )

      lContador = lContador + 1
      lIdCaracteristica = @Val( @Escoge(pIdCaracteristica1; lContador) )

    FinMientras    

  FinSi

  // Procesa las caracteristicas 2
  Si pIdCaracteristica2 != 0

    lContador = 0
    lIdCaracteristica = @Val( @Escoge(pIdCaracteristica2; lContador) )

    Mientras lIdCaracteristica != 0

      fImprimeValoresCaracteristica( lIdCaracteristica; pIdValoresCarac2 )

      lContador = lContador + 1
      lIdCaracteristica = @Val( @Escoge(pIdCaracteristica2; lContador) )

    FinMientras    

  FinSi

  // Procesa las caracteristicas 3
  Si pIdCaracteristica3 != 0

    lContador = 0
    lIdCaracteristica = @Val( @Escoge(pIdCaracteristica3; lContador) )

    Mientras lIdCaracteristica != 0

      fImprimeValoresCaracteristica( lIdCaracteristica; pIdValoresCarac3 )

      lContador = lContador + 1
      lIdCaracteristica = @Val( @Escoge(pIdCaracteristica3; lContador) )

    FinMientras    

  FinSi
  
FinFunc


// ****************************************************************************
// Función fImprimeClasesExcel()
// Descripción: Imprime los nombres de las clases justificados al centro
// 
// Entradas: - aNumClases = El número total de clases seleccionadas,contando 
//                          todas las clasificaciones
//           - aNumPorClase = Lista que tiene como elementos el numero de 
//                            clases seleccionadas para cada clasificación.
//
// Salidas :
//
// Historia de modificaciones
// ****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// ----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// ****************************************************************************
Deffunc fImprimeClasesExcel(aListaNombreClases;aNumPorClase)
  
  Local lCont,lNumElem,lContPrincipal,lLeyenda,lOffset

  lOffset = 0
  lContPrincipal = 0
  lLeyenda = ''

  // Se barren las seis listas de ID´s
  Mientras  lContPrincipal < 6

    // solo se imprimen los que si tuvieron al menos un ID 
    Si   @Escoge(aNumPorClase;lContPrincipal) != ''
      // Obtengo el número de elementos para la clase
      lNumElem = @Val(@Escoge(aNumPorClase;lContPrincipal))

      lCont = 0
      // Barre todos los elementos de esta clase
      Mientras lCont < lNumElem
        lLeyenda = lLeyenda &','& @Escoge(aListaNombreClases;lOffset+lCont)
        lCont = lCont +1
      FinMientras 

      lOffset = lOffset + lNumElem 
    
      Si pTipoReporte = kReporteDetallado // -----------------------------------

        // Se imprime la clase y sus valores seleccionados
        ws.Range( kColBlanco & RenActual ).Value = 'CLASIFICACIÓN No. ' & @Str(lContPrincipal+1;0) & ' : '& @SubStr(lLeyenda;1;@Len(lLeyenda)-1)[C0]
        // Lo centra en las columnas A a la M --------------------------------------
        ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).HorizontalAlignment = xlCentrarEnSeleccion[C0]
        ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Font.FontStyle = 'Negrita'[C0]

      SiNo // Reporte Resumen --------------------------------------------------

        // Se imprime la clase y sus valores seleccionados
        ws.Range( kColBlancoR & RenActual ).Value = 'CLASIFICACIÓN No. ' & @Str(lContPrincipal+1;0) & ' : '& @SubStr(lLeyenda;1;@Len(lLeyenda)-1)[C0]
        // Lo centra en las columnas A a la G --------------------------------------
        ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).HorizontalAlignment = xlCentrarEnSeleccion[C0]
        ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle = 'Negrita'[C0]

      FinSi

      // Avanza de renglon
      RenActual = RenActual + 1[C0]

      lLeyenda = ''
  
    Finsi
    lContPrincipal = lContPrincipal + 1

  FinMientras
FinFunc

// *****************************************************************************
// Encabezado del reporte
// 
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 06/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
Encab
  Si pTipoReporte = kReporteDetallado // ---------------------------------------

    // ++++++++++++++++++++++++++++++++++++++++++++
    // + Columna + Descripcion  + Constante       +
    // ++++++++++++++++++++++++++++++++++++++++++++
    // +   A     + Blanco       + kColBlanco      +
    // +   B     + Fecha        + kColFecha       +
    // +   C     + Concepto     + kColConcepto    +
    // +   D     + Serie        + kColSerie       +
    // +   E     + Folio        + kColFolio       +
    // +   F     + Almacén      + kColAlmacen     +
    // +   G     + Cantidad     + kColCantidad    +
    // +   H     + Precio       + kColPrecio      +
    // +   I     + Neto         + kColNeto        +
    // +   J     + Descuentos   + kColDescuentos  +
    // +   K     + Impuestos    + kColImpuestos   +
    // +   L     + Total        + kColTotal       +
    // ++++++++++++++++++++++++++++++++++++++++++++

    // Pone el nombre del sistema ----------------------------------------------
    // Columna 'A'
    ws.Range( kColBlanco & RenActual ).Font.Color = @RGB(255;0;0)[C0]
    ws.Range( kColBlanco & RenActual ).Font.Size = 10[C0]
    ws.Range( kColBlanco & RenActual ).Value = 'AdminPAQ'[C0]

    // Pone el nombre de la empresa --------------------------------------------
    // Columna 'C'
    ws.Range( kColConcepto & RenActual ).Font.Size = 14[C0]
    ws.Range( kColConcepto & RenActual ).Font.FontStyle = 'Negrita'[C0]

    // Lo centra en las columnas 'C' a la 'L' ----------------------------------
    ws.Range( kColConcepto & RenActual & ':' & kColImpuestos & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range( kColConcepto & RenActual ).Value = tEmpresa->Nombre

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Pone el titulo del reporte en EXCEL -------------------------------------
    // Columna 'A'
    ws.Range(kColBlanco & RenActual).Font.Size = 12[C0]
    ws.Range(kColBlanco & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range(kColBlanco & RenActual ).Value = 'M O V I M I E N T O S     P O R     C A R A C T E R I S T I C A'[C0]
    // Lo centra en las columnas A a la M --------------------------------------
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Pone el titulo del reporte en EXCEL -------------------------------------
    // Columna 'A'
    ws.Range(kColBlanco & RenActual).Font.Size = 12[C0]
    ws.Range(kColBlanco & RenActual).Font.FontStyle = 'Negrita'[C0]    
    ws.Range(kColBlanco & RenActual ).Value = 'Del: ' & fFormateaFecha(pFechaInicial;gIdioma) & ' Al: ' & fFormateaFecha(pFechaFinal;gIdioma)[C0]
    // Lo centra en las columnas A a la M --------------------------------------
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Se Revisan las clasificaciones, para recuperarlas e imprimirlas en el encabezado
    // ===== se arman los ID en una LIsta para poder recorrerlos en una iteración
    gClasesRecibidas = fCuentaClases(&gNumClasesPorTipo;pIdClase1;pIdClase2;pIdClase3;pIdClase4;pIdClase5;pIdClase6)

    // se cargan las clasificaciones validas y se obtiene el número de clases validas
    gNumDeClases = fCargaClases(tValoresDeClasif;&gListNombreDeClases; &gListIdDeClases; gClasesRecibidas)

    // Solo si hubo al menos una clase seleccionada se imprimen las clasificaciones
    Si gNumDeClases > 0    
      fImprimeClasesExcel(gListNombreDeClases;gNumClasesPorTipo) 
    Finsi

    // Imprime los nombres de las caracteristicas seleccionadas ----------------
    fImprimeCaracteristicasExcel()

    // Imprime la moneda seleccionada ------------------------------------------
    tMoneda.Busca[@Str(pIdMoneda;0)]
    Si tMoneda->Encontro
      // Columna 'L'
      ws.Range(kColImpuestos & RenActual ).Value = 'Moneda: ' & tMoneda(cNombreMoneda)[C0]
    FinSi

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Pone el titulo de cada columna en EXCEL ---------------------------------
    // Rango de las columnas 'A' a la 'L'
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Interior.ColorIndex            = 55[C0]    
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Font.FontStyle                 = 'Negrita'[C0]    
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Font.Color                     = @RGB(255;255;255)[C0]

    // Columna 'E'
    ws.Range(kColFolio & RenActual).HorizontalAlignment = xlDerecha[C0]
    // Columna 'F'
    ws.Range(kColAlmacen & RenActual).HorizontalAlignment = xlCentro[C0]
    // Rango de columnas de la 'H' hasta la 'L'
    ws.Range(kColCantidad & RenActual & ':' & kColTotal & RenActual).HorizontalAlignment = xlDerecha[C0]
    // Rango de columnas de la 'A' hasta la 'L'
    ws.Range(kColBlanco & RenActual & ':' & kColTotal & RenActual).Value = '','Fecha','Concepto','Serie','Folio','Almacén','Cantidad','Precio','Neto','Descuentos','Impuestos','Total'

  SiNo // Reporte Resumen ------------------------------------------------------

    // ++++++++++++++++++++++++++++++++++++++++++++
    // + Columna + Descripcion  + Constante       +
    // ++++++++++++++++++++++++++++++++++++++++++++
    // +   A     + Blanco       + kColBlancoR     +
    // +   B     + Producto     + kColProductoR   +
    // +   C     + Cantidad     + kColCantidadR   +
    // +   D     + Neto         + kColNetoR       +
    // +   E     + Descuentos   + kColDescuentosR +
    // +   F     + Impuestos    + kColImpuestosR  +
    // +   G     + Total        + kColTotalR      +
    // ++++++++++++++++++++++++++++++++++++++++++++

    // Pone el nombre del sistema ----------------------------------------------
    // Columna 'A'
    ws.Range( kColBlancoR & RenActual ).Font.Color = @RGB(255;0;0)[C0]
    ws.Range( kColBlancoR & RenActual ).Font.Size = 10[C0]
    ws.Range( kColBlancoR & RenActual ).Value = 'AdminPAQ'[C0]

    // Pone el nombre de la empresa --------------------------------------------
    // Columna 'C'
    ws.Range( kColCantidadR & RenActual ).Font.Size = 14[C0]
    ws.Range( kColCantidadR & RenActual ).Font.FontStyle = 'Negrita'[C0]

    // Lo centra en las columnas 'C' a la 'G' ----------------------------------
    ws.Range( kColCantidadR & RenActual & ':' & kColImpuestosR & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range( kColCantidadR & RenActual ).Value = tEmpresa->Nombre

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Pone el titulo del reporte en EXCEL -------------------------------------
    // Columna 'A'
    ws.Range( kColBlancoR & RenActual ).Font.Size = 12[C0]
    ws.Range( kColBlancoR & RenActual ).Font.FontStyle = 'Negrita'[C0]
    ws.Range( kColBlancoR & RenActual ).Value = 'V E N T A S     P O R     C A R A C T E R I S T I C A'[C0]
    // Lo centra en las columnas A a la G --------------------------------------
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Pone el titulo del reporte en EXCEL -------------------------------------
    // Columna 'A'
    ws.Range( kColBlancoR & RenActual ).Font.Size = 12[C0]
    ws.Range( kColBlancoR & RenActual ).Font.FontStyle = 'Negrita'[C0]    
    ws.Range( kColBlancoR & RenActual ).Value = 'Del: ' & fFormateaFecha(pFechaInicial;gIdioma) & ' Al: ' & fFormateaFecha(pFechaFinal;gIdioma)[C0]
    // Lo centra en las columnas A a la G --------------------------------------
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).HorizontalAlignment = xlCentrarEnSeleccion[C0]

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Se Revisan las clasificaciones, para recuperarlas e imprimirlas en el encabezado
    // ===== se arman los ID en una LIsta para poder recorrerlos en una iteración
    gClasesRecibidas = fCuentaClases(&gNumClasesPorTipo;pIdClase1;pIdClase2;pIdClase3;pIdClase4;pIdClase5;pIdClase6)

    // se cargan las clasificaciones validas y se obtiene el número de clases validas
    gNumDeClases = fCargaClases(tValoresDeClasif;&gListNombreDeClases; &gListIdDeClases; gClasesRecibidas)

    // Solo si hubo al menos una clase seleccionada se imprimen las clasificaciones
    Si gNumDeClases > 0    
      fImprimeClasesExcel(gListNombreDeClases;gNumClasesPorTipo) 
    Finsi

    // Imprime los nombres de las caracteristicas seleccionadas ----------------
    fImprimeCaracteristicasExcel()

    // Imprime la moneda seleccionada ------------------------------------------
    tMoneda.Busca[@Str(pIdMoneda;0)]
    Si tMoneda->Encontro
      // Columna 'G'
      ws.Range(kColImpuestosR & RenActual ).Value = 'Moneda: ' & tMoneda(cNombreMoneda)[C0]
    FinSi

    // Avanza de renglon -------------------------------------------------------
    RenActual = RenActual + 1[C0]

    // Pone el titulo de cada columna en EXCEL ---------------------------------
    // Rango de las columnas 'A' a la 'L'
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlDerecha).LineStyle   = xlLineaSimple[C0]
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Interior.ColorIndex            = 55[C0]    
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle                 = 'Negrita'[C0]    
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Font.Color                     = @RGB(255;255;255)[C0]

    // Rango de columnas de la 'C' hasta la 'G'
    ws.Range( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).HorizontalAlignment = xlDerecha[C0]
    // Rango de columnas de la 'A' hasta la 'G'
    ws.Range( kColBlancoR & RenActual & ':' & kColTotalR & RenActual ).Value = '','Producto','Cantidad','Neto','Descuentos','Impuestos','Total'
  FinSi

  // Avanza de renglon ---------------------------------------------------------
  RenActual = RenActual + 1
  Excel.Rows(RenActual & ':' & RenActual).Select
  Excel.ActiveWindow.FreezePanes = True
  ws.Range(kColBlanco & RenActual).Select
FinEncab

// ****************************************************************************
// Modulo Principal
//
// Historia de modificaciones
// ****************************************************************************
// Fecha        Nombre   Id.Lotus    Descripción
// ----------------------------------------------------------------------------
// 06/01/2003   CILA     N.C. 286    Implementación Inicial
// ****************************************************************************

// ****************************************************************************
// Ejecuta funciones de inicialización del reporte. 
// ****************************************************************************
fConfiguraDecimales()

// ****************************************************************************
// Obtiene los productos en el rango especificado en los parámetros del reporte 
// ****************************************************************************

// Si el rango inicial es el primer producto, recupera el código del primero
Si pProductoInicial = ' '
  tProducto.Busca Primero
  Si tProducto->Encontro
    pProductoInicial = tProducto(cCodigoProducto)
  FinSi
FinSi

// Si el rango final es el último producto, recupera el código del último
Si pProductoFinal = ' '
  tProducto.Busca Ultimo
  Si tProducto->Encontro
    pProductoFinal = tProducto(cCodigoProducto)
  FinSi
FinSi

// ****************************************************************************
// Recorrer los productos seleccionados y sus caracteristicas
// ****************************************************************************

// Mientras hay productos en el rango
Mientras[ tProducto.Busca[ pProductoInicial & '..' & pProductoFinal ]; tProducto->Encontro; tProducto.Busca Siguiente[1] ]

  // Si el producto no maneja las características seleccionadas descartarlo
  Si pIdCaracteristica1 != 0 Y tProducto(cIdPadreCaracteristica1) != pIdCaracteristica1 Y tProducto(cIdPadreCaracteristica2) != pIdCaracteristica1 Y tProducto(cIdPadreCaracteristica3) != pIdCaracteristica1 
    Continua
  FinSi

  Si pIdCaracteristica2 != 0 Y tProducto(cIdPadreCaracteristica1) != pIdCaracteristica2 Y tProducto(cIdPadreCaracteristica2) != pIdCaracteristica2 Y tProducto(cIdPadreCaracteristica3) != pIdCaracteristica2 
    Continua
  FinSi

  Si pIdCaracteristica3 != 0 Y tProducto(cIdPadreCaracteristica1) != pIdCaracteristica3 Y tProducto(cIdPadreCaracteristica2) != pIdCaracteristica3 Y tProducto(cIdPadreCaracteristica3) != pIdCaracteristica3 
    Continua
  FinSi    

  // Si no se imprimen productos dados de baja descartarlo
  Si (pEstadoProducto) Y (pEstadoProducto != @Abs(tProducto(cStatusProducto) - 2))
    Continua
  FinSi

  // Si el producto no cumple con las clasificaciones especificadas descartarlo
  Si !fMiembroDeUnaClase(tProducto; gNumDeClases; gListIdDeClases; 2)
    Continua
  FinSi

  // Inicializa la bandera
  gProductoImpreso = False

  // Si se incluyen todos los productos, imprimir el actual 
  Si pImprimirProductos = kTodo
    // Imprime nombre del producto
    fImprimeDatosProducto( tProducto )
    gProductoImpreso = True
  FinSi  

  // Recorre los detalles de característica del producto imprimiendo sus movimientos
  fRecorreDetallesCarac(tProducto)

  // Imprime los totales del produto -------------------------------------------
  Si pTipoReporte = kReporteDetallado //  --------------------------------------
    fImprimeTotalesProducto()
  SiNo // Reporte Resumen ------------------------------------------------------
    fImprimeTotalesProductoRes()
  FinSi

FinMientras  // Hay productos en el rango

// Imprime totales del reporte -------------------------------------------------
Si pTipoReporte = kReporteDetallado // -----------------------------------------
  fImprimeTotales()
SiNo // Reporte Resumen -------------------------------------------------------  
  fImprimeTotalesRes()
FinSi

//Fin Reporte
