Access
 sql >> Base de Dados >  >> RDS >> Access

Eventos de classificação de arrastar-soltar de controle de ListView

Reorganizando linhas de dados no controle ListView.


No episódio anterior deste Tutorial, aprendemos como reorganizar as Colunas ativando este recurso:AllowColumnReorder opção na folha de propriedades. Mas, a realocação de uma linha é feita arrastando-a e colocando-a em outra linha. Para reorganizar as linhas de controle ListView, a ação ListItem Drag and Drop requer a ativação desse recurso na folha de propriedades. Mas isso por si só não funcionará, precisa de código VBA para reorganizar o item em sua ordem necessária.

Vamos criar um formulário de acesso de exemplo com controles e código VBA em nosso banco de dados para este exercício. A imagem de exemplo do formulário com controles ListBox e ListView é fornecida abaixo.

Criamos uma lista de tabelas e consultas (não consultas de ação) na caixa de listagem. A seleção de um dos itens da lista exibirá os registros instantaneamente no controle ListView, como os vemos na exibição DataSheet.

A Tarefa de Design.


  1. Crie uma nova tabela com um único campo de texto, com o nome do campo DataList .

  2. Salve a Tabela com o nome lvTables (lv significa ListView).

  3. Abra a tabela no modo folha de dados.

  4. Adicione alguns nomes de tabela e selecione nomes de consulta de seu banco de dados na tabela. Eu importei tabelas do banco de dados de exemplo Northwind para minha lista.

    Observação: O Anexo O campo não é válido no controle ListView. Crie consultas de seleção para tabelas com campo de anexo e selecione todos os campos, exceto o campo de anexo.

  5. Crie e abra um novo formulário no modo de design.

  6. Insira um controle ListBox no formulário, exiba a folha de propriedades e altere seu Nome valor da propriedade para List0 .

  7. Alterar seu rótulo filho Legenda valor para Tabelas .

  8. Exiba a folha de propriedades do controle ListBox e defina a Origem da linha valor da propriedade para as lvTables nome.

  9. Verifique se o Tipo de Origem da Linha está definido como Tabela/Consulta e o valor da propriedade Coluna Vinculada é 1. Se for diferente, altere.

  10. Insira um controle ListView da lista de controles ActiveX e altere seu valor de propriedade de nome para ListView1 .

  11. Redimensione ambos os controles conforme mostrado na imagem do formulário de demonstração fornecida acima.

  12. Insira um rótulo acima dos controles e altere seus valores de propriedade de nome e legenda para título. O valor da legenda será alterado do código vba quando uma tabela ou consulta for selecionada no ListBox.

  13. Crie um botão de comando abaixo dos controles e altere o valor da propriedade Name para cmdClose e o valor da propriedade Caption para Fechar .

  14. Clique com o botão direito do mouse no controle ListView, realce o Objeto ListViewCtrl opção e selecione Propriedades .

  15. Altere as configurações de propriedade para corresponder às configurações em Geral Imagem da guia fornecida abaixo.

  16. Imagem da folha de propriedades do controle ListView - a visualização da guia geral é fornecida abaixo:

    Algumas dessas opções já definimos nas sessões anteriores. Aqui precisamos das seguintes opções para nossa ação Arrastar Soltar:

    • OLEDragAutomático - 1

    • OLEDropManual - 1

    • FullRowSelect - Verdadeiro

    • HotTracking - Verdadeiro

Certifique-se de que as configurações acima correspondam à sua folha de propriedades e salve o formulário.

Exiba o módulo VBA do formulário.

O código VBA do módulo de formulário.


Copie e cole o seguinte código VBA no módulo, substituindo as linhas de código existentes, se houver:
Option Compare Database
Option Explicit

Dim lvwList As MSComctlLib.ListView
Dim strTable As String
Dim db As DAO.Database
Dim rst As DAO.Recordset

Private Sub Form_Load()
    Set lvwList = Me.ListView1.Object

End Sub


Private Sub Form_Unload(Cancel As Integer)
On Error GoTo Form_Unload_Err
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim flag As Boolean
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)
flag = False
For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) _
       And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

Form_Unload_Exit:
Exit Sub

Form_Unload_Err:
MsgBox Err & " : " & Err.Description, , "Form_Unload()"
Resume Form_Unload_Exit

End Sub

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control
' sorts the data of that column. On the first Click on the Column
'will sort in Ascending Order, second Click will sort in Descending
With Me.ListView1
    ' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
' Set Sorted to True to sort the list.
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 
    .Sorted = True
End With

End Sub

Private Sub List0_Click()

strTable = List0.Value

Call LoadListView(strTable)

End Sub

Private Sub LoadListView(ByVal s_Datasource As String)
On Error GoTo LoadListView_Err
    Dim j As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim strHeading As String
    
    strHeading = UCase(s_Datasource)
    With Me.Heading
        .caption = strHeading
        .FontName = "Courier New"
        .FontSize = 20
        .FontItalic = True
        .FontBold = True
    End With
    
   'Initialize ListView Control
    lvwList.ColumnHeaders.Clear
    lvwList.ListItems.Clear
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(s_Datasource, dbOpenSnapshot)
       
    'Initialize ListView & Column Headers Property Values
     With lvwList
        .Font.Size = 10
        .Font.Name = "Verdana"
        .Font.Bold = False
        .GridLines = True
    End With
    
    With lvwList
        'Syntax: .ColumnHeaders.Add Index, Key, Text, Width in Pixels, Alignment, Icon
       For j = 0 To rst.Fields.Count - 1
        .ColumnHeaders.Add , , rst.Fields(j).Name, IIf(j = 0, 3000, 1400), 0
       Next
    End With
   Dim I As Long
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
    'Syntax: lvwList.ListItems.Add Index, Key, Text, Icon, SmallIcon
        Set tmpLItem = lvwList.ListItems.Add(, , rst.Fields(0).Value) 'Name column
        
         'Syntax: tmpLItem.ListSubItems.Add Index, Key, Text, ReportIcon, ToolTipText
          With tmpLItem
                For j = 1 To rst.Fields.Count - 1
                    .ListSubItems.Add , , Nz(rst.Fields(j).Value, "")
                Next
          End With
        rst.MoveNext
    Loop
    rst.Close
    
    With lvwList
        If .ListItems.Count > 0 Then
            .ListItems(1).Selected = True
        End If
    End With
  
    Set db = Nothing
    Set rst = Nothing
    
LoadListView_Exit:
Exit Sub

LoadListView_Err:
MsgBox Err & " : " & Err.Description, , "LoadListView()"
Resume LoadListView_Exit
End Sub


Private Sub ListView1_OLEDragOver(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)

End Sub

