// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//
//	AnPreciosExcel.rpt
//	Nombre del reporte en el sistema: Análisis de Precios por Cliente o Proveedor
//
//  Sistema: AdminPAQ v1.1.
// 
//  Este reporte pertenece al módulo de ventas y compras. Despliega en Excel
//  un listado de los productos con precio de venta/compra
//
//	Consideraciones especiales:
//  
//	Elaboró:	Leonardo Aguilar Pizano
//	Fecha: 	  11 de septiembre de 2002
//  Lotus Notes:  S.C.236
//
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 01/11/2002  DRdA     N.D.1476     Presenta en la columna de "Dias de crédito" algunos datos
//                                   en negativo.
//                                   Se modificó: fImprimeRenglon.
// 05/11/2002 LAP       N.D.1471     Modificación de las busquedas de los movimientos a fin de 
//                                   considerar que las compras que vienen de consignaciones no 
//                                   están afectadas en inventarios
//                                   - Cuerpo del reporte
// 03/11/2004 LAP       N.D.2752     Adición de la columna de Descuestos
//                                   - Inicializa EXCEL
//                                   - fConfiguraColumnas
//                                   - fImprimeRenglon
//                                   - Encabezado del reporte
// 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.
//                                   - fImporteMonedaReporte cambio a fImporteMonedaReporteBis
// 28/06/2005 HVA       N.D.3326     No imprime valores con el parametro "Solo con Existencias", esta se debe sacar a la fecha inicial
// 14/11/2005 HVA       N.D.3682     No se comporta de la misma manera con el parametro "Solo con Existencias", ahora en vez de ser al inicio se saca al final.
// 15/12/2005 LAP       N.D.3010     Nuevo esquema de búsquedas parciales para agilizar los reportes
// 24/04/2006 HVA       N.D.3867     Los descuentos se restaban entre ellos y deben de sumarse para sacar su total.
// 26/02/2010 ELVS      N.D.6222     Reportes - ERROR CALCULO INCORRECTO EN LA COLUMNA IMPORTE AL EJECUTAR EL REPORTE
//                                   ANALISIS DE PRECIOS POR PROVEEDOR SELECCIONANDO SI EN EL FILTRO INCLUIR GASTOS.
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


// *********************************************************************************************
// Funciones de librería
// *********************************************************************************************
Incluye LibAdminPAQ.rpt
Incluye LibInventarios.rpt


// *********************************************************************************************
// Parámetros
// *********************************************************************************************
Parametro pTipoReporte 	= 1									// Tipo del reporte
																						// 1 - Por cliente
																						// 2 - Por Proveedor
Parametro pFechaInicial			= '20020910'    // Fecha inicial del rango
Parametro pFechaFinal				= '20021231'    // Fecha final del rango
Parametro pCteProvInicial		= ' '						// Cliente inicial del rango
Parametro pCteProvFinal			= ' '						// Cliente final del rango
Parametro pProductoInicial	= ' '						// Producto inicial del rango
Parametro pProductoFinal		= ' '						// Producto final del rango
Parametro pAlmacenInicial		= ' '						// Almacen inicial del rango
Parametro pAlmacenFinal			= ' '						// Producto final del rango
Parametro pDocumentoModelo	= 4 						// Documento modelo a imprimir
Parametro pConGastos				= 0							// Incluir gastos solo para Proveedores
																						// 0 No incluir gastos
																						// 1 Incluir gastos
Parametro pImprimirProductos	= 0						// 0 Todos
																						// 1 Solo con existencias
Parametro pEstadoProducto			= 0						// Estado del producto
																						// 0 Todos
																						// 1 Activos
																						// 2 Inactivos
Parametro pUsaMoneda					= 0						// 0 - No
																						// 1 - Si utiliza
Parametro pIdMonedaReporte		= 1						// Moneda del reporte
Parametro pTipoCambio					= 1						// Tipo de cambio en formato de cadena

// *********************************************************************************************
// Tablas 
// *********************************************************************************************
UsaEmpresa tEmpresa;'ADMINPAQW'                   // Parámetros

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

