Importare dati da una matrice su 2 listbox

Anonimo
2016-06-21T09:57:27+00:00

Buongiorno a tutti,

avrei bisogno di un aiuto nel creare una routine per caricare dei dati in due listbox in funzione di due condizioni.

Venendo al dunque, ho su una userform 3 listbox, nella prima un elenco di nomi e gradi che sono le colonne A e B del foglio di lavoro.

Nelle intestazioni delle altre colonne ci sono 30 corsi in 30 colonne. Nell'incrocio tra le colonne e le righe ho se quel determinato corso è obbligatorio oppura raccomandato per la persona selezionata.

Quindi al momento che clicco su una persona vorrei che una routine spazzoli tutti i corsi ed ad ogni intersezione con la riga mi inserisca quelli obbligatori in una listbox e quelli raccomandati nella seconda listbox. Ovviamente se l'intersezione risulta vuota non aggiunge nessun corso. Spero di essere stato chiaro nella spiegazione e vi allego una parte della tabella con i dati mensionati.

Anticipatamente ringrazio

Saluti

Giuseppe

JOB TITLE SURMANE & NAME PERSONAL SURVIVAL TECNIQUES STCW A-VI/1-1 FIRE PREVENTION AND FIREFIGHTING STCW  A-VI/1-2 ELEMENTARY FIRST AID STCW A-VI/1-3 PERSONAL SAFETY & SOCIAL RESPONSIBILIES STCW A-VI/1-4 PROFICENCY IN SURVIVAL CRAFTS AND RESCUE BOATS (other than fast rescue boat) STCW A-VI/2<br>(7*) ADVANCED FIRE FIGHTING STCW A-VI/3 (7*) FAST RESCUE BOATS STCW  A-VI/2 MEDICAL FIRST AID STCW A-VI/4-1 MEDICAL CARE STCW A-VI/4-2 GMDSS STCW A- IV/2
Master LANGELLA GIUSEPPE M M M M M M M M
Master CASTELLANO GIUSEPPE M M M M M M M M
Chief Mate PITINO SALVATORE M M M M M M R M M
Chief Mate SEKULJA RAJKO M M M M M M R M M
2nd Mate PERSIANO RAFFAELE M M M M M M R R R M
2nd Mate LANDINI ANDREA M M M M M M R R R M
3rd Mate BAZIN ALEKSANDR M M M M M M R R R M
3rd Mate FILIPCIUK ANDREJ M M M M M M R R M
Chief Engineer ANICHINI FEDERICO M M M M M M R
Chief Engineer RIVANO VICTOR M M M M M M R
1st Engineer SOLARI FABIO M M M M M M R R
1st Engineer MORGERA GIUSEPPE M M M M M M R R
2nd Engineer FAVATELLA ANTONIO M M M M M M R R
2nd Engineer LUCIA LUIGI M M M M M M R R
2nd Engineer SENYAK YURIY M M M M R R R R
Microsoft 365 e Office | Excel | Per la casa | Windows

Domanda bloccata. Questa domanda è stata eseguita dalla community del supporto tecnico Microsoft. È possibile votare se è utile, ma non è possibile aggiungere commenti o risposte o seguire la domanda.

0 commenti Nessun commento
Risposta accettata dall'autore della domanda
Anonimo
2016-06-23T00:28:30+00:00

