Introducción.
Estamos familiarizados con las operaciones de arrastrar y soltar en TreeView Control, en Ms-Access que reorganiza los nodos. Todos los registros base para los nodos de control Treeview provienen de una única tabla de acceso. Siempre actualizamos el ParentID del nodo de origen valor de campo, con el Valor de ID del Nodo de Destino en el mismo registro de la Tabla, para realizar el cambio de posición en el Control TreeView. Los registros no se mueven físicamente a ningún lado.
Aquí, con la adición de ListView Control junto con TreeView Control, planeamos trabajar con dos tablas de acceso diferentes.
- lvCategory:código de categoría y descripción.
- lvProducts:productos por categoría.
De esta forma es más fácil entender la relación entre ambas Tablas. Qué cambios tenemos que hacer y dónde, cuando un elemento de producto (elemento ListView) se mueve de una categoría a otra en el control TreeView.
La categoría lv Access Table tiene 20 registros para TreeView Nodes y lvProducts La tabla tiene 45 para el control ListView. Uno o más registros en la tabla Productos están directamente relacionados con una categoría de productos en la Tabla de categorías. La relación entre ellos se actualizó con el valor del campo Id. de categoría (CID) en el ParentID de la tabla de productos. campo para que el cambio de categoría del producto se refleje inmediatamente en el ListView Control.
La tabla de datos de demostración se tomó de Microsoft Access Sample Database Northwind.accdb y se dividió en dos partes.
Según el valor del campo ParentID, de los registros lvProduct, podríamos filtrar y enumerar todos los elementos de productos relacionados en el control ListView, cuando se selecciona un nodo de categoría en el control TreeView.
Temas que hemos cubierto hasta ahora.
Los siguientes son los temas principales en TreeView , Lista de imágenes , ImageCombo, y Vista de lista Controles que hemos cubierto hasta ahora en MS-Access:
- Tutorial de control TreeView de Microsoft
- Creación del menú de acceso con TreeView Control
- Asignación de imágenes al control TreeView
- Asignación de imágenes a TreeView Control-2
- Control de TreeView Marca de verificación Agregar Eliminar nodos
- Menú de acceso desplegable TreeView ImageCombo
- Reorganizar los nodos de TreeView arrastrando y soltando
- Control ListView con MS-Access TreeView
La tarea de arrastrar y soltar ListView.
En lo que respecta a la operación de arrastrar y soltar de ListView, es un ejercicio simple que compara el mismo método solo dentro del control TreeView. Dado que la acción Arrastrar y soltar involucra tanto los controles TreeView como ListView, usamos el mismo procedimiento de evento TreeView0_OLEDragDrop() con un código VBA simple.
Los elementos del producto enumerados en el control ListView pertenecen al elemento de categoría actual seleccionado en el control TreeView.
El usuario selecciona un elemento de producto en particular del control ListView, si cree que pertenece a un elemento de categoría diferente, luego arrástrelo y suéltelo en el elemento de categoría de destino en el control TreeViewC.
El elemento de producto ListView movido se agregará a la lista de elementos que pertenecen a la categoría modificada. El valor del campo ParentID del registro del producto se actualiza con el ID del registro de la categoría de destino (valor CID).
Es solo una acción unidireccional, siempre mueva el elemento ListView de una categoría y colóquelo en un nodo de categoría diferente en el control TreeView.
El formulario de acceso de demostración de arrastrar y soltar de ListView frmListViewDrag’ La imagen de la pantalla de ejecución de prueba se muestra a continuación:

En la Imagen de arriba, las Bebidas Se ha seleccionado la categoría en TreeView. Los productos pertenecientes a la categoría Bebidas han sido listados en el ListView Control.
La vista de diseño del formulario anterior:

La lista de nombres de control en el formulario es la siguiente:
- Control TreeView:TreeView0
- Control de vista de lista:Vista de lista0
- Control de lista de imágenes:ImageList3
- Botón de comando:cmdCerrar
El código VBA en frmListViewDrag Módulo de clase:
Option Compare Database Option Explicit Dim tv As MSComctlLib.TreeView Dim lvList As MSComctlLib.ListView Dim imgList As MSComctlLib.ImageList Const Prfx As String = "X" Private Sub Form_Load() Dim db As DAO.Database Dim tbldef As TableDef Set tv = Me.TreeView0.Object tv.Nodes.Clear Set imgList = Me.ImageList3.Object With tv .Font.Size = 9 .Font.Name = "Verdana" .ImageList = imgList 'assign preloaded imagelist control End With Set lvList = Me.ListView0.Object lvList.ColumnHeaders.Clear lvList.ListItems.Clear lvList.Icons = imgList Set db = CurrentDb Set tbldef = db.TableDefs("lvProducts") 'Initialize ListView & Column Headers Property Values With lvList .ColumnHeaderIcons = imgList .Font.Size = 9 .Font.Name = "Verdana" .Font.Bold = False 'ColumnHeaders.Add() Syntax: 'lvList.ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon 'Alignment: 0 - Left, 1 - Right, 2 - Center .ColumnHeaders.Add 1, , tbldef.Fields(1).Name, 2600, 0, 5 .ColumnHeaders.Add 2, , tbldef.Fields(3).Name, 2600, 0, 5 .ColumnHeaders.Add 3, , tbldef.Fields(4).Name, 1440, 1, 5 End With Set db = Nothing Set tbldef = Nothing LoadTreeView 'Create TreeView Nodes End Sub Private Sub LoadTreeView() Dim Nod As MSComctlLib.Node Dim firstCatID As Long Dim strCategory As String Dim strCatKey As String Dim strBelongsTo As String Dim strSQL As String Dim db As DAO.Database Dim rst As DAO.Recordset 'Initialize treeview nodes tv.Nodes.Clear 'Initialize Listview nodes While lvList.ListItems.Count > 0 lvList.ListItems.Remove (1) Wend strSQL = "SELECT lvCategory.CID, lvCategory.Category, " strSQL = strSQL & "lvcategory.BelongsTo FROM lvCategory ORDER BY lvCategory.CID;" Set db = CurrentDb Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot) If Not rst.BOF And Not rst.EOF Then rst.MoveFirst firstCatID = rst!CID Else Exit Sub End If ' Populate all Records as Rootlevel Nodes Do While Not rst.BOF And Not rst.EOF strCatKey = Prfx & CStr(rst!CID) strCategory = rst!Category Set Nod = tv.Nodes.Add(, , strCatKey, strCategory, 1, 2) Nod.Tag = rst!CID rst.MoveNext Loop 'In the second pass of the the same set of records 'Move Child Nodes under their Parent Nodes rst.MoveFirst Do While Not rst.BOF And Not rst.EOF strBelongsTo = Nz(rst!BelongsTo, "") If Len(strBelongsTo) > 0 Then strCatKey = Prfx & CStr(rst!CID) strBelongsTo = Prfx & strBelongsTo strCategory = rst!Category Set tv.Nodes.Item(strCatKey).Parent = tv.Nodes.Item(strBelongsTo) End If rst.MoveNext Loop rst.Close ' Populate ListView Control with Product details ' of the first Category Item LoadListView firstCatID End Sub Private Sub LoadListView(ByVal CatID) Dim strProduct As String Dim strPKey As String Dim intcount As Integer Dim tmpLItem As MSComctlLib.ListItem Dim db As DAO.Database Dim rst As DAO.Recordset Dim strSQL As String ' Initialize ListView Control While lvList.ListItems.Count > 0 lvList.ListItems.Remove (1) Wend strSQL = "SELECT lvProducts.* FROM lvProducts " strSQL = strSQL & "WHERE (lvProducts.ParentID = " & CatID & ") " strSQL = strSQL & "ORDER BY lvProducts.[Product Name];" 'Open filtered Products List for selected category Set db = CurrentDb Set rst = db.OpenRecordset(strSQL, dbOpenSnapshot) Do While Not rst.BOF And Not rst.EOF intcount = intcount + 1 strProduct = rst![Product Name] strPKey = Prfx & CStr(rst!PID) 'List Item Add() Syntax: 'lvList.ListItems.Add Index,Key,Text,Icon,SmallIcon Set tmpLItem = lvList.ListItems.Add(, strPKey, strProduct, , 3) 'first column lvList.ForeColor = vbBlue 'List second column sub-item Syntax: 'tmpLItem.ListSubItems.Add Column - Index, Key, Text, ReportIcon, ToolTipText tmpLItem.ListSubItems.Add 1, strPKey & CStr(intcount), Nz(rst![Quantity Per Unit], ""), 6 'List third column sub-item tmpLItem.ListSubItems.Add 2, strPKey & CStr(intcount + 1), Format(rst![list Price], "0.00"), 6, "In Local Currency." rst.MoveNext Loop Set db = Nothing Set rst = Nothing If intcount > 0 Then lvList.ListItems(1).Selected = True End Sub Private Sub TreeView0_NodeClick(ByVal Node As Object) Dim Cat_ID As String Cat_ID = Node.Tag LoadListView Cat_ID End Sub Private Sub TreeView0_OLEStartDrag(Data As Object, AllowedEffects As Long) Set tv.SelectedItem = Nothing End Sub Private Sub TreeView0_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) On Error GoTo TreeView0_OLEDragOver_Err Dim nodSelected As MSComctlLib.Node Dim nodOver As MSComctlLib.Node If tv.SelectedItem Is Nothing Then 'Select a node if one is not selected Set nodSelected = tv.HitTest(X, Y) If Not nodSelected Is Nothing Then nodSelected.Selected = True End If Else If tv.HitTest(X, Y) Is Nothing Then 'do nothing Else 'Highlight the node the mouse is over Set nodOver = tv.HitTest(X, Y) Set tv.DropHighlight = nodOver End If End If TreeView0_OLEDragOver_Exit: Exit Sub TreeView0_OLEDragOver_Err: MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragOver()" Resume TreeView0_OLEDragOver_Exit End Sub Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) Dim tv_nodSource As Node Dim tv_nodTarget As Node Dim strtv_ParentKey As String Dim strtv_TargetKey As String Dim strListItemKey As String Dim strSQL As String Dim vCatID As Long Dim lngPID As Long On Error GoTo TreeView0_OLEDragDrop_Err 'Get the source/destination Nodes Set tv_nodSource = tv.SelectedItem Set tv_nodTarget = tv.HitTest(X, Y) If Not tv_nodTarget Is Nothing Then strtv_ParentKey = tv_nodSource.Key strtv_TargetKey = tv_nodTarget.Key If strtv_ParentKey = strtv_TargetKey Then Exit Sub 'Extract ListItem Key strListItemKey = lvList.SelectedItem.Key 'extract Category Record CID Value 'and ListItem Product ID Key vCatID = Val(Mid(tv_nodTarget.Key, 2)) lngPID = Val(Mid(strListItemKey, 2)) 'UPDATE lvProducts Table strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _ " WHERE PID = " & lngPID CurrentDb.Execute strSQL, dbFailOnError Set tv.DropHighlight = Nothing tv_nodSource.Selected = True 'Rebuild ListView Nodes TreeView0_NodeClick tv_nodSource Else ' Invalid Target location MsgBox "The destination is invalid!", vbInformation End If TreeView0_OLEDragDrop_Exit: Exit Sub TreeView0_OLEDragDrop_Err: MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()" Resume TreeView0_OLEDragDrop_Exit End Sub Private Sub TreeView0_OLECompleteDrag(Effect As Long) Set tv.DropHighlight = Nothing End Sub Private Sub cmdClose_Click() DoCmd.Close End Sub
Los familiares segmentos de código VBA.
En el Form_Load() Procedimiento de evento, inicializamos los controles TreeVew, ListView, ImageList. Crea los Encabezados de columna del control ListView, antes de completar los elementos de la lista en el control Listview. Al final de esta rutina, llamamos a la subrutina LoadTreeView().
El LoadTreeView() subrutina rellena los nodos de categoría de los productos en el control TreeView, con los registros de lvCategory Mesa. La carga de nodos en el control TreeView es un proceso de dos pasos. ¿Por qué es así, en lugar de hacerlo de una vez? Este aspecto se ha explicado en detalle en una página anterior, el enlace 7 en la lista de enlaces que figuran arriba si desea revisarla. Repetirlos todos aquí puede no ser apropiado.
Al final de la subrutina anterior, LoadListView() se ha llamado a la subrutina con el valor CID del primer registro de categoría 1 como parámetro.
Los registros de productos con el valor del campo ParentID 1 han sido filtrados y listados en ListView Control. Este procedimiento fue explicado en detalle en la publicación de la semana pasada, el artículo 8, entre la Lista de Enlaces dada arriba.
Las subrutinas de acción de arrastrar y soltar.
Las siguientes subrutinas asociadas con la acción de arrastrar y soltar se ejecutarán automáticamente en el orden en que se presentan a continuación:
- Vista de árbol0_OLEStartDrag()
- TreeView0_OLEDragOver()
- Vista de árbol0_OLEDragDrop()
- TreeView0_OLECompleteDrag()
La primera y la última Subrutina inicializan los Nodos involucrados y restablecen su estado al final respectivamente.
La segunda, la subrutina OLEDragOver(), funciona como el procedimiento de evento MouseMove y rastrea el movimiento del mouse durante la operación de arrastrar y soltar. Resalta el NodeText cuando el mouse está sobre un Nodo y rastrea su trayectoria hasta que se suelta el botón izquierdo del mouse.
El código del procedimiento TreeView0_OLEDragDrop() solo se muestra a continuación.
Private Sub TreeView0_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) Dim tv_nodSource As Node Dim tv_nodTarget As Node Dim strtv_ParentKey As String Dim strtv_TargetKey As String Dim strListItemKey As String Dim strSQL As String Dim vCatID As Long Dim lngPID As Long On Error GoTo TreeView0_OLEDragDrop_Err 'Get the source/destination Nodes Set tv_nodSource = tv.SelectedItem Set tv_nodTarget = tv.HitTest(X, Y) If Not tv_nodTarget Is Nothing Then strtv_ParentKey = tv_nodSource.Key strtv_TargetKey = tv_nodTarget.Key If strtv_ParentKey = strtv_TargetKey Then Exit Sub 'Extract ListItem Key strListItemKey = lvList.SelectedItem.Key 'extract Category Record CID Value 'and ListItem Product ID Key vCatID = Val(Mid(tv_nodTarget.Key, 2)) lngPID = Val(Mid(strListItemKey, 2)) 'UPDATE lvProducts Table strSQL = "UPDATE lvProducts SET ParentID = " & vCatID & _ " WHERE PID = " & lngPID CurrentDb.Execute strSQL, dbFailOnError Set tv.DropHighlight = Nothing tv_nodSource.Selected = True 'Rebuild ListView Nodes TreeView0_NodeClick tv_nodSource Else ' Invalid Target location MsgBox "The destination is invalid!", vbInformation End If TreeView0_OLEDragDrop_Exit: Exit Sub TreeView0_OLEDragDrop_Err: MsgBox Err & " : " & Err.Description, vbInformation, "TreeView0_OLEDragDrop()" Resume TreeView0_OLEDragDrop_Exit End Sub
La acción de arrastrar y soltar paso a paso.
El procedimiento TreeView0_OLEDragDrop() se ejecuta inmediatamente después de soltar el botón izquierdo del mouse para completar la acción de soltar. Al comienzo del código, las referencias activas y del Nodo TreeView de destino se han guardado en tv_nodSource y tv_nodTarget Objeto Variables respectivamente.
A continuación, realizamos una verificación, si ListItem se ha colocado en un nodo TreeView válido o no. Si se coloca en el mismo nodo de categoría de origen o en un área vacía en el control TreeView, estos movimientos no son válidos. Si se ha soltado en un área vacía del control TreeView, entonces tv_nodTarget La variable de objeto contendrá el valor Nada. En ese caso, muestra un mensaje y sale del programa.
A continuación, los valores clave del nodo de origen y de destino de TreeView se guardan en dos variables de cadena. Si ambas claves son iguales, ListItem se arrastra y suelta en su propio nodo principal (nodo de categoría) en el control TreeView. La ejecución del programa se cancela para continuar.
Si ambas claves son diferentes, entonces es hora de actualizar el cambio en el ParentID del registro de producto. campo, con el CID del registro de categoría objetivo Codifique y actualice los elementos de ListView.
El valor clave del ListItem seleccionado (PID valor de campo) se ha guardado en strListItemKey Variable de cadena.
El CID real del registro de categoría el valor del campo se ha extraído del nodo de destino, eliminando el valor del carácter del prefijo X y guardándolo en la variable vCatID . Este es el valor que actualizaremos en el campo ParentID del registro del producto para colocar el ListItem en la nueva categoría.
Del mismo modo, el valor de PID clave del producto del elemento de lista seleccionado se extrae y se guarda en la variable lngPID . Esto se ha utilizado como criterio para filtrar y seleccionar ese registro de Producto en particular para actualizar el campo ParentID con vCatID .
Una ACTUALIZACIÓN Se ha creado Query SQL para filtrar el registro, usando el lngPID Código como criterio, para filtrar el registro del producto y para actualizar el vCatID Valor en la P arentID campo.
Ejecutar método de Currentdb ha sido llamado con el SQL y actualiza el cambio.
El punto culminante del nodo se ha restablecido al nodo de origen.
A continuación, se ha llamado a la subrutina TreeView0_NodeClick() con tv_nodSource como parámetro para reflejar el cambio en ListView Control.
El Cerrar Hacer clic en el botón cerrará el formulario.
Descargar base de datos de demostración.
Puede descargar la base de datos de demostración, realizar pruebas y estudiar el código VBA.
LES DESEO UN MUY FELIZ AÑO NUEVO.
GESTIÓN DE EVENTOS DE MS-ACCESS
- Con eventos MS-Access Class Module
- Con eventos y definición de sus propios eventos
- Pestaña de cuadro de texto de lista combinada de eventos
- Acceso a arreglos de control de formularios y eventos
- Arrays de control de formulario de acceso y Event-2
- Arrays de control de formulario de acceso y Event-3
- Con eventos en el módulo de clase para subformulario
- Con eventos en Módulo de Clase y Datos
- Sumidero de eventos de informes de acceso y sin eventos
- Sin eventos y Ocultación de línea de informe
- Con eventos y resaltado de línea de informe
- Con cuadro de texto de eventos y botón de comando
- Botón de comando del cuadro de texto Withevents
- Con eventos y todos los tipos de control de formulario