// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
//	MovtosVtaCaractExcel.rpt
//	Nombre del reporte en el sistema: Movimientos de Venta de Características
//                                    en Excel en Detalle 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: 	    05 de Diciembre del 2002
//
//  Historia de revisiones:
//	05/12/2002  CILA   N.C.  286  Implementación Inicial  
//  31/01/2003  RPC    N.D. 1745  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['iCaract123']                                        // Indice: cIdValorCarateristica1+cIdValorCarateristica2+cIdValorCarateristica3

  UsaTabla tProducto        = tEmpresa['MGW10005']                        // Productos
  tProducto.UsaIndice['']                                                 // Indice Primario

  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']                                // Indice: 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
  gTotalProducto     = 0
  gTotalDetalle      = 0
  gTotal             = 0
  gValorCarac1       = 0
  gValorCarac2       = 0
  gValorCarac3       = 0
  gIdioma            = 0   // Idioma del reporte
                           // 0 = Español
                           // 1 = Inglés
  gNumDeClases       = 0 
  gClasesRecibidas   = ''  
  gIdPdroducto       = 0
  gDetalleImpreso    = False
  gHayMovtosProducto = 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 kColProducto    'G'
  Constante kColCantidad    'H'
  Constante kColPrecio      'I'
  Constante kColNeto        'J'
  Constante kColDescuentos  'K'
  Constante kColImpuestos   'L'
  Constante kColTotal       'M'
  // 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 *****************************************************
  Constante kNumColCero        0
  // Constantes para el Reporte Detallado --------------------------------------
  Constante kNumColBlanco      1
  Constante kNumColFecha       2
  Constante kNumColConcepto    3
  Constante kNumColSerie       4
  Constante kNumColFolio       5
  Constante kNumColAlmacen     6
  Constante kNumColProducto    7
  Constante kNumColCantidad    8
  Constante kNumColPrecio      9
  Constante kNumColNeto       10
  Constante kNumColDescuentos 11
  Constante kNumColImpuestos  12
  Constante kNumColTotal      13
  // 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 anteriormente
     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(kNumColProducto).ColumnWidth   = 30[C0] // Producto
    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   = 30[C0] // Producto
    ws.Columns(kNumColCantidadR).ColumnWidth   = 19[C0] // Cantidad    
    ws.Columns(kNumColNetoR).ColumnWidth       = 19[C0] // Neto
    ws.Columns(kNumColDescuentosR).ColumnWidth = 19[C0] // Descuentos
    ws.Columns(kNumColImpuestosR).ColumnWidth  = 19[C0] // Impuestos
    ws.Columns(kNumColTotalR).ColumnWidth      = 19[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
// -----------------------------------------------------------------------------
// 10/12/2002  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 // -------------------------------------
      [C7..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 // Reporte Resumen ----------------------------------------------------
      [C2..C7].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 fImprimeDatosCaracteristicas()
//
// Descripción: Busca los nombres de los valores de las caracteristicas e 
//              imprime dichos valores en el reporte.
// 
// Entradas:
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 10/12/2002  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeDatosCaracteristicas( aIdValorCaract1; aIdValorCaract2; aIdValorCaract3 )
  Local lCaracteristicas

  // Inicializa variables locales
  lCaracteristicas = ''

  // Busca y arma la cadenda con la caracteristica 1
  Si aIdValorCaract1 != 0
    tValorCarac.Busca[ @Str(aIdValorCaract1;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 aIdValorCaract2 != 0
    lCaracteristicas[0] = lCaracteristicas & '-'
    tValorCarac.Busca[ @Str(aIdValorCaract2;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 aIdValorCaract3 != 0
    lCaracteristicas[0] = lCaracteristicas & '-'
    tValorCarac.Busca[ @Str(aIdValorCaract3;0) ]
    Si tValorCarac->Encontro
      lCaracteristicas[0] = lCaracteristicas & tValorCarac( cValorCaracteristica )
    SiNo
      lCaracteristicas[0] = lCaracteristicas & 'Caracteritica 3'
    FinSi
  FinSi

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

  Si pTipoReporte = kReporteDetalle // -----------------------------------------
    // Imprime las caracteristicas
    ws.Range( kColFecha & RenActual & ':' & kColTotal & RenActual ).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range( kColFecha & RenActual ).Font.FontStyle = 'Negrita'[C0]
    ws.Range( kColFecha & RenActual ).Value = @Col(lCaracteristicas;0)[C0]
  SiNo  // Reporte Resumen -----------------------------------------------------
    // Imprime las caracteristicas    
    ws.Range( kColProductoR & RenActual ).Font.FontStyle = 'Negrita'[C0]
    ws.Range( kColProductoR & RenActual ).Value = @Col(lCaracteristicas;0)[C0]
  FinSi
  
  // Imcrementa el contador de renglones de la hoja de Excel -------------------
  RenActual = RenActual + 1
    
FinFunc


// *****************************************************************************
// Función fImprimeSubTotales()
//
// Descripción: Imprime los subtotales por detalle de la caracteristicas.
// 
// Entradas:
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 10/12/2002  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeSubTotales()

  // 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( kColProducto   & RenActual ).HorizontalAlignment = xlDerecha[C0]
  ws.Range( kColProducto   & RenActual ).Value = 'Total:  '[C0]
  ws.Range( kColCantidad   & RenActual ).Value = @Col(gTotalDetalle;6)[C0]
  ws.Range( kColPrecio     & RenActual ).Value = @Col(gTotalDetalle;7)[C0]
  ws.Range( kColNeto       & RenActual ).Value = @Col(gTotalDetalle;8)[C0]
  ws.Range( kColDescuentos & RenActual ).Value = @Col(gTotalDetalle;9)[C0]
  ws.Range( kColImpuestos  & RenActual ).Value = @Col(gTotalDetalle;10)[C0]
  ws.Range( kColTotal      & RenActual ).Value = @Col(gTotalDetalle;11)[C0] 

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

FinFunc


// *****************************************************************************
// Función fImprimeTotales()
//
// Descripción: Imprime los totales del reporte
// 
// Entradas:
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 10/12/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( kColProducto & RenActual & ':' & kColTotal & RenActual ).Font.FontStyle = 'Negrita'[C0]

  // Imprime el total general del reporte ----------------------------------------
  ws.Range( kColProducto   & RenActual ).HorizontalAlignment = xlDerecha[C0]
  ws.Range( kColProducto   & RenActual ).Value = 'Total General:  '[C0]
  ws.Range( kColCantidad   & RenActual ).Value = @Col(gTotal;6)[C0]
  ws.Range( kColNeto       & RenActual ).Value = @Col(gTotal;8)[C0]
  ws.Range( kColDescuentos & RenActual ).Value = @Col(gTotal;9)[C0]
  ws.Range( kColImpuestos  & RenActual ).Value = @Col(gTotal;10)[C0]
  ws.Range( kColTotal      & RenActual ).Value = @Col(gTotal;11)[C0] 

FinFunc


// *****************************************************************************
// Función fImprimeMovimientos()
// Descripción: Imprime los movimientos de una combinación de valores de 
//              característica ordenados por fecha. Los movimientos se toman de 
//              la hoja del reporteador.
// 
// Entradas: 
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 05/12/2002  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeMovimientos()
  Local lRenglon, lFecha, lFechaEditada
  Local lImpresoDetalle

  // Inicialización de variables
  gTotalDetalle   = 0
  lFecha          = pFechaInicial
  lImpresoDetalle = False

  // Si se incluyen todos los detalles de característica, imprimir el actual 
  Si pImprimirDetalles = kTodos Y lImpresoDetalle = False
    // Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
    fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )

    lImpresoDetalle = True
  FinSi

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

    // Revisar todos los movimientos almacenados en la hoja del reporteador buscando 
    // los que pertenecen a los valorees de característica y a la fecha actual
    lRenglon = 1

    Mientras lRenglon <= gRenglonesHoja
      Si @Col({lRenglon};3) != lFecha
        lRenglon = lRenglon + 1
        Continua 
      FinSi

      // Sólo se incluyen detalles con movtos y no se ha impreso el detalle actual
      Si pImprimirDetalles = kSoloConMovtos Y lImpresoDetalle = False
        // Imprimir el nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3 
        fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )

        lImpresoDetalle = True
      FinSi

      // Imprime el movimiento -------------------------------------------------
      ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
      ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]

      lFechaEditada = fFormateaFecha( @Col({lRenglon};3); gIdioma )

      ws.Range( kColFecha      & RenActual ).Value = @CHR(39) & lFechaEditada[C0]
      ws.Range( kColConcepto   & RenActual ).Value = @Col({lRenglon};4)[C0]
      ws.Range( kColSerie      & RenActual ).Value = @Col({lRenglon};5)[C0]
      ws.Range( kColFolio      & RenActual ).Value = @Col({lRenglon};6)[C0]
      ws.Range( kColAlmacen    & RenActual ).Value = @Col({lRenglon};7)[C0]
      ws.Range( kColProducto   & RenActual ).Value = @Col({lRenglon};8)[C0]
      ws.Range( kColCantidad   & RenActual ).Value = @Col({lRenglon};9)[C0]
      ws.Range( kColPrecio     & RenActual ).Value = @Col({lRenglon};10)[C0]
      ws.Range( kColNeto       & RenActual ).Value = @Col({lRenglon};11)[C0]
      ws.Range( kColDescuentos & RenActual ).Value = @Col({lRenglon};12)[C0]
      ws.Range( kColImpuestos  & RenActual ).Value = @Col({lRenglon};13)[C0]
      ws.Range( kColTotal      & RenActual ).Value = @Col({lRenglon};14)[C0]

      // Imcrementa el contador de renglones de la hoja de Excel --------------
      RenActual = RenActual + 1 
 
      gTotalDetalle[6]  = @Col(gTotalDetalle;6)  + @Col({lRenglon};9)  // Cantidad
      gTotalDetalle[7]  = '' // Precio
      gTotalDetalle[8]  = @Col(gTotalDetalle;8)  + @Col({lRenglon};11) // Neto
      gTotalDetalle[9]  = @Col(gTotalDetalle;9)  + @Col({lRenglon};12) // Descuentos
      gTotalDetalle[10] = @Col(gTotalDetalle;10) + @Col({lRenglon};13) // Impuestos
      gTotalDetalle[11] = @Col(gTotalDetalle;11) + @Col({lRenglon};14) // Total

      lRenglon = lRenglon + 1

    FinMientras  // Hay renglones en la hoja electrónica
    
    // Incrementa un día a la fecha
    lFecha = fFechaSiguiente(lFecha)
 
  FinMientras  // Hay días en el rango de fechas

  Si lImpresoDetalle = True
    // Imprime los subtotales por caracteristica
    fImprimeSubTotales()
  FinSi

  // Actualiza el total del reporte
  gTotal = gTotal + gTotalDetalle[C6,C8..C11]

  // Inicializa los subtotales por caracteristica
  gTotalDetalle = ''

  // Limpiar hoja del reporteador
  gRenglonesHoja = 0

FinFunc

// *****************************************************************************
// Función fAlmacenaMovimientos()
// Descripción: Recorre los movimientos de característica de un producto y los 
//              guarda en la hoja del reporteador. Luego los movimientos en la 
//              hoja se recorren ordenados por característica y fecha y se 
//              imprimen.
// 
// Entradas: atDetalla: Tabla de Producto Identificador
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 05/12/2002  CILA    N.C. 286        Implementación Inicial
// 04/02/2003  RPC     N.D. 1770       El neto no debe incluir descuentos
// *****************************************************************************
DefFunc fAlmacenaMovimientos( atDetalle: TABLA ) 
  Local lNeto, lFecha
  Local lCantidad, lPrecio, lDescuentos, lImpuestos, lTotal, lPosicion
  Local lIdMonedaCte

  // Inicializa varaibelos locales
  lFecha      = pFechaInicial
  lCantidad   = 0
  lNeto       = 0
  lPrecio     = 0
  lDescuentos = 0 
  lImpuestos  = 0
  lTotal      = 0
  lPosicion   = 0 // sirve para barrer las lista de documentos modelos FBCS POS (4,35)

  // Buscar producto del detalle de caracterìsticas para verificar que se debe incluir en el reporte
  tProducto.Busca[ @Str(atDetalle(cIdProductoPadre);0) ]
  Si !(tProducto->Encontro)
    Retorna
  FinSi

  // Valida si el código esta en el rango de productos 
  Si (tProducto(cCodigoProducto) < pProductoInicial) O (tProducto(cCodigoProducto) > pProductoFinal)
    Retorna
  FinSi  

  // 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 
    Retorna
  FinSi

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

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

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

  // Si el producto no cumple con las clasificaciones especificadas descartarlo
  Si !fMiembroDeUnaClase(tProducto; gNumDeClases; gListIdDeClases; 2)
    Retorna
  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    // FBCS POS 
      Mientras[ tMovimiento.Busca[ @Str(atDetalle(cIdProducto);0) & ':' & pIdDocumentoDe & ':' & '1' & ':' & lFecha ]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4] ]
          // Si no se incluyen productos en cero
        Si pImprimirProductos = kSoloConMovtos Y tMovimiento(cUnidades) = 0
          Continua
        FinSi 

        // Obtiene los valores de Precio, Descuentos, Impuestos 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

        lCantidad = tMovimiento(cUnidades)

        // Comvierte los valores de Precio,Neto,Descuentos,Impuestos y Total 
        // A la moneda del reporte.
        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)
  
        gRenglonesHoja = gRenglonesHoja + 1

        // Agregar a la hoja del reporteador un renglón con los datos del movimiento
        {gRenglonesHoja}[0]  = atDetalle(cIdValorCaracteristica1)
        {gRenglonesHoja}[1]  = atDetalle(cIdValorCaracteristica2)
        {gRenglonesHoja}[2]  = atDetalle(cIdValorCaracteristica3)
        {gRenglonesHoja}[3]  = tMovimiento(cFecha)
        {gRenglonesHoja}[4]  = tConcepto(cNombreConcepto)
        {gRenglonesHoja}[5]  = tDocumento(cSerieDocumento)
        {gRenglonesHoja}[6]  = tDocumento(cFolio)
        {gRenglonesHoja}[7]  = tAlmacen(cNombreAlmacen)
        {gRenglonesHoja}[8]  = tProducto(cNombreProducto)
        {gRenglonesHoja}[9]  = tMovimiento(cUnidades)
        {gRenglonesHoja}[10] = lPrecio
        {gRenglonesHoja}[11] = lNeto
        {gRenglonesHoja}[12] = lDescuentos
        {gRenglonesHoja}[13] = lImpuestos
        {gRenglonesHoja}[14] = lTotal
        {gRenglonesHoja}[15] = tProducto(cIdProducto)
      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 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
// -----------------------------------------------------------------------------
// 10/12/2002  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
// -----------------------------------------------------------------------------
// 10/12/2002  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
// -----------------------------------------------------------------------------
// 10/12/2002  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

// *****************************************************************************
// 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
// -----------------------------------------------------------------------------
// 08/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
DefFunc fImprimeTotalesProducto()

  // 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]
  ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlInferior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]

  // Imprimir totales de producto   
  ws.Range( kColProductoR   & RenActual ).Value = tProducto(cNombreProducto)[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
  gTotalDetalle[kNumColCantidadR]   = @Col(gTotalDetalle;kNumColCantidadR)   + @Col(gTotalProducto;kNumColCantidadR)
  gTotalDetalle[kNumColNetoR]       = @Col(gTotalDetalle;kNumColNetoR)       + @Col(gTotalProducto;kNumColNetoR)
  gTotalDetalle[kNumColDescuentosR] = @Col(gTotalDetalle;kNumColDescuentosR) + @Col(gTotalProducto;kNumColDescuentosR)
  gTotalDetalle[kNumColImpuestosR]  = @Col(gTotalDetalle;kNumColImpuestosR)  + @Col(gTotalProducto;kNumColImpuestosR)
  gTotalDetalle[kNumColTotalR]      = @Col(gTotalDetalle;kNumColTotalR)      + @Col(gTotalProducto;kNumColTotalR)
  
  // Inicializa el total del detalle por producto
  gTotalProducto = '' 

  // Inicializa la bandera de movimiento
  gHayMovtosProducto = False

FinFunc

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

  Si gDetalleImpreso = 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( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
    ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle = 'Negrita'[C0]
    
    // Imprimir totales de gValorCarac1-gValorCarac2-gValorCarac3 
    ws.Range( kColProductoR   & RenActual ).HorizontalAlignment = xlDerecha[C0]
    ws.Range( kColProductoR   & RenActual ).Value = 'Total Caracteristica: '
    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  
    gTotal[kNumColCantidadR]   = @Col(gTotal;kNumColCantidadR)   + @Col(gTotalDetalle;kNumColCantidadR)
    gTotal[kNumColNetoR]       = @Col(gTotal;kNumColNetoR)       + @Col(gTotalDetalle;kNumColNetoR)
    gTotal[kNumColDescuentosR] = @Col(gTotal;kNumColDescuentosR) + @Col(gTotalDetalle;kNumColDescuentosR)
    gTotal[kNumColImpuestosR]  = @Col(gTotal;kNumColImpuestosR)  + @Col(gTotalDetalle;kNumColImpuestosR)
    gTotal[kNumColTotalR]      = @Col(gTotal;kNumColTotalR)      + @Col(gTotalDetalle;kNumColTotalR)
    
    // Inicializa el total del detalle por caracteristica
    gTotalDetalle = 0

  FinSi

FinFunc

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

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

  // 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( kColCantidadR & RenActual & ':' & kColTotalR & RenActual ).Borders(xlSuperior).LineStyle  = xlLineaSimple[C0]
  ws.Range( kColProductoR & RenActual & ':' & kColTotalR & RenActual ).Font.FontStyle = 'Negrita'[C0]
  
  // Imprimir totales de gValorCarac1-gValorCarac2-gValorCarac3 
  ws.Range( kColProductoR   & RenActual ).HorizontalAlignment = xlDerecha[C0]
  ws.Range( kColProductoR   & RenActual ).Value = 'Total General: '
  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] 

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

FinFunc

// RPC - ND 1745  Las funciones fProcesaDetalleCarac() y fSumaMovimientos() son
// sustituidas por la nueva función fImprimeProductos() porque esta última 
// funciona con características en desorden usando la hoja del reporteador
// *****************************************************************************
// Función fSumaMovimientos()
// Descripción: Recorre los movimientos de característica de un detalle y los 
//              suma en la variable global gTotalDetalle
// 
// Entradas: 
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 08/01/2003  CILA    N.C. 286       Implementación Inicial
// *****************************************************************************
//DefFunc fSumaMovimientos( atDetalle: Tabla )
//  Local lFecha
//  Local lPrecio, lNeto, lDescuentos, lImpuestos, lTotal
//
//  // Inicializa variables
//  gHayMovtosProducto = False
//  lFecha             = pFechaInicial
//  lPrecio            = 0 
//  lNeto              = 0
//  lDescuentos        = 0
//  lImpuestos         = 0
//  lTotal             = 0
//  
//  // Buscar producto del detalle de características para verificar que se debe incluir en el reporte
//  tProducto.Busca[@Str(atDetalle(cIdProductoPadre);0)]
//  Si tProducto->Encontro = False
//    Retorna
//  FinSi
//
//  // Si el producto no pertenece al rango descartarlo
//  Si tProducto(cCodigoProducto) < pProductoInicial Y tProducto(cCodigoProducto) > pProductoFinal 
//    Retorna
//  FinSi
//
//  // 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 
//    Retorna
//  FinSi
//
//  Si pIdCaracteristica2 != 0 Y tProducto(cIdPadreCaracteristica1) != pIdCaracteristica2 Y tProducto(cIdPadreCaracteristica2) != pIdCaracteristica2 Y tProducto(cIdPadreCaracteristica3) != pIdCaracteristica2 
//    Retorna
//  FinSi
//
//  Si pIdCaracteristica3 != 0 Y tProducto(cIdPadreCaracteristica1) != pIdCaracteristica3 Y tProducto(cIdPadreCaracteristica2) != pIdCaracteristica3 Y tProducto(cIdPadreCaracteristica3) != pIdCaracteristica3 
//    Retorna
//  FinSi
//
//  // Si no se imprimen productos dados de baja
//  Si pEstadoProducto y pEstadoProducto != @Abs(tProducto(cStatusProducto) - 2)
//    Retorna
//  FinSi
//
//  // Si el producto no cumple con las clasificaciones especificadas descartarlo
//  Si !fMiembroDeUnaClase(tProducto; gNumDeClases; gListIdDeClases; 2)
//    Retorna
//  FinSi
//
//  // Buscar Movimientos en el rango de días y sumarlos
//  Mientras lFecha <= pFechaFinal
//
//    // 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
//      gHayMovtosProducto = True
//
//      lNeto = fNetoMovtoPaquete(tMovimiento; tMovtoOwner; tMovtoPaquete; tProducto; tPaqComponente; &lPrecio; &lDescuentos; &lImpuestos; &lTotal)
//
//      // Convertir  lNeto, lDescuentos, lImpuestos y lTotal a la moneda pIdMoneda
//      fConvierteTipoCambio( &lNeto;       tDocumento(cIdMoneda); pIdMoneda; tDocumento(cFecha); tTipoCambio )
//      fConvierteTipoCambio( &lDescuentos; tDocumento(cIdMoneda); pIdMoneda; tDocumento(cFecha); tTipoCambio )
//      fConvierteTipoCambio( &lImpuestos;  tDocumento(cIdMoneda); pIdMoneda; tDocumento(cFecha); tTipoCambio )
//      fConvierteTipoCambio( &lTotal;      tDocumento(cIdMoneda); pIdMoneda; tDocumento(cFecha); tTipoCambio )
//
//      // Sumar el movimiento a los totales del producto      
//      gTotalProducto[kNumColCantidadR]   = @Col(gTotalProducto;kNumColCantidadR)   + tMovimiento(cUnidades)        // Unidades
//      gTotalProducto[kNumColNetoR]       = @Col(gTotalProducto;kNumColNetoR)       + @Col(lNeto;kNumColCero)       // Neto
//      gTotalProducto[kNumColDescuentosR] = @Col(gTotalProducto;kNumColDescuentosR) + @Col(lDescuentos;kNumColCero) // Descuentos
//      gTotalProducto[kNumColImpuestosR]  = @Col(gTotalProducto;kNumColImpuestosR)  + @Col(lImpuestos;kNumColCero)  // Impuestos
//      gTotalProducto[kNumColTotalR]      = @Col(gTotalProducto;kNumColTotalR)      + @Col(lTotal;kNumColCero)      // Total
//
//    FinMientras  // Hay movimientos del día
//
//    lFecha = fFechaSiguiente(lFecha)
//
//  FinMientras  //  Hay días en el rango
//
//FinnFunc
//
//
// *****************************************************************************
// Función fProcesaDetalleCarac()
// Descripción: Procesa un detalle de carac. mandando llamar a la funciones que 
//              suman sus movimientos y despliegan totales por producto.
// 
// Entradas: 
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 08/01/2003  CILA    N.C. 286        Implementación Inicial
// *****************************************************************************
//DefFunc fProcesaDetalleCarac()
//
//  // Si se incluyen todos los detalles de característica, imprimir el actual 
//  Si pImprimirDetalles = kTodos Y gDetalleImpreso = False
//
//    // Imprime Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3
//    fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )
//
//    gDetalleImpreso = True
//  FinSi
//
//  // Si hay cambio de prod Y no es la primera búsqueda Y hay movtos, imprimir totales del prod.
//  Si gIdPdroducto != tDetalle(cIdProductoPadre) Y gEsPrimeraVez = False Y gHayMovtosProducto = True
//
//    // Sólo se incluyen detalles con movtos y no se ha impreso el detalle actual
//    Si pImprimirDetalles = kSoloConMovtos Y gDetalleImpreso = False
//
//      //Imprime Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3
//      fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )
//
//      gDetalleImpreso = True
//    FinSi
//
//    fImprimeTotalesProducto()
//
//  FinSi
//
//  gIdPdroducto = tDetalle(cIdProductoPadre)
//
//  // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
//  fSumaMovimientos( tDetalle )
//
//  gEsPrimeraVez = False
//
//FinFunc
// FIN RPC - ND 1745


// *****************************************************************************
// Función fImprimeProductos()
// Descripción: Calcula usando la hoja del reporteador los totales de cada 
//              producto dentro de una combinación de características en el 
//              reporte concentrado. Sustituye a las funciones 
//              fProcesaDetalleCarac() y fSumaMovimientos()
// 
// Entradas: 
//
// Salidas :
//
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 31/01/2003  PRC     N.D. 1745       Implementación Inicial
// *****************************************************************************
DefFunc fImprimeProductos()
Local  lHayMovimientos

  tProducto.UsaIndice['iCodigoTipo']  // cCodigoProducto+cTipoProducto
  // Recorrer los productos para imprimir los totales de cada uno dentro de la combinación de características
  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
    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

    gTotalProducto = 0
    lHayMovimientos = False

    // Revisar todos los movimientos almacenados en la hoja del reporteador buscando 
    // los que pertenecen a los valorees de característica y a la fecha actual
    lRenglon = 1

    Mientras lRenglon <= gRenglonesHoja
      Si @Col({lRenglon};15) != tProducto(cIdProducto)
        lRenglon = lRenglon + 1
        Continua 
      FinSi
      Si @Col({lRenglon};15) = tProducto(cIdProducto)
        gTotalProducto[kNumColCantidadR]   = @Col(gTotalProducto;kNumColCantidadR)   + @Col({lRenglon};9)
        gTotalProducto[kNumColNetoR]       = @Col(gTotalProducto;kNumColNetoR)       + @Col({lRenglon};11)
        gTotalProducto[kNumColDescuentosR] = @Col(gTotalProducto;kNumColDescuentosR) + @Col({lRenglon};12)
        gTotalProducto[kNumColImpuestosR]  = @Col(gTotalProducto;kNumColImpuestosR)  + @Col({lRenglon};13)
        gTotalProducto[kNumColTotalR]      = @Col(gTotalProducto;kNumColTotalR)      + @Col({lRenglon};14)
        lHayMovimientos = True
      FinSi 
      lRenglon = lRenglon + 1
    FinMientras  // Hay renglones en la hoja electrónica

    Si ( lHayMovimientos O pImprimirDetalles = 0 ) Y gDetalleImpreso = False  
      // Imprime Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3
      fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )
      gDetalleImpreso = True
    FinSi
    Si lHayMovimientos O ( pImprimirProductos = 0 Y gDetalleImpreso )
      fImprimeTotalesProducto()
    FinSi
  FinMientras  // Hay productos en el rango
  tProducto.UsaIndice['']

  // Limpiar hoja del reporteador
  gRenglonesHoja = 0
