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