// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
// KardexExcel.rpt
// Nombre del reporte en el sistema: KardexExcel
//
//  Sistema: AdminPAQ v1.1
// 
//  Este reporte perteneciente al módulo de inventarios, despliega en Excel
//  los movimientos de entrada y salida de productos. Por cada movimiento,
//  se presenta las unidades y el costo.
//
// Elaboró:    Roberto Del Alto Torres
// Fecha:      29 de Octubre de 2001
//
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 24/01/2002   MOFM    SC 24       Se agregó el parámetro pAlmacen y se modifi-
//                                  caron los métodos: fProcesaSinCapas y el 
//                                  cuerpo del reporte
// 15/02/2002   MOFM    SC 24       Se modifica el parámetro pAlmacen para recibir
//                                  un rango de códigos de almacén.
// 19/02/2002   RPC     ND 141      Se agregaron totales en kárdex global
//                                  En kárdex por almacén fallaba el cálculo de  
//                                  la existencia y costo inicial
//                                  En kárdex por almacén ponía los datos del 
//                                  almacén antes de los datos del producto
//                                  En kárdex por almacén el total por producto
//                                  debe incluir la existencia o costo final
// 19/03/2002   CILA    SC 35       Se agrego un nuevo parametro para filtrar los
//                                  los movimientos, Todos, Afectados o Sin Afectar
//                                  Agregando leyendas en el encabezado del reporte. 
// 25/04/2002   FG      ND 361      Se agrego (') al codigo del producto para que 
//                                  cuando empiece con ceros, Excel no se los quite
// 16/05/2002   EGV     ND 390      Se modificaron las funciones:
//                                  - fProcesaPorAlmacen,
//                                  - fImprimeMovimiento,
//                                  - Cuerpo del reporte. (EGV) 
// 21/06/2002   LAP     ND 585      Adición de fExistenciaProductoSinAfectar y
//                                  fCostoProductoSinAfectar para obtener las
//                                  unidades y costo de los movimientos sin
//                                  afectar. Y dependiendo de si el usuario  
//                                  desea ver todos los movimientos, los 
//                                  movimientos afectados o los movimientos sin
//                                  afectar, poder desplegar correctamente la
//                                  existencia o el costo inicial.
//                                  - Cuerpo del reporte
//                                  - fProcesaPorAlmacen
// NOTA: Temporalmente se definen las funciones fExistenciaProductoSinAfectar y
//       fCostoProductoSinAfectar y no en LibInventarios.Rpt ya que algunos
//       reportes no se pueden compilar por que se excede el límite máximo de
//       instrucciones del reporteador.
// 16/07/2002   LAP     ND 884      Al calcular el inventario inicial se deben
//                                  de considerar exclusivamente los movimientos 
//                                  del primer periodo hasta antes de la fecha
//                                  indicada ya que los movimientos a partir de 
//                                  la fecha inicial ya se consideran parte del
//                                  reporte.
//                                  - fExistenciaProductoSinAfectar
//                                  - fCostoProductoSinAfectar
// 26/07/2002   RPC     SC 150      Debido a la SC 150 todos los movtos ahora se
//                                  afectan en línea y se permiten existencias 
//                                  negativas protegiendo al costo. Los movtos 
//                                  sin afectar se consideran erroneos y se 
//                                  siguen imprimiendo con asterisco pero con 
//                                  totales separados. Esta modificación  
//                                  incluye quitar todas las modificaciones  
//                                  efectuadas la ND 585 y una parte de la SC 35
// 11/11/2002   LAP     N.D.1538    Corrección en el congelamiento del Encabezado
//                                  del reporte ya que tomaba un renglón del cuerpo 
//                                  del reporte.
//                                  - Encabezado
//  27/01/2003  LAP     N.D.1377    Los movimientos incompletos de detalles de
//                                  características no se deben de imprimir
//                                  - fProcesaSinCapas
//                                  - fProcesaPorAlmacen
// 08/09/2003   EGV     N.D.2410    Se modificó: fProcesaPorAlmacen. (EGV)
// 30/11/2004   DRdA    N.C.84      Que se calcule e imprima el costo unitario para
//                                  los movimientos de ajuste al inventario.
//                                  - fPonValInvHoja
//                                  - fGetRenAlmHoja
//                                  - fImprimeMovimiento
//                                  - Cuerpo Principal
// 29/04/2005   LAP     N.D.3240    Expresar los importes de los documentos en la moneda 
//                                  del reporte. Considerando que los documentos en moneda 
//                                  base tienen el tipo de cambio de la moneda del cliente 
//                                  a la moneda base. Utilizar fCambiarMonedaDoctoAReporte y
//                                  fCambiarMonedaImporteAReporte de LibAdminPAQ.rpt
// 14/11/2005   HVA     N.D.3484    Al utilizar el filtro "Solo con Movimientos" aparecen los que tienen existencia inicial
// 23/02/2006   HVA     N.D.3868    Se duplican los costos cuando el producto tiene unidadades no convertibles.
// 27/11/2006   LAP     N.D.4355    Totalizar el Inventario Inicial al imprimir por con la opción
//                                  "Solo con Movimientos" (LAP)
//                                  - fProcesaPorAlmacen  
// 15/05/2007   JAAM    N.C.147     Esquema de adicion de unidades de compra y venta  
//  05/02/2008  JENL    N.D.5062    ERROR TARDA 6 MINUTOS AL MOMENTO DE CONVERTIR UN PEDIDO EN FACTURA 
//                                  Se modifica:
//                                  -fProcesaPorAlmacen
//                                  -Cuerpo del reporte
// 18/08/2008   IYPZ   N.D.5266     Se regresa el cambio 5062 a como estaba antes de la 419. 
// 12/11/2008   ELVS   N.C.224      Se deben considerar los movimientos que están con el 
//                                  campo cAfectadoInventario = 2, se agrega marca y leyenda
//                                  de que esos movimientos están en captura.
// 05/02/2009   RPC    S.C.231      Agregar opciones para imprimir por orden de captura
// 05/06/2009   MGCJ   N.D.5848     Agregar la impresión de las características
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


// *****************************************************************************
// Funciones de librería

Incluye LibAdminPAQ.Rpt
Incluye LibInventarios.Rpt


// *****************************************************************************
// Parámetros del reporte:

Parametro pFechaInicial = '20080101'    // Fecha inicial del rango
Parametro pFechaFinal = '20091231'      // 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 pAlmacenInicial = ' '         // Código inicial del almacen
Parametro pAlmacenFinal = ' '           // Código final del almacén
Parametro pImprimirProductos = 1        // Productos a imprimir:
                                        // 0 = Todos
                                        // 1 = Solo productos con movimientos 
Parametro pEstadoProducto = 0           // Incluir productos con estado:
                                        // 0 = Todos
                                        // 1 = Activos
                                        // 2 = Inactivos
Parametro pCaracteristica = 1           // ND. 5848 Por default imprime detalle de caracteristicas
Parametro pUnidad = 0                   // Unidad de medida y peso para expresar el reporte
                                        // 0 = Unidad base del producto
                                        // 1 = Unidad no equivalente del producto
                                        // 2 = Unidad equivalente (ver parámetro pIdUnidad)
                                        // 3 = Unidad de compra
                                        // 4 = Unidad de venta
Parametro pIdUnidad = 0                 // Id de la unidad equivalente
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 pTipoKardex = 0               // 0 = Kárdex global
                                        // 1 = Kárdex por almacén
                                        // 2 = Kárdex global por orden de captura
                                        // 3 = Kárdex por almacén y orden de captura
Parametro pOrdenKardex = 0              // 0 = Kárdex por orden de fecha
                                        // 1 = Kárdex por orden de captura


Si pOrdenKardex = 1
   pTipoKardex = pTipoKardex + 2
FinSi


// Esta sección de acepta para los parámetros es provisional
// Acepta 'Fecha de inicio (aaaammdd):'; pFechaInicial
// Acepta 'Fecha final (aaaammdd):'; pFechaFinal
// Acepta 'Producto inicial (vacío = Todos):'; pProductoInicial
// Acepta 'Producto final (vacío = Todos):'; pProductoFinal

// *****************************************************************************
// Tablas a utilizar e Indices de búsqueda por omisión

UsaEmpresa tEmpresa;'ADMINPAQW'                   // Parámetros

UsaTabla tProducto = tEmpresa['MGW10005']         // Productos
tProducto.Usaindice['iCodigoTipo']                // cCodigoProducto+cTipoProducto

// N.D.1377 Inicio
// Productos identificadores a fin de saber si el producto es un detalle de
//  caracteristicas o no
UsaTabla tDetalleProducto = tEmpresa['MGW10004']  // Productos
tDetalleProducto.Usaindice['']                    // Indice primario: cIdProducto
// N.D.1377 Fin

UsaTabla tDocumento = tEmpresa['MGW10008']        // Documentos
tDocumento.Usaindice['']                          // Indice primario: cIdDocumento

UsaTabla tMovimiento = tEmpresa['MGW10010'] Alias 'Movto'       // Movimientos
tMovimiento.Usaindice['iProductoFechaAfecta']     // cIdProducto+cFecha+cAfectaExistencia

UsaTabla tMovtoOwner = tEmpresa['MGW10010'] Alias 'MovtoOwner'  // Movimientos
tMovtoOwner.Usaindice['']                         // Indice primario: cIdMovimiento

UsaTabla tMovtoSinAfectar = tEmpresa['MGW10010'] Alias 'MovtoSinAfectar'  // Movimientos sin afectar
tMovtoSinAfectar.Usaindice['iProductoDoctoDeAfecFecha']    // cIdProducto+cIdDocumentoDe+cAfectadoInventario+cFecha

UsaTabla tEjercicio = tEmpresa['MGW10031']        // Ejercicios
tEjercicio.Usaindice['cNumeroEjercicio']          // cNumeroEjercicio

UsaTabla tExistencia = tEmpresa['MGW10030']       // Existencia
tExistencia.Usaindice['iProdEjerAlmacenTipo']     // cIdProducto+cIdEjercicio+cIdAlmacen+cTipoExistencia

UsaTabla tCostoHistorico = tEmpresa['MGW10017']   // Costo histórico
tCostoHistorico.Usaindice['iProdAlmacenFecha']    // cIdProducto+cIdAlmacen+cFechaCostoH+cTipoCosto

UsaTabla tMoneda = tEmpresa['MGW10034']           // Monedas
tMoneda.Usaindice['']                             // Indice primario: cIdMoneda

UsaTabla tTipoCambioLib = tEmpresa['MGW10035']       // Tipo de cambio
tTipoCambioLib.Usaindice['iMonedaFecha']             // cIdMoneda+cFecha

UsaTabla tUnidad = tEmpresa['MGW10026']           // Unidades de peso y medida
tUnidad.Usaindice['']                             // Indice primario: cIdUnidad

UsaTabla tEquivalencia = tEmpresa['MGW10027']     // Equivalencia de unidades de peso y medida
tEquivalencia.Usaindice['']                       // Indice primario: cIdUnidad1+cIdUnidad2

UsaTabla tAlmacen = tEmpresa['MGW10003']          // Almacenes
tAlmacen.Usaindice['']                            // Indice primario: cIdAlmacen

UsaTabla tAlmacenRecorrido = tEmpresa['MGW10003'] Alias 'AlmacenRecorrido' //Almacenes
tAlmacenRecorrido.Usaindice['cCodigoAlmacen']     // Indice primario: cIdAlmacen

UsaTabla tConcepto = tEmpresa['MGW10006']         // Concepos de documentos
tConcepto.Usaindice['']                           // Indice primario: cIdConceptoDocumento

UsaTabla tValoresDeClasif = tEmpresa['MGW10020']
tValoresDeClasif.UsaIndice['']                    // Indice primario: cIdValorClasificacion

UsaTabla tParametros = tEmpresa['MGW10000']       // Parámetros de la empresa
tParametros.Usaindice['']                         // Indice primario: cIdEmpresa

// N.D.3240
UsaTabla tClienteProveedor = tEmpresa['MGW10002'] // Clientes/Proveedores
tClienteProveedor.Usaindice['']                   // Indice primario: cIdClienteProveedor

// N.D. 5848
UsaTabla tMovtoCar = tEmpresa['MGW10010'] Alias 'MovtoCar'  // Movimientos
tMovtoCar.Usaindice['iMovtoOw02']                      
UsaTabla tCaracteristicas = tEmpresa['MGW10022'] 
tCaracteristicas.Usaindice['']                           // Indice pr    


// *****************************************************************************
// Definiciones y asumidos globales para el reporte

Columnas 16;1

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

// *****************************************************************************
// Variables de ámbito global:

gIdioma = 0                       // Idioma del reporte
                                  // 0 = Español
                                  // 1 = Inglés
// Las siguientes variables se utilizan en el cuerpo principal del reporte
gPeriodo = 0                      // Numero de período que corresponde a la fecha de inicio del reporte
gIdEjercicio = 0                  // ID del ejercicio que contiene la fecha de inicio del reporte
gUnidad = pUnidad                 // Almacenamiento del parámetro pUnidad
gDescUnidad = ''                  // Descripción de la unidad de medida o peso
gIdUnidad = pIdUnidad             // Descripcion del Identificador de la unidad de medida o peso
gInventarioInicial = 0            // Inventario final
gDatosProducto = 0                // Bandera que indica si los datos del producto ya fueron impresos
gMascarillaProducto = ''          // Mascarilla para el código del producto
gTotalEntradasAlmacen = 0.0       // Total de entradas del producto en un almacén
gTotalSalidasAlmacen = 0.0        // Total de salidas del producto en un almacén
gTotalEntradasProducto = 0.0      // Total de entradas del producto
gTotalSalidasProducto = 0.0       // Total de salidas del producto
gTotalEntradas = 0.0              // Total de entradas de todos los productos en todos los almacenes
gTotalSalidas = 0.0               // Total de salidas de todos los productos en todos los almacenes
gTotal = 0.0                      // Total de existencia o costo total de todos los productos
gInventarioInicialAlmacen = 0     // Inventario incial de una Almacén en específico.
// RPC - SC 150 Nuevas variables globales para totales sin afectar
gTotalEntradasProdSinAfectar = 0  // Total de entradas sin afectar del producto 
gTotalSalidasProdSinAfectar = 0   // Total de salidas sin afectar del producto   
gTotalEntradasAlmSinAfectar = 0   // Total de entradas sin afectar del almacén  
gTotalSalidasAlmSinAfectar = 0    // Total de salidas sin afectar del almacén  
gTotalEntradasSinAfectar = 0      // Total de entradas sin afectar 
gTotalSalidasAfectar = 0          // Total de salidas sin afectar 
// FIN RPC - SC 150 
gRenglonesHoja = 0
// SC 231 
gRenIniProd = 0

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

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

RenActual = 1

// Pone la longitud de cada columna
ws.Columns(1).ColumnWidth = 1.5[C0] //N.C.224
ws.Columns(2).ColumnWidth = 12[C0]
ws.Columns(3).ColumnWidth = 8[C0]
ws.Columns(4).ColumnWidth = 10[C0]
ws.Columns(5).ColumnWidth = 30[C0]
ws.Columns(6).ColumnWidth = 12[C0]
ws.Columns(7).ColumnWidth = 15[C0]
ws.Columns(8).ColumnWidth = 15[C0]
ws.Columns(9).ColumnWidth = 15[C0]
ws.Columns(10).ColumnWidth = 15[C0]
ws.Columns(11).ColumnWidth = 15[C0]
ws.Columns(12).ColumnWidth = 15[C0]
ws.Columns(13).ColumnWidth = 15[C0]
ws.Columns(14).ColumnWidth = 0[C0]

DefFunc fPonValInvHoja(aIdAlmacen;aExistencia;aCosto)
  Local lCiclo

  lCiclo = 0
  Mientras lCiclo < gRenglonesHoja
    Si @Col({lCiclo};0) = aIdAlmacen
      FinCiclo
    FinSi
    lCiclo = lCiclo + 1
  FinMientras
  Si lCiclo = gRenglonesHoja
    {lCiclo} = 0[C1,C2]
    {lCiclo} = @Col(aIdAlmacen;0)[C0]
    gRenglonesHoja = gRenglonesHoja + 1
  FinSi
  {lCiclo} = @Col({lCiclo};1) + @Col(aExistencia;0)[C1]
  {lCiclo} = @Col({lCiclo};2) + @Col(aCosto;0)[C2]
FinFunc

DefFunc fGetRenAlmHoja(aIdAlmacen)
  Local lCiclo

  lCiclo = 0
  Mientras lCiclo < gRenglonesHoja
    Si @Col({lCiclo};0) = aIdAlmacen
      FinCiclo
      //! N.D.4294 En los ciclos Mientras no se permiten instrucciones RETORNA 
      //! ya que WinRep al ejecutar la función se queda trabado
      //! Retorna lCiclo
    FinSi
    lCiclo = lCiclo + 1
  FinMientras
  Retorna lCiclo
FinFunc

// *****************************************************************************
//  fConfiguraDecimales
//
//  Configura el número de decimales de las columnas de importes, basado en
//  en los parámetros de la empresa.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fConfiguraDecimales()
  LOCAL lDigDecimales, lDecs, lFormato

  lDigsDecimales = '0000000000'

  // Busca el registro de la empresa
  tParametros.Busca Primero
  Si tParametros->Encontro // Si lo encontró
    lDecs = @SUBSTR(lDigsDecimales;1;tParametros(cDecimalesUnidades))
    lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
    ws.Columns(7).NumberFormat = lFormato[C0]
    ws.Columns(8).NumberFormat = lFormato[C0]
    ws.Columns(9).NumberFormat = lFormato[C0]

    lDecs = @SUBSTR(lDigsDecimales;1;tParametros(cDecimalesCostos))
    lFormato = '#,##0.' & lDecs & '_);(#,##0.' & lDecs & ')'
    ws.Columns(10).NumberFormat = lFormato[C0]
    ws.Columns(11).NumberFormat = lFormato[C0]
    ws.Columns(12).NumberFormat = lFormato[C0]
    ws.Columns(13).NumberFormat = lFormato[C0]

    gMascarillaProducto = tParametros(cMascarillaProducto)  // mascarilla para el código del producto
  Sino // Si no encontró el registro de la empresa
    [C11,C13,C15].Decimales 2
    ws.Columns(7).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    ws.Columns(8).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    ws.Columns(9).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    ws.Columns(10).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    ws.Columns(11).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    ws.Columns(12).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
    ws.Columns(13).NumberFormat = '#,##0.00_);(#,##0.00)'[C0]
  FinSi
FinFunc


// *****************************************************************************
//  fImprimeDatosProducto
//
//  Esta función imprime los datos del producto (código, nombre, método de 
//  costeo y unidad de medida y peso)
//
//  Parámetros 
//
//  Salidas 
//
//  Historia de Revisiones
// Fecha       Nombre   IDLotus                     Descripcion
// 26/07/2002  RPC      SC 150     Incluir la detección y manejo de los errores
//                                 de existencias negativas y movtos sin afectar
// *****************************************************************************
DefFunc fImprimeDatosProducto(atProducto: Tabla)
Local vImprime, vImprime2, vImprime3, lCodigoEditado, lFechaEditada
Local lFechaSinAfectar, lExistenciaCongelada

  lCodigoEditado = fMascarilla(atProducto(cCodigoProducto); gMascarillaProducto)

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
  ws.Range('A' & RenActual ).Value = 'Producto:'[C0]
  ws.Range('D' & RenActual ).Value = @Chr(39) & @Col(lCodigoEditado;0)[C0]
  
  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
  ws.Range('A' & RenActual ).Value = 'Nombre:'[C0]
  ws.Range('D' & RenActual ).Value = atProducto(cNombreProducto)[C0]

  
  vImprime = 'Método de costeo: '[C0]
  Escoge atProducto(cMetodoCosteo)
    Caso 1
      vImprime = 'Costo Promedio'[C1]
    FinCaso
    Caso 2
      vImprime = 'Costo Promedio por Almacén'[C1]
    FinCaso
    Caso 3
      vImprime = 'Ultimo Costo'[C1]
    FinCaso
    Caso 4
      vImprime = 'UEPS'[C1]
    FinCaso
    Caso 5
      vImprime = 'PEPS'[C1]
    FinCaso
    Caso 6
      vImprime = 'Costo Específico'[C1]
    FinCaso
    Caso 7
      vImprime = 'Costo Estándar'[C1]
    FinCaso
  FinEscoge

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
  ws.Range('A' & RenActual ).Value = @COL(vImprime;0)[C0]
  ws.Range('D' & RenActual ).Value = @COL(vImprime;1)[C0]

  // Imprime unidad de medida y peso
  Escoge pUnidad
      Caso 0 // Unidad base
        tUnidad.Busca[@Str(atProducto(cIdUnidadBase);0)]      
      FinCaso
      Caso 1 // Unidad no equivalente
        tUnidad.Busca[@Str(atProducto(cIdUnidadNoConvertible);0)]        
      FinCaso
      Caso 2 // Unidad equivalente
        tEquivalencia.Busca[atProducto(cIdUnidadBase) & ':' & pIdUnidad]
        Si tEquivalencia->Encontro // Si encontró una equivalencia con la unidad base
          tUnidad.Busca[@Str(pIdUnidad;0)] // Busca la unidad equivalente
        Sino // Si no encontró la unidad equialente, Busca la unidad base
          tUnidad.Busca[@Str(atProducto(cIdUnidadBase);0)]
        FinSi
      FInCaso
    FinEscoge
    Si tUnidad->Encontro y tUnidad(cIdUnidad) != 0 // Encontró el registro de la unidad de medida y peso
      // Guarda la descripción de la unidad en una variable global
      // Así se evita tener que leerla nuevamente al desplegar los totales
      gDescUnidad = tUnidad(cDespliegue) 
      Si gDescUnidad != ''
        vImprime = 'Unidad:'[C0]
        vImprime = @Col(gDescUnidad;0)[C1]

        // Avanza de renglon
        RenActual = RenActual + 1[C0]
        ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
        ws.Range('A' & RenActual ).Value = @COL(vImprime;0)[C0]
        ws.Range('D' & RenActual ).Value = @COL(vImprime;1)[C0]
      FinSi
    Sino
      gDescUnidad = ''
  FinSi

  // RPC - SC 150 Verificar si el producto tiene algún error y sí es así 
  // desplegar en la última columna el número de error
   vImprime = ''

  // Verificar si hay existencias congeladas
  lExistenciaCongelada = fVerificarExistenciaCongelada(atProducto(cIdProducto); 0; tParametros(cIdEjercicioActual); tExistencia)

  // Si no hay existencias congeladas verificar si hay movimientos sin afectar.
  // Cuando hay existencias congeladas no se revisan movimientos sin afectar 
  // porque pueden deberse a dicha existencia congelada
  Si !lExistenciaCongelada
    // Verificar si hay movimientos sin afectar y en que fecha
    lFechaSinAfectar = fVerificarMovtosSinAfectar(atProducto(cIdProducto); tMovtoSinAfectar; tMovtoOwner; tDocumento)
  SiNo  
    vImprime =  'Advertencia:'[C0]
    vImprime =  '*** En proceso de levantamiento de inventario físico'[C1]
    vImprime2 = '*** Se recomienda aplicar el inventario físico'[C1]
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('A' & RenActual ).Value = @COL(vImprime;0)[C0] 
    ws.Range('D' & RenActual ).Value = @COL(vImprime;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('D' & RenActual ).Value = @COL(vImprime2;1)[C0]
  FinSi

  // Si hay error de costos y no hay movtos sin afectar O
  // el error de costos ocurrió antes de los movtos sin afectar
  // entonces se despliega el error de costos  
  Si ( atProducto(cErrorCosto) Y !lFechaSinAfectar) O ( lFechaSinAfectar Y atProducto(cErrorCosto) Y atProducto(cFechaErrorCosto) < lFechaSinAfectar )
    vImprime = 'Error en costos:'[C0]
    Escoge atProducto(cErrorCosto)
      Caso 1
        vImprime =  '*** Captura en desorden de entradas'[C1]
        vImprime2 = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C1]
        vImprime3 = ''
      FinCaso
      Caso 2
        vImprime =  '*** Captura en desorden de salidas'[C1]
        vImprime2 = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C1]
        vImprime3 = ''
      FinCaso
      Caso 3
        vImprime =  '*** Existencias negativas'[C1]
        vImprime2 = '*** Se recomienda registrar las entradas necesarias'[C1]
        vImprime3 = '*** y ejecutar el proceso "Recosteo" para éste producto'[C1]
      FinCaso
      Caso 4
        vImprime =  '*** Series sin movimiento de entrada'[C1]
        vImprime2 = '*** Se recomienda registrar la entrada de las series pendientes'[C1]
        vImprime3 = '*** y ejecutar el proceso "Recosteo" para éste producto'[C1]
      FinCaso
      Caso 5
        vImprime =  '*** Series sin costo'[C1]
        vImprime2 = '*** Se recomienda ejecutar el proceso "Recosteo" para éste producto'[C1]
        vImprime3 = ''
      FinCaso
    FinEscoge
    lFechaEditada = fFormateaFecha(atProducto(cFechaErrorCosto); gIdioma)
    vImprime = @Col(vImprime;1) & ' a partir del ' & @Col(lFechaEditada;0)[C1]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('A' & RenActual ).Value = @COL(vImprime;0)[C0] 
    ws.Range('D' & RenActual ).Value = @COL(vImprime;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('D' & RenActual ).Value = @COL(vImprime2;1)[C0]

    // Avanza de renglon
    Si vImprime3 
      RenActual = RenActual + 1[C0]
      ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
      ws.Range('D' & RenActual ).Value = @COL(vImprime3;1)[C0]
    FinSi
  FinSi  // Hay error de costos

  // Si hay movtos sin afectar y no hay errores de costos O
  // los movtos sin afectar ocurrieron antes del error de costos
  // entonces se despliega el error de movtos sin afectar
  Si ( lFechaSinAfectar Y !atProducto(cErrorCosto) ) O ( lFechaSinAfectar Y atProducto(cErrorCosto) Y lFechaSinAfectar <= atProducto(cFechaErrorCosto) )
    vImprime = 'Error en costos:'[C0]
    vImprime = '*** Movimientos sin afectar'[C1]
    lFechaEditada = fFormateaFecha(lFechaSinAfectar; gIdioma)
    vImprime = @Col(vImprime;1) & ' a partir del ' & @Col(lFechaEditada;0)[C1]
    vImprime2 = '*** Se recomienda consultar el reporte "Movimientos sin Afectar"'[C1]
    vImprime3 = '*** y ejecutar el proceso "Recosteo" para éste producto'[C1]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('A' & RenActual ).Value = @COL(vImprime;0)[C0] 
    ws.Range('D' & RenActual ).Value = @COL(vImprime;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('D' & RenActual ).Value = @COL(vImprime2;1)[C0]

    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('D' & RenActual ).Value = @COL(vImprime3;1)[C0]
  FinSi  // Hay error de movimientos sin afectar
  // FIN RPC - SC 150

  // Modifica la variable global que indica que los datos del producto ya fueron impresos
  gDatosProducto = 1
FinFunc

// *****************************************************************************
//  fImprimeDatosAlmacen
//
// Esta función imprime los datos del almacén
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeDatosAlmacen( )
  Local lIdAlmacen

  lIdAlmacen = tAlmacenRecorrido(cIdAlmacen)  
  Si lIdAlmacen != 0
    lCodigoEditado = fMascarilla(tAlmacenRecorrido(cCodigoAlmacen); tParametros(cMascarillaAlmacen))
    // Avanza de renglon
    RenActual = RenActual + 2[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('A' & RenActual ).Value = 'Almacén:'[C0]
    ws.Range('D' & RenActual ).Value = @Col(lCodigoEditado;0)[C0]
  
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    ws.Range('A' & RenActual & ':D' & RenActual).Font.FontStyle = 'Negrita'[C0]
    ws.Range('A' & RenActual ).Value = 'Nombre:'[C0]
    ws.Range('D' & RenActual ).Value = tAlmacenRecorrido(cNombreAlmacen)[C0]
  FinSi
FinFunc


// *****************************************************************************
//  fImprimeInventarioInicial
//
// Esta función imprime los datos del inventario inicial del reporte.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 05/02/2009   RPC     SC 231      Guardar el renglón en que se imprimió la 
//                                  existencia inicial en una variable global 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeInventarioInicial(aInventarioInicial)

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlBordeInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlBordeSuperior).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlBordeIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlBordeDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Font.FontStyle = 'Negrita'[C0]    

  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlBordeInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlBordeSuperior).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlBordeIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlBordeDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]    

  ws.Range('G' & RenActual).Value = 'Inventario Inicial:'[C0]
  ws.Range('I' & RenActual).Value = @COL(aInventarioInicial;0)[C0]

  ws.Range('K' & RenActual).Value = 'Inventario Inicial:'[C0]
  ws.Range('M' & RenActual).Value = @COL(aInventarioInicial;1)[C0]

  ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]

  // SC 231
  gRenIniProd = RenActual[C0]
FinFunc


// *****************************************************************************
//  fBuscaRenglon
//
//  Usa una búsqueda binaria no recursiva para localizar el renglón en que un 
//  movimiento en desorden se debe insertar. Usada únicamente cuando se imprime 
//  por orden de captura.
//
//  Parámetros aIdMovimiento - Id del movimiento
//
//  Salidas Renglón en que debe insertarse el movimiento
// *****************************************************************************
DefFunc fBuscaRenglon(aIdMovimiento)
Local lPosIni, lPosFin, lCentro
  
  lPosIni = gRenIniProd + 1
  lPosFin = RenActual

  Mientras True
    lCentro = @Int((lPosIni + lPosFin) / 2)

    // Si el Id se debe insertar entre dos remglones continuos
    Si aIdMovimiento > ws.Range('N' & (lCentro-1)).Value Y aIdMovimiento < ws.Range('N' & lCentro).Value
      Retorna lCentro
    FinSi

    Si aIdMovimiento < ws.Range('N' & lCentro).Value 
      lPosFin = lCentro - 1
    SiNo
      lPosIni = lCentro + 1
    FinSi

    // Si ya no hay más renglones en que buscar
    Si lCentro = lPosIni Y lCentro = lPosFin
      Retorna lCentro
    FinSi
  FinMientras
FinFunc

// ***********************************************************************************
// fBuscaCaracteristicas
// Esta función busca las características de un detalle e imprime concatenado
// las hasta tres abreviaturas
// ************************************************************************************
DEFFUNC fBuscaCaracteristicas(pIdProdu01; atDetalle:Tabla; atCaracteristicas: Tabla)
   LOCAL lRegreso
   lRegreso = ''
   atDetalle.BUSCA[@STR(pIdProdu01;0)]
   SI atDetalle->ENCONTRO
      SI atDetalle(cIdValor01) != 0
         atCaracteristicas.BUSCA[@STR(atDetalle(cIdValor01);0)]
         SI atCaracteristicas->ENCONTRO
            lRegreso = lRegreso & atCaracteristicas(cNemoCar01)
         FINSI
      FINSI
      SI atDetalle(cIdValor02) != 0
         atCaracteristicas.BUSCA[@STR(atDetalle(cIdValor02);0)]
         SI atCaracteristicas->ENCONTRO
            lRegreso = lRegreso & '-' & atCaracteristicas(cNemoCar01)
         FINSI
      FINSI
      SI atDetalle(cIdValor03) != 0
         atCaracteristicas.BUSCA[@STR(atDetalle(cIdValor03);0)]
         SI atCaracteristicas->ENCONTRO
            lRegreso = lRegreso & '-' & atCaracteristicas(cNemoCar01)
         FINSI
      FINSI
   FINSI

   RETORNA lRegreso
FINFUNC

// *****************************************************************************
//  fImprimeMovimiento
//
// Esta función imprime los datos de cada movimiento de entrada o salida
//  que se incluye en el reporte.
//
//  Parámetros 
//
//  Salidas
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 13/05/2002   EGV     ND 390      Cuando se imprime la existencia, ésta se
//                                  hace en base al atributo global
//                                  gInventarioInicialAlmacen y no en base al
//                                  atributo gInventarioInicial.
// 26/07/2002   RPC     SC 150      No sumar los movimientos sin afectar a los
//                                  totales
// 05/02/2009   RPC     SC 231      Imprimir los movimientos por orden de Id 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeMovimiento(atProducto: Tabla; atMovimiento: Tabla; aCostoExistencia)
  Local lFechaEditada, lIdDocumento, lInvInicial, lRenAlm, lRenMovto


  // lee el documento del movimiento
  Si atMovimiento(cIdDocumento)
    tDocumento.Busca[@Str(atMovimiento(cIdDocumento);0)]
  Sino // es un movimiento oculto
    // Busca el ID del documento en el movimiento owner
    lIdDocumento = fIdDocumentoMovtoOwner(atMovimiento; tMovtoOwner) 
    tDocumento.Busca[@Str(lIdDocumento;0)]
  FinSi

  Si tDocumento->Encontro
    Si tDocumento(cCancelado) = 1   // Esta cancelado??? 
      Retorna                     // No se imprime
    Finsi
  Finsi

  // Antes de imprimir el movimento, verifica si ya se imprimieron los datos del producto
  Si !gDatosProducto // Si no se han impreso
    // Imprime los datos del producto
    fImprimeDatosProducto(atProducto)
    // y el inventario inicial
    fImprimeInventarioInicial(gInventarioInicial)
  FinSi

  // SC 231 Si es kárdex global o por almacén (ordenadom por fecha)
  Si pTipoKardex < 2
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    lRenMovto = RenActual[C0]

  // Si es kárdex en orden de captura
  SiNo
    // Escribir en el renglón adecuado el movimiento. El renglón adecuado se decide
    // comparando el Id con los de los movimientos ya escritos. Si el Id del 
    // movimiento actual es menor al de uno ya impreso, se inserta un nuevo renglón 
    // (desplazando el resto del reporte hacia abajo) y se escribe el movimiento en 
    // dicho renglón
  
    // Es el primer movimiento del producto, siempre imprimirlo en el renglón actaul
    Si gRenIniProd = RenActual
      // Avanza de renglon
      RenActual = RenActual + 1[C0]
      lRenMovto = RenActual[C0]
  
    // No es el primer movimiento del producto, buscar en que renglón se debe imprimir
    SiNo
      // Si el Id del movto actual ya es mayor al del último movimiento, imprimirlo en 
      // el renglón siguiente sin verificar el resto de los movimientos
      Si atMovimiento(cIdMovimiento) > ws.Range('N' & RenActual).Value
        lRenMovto = RenActual + 1
      SiNo
      	// N.D.8640 ALRH
        lRenMovto = fBuscaRenglon(atMovimiento(cIdMovimiento)) + 1
        ws.Rows(lRenMovto & ':' & lRenMovto).Select
        Excel.Selection.Insert(xlAbajo)

        // OJO ¿Señalar los movimientos en desorden?
        // ws.Range('A' & lRenMovto).Value = '3' 
        // ws.Range('A' & lRenMovto & ':M' & lRenMovto).Interior.ColorIndex = 36[C0]
        ws.Range('A' & lRenMovto & ':M' & lRenMovto).Font.Bold = False[C0]

        // Ajustar las fórmulas de los totales del movimiento desplazado hacia abajo
        ws.Range('I' & (lRenMovto+1)).Value = '=I' & lRenMovto & '+G' & (lRenMovto+1) & '-H' & (lRenMovto+1)[C0]
        ws.Range('M' & (lRenMovto+1)).Value = '=M' & lRenMovto & '+K' & (lRenMovto+1) & '-L' & (lRenMovto+1)[C0]