FinFunc


// *****************************************************************************
// Encabezado del reporte
// 
// Historia de modificaciones
// *****************************************************************************
// Fecha       Nombre  Id.Lotus        Descripción
// -----------------------------------------------------------------------------
// 05/12/2002  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     + Producto     + kColProducto    +
    // +   H     + Cantidad     + kColCantidad    +
    // +   I     + Precio       + kColPrecio      +
    // +   J     + Neto         + kColNeto        +
    // +   K     + Descuentos   + kColDescuentos  +
    // +   L     + Impuestos    + kColImpuestos   +
    // +   M     + 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 'M'
    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 'M'
    ws.Range( kColCantidad & RenActual & ':' & kColTotal & RenActual ).HorizontalAlignment = xlDerecha[C0]
    // Rango de columnas de la 'A' hasta la 'M'
    ws.Range( kColBlanco & RenActual & ':' & kColTotal & RenActual ).Value = '','Fecha','Concepto','Serie','Folio','Almacén','Producto','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 'F' ----------------------------------
    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 'F'
      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 'G'
    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
// -----------------------------------------------------------------------------
// 05/12/2002  CILA    N.C. 286        Implementación Inicial
// 31/01/2003  RPC     N.D. 1745       Incluir variaciones en el orden de las 
//                                     características
// *****************************************************************************

