     Public Function CrearReporteHTML(sArchivo As String) As String
            Try
                'Cargamos la plantilla
                Dim sRtaPla As String = Path.Combine(DirectorioCAI, "Reportes", sArchivo)
                If Not File.Exists(sRtaPla) Then Throw New Exception("No existe " & sArchivo)
                Dim srPla As New StreamReader(sRtaPla, Encoding.UTF8)
                Dim sPla As String = srPla.ReadToEnd
                srPla.Close()
                'Procesamos
                sPla = NucleoDatos.GenerarDocumento(sPla)
                'Creamos el archivo
                Dim sNme As String = Path.GetFileNameWithoutExtension(sRtaPla) & "_tmp"
                Dim sDir As String = Path.GetDirectoryName(sRtaPla)
                Dim sExt As String = Path.GetExtension(sRtaPla)
                Dim sRtaDoc As String = Path.Combine(sDir, sNme & sExt)
                'Establecemos en la propiedades web del modulo la url del resultado del reporte
                Dim sTblBse As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("engDrlWebProperties")
                If sTblBse.CrearVista({InCondicion("ModuleID", xeClsMain.IDModulo)}).Tabla.Rows.Count > 0 Then _
                sTblBse.Actualizar({InSentencia("WebURL", sRtaDoc, "'")}, {InCondicion("ModuleID", xeClsMain.IDModulo)})
                'Se crea el archivo.
                Dim swDoc As New StreamWriter(sRtaDoc)
                swDoc.WriteLine(sPla)
                swDoc.Flush()
                swDoc.Close()
                Return sRtaDoc
            Catch ex As Exception
                CrearReporteHTML = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.CrearReporteHTML")
            End Try
        End Function
        Public Function ImprimirReporteHTML(sNombreArchivo As String) As Boolean
            Try
                Dim frmTmp As New frmImprimirHTML
                frmTmp.Url = Path.Combine(DirectorioCAI, "Reportes", sNombreArchivo)
                frmTmp.ShowDialog()
                Return True
            Catch ex As Exception
                ImprimirReporteHTML = False
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ImprimirReporteHTML")
            End Try
        End Function
        Public Function ImporteLetras(sCifra As String) As String
            Try
                'Calculamos la cifra y los decimales
                Dim sCfa As String = Format(Val(sCifra), "###,###,###0.00")
                Dim aCfa As String() = Split(sCfa, ".")
                Dim sEnt As String = aCfa(0)
                Dim sDec As String = aCfa(1)
                Dim aBlq As String() = Split(sEnt, ",")
                Dim sPla As String = "{0}pesos {1}/100 m.n"
                Dim sbEntLet As New Text.StringBuilder
                'Se invierten los grupos, en un lista
                Dim lBlq As New List(Of String)
                For Each blq As String In aBlq
                    lBlq.Insert(0, Format(Val(blq), "000"))
                Next
                'Se convierte bloque por bloque a letras
                Dim ci As Integer = 0
                For Each s As String In lBlq
                    sbEntLet.Insert(0, ConvertirBloque(s, ci))
                    ci = ci + 1
                Next
                If Val(sCifra) < 1 Then sbEntLet.Insert(0, "cero ")
                Return UCase(String.Format(sPla, sbEntLet.ToString, sDec))
            Catch ex As Exception
                Return "#Error"
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ImporteLetras")
            End Try
        End Function
        Public Function EstablecerParametrosAC() As Boolean
            Try
                For Each ctl As rtAppControl In rtApplication.Aplicacion.Controles
                    If xeClsMain.IDModulo < 1 Then _
                    Throw New Exception("Debe establecer el ModuleID de la aplicacin desde los parametros.")
                    Dim tblModPar As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("engModuleParameter")
                    Dim aCnd As String() = {InCondicion("ModuleID", xeClsMain.IDModulo),
                                            InCondicion("ParameterKey", "AF" & ctl.ControlCaption, "'")}
                    Dim aSts As String() = {InSentencia("ModuleID", xeClsMain.IDModulo),
                                            InSentencia("Section", "AccesoFacil", "'"),
                                            InSentencia("ParameterKey", "AF" & ctl.ControlCaption, "'"),
                                            InSentencia("ParameterCaption", ctl.ControlCaption, "'"),
                                            InSentencia("Value", ctl.Valor, "'")}
                    If tblModPar.CrearVista(aCnd, "AND").Tabla.Rows.Count > 0 _
                    Then tblModPar.Actualizar(aSts, aCnd, "AND") _
                    Else tblModPar.Agregar(aSts)
                Next
                Return True
            Catch ex As Exception
                EstablecerParametrosAC = False
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.EstablecerParametrosAC")
            End Try
        End Function
        Public Function RecargarDatos(lDataID As String) As String
            Try

            Catch ex As Exception
                Return CAI.Base.NucleoCAI.Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.RecargarDatos")
            End Try
        End Function
        Public Function ActualizarRegistro(sTabla As String, sCampoID As String, sID As String, sCampo As String, sValor As String) As Boolean
            Try
                Dim tblBse As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase(sTabla)

                Dim sFil As String = InCondicion(sCampoID, sID,
                ConexionActual.ObtenerContextoCampo(sTabla, sCampoID))
                Dim sSen As String = InSentencia(sCampo, sValor,
                ConexionActual.ObtenerContextoCampo(sTabla, sCampo))

                tblBse.Actualizar({sSen}, {sFil})
                Return True
            Catch ex As Exception
                ActualizarRegistro = False
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ActualizarRegistro")
            End Try
        End Function
        Public Function AbrirDocumentoXE(lID As Int32) As Boolean
            Try
                Dim oXdc As Object = CreateObject("Document.clsMain") 'New Document.clsMain
                If rtApplication.Aplicacion.ObjetoClsMain Is Nothing _
                Then Throw New Exception("No se conecto con una instancia de XEngine")
                oXdc.XEngineLib = rtApplication.Aplicacion.ObjetoClsMain.XEngineLib
                'oXdc.OpenNewFormBasedOn(lID)
                oXdc.OpenForm(lID, 1, True)
            Catch ex As Exception
                AbrirDocumentoXE = False
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.AbrirDocumentoXE")
            End Try
        End Function
        Public Function Mensaje(sMensaje As String) As Boolean
            Try
                MsgBox(sMensaje)
                Return False
            Catch ex As Exception
                Mensaje = False
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.Mensaje")
            End Try
        End Function
        Public Function EnviarCorreoCFDI(lDocumentID As Long, lUserID As Long, bSSL As Boolean) As Boolean
            Try
                xeDocDocument.DocumentoID(lDocumentID).EnviarCFDi(lUserID, bSSL)
                Return True
            Catch ex As Exception
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.EnviarCorreoCFDI")
            End Try
        End Function
        'Funciones con valor colateral
        Public Function CopiarDocumento(lDocumentID As Long, lModuleID As Long, lDocumentTypeID As Long, lDocRecipientID As Long) As Long
            Try
                Dim docOri As New xeDocDocument(lDocumentID)
                Dim docDes As xeDocDocument = docOri.Copiar()
                docDes.ModuleID = lModuleID
                docDes.DocumentTypeID = lDocumentTypeID
                docDes.DocRecipientID = lDocRecipientID

                Dim DocID As String = docDes.GuardarDocumento()
                Return DocID
            Catch ex As Exception
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.CopiarDocumento")
            End Try
        End Function
        Public Function CopiarDocumentoEncabezado(lDocumentID As Long, lModuleID As Long, lDocumentTypeID As Long, lDocRecipientID As Long) As Long
            Try
                Dim docOri As xeDocDocument = xeDocDocument.DocumentoID(lDocumentID)
                Dim docDes As xeDocDocument = docOri.Copiar(False)
                docDes.ModuleID = lModuleID
                docDes.DocumentTypeID = lDocumentTypeID
                docDes.DocRecipientID = lDocRecipientID

                Dim DocID As String = docDes.Guardar()
                Return DocID
            Catch ex As Exception
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.CopiarDocumentoEncabezado")
            End Try
        End Function
        Public Function CopiarDocumentoPartida(lDocumentItemID As Long, lDocumentID As Long, Optional dCantidad As Double = 0) As Long
            Try
                Dim docItmOri As New xeDocDocumentItem(lDocumentItemID)
                Dim docDes As xeDocDocument = xeDocDocument.DocumentoID(lDocumentID)
                Dim docItmDes As xeDocDocumentItem = docItmOri.Copiar(lDocumentID)

                docItmDes.Quantity = dCantidad
                docItmDes.GuardarPartida()
                docDes.GuardarDocumento()
                Return docItmDes.DocumentItemID
            Catch ex As Exception
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.CopiarDocumentoPartida")
            End Try
        End Function

        Public Function CrearKardexDocumentItem(lDocumentItemID As Long, lDepotID As Long)
            Try
                Dim tblBseKdx As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("orgProductKardex")
                Dim tblBseDcmItm As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("docDocumentItem")
                Dim lScs As New List(Of String)
                Dim dtDocItm As DataTable = tblBseDcmItm.CrearVista({InCondicion("DocumentItemID", lDocumentItemID)}).Tabla

                For Each dr As DataRow In dtDocItm.Rows
                    Dim tblPrd As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("orgProduct")
                    Dim lPid As Long = Val(dr.Item("ProductID").ToString)
                    Dim lDocId As Long = Val(dr.Item("DocumentID").ToString)
                    Dim tblDoc As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("docDocument")
                    Dim lModId As Long = Val(tblDoc.Buscar({InCondicion("DocumentID", lDocId)}, "ModuleID"))
                    Dim dQty As Double = Val(dr.Item("Quantity").ToString)
                    Dim sParUnt As String = dr.Item("Unit").ToString
                    Dim iKsa As Integer = 0 '0= no afecta, 1= afecta a presente, 2= afecta a disponible, 3= afecta ambos, de manera opuesta.
                    Dim xopPrd As New xeOrgProduct(lPid)

                    If sParUnt <> xopPrd.Unit Then
                        'dQty = xopPrd.ObtenerConversionUnidadBase(dQty, sParUnt)
                    End If

                    If lModId > 0 Then
                        Dim tblModPar As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("engModuleParameter")
                        Dim iPsa As Integer = Val(tblModPar.Buscar({InCondicion("ModuleID", lModId),
                                                               InCondicion("ParameterKey", "StockAffectation", "'")}, "Value", "AND"))
                        If iPsa < 0 Then dQty = -(dQty)
                        If iPsa = 0 Then Return 0
                        Select Case Math.Abs(iPsa)
                            Case 1
                                lScs.Add(InSentencia("Quantity", dQty))
                            Case 2
                                lScs.Add(InSentencia("QuantityToBeDelivered", dQty))
                            Case 3
                                lScs.Add(InSentencia("Quantity", dQty))
                                lScs.Add(InSentencia("QuantityToBeDelivered", -(dQty)))
                        End Select
                    End If

                    lScs.Add(InSentencia("DateTransaction", Format(Now, "yyyy/MM/dd"), "'"))
                    lScs.Add(InSentencia("DepotID", lDepotID))
                    lScs.Add(InSentencia("ProductID", lPid))
                    lScs.Add(InSentencia("DocumentID", Val(dr.Item("DocumentID").ToString)))
                    lScs.Add(InSentencia("DocumentItemID", Val(dr.Item("DocumentItemID").ToString)))
                    lScs.Add(InSentencia("AmountPrice", Val(dr.Item("UnitPrice").ToString)))
                    lScs.Add(InSentencia("Cancelled", 0))
                    lScs.Add(InSentencia("ProductImportID", Val(dr.Item("ProductImportID").ToString)))
                    lScs.Add(InSentencia("DepotValue", 0))
                    lScs.Add(InSentencia("DepotValueAverage", 0))
                    lScs.Add(InSentencia("QuantityImport", 0))

                    tblBseKdx.Agregar(lScs.ToArray)
                Next
                If dtDocItm.Rows.Count Then _
                Return tblBseKdx.UltimoID("StockTransactionID") _
                Else Return 0
            Catch ex As Exception
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.CrearKardexDocumentItem")
            End Try
        End Function
        Public Function EstablecerDocDocumentExt(lDocumentID As Long, sCampo As String, sValor As String)
            Try
                Dim tblDde As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("docDocumentExt")
                If ConexionActual.ColumnaTablaExiste("docDocumentExt", sCampo) Then
                    Dim sStc As String = InSentencia(sCampo, sValor, ConexionActual.ObtenerContextoCampo("docDocumentExt", sCampo))
                    Dim sCnd As String = InCondicion("IDExtra", lDocumentID)
                    Dim dtDde As DataTable = tblDde.CrearVista({sCnd}).Tabla

                    If dtDde.Rows.Count > 0 Then
                        tblDde.Actualizar({sStc}, {sCnd})
                    Else
                        tblDde.Agregar({sStc, InSentencia("IDExtra", lDocumentID)})
                    End If
                End If
                Return Nothing
            Catch ex As Exception
                Return Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.CrearKardexDocumentItem")
            End Try
        End Function
        'Funciones con valor variable
        Public Function BuscarValorBD(sTabla As String, sCampoFiltro As String, sValorFiltro As String, aCampo As String) As String
            Try
                Dim tblTbl As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase(sTabla)
                Dim sFil As String = InCondicion(sCampoFiltro, sValorFiltro, ConexionActual.ObtenerContextoCampo(sTabla, sCampoFiltro))
                Return tblTbl.Buscar({sFil}, aCampo)
            Catch ex As Exception
                BuscarValorBD = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.BuscarValorBD")
            End Try
        End Function
        Public Function ObtenerFolioPrefijoFormato(sTabla As String, sCampo As String, sPrefijo As String, sFormato As String) As String
            Try
                Dim tblTbl As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase(sTabla)
                Dim sFil As String = InCondicionLike(sCampo, sPrefijo)
                Dim sFilDel As String = InCondicion("DeletedOn", "Null", , " is ")
                Dim dtFol As DataTable = tblTbl.CrearVista({sFil, sFilDel}, "And").Tabla
                Dim lFol As Long = 0
                For Each dr As DataRow In dtFol.Rows
                    Dim lTmpFol As Long = 0
                    Dim sFol As String = dr.Item(sCampo).ToString
                    If sFol.Length > sPrefijo.Length Then
                        sFol = Right(sFol, sFol.Length - sPrefijo.Length)
                        lTmpFol = Val(sFol)
                    End If
                    If lTmpFol > lFol Then lFol = lTmpFol
                Next
                lFol += 1
                Return sPrefijo & Format(lFol, sFormato)
            Catch ex As Exception
                ObtenerFolioPrefijoFormato = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.BuscarValorBD")
            End Try
        End Function
        Public Function ObtenerFolioDocumento(lDocumentTypeID As Long, Optional lDocRecipientID As Long = 0, Optional lModuleID As Long = 0) As String
            Try
                Dim tblTbl As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("docDocument")
                Dim lCnd As New List(Of String)

                lCnd.Add(InCondicion("DocumentTypeID", lDocumentTypeID))
                lCnd.Add(InCondicion("DeletedOn", "null",, " is "))
                If lDocRecipientID > 0 Then lCnd.Add(InCondicion("DocRecipientID", lDocRecipientID))
                If lModuleID > 0 Then lCnd.Add(InCondicion("ModuleID", lModuleID))

                Dim dtFol As DataTable = tblTbl.CrearVista(lCnd.ToArray, "And").Tabla
                Dim lFol As Long = 0
                For Each dr As DataRow In dtFol.Rows
                    Dim sFol As String = dr.Item("Folio").ToString
                    If Val(sFol) > lFol Then lFol = Val(sFol)
                Next
                lFol += 1
                Return lFol
            Catch ex As Exception
                ObtenerFolioDocumento = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ObtenerFolioDocumento")
            End Try
        End Function
        Public Function AoActualYY() As String
            Try
                Return Format(Now, "yy")
            Catch ex As Exception
                AoActualYY = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.AoActualYY")
            End Try
        End Function
        Public Function MensajeSiEs(sValor1 As String, sValor2 As String, sMensaje As String) As Boolean
            Try
                Dim aCri As String() = Split(sValor2, "|")
                For Each str As String In aCri
                    If sValor1 = str Then Throw New Exception(sMensaje)
                Next
                Return True
            Catch ex As Exception
                MensajeSiEs = False
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.MensajeSiEs")
            End Try
        End Function
        'Funciones con valor de estructura de XEngine
        Public Function ObtenerOrgContactUserID(lUserID As Long, sCampo As String) As String
            Try
                Dim tblBse As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("engUser")
                Dim tblCtc As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("orgContact")
                Dim lCtcID As Long = Val(tblBse.Buscar({InCondicion("UserID", lUserID)}, "ContactID"))
                Return tblCtc.Buscar({InCondicion("ContactID", lCtcID)}, sCampo)
            Catch ex As Exception
                ObtenerOrgContactUserID = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ObtenerOrgContactUserID")
            End Try
        End Function
        Public Function ObtenerOrgContact(lContactID As Long, sCampo As String) As String
            Try
                Dim tblCtc As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("orgContact")
                Return tblCtc.Buscar({InCondicion("ContactID", lContactID)}, sCampo)
            Catch ex As Exception
                ObtenerOrgContact = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ObtenerOrgContact")
            End Try
        End Function
        Public Function ObtenerOrgCustomer(lCustomerID As Long, sCampo As String)
            Try
                Dim tblCtc As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("orgCustomer")
                Return tblCtc.Buscar({InCondicion("CustomerID", lCustomerID)}, sCampo)
            Catch ex As Exception
                ObtenerOrgCustomer = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ObtenerOrgCustomer")
            End Try
        End Function
        Public Function ObtenerOrgCustomerBusinessEntityID(lBusinessEntityID As Long, sCampo As String) As String
            Try
                Dim tblCtc As NucleoBaseDatos.TablaBase = NucleoBaseDatos.TablaBase.TablaBase("orgCustomer")
                Return tblCtc.Buscar({InCondicion("BusinessEntityID", lBusinessEntityID)}, sCampo)
            Catch ex As Exception
                ObtenerOrgCustomerBusinessEntityID = ""
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ObtenerOrgCustomerBusinessEntityID")
            End Try
        End Function

        Public Function ConciliacionAutomatica() As Boolean
            Try
                xeDocEdoCtaBanco.Conciliar()
                Return True
            Catch ex As Exception
                ConciliacionAutomatica = False
                Excepciones.ProcesarExcepcion _
                (ex, "FuncionesCAI.ConciliacionAutomatica")
            End Try
        End Function