range celle variabile e delimitato



  • range celle variabile e delimitato
    di trasp (utente non iscritto) data: 27/09/2012 19:51:23

    salve,
    sto cercando una soluzione che mi permetta di trasporre del testo elencato in verticale.
    Il range di celle non è costante ed è delimitato all'inizio e alla fine da un carattere (p.e. un punto).
    Porto un esempio:
    .
    a
    b
    c
    d
    .
    a
    b
    c
    .
    ecc.
    ho trovato una soluzione parziale in vba che mi estrae i dati dalla colonna A1 ma la logica di estrazione prevede gruppi di tre celle per volta.
    Ringrazio sin d'ora se qualcuno riesce a dirmi come modificare il codice, adattando la parte legata al range.
    Premetto che smanetto un pò ma non conosco la sintassi vb, inoltre prima di chiedere ho girato molto e provato soluzioni altre senza grosse soddisfazioni.
    Posto di seguito il codice.
    Grazie ancora per l'eventuale aiuto.
    un saluto
     
    Sub Trasponi()
    Dim D1, D2 As Date 
    Dim tempoimpiegato As String 
    D1 = Time
    Application.ScreenUpdating = False 
    
    Set zona = Range(Range("A1"), Range("A1").End(xlDown)) 
    cont = zona.Rows.Count 
    For N = 1 To cont Step 3   
    If Worksheets("Foglio1").Cells(N, 1) <> "" Then  
    Range(Cells(N, 1), Cells(N + 2, 1)).Select  
    Selection.Copy  
    
    Worksheets("Foglio2").Select 
    Dim iRow As Integer
    iRow = 1  
    While Cells(iRow, 1).Value <> "" 
    iRow = iRow + 1   
    Wend
    Cells(iRow, 1).Select 
    Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
    :=False, Transpose:=True
    End If
    Worksheets("Foglio1").Select  
    Next  
    Application.CutCopyMode = False  
    
    D2 = Time 
    tempoimpiegato = Format(D2 - D1, "hh:mm:ss") 
    MsgBox "Tempo impiegato: " & tempoimpiegato 
    
    End Sub
    



  • di Vecchio Frac data: 27/09/2012 20:28:34

    Non ho capito la domanda...
    hai un range di celle in colonna A (tutto in verticale) e vuoi trasporre i dati in riga (quindi in orizzontale), ma a gruppi di celle delimitate dal punto?
    Se sì: un'idea è buttare tutot in una variabile locale, splittarla al punto, e ogni pezzo trasporlo nel range orizzontale che ti interessa.
    Se i bambini vanno a leto senza storie e la moglie non mi stressa, dopo provo a tradurre questo pensiero in VBA... altrimenti domattina :)





  • di trasp (utente non iscritto) data: 27/09/2012 20:54:18

    si esatto! in effetti, quel codice sarebbe stato perfetto se non avesse avuto il range a step di tre (modificabile da codice ma sempre costante).
    L'output che mi indichi è corretto, come risultato avrei i dati incolonnati parallelamente e trasposti a gruppi delimitati dalla costante "punto":
    prima
    .
    a
    b
    c
    d
    .
    a
    b
    c
    .
    dopo

    abcd
    abc

    grazie per la tua disponibilità.
    Mi sono un pò fusa la testa a cercare in questi giorni, alcune cose del codice sono comprensibili, altre un pò meno quando non si conosce la logica di un linguaggio.
    ad ogni modo appena puoi



  • di HarryBosch data: 27/09/2012 20:55:47

    Mi intrometto anch'io :)
    L'idea di "splittare" la variabile che raccoglie l'intervallo fra i punti è molto bella (è una funzione che uso molto anch'io.. lo split, intendo).
    Ma la lascio a Vecchio Frac che ha sicuramente già immaginato il "progetto"

    Nel frattempo sono andato "sopra" al codice che hai postato, modificandolo allo scopo che hai chiesto.

     
    Sub Trasponi()
    
        Dim D1 As Date, D2 As Date
        Dim tempoimpiegato As String
        Dim cella As Range, zona As Range
        Dim iRow As Integer, iCol As Integer
        D1 = Time
    
        Set zona = Range(Range("A1"), Range("A1").End(xlDown))
        iCol = 1
        iRow = 1
        
        With Sheets("Foglio2")
            For Each cella In zona
                If cella <> "." Then
                    .Cells(iRow, iCol) = cella.Value
                    iCol = iCol + 1
                ElseIf cella = "." Then
                    While .Cells(iRow, 1).Value <> ""
                        iRow = iRow + 1
                    Wend
                       iCol = 1
                End If
            Next cella
        End With
    
        Sheets("Foglio2").Activate
        D2 = Time
        tempoimpiegato = Format(D2 - D1, "hh:mm:ss")
        MsgBox "Tempo impiegato: " & tempoimpiegato
    
    End Sub
    



  • di trasp (utente non iscritto) data: 27/09/2012 21:24:48

    che posso dire...grazie! è il risultato che mi aspettavo!
    Questo sito me lo tengo tra i preferiti e lo consiglierò come punto di riferimento.
    Grazie anche per la velocità della soluzione, è magnifico!
    ciao e a presto



  • di Vecchio Frac data: 27/09/2012 21:52:44

    Se consideri risolta la discussione bene, merito di Harry :)
    Penso comunque che ci proverò lo stesso... ma domani, perchè preso dall'entusiasmo ho dimenticato di dirvi che qui a casa ho sostituito l'hard disk con un più ciccione (2TB) e ne ho approfittato per provare ad installare un Ubuntu nuovo di zecca. Risultato: tutto perfetto, a parte la novità un po' scioccante per un Windowsiano storico come me... il dramma è che non ho a disposizione nè Office nè Excel e quindi devo approntare una macchina virtuale per tornare operativo :)





  • di trasp (utente non iscritto) data: 27/09/2012 22:09:02

    Caro Frac,
    sarei curiosa di sperimentare la tua soluzione, qualora la volessi postare, in ogni caso sono davvero grata a te ed Harry per disponibilità e prontezza nell'aiuto.
    Grazie e a presto



  • di HarryBosch data: 27/09/2012 22:28:58

    @ trasp
    Ma di niente, anzi, vieni a trovarci presto.. vedrai poi che la soluzione con lo split sarà sicuramente più elegante.
    E se hai qualche dubbio sui passaggi del codice chiedi pure.

    @ Vecchio Frac
    wow, Bravo Vecchio Frac! anch'io ogni tanto giro su Ubuntu con la "solita" virtual machine, più che altro per smacchinare con il terminale ma come te, a Windows faccio fatica a rinunciare. Ho provato pure Windows 8 e sarà anche innovativo ma, tutte queste task mi rovinano il classico desktop con le mie "comode" cartelle. Hai provato i "cloni" gratuiti di Office? Ci sono anche portable



  • di Vecchio Frac data: 28/09/2012 08:36:50

    [OT]
    Io faccio una fatica doppia perchè in ufficio ho XP e a casa (avevo) Seven, due mondi diversi :)
    Win8 volevo provarlo ma non sono riuscito a virtualizzarlo.
    LibreOffice attualmente presente su Linux è nel complesso carino e pulito, molto simile a Office, ha un Basic suo abbastanza versatile ma non completamente compatibile. Mi piace molto che ci sia l'interprete Python integrato (sto studiando anche Python adesso ^_^).
    Però preferisco Office, lo conosco mille volte meglio.
    [/OT]





  • di Vecchio Frac data: 28/09/2012 09:52:04

    Provate questo codice, ditemi cosa ne pensate.
    Notate la tecnica molto carina per "appiattire" un range in un array.
    Sembra contorto ma non lo è: dopo aver appiattito con Transpose il range (zona) e unificato con Join, l'ho risuddiviso in corrispondenza del carattere punto (con Split).
    Quindi ho trasferito ogni elemento del vettore così ottenuto nel foglio2, utilizzando TextToColumns (separando ogni elemento del vettore in corrispondenza del carattere nullo).
    Doveroso sottolineare che la routine suppone di trovare i dati in colonna A del foglio1, che non ci siano righe vuote prima dell'inizio del range e che il foglio2 sia liberamente disponibile ad accogliere il risultato dell'operazione.

     
    Sub trasponi2()
    Dim zona As Range, t1 As Single, compact_range As Variant, v As Variant, i As Integer
    
        Application.ScreenUpdating = False
        Application.DisplayAlerts = False
        
        t1 = Timer
        Sheets("Foglio1").Activate
        Set zona = Range([A1], [A1].End(xlDown))
        
        compact_range = Split(Join(WorksheetFunction.Transpose(zona)), ".")
        
        For Each v In compact_range
            With Sheets("Foglio2").[A1].Offset(i, 0)
                .Value = v
                .TextToColumns other:=True, otherchar:=vbNullChar
            End With
            i = i + 1
        Next
    
        Application.ScreenUpdating = True
        Application.DisplayAlerts = True
        
        MsgBox "Tempo impiegato: " & Format(Timer - t1, "0.00") & " secs."
        
    End Sub






  • di trasp (utente non iscritto) data: 30/09/2012 13:48:20

    ciao Vecchio Frac,
    solo oggi ho potuto fare una prova pratica del codice.
    Tutto è disposto secondo quanto hai detto:
    foglio1 con dati incolonnati in A,foglio2 pronto ad accogliere i dati estratti.
    Quando lancio il codice si ferma ad un errore di debug in corrispondenza dell'istruzione ".TextToColumns other:=True, otherchar:=vbNullChar" e la finestra di dialogo dice che "non è stato selezionato alcun dato da analizzare".
    Una precisazione, la colonna A del foglio1 inizia con un punto, se lo tolgo ottengo l'incolonnamento ma incontro un altro problema legato alla formattazione d'origine della data, che a sua volta è frutto di un'estrazione da codice, (es. dom30/09/20120.13.48,66)
    Difatti, ho disposti verticalmente anche i numeri della data seguiti dal punto (13 e 48,66).
    Un piccolo inciso, anche sulla data ho provato a fare un passaggio successivo per estrarre solo 30/09/2012 con stringa estrai ed è perfetto ma se poi desidero cambiare il formato in 30-set (il formato che mi serve), non lo prende, questa è comunque un'altra faccenda.
    Altra cosa, il codice è velocissimo in esecuzione!
    Sarei curiosa di capire come mai mi da quell'errore, è per via del punto iniziale immagino, ma non è una cella vuota..
    Grazie per il tempo che hai dedicato.
    A presto




  • di Vecchio Frac data: 01/10/2012 11:49:48

    Ti chiederei, se possibile, il file con il codice che dà errore e con dati fittizi per fare delle prove sul campo.





  • di Vecchio Frac data: 01/10/2012 13:54:53

    Dunque ho risolto il problema del punto iniziale: la stringa nulla derivante dà split mandava in confusione il successivo TextToColumns.
    Allego quindi la versione del codice che tenga conto dell'eventualità e la corregga.
    Quindi adesso funziona, punto iniziale o no :)
    Sul problema della data, attendo, se ti interessa ancora, un piccolo file con dati di esempio su cui lavorare perchè sicuramente si può risolvere :)
     
    Sub trasponi2()
    Dim zona As Range, t1 As Single, compact_range As Variant, v As Variant, i As Integer
    
        Application.ScreenUpdating = False
        Application.DisplayAlerts = False
        
        t1 = Timer
        Sheets("Foglio1").Activate
        Set zona = Range([A1], [A1].End(xlDown))
        
        compact_range = Split(Join(WorksheetFunction.Transpose(zona)), ".")
        
        For Each v In compact_range
            If v <> vbNullString Then
                With Sheets("Foglio2").[A1].Offset(i, 0)
                    .Value = v
                    .TextToColumns other:=True, otherchar:=vbNullChar
                End With
                i = i + 1
            End If
        Next
    
        Application.ScreenUpdating = True
        Application.DisplayAlerts = True
        
        MsgBox "Tempo impiegato: " & Format(Timer - t1, "0.00") & " secs."
        
    End Sub






  • di trasp (utente non iscritto) data: 01/10/2012 16:07:45

    ciao Vecchio Frac,
    ho fatto le debite prove e stavolta non mi segnala nessun errore di debug ma il risultato dell'incolonnamento è lo stesso, nel senso che incolonna anche i numeri successivi alla data.
    Ti allego due file, il primo è il file di testo dal quale pesco i dati (quello che ti allego è un campione rappresentativo), il secondo è un xls dove all'interno troverai tre fogli:
    dati
    foglio1
    foglio2
    nel foglio dati, vedrai un elenco con le voci che voglio estrapolare dal txt (anche qui, non ho capito perchè mi tronca le voci in elenco, inoltre ho scoperto che è case sensitive, cmq sempre altro discorso che, per estensione, investe anche la data)
    il foglio1 ha successivi passaggi che sono pulisci e trasponi appunto (azioni avviate da pulsanti)
    il foglio2 già sai.
    ps a sto punto tolgo il flag a risolto vista la continuità della conversazione
    ciao



  • di Vecchio Frac data: 02/10/2012 08:19:26

    Scusa la domanda ingenua, ma nel tracciato del file txt allegato le diverse sezioni da importare sono delimitate da numerosi trattini consecutivi (cui segue un punto su riga nuova):
    -------------------------
    .
    start process =
    ...
    END PROCESS =
    -------------------------
    .

    Allora mi (ti) chiedo: perchè non consideriamo come separatore la riga di trattini, evitando così i problemi legati al riconoscimento della data, che altrimenti verrebbe splittata in considerazione del punto? in mattinata posterò il codice modificato in questo senso.






  • di Vecchio Frac data: 02/10/2012 09:41:48

    E il tuo obiettivo finale qual è?
    Da quel che ho capito io è:
    - nel "foglio2" voglio vedere, incolonnate per categoria, le voci che ho specificato in "dati", estratte dal file di log.
    In pratica, un risultato simile a questo, per le prime due sezioni di dati separate dai trattini:
    START PROCESS mer 12/09/2012 0.11.48,66 mer 12/09/2012 0.14.08,29 ecc.
    LAVORAZIONE MOD6994 MOD6399
    VOLUME 97419 (assente)
    PAGINE IN DESTINAZIONE 73 (assente)

    E' corretta la mia interpretazione?






  • di Vecchio Frac data: 02/10/2012 11:26:09

    cit. " non ho capito perchè mi tronca le voci in elenco "
    ---> Bè sì, se leggi il codice è facile capirlo. Nella tua Sub originale "ImportaTxt" c'è una semplice istruzione:
    Ftesto2 = Replace(Replace(Replace(Ftesto, " ", ""), "E", ""), "]", "")
    che in pratica elimina spazi vuoti, lettere "E" e parentesi quadre "]" dove le trova e quindi il risultato che produce è, come dire, un po' monco :)





  • di trasp (utente non iscritto) data: 02/10/2012 14:57:41

    ciao
    grazie per le indicazioni.
    La tua re-interpretazione è corretta, se esegui gli step come li ho impostati nel foglio di lavoro avrai che. dopo l'importazione, i dati verranno "ripuliti" da pulsante "pulisci" e trasposti dall'omonimo pulsante.
    Dopo la pulizia, l'incolonnamento ha la serie di dati che ho filtrato dall'importazione, preceduta e seguita dal punto.
    Lanciando il codice originale per trasporre, (quello modificato da Harry), ottengo il risultato nel foglio2 a prescindere dalla presenza dei punti nel formato data..c'è qualcosa in quel codice che considera solo i punti delimitanti il gruppo di dati ed è la giusta chiave di volta.
    Che ne pensi?
    A presto



  • di Vecchio Frac data: 02/10/2012 15:19:10

    Allego il file da me elaborato.
    Non so se presenta il risultato voluto, da quello che ho capito io sì, ma fammi sapere.





  • di trasp (utente non iscritto) data: 02/10/2012 23:50:11

    ciao
    complimenti, proprio un buon lavoro, ordinato e preciso! Addirittura la numerazione delle righe! Grazie per il tempo che hai dedicato.
    Con il tempo vorrei dedicarmi a capire la struttura e la sintassi di questo linguaggio per ottenere autonomamente certi risultati.
    In questo forum ho trovato un buon punto di riferimento.
    A presto





  • di Vecchio Frac data: 03/10/2012 07:24:16

    Grazie, presumo che il risultato sia soddisfacente ^_^
    Allora se ritieni chiusa la discussione per cortesia spunta la casella "Spunta se risolta".
    Ti aspettiamo ancora :)





  • di trasp (utente non iscritto) data: 04/10/2012 14:31:46

    ciao
    chiudo la discussione