UsaTabla tMovimiento = tEmpresa['MGW10010']       // Movimientos
tMovimiento.Usaindice['iProductoDoctoDeAfecFecha']// cidProducto+ciddocumentode+cAfectadoInventario+cFecha

UsaTabla tAlmacen = tEmpresa['MGW10003']					// Almacenes
tAlmacen.UsaIndice['']														// cIdAlmacen

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

UsaTabla tClienteProveedor = tEmpresa['MGW10002'] // Clientes/Proveedores
tClienteProveedor.Usaindice['']                   // cIdClienteProveedor

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

UsaTabla tConcepto = tEmpresa['MGW10006']       	// Conceptos de documentos
tConcepto.Usaindice['']             							// cIdConceptoDocumento

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

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

UsaTabla tMovimientoAuxiliar = tEmpresa['MGW10010'] ALIAS 'MovtosExistencia'      // Movimientos
tMovimientoAuxiliar.Usaindice['iProductoFechaAfecta']			// cIdProducto+cFecha+cAfectaExistencia

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

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


// *********************************************************************************************
// Definiciones y asumidos globales para el reporte
// *********************************************************************************************
Columnas 38;1
Usaletra 'Arial'
Altura 9


// *********************************************************************************************
// Variables de ámbito global
// *********************************************************************************************
gIdioma = 0             // Idioma del reporte
                        // 0 = Español
                        // 1 = Inglés
gIdEjercicio = 0        // ID del ejercicio que contiene la fecha de inicio del reporte
gPeriodo = 0            // Numero de período que corresponde a la fecha de inicio del reporte
gDecimalesMonedaReporte = 2    // Número de decimales en la moneda
gNombreMonedaReporte 		= 'Peso Mexicano'


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

// *********************************************************************************************
// Inicializa EXCEL
// *********************************************************************************************
// Acceso a los 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
// Codigo-Producto 	= 10 caracteres
ws.Columns(1).ColumnWidth = 10[C0]
// Nombre-Producto 	= 15 caracteres
ws.Columns(2).ColumnWidth = 15[C0]
// Codigo-Cliente 	= 10 caracteres
ws.Columns(3).ColumnWidth = 10[C0]
// Nombre-Cliente 	= 15 caracteres
ws.Columns(4).ColumnWidth = 15[C0]
// Fecha 						= 12 caracteres
ws.Columns(5).ColumnWidth = 12[C0]
// Serie y Folio 		= 14 caracteres [ 1Espacio + 4Serie +1Espacio + 7Folio]
ws.Columns(6).ColumnWidth = 14[C0]
// Dias de Credito 	= 15 caracteres
ws.Columns(7).ColumnWidth = 15[C0]
// Codigo-Almacen 	= 10 caracteres
ws.Columns(8).ColumnWidth = 10[C0]
// Nombre-Almacen 	= 15 caracteres
ws.Columns(9).ColumnWidth = 15[C0]
// Concepto  				= 15 caracteres
ws.Columns(10).ColumnWidth = 15[C0]
// Moneda 					= 10 caracteres
ws.Columns(11).ColumnWidth = 10[C0]
// Precio Unitario 	= 15 caracteres
ws.Columns(12).ColumnWidth = 15[C0]
Si pConGastos = 1 y pTipoReporte = 2
	// Gastos Unitarios = 15 caracteres
	ws.Columns(13).ColumnWidth = 15[C0]
	// Precio con gastos = 15 caracteres
	ws.Columns(14).ColumnWidth = 15[C0]
	// Cantidad 				= 10 caracteres
	ws.Columns(15).ColumnWidth = 10[C0]
  // N.D.2752 Inicio
  // Adición de la columna de Descuentos
	// Descuentos 			= 15 caracteres
	ws.Columns(16).ColumnWidth = 15[C0]
	// Importe 					= 15 caracteres
	ws.Columns(17).ColumnWidth = 15[C0]
  // N.D.2752 Fin
