Jump to content

YoelMonsalve

Members
  • Content Count

    166
  • Joined

  • Last visited

  • Days Won

    3

Reputation Activity

  1. Upvote
    YoelMonsalve got a reaction from Jesús Díaz R in Aporte al foro: Lista desplegable inteligente - parte 3.   
    Hola amigos del foro, estuve ausente un tiempo por asuntos de trabajao pero vuelvo para retomar un tema anterior del que prometí una tercera parte (y siempre debemos tratar de cumplir la palabra prometida jeje).
    En aquélla ocasión explicaba cómo podemos, a partir de métodos "básicos", emular la función de la característica Validación de Datos de Excel, es decir, una lista desplegable que nos permite escoger dentro de un conjunto limitado de valores para una celda. El ejercicio es en realidad más que todo pedagógico porque si observamos bien el asunto, podríamos operar con macros para establecer el origen de la validación y así lograr un efecto similar, ... pero en fin ya estamos muy adelantados para retroceder.
    En esta ocasión lo que queremos es rellenar fácilmente una tabla de competición cruzada de equipos. Los nombres de los equipos se dan en la Hoja1, agrupados en dos Divisiones o Ligas. En la segunda hoja queremos armar la tabla de juegos. Pero, y no sabría decir si en mi interés pedagógico (o en mi mala fe para complicar las cosas ... jeje), en cada partido sucede que ambos, tanto el equipo Casa como el Visitante podrían provenir de la División A o la B. Entonces, el rango de datos de la Lista Desplegable NO es fijo, sino que cambia entre las dos Ligas, según los OptionButtons situados en la parte de arriba de la hoja de Partidos.
    Por lo que obligatoriamente debemos usar una macro para dinámicamente modificar el origen de datos del DropDown, según querramos elegir de la DivA o la DivB. Por lo cual modificamos ligeramente el método LOAD_Lst explicado en la parte 2 del tema (para poder pasar como segundo argumento el rango de datos a cargar) y creamos dos variantes, LOAD_DivA(), LOAD_DivB() para ser invocadas por los OptionButtons.
    ' Rellena el objeto Dropdown con los valores encontrados en la columna A ' de Hoja1. Sub LOAD_Lst(Lst As DropDown, Header As Range)     Dim SheetName As String     Dim S2 As Worksheet     Dim i As Long, _         N As Long          ' Nombre de la hoja donde buscar los datos. Puede cambiarlo si es     ' necesario.     SheetName = "Equipos"     Set S2 = Sheets(SheetName)          ' calculando el número de elementos a cargar     If Header.Offset(1, 0) = "" Then         N = 0     Else         If Header.Offset(2, 0) = "" Then             N = 1         Else             N = Header.End(xlDown).Row - 1         End If     End If     If N = 0 Then Exit Sub      ' sale, si no hay elementos          ' y rellena la lista     Lst.RemoveAllItems     For i = 1 To N         Lst.AddItem Header.Offset(i, 0)     Next End Sub ' Cargar el DropDown con los equipos de la División A Sub LOAD_DivA()     Dim mylst As DropDown     SET_Lst mylst     If mylst Is Nothing Then Exit Sub     LOAD_Lst mylst, Sheets("Equipos").[A1] End Sub ' Cargar el DropDown con los equipos de la División B Sub LOAD_DivB()     Dim mylst As DropDown     SET_Lst mylst     If mylst Is Nothing Then Exit Sub     LOAD_Lst mylst, Sheets("Equipos").[C1] End Sub Así que para llenar la tabla, por ejemplo en Partido 1, supongamos que juega el equipo Casa de la DivA vs. el equipo Visitante de la DivB. Entonces nos situamos en la celda C3 y marcamos el OptionButton "DivA", luego la lista muestra sólo los equipos de la División A y escogemos el equipo. Luego vamos a la celda D3 y marcamos el OptionButton "DivB", para elegir un equipo de la División B.
    Y así repetimos todo el proceso, en el ejemplo dado para el segundo partido invertí la situación, poniendo el equipo Casa de la DivB vs. el equipo Visitante de la DivA, y así sucesivamente.
    Te adjunto el archivo Excel para que lo pruebes y ¡no olvides! si te gustó este tema, recompénsame con un "me gusta".
    ================================================================================================
    P.D.-  Viendo ahora el tema estoy pensando en crear una parte 4 - implementación de este mismo control usando Clases.
  2. Upvote
    YoelMonsalve got a reaction from Jesús Díaz R in Aporte al foro: Lista desplegable inteligente - parte 3.   
    Hola amigos del foro, estuve ausente un tiempo por asuntos de trabajao pero vuelvo para retomar un tema anterior del que prometí una tercera parte (y siempre debemos tratar de cumplir la palabra prometida jeje).
    En aquélla ocasión explicaba cómo podemos, a partir de métodos "básicos", emular la función de la característica Validación de Datos de Excel, es decir, una lista desplegable que nos permite escoger dentro de un conjunto limitado de valores para una celda. El ejercicio es en realidad más que todo pedagógico porque si observamos bien el asunto, podríamos operar con macros para establecer el origen de la validación y así lograr un efecto similar, ... pero en fin ya estamos muy adelantados para retroceder.
    En esta ocasión lo que queremos es rellenar fácilmente una tabla de competición cruzada de equipos. Los nombres de los equipos se dan en la Hoja1, agrupados en dos Divisiones o Ligas. En la segunda hoja queremos armar la tabla de juegos. Pero, y no sabría decir si en mi interés pedagógico (o en mi mala fe para complicar las cosas ... jeje), en cada partido sucede que ambos, tanto el equipo Casa como el Visitante podrían provenir de la División A o la B. Entonces, el rango de datos de la Lista Desplegable NO es fijo, sino que cambia entre las dos Ligas, según los OptionButtons situados en la parte de arriba de la hoja de Partidos.
    Por lo que obligatoriamente debemos usar una macro para dinámicamente modificar el origen de datos del DropDown, según querramos elegir de la DivA o la DivB. Por lo cual modificamos ligeramente el método LOAD_Lst explicado en la parte 2 del tema (para poder pasar como segundo argumento el rango de datos a cargar) y creamos dos variantes, LOAD_DivA(), LOAD_DivB() para ser invocadas por los OptionButtons.
    ' Rellena el objeto Dropdown con los valores encontrados en la columna A ' de Hoja1. Sub LOAD_Lst(Lst As DropDown, Header As Range)     Dim SheetName As String     Dim S2 As Worksheet     Dim i As Long, _         N As Long          ' Nombre de la hoja donde buscar los datos. Puede cambiarlo si es     ' necesario.     SheetName = "Equipos"     Set S2 = Sheets(SheetName)          ' calculando el número de elementos a cargar     If Header.Offset(1, 0) = "" Then         N = 0     Else         If Header.Offset(2, 0) = "" Then             N = 1         Else             N = Header.End(xlDown).Row - 1         End If     End If     If N = 0 Then Exit Sub      ' sale, si no hay elementos          ' y rellena la lista     Lst.RemoveAllItems     For i = 1 To N         Lst.AddItem Header.Offset(i, 0)     Next End Sub ' Cargar el DropDown con los equipos de la División A Sub LOAD_DivA()     Dim mylst As DropDown     SET_Lst mylst     If mylst Is Nothing Then Exit Sub     LOAD_Lst mylst, Sheets("Equipos").[A1] End Sub ' Cargar el DropDown con los equipos de la División B Sub LOAD_DivB()     Dim mylst As DropDown     SET_Lst mylst     If mylst Is Nothing Then Exit Sub     LOAD_Lst mylst, Sheets("Equipos").[C1] End Sub Así que para llenar la tabla, por ejemplo en Partido 1, supongamos que juega el equipo Casa de la DivA vs. el equipo Visitante de la DivB. Entonces nos situamos en la celda C3 y marcamos el OptionButton "DivA", luego la lista muestra sólo los equipos de la División A y escogemos el equipo. Luego vamos a la celda D3 y marcamos el OptionButton "DivB", para elegir un equipo de la División B.
    Y así repetimos todo el proceso, en el ejemplo dado para el segundo partido invertí la situación, poniendo el equipo Casa de la DivB vs. el equipo Visitante de la DivA, y así sucesivamente.
    Te adjunto el archivo Excel para que lo pruebes y ¡no olvides! si te gustó este tema, recompénsame con un "me gusta".
    ================================================================================================
    P.D.-  Viendo ahora el tema estoy pensando en crear una parte 4 - implementación de este mismo control usando Clases.
  3. Upvote
    YoelMonsalve got a reaction from waltermendez99 in UTILIZAR RANGE CON VALOR DE UNA CELDA   
    Hola WalterMendez. Tu problema se soluciona si declaras explícitamente los tipos de las variables, de acuerdo con la intención que deseas. CeldaLocalizada debe ser un String, igual al valor colocado en la primera celda, que sirva como argumento para que la función Range localice la segunda celda que deseas:

    Dim CeldaLocalizada as String CeldaLocalizada = Hoja3.Cells(2, 17)  Range(CeldaLocalizada).Select
    Walter.xlsm
  4. Upvote
    YoelMonsalve got a reaction from Jesús Díaz R in Aporte al foro: Lista desplegable inteligente - parte 3.   
    Hola amigos del foro, estuve ausente un tiempo por asuntos de trabajao pero vuelvo para retomar un tema anterior del que prometí una tercera parte (y siempre debemos tratar de cumplir la palabra prometida jeje).
    En aquélla ocasión explicaba cómo podemos, a partir de métodos "básicos", emular la función de la característica Validación de Datos de Excel, es decir, una lista desplegable que nos permite escoger dentro de un conjunto limitado de valores para una celda. El ejercicio es en realidad más que todo pedagógico porque si observamos bien el asunto, podríamos operar con macros para establecer el origen de la validación y así lograr un efecto similar, ... pero en fin ya estamos muy adelantados para retroceder.
    En esta ocasión lo que queremos es rellenar fácilmente una tabla de competición cruzada de equipos. Los nombres de los equipos se dan en la Hoja1, agrupados en dos Divisiones o Ligas. En la segunda hoja queremos armar la tabla de juegos. Pero, y no sabría decir si en mi interés pedagógico (o en mi mala fe para complicar las cosas ... jeje), en cada partido sucede que ambos, tanto el equipo Casa como el Visitante podrían provenir de la División A o la B. Entonces, el rango de datos de la Lista Desplegable NO es fijo, sino que cambia entre las dos Ligas, según los OptionButtons situados en la parte de arriba de la hoja de Partidos.
    Por lo que obligatoriamente debemos usar una macro para dinámicamente modificar el origen de datos del DropDown, según querramos elegir de la DivA o la DivB. Por lo cual modificamos ligeramente el método LOAD_Lst explicado en la parte 2 del tema (para poder pasar como segundo argumento el rango de datos a cargar) y creamos dos variantes, LOAD_DivA(), LOAD_DivB() para ser invocadas por los OptionButtons.
    ' Rellena el objeto Dropdown con los valores encontrados en la columna A ' de Hoja1. Sub LOAD_Lst(Lst As DropDown, Header As Range)     Dim SheetName As String     Dim S2 As Worksheet     Dim i As Long, _         N As Long          ' Nombre de la hoja donde buscar los datos. Puede cambiarlo si es     ' necesario.     SheetName = "Equipos"     Set S2 = Sheets(SheetName)          ' calculando el número de elementos a cargar     If Header.Offset(1, 0) = "" Then         N = 0     Else         If Header.Offset(2, 0) = "" Then             N = 1         Else             N = Header.End(xlDown).Row - 1         End If     End If     If N = 0 Then Exit Sub      ' sale, si no hay elementos          ' y rellena la lista     Lst.RemoveAllItems     For i = 1 To N         Lst.AddItem Header.Offset(i, 0)     Next End Sub ' Cargar el DropDown con los equipos de la División A Sub LOAD_DivA()     Dim mylst As DropDown     SET_Lst mylst     If mylst Is Nothing Then Exit Sub     LOAD_Lst mylst, Sheets("Equipos").[A1] End Sub ' Cargar el DropDown con los equipos de la División B Sub LOAD_DivB()     Dim mylst As DropDown     SET_Lst mylst     If mylst Is Nothing Then Exit Sub     LOAD_Lst mylst, Sheets("Equipos").[C1] End Sub Así que para llenar la tabla, por ejemplo en Partido 1, supongamos que juega el equipo Casa de la DivA vs. el equipo Visitante de la DivB. Entonces nos situamos en la celda C3 y marcamos el OptionButton "DivA", luego la lista muestra sólo los equipos de la División A y escogemos el equipo. Luego vamos a la celda D3 y marcamos el OptionButton "DivB", para elegir un equipo de la División B.
    Y así repetimos todo el proceso, en el ejemplo dado para el segundo partido invertí la situación, poniendo el equipo Casa de la DivB vs. el equipo Visitante de la DivA, y así sucesivamente.
    Te adjunto el archivo Excel para que lo pruebes y ¡no olvides! si te gustó este tema, recompénsame con un "me gusta".
    ================================================================================================
    P.D.-  Viendo ahora el tema estoy pensando en crear una parte 4 - implementación de este mismo control usando Clases.
  5. Upvote
    YoelMonsalve got a reaction from smart27 in Cómo crear un TextBox "con clase"   
    Hola amigos de toda la comunidad. En esta ocasión vengo a presentar un tema que nos puede resultar útil en más de una ocasión.
    ¿No nos ha pasado que debemos crear varias instancias de un control de formulario (por ejemplo Textbox), con las mismas propiedades y eventos? En este caso, en lugar de editar manualmente todas las propiedades y escribir manualmente los Callback's para cada uno de los objetos, lo mejor será definir una clase personalizada y definir todos nuestros controles como "instancias" de la clase.
    Para saber más sobre creación de clases en VB pueden consultar este buen tutorial: http://www.recursosvisualbasic.com.ar/htm/tutoriales/c1-creacion-de-clases.htm, o los muchos otros que hay en Internet. También podríamos abrir varios temas de discusión en este foro, .... que me imagino ya existen varios de ellos (¿no?)
    En este caso deseamos crear un Texbox personalizado a nuestro propio estilo, con siguientes características:
     * Tamaño y tipo de letra específico ( Times New Roman, 20 )
     * Color de la letra específico ( blanco )
     * Alineación del texto a la derecha
     * Color de fondo específico ( gris oscuro )
    Los Textbox's serán para contener cantidades numéricas, y por lo tanto todos ellos deberán poseer un Callback para el evento Change que, en caso de recibir un texto que se pueda convertir a un número muestre color de fondo gris, pero en caso contrario muestre un fondo color rojo.
    Imagínate que tuviéramos 10 cajas de texto de este tipo, y tuviéramos que asignar "a mano" todas estas propiedades, además escribir manualmente todos los Callback's. Por ello definimos una clase llamada xNumTBox, la cual consta de un objeto Textbox, un método Set, un método Get, y un controlador de eventos Change().
    Para crear y definir la clase, insertamos un nuevo Módulo de Clase en nuestro proyecto VBA (clic derecho sobre el árbol de elementos del proyecto), damos al módulo el nombre cNumTBox, y escribimos:
    Private WithEvents pTBox As MSForms.TextBox Private Const NormalColor As Long = &H808080 Private Const ErrorColor As Long = &HFF& Fíjate la instrucción WithEvents que acompaña a la declaración el miembro privado pTBox. Esto permite que el miembro pTBox reciba eventos, y por ende puedan a ser pasados a los controladores de eventos privados de la clase (esto lo veremos más adelante).
    O sea, imagínense que la clase recibe un objeto Textbox (normal de MSForms), y realiza ciertas operaciones sobre él, para "convertirlo" en un control personalizado a nuestro estilo. Lo cual por supuesto expande considerablemente las potencialidades de VBA para la creación de Aplicaciones de Formulario.
    El método Set() realiza justo esta función, recibe un objeto TextBox y lo asigna al miembro privado pTBox, además establece ciertos atributos del mismo (color, tipo de letra, etc):
    Public Property Set TBox(control As MSForms.TextBox) Set pTBox = control ' Asignar propiedades / To assign properties With pTBox .Font.Name = "Times New Roman" .Font.Size = 20 .SpecialEffect = fmSpecialEffectEtched .TextAlign = fmTextAlignRight .BackColor = NormalColor .ForeColor = vbWhite End With End Property A continuación mira como definimos un controlador de eventos para el miembro privado PTBox. Una vez el método Set() establezca el control pasado por nosotros (un TextBox normal) como el miembro pTBox, el controlador pTBox_Change() afectará directamente a este control. Es decir, este controlador de eventos afectará a todos los controles de formulario que hayan sido declarados como instancias de la clase cNUmTBox (sin tener que escribir manualmente dicho controlador de eventos para todos y cada uno de los Textbox deseados en nuestro módulo de código de Formulario)
    Private Sub pTBox_Change() Static No_Change As Boolean ' Previene el llamamiento recursivo del Callback / ' Prevents for recursive calling of this Callback If No_Change = True Then Exit Sub Else No_Change = True End If ' Establecer propiedades / Set some properties If pTBox.Text = "" Then pTBox.BackColor = NormalColor ElseIf IsNumeric(pTBox.Text) Then pTBox.BackColor = NormalColor pTBox.Text = Replace(pTBox.Text, ",", ".") Else pTBox.BackColor = ErrorColor End If ' Restaurar flag / Restore flag No_Change = False End Sub En este caso lo que hacemos es simplemente fijar el color de fondo según que la cadena introducida sea o no un número, y lo que puede ser útil dependiendo del proyecto, reemplazar la coma por un punto decimal.
    Ahora, para hacer que un TextBox normal y corriente herede estas propiedades (sin tener que escribirlas a mano para cada control definido), en el módulo de código de Formulario creamos una variable cTBox1 de la clase cNumTBox.
    Dim cTBox1 As cNumTBox Esta definición debe ir antes y por fuera de cualquier procedimiento Sub o Function, para que la vida de la variable sea desde que se muestra hasta que se descarga el formulario.
    En el Userform_Initialize inicializamos la clase con
    Set cTBox1 = New cNumTBox
    Set cTBox1 = New cNumTBox y finalmente si tenemos creado en el Forumario un Textbox (normal y corriente) llamado TBox1, y queremos asociarlo a la clase creada, sólo hay que poner la instrucción
    Set cTBox1.TBox = TBox1 En el archivo adjunto tienes 2 Userform's, uno en el que vemos cómo el Textbox normal es "convertido" a un control personalizado, y otro donde hacemos este procedimiento con varios controles.
    Observa lo que sucede cuando introduces al TextBox una cantidad numérica, y cuándo no es numérica !!!
    Examina los módulos de código, que se encuentran detalladamente explicados y comentariados, y si quieres
    incluir esta clase en tu proyecto simplemente importa el archivo *.cls que te adjunto.
    Existirán temas más avanzados que puedan surgir a partir de éste, como "derivar" clases hijas de esta clase padre, y crear controles dinámicamente para poblar el Formulario, pero lo podemos dejar para una parte 2, y quizá una parte 3 de este mismo tema.
    ======================================================================================
    Saludos, se les quiere a todos, y si te gustó este aporte no olvides darme un "me gusta" correspondiente, es gratis!!
     
     
     
     
     
    cNumTBox.cls
    TextBox_C_Clase_by_Yoel.-parte1.xlsm
     
     
     


  6. Upvote
    YoelMonsalve got a reaction from tierra_pampa in Problemas con rango en listbox   
    Hola olguita, gusto en conocerte. Bueno, además de lo que aportó Dr. Hyde, estuve examinando el código y aunque técnicamente funciona, la parte del llenado del Combobox2 resulta un poco "ruda".
    Pues lo hacen a través de Instrucciones On Error, que no me parece muy aconsejable pues el programa debe evitar la aparición de errores, y no generarlos intencionalmente. Una alternativa más o menos parecida sería:
    ComboBox2.Clear For i = 1 To DATOS.Rows.Count nombre = DATOS.Cells(i, 2) For j = 0 To ComboBox2.ListCount - 1 If ComboBox2.List(j) = nombre Then Exit For Next If j = ComboBox2.ListCount Then ComboBox2.AddItem nombre Next i que inspecciona si el elemento existe en el List(), y sólo en caso contrario lo agrega. Podría hacerse de otras maneras (por ejemplo con Arrays) pero sería complicar el asunto.
    Incluyo el archivo con todas las modificaciones.
    Thanks!
    EJEMPLO LISTAS.xlsm
  7. Upvote
    YoelMonsalve got a reaction from jesus miguel in Formula de suma en rango variable   
    Hola Jesús, gusto en conocerte.
    La Macro FormulaSumar() del Módulo1 inserta automáticamente la fórmula que deseas, al final del campo de datos de la columna "L". Puedes aumentar la columna hacia abajo, pero siempre debe comenzar en la fila 8.
    Ahora, no se cómo quieres invocar la macro, si por medio de un botón, o automáticamente al llenar la hoja .... Coméntame esto, para adaptarlo.
     
     
    jesus-miguel-suma-ByYoel.xlsm
  8. Upvote
    YoelMonsalve reacted to Haplox in (Solucionado) Cambiar calidad de imagen en ImageBox   
    Gracias YoelMonsalve,
     
    El módulo GDI ya lo  había probado, pero el rango exportado es grande, así que el imagebox también debería serlo para usar este método.Por otra parte el CopyPicture no permite configurar propiedades de la imagen exportada (me refiero a características gráficas).
    Al final he solucionado el problema con un código adaptado sacado de esta página:
    Pegar desde Clipboard
    Concretamente el fichero PastePicture.zip de la página. Cargo un fichero emf desde el Cliboard, de esta manera además me evito tener que xportar como imagen y cargarla en el picturebox, con lo que es más rápido y el resultado es muy bueno.
    El código es este:
    Sub ListBox1_Change() Dim i As Integer Dim seleccionados As Integer Dim Rango As Range Dim Imagen As Chart Dim oCht As Chart, lPicType As Long Application.ScreenUpdating = False For i = 0 To ListBox1.ListCount - 1 'verificamos si está o no seleccionado 'en caso afirmativo, acumulamos el contador If ListBox1.Selected(i) = True Then seleccionados = seleccionados + 1 If seleccionados > 1 Then Exit Sub End If End If Next i For i = 0 To ListBox1.ListCount - 1 If ListBox1.Selected(i) Then Directory = Worksheets("Hoja1").Cells(i + 2, 1) Workbooks.Open (Directory & "\" & ListBox1.List(i)) Workbooks.Open(Directory & "\" & ListBox1.List(i)).Activate Set Rango = Range("H2:Q74") lPicType = IIf(obMetafile, xlPicture, xlBitmap) With Rango .CopyPicture xlScreen, lPicType Set oCht = Rango.Parent.ChartObjects.Add(10, 10, .Width, .Height).Chart End With 'Imagen.Paste 'Imagen.ChartArea.Border.LineStyle = 0 'Imagen.ChartArea.Width = Imagen.ChartArea.Width 'Imagen.ChartArea.Height = Imagen.ChartArea.Height 'ActiveChart.Export filename:="C:\temp\1.jpg", filtername:="jpg" ActiveWorkbook.Saved = True ActiveWorkbook.Close End If Next i Set Image1.Picture = PastePicture(lPicType) End Sub Las líneas comentadas al final (desde Imagen.Paste) es todo lo que me evito de exportar, cargar y borrar. La funcion del PastePicture está definida en el archivo que enlacé arriba. este es el resultado:
     

  9. Upvote
    YoelMonsalve got a reaction from cemaaiem in ayuda con validacion de fechas para textbox II   
    Mmmmm, raro, déjame revisar.
    Ok, había unos problemitas con las columnas, tenías "n" y "o", creo que deben ser "k" y "l". Para evitar esto, te puse al inicio del código dos constantes llamandas ColPago y ColVence, simplemente cambia estos valores a los requeridos y serán tomados como tal por el resto del código (pues en las líneas subsiguientes hacemos referencia a estos nombres ColPago y ColVence, más bien que las constantes de letra).
    Vi que quitaste el "VENCIDA", obviamente para que no te sobreescriba las columnas, y ahora simplemente se marca de amarillo en la columna K aquéllas facturas vencidas y sin pago.
    Además, moviste el código al códulo de código Módulo1, no debe estar ahí sino en el módulo de Hoja2 (CXC).
    Revisa y avisa si quedó solucionado!
    CARTERA2017.xlsm
  10. Upvote
    YoelMonsalve got a reaction from olguita9222 in Problemas con rango en listbox   
    Hyde entiendo, sueles trabajar los datos en grupos, creando memoria virtual para ellos. Si mal no recuerdo ofreciste una solución de ese tipo en un post hace poco. Y usar las funciones de Hoja de Cálculo de Excel (vLookUp) cuando sea posible.
    Olguita, que bueno te haya ayudado, en mi particular agradecería si me dieras un "like" y si ya está listo podrías dar el tema cerrado.
  11. Upvote
    YoelMonsalve got a reaction from cemaaiem in ayuda con validacion de fechas para textbox II   
    Mmmmm, raro, déjame revisar.
    Ok, había unos problemitas con las columnas, tenías "n" y "o", creo que deben ser "k" y "l". Para evitar esto, te puse al inicio del código dos constantes llamandas ColPago y ColVence, simplemente cambia estos valores a los requeridos y serán tomados como tal por el resto del código (pues en las líneas subsiguientes hacemos referencia a estos nombres ColPago y ColVence, más bien que las constantes de letra).
    Vi que quitaste el "VENCIDA", obviamente para que no te sobreescriba las columnas, y ahora simplemente se marca de amarillo en la columna K aquéllas facturas vencidas y sin pago.
    Además, moviste el código al códulo de código Módulo1, no debe estar ahí sino en el módulo de Hoja2 (CXC).
    Revisa y avisa si quedó solucionado!
    CARTERA2017.xlsm
  12. Upvote
    YoelMonsalve reacted to Antoni in Problemas con rango en listbox   
    Sin nombres definidos, elimina todo el código del formulario y sustitúyelo por este:
    Dim LISTA As Range, LISTA2 As Range '----------------------------------------------------------------------- Private Sub UserForm_Initialize() Set LISTA = Range("D2:F" & Range("E" & Rows.Count).End(xlUp).Row) 'Ordenamos En proceso LISTA.Sort KEY1:=Columns("E"), KEY2:=Columns("D"), KEY3:=Columns("F") '-- Set LISTA2 = Range("J2:L" & Range("K" & Rows.Count).End(xlUp).Row) 'Ordenamos Detenidos LISTA2.Sort KEY1:=Columns("K"), KEY2:=Columns("J"), KEY3:=Columns("L") '-- For x = 2 To Range("E" & Rows.Count).End(xlUp).Row 'Cargamos Proyectistas sin duplicados If Range("E" & x) <> Range("E" & x + 1) Then ComboBox2.AddItem Range("E" & x) Next '-- UserForm1.Caption = "Proyectos en Proceso" 'Nombramos y reubicamos formulario UserForm1.Move 200, 15 End Sub '----------------------------------------------------------------------- Private Sub ComboBox2_Change() VALOR = ComboBox2.Value With WorksheetFunction cuenta = .CountIf(LISTA.Columns(2), VALOR) 'Obtenemos En proceso FILA = .Match(VALOR, LISTA.Columns(2), 0) Set Proyect = LISTA.Rows(FILA).Resize(cuenta, LISTA.Columns.Count) ListBox1.RowSource = "=" & Proyect.Address '-- cuenta = .CountIf(LISTA2.Columns(2), VALOR) 'Obtenemos Detenidos If cuenta = 0 Then MsgBox ("NO CUENTA CON PROYECTOS DETENIDOS"), vbInformation, "AVISO" ListBox2.RowSource = Empty Else FILA = .Match(VALOR, LISTA2.Columns(2), 0) Set Proyect = LISTA2.Rows(FILA).Resize(cuenta, LISTA2.Columns.Count) ListBox2.RowSource = "=" & Proyect.Address End If End With End Sub '----------------------------------------------------------------------- Private Sub CommandButton1_Click() Unload Me End Sub  
    Nota: Para comprobar la existencia de un valor en un combobox, no hace falta recorrer el combobox, basta con mover el valor al combobox y luego preguntar por el índice.
     
    ComboBox1 = valor If ComboBox1.ListIndex = -1 Then MsgBox "El valor no existe" Else MsgBox "Valor encontrado en elemento " & ComboBox1.ListIndex End If  
  13. Upvote
    YoelMonsalve got a reaction from cemaaiem in ayuda con validacion de fechas para textbox   
    Iba por lo mismo. Tuve que haber escrito:
    If FechaPago = "" And Date > FechaVenc Then ... en lugar de simplemente If FechaPago = "" Then. Es decir, si la fecha de vencimiento ya pasó y sigue sin ser pagada.
    Adjunto archivo modificado.
    ValidarFechas-2-byYoel.xlsm
  14. Upvote
    YoelMonsalve got a reaction from lug barry in ayuda con validacion de fechas para textbox   
    Hola cemaa, en ese caso debes definir un rango de búsqueda e inspeccionar sobre todas las celdas del rango, normalmente con un ciclo FOR. Revisa el archivo adjunto donde coloco mi versión del programa, y de paso observé que estuviste trabajando en el archivo anterior. Por lo cual en esta versión hallarás corregidos algunos de los problemitas de sintaxis que tuviste cuando lo intentaste en el anterior, y pusiste en comentario (y felicitaciones por tu iniciativa)
    En el camino a escribir mi aporte, publicó su respuesta el amigo Enigma ( saludos! ), con el muy conveniente estilo de "Factura Vencida" en la columna E que incorporé "prestado" a mi programa (espero no sea molestia jaja).
    Notarás un argumento mostrarMsg un poco extraño en la función CalcularVencidas(), el cual es para que se invoque la macro tanto si activas la Hoja1, como si cambias los datos en la columna E de la misma. Pero en el primer caso muestra mensaje y en el segundo no (pues sería fastidioso que muestre mensaje cada vez que cambias una celda).
    Algo que no me quedó claro es el criterio para decidir factura vencida, obviamente está vencida y sin pago si la celda contigua de la columna E aparece vacía, ahora en caso contrario que haya pagado pero posterior a la fecha de la columna E, sería acaso "Factura pagada con atraso", o simplemente no se advierte nada ?
    Ten el archivo, y si te gustó mi segunda colaboración contigo no me pondría bravo con otro "like" !
    ValidarFechas-2-byYoel.xlsm

  15. Upvote
    YoelMonsalve reacted to Enigma25 in Ayuda con macro para agregar datos de manera especial   
    Buenas tardes
     
    Dejo mi solución
    Debí copiar y pegar la información de la hoja que usabas anteriormente ya que tenia combinaciones de celdas y eso no ayuda a la hora de registrar información. Creé una nueva hoja con la misma estructura y luego el formulario para registrar la información.
     
    La solucion es registrar informacion en columnas vacias. Ejemplo :
    .Cells(I, Columns.Count).End(xlToLeft).Column De todos modos, dejo el archivo con los cambios.
    Saludos.
    Ayuda Excel-Cuentas.xlsm
     
  16. Upvote
    YoelMonsalve got a reaction from johan moreno in Combobox con Lista Dependiente año/mes   
    Ok, pero si logramos algo sustantivo lo publicamos por aquí (aunque sea una versión demo reducida con valores ficticios), a fin de también compartir el conocimiento, siempre debemos considerar que educar, enseñar y aprender es lo más importante
    Template.xlsm
  17. Upvote
    YoelMonsalve got a reaction from Enigma25 in Ayuda con macro para agregar datos de manera especial   
    Incluye un archivo, aunque sea con datos ficticios por favor. Es necesario saber con exactitud las celdas donde está localizada la información.
    Debes incluir un archivo base de Excel, para ayudarte a partir de ahí.
  18. Upvote
    YoelMonsalve reacted to Antoni in Mostrar imagen en lista que se ordena automaticamente   
    He ligado la actualización de las imágenes al evento Worksheet_Calculate, de manera, que cada vez que modifiques una celda que intervenga en una fórmula las imágenes del bloque 1 (Columna"F") se actualizarán de forma automática.
    He respetado el nombre de los controles Image, no les cambies el nombre porqué dejaría de funcionar el invento.
    Debes asignar el escudo en la propiedad .Picture de las imágenes del grupo2 (Columna "P"), así nos ahorramos tener que cargar las imágenes cada vez que abrimos el archivo, pero lo dejo a tu elección.
    Te dejo el archivo y la macro:
    Private Sub Worksheet_Calculate() Application.ScreenUpdating = False On Error Resume Next Dim y As Range For x = 6 To 24 Step 2 If Not Range("B" & x) = "" Then ActiveSheet.OLEObjects("Image" & Range("A" & x)).Object.Picture = LoadPicture("") Set y = Range("M:O").Find(Range("B" & x)) If Not y Is Nothing Then ActiveSheet.OLEObjects("Image" & Range("A" & x)).Object.Picture = _ ActiveSheet.OLEObjects("Image1" & Range("L" & y.Row)).Object.Picture End If End If Next End Sub  
     
     
    campeonato.xlsm
  19. Upvote
    YoelMonsalve reacted to Antoni in Actualizar fórmula cuando cambio color de celda   
    No se limpiaba el rango seleccionado, ahora creo que funciona correctamente.
    SUMACOLOR.xlsm
  20. Upvote
    YoelMonsalve got a reaction from lug barry in ayuda con validacion de fechas para textbox   
    Hola cemaa, en ese caso debes definir un rango de búsqueda e inspeccionar sobre todas las celdas del rango, normalmente con un ciclo FOR. Revisa el archivo adjunto donde coloco mi versión del programa, y de paso observé que estuviste trabajando en el archivo anterior. Por lo cual en esta versión hallarás corregidos algunos de los problemitas de sintaxis que tuviste cuando lo intentaste en el anterior, y pusiste en comentario (y felicitaciones por tu iniciativa)
    En el camino a escribir mi aporte, publicó su respuesta el amigo Enigma ( saludos! ), con el muy conveniente estilo de "Factura Vencida" en la columna E que incorporé "prestado" a mi programa (espero no sea molestia jaja).
    Notarás un argumento mostrarMsg un poco extraño en la función CalcularVencidas(), el cual es para que se invoque la macro tanto si activas la Hoja1, como si cambias los datos en la columna E de la misma. Pero en el primer caso muestra mensaje y en el segundo no (pues sería fastidioso que muestre mensaje cada vez que cambias una celda).
    Algo que no me quedó claro es el criterio para decidir factura vencida, obviamente está vencida y sin pago si la celda contigua de la columna E aparece vacía, ahora en caso contrario que haya pagado pero posterior a la fecha de la columna E, sería acaso "Factura pagada con atraso", o simplemente no se advierte nada ?
    Ten el archivo, y si te gustó mi segunda colaboración contigo no me pondría bravo con otro "like" !
    ValidarFechas-2-byYoel.xlsm

  21. Upvote
    YoelMonsalve got a reaction from Antoni in Actualizar fórmula cuando cambio color de celda   
    MacroAntonio no se si es sólo a mi que me sucede, pero cambia la celda B2 a color amarillo. Si luego haces doble clic sobre C2 (amarillo) está bien, pero ve lo que sucede si luego haces doble clic alternadamente sobre las demás celdas de la columna C.
  22. Upvote
    YoelMonsalve reacted to ikanni in Actualizar fórmula cuando cambio color de celda   
    Hola Huaso,
    la verdad con lo que pones no es fácil ayudarte.
    Te pego una UDF que hice hace muchos años y que la uso en una hoja personal para mis cosas personales.
    Primer parametro: Color de una casilla(Uso dos casillas maestras para los 2 colores que uso)
    Segundo Parametro: el rango a sumar.
    A ver sí te sirve...
    Saludos
    Ikanni
    Function SumarColor(Celdacolor As Range, RangoASumar As Range) As Currency Dim celda As Range For Each celda In RangoASumar If celda.Interior.ColorIndex = Celdacolor.Interior.ColorIndex Then Sumarcolor = Sumarcolor + celda Next celda End Function  
  23. Upvote
    YoelMonsalve got a reaction from smart27 in Cómo crear un TextBox "con clase"   
    Hola amigos de toda la comunidad. En esta ocasión vengo a presentar un tema que nos puede resultar útil en más de una ocasión.
    ¿No nos ha pasado que debemos crear varias instancias de un control de formulario (por ejemplo Textbox), con las mismas propiedades y eventos? En este caso, en lugar de editar manualmente todas las propiedades y escribir manualmente los Callback's para cada uno de los objetos, lo mejor será definir una clase personalizada y definir todos nuestros controles como "instancias" de la clase.
    Para saber más sobre creación de clases en VB pueden consultar este buen tutorial: http://www.recursosvisualbasic.com.ar/htm/tutoriales/c1-creacion-de-clases.htm, o los muchos otros que hay en Internet. También podríamos abrir varios temas de discusión en este foro, .... que me imagino ya existen varios de ellos (¿no?)
    En este caso deseamos crear un Texbox personalizado a nuestro propio estilo, con siguientes características:
     * Tamaño y tipo de letra específico ( Times New Roman, 20 )
     * Color de la letra específico ( blanco )
     * Alineación del texto a la derecha
     * Color de fondo específico ( gris oscuro )
    Los Textbox's serán para contener cantidades numéricas, y por lo tanto todos ellos deberán poseer un Callback para el evento Change que, en caso de recibir un texto que se pueda convertir a un número muestre color de fondo gris, pero en caso contrario muestre un fondo color rojo.
    Imagínate que tuviéramos 10 cajas de texto de este tipo, y tuviéramos que asignar "a mano" todas estas propiedades, además escribir manualmente todos los Callback's. Por ello definimos una clase llamada xNumTBox, la cual consta de un objeto Textbox, un método Set, un método Get, y un controlador de eventos Change().
    Para crear y definir la clase, insertamos un nuevo Módulo de Clase en nuestro proyecto VBA (clic derecho sobre el árbol de elementos del proyecto), damos al módulo el nombre cNumTBox, y escribimos:
    Private WithEvents pTBox As MSForms.TextBox Private Const NormalColor As Long = &H808080 Private Const ErrorColor As Long = &HFF& Fíjate la instrucción WithEvents que acompaña a la declaración el miembro privado pTBox. Esto permite que el miembro pTBox reciba eventos, y por ende puedan a ser pasados a los controladores de eventos privados de la clase (esto lo veremos más adelante).
    O sea, imagínense que la clase recibe un objeto Textbox (normal de MSForms), y realiza ciertas operaciones sobre él, para "convertirlo" en un control personalizado a nuestro estilo. Lo cual por supuesto expande considerablemente las potencialidades de VBA para la creación de Aplicaciones de Formulario.
    El método Set() realiza justo esta función, recibe un objeto TextBox y lo asigna al miembro privado pTBox, además establece ciertos atributos del mismo (color, tipo de letra, etc):
    Public Property Set TBox(control As MSForms.TextBox) Set pTBox = control ' Asignar propiedades / To assign properties With pTBox .Font.Name = "Times New Roman" .Font.Size = 20 .SpecialEffect = fmSpecialEffectEtched .TextAlign = fmTextAlignRight .BackColor = NormalColor .ForeColor = vbWhite End With End Property A continuación mira como definimos un controlador de eventos para el miembro privado PTBox. Una vez el método Set() establezca el control pasado por nosotros (un TextBox normal) como el miembro pTBox, el controlador pTBox_Change() afectará directamente a este control. Es decir, este controlador de eventos afectará a todos los controles de formulario que hayan sido declarados como instancias de la clase cNUmTBox (sin tener que escribir manualmente dicho controlador de eventos para todos y cada uno de los Textbox deseados en nuestro módulo de código de Formulario)
    Private Sub pTBox_Change() Static No_Change As Boolean ' Previene el llamamiento recursivo del Callback / ' Prevents for recursive calling of this Callback If No_Change = True Then Exit Sub Else No_Change = True End If ' Establecer propiedades / Set some properties If pTBox.Text = "" Then pTBox.BackColor = NormalColor ElseIf IsNumeric(pTBox.Text) Then pTBox.BackColor = NormalColor pTBox.Text = Replace(pTBox.Text, ",", ".") Else pTBox.BackColor = ErrorColor End If ' Restaurar flag / Restore flag No_Change = False End Sub En este caso lo que hacemos es simplemente fijar el color de fondo según que la cadena introducida sea o no un número, y lo que puede ser útil dependiendo del proyecto, reemplazar la coma por un punto decimal.
    Ahora, para hacer que un TextBox normal y corriente herede estas propiedades (sin tener que escribirlas a mano para cada control definido), en el módulo de código de Formulario creamos una variable cTBox1 de la clase cNumTBox.
    Dim cTBox1 As cNumTBox Esta definición debe ir antes y por fuera de cualquier procedimiento Sub o Function, para que la vida de la variable sea desde que se muestra hasta que se descarga el formulario.
    En el Userform_Initialize inicializamos la clase con
    Set cTBox1 = New cNumTBox
    Set cTBox1 = New cNumTBox y finalmente si tenemos creado en el Forumario un Textbox (normal y corriente) llamado TBox1, y queremos asociarlo a la clase creada, sólo hay que poner la instrucción
    Set cTBox1.TBox = TBox1 En el archivo adjunto tienes 2 Userform's, uno en el que vemos cómo el Textbox normal es "convertido" a un control personalizado, y otro donde hacemos este procedimiento con varios controles.
    Observa lo que sucede cuando introduces al TextBox una cantidad numérica, y cuándo no es numérica !!!
    Examina los módulos de código, que se encuentran detalladamente explicados y comentariados, y si quieres
    incluir esta clase en tu proyecto simplemente importa el archivo *.cls que te adjunto.
    Existirán temas más avanzados que puedan surgir a partir de éste, como "derivar" clases hijas de esta clase padre, y crear controles dinámicamente para poblar el Formulario, pero lo podemos dejar para una parte 2, y quizá una parte 3 de este mismo tema.
    ======================================================================================
    Saludos, se les quiere a todos, y si te gustó este aporte no olvides darme un "me gusta" correspondiente, es gratis!!
     
     
     
     
     
    cNumTBox.cls
    TextBox_C_Clase_by_Yoel.-parte1.xlsm
     
     
     


  24. Upvote
    YoelMonsalve got a reaction from cemaaiem in ayuda con validacion de fechas para textbox   
    Hola cema, gusto en conocerte aquí en el Foro. Como dice Toldeman, haría falta el archivo específico, pero especulando creo que necesitas algo como el adjunto.
    La celda D2 (fecha vencimiento) contiene el valor de B2 (fecha emisión) más 30 días. Se programa una macro en el Callback del evento Worksheet_Activate() para que cada vez que seleccionas la Hoja indique si la factura está vencida.
    ===============================================================================================
    Saludos, y si te sirvió este aporte no olvides darme un "me gusta", aquí en la flechita de la esquina inferior derecha
     
    cema-ValidarFechas-byYoel.xlsm

  25. Upvote
    YoelMonsalve got a reaction from smart27 in Cómo crear un TextBox "con clase"   
    Hola amigos de toda la comunidad. En esta ocasión vengo a presentar un tema que nos puede resultar útil en más de una ocasión.
    ¿No nos ha pasado que debemos crear varias instancias de un control de formulario (por ejemplo Textbox), con las mismas propiedades y eventos? En este caso, en lugar de editar manualmente todas las propiedades y escribir manualmente los Callback's para cada uno de los objetos, lo mejor será definir una clase personalizada y definir todos nuestros controles como "instancias" de la clase.
    Para saber más sobre creación de clases en VB pueden consultar este buen tutorial: http://www.recursosvisualbasic.com.ar/htm/tutoriales/c1-creacion-de-clases.htm, o los muchos otros que hay en Internet. También podríamos abrir varios temas de discusión en este foro, .... que me imagino ya existen varios de ellos (¿no?)
    En este caso deseamos crear un Texbox personalizado a nuestro propio estilo, con siguientes características:
     * Tamaño y tipo de letra específico ( Times New Roman, 20 )
     * Color de la letra específico ( blanco )
     * Alineación del texto a la derecha
     * Color de fondo específico ( gris oscuro )
    Los Textbox's serán para contener cantidades numéricas, y por lo tanto todos ellos deberán poseer un Callback para el evento Change que, en caso de recibir un texto que se pueda convertir a un número muestre color de fondo gris, pero en caso contrario muestre un fondo color rojo.
    Imagínate que tuviéramos 10 cajas de texto de este tipo, y tuviéramos que asignar "a mano" todas estas propiedades, además escribir manualmente todos los Callback's. Por ello definimos una clase llamada xNumTBox, la cual consta de un objeto Textbox, un método Set, un método Get, y un controlador de eventos Change().
    Para crear y definir la clase, insertamos un nuevo Módulo de Clase en nuestro proyecto VBA (clic derecho sobre el árbol de elementos del proyecto), damos al módulo el nombre cNumTBox, y escribimos:
    Private WithEvents pTBox As MSForms.TextBox Private Const NormalColor As Long = &H808080 Private Const ErrorColor As Long = &HFF& Fíjate la instrucción WithEvents que acompaña a la declaración el miembro privado pTBox. Esto permite que el miembro pTBox reciba eventos, y por ende puedan a ser pasados a los controladores de eventos privados de la clase (esto lo veremos más adelante).
    O sea, imagínense que la clase recibe un objeto Textbox (normal de MSForms), y realiza ciertas operaciones sobre él, para "convertirlo" en un control personalizado a nuestro estilo. Lo cual por supuesto expande considerablemente las potencialidades de VBA para la creación de Aplicaciones de Formulario.
    El método Set() realiza justo esta función, recibe un objeto TextBox y lo asigna al miembro privado pTBox, además establece ciertos atributos del mismo (color, tipo de letra, etc):
    Public Property Set TBox(control As MSForms.TextBox) Set pTBox = control ' Asignar propiedades / To assign properties With pTBox .Font.Name = "Times New Roman" .Font.Size = 20 .SpecialEffect = fmSpecialEffectEtched .TextAlign = fmTextAlignRight .BackColor = NormalColor .ForeColor = vbWhite End With End Property A continuación mira como definimos un controlador de eventos para el miembro privado PTBox. Una vez el método Set() establezca el control pasado por nosotros (un TextBox normal) como el miembro pTBox, el controlador pTBox_Change() afectará directamente a este control. Es decir, este controlador de eventos afectará a todos los controles de formulario que hayan sido declarados como instancias de la clase cNUmTBox (sin tener que escribir manualmente dicho controlador de eventos para todos y cada uno de los Textbox deseados en nuestro módulo de código de Formulario)
    Private Sub pTBox_Change() Static No_Change As Boolean ' Previene el llamamiento recursivo del Callback / ' Prevents for recursive calling of this Callback If No_Change = True Then Exit Sub Else No_Change = True End If ' Establecer propiedades / Set some properties If pTBox.Text = "" Then pTBox.BackColor = NormalColor ElseIf IsNumeric(pTBox.Text) Then pTBox.BackColor = NormalColor pTBox.Text = Replace(pTBox.Text, ",", ".") Else pTBox.BackColor = ErrorColor End If ' Restaurar flag / Restore flag No_Change = False End Sub En este caso lo que hacemos es simplemente fijar el color de fondo según que la cadena introducida sea o no un número, y lo que puede ser útil dependiendo del proyecto, reemplazar la coma por un punto decimal.
    Ahora, para hacer que un TextBox normal y corriente herede estas propiedades (sin tener que escribirlas a mano para cada control definido), en el módulo de código de Formulario creamos una variable cTBox1 de la clase cNumTBox.
    Dim cTBox1 As cNumTBox Esta definición debe ir antes y por fuera de cualquier procedimiento Sub o Function, para que la vida de la variable sea desde que se muestra hasta que se descarga el formulario.
    En el Userform_Initialize inicializamos la clase con
    Set cTBox1 = New cNumTBox
    Set cTBox1 = New cNumTBox y finalmente si tenemos creado en el Forumario un Textbox (normal y corriente) llamado TBox1, y queremos asociarlo a la clase creada, sólo hay que poner la instrucción
    Set cTBox1.TBox = TBox1 En el archivo adjunto tienes 2 Userform's, uno en el que vemos cómo el Textbox normal es "convertido" a un control personalizado, y otro donde hacemos este procedimiento con varios controles.
    Observa lo que sucede cuando introduces al TextBox una cantidad numérica, y cuándo no es numérica !!!
    Examina los módulos de código, que se encuentran detalladamente explicados y comentariados, y si quieres
    incluir esta clase en tu proyecto simplemente importa el archivo *.cls que te adjunto.
    Existirán temas más avanzados que puedan surgir a partir de éste, como "derivar" clases hijas de esta clase padre, y crear controles dinámicamente para poblar el Formulario, pero lo podemos dejar para una parte 2, y quizá una parte 3 de este mismo tema.
    ======================================================================================
    Saludos, se les quiere a todos, y si te gustó este aporte no olvides darme un "me gusta" correspondiente, es gratis!!
     
     
     
     
     
    cNumTBox.cls
    TextBox_C_Clase_by_Yoel.-parte1.xlsm
     
     
     


×
×
  • Create New...

Important Information

Privacy Policy


CTA Templates.png