// Contador de renglones en la hoja del reporteador
gRenglonesHoja = 0

// Configura los decimales 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 las combinaciones de valores de características seleccionadas
// *****************************************************************************

// Si se usan las tres características +++++++++++++++++++++++++++++++++++++++++
Si (pIdValoresCarac1 != 0) Y (pIdValoresCarac2 != 0) Y (pIdValoresCarac3 != 0)

  // 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

        Si pTipoReporte = kReporteResumen // -----------------------------------
          gDetalleImpreso = False
        FinSi
// 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 carac1, carac2, carac3
//        Mientras [tDetalle.Busca[@Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
//          Si pTipoReporte = kReporteDetallado // -------------------------------
//            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
//            fAlmacenaMovimientos( tDetalle )
//          SiNo // Reporte Resumen ----------------------------------------------
//            // Procesa el detalle de carac. sumando sus movimientos
//            fProcesaDetalleCarac()
//          FinSi
//        FinMientras // Hay valores de características

        // Recorrer todos los detalles de características que usan la combinación de valores carac1, carac2, carac3
        Mientras [tDetalle.Busca[@Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
          fAlmacenaMovimientos( tDetalle )
        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(gValorCarac1;0) & ':' & @Str(gValorCarac3;0) & ':' & @Str(gValorCarac2;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
          fAlmacenaMovimientos( tDetalle )
        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(gValorCarac2;0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
          fAlmacenaMovimientos( tDetalle )
        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(gValorCarac2;0) & ':' & @Str(gValorCarac3;0) & ':' & @Str(gValorCarac1;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
          fAlmacenaMovimientos( tDetalle )
        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(gValorCarac3;0) & ':' & @Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
          fAlmacenaMovimientos( tDetalle )
        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(gValorCarac3;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac1;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
          fAlmacenaMovimientos( tDetalle )
        FinMientras // Hay valores de características

        Si pTipoReporte = kReporteDetallado // ---------------------------------
          // Recorrer los movimientos almacenados en orden de fechas
          fImprimeMovimientos()
        SiNo // Reporte Resumen ------------------------------------------------
// RPC - ND 1745 Se incluye la nueva función fImprimeProductos() que contiene al siguiente código 
//          // Sólo se incluyen detalles con movtos y no se ha impreso el detalle actual
//          Si pImprimirDetalles = kSoloConMovtos Y gDetalleImpreso = False Y gHayMovtosProducto = True
//
//            //Imprime Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3
//            fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )
//            gDetalleImpreso = True
//          FinSi
//
//          Si gHayMovtosProducto = True
//            //Imprime totales del movimiento
//            fImprimeTotalesProducto()
//          FinSi
          fImprimeProductos()
// FIN RPC -ND 1745
          // Despliega los totales de la combinación de valores de característica
          fImprimeTotalesCarac() 
        FinSi

        // Se mueve a la siguiente caracteristica a procesar
        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 != 0) Y (pIdValoresCarac2 != 0)

    // 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

        Si pTipoReporte = kReporteResumen // -----------------------------------
          gDetalleImpreso = False
        FinSi

// RPC - ND 1745 Cambiar la búsqueda de una combinación de características fija 
// por un barrido de la tabla de detalles buscando los que usan las características 
// actuales. Tiene que ser con un barrido porque no hay forma de buscar las 
// carac 2 y 3 sin tener valor en la carac. 1
//        // Recorrer todos los detalles de características que usan la combinación de valores
//        Mientras [tDetalle.Busca[@Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
//          Si pTipoReporte = kReporteDetallado // -------------------------------
//            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
//            fAlmacenaMovimientos( tDetalle )
//        SiNo // Reporte Resumen ----------------------------------------------
//          // Procesa el detalle de carac. sumando sus movimientos
//          fProcesaDetalleCarac()
//        FinSi
        tDetalle.Busca Primero
        Mientras tDetalle->Encontro
          Si tDetalle(cIdValorCaracteristica1) = gValorCarac1 Y tDetalle(cIdValorCaracteristica2) = gValorCarac2 
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica1) = gValorCarac2 Y tDetalle(cIdValorCaracteristica2) = gValorCarac1
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica2) = gValorCarac1 Y tDetalle(cIdValorCaracteristica3) = gValorCarac2 
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica2) = gValorCarac2 Y tDetalle(cIdValorCaracteristica3) = gValorCarac1
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica1) = gValorCarac1 Y tDetalle(cIdValorCaracteristica3) = gValorCarac2
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica1) = gValorCarac2 Y tDetalle(cIdValorCaracteristica3) = gValorCarac1
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          tDetalle.Busca Siguiente[0]
// FIN RPC - ND 1745 
        FinMientras // Hay valores de características

        Si pTipoReporte = kReporteDetallado // ---------------------------------
          // Recorrer los movimientos almacenados en orden de fechas
          fImprimeMovimientos()
        SiNo // Reporte Resumen ------------------------------------------------
