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