Sino
	// Cantidad 				= 10 caracteres
	ws.Columns(13).ColumnWidth = 10[C0]
  // N.D.2752 Inicio
  // Adición de la columna de Descuentos
	// Descuentos 			= 15 caracteres
	ws.Columns(14).ColumnWidth = 15[C0]
	// Importe 					= 15 caracteres
	ws.Columns(15).ColumnWidth = 15[C0]
  // N.D.2752 Fin
FinSi


// *********************************************************************************************
// Nombre:		fConfiguraColumnas
// Proceso:   
// Entradas:	
// Salidas
// *********************************************************************************************
DEFFUNC fConfiguraColumnas ()
LOCAL lDigDecimales, lDecimales, lNumDecimales, lFormato

	// Configuración de las columnas
	//____________________________________________________________________________________________
	tParametros.Busca Primero
  lDigDecimales = '0000000000'

	// Configuración de Decimales de la columna de Cantidad
  lDecimales = @SUBSTR(lDigDecimales; 1; tParametros(cDecimalesUnidades))
  lFormato = '#,##0.' & lDecimales & '_);(#,##0.' & lDecimales & ')'
	SI pTipoReporte = 1
	  ws.Columns(13).NumberFormat = lFormato[C0]
	SINO
	  ws.Columns(15).NumberFormat = lFormato[C0]
	FINSI	

	// Configuración de Decimales de las columnas de importes
	// Si no se desea filtrar la moneda, entonces utilizar dos decimales
	gDecimalesMonedaReporte = 2		
	Si pUsaMoneda = 1
		tMoneda.Busca[@str(pIdMonedaReporte;0)]	
		gDecimalesMonedaReporte	= tMoneda(cDecimalesMoneda)
		gNombreMonedaReporte 		=	tMoneda(cNombreMoneda)
	FinSi
  lDecimales = @SUBSTR(lDigDecimales; 1; gDecimalesMonedaReporte)
  lFormato   = '#,##0.' & lDecimales & '_);(#,##0.' & lDecimales & ')'

	// Precio
  ws.Columns(12).NumberFormat = lFormato[C0]
	Si pConGastos = 1 y pTipoReporte = 2
		// El reporte de Proveedor que incluye gastos tiene dos columnas más
		// Gastos
	  ws.Columns(13).NumberFormat = lFormato[C0]
		// Precio con gastos
	  ws.Columns(14).NumberFormat = lFormato[C0]
    // N.D.2752 Inicio
    // Adición de la columna de Descuentos
  	// Descuentos
	  ws.Columns(16).NumberFormat = lFormato[C0]
		// Importe
	  ws.Columns(17).NumberFormat = lFormato[C0]
    // N.D.2752 Fin
	Sino
    // N.D.2752 Inicio
    // Adición de la columna de Descuentos
  	// Descuentos
	  ws.Columns(14).NumberFormat = lFormato[C0]
		// Importe
	  ws.Columns(15).NumberFormat = lFormato[C0]
    // N.D.2752 Fin
	FinSi
FINFUNC
// Fin método: fConfiguraColumnas


// ==========================================================================================
// fImporteMonedaReporteBis
// Descripcion : El importe lo cambia al IdMoneda que recibe a la moneda del Reporte
// Entrada : 		aImporte 					: 	Importe a cambiar
//							aIdMonedaDocto		:   Id de la moneda del documento
//          		aTipoCambioDocto	: 	Tipo de cambio del documento a la moneda base
// Salida  :		Importe del documento o movimiento reflejado en la moneda que recibe 
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// Historia de modificaciones
//  Fecha      Nombre   IDLotus                     Descripcion
// ==========================================================================================
Deffunc fImporteMonedaReporteBis(aImporte; aIdMonedaDocto; aTipoCambioDocto)
Local lImporteMonedaRpt, lImporteMonedaBase

	Si pUsaMoneda = 1 y aIdMonedaDocto != pIdMonedaReporte
		// Transforma el importe a la moneda base tomando el tipo de cambio del documento
		lImporteMonedaBase = aImporte
		Si aIdMonedaDocto != 1
		  lImporteMonedaBase = aImporte * aTipoCambioDocto
		FinSi
		
		Si pIdMonedaReporte != 1
			// Si la moneda del reporte es diferente a la base convierte tomando el tipo de cambio
			//	enviado como parametro
			lImporteMonedaRpt = lImporteMonedaBase / pTipoCambio
		Sino
			lImporteMonedaRpt = lImporteMonedaBase
		FinSi		
	Sino
		lImporteMonedaRpt = aImporte
	FinSi

	Retorna lImporteMonedaRpt