Private Sub ListView1_OLEDragDrop(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dropped
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being readded to the list
Dim lvwTarget As ListItem
'Subitem reference in dropped item
Dim lvwSub As ListSubItem
'Drop position
Dim intTgtIndex As Integer
Dim j As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

'Ignore overlapping drag or drop Item actions
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

'Save the droped position Index Number
intTgtIndex = lvwDrop.Index
'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'For j = intTgtIndex To ListItems.Count
    
'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

'Destroy all objects
Set lvwTarget = Nothing
Set lvwDrag = Nothing
Set lvwDrop = Nothing
Set lvwList.DropHighlight = Nothing

End Sub

Private Sub cmdClose_Click()
    DoCmd.Close acForm, Me.Name
End Sub


Você está familiarizado com o código VBA acima, exceto as sub-rotinas recém-adicionadas:ListView1_OLEDragOver(), ListView1_OLEDragDrop(), Form_Unload(), e o ListView1_ColumnClik() procedimentos. Os dois primeiros procedimentos nos ajudarão a arrastar um Item (linha) e Soltá-lo sobre outro Item para inseri-lo em um novo local. Os procedimentos Form_Unload() e ListView1_ColumnClick() ordenarão os itens.

As imagens a seguir mostram a ação Arrastar e Soltar em sequências de sua execução

A primeira imagem abaixo mostra a sequência de ação de arrastar e soltar. O ListItem, com EmployeeID 7, é arrastado pelo usuário e cai sobre o ListItem com ID 3.

A segunda imagem mostra a movimentação de ListItem na ordem inversa.

Quando o ponteiro do mouse se move sobre uma linha com o item arrastado, entre as linhas de origem e destino, será realçado um após o outro no caminho para cima.

A ação de arrastar e soltar em imagens.

A linha com Employee ID 7 é descartada no Item com Employee ID 3 acima.

A análise por segmento de código VBA.


Uma seleção de item do ListBox o procedimento de evento List0_Click() é executado e carrega os registros no controle ListView.
Private Sub List0_Click()
Dim strTable As String

strTable = List0.Value

  Call LoadListView(strTable)

End Sub

O nome da Tabela/Consulta selecionada é salvo na strTable variável de seqüência de caracteres. A LoadListView() a sub-rotina é executada com a variável strTable como parâmetro. Passamos por este Código mais de uma vez em sessões anteriores, e você pode visitar essas Páginas usando os Links fornecidos na parte inferior desta página para obter detalhes. Você pode encontrar algumas pequenas alterações que fiz neste Código.

Não usamos o controle ImageList neste episódio o Icon, SmallIcon Valores de parâmetro no método ListItems.Add() e ReportIcon, TooltipText valores de parâmetro no método ListSubItems.Add() também não são usados.

Vejamos o que está acontecendo no ListView1_OLEDragOver() e ListView1_OLEDragDrop() Segmentos de código VBA.

O procedimento ListView1_OLEDragOver().

Private Sub ListView1_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)
End Sub 

Este procedimento é executado automaticamente quando você tenta clicar e segurar em uma linha, começar a arrastar e mover sobre outras linhas no caminho para a linha de destino. A ação de arrastar se move sobre outra linha e será destacada.

O ListView1.HitTest(x, y) A função lê as coordenadas x, y que determinam a posição da linha no controle ListView e realça essa linha. Este processo continua quando você está sobre outras linhas até soltá-lo na linha de destino, liberando o botão do mouse. A ação de soltar aciona o ListView1_OLEDragDrop() procedimento e executa os procedimentos de alteração da linha de origem.

O procedimento ListView1_OLEDragDrop.

Private Sub ListView1_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem 'Drop position index Dim intTgtIndex As Integer Set lvwDrop = lvwList.HitTest(x, y) 'save the source item Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item 'Ignore overlapping drag or drop Item actions If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If 'Save the droped position Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True 'Destroy all objects Set lvwTarget = Nothing Set lvwDrag = Nothing Set lvwDrop = Nothing Set lvwList.DropHighlight = Nothing End Sub

Vamos rever este procedimento parte por parte e entender o que está acontecendo lá. O seguinte segmento de código declara as variáveis ​​de objeto necessárias para lidar com a ação de arrastar e soltar:
'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Reference of the Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem
'Drop position index
Dim intTgtIndex As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

Os três primeiros objetos temporários ListItem são declarados com nomes diferentes.

O lvwDrag O objeto ListItem conterá a cópia da linha que escolhemos para arrastar para um novo local.

O lvwDrop O objeto ListItem salvará a referência da linha na qual soltamos o item da lista arrastado.

Durante a mudança da ação ListItems, excluiremos o item Source de seu local original e o criaremos no local de destino, com o número do índice ListItem de origem. As referências deste novo ListItem são salvas no lvwTarget Variável de objeto ListItem.

O lvwSub Variável declarada como uma variável de objeto de sequenciamento no For . . .Próximo Ciclo. Este loop requer a seqüência através de ListSubItems, (2ª coluna em diante) um por um, a partir do objeto lvwDrag. Embora tenhamos excluído o ListItem original, salvamos uma cópia dele no objeto lvwDrag ListItem.

O número lvwDrop ListItem Index é salvo no intTgtIndex Variável.

O lvwList.HitTest(x, y) A função lê as coordenadas x, y do controle ListView e identifica o ListItem de destino onde soltamos o ListItem de origem e faz uma cópia dele no objeto lvwDrop.