Prova a vedere questo file di esempio (#5) dove alla UserForm ho aggiunto delle ListBox dedicate alle "intestazioni multiple" e dove ho modificato i comandi nell'evento Initialize della user.

Se poi tu volessi impostare anche la larghezza delle colonne potresti dichiarare delle costanti di testo con le misure desiderate e poi assegnare quelle misure alle rispettive TextBox (sia quelle dedicate a contenere i dati veri e propri che quelle dedicate a contenere le intestazioni multiple). In questo modo avresti i dati sempre allineati.

Questo il nuovo file: File esempio #5

Questo il codice, all'interno della User, che ho modificato per tener conto delle ListBox che fanno da intestazione.

'---

Private Sub UserForm_Initialize()

  Dim sLB_Header_MaritimeCrew As Variant

  Dim sLB_Header_CertificateOnBoard As Variant

  Dim sLB_Header_CertificateExpired As Variant

  sLB_Header_MaritimeCrew = Array("Grado", "Cognome e Nome", "Badge Nr")

  sLB_Header_CertificateOnBoard = Array("Certificato", "Data Scadenza")

  sLB_Header_CertificateExpired = Array("Certificato", "Data Scadenza", "Giorni scadenza")

  Set Wb = ThisWorkbook

  With Wb

    Set Ws1 = .Worksheets(sNameWs1)

    Set Ws1Rng1 = Ws1.Range(sWs1Rng1)

    Set CR1 = Ws1Rng1.CurrentRegion

    NumRowCR1 = CR1.Rows.Count

    NumColumnCR1 = CR1.Columns.Count

    Set Ws2 = .Worksheets(sNameWs2)

    Set Ws2Rng1 = Ws2.Range(sWs2Rng1)

    Set CR2 = Ws2Rng1.CurrentRegion

    NumRowCR2 = CR2.Rows.Count

    NumColumnCR2 = CR2.Columns.Count

  End With

  DataOdierna = Date

  With Me

    With .LB_MaritimeCrew

      .List() = CR1.Offset(1, 0).Resize(NumRowCR1 - 1, 3).Value

      .ColumnCount = 3

    End With

    With .LB_Header_MaritimeCrew

      .Column() = sLB_Header_MaritimeCrew

      .ColumnCount = 3

    End With

    With .LB_Header_CertificateOnBoard

      .Column() = sLB_Header_CertificateOnBoard

      .ColumnCount = 2

    End With

    With .LB_Header_CertificateExpired

      .Column() = sLB_Header_CertificateExpired

      .ColumnCount = 3

    End With

    .LB_CertificateOnBoard.ColumnCount = 2

    .LB_CertificateExpired.ColumnCount = 3

  End With

End Sub

'---

p.s. mi sono accorto che avevo nominato la listbox dei certificati scaduti LB_CertificateExipired (con una i dopo la x) e ho provveduto a modificare il nome della TextBox e i relativi riferimenti nel codice con LB_CertificateExpired

p.p.s questo l'aspetto grafico della UserForm con le listbox delle intestazioni colorate di "giallo chiaro"

![](http://fud.community.services.support.microsoft.com/Fud/FileDownloadHandler.ashx?fid=c6cd949e-07d5-4a2d-9cfc-4e1045bce1c3)

La risposta è stata utile?

0 commenti Nessun commento
Risposta accettata dall'autore della domanda
Anonimo
2016-06-22T21:16:50+00:00

Dopo la partita dell'Italia, un po' deludente a dire il vero, ti propongo questo file esempio (il quarto :-) ) dove ho inserito una UserForm2.

File esempio #4

Tutto il codice (così Mauro non mi cazzia :-D) è presente all'interno della UserForm2.

Alle ListBox ho dato dei nomi "particolari" (LB_MaritimeCrew, LB_Mandatory, LB_Racommended, LB_CertificateOnBoard, LB_CertificateExipired).

Questo il codice presente all'interno della UserForm2 (caricabile tramite il pulsante presente nel Foglio1).

'---

Option Explicit

Const sNameWs1 As String = "Foglio1"

Const sWs1Rng1 As String = "A1"

Const sNameWs2 As String = "Foglio2"

Const sWs2Rng1 As String = "A1"

Dim Wb As Workbook

Dim Ws1 As Worksheet

Dim Ws1Rng1 As Range

Dim CR1 As Range

Dim NumRowCR1 As Integer

Dim NumColumnCR1 As Integer

Dim Ws2 As Worksheet

Dim Ws2Rng1 As Range

Dim CR2 As Range

Dim NumRowCR2 As Integer

Dim NumColumnCR2 As Integer

Dim DataOdierna As Date

Private Sub UserForm_Initialize()

  Set Wb = ThisWorkbook

  With Wb

    Set Ws1 = .Worksheets(sNameWs1)

    Set Ws1Rng1 = Ws1.Range(sWs1Rng1)

    Set CR1 = Ws1Rng1.CurrentRegion

    NumRowCR1 = CR1.Rows.Count

    NumColumnCR1 = CR1.Columns.Count

    Set Ws2 = .Worksheets(sNameWs2)

    Set Ws2Rng1 = Ws2.Range(sWs2Rng1)

    Set CR2 = Ws2Rng1.CurrentRegion

    NumRowCR2 = CR2.Rows.Count

    NumColumnCR2 = CR2.Columns.Count

  End With

  DataOdierna = Date

  With Me

    With .LB_MaritimeCrew

      .List() = CR1.Offset(1, 0).Resize(NumRowCR1 - 1, 3).Value

      .ColumnCount = 3

    End With

    .LB_CertificateOnBoard.ColumnCount = 2

    .LB_CertificateExipired.ColumnCount = 3

  End With

End Sub

Private Sub LB_MaritimeCrew_Click()

  Dim sJobTitle As String

  Dim sNomePersonale As String

  Dim rngFindCorsiJobTitle As Range

  Dim rngFindCorsiPersonale As Range

  Dim i As Integer, t As Integer

  With Me

    .LB_Mandatory.Clear

    .LB_Racommended.Clear

    .LB_CertificateOnBoard.Clear

    .LB_CertificateExipired.Clear

  With .LB_MaritimeCrew

    sJobTitle = .List(.ListIndex, 0)

    sNomePersonale = .List(.ListIndex, 1)

  End With

  Set rngFindCorsiJobTitle = CR2.Resize(NumRowCR2, 1).Find(What:=sJobTitle, After:=Ws2Rng1, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)

  Set rngFindCorsiPersonale = CR1.Resize(NumRowCR1, 2).Find(What:=sNomePersonale, After:=Ws1Rng1.Offset(0, 1), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows)

    For i = 1 To NumColumnCR2 - 1

      If UCase(rngFindCorsiJobTitle.Offset(0, i).Value) = "M" Then

        .LB_Mandatory.AddItem Ws2Rng1.Offset(0, i).Value

      End If

      If UCase(rngFindCorsiJobTitle.Offset(0, i).Value) = "R" Then

        .LB_Racommended.AddItem Ws2Rng1.Offset(0, i).Value

      End If

        For t = 1 To NumColumnCR1 - 3

          If Ws1Rng1.Offset(0, t + 2).Value = Ws2Rng1.Offset(0, i).Value Then

            If rngFindCorsiPersonale.Offset(0, t + 1).Value <> "" Then

              If IsDate(rngFindCorsiPersonale.Offset(0, t + 1).Value) And _

                 UCase(rngFindCorsiJobTitle.Offset(0, i).Value) = "M" Then '<------------

                If rngFindCorsiPersonale.Offset(0, t + 1).Value > DataOdierna + 90 Then

                  With .LB_CertificateOnBoard

                    .AddItem

                    .List(.ListCount - 1, 0) = Ws1Rng1.Offset(0, t + 2).Value

                    .List(.ListCount - 1, 1) = rngFindCorsiPersonale.Offset(0, t + 1).Value

                  End With

                Else

                  With .LB_CertificateExipired

                    .AddItem

                    .List(.ListCount - 1, 0) = Ws1Rng1.Offset(0, t + 2).Value

                    .List(.ListCount - 1, 1) = rngFindCorsiPersonale.Offset(0, t + 1).Value

                    .List(.ListCount - 1, 2) = rngFindCorsiPersonale.Offset(0, t + 1).Value - DataOdierna

                  End With

                End If

              Else

                With .LB_CertificateOnBoard

                  .AddItem

                  .List(.ListCount - 1, 0) = Ws1Rng1.Offset(0, t + 2).Value

                  .List(.ListCount - 1, 1) = rngFindCorsiPersonale.Offset(0, t + 1).Value

                End With

              End If

            Else

              If UCase(rngFindCorsiJobTitle.Offset(0, i).Value) = "M" Then

                With .LB_CertificateExipired

                  .AddItem

                  .List(.ListCount - 1, 0) = Ws1Rng1.Offset(0, t + 2).Value

                  .List(.ListCount - 1, 1) = "To be done"

                  .List(.ListCount - 1, 2) = "!!!!!"

                End With

              End If

            End If

          End If

        Next t

    Next i

  End With

End Sub

'---

Prova a verificare se riesce a fare ciò che è nelle tue intenzioni.

La risposta è stata utile?

0 commenti Nessun commento

68 risposte aggiuntive

Ordina per: Più utili
  1. Anonimo
    2016-06-25T06:09:03+00:00

    Allora faccimo una modifica.

    Dalla procedura LoadCrew

    • Eliminare la riga: Dim sCrewName As String
    • Sostituire la riga: sCrewName = .List(.ListIndex, 1) con Set FindCertificateFromWsCrew = Ws1Rng1.Offset(.ListIndex + 1, 1)
    • Eliminare la riga: Set FindCertificateFromWsCrew = CR1.Resize(NumRowCR1, 1).Offset(0, 1).Find(What:=sCrewName, _

                                                                                   After:=Ws1Rng1.Offset(0, 1), _

                                                                                   LookIn:=xlValues, _

                                                                                   LookAt:=xlWhole, _

                                                                                   SearchOrder:=xlByRows)

    In questo modo la cella di riferimento viene impostata tramite la proprietà ListIndex.

    Il file modificato: File esempio #7 modificato

    ciao

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2016-06-24T22:48:26+00:00

    Ciao Cas.....

    Beh in effetti le probabilità di omonimia sono alquanto remote ma non impossibili. Soprattutto sui nomi italiani a volte è capitato di avere doppioni ed anche un confronto a tre elementi potrebbero esistere (grado cognome e nome).

    Per questo motivo, ora che mi ci hai fatto pensare, sul vecchio file, quando lo feci scelsi la trada del puntare la cella. Ovviamente anche perchè non sarei in grado di scrivere un codice come l'hai strutturato tu. Però devo dire che se pure stupido in effetti faceva bene il suo lavoro perchè sfruttando la proprietà listindex andavo a mirare esattamente la persona desiderata e poi con l'offset ricavavo i dati di detta persona senza probabilità di errore. Nello stesso tempo trovandomi già selezionata la riga interessata, manipolavo le varie modifiche da fare. L'unico problema che ho riscontrato con il mio codice (ed è per questo che ho chiesto aiuto a voi cercando di usare un'altra metodologia) è che a volte quando andavo ad inserire un aggiornamento data, nonostante la cella selezionata e l'offset mi ritrovavo la data inserita in un'altra posizione. Probabilmente era il codice scritto male ma secondo me l'idea di selezionare la persona con il listindex e muoversi con l'offset con un ciclo for next andrei a popolare tutte le list box senza rischiare di caricare le list box con corsi di un omonimo.

    Però sicuramente ci sarà un modo anche per evitare l'omonimia ma io non ne sono proprio capace.

    Grazie comunque del tuo prezioso aiuto e considerazioni, ripeto che lo scopo mio, nel chiedere a voi è apprendere sempre più il VBA perchè mi piace tantissimo ma non ho ne mai fatto un corso ne tantomeno letto libri quindi immagina il mio livello di conoscenze. So quelle quattro cose e le metto insieme per logica con ovvi risultati di debug.

    Ciao

    Peppe

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2016-06-24T13:47:02+00:00

    Grazie a te Giuseppe :-)

    Anche se ... ci sono sempre dei se :-)

    Stavo pensando, e quindi ti chiedo:

    Qual è la probabilità che vi sia un caso di omonimia sia nel cognome che nel nome?

    Perché, appunto riflettendo, per come ho impostato la ricerca relativamente al nominativo in verità la procedura si fermerebbe al primo trovato e, di conseguenza, se nell'elenco fosse presente un successivo componente con medesimo cognome e nome riporterebbe i dati relativi a certificati e scadenze del primo trovato.

    La risposta è stata utile?

    0 commenti Nessun commento