FinFunc
// Fin método: fImporteMonedaReporteBis


// *****************************************************************************
//  fImprimeRenglon
//
//  Parámetros 
//
//  Salidas 
// *****************************************************************************
DefFunc fImprimeRenglon(aFecha; aGastoUnitario)
Local lFechaEditada, lCodigo, lMascarilla, lSerieFolio
Local lTotalDescuentos
Local lTotalMovimiento
Local lTotalGastos

  // Avanza de renglon
  RenActual = RenActual + 1[C0]
  // N.D.2752 Inicio
  // Adición de la columna de Descuentos
	// Dibuja los bordes de las celdas
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
	  ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
	Sino
	  ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
	  ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
	FinSi
  // N.D.2752 Fin

	// Codigo_Producto
  lMascarilla = tParametros(cMascarillaProducto)
  lCodigo = tProducto(cCodigoProducto)
  ws.Range('A' & RenActual).Value = @Chr(39) & fMascarilla(lCodigo;lMascarilla)[C0]
	// Nombre_Producto
  ws.Range('B' & RenActual).Value = tProducto(cNombreProducto)[C0]
	// Codigo_Cliente
  lMascarilla = tParametros(cMascarillaClientes)
  lCodigo = tClienteProveedor(cCodigoCliente)
  ws.Range('C' & RenActual).Value = @Chr(39) & fMascarilla(lCodigo;lMascarilla)[C0]
	// Nombre_Cliente
  ws.Range('D' & RenActual).Value = tClienteProveedor(cRazonSocial)[C0]
  // Fecha
  lFechaEditada = fFormateaFecha(aFecha; gIdioma)
  ws.Range('E' & RenActual).Value = @Col(lFechaEditada;0)[C0]
  // Serie_Folio
	lSerieFolio = tDocumento(cSerieDocumento) & ' ' & @col(tDocumento(cFolio);0)
  ws.Range('F' & RenActual).Value = lSerieFolio[C0]
  // Dias_crédito
  // Inicia N.D.1476
  // Si el reultado es negativo se pone en cero por que no se asignó fecha de vencimiento
  Si (fConvJul(tDocumento(cFechaVencimiento)) - fConvJul(tDocumento(cFecha))) < 0
    ws.Range('G' & RenActual).Value = 0[C0]
  SiNo
    ws.Range('G' & RenActual).Value = (fConvJul(tDocumento(cFechaVencimiento)) - fConvJul(tDocumento(cFecha)))[C0]
  Finsi
  // Fin N.D.1476
  // Codigo_Almacen
  lMascarilla = tParametros(cMascarillaAlmacen)
  lCodigo = tAlmacen(cCodigoAlmacen)
  ws.Range('H' & RenActual).Value = @Chr(39) & fMascarilla(lCodigo;lMascarilla)[C0]
	// Nombre_Almacen
  ws.Range('I' & RenActual).Value = tAlmacen(cNombreAlmacen)[C0]
	// Concepto
  ws.Range('J' & RenActual).Value = tConcepto(cNombreConcepto)[C0]
	// Moneda
	Si pUsaMoneda = 1
	  ws.Range('K' & RenActual).Value = gNombreMonedaReporte[C0]
	Sino
	  ws.Range('K' & RenActual).Value = tMoneda(cNombreMoneda)[C0]
	FinSi
	// Precio_Unitario
  ws.Range('L' & RenActual).Value = fImporteMonedaReporteBis(tMovimiento(cPrecio); tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
	// Gastos_Unitarios
  // N.D.2752 Inicio
  // Calcular el total de gastos
  lTotalGastos = 0
	Si pTipoReporte = 2 y pConGastos = 1
	  ws.Range('M' & RenActual).Value = fImporteMonedaReporteBis(aGastoUnitario; tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
    lTotalGastos =  tMovimiento(cUnidades) * aGastoUnitario
	FinSi
  // N.D.2752 Fin
	// Precio con Gastos 
	Si pTipoReporte = 2 y pConGastos = 1
	  ws.Range('N' & RenActual).Value = fImporteMonedaReporteBis(tMovimiento(cPrecio)+aGastoUnitario; tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
	FinSi
	// Cantidad
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('O' & RenActual).Value = tMovimiento(cUnidades)[C0]
	Sino
	  ws.Range('M' & RenActual).Value = tMovimiento(cUnidades)[C0]
	FinSi	
  // N.D.2752 Inicio
  // Adición de la columna de Descuentos
  // Los defectos se suman no se restan entre ellos. 
  lTotalDescuentos = tMovimiento(cDescuento1) + tMovimiento(cDescuento2) + tMovimiento(cDescuento3) + tMovimiento(cDescuento4) + tMovimiento(cDescuento5)
	Si pConGastos = 1 y pTipoReporte = 2
    ws.Range('P' & RenActual).Value = fImporteMonedaReporteBis(lTotalDescuentos; tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
  Sino
    ws.Range('N' & RenActual).Value = fImporteMonedaReporteBis(lTotalDescuentos; tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
  FinSi
	// Importe
  // Neto del movimientos menos los descuentos más el total de gastos
  lTotalMovimiento = tMovimiento(cNeto) - lTotalDescuentos + lTotalGastos
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('Q' & RenActual).Value = fImporteMonedaReporteBis(lTotalMovimiento; tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
	Sino
	  ws.Range('O' & RenActual).Value = fImporteMonedaReporteBis(lTotalMovimiento; tDocumento(cIdMoneda); tDocumento(cTipoCambio))[C0]
	FinSi	
  // N.D.2752 Fin

FinFunc
// Fin método: fImprimeRenglon


// *********************************************************************************************
// Encabezado del reporte
// *********************************************************************************************
Encab

	// Pone el nombre del sistema
  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('B' & RenActual).Font.Size = 14[C0]
  ws.Range('B' & RenActual).Font.FontStyle = 'Negrita'[C0]
  // Lo centra en las columnas B a la N
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('B' & RenActual & ':O' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
	Sino	
	  ws.Range('B' & RenActual & ':M' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
	FinSi
  ws.Range('B' & 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]
  Si pTipoReporte = 1
    ws.Range('A' & RenActual ).Value = 'A N A L I S I S     D E     P R E C I O S     P O R     C L I E N T E'[C0]
  SiNo
    ws.Range('A' & RenActual ).Value = 'A N A L I S I S     D E     P R E C I O S     P O R     P R O V E E D O R'[C0]
  FinSi
  // Lo centra en las columnas A a la O
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('A' & RenActual & ':P' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
	Sino
	  ws.Range('A' & RenActual & ':N' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
	FinSi
  // Avanza de renglon
  RenActual = RenActual + 1[C0]

  // Pone el rango de fechas 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 O
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('A' & RenActual & ':P' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
	Sino
	  ws.Range('A' & RenActual & ':N' & RenActual).HorizontalAlignment = xlCentrarEnSeleccion[C0]
	FinSi
  // Avanza de renglon
  RenActual = RenActual + 1[C0]

  // Pone el titulo de cada columna en EXCEL
  // N.D.2752 Inicio
  // Adición de la columna de Descuentos
	Si pConGastos = 1 y pTipoReporte = 2
	  ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
	  ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':Q' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
	  ws.Range('A' & RenActual & ':Q' & RenActual).Interior.ColorIndex = 55[C0]    
  	ws.Range('A' & RenActual & ':Q' & RenActual).Font.FontStyle = 'Negrita'[C0]    
	  ws.Range('A' & RenActual & ':Q' & RenActual).Font.Color = @RGB(255;255;255)[C0]
	  ws.Range('E' & RenActual & ':Q' & RenActual).HorizontalAlignment = xlCentro[C0]
  	ws.Range('A' & RenActual & ':Q' & RenActual).Value = 'Código','Nombre(Producto)','Codigo',(pTipoReporte=1?'Nombre(Cliente)':'Nombre(Proveedor)'),'Fecha','Folio y Serie','Dias de Crédito','Código','Almacén','Concepto','Moneda','Precio Unitario','Gastos Unitarios','Precio con gastos','Cantidad','Descuentos','Importe'
	Sino
	  ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlInferior).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlSuperior).LineStyle = xlLineaSimple[C0]
	  ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlIzquierda).LineStyle = xlLineaSimple[C0]
  	ws.Range('A' & RenActual & ':O' & RenActual).Borders(xlDerecha).LineStyle = xlLineaSimple[C0]
	  ws.Range('A' & RenActual & ':O' & RenActual).Interior.ColorIndex = 55[C0]    
  	ws.Range('A' & RenActual & ':O' & RenActual).Font.FontStyle = 'Negrita'[C0]    
	  ws.Range('A' & RenActual & ':O' & RenActual).Font.Color = @RGB(255;255;255)[C0]
	  ws.Range('E' & RenActual & ':O' & RenActual).HorizontalAlignment = xlCentro[C0]
  	ws.Range('A' & RenActual & ':O' & RenActual).Value = 'Código','Nombre(Producto)','Codigo',(pTipoReporte=1?'Nombre(Cliente)':'Nombre(Proveedor)'),'Fecha','Folio y Serie','Dias de Crédito','Código','Almacén','Concepto','Moneda','Precio Unitario','Cantidad','Descuentos','Importe'
	FinSi
  // N.D.2752 Fin
	RenFijo = RenActual+1
  Excel.Rows(RenFijo & ':' & RenFijo).Select
  Excel.ActiveWindow.FreezePanes = True
  ws.Range('A' & RenActual).Select
FinEncab


// *********************************************************************************************
// Cuerpo del reporte
// *********************************************************************************************

	fConfiguraColumnas()

	// Determina los codigos que formaran el rango de productos 
	tProducto.Usaindice['iCodigoTipo']
	// 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

	lNetoMenosDescuentos 	= 0
	lGastoUnitario				= 0
	lGastoTotal						= 0

	Mientras[tProducto.Busca[pProductoInicial & '..' & pProductoFinal]; tProducto->Encontro; tProducto.Busca Siguiente[1]]
		// No considerar el producto 0		
		Si tProducto(cIdProducto) = 0
			Continua
		FinSi		

		// Discriminación según el Filtro de Estado del Producto: Activos	/ Inactivos
		Si (pEstadoProducto = 1) Y (tProducto(cStatusProducto) != 1)
			Continua
		FinSi
		Si (pEstadoProducto = 2) Y (tProducto(cStatusProducto) != 0)
			Continua
		FinSi

    // N.D.3010 Inicio
		//!lFecha = pFechaInicial
		//!Mientras lFecha <= pFechaFinal  
    // A partir de la fecha de fin del reporte, obtiene el ejercicio y periodo correspondiente
  	// esto es util para el cálculo del inventario inicial del reporte
		fEjercicioPeriodo(pFechaFinal; &gPeriodo; &gIdEjercicio; tEjercicio) 

      // N.D.1471 Inicio
      // Ahora imprime primero los movimientos afectados en inventario y posteriormente
      //  los no afectados
      lListaAfectado = '1,0'
      lCiclo = 0
      Mientras lCiclo < 2
  			//!lLlave = tProducto(cIdProducto) & ':' & pDocumentoModelo & @Escoge(lListaAfectado; lCiclo) & lFecha
  			// N.D.3010
	  		//!Mientras [tMovimiento.Busca[@Str(lLlave;0)]; tMovimiento->Encontro; tMovimiento.Busca Siguiente[4]]
        // NOTA: Es obligatorio volver a fijar el índice a fin de que las búsquedas parciales funcionen correctamente
        tMovimiento.Usaindice['iProductoDoctoDeAfecFecha']
        // Localización del primer movimiento del producto
        lFecha = pFechaInicial
        tMovimiento.Busca[tProducto(cIdProducto) & ':' & pDocumentoModelo & ':' & @Escoge(lListaAfectado; lCiclo) & ':' & lFecha]
        Si !tMovimiento->Encontro
          // Busquedas parciales: Cursor en el registro más cercano que cumple con la llave
          // NOTA: La propiedad Llave de la tabla nos regresa la llave más cercana que cumple con el criterio de la búsqueda
          //       La llave está en formato cadena y no tiene ningún separador entre los campos, por lo que es necesario revisar
          //       en FoxPro la definición del índice para descomponer los elementos de la Llave
          // Revisar si la llave actual corresponde al Producto / Almacén y al Rango de Fechas.
          Si tProducto(cIdProducto) = @Val(@SUBSTR(tMovimiento->Llave;0;11))
            Si @Col(pDocumentoModelo;0) = @Val(@SUBSTR(tMovimiento->Llave;11;11))
              Si @Val(@Escoge(lListaAfectado; lCiclo)) = @Val(@SUBSTR(tMovimiento->Llave;22;6))
                Si @SUBSTR(tMovimiento->Llave;28;8) >= pFechaInicial Y @SUBSTR(tMovimiento->Llave;28;8) <= pFechaFinal
                  // Realizar nuevamente la búsqueda a fin de posicionarnos en el registro y activar la propiedad Encontro
                  lFecha = @SUBSTR(tMovimiento->Llave;28;8)
                  tMovimiento.Busca[tProducto(cIdProducto) & ':' & pDocumentoModelo & ':' & @Escoge(lListaAfectado; lCiclo) & ':' & lFecha]
                FinSi
              FinSi
            FinSi
          FinSi        
        FinSi
        // N.D.3010 Recorrer los movimientos hasta que sea diferente producto, almacén o se rompa el rango de fechas
        Mientras tMovimiento->Encontro Y (tMovimiento(cFecha) <= pFechaFinal)
		  		// Ubica el documento del movimiento
			  	tDocumento.Busca[@Str(tMovimiento(cIdDocumento);0)]
				  Si !tDocumento->Encontro
            // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
            tMovimiento.BUSCA SIGUIENTE[3]
					  Continua
  				FinSi
  
	  			// No considerar los cancelados
		  		Si tDocumento(cCancelado) = 1
            // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
            tMovimiento.BUSCA SIGUIENTE[3]
			  		Continua
  				FinSi
  
	  			// Discriminación por el Filtro de Almacén
		  		tAlmacen.Busca[@Str(tMovimiento(cIdAlmacen);0)]
			  	Si tAlmacen->Encontro
				  	Si (pAlmacenInicial != ' '  y (tAlmacen(cCodigoAlmacen) < pAlmacenInicial))
              // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
              tMovimiento.BUSCA SIGUIENTE[3]
					  	Continua
  					FinSi
	  				Si (pAlmacenFinal != ' ' y (tAlmacen(cCodigoAlmacen) > pAlmacenFinal))
              // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
              tMovimiento.BUSCA SIGUIENTE[3]
		  				Continua
			  		FinSi
				  Sino
            // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
            tMovimiento.BUSCA SIGUIENTE[3]
  					Continua
	  			FinSi

  				// Discriminación por el Filtro de Cliente/Proveedor
	  			tClienteProveedor.Busca[@Str(tDocumento(cIdClienteProveedor);0)]
		  		Si tClienteProveedor->Encontro
			  		Si (pCteProvInicial != ' ' y (tClienteProveedor(cCodigoCliente) < pCteProvInicial))  
              // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
              tMovimiento.BUSCA SIGUIENTE[3]
				  		Continua
					  FinSi
  					Si (pCteProvFinal != ' ' y tClienteProveedor(cCodigoCliente) > pCteProvFinal)
              // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
              tMovimiento.BUSCA SIGUIENTE[3]
	  					Continua
		  			FinSi
			  	Sino
            // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
            tMovimiento.BUSCA SIGUIENTE[3]
  					Continua
	  			FinSi

          // La existencia se obtiene con la fecha final y solo sirve para filtrar
          //! N.D.3682 lExistencia = fExistenciaInicialProducto(tProducto(cIdProducto); tMovimiento(cIdAlmacen); fFechaSiguiente(pFechaFinal); gIdEjercicio; gPeriodo; 2; tProducto(cIdUnidadBase); tProducto(cIdUnidadBase); tMovimientoAuxiliar; tExistencia; tEquivalencia)
          // N.D.3682 Utilizar fExistenciaProducto para obtener la existencia a la fecha indicada (Incluye los movtos de dicho dia)
          lExistencia = fExistenciaProducto(tProducto(cIdProducto); tMovimiento(cIdAlmacen); pFechaFinal; 2; tProducto(cIdUnidadBase); tProducto(cIdUnidadBase); tMovimientoAuxiliar; tExistencia; tEquivalencia; tEjercicio)                   

		  		Si pImprimirProductos = 1 y lExistencia = 0
            // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
            tMovimiento.BUSCA SIGUIENTE[3]
			  		Continua
				  FinSi

  				// Obtención de la moneda
	  			tMoneda.Busca[@Str(tDocumento(cIdMoneda);0)]
		  		// Obtención del Concepto del documento
			  	tConcepto.Busca[@Str(tDocumento(cIdConceptoDocumento);0)]
				  // Obtención del gasto del movimiento
  				lNetoMenosDescuentos = tMovimiento(cNeto) - tMovimiento(cDescuento1) - tMovimiento(cDescuento2) - tMovimiento(cDescuento3) - tMovimiento(cDescuento4) - tMovimiento(cDescuento5)
	  			// Reporte de Proveedores que incluye Gastos
		  		Si pTipoReporte = 2 y pConGastos = 1
            //N.D.6222
            //Si el documento incluye servicios, no se prorratean los gastos en los servicios												
            lTotalMovimiento = tMovimiento(cTotal) 
            lTotalDocumento = tDocumento(cTotal)
            lGastoTotal = tDocumento(cGasto1) +  tDocumento(cGasto2) + tDocumento(cGasto3)
            //Campo usado para guardar el total por servicios se usa para no considerar ese total en el cálculo de gastos
            lTotalDoctoServicios = tDocumento(CIMPCHEQ01)					
            Si lTotalDoctoServicios > 0														
              lGastoTotal = (lTotalMovimiento * lGastoTotal) / (lTotalDocumento - lTotalDoctoServicios)			
            SiNo
              lGastoTotal = (lTotalMovimiento * lGastoTotal) / lTotalDocumento							  
            FinSi							
            lGastoUnitario = lGastoTotal / tMovimiento(cUnidades)
            //Fin N.D.6222						
  				Sino
	  				lGastoUnitario = 0.0
		  		FinSi
      		// N.D.4235 4117 Mostrar la fecha del movimiento
 		    	fImprimeRenglon(tMovimiento(cFecha); lGastoUnitario)
          // N.D.3010 Búsqueda del siguiente registro que cumpla con el producto / docto modelo / afectado
          tMovimiento.BUSCA SIGUIENTE[3]
	  		FinMientras
		  	// Fin recorrido de los movimientos
        lCiclo = lCiclo + 1
      FinMientras
      // Fin ciclo de afectados
      // N.D.1471 Fin
		//!	lFecha = fFechaSiguiente(lFecha)
		//!FinMientras
		//!// Fin recorrido de las fechas
		// N.D.3010 Fin
	FinMientras
	// Fin recorrido de los productos