Vamos selecionar um ListItem primeiro antes de arrastá-lo para a nova posição.

O lvwList.SelectedItem A propriedade será definida como True. Com a ajuda deste status de propriedade, fazemos uma cópia do ListItem selecionado no lvwDrag Objeto ListItem. O próximo segmento de código valida os objetos ListItem de origem e destino.

Verificações de validação na ação de arrastar e soltar.

'Ignore overlapping drag or drop Item actions, 
'OR drag and drop happens on the same ListItem.
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing)  Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

O segmento de código acima valida a ação de arrastar e soltar. Se essas ações não iniciarem ou terminarem em um item válido, os objetos lvwDrop ou lvwDrag ou ambos estarão vazios. Ou outro movimento inválido pode acontecer quando o usuário move uma linha para cima ou para baixo, mas pode mudar de ideia e soltá-la de volta na mesma linha. A detecção desses tipos de movimentos errados encerrará o programa.

Se o teste acima for válido, o programa continuará executando o próximo procedimento para reorganizar as linhas.
'Save the dropped position ListItem Index Number
intTgtIndex = lvwDrop.Index

'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

As nove linhas acima de ações de código executável (outras linhas são comentários) são um pouco diretas.



O intTgtIndex =lvwDrop.Index A instrução salva o número do índice do ListItem de destino em intTgtIndex Variável.

Como já salvamos o Source Row listItem no objeto temporário lvwDrag, a próxima etapa é remover o ListItem de origem do controle ListView. O procedimento ListItems.Remove() é chamado, com a instrução lvwList.ListItems.Remove lvwDrag.Index .



Em resumo, a ação Arrastar Soltar é excluir um ListItem de seu local original e criá-lo novamente no local de destino com o número de índice da linha de destino.

A instrução Set lvwTarget =lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) cria o novo ListItem com seu número de índice de localização de destino intTgtIndex e o Text valor de Source ListItem salvo no objeto lvwDrag anteriormente.

Ao criar o ListItem pela primeira vez, usamos apenas esses dois valores, o índice e o Texto valores de parâmetros. Não usamos as outras opções de parâmetro Chave, Ícone, e SmallIcon caso contrário, devemos incluir esses valores de parâmetro também do objeto lvwDrag.

De acordo com nossas imagens de exemplo de arrastar e soltar mostradas acima, movemos o 7º ListItem e o soltamos no 3º ListItem. Depois disso, excluímos o 7º Item (ou ListItem de origem) do controle ListView. Criou um novo ListItem com o número de índice de destino 3.

Agora, existem dois itens com o mesmo número de índice 3, o existente com o número de índice 3 e o novo que criamos com o número de índice 3. Todas as outras informações são retiradas do objeto lvwDrag (ou do 7º ListItem salvo em lvwDrag Objeto anterior).

O sistema incrementa automaticamente o ListItem 3 existente para os próximos números de sequência 3,4,5 . . . a 4,5,6. . . e os move para frente para dar espaço para o item de entrada inserir no meio.

O impacto de excluir uma linha e criá-la em outro lugar.

Suponha que fazemos esse movimento na ordem inversa, como arrastar ListItem número 3 de cima e soltá-lo no item número 7, então o que acontece?

Naturalmente, excluiremos o 3º Item e tentaremos criar um novo item com o número de índice 7 no novo local. Quando o item número 3 for excluído, o item número 4 em diante mudará para cima ou 4,5,6,7,8,9 se tornará 3,4,5,6,7,8 (para fazer todos os itens em sequência) ou quanto mais cedo item com número de índice 7 se tornará 6.

Quando criamos o novo Item com número de índice 7, o 7,8 existente se tornará 8,9 novamente. Quando observamos o movimento das linhas durante a exclusão e o tempo de criação da linha, o primeiro exemplo moverá a linha de destino para baixo para abrir caminho para o item de entrada. No segundo exemplo explicado (mover de 3 para 7) a linha de destino se moverá para cima.

Observação: Assista to valor de ID de funcionários para sua colocação como uma pista para ListItem se deslocando para baixo ou para cima quando reorganizamos ListItem.