//        Búsqueda secuencial del renglón donde se imprime un movimiento
//        Mientras[lRenMovto = (gRenIniProd+1); lRenMovto <= RenActual; lRenMovto = lRenMovto + 1]
//          // Si un movimiento impreso tiene un Id mayor (hay desorden), insertar un renglón e imprimir el movimiento
//          Si atMovimiento(cIdMovimiento) < ws.Range('N' & lRenMovto).Value
//            ws.Rows(lRenMovto & ':' & lRenMovto).Select
//            Excel.Selection.Insert(xlAbajo)
//    
//            // OJO ¿Señalar los movimientos en desorden?
//            // ws.Range('A' & lRenMovto).Value = '3' 
//            // ws.Range('A' & lRenMovto & ':M' & lRenMovto).Interior.ColorIndex = 36[C0]
//            ws.Range('A' & lRenMovto & ':M' & lRenMovto).Font.Bold = False[C0]
//    
//            // Ajustar las fórmulas de los totales del movimiento desplazado hacia abajo
//            ws.Range('I' & (lRenMovto+1)).Value = '=I' & lRenMovto & '+G' & (lRenMovto+1) & '-H' & (lRenMovto+1)[C0]
//            ws.Range('M' & (lRenMovto+1)).Value = '=M' & lRenMovto & '+K' & (lRenMovto+1) & '-L' & (lRenMovto+1)[C0]
//            FinCiclo
//          FinSi
//        FinMientras
      FinSi

      // Avanza de renglon
      RenActual = RenActual + 1[C0]
    FinSi
  FinSi  // FIN SC 231

  ws.Range('A' & lRenMovto & ':M' & lRenMovto).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('A' & lRenMovto & ':M' & lRenMovto).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]

  // CILA - SC 35
  // Asterisco e Itálicas para movimientos sin afectar  
  Si atMovimiento(cAfectadoInventario) = 0
    ws.Range('A' & lRenMovto & ':M' & lRenMovto).Font.FontStyle = 'Cursiva'[C0]
    ws.Range('A' & lRenMovto).Value = '1' 
  FinSi 
  // Fin CILA - SC 35

  // Fecha del movimiento
  lFechaEditada = fFormateaFecha(atMovimiento(cFecha); gIdioma)
  ws.Range('B' & lRenMovto).Value = @CHR(39) & lFechaEditada[C0]
 
  Si tDocumento->Encontro
    // Serie
    ws.Range('C' & lRenMovto).Value = tDocumento(cSerieDocumento)[C0]
    // Folio
    ws.Range('D' & lRenMovto).Value = tDocumento(cFolio)[C0]
    // lee el concepto del documento
    tConcepto.Busca[@Str(tDocumento(cIdConceptoDocumento);0)]
    Si tConcepto->Encontro
      vImprime = tConcepto(cNombreConcepto)[C6]
      ws.Range('E' & lRenMovto).Value = tConcepto(cNombreConcepto)[C0]
    FinSi
  FinSi

  // Almacen
  tAlmacen.Busca[@Str(atMovimiento(cIdAlmacen);0)]
  Si tAlmacen->Encontro
    ws.Range('F' & lRenMovto).HorizontalAlignment = xlCentro[C0]
    ws.Range('F' & lRenMovto).Value = tAlmacen(cCodigoAlmacen)[C0]
  FinSI

  Si atMovimiento(cAfectaExistencia) = 1 // Entradas
     ws.Range('G' & lRenMovto).Value = @Col(aCostoExistencia;0)[C0]
     ws.Range('K' & lRenMovto).Value = @Col(aCostoExistencia;1)[C0]
    // RPC - SC 150 Si el movimiento esta afectado sumarlo a los totales
    //N.C.224 Considera los movimientos afectados en costos (1) y afectados en inventario (2)
    //Se deben considerar las unidades que afectaron el inventario 
    //aunque todavía no se afecte el costo, esto sucede cuando todavía se tienen 
    //movimientos en captura.    
    Si atMovimiento(cAfectadoInventario) = 1 o atMovimiento(cAfectadoInventario) = 2
      // acumula en el total de entradas del producto en el almacén
      gTotalEntradasAlmacen = @COL(gTotalEntradasAlmacen;0) + @COL(aCostoExistencia;0)[C0]
      gTotalEntradasAlmacen = @COL(gTotalEntradasAlmacen;1) + @COL(aCostoExistencia;1)[C1]
      fPonValInvHoja(atMovimiento(cIdAlmacen);@COL(aCostoExistencia;0);@COL(aCostoExistencia;1))
      // acumula en el total de entradas del producto
      gTotalEntradasProducto = @COL(gTotalEntradasProducto;0) + @COL(aCostoExistencia;0)[C0]
      gTotalEntradasProducto = @COL(gTotalEntradasProducto;1) + @COL(aCostoExistencia;1)[C1]
      //N.C.224 Debe marcar con una leyenda el movimiento que está siendo capturado en el momento
      Si atMovimiento(cAfectadoInventario) = 2
      	ws.Range('A' & lRenMovto).Value = '2'[C0]
      FinSi	

    SiNo  // Si el movto no esta afectado sumarlo a los totales sin afectar
      // acumula en el total de entradas sin afectar del producto en el almacén
      gTotalEntradasAlmSinAfectar = @COL(gTotalEntradasAlmSinAfectar;0) + @COL(aCostoExistencia;0)[C0] 
      gTotalEntradasAlmSinAfectar = @COL(gTotalEntradasAlmSinAfectar;1) + @COL(aCostoExistencia;1)[C1] 
      // acumula en el total de entradas sin afectar del producto
      gTotalEntradasProdSinAfectar = @COL(gTotalEntradasProdSinAfectar;0) + @COL(aCostoExistencia;0)[C0] 
      gTotalEntradasProdSinAfectar = @COL(gTotalEntradasProdSinAfectar;1) + @COL(aCostoExistencia;1)[C1] 
    FinSi  // Si el movimiento esta afectado
    // FIN RPC - SC 150
  SiNo  // Salidas
    ws.Range('H' & lRenMovto).Value = @Col(aCostoExistencia;0)[C0]
    ws.Range('L' & lRenMovto).Value = @Col(aCostoExistencia;1)[C0]
    // RPC - SC 150 Si el movimiento esta afectado sumarlo a los totales
    //N.C.224
    Si atMovimiento(cAfectadoInventario) = 1 o atMovimiento(cAfectadoInventario) = 2
      // acumula en el total de salidas del producto
      gTotalSalidasAlmacen = @COL(gTotalSalidasAlmacen;0) + @COL(aCostoExistencia;0)[C0]
      gTotalSalidasAlmacen = @COL(gTotalSalidasAlmacen;1) + @COL(aCostoExistencia;1)[C1]
      fPonValInvHoja(atMovimiento(cIdAlmacen);-@COL(aCostoExistencia;0);-@COL(aCostoExistencia;1))
      // acumula en el total de entradas del producto
      gTotalSalidasProducto = @COL(gTotalSalidasProducto;0) + @COL(aCostoExistencia;0)[C0]
      gTotalSalidasProducto = @COL(gTotalSalidasProducto;1) + @COL(aCostoExistencia;1)[C1]
      //N.C.224 Debe marcar con una leyenda el movimiento que está siendo capturado en el momento
      Si atMovimiento(cAfectadoInventario) = 2					
      	ws.Range('A' & lRenMovto).Value = '2'[C0]    	
      FinSi      
    SiNo  // Si el movto no esta afectado sumarlo a los totales sin afectar
      // acumula en el total de entradas sin afectar del producto en el almacén
      gTotalSalidasAlmSinAfectar = @COL(gTotalSalidasAlmSinAfectar;0) + @COL(aCostoExistencia;0)[C0] 
      gTotalSalidasAlmSinAfectar = @COL(gTotalSalidasAlmSinAfectar;1) + @COL(aCostoExistencia;1)[C1] 
      // acumula en el total de entradas sin afectar del producto
      gTotalSalidasProdSinAfectar = @COL(gTotalSalidasProdSinAfectar;0) + @COL(aCostoExistencia;0)[C0] 
      gTotalSalidasProdSinAfectar = @COL(gTotalSalidasProdSinAfectar;1) + @COL(aCostoExistencia;1)[C1] 
    FinSi  // Si el movimiento esta afectado
    // FIN RPC - SC 150
  FinSi  // Si el movimiento es entrada o salida

  // Total
  // Kardex Global o por almacen  
  Si pTipoKardex < 2  
    Si pTipoKardex = 0 // GLOBAL
        ws.Range('I' & lRenMovto).Value = @Col(gInventarioInicialAlmacen;0)+@Col(gTotalEntradasProducto;0)-@Col(gTotalSalidasProducto;0)[C0]
		Si atProducto(cMetodoCosteo) = 7 Y atMovimiento(cIdDocumentoDe) = 5 //N.D. 8503
			ws.Range('J' & lRenMovto).Value = atProducto(cCostoEstandar)[C0]
		SiNo
			ws.Range('J' & lRenMovto).Value = @Col(aCostoExistencia;1) / @Col(aCostoExistencia;0)[C0]
		FinSi
        ws.Range('M' & lRenMovto).Value = @Col(gInventarioInicialAlmacen;1)+@Col(gTotalEntradasProducto;1)-@Col(gTotalSalidasProducto;1)[C0]
    SiNo  // Si es kárdex por almacén
        ws.Range('I' & lRenMovto).Value = @Col(gInventarioInicialAlmacen;0)+@Col(gTotalEntradasAlmacen;0)-@Col(gTotalSalidasAlmacen;0)[C0]
        ws.Range('J' & lRenMovto).Value = @Col(aCostoExistencia;1) / @Col(aCostoExistencia;0)[C0]
        ws.Range('M' & lRenMovto).Value = @Col(gInventarioInicialAlmacen;1)+@Col(gTotalEntradasAlmacen;1)-@Col(gTotalSalidasAlmacen;1)[C0]
    FinSi
  SINO
  Si pTipoKardex = 0 O pTipoKardex = 2 // Si es kárdex global
    ws.Range('I' & lRenMovto).Value = '=I' & (lRenMovto-1) & '+G' & lRenMovto & '-H' & lRenMovto[C0] //SC 231 @Col(gInventarioInicialAlmacen;0)+@Col(gTotalEntradasProducto;0)-@Col(gTotalSalidasProducto;0)[C0]
    ws.Range('J' & lRenMovto).Value = @Col(aCostoExistencia;1) / @Col(aCostoExistencia;0)[C0]
    ws.Range('M' & lRenMovto).Value = '=M' & (lRenMovto-1) & '+K' & lRenMovto & '-L' & lRenMovto[C0] //SC 231 @Col(gInventarioInicialAlmacen;1)+@Col(gTotalEntradasProducto;1)-@Col(gTotalSalidasProducto;1)[C0]
  SiNo  // Si es kárdex por almacén
    ws.Range('I' & lRenMovto).Value = '=I' & (lRenMovto-1) & '+G' & lRenMovto & '-H' & lRenMovto[C0] //SC 231 @Col(gInventarioInicialAlmacen;0)+@Col(gTotalEntradasAlmacen;0)-@Col(gTotalSalidasAlmacen;0)[C0]
    ws.Range('J' & lRenMovto).Value = @Col(aCostoExistencia;1) / @Col(aCostoExistencia;0)[C0]
    ws.Range('M' & lRenMovto).Value = '=M' & (lRenMovto-1) & '+K' & lRenMovto & '-L' & lRenMovto[C0] //SC 231 @Col(gInventarioInicialAlmacen;1)+@Col(gTotalEntradasAlmacen;1)-@Col(gTotalSalidasAlmacen;1)[C0]
  FinSi
  FINSI  
  // SC 231
  ws.Range('N' & lRenMovto).Value = atMovimiento(cIdMovimiento)[C0]

  // N.D. 5848 
  SI pCaracteristica = 1 
   // CAMBIO MGCJ 
   Si atMovimiento(cIdMovto01) != 0 Y atMovimiento(cMovtoOc01) != 2
      // Entonces busca los detalles de características partiendo del cIdMovtoOwner de dicho movimiento
      lIdMovimiento = atMovimiento(cIdMovto01)
   Sino // Sino, busca los detalles de características de la forma ordinaria
      lIdMovimiento = atMovimiento(cIdMovimiento)
   FinSi
   RenActual = lRenMovto
   // Imprime el detalle de caracteristicas
   Mientras [ tMovtoCar.Busca[@STR(lIdMovimiento;0)]; tMovtoCar->Encontro; tMovtoCar.Busca Siguiente[1] ]                
      //ws.Range('A' & lRenMovto & ':M' & lRenMovto).Borders(xlArriba).LineStyle = xlLineaSimple[C0]
      //ws.Range('A' & lRenMovto & ':M' & lRenMovto).Borders(xlAbajo).LineStyle = xlLineaSimple[C0]

      SI tMovtoCar(ctipotra01) = 4
         // CAMBIO MGCJ
         Si tMovtoCar(cAfectaE01) = 0
		      Continua
	   	FinSi
         // CAMBIO MGCJ
         Si tMOvtoCar(cIdAlmacen) != tAlmacen(cIdAlmacen)
            Continua
         FINSI
         RenActual = RenActual + 1[c0]
         ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
         ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
         ws.Range('A' & RenActual & ':M' & RenActual).Font.Size = 9[C0]
         ws.Range('A' & RenActual & ':M' & RenActual).Font.FontStyle = 'Cursiva'[C0]               
         ws.Range('F' & RenActual).HorizontalAlignment = xlCentro[C0]
         ws.Range('F' & RenActual).Value = fBuscaCaracteristicas(tMovtoCar(cIdProdu01); tDetalleProducto; tCaracteristicas)[C0]
         SI atMovimiento(cAfectaE01) = 1
            ws.Range('G' & RenActual).Value = tMovtoCar(cUnidades)[C0]
         SINO
            ws.Range('H' & RenActual).Value = tMovtoCar(cUnidades)[C0]   
         FINSI   
     FINSI
   FinMientras
   //RenActual = lRenMovto[C0]          
  FINSI 
  // N.D.4576 Respetar el costo unitario del movimiento
  //!Si ws.Range('J' & lRenMovto).Value = 0
  //!  lInvInicial = fExistenciaInicialProducto(tProducto(cIdProducto); atMovimiento(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)[C0]
  //!  Si tProducto(cMetodoCosteo) = 7
  //!    lInvInicial = @Col(lInvInicial;0) * tProducto(cCostoEstandar)[C1]
  //!  Sino
  //!    lInvInicial = fCostoInicialProducto(tProducto(cIdProducto); atMovimiento(cIdAlmacen); pFechaInicial; gIdEjercicio; gPeriodo; tProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambioLib; pIdMoneda)[C1]
  //!  FinSi
  //!  lRenAlm = fGetRenAlmHoja(atMovimiento(cIdAlmacen))
  //!  Si lRenAlm < gRenglonesHoja
  //!    lInvInicial = @Col(lInvInicial;0) + @Col({lRenAlm};1)[C0]
  //!    lInvInicial = @Col(lInvInicial;1) + @Col({lRenAlm};2)[C1]
  //!    ws.Range('J' & lRenMovto).Value = @Col(lInvInicial;1) / @Col(lInvInicial;0)[C0]
  //!  FinSi
  //!FinSi

FinFunc


