Introducción.
Continuación del Tutorial de control ActiveX ListView-01 de la semana pasada.
En esta sesión del tutorial, aprenderemos cómo buscar y encontrar los valores de fila y columna en particular y mostrarlos en un control de etiqueta en el formulario. Esto es muy útil cuando tenemos un gran volumen de datos en el control ListView. También aprenderemos el uso de algunas configuraciones de propiedades de ListView.
En primer lugar, veremos lo fácil que es reorganizar las columnas, como lo hacemos con Access Datasheet View de la forma en que queremos que estén en ListView Control. Hemos agregado algunos cuadros de texto, cuadros combinados, botones de comando y etiquetas para facilitar la selección de parámetros de búsqueda y la visualización de resultados de búsqueda.
He realizado algunos cambios en los datos de demostración de la semana pasada. Los valores de la primera columna los he tomado de la base de datos de ejemplo de la tabla de empleados de Northwind.accdb. Creó una consulta para unir los valores de apellido y nombre con el nombre de campo Student y EmployeeID utilizados como clave (X01, X02 ...).

Antes de pasar a las operaciones de búsqueda, comprobaremos cómo reorganizar las columnas mediante el método de arrastrar y soltar.
Nota: Si no ha pasado por la página del tutorial anterior y desea continuar con esta sesión, vaya a la página Tutorial-01 de ListView Control y descargue la base de datos de demostración desde la parte inferior de esa página.
Descomprima el archivo y abra la base de datos. El formulario de demostración estará en vista normal.
-
Abre tu Base de Datos, con el Formulario Demo de la última sesión, o el Formulario que has creado, ábrelo en Vista Normal.
Ahora, intentaremos arrastrar y mover una columna desde el medio de la lista (por ejemplo, la columna Peso) y soltarla en Edad. columna y ver qué pasa. Lo que se espera que suceda es que la columna Edad se desplace hacia la derecha e inserte la columna entrante en su lugar.
-
Mueva el puntero del mouse sobre el encabezado de columna con el nombre Peso, haga clic y mantenga presionado el botón izquierdo del mouse. Cuando presiona el botón izquierdo del mouse, el encabezado de la columna se moverá ligeramente hacia abajo.
-
Ahora, intente arrastrar la columna hacia la izquierda y suéltela en la columna Edad .
No pasará nada, porque no hemos habilitado esta función en la hoja de propiedades y esa es la única configuración que debemos cambiar para que esta función funcione.
-
Cambie el formulario en la vista de diseño.
-
Haga clic con el botón derecho en ListView Control y resalte la opción Objeto ListViewCtrl y seleccione Propiedades.
-
Hay una opción 'AllowColumnReorder ' en el lado derecho. Coloque una marca de verificación para seleccionarlo, luego haga clic en Aplicar botón seguido de OK para cerrar la vista de propiedades.
-
Ahora, intente repetir los pasos 2 y 3 anteriores y vea qué sucede.
Esa es la única configuración que necesita para habilitar esta función en ListView Control. Quizás estés pensando, ¿qué hay de reorganizar las filas?.
Esa función necesita programar algunos procedimientos de eventos como lo hicimos anteriormente en TreeView Control Drag-Drop Events. Esa parte la haremos después de algún tiempo.
-
Puede experimentar con cualquier columna para moverla a cualquier lugar que desee, incluida la primera columna también.
Nota: Antes de soltar la columna de origen, compruebe que la columna de destino esté cubierta por el marco de la columna entrante antes de intentar soltarla. De lo contrario, la columna entrante puede cambiar a la siguiente posición de columna en el lado derecho.
A continuación, aprenderemos cómo encontrar información de ListView rápidamente, asumiendo que tenemos un gran volumen de datos en él.
Hemos agregado una subrutina al módulo Tutorial-01 para cargar los nombres de encabezado de columna en un cuadro combinado en el formulario con el color de fondo rojo. El nombre de la columna se usará para encontrar el valor de la columna (edad, altura, peso o clase) de un estudiante.
Nuevo código VBA agregado al módulo de clase de formulario.
El siguiente procedimiento nuevo de VBA se agregó al módulo de clase del formulario de tutorial de la semana pasada:
El txtColCombo crea la lista de etiquetas de encabezado de columna (nombres de campo) en el ComboBox. Uno de estos detalles de la edad, altura, peso del estudiante o Clase se puede encontrar junto con el nombre del estudiante como parte de la operación de búsqueda y hallazgo.
Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub
El cuadro combinado no se cargará con un valor predeterminado de nombre de encabezado de columna. Si se selecciona, el valor de la columna del estudiante se muestra en la etiqueta grande debajo del nombre del estudiante. Si se deja en blanco, la operación de búsqueda solo encontrará el nombre del estudiante.
El método de operación de búsqueda es muy flexible y rápido. Tenemos dos métodos para encontrar un registro.
Encuentre el registro proporcionando el texto de búsqueda. El texto de búsqueda puede ser de cualquiera de las columnas, ya sea el texto completo o algunos caracteres parciales de la izquierda. Dado que tenemos dos categorías de miembros de objetos en una fila en el control ListView:ListItem - la primera columna y las demás columnas son ListSubItems. La operación de búsqueda de texto en estos objetos se realiza por separado.
Se proporciona un grupo de opciones con dos casillas de verificación junto al cuadro de texto de entrada de texto de búsqueda en el formulario para seleccionar las opciones de búsqueda y búsqueda. La primera opción está seleccionada por defecto y la búsqueda se realiza en la primera Columna (ListItem ) para buscar el texto dado.
Seleccione la segunda opción para buscar el texto en el ListSubItem columnas.
Nota: Reorganizar las columnas no cambiará los objetos, sino solo su posición de visualización. Arrastrando un ListSubItem columna y colocarla en la primera columna no cambiará en un ListItem objeto.
Si desea recuperar un valor desconocido de una columna en particular, seleccione un nombre de columna del cuadro combinado que se encuentra debajo del primer cuadro de texto en el formulario para el texto de búsqueda. Por ejemplo, si no conoce la medida de altura de un estudiante y le gustaría averiguarlo, seleccione el nombre de columna Altura del cuadro combinado.
Después de configurar los valores anteriores, haga clic en Buscar elemento Botón de comando para ir a la operación de búsqueda. Si la búsqueda fue exitosa, el resultado se mostrará en el control de etiqueta grande debajo del botón de comando.
Haga clic en el botón de comando [Buscar elemento].
Llama a SearchAndFind() Procedimiento.
Private Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lvwList.ListItems.Item(j).Selected = True lblMsg.caption = msgText End If End Sub
Al comienzo del programa, tanto el Nombre del estudiante y Nombre de columna ( 0opcional), se copian de los cuadros de texto a las variables strFind y strColName respectivamente después de las comprobaciones de validación.
Nota: El nombre de la columna Combo Box's Non-in-List Property se establece en Sí. Puede seleccionar un valor válido de la lista o escribirlo o dejar el cuadro combinado en blanco. Si ingresa un valor diferente que no está en la lista, no será aceptado.
Según la opción de búsqueda seleccionada (1 - ListItem o 2 - ListSubItem), el método de exploración se dirige a los objetos especificados.
El uso de cualquiera de estos métodos de búsqueda encontrará el Objeto ListItem o fila que contiene el texto de búsqueda. El valor de índice de ListItem se guarda en la variable J para su uso posterior en el programa.
Nota: El sistema crea los números automáticos del índice automáticamente en el momento en que se completan los elementos de control de ListView.
El ListItem.Text se recupera el valor. Esta información se une con el primer encabezado de columna. Texto (como Estudiante:Robert King) y agregado a la cadena Msgtext para mostrar en el control Etiqueta en el Formulario.
Si se selecciona la columna Nombre del encabezado en el ComboBox, entonces GetColVal() La función se llama con el objeto ListItem y el valor del texto del encabezado de columna como parámetros. Esta opción es buena para recuperar información desconocida sobre un estudiante, como la altura del estudiante, del registro.
El código VBA de la función GetColVal().
Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function
La función anterior pide dos parámetros. El primer parámetro es ListItem, donde se encuentra el nombre del estudiante. El segundo parámetro es el nombre de la columna. La edad, altura, peso, clase del estudiante seleccionado los valores se almacenan en ListItem.ListSubItems Objetos. La función mira a través de lvwList.ColumnHeader valores para encontrar el nombre de columna coincidente, cuando se encuentra que el número de índice de columna se usa para recuperar el valor de columna del objeto ListSubItems y devuelve el valor al programa que llama.
El botón de comando [Buscar por clave] haga clic en el procedimiento de evento.
Hemos agregado otro método para encontrar el nombre del estudiante usando el valor clave único de ListItem si se usa al crear la lista ListItem. Aunque es opcional, es mejor agregar Valor de cadena de clave único (debe comenzar con un carácter alfabético) en lugar de ignorarlo.
Por ejemplo, si tenemos que encontrar la información de alguien por su número de identificación, como el número de seguro social, el número de documento nacional de identidad, el número de pasaporte o el número de licencia de conducir, etc., una de estas informaciones se puede utilizar como valor clave para ListItem. Encontrar un registro con este valor único es muy fácil y rápido en lugar del método de búsqueda por texto anterior.
El procedimiento de evento cmdKey_Click().
Calls FindByKey() Subroutine.
Private Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") If len(lvKeyVal) > 0 then On Error Resume Next Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!",vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Como puede ver en la subrutina anterior, podríamos encontrar directamente el ListItem donde está el nombre del Estudiante, con el uso de la Clave-valor, con una sola instrucción:Establecer lvItem =lvwList.ListItems.Item(xKeyVal).
La siguiente línea lee el texto ListItem (o el nombre del estudiante) en la variable txt . Las siguientes dos líneas crean el texto del mensaje con el nombre del estudiante en la variable de cadena msgText.
El próximo Si . . .Entonces La instrucción comprueba si se ha introducido un valor de nombre de columna en el control del cuadro combinado. Si se encuentra, llama a GetColVal() Función con los parámetros requeridos para encontrar el valor de la columna y recuperarlo en varColVal Variable y vuelve al programa de llamada. El nombre de columna y su valor recuperado se agregan a la variable de cadena msgText para mostrar en el control de etiqueta en el formulario.
La siguiente declaración resalta el registro Fila del estudiante como una indicación visual de que el elemento buscado se encuentra en la fila. El valor de msgText se muestra en la propiedad de título de la etiqueta en el formulario.
El código VBA completo en el módulo de formulario.
Option Compare Database Option Explicit Dim lvwList As MSComctlLib.ListView 'ListView Control Dim lvwItem As MSComctlLib.ListItem ' Dim ObjImgList As MSComctlLib.ImageList Const prfx As String = "K" Private Sub Form_Load() Call LoadListView Call txtColCombo End Sub Private Function LoadListView() 'Populate the ListView control with Student Details Dim db As DAO.Database Dim rst As DAO.Recordset Dim intCounter As Integer Dim strKey As String 'Assign ListView Control on Form to lvwList Object Set lvwList = Me.ListView1.Object With lvwList .AllowColumnReorder = True .Enabled = True .Font = "Verdana" .Font.Bold = True .Font.Size = 9 .ForeColor = vbBlack .BackColor = vbWhite End With 'Create Column Headers for ListView With lvwList .ColumnHeaders.Clear 'initialize header area 'Syntax: .ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon .ColumnHeaders.Add , , "Student", 2500 .ColumnHeaders.Add , , "Age", 1200 .ColumnHeaders.Add , , "Height", 1200 .ColumnHeaders.Add , , "weight", 1200 .ColumnHeaders.Add , , "Class", 1200 End With 'Initialize ListView Control While lvwList.ListItems.Count > 0 lvwList.ListItems.Remove (1) Wend 'Student Names and Ids are taken from Employees Table 'through the StudentQ Query. Set db = CurrentDb Set rst = db.OpenRecordset("StudentQ", dbOpenDynaset) With lvwList Do While Not rst.EOF And Not rst.BOF intCounter = rst![EmployeeID] strKey = "X" & Format(intCounter, "00") 'Key Value sample: X01 'Syntax: .ListItems.Add(Index, Key, Text, Icon, SmallIcon) Set lvwItem = .ListItems.Add(, strKey, rst![Student]) With lvwItem 'Syntax: .Add Index,Key,Text,Report Icon,TooltipText .ListSubItems.Add , strKey & CStr(intCounter), CStr(5 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 1), CStr(135 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 2), CStr(40 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 3), ("Class:" & Format(intCounter, "00")) End With rst.MoveNext Loop rst.Close Set rst = Nothing Set db = Nothing Set lvwItem = Nothing End With lvwList.Refresh End Function Private Sub cmdClose_Click() DoCmd.Close acForm, Me.Name End Sub Private Sub cmdFind_Click() Call SearchAndFind End Sub Private Sub cmdKey_Click() Call FindByKey End Sub Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub Public Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found in the List!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lblMsg.caption = msgText lvwList.ListItems.Item(j).Selected = True End If End Sub Public Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") On Error Resume Next If Len(lvKeyVal) > 0 Then Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!", vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Descargue la base de datos de demostración desde el siguiente enlace:
- Tutorial de control TreeView de Microsoft
- Creación del menú de acceso con TreeView Control
- Asignación de imágenes a nodos TreeView
- Asignación de imágenes a TreeView Nodes-2
- Control de TreeView Marca de verificación Agregar Eliminar
- Acceso desplegable de TreeView ImageCombo
- Reorganizar los nodos de TreeView arrastrando y soltando
- Control ListView con MS-Access TreeView
- Eventos de arrastrar y soltar de control ListView
- Control TreeView con subformularios