Eu mencionei ListItem em todos os lugares em operações de arrastar e soltar. O ListItem refere-se apenas à primeira coluna da linha ListView. Outros valores de coluna são ListSubItems ou os itens filho do ListItem. Isso significa que você poderá arrastar e soltar apenas a primeira coluna. Outras colunas ou ListSubItems serão movidas para ListItem com código VBA.

Isso é verdade se você não ativou a FullRowSelection na folha de propriedades do controle ListView na seção Geral Aba.

Se habilitado, você pode selecionar qualquer coluna, mas o sistema se refere ao índice ListItem para fins de reordenação de linhas. Compare as duas imagens acima com outro conjunto de duas imagens de amostra, a terceira e a quarta imagens do topo desta página.

A ação Arrastar e Soltar não funcionará se os dois valores de propriedade a seguir não estiverem definidos na folha de propriedades do controle ListView em Geral Aba.:


  • ccOLEDragAutomático =1
  • ccOLEDropManual =1



As próximas cinco instruções moverão os ListSubItems, se houver, para o ListItem recém-criado no novo local.

Em seguida, o ListItem recém-criado é realçado.

Em seguida, todos os objetos temporários criados são apagados da memória.

Observação: Outro ponto importante a ser observado aqui é que esse arranjo é temporário e se perde quando você fecha o Form ou carrega outra Tabela/Consulta no Controle ListView.

Se quisermos que o pedido alterado de ListItems permaneça permanente, ou até que o pedido seja alterado na próxima vez, devemos ser capazes de atualizar o número do pedido indexado atual na própria tabela. Adicionamos um novo campo Integer com o ID do nome do campo na Tabela Employees.

A tela de exemplo com os dados dos Empregados reorganizados em ordem alfabética é apresentada abaixo:

Como o campo Employees ID é um campo AutoNumeração e vinculado a outras tabelas relacionadas, adicionamos um novo campo de número com o ID do nome do campo. Este valor de campo é definido inicialmente com os mesmos números de sequência do ID de Empregados manualmente. Este valor de campo será inicialmente nesta ordem. Mas, os dados ListView Rows podem alterar sua ordem quando você reorganiza os dados no controle ListView devido à ação de arrastar e soltar.

Veja os FuncionáriosQ Consulta SQL fornecida abaixo:
SELECT [FirstName] & " " & [LastName] AS EmployeeName, 
Employees.ID, 
Employees.EmployeeID, 
Employees.TitleOfCourtesy, 
Employees.Title, 
Employees.Address, 
Employees.City, 
Employees.Region, 
Employees.PostalCode, 
Employees.Country, 
Employees.HomePhone, 
Employees.Extension, 
Employees.Notes
FROM Employees
ORDER BY Employees.ID;

A consulta acima é usada como fonte de dados para o controle ListView e são classificadas no campo ID. O campo ID é atualizado com a ordem alterada dos números de índice no controle ListView. O processo de atualização é executado a partir do Form_Unload() Procedimento de evento ao fechar o formulário. Esse método garante que, quando você abrir o controle ListView na próxima vez, os dados estarão na ordem que você reordenou da última vez.

O Form_Unload() Código VBA do procedimento de evento.

Private Sub Form_Unload(Cancel As Integer)
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)

For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text 'EmployeeName
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp 'replace ID number
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

End Sub

Verifique o EmployeeName Valor do campo na imagem acima. Estão dispostos em ordem alfabética. O novo valor do campo ID na Tabela Employees será atualizado com a sequência numérica do índice ListView Control ListItem atual.

Se você observar os seguintes pontos, poderá entender facilmente o que fazemos com o código acima:

  1. O Texto do ListItem (primeira coluna) valor do parâmetro é o nome do funcionário e organizado em ordem alfabética.

  2. O ListItems no controle ListView tem números de índice de 1 a 9 na ordem em que é mostrado na tela, ou seja, o número de índice do primeiro item é 1 e o último é 9. Os dados originais no valor do campo Employees Table ID não são nesta ordem.

  3. Pegamos o Texto Valor (Employee Name) do primeiro ListItem e procure o nome na tabela.

  4. Quando o registro é encontrado, o número Index do ListItem atual é atualizado (substituído) no campo ID da tabela.

  5. Esse processo foi repetido para todos os registros restantes da tabela.

Vamos passar pelo código VBA. No início, verificamos se a tabela/consulta de dados de origem foi carregada no controle ListView ou não?

Se a strTabela A variável não é inicializada com o nome da consulta, então o controle ListView está vazio. Se for esse o caso, o usuário abriu o formulário e o fechou sem selecionar o nome da consulta para carregar os dados no controle ListView. O Form_Unload O procedimento de evento é abortado neste ponto e fecha o formulário.

Se o controle ListView tiver dados, a próxima etapa será executada e abrirá a consulta de dados de origem EmployeesQ para atualizar.

A próxima etapa é percorrer cada ListItem e atualizar o número de índice no campo ID do registro Employees.

Primeiro, o número do índice da linha atual é salvo no tmp Variável.

O primeiro nome lvwList.ColumnHeader EmployeeName e o nome do funcionário é retirado do ListItem.Text em uma expressão nos Critérios variável de string, como EmployeeName ="Andrew Fuller".

Os critérios rst.FindFirst O comando pesquisa a tabela de dados de origem para localizar o registro com o nome fornecido. Quando o registro é encontrado, o número do Índice ListItem atual é atualizado no Campo de ID.

Este processo é repetido para todas as linhas do controle ListView e quando finalizado o formulário é fechado.

Na próxima vez que você carregar os registros desta consulta no controle ListView, eles serão exibidos na mesma ordem quando você fechou o formulário da última vez.

Nota:A consulta tornou-se necessária aqui para ordenar os dados no campo ID e exibi-los na ordem alterada no controle ListView.

Todo esse trabalho foi para salvar os dados na última ordem de classificação para que na próxima vez que você abrir o Form os dados no controle ListView estejam nessa ordem.

O Windows Explorer gosta do método de classificação.


No Windows Explorer, você pode classificar a lista exibida em ordem crescente ou decrescente clicando em qualquer título de coluna. O cabeçalho da coluna funcionará como um botão de alternância. Cliques repetidos no cabeçalho da coluna classificarão os dados da coluna em ordem crescente/decrescente pela seguinte ListView1_ColumnClick() Procedimento do evento:
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control is
' sorted by the subitems of that column.

With Me.ListView1
' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 ' Set Sorted to True to sort the list.
     .Sorted = True
End With
End Sub

Observação: A classificação de todos os dados é feita apenas no modo de comparação de texto. Os ListItems e ListSubItems Adicionar() terceiro parâmetro do método, as informações exibidas no controle ListView são Texto tipo. Os valores de data e numéricos são tratados apenas como texto.

O Windows Explorer salva a última ordem classificada de itens na pasta. Quando abrimos essa pasta novamente, a lista será exibida na ordem de classificação anterior.

Com o Form_Unload() Procedimento de Evento este recurso do Windows Explorer torna-se possível na Tabela Funcionários. Ao fechar o Formulário após ordenar em qualquer coluna essa sequência de ordem indexada será salva na Tabela Funcionários no campo ID. A Consulta EmployeesQ sempre ordena os dados no campo ID quando aberto.

O banco de dados Demo está anexado para download. Existem dois formulários de demonstração no banco de dados. O primeiro Form demonstra a abertura de Tabelas e Consultas no Controle ListView para visualizar os dados no Modo Folha de Dados. O segundo formulário usa apenas o EmployeesQ Consulta sozinho para arrastar, soltar, classificar e salvar a última ordem de classificação de dados para uso futuro.


  1. Tutorial de controle ActiveX ListView-01.
  2. Tutorial de controle do ListView-02.
  3. Atribuindo imagens a itens do ListView.
  4. Eventos de classificação por arrastar e soltar do controle ListView
  5. Controle de ListView com MS-Access TreeView
  6. TreeView/ListView controla eventos de arrastar e soltar