// RPC - ND 1745 Se incluye la nueva función fImprimeProductos() que contiene al siguiente código 
//          // Sólo se incluyen detalles con movtos y no se ha impreso el detalle actual
//          Si pImprimirDetalles = kSoloConMovtos Y gDetalleImpreso = False Y gHayMovtosProducto = True
//
//            //Imprime Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3
//            fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )
//            gDetalleImpreso = True
//          FinSi
//
//          Si gHayMovtosProducto = True
//            //Imprime totales del movimiento
//            fImprimeTotalesProducto()
//          FinSi
          fImprimeProductos()
// FIN RPC -ND 1745
          // Despliega los totales de la combinación de valores de característica
          fImprimeTotalesCarac() 
        FinSi

        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 != 0

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

      Mientras gValorCarac1 != 0

        Si pTipoReporte = kReporteResumen // -----------------------------------
          gDetalleImpreso = False
        FinSi

// RPC - ND 1745 Cambiar la búsqueda de una características fija por un barrido 
// de la tabla de detalles buscando los que usan la característica actual. Tiene
// que ser con un barrido porque no hay forma de buscar la 3 sin tener valores 
// en las carac. 1 y 2
//        // Recorrer todos los detalles de características que usan la combinación de valores
//      Mientras [tDetalle.Busca[@Str(gValorCarac1;0) & ':' & @Str(gValorCarac2;0) & ':' & @Str(gValorCarac3;0)]; tDetalle->Encontro; tDetalle.Busca Siguiente[3]]
//        Si pTipoReporte = kReporteDetallado // -------------------------------
//          // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
//          fAlmacenaMovimientos( tDetalle )
//        SiNo // Reporte Resumen ----------------------------------------------
//          // Procesa el detalle de carac. sumando sus movimientos
//          fProcesaDetalleCarac()
//        FinSi
        tDetalle.Busca Primero
        Mientras tDetalle->Encontro
          Si tDetalle(cIdValorCaracteristica1) = gValorCarac1 
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica2) = gValorCarac1
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          Si tDetalle(cIdValorCaracteristica3) = gValorCarac1 
            // Recorrer y almacenar todos los movimientos del detalle en la hoja del reporteador
            fAlmacenaMovimientos( tDetalle )
          FinSi
          tDetalle.Busca Siguiente[0]
