sábado, 31 de octubre de 2020

39 - RowSource o cómo actualizar desplegables desde otro formulario.

 Ya hemos visto en video N° 9 cómo utilizar macros o procesos desde diferentes ámbitos o llamadas.

Ahora veremos cómo actualizar un control desplegable que tenemos en nuestro userform abierto cuando la lista se actualiza desde otro formulario. Sin necesidad de cerrarlo y volverlo a abrir.

En el video 39 dejo 3 ejemplos: 

Ej 1- solicitando el nuevo elemento de la lista desde un InputBox.
Nuestro desplegable tendrá asignado el rango a mostrar, desde la propiedad RowSource (no desde el código).

Una vez ingresado el texto en el InputBox se procede a volcarlo a la lista en modo mayúscula.


Private Sub CommandButton1_Click()             'nueva caja

'solicita nuevo nombre (en mayúsculas)

caja = UCase(InputBox("Ingresar nuevo Tipo."))

'si el InputBox queda vacío

If caja = "" Then

    ComboBox2.SetFocus

Else

'agrega a la hoja Listas       'verificar q no se duplique (*)

    With Sheets("Listas")

        .Range("E" & .Range("E" & Rows.Count).End(xlUp).Row + 1) = caja

    End With

                                       

'actualizar el control         'ordenar previamente (**)

    ComboBox2.RowSource = "=cajas"

    ComboBox2.Text = caja

    'opcional: pasarle el foco a algún otro control

    ComboBox4.SetFocus

End If

End Sub


NOTA: las macros para evitar duplicados y ordenar la lista se encuentran en el libro de descarga, en formularios del modelo N° 2.

Ej 2: solicitando el nuevo nombre desde otro Userform con un control TextBox:
En este caso dejamos vacía la propiedad RowSource del control desplegable. Se lo alimentará con el método AddIem desde el evento Initialize del formulario, recorriendo la columna de datos que se encuentra en una hoja (Listas).

Private Sub UserForm_Initialize()

x = Sheets("Listas").Range("A" & Rows.Count).End(xlUp).Row

If x > 2 Then

    For i = 3 To x

        ComboBox1.AddItem Sheets("Listas").Range("A" & i)

    Next i

End If

End Sub


Private Sub CommandButton3_Click()       'nueva marca

'llamar al segundo formulario

UF_ProdMarcas.Show

'al regresar ya se habrá dejado en el control Combobox el texto ingresado

If ComboBox1 <> "" Then

    'guardarlo provisoriamente en una variable

    dato = ComboBox1.Text

    'ordenar la lista

    Call ordenaLISTAS

    'vaciar el combo para actualizarlo nuevamente con la lista actualizada

    ComboBox1.Clear

    For i = 3 To Sheets("Listas").Range("A" & Rows.Count).End(xlUp).Row

        ComboBox1.AddItem Sheets("Listas").Range("A" & i)

    Next i

    'volver a mostrar el dato guardado

    ComboBox1 = dato

End If

End Sub


En el segundo formulario, el botón GUARDAR tendrá el siguiente código:

Private Sub CommandButton2_Click()       

UF_Prod.ComboBox1 = TextBox1     'lo muestra en el control

Unload UF_ProdMarcas 

End Sub 


NOTA: el código completo, con el control para evitar duplicados y macro de ordenamiento se encuentra en el libro de descarga.

Ej 3: llamando a un segundo formulario común a otros procesos.
En este tercer ejemplo, el desplegable se alimenta con la propiedad RowSource declarada en el evento Initialize del formulario principal.

Como en el segundo formulario es posible actualizar la lista con más de un elemento, al cerrarlo se deja vacío el desplegable para realizar la selección.

Private Sub UserForm_Initialize()

filx = Sheets("Listas").Range("C1").CurrentRegion.Rows.Count

ComboBox2.RowSource = "=Listas!C3:C" & filx

End Sub

 

Private Sub CommandButton4_Click()

'se selecciona la primer opción del 2do formulario, dándole el foco al control de texto

UF_VerificaListas.OptionButton1.Value = True

UF_VerificaListas.TextBox1.SetFocus

'se llama al 2do formulario

UF_VerificaListas.Show

'al regresar se actualiza el control combobox con el nuevo rango

ComboBox2.RowSource = "=Listas!C3:C" & Sheets("Listas").Range("C1").CurrentRegion.Rows.Count

             End Sub 

NOTA: el botón de guardado del segundo formulario debe realizar el control de duplicados. Es opcional ordenar la lista desde ese formulario o al regresar al formulario principal (códigos que se encuentran en formulario del modelo N° 2)

Descarga libro completo desde aquí.

Ver Video N° 39 desde aquí.

sábado, 17 de octubre de 2020

38 - Funciones de Conversión para controles TextBox.

Frecuentemente se encuentran consultas acerca de 'errores' al trabajar con controles del tipo TextBox. Errores que no son tales si recordamos que esos controles guardan su información en formato 'Texto'.

