Excel e gli applicativi Microsoft Office Funzione ricorsiva VBA per strutturazione file Excel

Login Registrati
Stai vedendo 25 articoli - dal 1 a 25 (di 43 totali)
  • Autore
    Articoli
  • #8561 Score: 0 | Risposta

    Jotric
    Partecipante

      Buongiorno a tutti. Ho il seguente problema, in diversi files Excel ho la necessità di formattare i dati. In particolare ho una colonna che mi identifica il livello di nidificazione degli stessi. In pratica qualcosa di simile:

      1
       2
        3
        3
        3
       2
        3
        3
         4
         4
       2
        3
      Devo scorrere questa sequenza di numeri (ovviamente a priori non so quanto possa essere profondo il livello di nidificazione).

      Il risultato che devo ottenere è qualcosa di simile:

      A1
       B1
        C1
        C2
        C3
       B2
        D1
        D2
         E1
         E2
       B3
        F1
      Qualche idea su come possa fare?

      #8568 Score: 0 | Risposta

      Luca73
      Partecipante
        54 pts

        Ciao

        Spiega la logica con cui vuoi tradurre da numeri a lettere + numero

        Non capisco la lettera D da dove arrivi.

        Cerca di speigare con parole come costruire il tuo elenco nidificato.

        Ciao

        Luca

         

         

        #8570 Score: 0 | Risposta

        Jotric
        Partecipante

          Grazie per l'attenzione Luca. In sostanza, diciamo che le lettere e i numeri sono dei progressivi. Il primo livello (1) è sempre identificato con la lettera A e seguito da un numero che identifica il progressivo degli oggetti di livello 1. Passando ai livelli a scendere, avrò sempre una lettera ed un numero, progressivi a parità di livello, ma univoci a livello di albero...Meglio che allego un immagine...

          Alberi origine e destinazione

          Spero adesso sia più chiaro....

          #8571 Score: 0 | Risposta

          Jotric
          Partecipante

            Questa è la rappresentazione dell'albero del primo esempio...

            Albero primo esempio

            #8578 Score: 0 | Risposta

            Luca73
            Partecipante
              54 pts

              Ciao Vediamo cosa si può fare.

              Rituieni che 

              a) i numeri possano superare il 9?

              b) le lettere possano superare la Z? (nel caso AA, AB, AC...BA, BB,  BC...?)

              c) i livelli arrivano fino a 4 O puoi averne di più?

              Ciao

              Luca

              #8579 Score: 0 | Risposta

              Jotric
              Partecipante

                Buongiorno a te 🙂

                a) I numeri che sono legati alla lettera non sono un gran problema. Nella situazione reale sono salvati in un'altra colonna e quindi alla mia lettera ci lego il numero che trovo nell'altra colonna. Ho messo i numeri negli esempi solo per chiarirmi le idee e rendere la cosa più comprensibile.

                b) In linea teorica si, le lettere possono diventare tante, ma anche li diciamo che si potrebbe risolvere con relativamente poco sforzo.

                c) I livelli anche qui, in linea teorica, possono raggiungere profondità considerevoli. Nel file che ho davanti, ci si limita a 4, ma al momento non saprei che dire e nel dubbio dico si.

                #8580 Score: 0 | Risposta

                Luca73
                Partecipante
                  54 pts

                  a) I numeri che sono legati alla lettera non sono un gran problema. Nella situazione reale sono salvati in un'altra colonna e quindi alla mia lettera ci lego il numero che trovo nell'altra colonna. Ho messo i numeri negli esempi solo per chiarirmi le idee e rendere la cosa più comprensibile.

                  Cosa intendi?

                  Puoi inviare un file di esempio? Senza dati sensibili?

                  Riguardo alle domande che ti ho fatto, avere i limiti o una idea dei limiti aiuta ad impostare il programma. se devo prevedere due lettere o una, se devo prevdere una formattazione dei numeri di un certo tipo, ....

                  Ciao

                  Luca

                  #8584 Score: 0 | Risposta

                  Jotric
                  Partecipante

                    Allora ti ho allegato il file xlsx che contiene i dati e il file .bas da associare al file.

                    Dopo l'importazione del file .bas lancia la macro "ScompattaDistinteNuovoFormato" che altro non fa che scorrere i fogli e preparare i livelli "A".Il dato numerico associato al nodo te lo trovi nella colonna B. Dopodiché,  sempre nello stesso file la macro che si chiama "GestioneSubLivello" dove ho iniziato a far qualcosa...C'è un'istruzione " For I = RangeLimitUp To RangeLimitDw" che scrolla il Range fra due livelli A.

                    Vedi se ti può essere utile.

                    Allegati:
                    You must be logged in to view attached files.
                    #8586 Score: 0 | Risposta

                    Jotric
                    Partecipante

                      Ciao Luca...scusa per le info incomplete. Ti allego il file dati che sto usando ed un file di macro che preparano gli stessi. DOpo aver caricato il file .bas, lancia la macro "ScompattaDistinteNuovoFormato" che prepara le colonne. Nella colonna B ti troverai appunto il numero da legare alla lettera.

                      Sempre nello stesso file c'è la macro "GestioneSubLivello" in cui ho iniziato a far qualcosa. Ti troverai un ciclo che itera fra due livello A " For I = RangeLimitUp To RangeLimitDw".

                      Vedi se può esserti utile.

                      Allegati:
                      You must be logged in to view attached files.
                      #8589 Score: 0 | Risposta

                      Jotric
                      Partecipante

                        Ho rinominato l'estensione del bas perchè non me lo lasciava caricare...

                        #8591 Score: 0 | Risposta

                        Luca73
                        Partecipante
                          54 pts

                          Ciao ci sto lavorando. Ho quasi finito spero Lunedì di ricordarmi.

                          Ciao

                          Luca

                          #8592 Score: 0 | Risposta

                          vecchio frac
                          Senior Moderator
                            238 pts

                            Questo è un caso interessante e potrebbe diventare anche un articolo per il blog.

                            Magari vi potesse interessare, si accettano proposte da chiunque...

                            Scrivete le bozze degli articoli direttamente a redazione@excelvba.it

                            Non ci sono premi ma la soddisfazione di stuzzicare interesse altrui 🙂

                            #8626 Score: 0 | Risposta

                            Luca73
                            Partecipante
                              54 pts

                              Ciao Ecco una prima proposta.

                              Siccome l'ho fatta e modificata. Secondo me va migliorata e ottimizzata. infatti il vettore che prevedevo dimutilizzare in un modo el'avevo riempito con un criterio, poi l'ho modificato e in parte non serve.

                              Accetta lettere multiple (ovvero dopo Z c'è AA,...dopo AA c'è AB, dopo AZ c'è BA,...dopo ZZ c'è AAA...)

                              ATTENZIONE al momento la macro parte da A2 e prende tutto ciò che c'è sotto e poi SCRIVE NELLA COLONNA A FIANCO.

                               

                              Option Explicit
                              
                              Sub Livelli()
                              Dim Vettore()
                              Dim NumeroLivelli As Integer
                              Dim NumeroCelle As Integer
                              Dim PrimaCella As Range
                              Dim UltimaCella As Range
                              Dim Intervallo As Range
                              Dim CellaW As Range
                              Dim Index As Integer
                              Dim Index2 As Integer
                              Dim LastLetter As String
                              Dim LetterToUse As String
                              Dim MaxN As Integer
                              Dim NumZeri As String
                              
                              Set PrimaCella = Range("A2")
                              Set UltimaCella = PrimaCella.End(xlDown)
                              Set Intervallo = Range(PrimaCella, UltimaCella)
                              
                              MaxN = 1
                              LastLetter = "A"
                              
                              NumeroCelle = Intervallo.Count
                              NumeroLivelli = 0
                              For Each CellaW In Intervallo
                                  If CellaW > NumeroLivelli Then
                                      NumeroLivelli = CellaW
                                  End If
                              Next CellaW
                              ReDim Vettore(0 To NumeroLivelli, 0 To NumeroCelle, 1 To 2)
                              For Index = 1 To NumeroCelle
                                  If PrimaCella.Offset(Index - 1, 0) * 1 = 1 Then
                                      Vettore(1, 0, 1) = Vettore(1, 0, 1) + 1
                                      Vettore(1, Index, 1) = Vettore(1, 0, 1)
                                      Vettore(0, Index, 1) = "A"
                                      Vettore(0, Index, 2) = Vettore(1, 0, 1)
                                      'PrintVect (Vettore)
                                      If Vettore(1, 0, 1) > MaxN Then
                                          MaxN = Vettore(1, 0, 1)
                                      End If
                                  Else
                                      If PrimaCella.Offset(Index - 1, 0) * 1 > PrimaCella.Offset(Index - 2, 0) * 1 Then
                                          Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) = 1
                                          Vettore(PrimaCella.Offset(Index - 1, 0), Index, 1) = 1
                                          LastLetter = LetterPlus1(LastLetter)
                                          Vettore(0, Index, 1) = LastLetter
                                          Vettore(PrimaCella.Offset(Index - 1, 0), 0, 2) = LastLetter
                                          Vettore(0, Index, 2) = 1
                                          'PrintVect (Vettore)
                                      ElseIf PrimaCella.Offset(Index - 1, 0) * 1 < PrimaCella.Offset(Index - 2, 0) * 1 Then
                                          For Index2 = (PrimaCella.Offset(Index - 1, 0) + 1) To NumeroLivelli
                                              Vettore(Index2, 0, 1) = 0
                                          Next Index2
                                          Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) + 1
                                          Vettore(PrimaCella.Offset(Index - 1, 0), Index, 1) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1)
                                          Vettore(0, Index, 2) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1)
                                          If Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) = 0 Then
                                              LastLetter = LetterPlus1(LastLetter)
                                              LetterToUse = LastLetter
                                          Else
                                              LetterToUse = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 2)
                                          End If
                                          
                                          Vettore(0, Index, 1) = LetterToUse
                                          Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) + 1
                                          If Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) > MaxN Then
                                              MaxN = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1)
                                          End If
                                          
                                          'PrintVect (Vettore)
                                      Else
                                          Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) + 1
                                          Vettore(PrimaCella.Offset(Index - 1, 0), Index, 1) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1)
                                          'PrintVect (Vettore)
                                          Vettore(0, Index, 1) = LastLetter
                                          Vettore(0, Index, 2) = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1)
                                          
                                          If Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1) > MaxN Then
                                              MaxN = Vettore(PrimaCella.Offset(Index - 1, 0), 0, 1)
                                          End If
                                          
                                      End If
                                  End If
                              Next Index
                              'PrintVect (Vettore)
                              NumZeri = ""
                              For Index = 1 To Len(MaxN)
                                  NumZeri = NumZeri & "0"
                              Next Index
                              For Index = 1 To NumeroCelle
                                  PrimaCella.Offset(Index - 1, 1) = Vettore(0, Index, 1) & Format(Vettore(0, Index, 2), NumZeri)
                              Next Index
                              End Sub
                              
                              
                              Function LetterPlus1(LetteraIniziale)
                              Dim PosLet As Integer
                              Dim VettoreLet
                              ReDim VettoreLet(1 To Len(LetteraIniziale))
                              For PosLet = 1 To Len(LetteraIniziale)
                                  VettoreLet(PosLet) = Mid(LetteraIniziale, Len(LetteraIniziale) - PosLet + 1, 1)
                              Next
                              
                              PosLet = 1
                              Do
                                  If VettoreLet(PosLet) < "Z" Then
                                      VettoreLet(PosLet) = Chr(Asc(VettoreLet(PosLet)) + 1)
                                      Exit Do
                                  Else
                                      VettoreLet(PosLet) = "A"
                                      PosLet = PosLet + 1
                                  End If
                                  If PosLet > UBound(VettoreLet, 1) Then
                                      ReDim Preserve VettoreLet(1 To PosLet)
                                      VettoreLet(PosLet) = Chr(Asc("A") - 1)
                                  End If
                              Loop
                              LetterPlus1 = ""
                              For PosLet = UBound(VettoreLet, 1) To 1 Step -1
                                  LetterPlus1 = LetterPlus1 & VettoreLet(PosLet)
                              Next
                              
                              End Function

                               

                               

                               

                              #8651 Score: 0 | Risposta

                              vecchio frac
                              Senior Moderator
                                238 pts

                                @luca,

                                ho fatto girare per prova sul file Esempio-1.xlsx. Si ferma, come giusto, sul primo ciclo For, perchè "CellaW" (che punta al range in colonna A)  non contiene un numero ma un testo e non lo puoi confrontare con un numero ("NumeroLivelli"). Probabilmente, presumo, il range "Intervallo" deve puntare alla colonna B ("Level").

                                Tu su che versione del file hai lavorato?

                                #8652 Score: 0 | Risposta

                                Jotric
                                Partecipante

                                  Buongiorno Luca. Intanto grazie per la risposta. Adesso la sto cercando di analizzare. In realtà la prima difficoltà che incontro è capire su che intervallo stai lavorando. Nel mio esempio, la colonna "A" contiene dati non preparati (ad esempio: 101 - 0.003988.E), le colonne "B" e "C"  contengono il dato scomposto. Nella colonna "D" i dati del primo livello. La colonna "E" è quella destinata a contenere il dato del livello elaborato. Nel tuo ciclo:

                                  For Each CellaW In Intervallo
                                      If CellaW > NumeroLivelli Then
                                          NumeroLivelli = CellaW
                                      End If
                                  Next CellaW

                                  in realtà non capisco su che dati tu vada ad operare...

                                   

                                  #8653 Score: 0 | Risposta

                                  Jotric
                                  Partecipante

                                    Lavoro sulla stessa versione del file. Ma hai caricato il file .bas e lanciato la macro "ScompattaDistinteNuovoFormato"?

                                    #8654 Score: 0 | Risposta

                                    vecchio frac
                                    Senior Moderator
                                      238 pts

                                      Comunque il codice non è male anche se sembra incasinato 🙂 ho fatto qualche aggiustatina perchè si arrabbiava ancora confrontando numeri con testo, e ho poi printato nell'ultima colonna anziché nella terza, ma alla fine mi sembra un risultato coerente con la richiesta iniziale. L'unica piccola pecca è che il livello zero viene indicato con "A01" (sicché alla fine ho due livelli "A01") ma penso che si possa sistemare facilmente.

                                      #8655 Score: 0 | Risposta

                                      vecchio frac
                                      Senior Moderator
                                        238 pts

                                        Jotric ha scritto:

                                        Ma hai caricato il file .bas e lanciato la macro "ScompattaDistinteNuovoFormato"?

                                        No, ho lanciato "LIvelli" 😀

                                        Adesso mi guardo il codice che hai indicato.

                                        #8656 Score: 0 | Risposta

                                        vecchio frac
                                        Senior Moderator
                                          238 pts

                                          Jotric ha scritto:

                                          in realtà non capisco su che dati tu vada ad operare...

                                          Nel codice originale della sub Livello, "Intervallo" punta alla colonna A. Ma ho sbagliato io e adesso vado a vedere il codice cui ti riferivi poco fa (è quello su cui Luca ha messo mano?).

                                          #8657 Score: 0 | Risposta

                                          Luca73
                                          Partecipante
                                            54 pts

                                            Ciao

                                            Non ho lavorato sul tuo file ma su uno che mi ero creato io.

                                            Basta cambiare la riga 

                                            Set PrimaCella = Range("A2")

                                            Il mio file parte da A2 e prende tutto ciò che c'è sotto fino alla prima libera

                                            Set UltimaCella = PrimaCella.End(xlDown)
                                            #8658 Score: 0 | Risposta

                                            vecchio frac
                                            Senior Moderator
                                              238 pts

                                              Jotric ha scritto:

                                              Lavoro sulla stessa versione del file. Ma hai caricato il file .bas e lanciato la macro "ScompattaDistinteNuovoFormato"?

                                              @jotric

                                              Quello è il tuo codice originale, che Luca ha probabilmente riscritto per venire incontro alla tua richiesta. Quindi non lo guardo neanche visto che lo ha già fatto l'amico Luca 🙂

                                              #8659 Score: 0 | Risposta

                                              vecchio frac
                                              Senior Moderator
                                                238 pts

                                                @luca

                                                Ho avuto difficoltà come dicevo sui test che i due Ifs fanno per controllare i valori di PrimaCella. Nel tuo codice viene confrontato un valore numerico con un valore testuale. Ho dovuto correggere così:

                                                If Val(PrimaCella.Offset(Index - 1, 0)) * 1 > Val(PrimaCella.Offset(Index - 2, 0)) * 1 Then

                                                forzando con Val() la traduzione numerica del contenuto indicizzato di PrimaCella. Poi tutto fila liscio con la particolarità del livello zero come ho già accennato. In realtà poi io metterei il risultato in ultima colonna, senza sovrascrivere la descrizione.

                                                For Index = 1 To NumeroCelle
                                                    PrimaCella.Offset(Index - 1, 11) = Vettore(0, Index, 1) & Format(Vettore(0, Index, 2), NumZeri)
                                                Next Index

                                                Comunque complimenti non era facile   

                                                #8662 Score: 0 | Risposta

                                                Jotric
                                                Partecipante

                                                  Ho risistemato le mie macro per impostare i dati in modo da far girare la macro. Impostando la colonna "B" col livello e lasciando libera la colonna "C", i livelli sono aggiunti correttamente, almeno per quanto riguarda la lettera. Adesso Devo sistemare i numeri che in realtà non sono progressivi ma sono i primi caratteri (quelli preceduti dal "-" ) nella colonna "A". Inoltre ci sono delle lettere che non sono ammesse (ad esempio la "I" e lo "O" come valori iniziali). Avevo pensato un approccio decisamente diverso, lavorando sul range del singolo gruppo, tu @luca hai lavorato sul range interno invece....Complimenti @vecchio frac che dici "sembra incasinato"....mi ci vorranno diversi giorni per capire il meccanismo di "vettore"  

                                                  #8667 Score: 0 | Risposta

                                                  vecchio frac
                                                  Senior Moderator
                                                    238 pts

                                                    Bè dai, è un vettore a tre dimensioni che raccoglie per ogni cella (seconda dimensione) il proprio numero di livello (prima dimensione) e il numero progressivo per livello (terza dimensione). Nel primo elemento della prima dimensione (indice zero) il vettore si ricorda dell'elemento radice per ogni nuova lettera (ogni nuova foglia dell'albero). Complesso ma non complicato e anche ingegnoso.

                                                    Ma il risultato che ha raggiunto Luca ti soddisfa o no? perchè dici:

                                                    Jotric ha scritto:

                                                    Adesso Devo sistemare i numeri che in realtà non sono progressivi ma sono i primi caratteri (quelli preceduti dal "-" ) nella colonna "A".

                                                    #8673 Score: 0 | Risposta

                                                    Jotric
                                                    Partecipante

                                                      In realtà, funziona in parte. Aumentando il livello di complessità dell'albero, ci sono degli errori nel risultato. Ora riuscire a capire dove e perché si verificano con una matrice a tre dimensioni non è semplicissimo. Vediamo se con un esempio riesco a spiegarmi:

                                                      Supponiamo questo albero, il risultato che si ottiene ha un errore...

                                                      Il livello è sempre il 3, quindi dovrebbe essere una C

                                                       

                                                    Login Registrati
                                                    Stai vedendo 25 articoli - dal 1 a 25 (di 43 totali)
                                                    Rispondi a: Funzione ricorsiva VBA per strutturazione file Excel
                                                    Gli allegati sono permessi solo ad utenti REGISTRATI
                                                    Le tue informazioni: