Introdução.
Continuação do Tutorial-01 de controle ActiveX ListView da semana passada.
Nesta sessão do Tutorial, aprenderemos como pesquisar e encontrar os valores de linha e coluna específicos e exibi-los em um controle de rótulo no formulário. Isso é muito útil quando temos um grande volume de dados no controle ListView. Também aprenderemos o uso de algumas configurações de propriedade ListView.
Em primeiro lugar, veremos como é fácil reorganizar as colunas, como fazemos com o Access Datasheet View da maneira que queremos que sejam no ListView Control. Adicionamos alguns TextBoxes, ComboBox, Command Buttons e Label para facilitar a seleção dos parâmetros de pesquisa e a exibição dos resultados da pesquisa.
Fiz algumas alterações nos dados de demonstração da semana passada. Os valores da primeira coluna que tirei da tabela de funcionários do banco de dados de exemplo Northwind.accdb. Criou uma Query para unir os valores LastName e FirstName com o nome do campo Student e EmployeeID usados como Chave (X01, X02...).
Antes de ir para as operações de pesquisa, vamos verificar como reorganizar as colunas pelo método de arrastar e soltar.
Observação: Se você não passou pela Página Tutorial anterior e gostaria de continuar com esta sessão, então vá para a Página Tutorial-01 de Controle ListView e baixe o banco de dados de demonstração na parte inferior dessa Página.
Descompacte o arquivo e abra o banco de dados. O formulário de demonstração estará na visualização normal.
-
Abra seu Banco de Dados, com o Demo Form da última sessão, ou o Form que você criou, abra-o em Normal View.
Agora, tentaremos arrastar e mover uma coluna do meio da lista (digamos, a coluna Peso) e soltá-la na Idade coluna e veja o que acontece. O que se espera que aconteça é que a coluna Idade se desloque para a direita e insira a coluna de entrada em seu lugar.
-
Mova o ponteiro do mouse no cabeçalho da coluna com o nome Peso, clique e segure o botão esquerdo do mouse. Quando você pressiona o botão esquerdo do mouse, o cabeçalho da coluna se move ligeiramente para baixo.
-
Agora, tente arrastar a coluna para a esquerda e soltá-la na coluna Idade .
Nada acontecerá, pois não habilitamos esse recurso na Folha de Propriedades e essa é a única configuração, precisamos alterar para que esse recurso funcione.
-
Altere o formulário no modo de design.
-
Clique com o botão direito do mouse no controle ListView e destaque a opção ListViewCtrl Object e selecione Propriedades.
-
Existe uma opção 'AllowColumnReorder ' do lado direito. Coloque uma marca de seleção para selecioná-lo e clique em Aplicar botão seguido pelo OK botão para fechar a Visualização de Propriedades.
-
Agora, tente repetir os passos 2 e 3 acima e veja o que acontece.
Essa é a única configuração necessária para habilitar esse recurso no controle ListView. Talvez você esteja pensando, que tal reorganizar as linhas?.
Essa função precisa programar alguns Event Procedures como fizemos anteriormente em TreeView Control Drag-Drop Events. Essa parte faremos depois de algum tempo.
-
Você pode experimentar qualquer coluna para mover para onde quiser, incluindo a primeira coluna também.
Observação: Antes de descartar a coluna de origem, verifique se a coluna de destino está coberta pelo quadro da coluna de entrada antes de tentar descartar. Caso contrário, a coluna de entrada pode mudar para a próxima posição da coluna no lado direito.
A seguir, aprenderemos a encontrar algumas informações do ListView rapidamente, assumindo que temos um grande volume de dados nele.
Adicionamos uma sub-rotina ao módulo Tutorial-01 para carregar os nomes do cabeçalho da coluna em uma caixa de combinação no formulário com a cor de fundo vermelha. O nome da coluna será usado para encontrar o valor da coluna (idade, altura, peso ou classe) de um aluno.
Novo código VBA adicionado ao módulo Form Class.
O novo procedimento VBA a seguir foi adicionado ao módulo de classe do Tutorial Form da semana passada:
O txtColCombo cria a lista de rótulos de cabeçalho de coluna (nomes de campo) no ComboBox. Um desses detalhes da idade, altura, peso, do aluno ou Classe pode ser encontrado junto com o nome do aluno como parte da operação de busca e localização.
Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub
A caixa de combinação não será carregada com um valor padrão do nome do cabeçalho da coluna. Se selecionado, o valor da coluna do Aluno é exibido no Rótulo Grande abaixo do Nome do Aluno. Se for deixado em branco, a operação de pesquisa encontrará apenas o nome do aluno.
O método de operação de pesquisa é muito flexível e rápido. Temos dois métodos para encontrar um registro.
Encontre o registro fornecendo o texto de pesquisa. O texto de pesquisa pode ser de qualquer uma das colunas, seja o texto completo ou parcial de alguns caracteres à esquerda. Como temos duas categorias de membros de objeto em uma linha no controle ListView:ListItem - a primeira coluna e outras colunas são ListSubItems. A operação de pesquisa de texto nesses objetos é realizada separadamente.
Um grupo de opções com dois CheckBoxes é fornecido ao lado do TextBox de entrada de texto de pesquisa no formulário para selecionar as opções de pesquisa e localização. A primeira opção é selecionada por padrão e a pesquisa é realizada na primeira Coluna (ListItem ) para procurar o texto fornecido.
Selecione a segunda opção para pesquisar o texto no ListSubItem colunas.
Observação: Reorganizar as colunas não alterará os objetos, mas apenas sua posição de exibição. Arrastar um ListSubItem coluna e trazê-la para a primeira coluna não mudará em um ListItem objeto.
Se você deseja recuperar um valor desconhecido de uma coluna específica, selecione um nome de coluna do ComboBox fornecido abaixo do primeiro TextBox no formulário para o texto de pesquisa. Por exemplo, você não sabe a medida da Altura de um aluno e gostaria de descobrir, selecione o nome da coluna Altura da ComboBox.
Depois de definir o(s) valor(es) acima, clique no botão Localizar item Botão de comando para ir para a operação de pesquisa. Se a pesquisa for bem-sucedida, o resultado será exibido no grande controle Label abaixo do botão de comando.
O clique do botão de comando [Localizar item].
Chama o SearchAndFind() Procedimento.
Private Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lvwList.ListItems.Item(j).Selected = True lblMsg.caption = msgText End If End Sub
No início do programa, tanto o Nome do Aluno e Nome da coluna ( 0opcional), são copiados dos TextBoxes para as Variáveis strFind e strColName respectivamente após as verificações de validação.
Observação: A propriedade Not-in-List da caixa de combinação do nome da coluna está definida como Sim. Você pode selecionar um valor válido na lista ou digitá-lo ou deixar a caixa de combinação em branco. Se você digitar um valor diferente que não esteja na lista, ele não será aceito.
Com base na opção de pesquisa selecionada (1 - ListItem ou 2 - ListSubItem) o método de varredura é direcionado para o(s) Objeto(s) especificado(s).
Usando qualquer um desses métodos de pesquisa, você encontrará o ListItem Object ou linha que contém o texto de pesquisa. O valor do índice do ListItem é salvo na variável J para uso posterior no programa.
Observação: O sistema cria os números automáticos de índice automaticamente no momento em que os itens de controle do ListView são preenchidos.
O ListItem.Text valor é recuperado. Essas informações são unidas ao primeiro ColumnHeader. Text (como Student:Robert King) e adicionado à string Msgtext para exibir no controle Label no Form.
Se o nome do cabeçalho da coluna estiver selecionado no ComboBox, então o GetColVal() A função é chamada com o objeto ListItem e o valor Column Header Text como parâmetros. Esta opção é boa para recuperar informações desconhecidas sobre um Aluno, como a Altura do Aluno, do registro.
O código VBA da função GetColVal().
Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function
A função acima pede dois parâmetros. O primeiro parâmetro é o ListItem, onde se encontra o nome do Aluno. O segundo parâmetro é o Nome da Coluna. A Idade, Altura, Peso, Classe do aluno selecionado os valores são armazenados em ListItem.ListSubItems Objetos. A função examina o lvwList.ColumnHeader valores para localizar o nome da coluna correspondente, quando encontrado que o número de índice da coluna é usado para recuperar o valor da coluna do objeto ListSubItems e retorna o valor para o programa de chamada.
O procedimento de evento de clique do botão de comando [Localizar por chave].
Adicionamos outro método para encontrar o nome do aluno usando o valor-chave exclusivo de ListItem se usado ao criar a ListItem List. Mesmo que seja opcional, é melhor adicionar um valor de string de chave exclusivo (deve começar com um caractere alfabético) em vez de ignorá-lo.
Por exemplo, se tivermos que encontrar as informações de alguém pelo seu número de identificação, como número do CPF, número da carteira de identidade, número do passaporte ou número da carteira de motorista e assim por diante, uma dessas informações pode ser usada como o valor da chave para o ListItem. Encontrar um registro com esse valor exclusivo é muito fácil e rápido, em vez do método de pesquisa por texto acima.
O procedimento de evento cmdKey_Click().
Calls FindByKey() Subroutine.
Private Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") If len(lvKeyVal) > 0 then On Error Resume Next Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!",vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Como você pode ver na sub-rotina acima, podemos encontrar diretamente o ListItem onde está o nome do aluno, com o uso do valor-chave, com uma única instrução:Set lvItem =lvwList.ListItems.Item(xKeyVal).
A próxima linha lê o texto ListItem (ou nome do aluno) na variável txt . As próximas duas linhas criam o texto da mensagem com o Nome do Aluno na variável de string msgText.
O próximo Se . . .Então verifica se um valor de nome de coluna é inserido no controle de caixa de combinação. Se for encontrado, então chama o método GetColVal() Função com os parâmetros necessários para encontrar o valor da coluna e recuperá-lo em varColVal Variável e retorna ao programa de chamada. O nome da coluna e seu valor recuperado são adicionados à variável de string msgText para exibir no controle Label no formulário.
A próxima declaração destaca o registro Fila do Aluno como uma indicação visual de que o item pesquisado foi encontrado na fileira. O valor msgText é exibido na propriedade de legenda do rótulo no formulário.
O código VBA completo no módulo de formulário.
Option Compare Database Option Explicit Dim lvwList As MSComctlLib.ListView 'ListView Control Dim lvwItem As MSComctlLib.ListItem ' Dim ObjImgList As MSComctlLib.ImageList Const prfx As String = "K" Private Sub Form_Load() Call LoadListView Call txtColCombo End Sub Private Function LoadListView() 'Populate the ListView control with Student Details Dim db As DAO.Database Dim rst As DAO.Recordset Dim intCounter As Integer Dim strKey As String 'Assign ListView Control on Form to lvwList Object Set lvwList = Me.ListView1.Object With lvwList .AllowColumnReorder = True .Enabled = True .Font = "Verdana" .Font.Bold = True .Font.Size = 9 .ForeColor = vbBlack .BackColor = vbWhite End With 'Create Column Headers for ListView With lvwList .ColumnHeaders.Clear 'initialize header area 'Syntax: .ColumnHeaders.Add Index, Key, Text, Width, Alignment, Icon .ColumnHeaders.Add , , "Student", 2500 .ColumnHeaders.Add , , "Age", 1200 .ColumnHeaders.Add , , "Height", 1200 .ColumnHeaders.Add , , "weight", 1200 .ColumnHeaders.Add , , "Class", 1200 End With 'Initialize ListView Control While lvwList.ListItems.Count > 0 lvwList.ListItems.Remove (1) Wend 'Student Names and Ids are taken from Employees Table 'through the StudentQ Query. Set db = CurrentDb Set rst = db.OpenRecordset("StudentQ", dbOpenDynaset) With lvwList Do While Not rst.EOF And Not rst.BOF intCounter = rst![EmployeeID] strKey = "X" & Format(intCounter, "00") 'Key Value sample: X01 'Syntax: .ListItems.Add(Index, Key, Text, Icon, SmallIcon) Set lvwItem = .ListItems.Add(, strKey, rst![Student]) With lvwItem 'Syntax: .Add Index,Key,Text,Report Icon,TooltipText .ListSubItems.Add , strKey & CStr(intCounter), CStr(5 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 1), CStr(135 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 2), CStr(40 + intCounter) .ListSubItems.Add , strKey & CStr(intCounter + 3), ("Class:" & Format(intCounter, "00")) End With rst.MoveNext Loop rst.Close Set rst = Nothing Set db = Nothing Set lvwItem = Nothing End With lvwList.Refresh End Function Private Sub cmdClose_Click() DoCmd.Close acForm, Me.Name End Sub Private Sub cmdFind_Click() Call SearchAndFind End Sub Private Sub cmdKey_Click() Call FindByKey End Sub Private Function GetColVal(lvwItem As MSComctlLib.ListItem, ByVal colName As String) As String Dim i As Integer Dim strVal As String 'first column is student name 'check for column value from 2nd column onwards For i = 2 To lvwList.ColumnHeaders.Count If lvwList.ColumnHeaders(i).Text = colName Then 'if col name matches strVal = lvwItem.ListSubItems.Item(i - 1).Text 'get column value Exit For 'No further scanning required End If Next GetColVal = strVal 'return the retrieved the value End Function Private Sub txtColCombo() 'Column Header List Combo Dim lvwColHead As MSComctlLib.ColumnHeader Dim cboName As ComboBox Set cboName = Me.txtCol cboName.RowSourceType = "Value List" For Each lvwColHead In lvwList.ColumnHeaders If lvwColHead.Index = 1 Then 'Nothing Else cboName.AddItem lvwColHead.Text End If Next 'cboName.DefaultValue = "=txtCol.Column(0, 0)" Set lvwColHead = Nothing Set cboName = Nothing End Sub Public Sub SearchAndFind() 'Find by Student Name Dim lstItem As MSComctlLib.ListItem Dim strFind As String Dim strColName As String Dim strColVal As String Dim j As Integer Dim intOpt As Integer Dim msgText As String Me.Refresh intOpt = Me.Opts strFind = Nz(Me![txtFind], "") strColName = Nz(Me![txtCol], "") Select Case intOpt Case 1 Set lstItem = lvwList.FindItem(strFind, , , lvwPartial) If Not lstItem Is Nothing Then j = lstItem.Index 'format the display text msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & " : " & lstItem.Text & vbCr & vbCrLf Else MsgBox "Text '" & strFind & "' Not Found in the List!", vbOKOnly + vbCritical, "cmdFind_Click()" Exit Sub End If Case 2 Set lstItem = lvwList.FindItem(strFind, lvwSubItem, , lvwPartial) If Not lstItem Is Nothing Then 'format the display text j = lstItem.Index msgText = lvwList.ColumnHeaders.Item(1).Text msgText = msgText & ": " & lstItem.Text & vbCr & vbCrLf Else MsgBox strFind & " Not Found!", vbOK + vbCritical, "cmdFind_Click()" Exit Sub End If End Select If Len(strColName) = 0 Then 'If column name is not selected GoTo nextStep Else 'Get the column value strColVal = GetColVal(lstItem, strColName) msgText = msgText & String(8 - (Len(strColName)), " ") & _ strColName & ": " & Nz(strColVal, "") End If nextStep: If Len(msgText) > 0 Then 'assign to form label lblMsg.caption = msgText lvwList.ListItems.Item(j).Selected = True End If End Sub Public Sub FindByKey() Dim colHeader As MSComctlLib.ColumnHeader Dim lvItem As MSComctlLib.ListItem Dim lvKeyVal As String Dim lvColName As String Dim txt As String Dim msgText As String Dim varcolVal As Variant lvKeyVal = UCase(Nz(Me!txtKey, "")) lvColName = Nz(Me!txtCol, "") On Error Resume Next If Len(lvKeyVal) > 0 Then Set lvItem = lvwList.ListItems.Item(lvKeyVal) 'get the item by Key If Err > 0 Then Err.Clear MsgBox "Key Value: '" & lvKeyVal & "' Not Found!", vbOKOnly + vbCritical, "cmdKey_Click()" On Error GoTo 0 Exit Sub End If Else MsgBox "Please Provide a Valid Key-Value!", vbOKOnly + vbCritical, "cmdKey_Click()" Exit Sub End If txt = lvItem.Text 'get the student name 'format message text msgText = lvwList.ColumnHeaders.Item(1).Text & " : " msgText = msgText & txt & vbCr & vbCrLf If Len(lvColName) > 0 Then 'if column name is given varcolVal = GetColVal(lvItem, lvColName) 'get column val of student msgText = msgText & String(8 - Len(lvColName), " ") & lvColName & ": " & varcolVal ' add it to display End If lvItem.Selected = True 'highlight the item on form Me.lblMsg.caption = msgText 'assign details to form Label End Sub
Baixe o banco de dados de demonstração no seguinte link:
- Tutorial de controle do Microsoft TreeView
- Criando menu de acesso com controle TreeView
- Atribuindo imagens a nós TreeView
- Atribuindo imagens aos nós TreeView-2
- Marca de seleção de controle TreeView Adicionar exclusão
- Acesso suspenso do TreeView ImageCombo
- Reorganizar nós TreeView por arrastar e soltar
- Controle de ListView com MS-Access TreeView
- Eventos de arrastar e soltar do controle ListView
- Controle TreeView com subformulários