Así por ejemplo, en el Video 38 se muestra la comparación entre 2 controles:

TextBox3 = "537"   TextBox5 = "1032"

Si TextBox3 < TexBox5 -------> pinte el control de rojo .... pero veremos que no se pinta. Porque entre textos el primero es mayor.

Por lo tanto, ya sea para realizar cálculos entre estos controles y datos de la hoja o para realizar comparaciones se necesitará convertirlos al formato número según se requiera.

1 - Función VAL: convierte un texto en un valor numérico:

      "537"  ------->  537

      "1432" ------>  1432

Pero si enviamos un valor numérico con decimales a un control TextBox, la función VAL truncará la parte decimal mostrando solamente la parte entera.

Por ejemplo: TextBox3 = 537,40      celda = 1430,50

Al realizar una suma:  suma = VAL(TextBox3) + celda = 537 + 1430,50 =  1957,50 (lo correcto: 1967,90)

2 - Función CDBL: convierte 'texto' con decimales a valor numérico con decimales.

Por ejemplo: TextBox3 = 537,40      TextBox5= 1430,50

Al realizar una suma:  suma = CDBL(TextBox3) + CDBL(TextBox5)

                                     suma = 537,40 + 1430,50 =  1967,90)

IMPORTANTE: La función CDBL dará error si se intenta convertir el contenido de un control vacío. Por lo tanto habrá que contemplar ese posible error, siendo los siguientes ejemplos algunos de los modos posibles.

Ejemplo 1: colocando una instrucción On Error antes de manipular ese control vacío:

'colorear según condición del resultado

On Error Resume Next

If CDbl(TextBox3) < TextBox5.Value Then

    TextBox5.BackColor = &HFF&                  '< rojo

ElseIf CDbl(TextBox3) = Range("G" & filx).Value Then

    TextBox5.BackColor = &H80FF&                '=naranja

Else

    TextBox5.BackColor = &HFFFF&                '> amarillo

End If

Ejemplo 2: evaluar si el control está vacío y en ese caso tomar otra decisión. En este ejemplo se coloca 1 en la celda, sino el valor convertido del control TextBox16:

If TextBox16 <> "" Then

    hox.Range("K" & fily) = CDbl(TextBox16)

Else

    hox.Range("K" & fily) = 1

End If


Ver VIDEO N° 38

viernes, 16 de octubre de 2020

37 - Protección en Excel: libros, hojas y estructura.

 En el siguiente video se muestran las diferentes opciones de protección que nos ofrece Excel:

Video 37

A continuación algunas instrucciones de protección:

1 - Apertura y guardado de Libros:

Sub abreProtegido()

'para abrir libro con contraseña de apertura

nbreLibro = ThisWorkbook.Path & "\Gestoria01.xlsm"

Application.Workbooks.Open nbreLibro, Password:="elsa"

'otro modo de escribir la misma instrucción

Application.Workbooks.Open nbreLibro, , , , "elsa"

End Sub

 

Sub abreEscritura()

'para abrir libro con contraseña de escritura

nbreLibro = ThisWorkbook.Path & "\Gestoria02.xlsm"

Application.Workbooks.Open nbreLibro, WriteResPassword:="yo", Password:="elsa"

'otro modo de escribir la misma instrucción

Application.Workbooks.Open nbreLibro, , , , "elsa", "yo"

End Sub

 

Sub abreSoloLectura()

'para abrir libro como solo lectura

nbreLibro = ThisWorkbook.Path & "\Gestoria03.xlsm"

Application.Workbooks.Open nbreLibro, ReadOnly:=True

'otro modo de escribir la misma instrucción

Application.Workbooks.Open nbreLibro, , True

End Sub

 

Sub guardaProtegido()

'para guardar libro con un nombre distinto al libro activo

nbreLibro = ThisWorkbook.Path & "\Gestoria03.xlsm"

ActiveWorkbook.SaveAs Filename:=nbreLibro, Password:="elsa"

'para guardar libro con el mismo nombre, pero con clave

ActiveWorkbook.SaveAs Password:="miclave"

End Sub

2 - Protección de Hojas:

Sub protegeHoja()

'para Desproteger una hoja con clave

Sheets(1).Unprotect "clave"

'para proteger con clave y algunos permisos

Sheets(1).Protect "clave", DrawingObjects:=True, Contents:=True, Scenarios:=True _

        , AllowFormattingCells:=True, AllowFormattingColumns:=True, _

        AllowFormattingRows:=True, AllowSorting:=True, AllowFiltering:=True, _

        AllowUsingPivotTables:=True

End Sub

3 - Protección de Estructura del libro. Esto permite inhabilitar la opción de crear, quitar o renombrar hojas de un libro.

Sub protegeLibro()

'desprotege la estructura del libro

ActiveWorkbook.Unprotect "tu"

'protege estructura con clave

 ActiveWorkbook.Protect "tu", Structure:=True, Windows:=False

End Sub