// FIN RPC - ND 1745 
        FinMientras // Hay valores de características

        Si pTipoReporte = kReporteDetallado // ---------------------------------
          // Recorrer los movimientos almacenados en orden de fechas
          fImprimeMovimientos()
        SiNo // Reporte Resumen ------------------------------------------------
// RPC - ND 1745 Se incluye la nueva función fImprimeProductos() que contiene al siguiente código 
//          // Sólo se incluyen detalles con movtos y no se ha impreso el detalle actual
//          Si pImprimirDetalles = kSoloConMovtos Y gDetalleImpreso = False Y gHayMovtosProducto = True
//
//            //Imprime Nombre de los valores de característica gValorCarac1-gValorCarac2-gValorCarac3
//            fImprimeDatosCaracteristicas( gValorCarac1; gValorCarac2; gValorCarac3 )
//            gDetalleImpreso = True
//          FinSi
//
//          Si gHayMovtosProducto = True
//            //Imprime totales del movimiento
//            fImprimeTotalesProducto()
//          FinSi
          fImprimeProductos()
// FIN RPC -ND 1745
          // Despliega los totales de la combinación de valores de característica
          fImprimeTotalesCarac() 
        FinSi

        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

Si pTipoReporte = kReporteDetalle // -------------------------------------------
  // Imprime el total del reporte
  fImprimeTotales()
SiNo  // Reporte Resumen -------------------------------------------------------
  // Imprime el total del reporte
  fImprimeTotalesGeneral()
FinSi