// *****************************************************************************
//  fImprimeTotales
//
// Esta función imprime los totales por producto.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 19/02/2002   RPC     ND 141    En kárdex por almacén agregar total de 
///                               existencia y costo
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeTotales(aInvInicial; aEntradas; aSalidas; aDescUnidad; aMensaje)
Local lMensajeSinAfectar

  // RPC - SC 150 Si se despliega el total sin afectar cambia el mensaje
  Si aMensaje 
    lMensajeSinAfectar = ''
  SiNo
    lMensajeSinAfectar = ' Sin Afectar'
  FinSi
  // FIN RPC - SC 150 

  // Avanza de renglon
  Si pTipoKardex = 0 O pTipoKardex = 2 // Si el reporte es global
    RenActual = RenActual + 1[C0]
    Si aMensaje
      ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
    FinSi
    ws.Range('G' & RenActual & ':H' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':H' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':H' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':L' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':L' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':l' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('E' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]    
    Si aDescUnidad != '' // Si la descripción de la unidad no está vacía
      ws.Range('E' & RenActual & ':F' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
      ws.Range('E' & RenActual).Value = 'Total' & lMensajeSinAfectar & ' en ' & @Col(aDescUnidad;0) & ':'[C0]
    SiNo
      ws.Range('F' & RenActual).Value = 'Total' & lMensajeSinAfectar & ':'[C0]
    Finsi
    ws.Range('J' & RenActual).HorizontalAlignment = xlCentro[C0]
    ws.Range('J' & RenActual).Value = 'Total' & lMensajeSinAfectar & ':'[C0]

    ws.Range('G' & RenActual).Value = @Col(aEntradas;0)[C0]
    ws.Range('H' & RenActual).Value = @Col(aSalidas;0)[C0]

    ws.Range('K' & RenActual).Value = @Col(aEntradas;1)[C0]
    ws.Range('L' & RenActual).Value = @Col(aSalidas;1)[C0]

  Sino   // Si el reporte es por almacén
    RenActual = RenActual + 1[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('E' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]    

    ws.Range('E' & RenActual & ':F' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('E' & RenActual).Value = 'Total' & lMensajeSinAfectar & ' del Producto :'[C0]
 
    ws.Range('G' & RenActual).Value = @Col(aEntradas;0)[C0]
    ws.Range('H' & RenActual).Value = @Col(aSalidas;0)[C0]
    ws.Range('I' & RenActual).Value = @Col(aInvInicial;0) + @Col(aEntradas;0) - @Col(aSalidas;0)[C0]

    ws.Range('K' & RenActual).Value = @Col(aEntradas;1)[C0]
    ws.Range('L' & RenActual).Value = @Col(aSalidas;1)[C0]
    ws.Range('M' & RenActual).Value = @Col(aInvInicial;1) + @Col(aEntradas;1) - @Col(aSalidas;1)[C0]
  FinSi
FinFunc

// *****************************************************************************
//  fImprimeTotalesPorAlmacen
//
// Esta función imprime los totales por almacen
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeTotalesPorAlmacen(aEntradas; aSalidas; aMensaje)
Local lMensajeSinAfectar

  // RPC - SC 150 Si se despliega el total sin afectar cambia el mensaje
  Si aMensaje 
    lMensajeSinAfectar = ''
  SiNo
    lMensajeSinAfectar = ' Sin Afectar'
  FinSi
  // FIN RPC - SC 150 

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  Si aMensaje
    ws.Range('A' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
  FinSi
  ws.Range('G' & RenActual & ':H' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':H' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':H' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':L' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':L' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':L' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('E' & RenActual & ':L' & RenActual).Font.FontStyle = 'Negrita'[C0]    

  ws.Range('E' & RenActual & ':F' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
  ws.Range('E' & RenActual).Value = 'Total' & lMensajeSinAfectar & ' del Almacén :'[C0]
 
  ws.Range('G' & RenActual).Value = @Col(aEntradas;0)[C0]
  ws.Range('H' & RenActual).Value = @Col(aSalidas;0)[C0]

  ws.Range('K' & RenActual).Value = @Col(aEntradas;1)[C0]
  ws.Range('L' & RenActual).Value = @Col(aSalidas;1)[C0] 
  
FinFunc

// *****************************************************************************
//  fImprimeTotalesGenerales
//
// Esta función imprime los totales generales cuando se trata de los reportes
// por almacén
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 19/02/2002   RPC     ND 141    Se agregan totales al kárdex glolal
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fImprimeTotalesGenerales(aEntradas; aSalidas; aTotal; aMensaje)
Local vImprime, lMensajeSinAfectar

  // RPC - SC 150 Si se despliega el total sin afectar cambia el mensaje
  Si aMensaje 
    lMensajeSinAfectar = ''
  SiNo
    lMensajeSinAfectar = ' Sin Afectar'
  FinSi
  // FIN RPC - SC 150 

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0] 
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
  ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  ws.Range('E' & RenActual & ':M' & RenActual).Font.FontStyle = 'Negrita'[C0]    

  ws.Range('E' & RenActual & ':F' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
  ws.Range('E' & RenActual).Value = 'Total General' & lMensajeSinAfectar & ':'[C0]
 
  ws.Range('G' & RenActual).Value = @Col(aEntradas;0)[C0]
  ws.Range('H' & RenActual).Value = @Col(aSalidas;0)[C0]
  ws.Range('I' & RenActual).Value = @Col(aTotal;0)[C0]

  ws.Range('K' & RenActual).Value = @Col(aEntradas;1)[C0]
  ws.Range('L' & RenActual).Value = @Col(aSalidas;1)[C0]
  ws.Range('M' & RenActual).Value = @Col(aTotal;1)[C0]

FinFunc

// *****************************************************************************
//  fProcesaSinCapas
//
//  Esta función lee y procesa los movimientos de entrada y salida cuando el
//  método de costeo es diferente de UEPS o PEPS, es decir, sin capas.
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 24/01/2002   MOFM    SC 24       La búsqueda sobre tMovimiento  cambia depen-
//                                  diendo del almacén seleccionado.               
// 15/02/2002   MOFM    SC 24       Se modifica para realizar la búsqueda en base
//                                  al rango de almacenes
// 19/03/2002   CILA    SC 35       Se agrego la validación para mostrar los todos
//                                  los movimientos, o solo los afectados o solo 
//                                  los que no estan afectados.
//  26/07/2002  RPC     SC 150      Discriminar todos los movtos sin afectar
//  27/01/2003  LAP     N.D.1377    Los movimientos incompletos de detalles de
//                                  características no se deben de imprimir
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fProcesaSinCapas(atProducto: Tabla)
Local lCostoExistencia, lFecha
Local lAlmacen
Local lIdDocumento, lIdMonedaCliente, lTipoCambioDocumento

  // Inicializa la Fecha de inicio del rango de fechas del reporte
  lFecha = pFechaInicial 

  Mientras lFecha <= pFechaFinal
    // Busca el primer movimiento en esa fecha
    // Si encontro al menos un movimiento, sigue buscando otros movimientos en esa misma fecha
    Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[2] ]
      // Discrimina los movimientos que no son entradas ni salidas
      Si tMovimiento(cAfectaExistencia) != 1 y tMovimiento(cAfectaExistencia) != 2
        Continua
      FinSi

      // N.D.1377 Inicio
      // Discrimina movimientos incompletos de características
      // Revisa si el movimiento corresponde a un detalle de características
      Si tMovimiento(cTipoTraspaso) = 4
        // Busca el producto identificador
        tDetalleProducto.Busca[@Str(tMovimiento(cIdProducto);0)]
        Si tDetalleProducto->Encontro
  	      // Si el producto corresponde a un padre de características, entonces
          //  no hay que procesar este movimiento ya que es un movto
          //  incompleto de características
          Si tDetalleProducto(cTipoProducto) = 0
            Continua
          FinSi
        FinSi
      FinSi
      // N.D.1377 Fin

      // N.D.3240 Localización de la moneda del cliente / proveedor
      lTipoCambioDocumento = 1.00
      Si tMovimiento(cIdDocumento)
        tDocumento.Busca[@Str(tMovimiento(cIdDocumento);0)]
      Sino 
        lIdDocumento = fIdDocumentoMovtoOwner(tMovimiento; tMovtoOwner) 
        tDocumento.Busca[@Str(lIdDocumento;0)]
      FinSi
      lIdMonedaCliente = 1
      Si tDocumento->Encontro
        lTipoCambioDocumento = tDocumento(cTipoCambio)
        tClienteProveedor.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
        Si tClienteProveedor->Encontro
          lIdMonedaCliente = tClienteProveedor(cIdMoneda)
        Sino
          lIdMonedaCliente = tDocumento(cIdMoneda)
        FinSi
      Finsi
      //! N.D.3240 lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; pIdMoneda)[C1]
      // Costo del movimiento en moneda base
	  Si atProducto(cMetodoCosteo) = 7 //Costo estándar N.D. 8503
		lCostoExistencia = tMovimiento(cCostoEspecifico)[C1]
	  SiNo
		lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; 1)[C1]
	  FinSi
      lCostoExistencia = fCambiarMonedaImporteLib(tTipoCambioLib; @Col(lCostoExistencia;1); 1; pIdMoneda; lTipoCambioDocumento; tMovimiento(cFecha); lIdMonedaCliente)[C1]
      lCostoExistencia = fUnidades(pUnidad; atProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tEquivalencia)[C0]
      // Imprime el movimiento
      fImprimeMovimiento(atProducto; tMovimiento; lCostoExistencia)
    FinMientras
    // Incrementa un día a la fecha
    lFecha = fFechaSiguiente(lFecha)
  FinMientras
FinFunc


// *****************************************************************************
//  fProcesaPorAlmacen
//
//  Esta función lee y procesa los movimientos de entrada y salida cuando el
//  método de costeo es diferente de UEPS o PEPS, es decir, sin capas. Sólo aplica
//  para reportes por almacén
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 18/02/2002   MOFM              Implementación inicial
// 19/02/2002   RPC     ND 141    Se corrige existencia y costo inicial
//                                Se corrigen impresión de datos del almacén 
//                                antes de datos del producto
// 19/03/2002   CILA    SC 35     Se agrego la validación para mostrar los todos
//                                los movimientos, o solo los afectados o solo 
//                                los que no estan afectados.
// 16/05/2002   EGV     ND 390    Cuando se obtiene la existencia inicial del
//                                Almacén, ésta es copiada a la variable global
//                                gInventarioInicialAlmacen a fin de que los
//                                movimientos sumen o resten existencia o importe
//                                de dicha existencia inicial y no de la
//                                existencia inicial acumulada de todos los 
//                                almacenes para ese Producto. (EGV)
// 21/06/2002   LAP     ND 585    Adición de fExistenciaProductoSinAfectar y
//                                fCostoProductoSinAfectar para obtener las
//                                unidades y costo de los movimientos sin
//                                afectar. Y dependiendo de si el usuario  
//                                desea ver todos los movimientos, los 
//                                movimientos afectados o los movimientos sin
//                                afectar, poder desplegar correctamente la
//                                existencia o el costo inicial.
// 26/07/2002   RPC     SC 150    Ya no se calcula la existencia y costo sin 
//                                afectar porque sólo se imprime lo afectado y 
//                                los movtos sin afectar son unerror
//  27/01/2003  LAP     N.D.1377    Los movimientos incompletos de detalles de
//                                  características no se deben de imprimir
// 08/09/2003   EGV     N.D.2410  Se checa que se cumpla el filtro Imprimir 
//                                Productos: Sólo con movimientos. (EGV)
//  05/02/2008  JENL    N.D.5062  Se cambia el indice iProductoAlmacenFechaAfec por iProductoAlmacenAfecFecha
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DefFunc fProcesaPorAlmacen(atProducto: Tabla)
Local lCostoExistencia, lFecha
Local lAlmacen
Local lAlmacenImpreso
Local lTotalEntradas, lTotalSalidas, lInventario
Local lTotalCostoEntradas, lTotalCostoSalidas
Local lIdDocumento, lIdMonedaCliente, lTipoCambioDocumento

  Mientras [ tAlmacenRecorrido.Busca[pAlmacenInicial & '..' & pAlmacenFinal]; tAlmacenRecorrido->Encontro; tAlmacenRecorrido.Busca Siguiente[1] ]
    lAlmacen = tAlmacenRecorrido(cIdAlmacen) 
    lFecha = pFechaInicial
    lAlmacenImpreso = 0
    gTotalEntradasAlmacen = 0.0
    gTotalSalidasAlmacen = 0.0
    gInventarioInicialAlmacen = 0
    gTotalEntradasAlmSinAfectar = 0 
    gTotalSalidasAlmSinAfectar = 0

    // Establecer el índice usado por el calculo de costo y existencia inicial
    tMovimiento.Usaindice['iProductoFechaAfecta']    // cIdProducto+cFecha+cAfectaExistencia

    // RPC - SC 150 Ya no se incluyen existencias o costos sin afectar
    lInventario = fCostoInicialProducto(tProducto(cIdProducto); lAlmacen; pFechaInicial; gIdEjercicio; gPeriodo; tProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambioLib; pIdMoneda)[C1]
    lInventario = fExistenciaInicialProducto(tProducto(cIdProducto); lAlmacen; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)[C0]
    // Imprime los datos del almacén. Se checa que se cumpla el filtro Imprimir Productos: Todos o sólo con movimientos.
//    Si (@col(lInventario;0) != 0 Y pImprimirProductos = 1)  O (pImprimirProductos = 0)

    Si (pImprimirProductos = 0) 
      // Imprime los datos del producto
      Si !gDatosProducto // Si no se han impreso
        // Imprime los datos del producto
        fImprimeDatosProducto(atProducto)
      FinSi
      fImprimeDatosAlmacen()  
      // y el inventario inicial
      fImprimeInventarioInicial(lInventario)
      gInventarioInicial = gInventarioInicial + lInventario
      gInventarioInicialAlmacen = lInventario
      lAlmacenImpreso = 1
    FinSi
    // Regresar al índice usado por el reporte 
    tMovimiento.Usaindice['iProductoAlmacenFechaAfec']    // cIdProducto+cIdAlmacen+cFecha+cAfectaExistencia
    //tMovimiento.Usaindice['iProductoAlmacenAfecFecha'] // cIdProducto+cIdAlmacen+CAFECTADOINVENTARIO+cFecha N.D.5062

    // Recorre todas las fechas en el rango de fechas del reporte
    Mientras lFecha <= pFechaFinal
      // Busca el primer movimiento en esa fecha
      // Si encontro al menos un movimiento, sigue buscando otros movimientos en esa misma fecha
      Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lAlmacen & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[3] ]
      //Mientras [ tMovimiento.Busca[atProducto(cIdProducto) & ':' & lAlmacen & ':' & '1' & ':' & lFecha]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4] ]//N.D.5062
        // Discrimina los movimientos que no son entradas ni salidas
        Si tMovimiento(cAfectaExistencia) != 1 y tMovimiento(cAfectaExistencia) != 2
          Continua
        FinSi
				
        // N.D.1377 Inicio
        // Discrimina movimientos incompletos de características
        // Revisa si el movimiento corresponde a un detalle de características
        Si tMovimiento(cTipoTraspaso) = 4
          // Busca el producto identificador
          tDetalleProducto.Busca[@Str(tMovimiento(cIdProducto);0)]
          Si tDetalleProducto->Encontro
  	        // Si el producto corresponde a un padre de características, entonces
            //  no hay que procesar este movimiento ya que es un movto
            //  incompleto de características
            Si tDetalleProducto(cTipoProducto) = 0
              Continua
            FinSi
          FinSi
        FinSi
        // N.D.1377 Fin

        // N.D.3240 Localización de la moneda del cliente / proveedor
        lTipoCambioDocumento = 1.00
        Si tMovimiento(cIdDocumento)
          tDocumento.Busca[@Str(tMovimiento(cIdDocumento);0)]
        Sino 
          lIdDocumento = fIdDocumentoMovtoOwner(tMovimiento; tMovtoOwner) 
          tDocumento.Busca[@Str(lIdDocumento;0)]
        FinSi
        lIdMonedaCliente = 1
        Si tDocumento->Encontro
          lTipoCambioDocumento = tDocumento(cTipoCambio)
          tClienteProveedor.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
          Si tClienteProveedor->Encontro
            lIdMonedaCliente = tClienteProveedor(cIdMoneda)
          Sino
            lIdMonedaCliente = tDocumento(cIdMoneda)
          FinSi
        Finsi
        //! N.D.3240 lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; pIdMoneda)[C1]
        // Costo del movimiento en moneda base
        lCostoExistencia = fCostoMovimiento(atProducto; tMovimiento; tCostoHistorico; tTipoCambioLib; 1)[C1]
        lCostoExistencia = fCambiarMonedaImporteLib(tTipoCambioLib; @Col(lCostoExistencia;1); 1; pIdMoneda; lTipoCambioDocumento; tMovimiento(cFecha); lIdMonedaCliente)[C1]
        lCostoExistencia = fUnidades(pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tEquivalencia)[C0]

        // Imprime los datos del producto
        Si !gDatosProducto // Si no se han impreso
          // Imprime los datos del producto
          fImprimeDatosProducto(atProducto)
        FinSi

        // Imprime el movimiento
        Si lAlmacenImpreso = 0
          fImprimeDatosAlmacen()  
          // y el inventario inicial
          fImprimeInventarioInicial(lInventario)
          // N.D.4355 Acumular el inventario inicial
          gInventarioInicial = gInventarioInicial + lInventario
          gInventarioInicialAlmacen = lInventario
          lAlmacenImpreso = 1
        FinSi  

        // Imprime el movimiento
        fImprimeMovimiento(atProducto; tMovimiento; lCostoExistencia)
      FinMientras
      // Incrementa un día a la fecha
      lFecha = fFechaSiguiente(lFecha)
    FinMientras  
   
    Si lAlmacenImpreso = 1
      fImprimeTotalesPorAlmacen(gTotalEntradasAlmacen; gTotalSalidasAlmacen; True)
      // RPC - SC 150 Incluir un total de los movimeintos sin afectar
      Si gTotalEntradasAlmSinAfectar != 0 O gTotalSalidasAlmSinAfectar != 0
        fImprimeTotalesPorAlmacen(gTotalEntradasAlmSinAfectar; gTotalSalidasAlmSinAfectar; False)
      FinSi
      // FIN RPC - SC 150 
    FinSi
  FinMientras
FinFunc



// ==========================================================================================
// fImprimeClasesExcel  (Procedimiento)
// Descripcion : Imprime los nombres de las clases justificados al centro
//   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.
// ==========================================================================================
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 
    
      // Se imprime la clase y sus valores seleccionados
      ws.Range('B' & RenActual ).Value = 'CLASIFICACIÓN No. ' & @Str(lContPrincipal+1;0) & ' : '& @SubStr(lLeyenda;1;@Len(lLeyenda)-1)[C0]
      // Avanza de renglon
      RenActual = RenActual + 1[C0]

      lLeyenda = ''
  
    Finsi
    lContPrincipal = lContPrincipal + 1

  FinMientras
FinFunc

// *****************************************************************************
// Encabezado del reporte
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 19/03/2002  CILA     SC 35         Se agrego los textos para saber si el re-
//                                    porte incluye todos los movimientos o solo
//                                    los afectados o solo los no afectados, 
//                                    Ademas se incluye una leyenda asociado al
//                                    asterisco.  
// 26/07/2002   RPC     SC 150        Ya no se imprimen el texto y el asterisco de 
//                                    movimientos sin afectar
// 05/02/2009   RPC     SC 231        Imprimir que los movimientos estan en orden
//                                    de captura 
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Encab
    // Pone el nombre del f
    ws.Range('A' & RenActual).Font.Color = @RGB(255;0;0)[C0]
    ws.Range('A' & RenActual).Font.Size = 10[C0]
    ws.Range('A' & RenActual).Value = 'AdminPAQ'[C0]

    // Pone el nombre de la empresa
    ws.Range('C' & RenActual).Font.Size = 14[C0]
    ws.Range('C' & RenActual).Font.FontStyle = 'Negrita'[C0]
    // Lo centra en las columnas A a la K
    ws.Range('C' & RenActual & ':L' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('C' & RenActual ).Value = tEmpresa->Nombre

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

    // Pone el titulo del reporte en EXCEL
    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.FontStyle = 'Negrita'[C0]
    // SC 231 Si es kárdex global o por almacén
    Si pTipoKardex < 2
      ws.Range('A' & RenActual ).Value = 'K  A  R  D  E  X'[C0]
    SiNo  // Es kárdex en orden de captura
      ws.Range('A' & RenActual ).Value = 'K A R D E X     E N    O R D E N     D E     C A P T U R A'[C0]
    FinSi  // FIN SC 231 
    // Lo centra en las columnas A a la M
    ws.Range('A' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]

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

    // Pone el titulo del reporte en EXCEL
    ws.Range('A' & RenActual).Font.Size = 12[C0]
    ws.Range('A' & RenActual).Font.FontStyle = 'Negrita'[C0]    
    ws.Range('A' & RenActual ).Value = 'Del: ' & fFormateaFecha(pFechaInicial;gIdioma) & ' Al: ' & fFormateaFecha(pFechaFinal;gIdioma)[C0]
    // Lo centra en las columnas A a la M
    ws.Range('A' & RenActual & ':M' & 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)
    // Si gNumDeClases > 0    // solo si hubo al menos una clase seleccionada
      // fImprimeClasesExcel(gListNombreDeClases;gNumClasesPorTipo) 
    // Finsi

    // CILA - SC 35
    // SC 231 ws.Range('A' & RenActual ).Value = '* - Movimiento que no ha sido afectado en Inventarios'
    // Fin CILA - SC 35  

    tMoneda.Busca[@Str(pIdMoneda;0)]
    Si tMoneda->Encontro
      ws.Range('K' & RenActual ).Value = 'Moneda: ' & tMoneda(cNombreMoneda)[C0]
    FinSi

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

    // Pone los titulos de Unidades 
    ws.Range('G' & RenActual & ':I' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('G' & RenActual & ':I' & RenActual).Interior.ColorIndex = 3[C0]    
    ws.Range('G' & RenActual).Font.Color = @RGB(255;255;255)[C0]
    ws.Range('G' & RenActual).Font.FontStyle = 'Negrita'[C0]    
    ws.Range('G' & RenActual ).Value = 'EN UNIDADES'[C0]

    // Pone los titulos de Importes
    ws.Range('K' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
    ws.Range('K' & RenActual & ':M' & RenActual).Interior.ColorIndex = 3[C0]    
    ws.Range('K' & RenActual).Font.Color = @RGB(255;255;255)[C0]
    ws.Range('K' & RenActual).Font.FontStyle = 'Negrita'[C0]    
    ws.Range('K' & RenActual ).Value = 'EN IMPORTES (COSTO HISTORICO)'[C0]

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

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

    ws.Range('D' & RenActual).HorizontalAlignment = xlDerecha[C0]
    ws.Range('F' & RenActual & ':N' & RenActual).HorizontalAlignment = xlDerecha[C0]
    ws.Range('A' & RenActual & ':N' & RenActual).Value = '','Fecha','Serie','Folio','Concepto','No. Almacén','Entradas','Salidas','Existencia','Costo Unitario','Entradas','Salidas','Costo Total','Identificador'

    // N.D.1538 Inicio
    // Excel.Rows('8:8').Select
    // Avanza de renglon
    RenActual = RenActual + 1[C0]
    Excel.Rows(RenActual & ':' & RenActual).Select
    // N.D.1538 Fin
    Excel.ActiveWindow.FreezePanes = True
    ws.Range('A' & RenActual).Select
FinEncab


// *****************************************************************************
// Cuerpo del reporte
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 24/01/2002   MOFM    SC 24       Se cambia el índice de tMovimiento depen-
//                                  diendo del almacén seleccionado.               
// 15/02/2002   MOFM    SC 24       Se modifica para realizar la búsqueda en base
//                                  al rango de almacenes
// 19/02/2002   RPC     ND 141      Se agrega total para kárdex globales
// 13/05/2002   EGV     ND 390      Cuando se obtiene la existencia inicial del
//                                  producto, se copia el valor de
//                                  gInventarioInicial a la variable
//                                  gInventarioInicialAlmacen para que la
//                                  función fImprimeMovimiento haga los cálculos
//                                  correctamente. Además, cuando el usuario
//                                  especifica que desea imprimir todos los
//                                  almacenes, se omite por código el Almacén 0.
// 21/06/2002   LAP     ND 585      Adición de fExistenciaProductoSinAfectar y
//                                  fCostoProductoSinAfectar para obtener las
//                                  unidades y costo de los movimientos sin
//                                  afectar. Y dependiendo de si el usuario  
//                                  desea ver todos los movimientos, los 
//                                  movimientos afectados o los movimientos sin
//                                  afectar, poder desplegar correctamente la
//                                  existencia o el costo inicial.
// 26/07/2002   RPC     SC 150      Ya no se calcula la existencia y costo sin 
//                                  afectar porque sólo se imprime lo afectado y
//                                  los movtos sin afectar son unerror
//  05/02/2008  JENL    N.D.5062  Se cambia el indice iProductoAlmacenFechaAfec por iProductoAlmacenAfecFecha
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

// Inicializa valores globales para la biblioteca LibAdminPAQ.rpt
fIniFechasHistoria(tEjercicio)

// Configura los decimales del reporte
fConfiguraDecimales()

// A partir de la fecha de inicio del reporte, obtiene el ejercicio y periodo correspondiente
// esto es util para el cálculo del inventario inicial del reporte
fEjercicioPeriodo(pFechaInicial; &gPeriodo; &gIdEjercicio; tEjercicio) 

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


// Si el rango inicial es el primer almacén, recupera el código del primero
Si pAlmacenInicial = ' '
  tAlmacenRecorrido.Busca Primero
  Si tAlmacenRecorrido->Encontro
    Si tAlmacenRecorrido(cIdAlmacen) = 0
      tAlmacenRecorrido.Saltareg[1]
    FinSi
    Si tAlmacenRecorrido->Encontro
      pAlmacenInicial = tAlmacenRecorrido(cCodigoAlmacen)
    FinSi
  FinSi
FinSi

// Si el rango final es el último almacén, recupera el código del último
Si pAlmacenFinal = ' '
  tAlmacenRecorrido.Busca Ultimo
  Si tAlmacenRecorrido->Encontro
    pAlmacenFinal = tAlmacenRecorrido(cCodigoAlmacen)
  FinSi
FinSi

Mientras [ tProducto.Busca[pProductoInicial & '..' & pProductoFinal]; tProducto->Encontro; tProducto.Busca Siguiente[1] ]

  // Solo busca productos, descarta paquetes y servicios
  Si tProducto(cTipoProducto) != 1
    Continua
  FinSi

  // Verifica si el producto es candidato a imprimirse en función de su estado
  // tProducto(cStatusProducto) = 0 (Inactivo)
  // tProducto(cStatusProducto) = 1 (Activo)
  Si pEstadoProducto y pEstadoProducto != @Abs(tProducto(cStatusProducto) - 2)
    Continua
  FinSi

  // Verifica si el producto cumple con las clasificaciones especificadas 
  Si gNumDeClases > 0
    Si !fMiembroDeUnaClase(tProducto; gNumDeClases; gListIdDeClases; 2)
      // Discrimina el producto por no pertenecer a alguna de las clasificaciones
      Continua
    FinSi
  FinSi

  // Inicializa variable para impresión de los datos del producto
  gDatosProducto = 0 // No se han impreso los datos del producto

  // Inicializa variables de totales del producto
  gTotalEntradasProducto = 0.0
  gTotalSalidasProducto = 0.0
  gInventarioInicial = 0.0
  gTotalEntradasProdSinAfectar = 0
  gTotalSalidasProdSinAfectar = 0

  gRenglonesHoja = 0

  // Verifica parámetro pUnidad
  fVerificaUnidad(tProducto)

  // Si el kárdex es general
  Si pTipoKardex = 0 O pTipoKardex = 2
    // RPC - SC 150 Ya no se imprime existencia o costo sin afectar
    gInventarioInicial = fExistenciaInicialProducto(tProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; pUnidad; tProducto(cIdUnidadBase); pIdUnidad; tMovimiento; tExistencia; tEquivalencia)[C0]
    Si tProducto(cMetodoCosteo) = 7
      gInventarioInicial = @Col(gInventarioInicial;0) * tProducto(cCostoEstandar)[C1]
    Sino
      gInventarioInicial = fCostoInicialProducto(tProducto(cIdProducto); 0; pFechaInicial; gIdEjercicio; gPeriodo; tProducto; tMovimiento; tExistencia; tCostoHistorico; tTipoCambioLib; pIdMoneda)[C1]
    FinSi
    gInventarioInicialAlmacen = gInventarioInicial

    Si !pImprimirProductos // No discriminar productos sin movimientos?
      // Imprime los datos del producto
      fImprimeDatosProducto(tProducto)
      // y el inventario inicial
      fImprimeInventarioInicial(gInventarioInicial)
    FinSi

    tMovimiento.Usaindice['iProductoFechaAfecta']     // cIdProducto+cFecha+cAfectaExistencia

    fProcesaSinCapas(tProducto)
    // Se imprimieron los datos del producto?
    Si gDatosProducto
      // Imprime los totales por producto
      fImprimeTotales(gInventarioInicial; gTotalEntradasProducto; gTotalSalidasProducto; gDescUnidad; True)
      // Acumula en los totales globales
      gTotalEntradas = gTotalEntradas + gTotalEntradasProducto
      gTotalSalidas = gTotalSalidas + gTotalSalidasProducto
      gTotal = gTotal + gInventarioInicial + gTotalEntradasProducto - gTotalSalidasProducto
      // RPC - SC 150 Incluir un total de los movimeintos sin afectar
      Si gTotalEntradasProdSinAfectar != 0 O gTotalSalidasProdSinAfectar != 0 
        fImprimeTotales(0; gTotalEntradasProdSinAfectar; gTotalSalidasProdSinAfectar; gDescUnidad; False)
        gTotalEntradasSinAfectar = gTotalEntradasSinAfectar + gTotalEntradasProdSinAfectar
        gTotalSalidasSinAfectar = gTotalSalidasSinAfectar + gTotalSalidasProdSinAfectar
      FinSi
      RenActual = RenActual + 1[C0]
      // FIN RPC - SC 150
    FinSi

  // Si el kárdex es por almacén
  Sino   
    Si !pImprimirProductos // No discriminar productos sin movimientos?
      // Imprime los datos del producto
      fImprimeDatosProducto(tProducto)
    FinSi

    tMovimiento.Usaindice['iProductoAlmacenFechaAfec']     // cIdProducto+cIdAlmacen+cFecha+cAfectaExistencia
    //tMovimiento.Usaindice['iProductoAlmacenAfecFecha'] // cIdProducto+cIdAlmacen+CAFECTADOINVENTARIO+cFecha N.D.5062

    fProcesaPorAlmacen(tProducto)
    // Se imprimieron los datos del producto?
    Si gDatosProducto
      // Imprime los totales por producto
      fImprimeTotales(gInventarioInicial; gTotalEntradasProducto; gTotalSalidasProducto; gDescUnidad; True)
      // Acumula en los totales globales
      gTotalEntradas = gTotalEntradas + gTotalEntradasProducto
      gTotalSalidas = gTotalSalidas + gTotalSalidasProducto
      gTotal = gTotal + gInventarioInicial + gTotalEntradasProducto - gTotalSalidasProducto
      // RPC - SC 150 Incluir un total de los movimeintos sin afectar
      Si gTotalEntradasProdSinAfectar != 0 O gTotalSalidasProdSinAfectar != 0 
        fImprimeTotales(0; gTotalEntradasProdSinAfectar; gTotalSalidasProdSinAfectar; gDescUnidad; False)
        gTotalEntradasSinAfectar = gTotalEntradasSinAfectar + gTotalEntradasProdSinAfectar
        gTotalSalidasSinAfectar = gTotalSalidasSinAfectar + gTotalSalidasProdSinAfectar
      FinSi
      RenActual = RenActual + 1[C0]
      // FIN RPC - SC 150
    FinSi
  FinSi // Si el kárdex es general o por almacén

  // Regresa el valor original de pUnidad guardado en la variable global gUnidad
  //pUnidad = gUnidad

FinMientras

// Imprimir los totales del reporte
fImprimeTotalesGenerales(gTotalEntradas; gTotalSalidas; gTotal; True)

// RPC - SC 150 Incluir un total de los movimeintos sin afectar
Si gTotalEntradasSinAfectar != 0 O gTotalSalidasSinAfectar != 0 
  fImprimeTotalesGenerales(gTotalEntradasSinAfectar; gTotalSalidasSinAfectar; gTotalEntradasSinAfectar - gTotalSalidasSinAfectar; False)
FinSi
// FIN RPC - SC 150 

//N.C.224 Debe marcar con una leyenda el problema del movimiento 
RenActual = RenActual + 4[C0]
ws.Range('A' & RenActual).Value = '1'
ws.Range('B' & RenActual).Value = 'Movimiento que no ha sido afectado en Inventarios'[C0]

RenActual = RenActual + 1[C0]
ws.Range('A' & RenActual).Value = '2'
ws.Range('B' & RenActual).Value = 'Este movimiento está actualmente en captura, por tal motivo solo está afectado en existencia y no en costo'[C0]

// SC 231 OJO ¿Señalar los movimientos en desorden?
//Si pTipoKardex >= 2
//  RenActual = RenActual + 1[C0]
//  ws.Range('A' & RenActual).Select
//  ws.Range('A' & RenActual & ':D' & RenActual).Interior.ColorIndex = 36[C0]
//  ws.Range('A' & RenActual).Value = '3'
//  ws.Range('B' & RenActual).Value = 'Movimiento capturado en desorden'[C0]
//FinSi  // Fin SC 231
