Introdução.
Estamos familiarizados com as operações de arrastar e soltar no controle TreeView, no Ms-Access que reorganiza Nodes. Todos os registros de base para os nós de controle Treeview vêm de uma única tabela de acesso. Sempre atualizamos o ParentID do nó de origem valor do campo, com o Valor ID do Nó de Destino no mesmo registro da Tabela, para fazer a mudança de posição no Controle TreeView. Os registros não são movidos fisicamente para nenhum lugar.
Aqui, com a adição de ListView Control junto com TreeView Control, planejamos trabalhar com duas tabelas de acesso diferentes.
- lvCategory – Código e descrição da categoria.
- lvProducts – Produtos Categorywise.
Assim fica mais fácil entender a relação entre as duas Tabelas. Quais alterações temos que fazer e onde, quando um item de produto (item ListView) se move de uma categoria para outra no controle TreeView.
A lvCategory A tabela de acesso tem 20 registros para os nós TreeView e os lvProducts A tabela tem 45 para o controle ListView. Um ou mais registros na tabela Produtos estão diretamente relacionados a uma categoria de produto na Tabela Categoria. A relação entre eles foi atualizada com o valor do campo ID da categoria (CID) no ParentID da Tabela de produtos campo para que a mudança de categoria do produto reflita imediatamente no controle ListView.
A tabela de dados de demonstração foi retirada do banco de dados de exemplo do Microsoft Access Northwind.accdb e dividida em duas partes.
Com base no valor do campo ParentID, dos registros lvProduct, podemos filtrar e listar todos os itens de produtos relacionados no controle ListView, quando um nó de categoria é selecionado no controle TreeView.
Tópicos que cobrimos até agora.
A seguir estão os principais tópicos no TreeView , Lista de imagens , ImageCombo, e ListView Controles, que cobrimos até agora no MS-Access:
- Tutorial de controle do Microsoft TreeView
- Criando menu de acesso com controle TreeView
- Atribuindo imagens ao controle TreeView
- Atribuindo imagens ao TreeView Control-2
- Marque de seleção de controle do TreeView Adicionar nós de exclusão
- Menu de acesso suspenso do TreeView ImageCombo
- Reorganize os nós do TreeView arrastando e soltando
- Controle de ListView com MS-Access TreeView
A tarefa de arrastar e soltar ListView.
No que diz respeito à operação de arrastar e soltar do ListView, é um exercício simples comparando o mesmo método dentro do controle TreeView sozinho. Como a ação Arrastar Soltar envolve os controles TreeView e ListView, usamos o mesmo procedimento de evento TreeView0_OLEDragDrop() com algum código VBA simples.
Os itens de produto listados no controle ListView pertencem ao item de categoria atual selecionado no controle TreeView.
O usuário seleciona um determinado item de produto do controle ListView, se ele acha que pertence a um item de categoria diferente, então arraste e solte no item de categoria de destino no TreeViewCcontrol.
O Item do Produto ListView movido será adicionado à lista de itens que pertencem à Categoria alterada. O valor do campo ParentID do registro do produto é atualizado com o ID do registro de categoria de destino (valor CID).
É apenas uma ação unidirecional, sempre mova o item ListView de uma categoria e solte-o em um nó de categoria diferente no controle TreeView.
O formulário de acesso de demonstração de arrastar e soltar ListView frmListViewDrag' A imagem da tela de execução de teste é fornecida abaixo:
Na imagem acima, as Bebidas A categoria no TreeView foi selecionada. Os produtos pertencentes à categoria Bebidas foram listados no Controle ListView.
A visualização de design do formulário acima:
A lista de nomes de controle no formulário é a seguinte:
- Controle TreeView:TreeView0
- Controle ListView:ListView0
- Controle ImageList:ImageList3
- Botão de comando:cmdFechar
O código VBA no frmListViewDrag Módulo de classe do :
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
Os segmentos de código VBA familiares.
No Form_Load() Event Procedure, inicializamos os controles TreeVew, ListView, ImageList. Ele cria os ColumnHeadings do controle ListView, antes de preencher itens de lista no controle Listview. Ao final desta rotina, chamamos a sub-rotina LoadTreeView().
O LoadTreeView() sub-rotina preenche os nós de categoria dos produtos no controle TreeView, com os registros da lvCategory Tabela. O carregamento de nós no controle TreeView é um processo de duas etapas. Por que é assim, em vez de fazê-lo de uma só vez? Este aspecto foi explicado em detalhes em uma página anterior, o 7º link na lista de links acima, se você quiser passar por isso. Repetir todos eles aqui pode não ser apropriado.
No final da sub-rotina acima, o LoadListView() a sub-rotina foi chamada com o valor CID do primeiro registro de categoria 1 como parâmetro.
Os registros do produto com o valor do campo ParentID 1 foram filtrados e listados no controle ListView. Este procedimento foi explicado detalhadamente no post da semana passada, o 8º item, dentre a Lista de Links dada acima.
As sub-rotinas de ação de arrastar e soltar.
As seguintes Sub-rotinas associadas à ação Arrastar e Soltar serão executadas automaticamente na ordem em que são apresentadas abaixo:
- TreeView0_OLEStartDrag()
- TreeView0_OLEDragOver()
- TreeView0_OLEDragDrop()
- TreeView0_OLECompleteDrag()
A primeira e a última Sub-rotinas inicializam os Nodes envolvidos e reiniciam seus status no final, respectivamente.
A segunda, a sub-rotina OLEDragOver() funciona como o MouseMove Event Procedure e acompanha o movimento do mouse durante a operação de arrastar e soltar. Ele destaca o NodeText quando o mouse está sobre um Node e rastreia sua trajetória até que o botão esquerdo do mouse seja liberado.
O código do procedimento TreeView0_OLEDragDrop() sozinho está listado abaixo.
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
A ação de arrastar e soltar passo a passo.
O procedimento TreeView0_OLEDragDrop() é executado imediatamente após o botão esquerdo do mouse ser liberado para concluir a ação de soltar. No início do código, as referências do nó TreeView ativo e de destino foram salvas em tv_nodSource e tv_nodTarget Variáveis de objeto respectivamente.
Em seguida, realizamos uma verificação, se o ListItem foi descartado em um nó TreeView válido ou não. Se ele for solto no mesmo nó de categoria de origem ou em uma área vazia no controle TreeView, esses movimentos não serão válidos. Se ele foi solto em uma área vazia do TreeView Control, o tv_nodTarget variável de objeto conterá o valor Nada. Nesse caso, exibe uma mensagem e sai do Programa.
Em seguida, os valores-chave do nó de origem e de destino TreeView estão sendo salvos em duas variáveis de string. Se ambas as chaves forem iguais, então o ListItem arrastou e soltou em seu próprio nó pai (nó de categoria) no controle TreeView. A execução do programa é abortada de prosseguir.
Se ambas as chaves forem diferentes, é hora de atualizar a alteração no ParentID do registro do produto campo, com o CID do registro de categoria de destino Code e atualize os itens ListView.
O valor da chave do ListItem selecionado (PID valor do campo) foi salvo no strListItemKey Variável de string.
O CID real do registro da categoria o valor do campo foi extraído do nó de destino, removendo o valor do caractere de prefixo X e salvo na variável vCatID . Este é o Valor que iremos atualizar no campo ParentID do Product Record, para colocar o ListItem na nova Category.
Da mesma forma, o valor PID da chave do produto do item de lista selecionado é extraído e salvo na variável lngPID . Isso foi usado como critério para filtrar e selecionar esse registro de produto específico para atualizar o campo ParentID com vCatID .
Uma ATUALIZAÇÃO A consulta SQL foi criada para filtrar o registro, usando o lngPID Codifique como critérios para filtrar o registro do produto e atualizar o vCatID Valor no P arentID campo.
O Executar método do Currentdb foi chamado com o SQL e atualiza a alteração.
O Destaque do Nó foi redefinido para o Nó de Origem.
Em seguida, a sub-rotina TreeView0_NodeClick() foi chamada com o tv_nodSource como um parâmetro para refletir a alteração no controle ListView.
O Fechar Clique no botão fechará o formulário.
Baixe o banco de dados de demonstração.
Você pode baixar o banco de dados Demo, fazer testes e estudar o código VBA.
DESEJAMOS UM FELIZ ANO NOVO.
TRATAMENTO DE EVENTOS MS-ACCESS
- Módulo de classe do MS-Access Withevents
- Com eventos e definindo seus próprios eventos
- Guia da caixa de texto da lista de combinação Withevents
- Matrizes e eventos de controle de formulário de acesso
- Matrizes de controle de formulário de acesso e evento-2
- Matrizes de controle de formulário de acesso e evento-3
- Módulo Withevents in Class para subformulário
- Com eventos no módulo de classe e dados
- Withevents e Access Report Event Sink
- Com eventos e ocultação de linha de relatório
- Withevents e destaque de linha de relatório
- Withevents Texbox e botão de comando
- Botão de comando da caixa de texto Withevents
- Com eventos e todos os tipos de controle de formulário