Modifica codice da codice



  • Modifica codice da codice
    di beppexile data: 05/07/2016 15:17:46

    Salve a tutti, ho una curiosità che piano piano sta diventando un vero e proprio quesito: esiste un modo per controllare una particolare sezione di codice alla chiusura di excel o del file al codice stesso, e, se vi è un'errore, modificarlo con un pezzo di codice standard già preimpostato?

    Mi spiego meglio;
    all'avvio del file, faccio partire la mia userform nel seguente modo:

    UserForm.Show vbModal

    quando invece devo fare dei test di debug al codice del file, per comodità e per seguire passo passo le istruzioni, modifico questa sezione di codice nel seguente modo:

    UserForm.Show 'vbModal

    ma il più delle volte, mi capita di dimenticare di rimettere il vbModal, facendo funzionare male il file all'utente.

    Avevo pensate che, se esisteva un modo di far controllare al codice stesso, in chiusura del file, solo quella parola, e se fosse 'vbModal di portarla a vbModal.

    Come fare?

    Vi ringrazio

    P.S.: Allego il file, anche se, visto che sono autodidatta, è abbastanza incasinato da riuscire a leggere bene il codice.
    a me basta anche solo un'esempio o un link.




  • di Vecchio Frac data: 05/07/2016 16:06:52

    Si può fare anche questo, anche se la ritengo una cosa piuttosto pericolosa da provare...
    si può accedere via codice al codice in effetti, attraverso una cosa simile a questa:
    ThisWorkbook.VBProject.VBComponents("Module1").CodeModule. ecc.

    Mi pare che il progetto debba essere reso attendibile (dovrei rispolverare vecchi ricordi).

    Suppongo però che ci sia un errore di fondo, di design, se sei costretto a pensare a questo escamotage.
    Io penserei a un'altra soluzione (ad esempio, un doppio click con ctrl sinistro su una label o un'immagine per chiudere e riavviare in modalità modeless). L'esempio sotto è associato a un pulsantino ma il concetto è quello.
     
    'un pulsante commuta da modale a non-modale
    Private Sub CommandButton2_Click()
        Me.Hide
        Me.Show vbModeless
    End Sub






  • di alfrimpa data: 05/07/2016 16:11:11

    Ciao Beppe

    Per essere un autodidatta veramente complimenti anche se il tuo file non sono riuscito ad aprirlo perché mi viene segnalata la mancanza di oggetti sul mio computer.

    Comunque venendo alla tua domanda voglio solo segnalarti questo link

    h t t p://www.cpearson.com/excel/vbe.aspx

    dove vengono illustrate alcune tecniche sul come intervenire (con codice) sull'editor di VBA.

    Alfredo





  • di Vecchio Frac data: 05/07/2016 16:15:02

    Ho guardato il file... io invece ti faccio i complimenti per la ascii graphic art nei diversi moduli





  • di alfrimpa data: 05/07/2016 16:17:47

    Scusa Francesco solo per curiosità ma, al di la della ASCII Graphic Art, a te il file si apre normalmente senza errori di mancanza di oggetti?

    Alfredo







  • di Vecchio Frac data: 05/07/2016 16:21:36

    Ah bè certo che no, ci sono un sacco di riferimenti a oggetti non caricati nel mio pc.
    Volevo guardare i riferimenti al progetto ma la visualizzazione è protetta da password (non è un grande ostacolo ma non ho voglia di perderci tempo ^_^).
    Comunque sì, esteticamente gradevole,m ben fatto e funzionale.
    Bravo beppexile (ma rivedi l'approccio al debug senza andare a modificare il codice da codice).





  • di alfrimpa data: 05/07/2016 16:30:21

    Cit. "Ah bè certo che no, ci sono un sacco di riferimenti a oggetti non caricati nel mio pc"

    Ah meno male cominciavo a preoccuparmi

    Beh sarebbe simpatico sapere quali sono questi fantomatici oggetti.

    Alfredo





  • di beppexile data: 05/07/2016 16:40:31

    Grazie per le lodi.... ma non credo di meritarlo: il 90% delle istruzioni le ho prese da questo forum, modificandole al mio scopo (vedi utenti come Vecchio Frac, scossa, alfrimpa, patel... ecc. e altri di cui non mi vengono i nomi in questo momento) quindi un grazie a tutto il forum.

    Il file ancora non è finito, e ci lavoro un pochino tutti i giorni per completare la sezione Scarico e le altre sezioni minori come Conteggi, Trova e Impostazioni

    Per la cronaca, la password e "p", e per accedere al VBA dalla Userform, basta un doppio clic sulla label in basso a destra con scritto "by G S" e digitare la password (p)

    I componenti aggiuntivi selezionati in Riferimenti sono:

    Visual Basic For Applications
    Microsoft Excel 15.0 Object Library
    Microsoft Form 2.0 Object Library
    Microsoft Visual Basic For Applications Extensibility 5.3
    Microsoft Common Controls-2 6.0 (SP6)
    Microsoft Common Controls 6.0 (SP6)
    Microsoft VBScript Regular Expressions 5.5
    OLE Automation

    Non chiedetemi se le ho usate tutte perchè non lo so!

    Per quanto riguarda il mio problema, grazie a tutti, prenderò spunto dal suggerimento di Vecchio Frac, buttando un'occhio anche al link di Alfredo, in quanto non voglio perderci molto tempo su questa cosa, era diventata di più uno sfizio sapere se è possibile.... poi magari mi aprite un'altro mondo da esplorare.



  • di beppexile data: 05/07/2016 16:45:39

    Nel file che ho caricato, nel modulo UF1_M_COMUNE, qualche riga in giù potrete notare che ho "dimenticato nuovamente di mettere il vbmodal..... -_-



  • di beppexile data: 05/07/2016 16:52:18

    risp a Vecchio Frac
    cit. "Suppongo però che ci sia un errore di fondo, di design, se sei costretto a pensare a questo escamotage. "

    In pratica, l'errore di fondo che mi porto dietro da parecchio è la creazione di una Userform generata automaticamente in diversi punti del file.
    Esempio, vai alla sezione Lavaggio, clicca su uno dei lotti caricati, e poi cliccate sul tastino accanto alla Textbox di inserimento dei Telai del Lotto, la userform che si generera non esiste, e viene creata sul momento. Con il vbModel attivo, inserendo i dati nella UF, e dando Ok, mi si chiude tutto, perchè non sono riuscito a capire come fare a chiudere solo quella form.
    Il codi che uso è il seguente:
     
        'GENERATORE USERFORM IMMISSIONE PESI E PEZZI TELAI ----------------------
            Sub LAVAGGIO_Genera_FormTelai()
                Dim TempForm As Object
                Dim NewLabelA As MSForms.Label
                Dim NewLabelB As MSForms.Label
                Dim NewLabelC As MSForms.Label
                Dim NewTextBoxA As MSForms.TextBox
                Dim NewTextBoxB As MSForms.TextBox
                Dim NewButton As MSForms.CommandButton
                Dim x As Integer
                Dim Line As Integer
                Dim MyScript(10) As String
                Dim y, sommapeso As Variant
                Application.ScreenUpdating = False
                    If UserForm1.LAVAGGIO_TB_Telai.Value <> "" Then
                        y = UserForm1.LAVAGGIO_TB_Telai.Value
                        Application.VBE.MainWindow.Visible = False
                        Set TempForm = ThisWorkbook.VBProject.VBComponents.Add(vbext_ct_MSForm)
                        'UserForm
                        With TempForm
                            .Properties("Caption") = "Peso Telai"
                            .Properties("Width") = 106
                            .Properties("Height") = 78 + (18 * y)
                        End With
                        'Label Telai
                        For x = 0 To (y - 1)
                            Set NewLabelA = TempForm.Designer.Controls.Add("Forms.label.1")
                            With NewLabelA
                                .Name = "FieldLabel" & x + 1
                                .Caption = "Telaio " & x + 1
                                .Top = 24 + (18 * x)
                                .Left = 6
                                .Width = 36
                                .Height = 12
                            End With
                        Next x
                        'Label intestazione Pesi
                        Set NewLabelB = TempForm.Designer.Controls.Add("Forms.label.1")
                        With NewLabelB
                            .Name = "PesoLabel"
                            .Caption = "Peso"
                            .Top = 6
                            .Left = 42
                            .Width = 54
                            .Height = 12
                            .TextAlign = fmTextAlignCenter
                            .SpecialEffect = fmSpecialEffectEtched
                        End With
                        'TextBox Pesi
                        For x = 0 To (y - 1)
                            Set NewTextBoxA = TempForm.Designer.Controls.Add("Forms.textbox.1")
                            With NewTextBoxA
                                .Name = "MyTextBoxA" & x + 1
                                .Top = 18 + (18 * x)
                                .Left = 42
                                .Width = 54
                                .Height = 18
                                .BorderStyle = fmBorderStyleNone
                                .SpecialEffect = fmSpecialEffectSunken
                                .MaxLength = 4
                            End With
                        Next x
                        'Tasto inserisci peso
                        Set NewButton = TempForm.Designer.Controls.Add("Forms.commandbutton.1")
                        With NewButton
                            .Name = "MyCommandButton"
                            .Caption = "Inserisci Peso"
                            .Top = 24 + (18 * y)
                            .Left = 6
                            .Width = 90
                            .Height = 24
                        End With
                        'Codice del tasto
                        With TempForm.CodeModule
                            Line = .CountOfLines
                            MyScript(0) = "Private Sub MyCommandButton_Click()"
                            .InsertLines Line + 1, MyScript(0)
                        End With
                        For x = 0 To (y - 1)
                            With TempForm.CodeModule
                                Line = .CountOfLines
                                MyScript(1) = "If MyTextBoxA" & x + 1 & " <> """" Then"
                                .InsertLines Line + 2, MyScript(1)
                            End With
                        Next x
                        For x = 0 To (y - 1)
                            With TempForm.CodeModule
                                Line = .CountOfLines
                                MyScript(3) = "Workbooks(FILE_LAVORO).Worksheets(""LISTE"").Range(""R" & 6 + x + 1 & """).Value = MyTextBoxA" & x + 1 & ".Value"
                                .InsertLines Line + 4, MyScript(3)
                            End With
                        Next x
                        With TempForm.CodeModule
                            Line = .CountOfLines
                            .InsertLines Line + 6, "Me.Hide"
                        End With
                        For x = 0 To (y - 1)
                            With TempForm.CodeModule
                                Line = .CountOfLines
                                MyScript(5) = "End If"
                                .InsertLines Line + 8, MyScript(5)
                            End With
                        Next x
                        With TempForm.CodeModule
                            Line = .CountOfLines
                            .InsertLines Line + 9, "End Sub"
                        End With
                        'Codice controllo inserimento dati
                        For x = 0 To (y - 1)
                            With TempForm.CodeModule
                                Line = .CountOfLines
                                MyScript(6) = "Private Sub MyTextBoxA" & x + 1 & "_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)"
                                MyScript(7) = "Const Numbers$ = ""0123456789"""
                                MyScript(8) = "If KeyAscii <> 8 Then"
                                MyScript(9) = "If InStr(Numbers, Chr(KeyAscii)) = 0 Then"
                                MyScript(10) = "KeyAscii = 0"
                                .InsertLines Line + 10, MyScript(6)
                                .InsertLines Line + 11, MyScript(7)
                                .InsertLines Line + 12, MyScript(8)
                                .InsertLines Line + 13, MyScript(9)
                                .InsertLines Line + 14, MyScript(10)
                                .InsertLines Line + 15, "End If"
                                .InsertLines Line + 16, "End If"
                                .InsertLines Line + 17, "End Sub"
                            End With
                        Next x
                        Workbooks(FILE_LAVORO).Activate
                        'Avvio UserForm
                        VBA.UserForms.Add(TempForm.Name).Show
                        'Elimino userform a fine utilizzo
                        ThisWorkbook.VBProject.VBComponents.Remove VBComponent:=TempForm
                        'faccio le somme dei dati ricavati dalla form e li scrivo su celle
                        sommapeso = WorksheetFunction.Sum(Worksheets("LISTE").Range("R7:R32").Value)
                        Worksheets("DATABASE").Range("PARK_PESO_L").Value = COMUNE_ValidaKg(sommapeso)
                        UserForm1.LAVAGGIO_TB_Peso.Value = COMUNE_ValidaKg(sommapeso)
                        Worksheets("DATABASE").Range("PARK_PEZZI_L").Value = Worksheets("DATABASE").Range("PARK_PEZZI_C").Value
                        Call LAVAGGIO_Genera_PesoMedio
                        Call LAVAGGIO_Genera_CaloPeso
                        Worksheets("LISTE").Range("R7:S32").ClearContents
                        With UserForm1
                            .LAVAGGIO_TB_Pezzi.Value = Worksheets("DATABASE").Range("PARK_PEZZI_L").Value
                            .LAVAGGIO_CmBInserisci.SetFocus
                        End With
                    Else
                        Exit Sub
                    End If
                Application.ScreenUpdating = True
                Set TempForm = Nothing
                Set NewLabelA = Nothing
                Set NewLabelB = Nothing
                Set NewLabelC = Nothing
                Set NewTextBoxA = Nothing
                Set NewTextBoxB = Nothing
                Set NewButton = Nothing
                Set y = Nothing
                Set sommapeso = Nothing
            End Sub



  • di Vecchio Frac data: 05/07/2016 17:51:23

    Allora ho guardato bene tutto il codice.
    A parte che è un lavoro enorme e certosino, in cui dai prova di abilità anche tecnica (ci sono anche le regex! ^_^), questa cosa del form che sparisce è legata al fatto che l'userform viene creato dinamicamente e in qualche modo interferisce con la normale visibilità dell'applicazione principale. Generare codice da codice in quella maniera è un suicidio per la manutenzione e il debug, ma è tutto molto ben costruito e intrigante :) (...Access qui sarebbe meglio ^_^)
    Dovresti quindi ridisegnare il flusso di pensieri: io farei una normale userform fissa, quindi non più creata al volo, che contiene una textbox, una listbox e i pulsanti "aggiungi" e "togli peso"; l'utente inserisce il valore nella textbox e lo sbatte nella listbox ad ogni "aggiungi". Quando ha finito preme "fine", l'userform si scarica e sotto ritrovi la maschera principale con i valori aggiornati.
    Certo devi rimettere mano a un bel po' di codice ma secondo me ne vale la pena, anche per eventuale manutenzione futura.





  • di beppexile data: 06/07/2016 08:39:59

    cit. "Dovresti quindi ridisegnare il flusso di pensieri: io farei una normale userform fissa, quindi non più creata al volo, che contiene una textbox, una listbox e i pulsanti "aggiungi" e "togli peso"; l'utente inserisce il valore nella textbox e lo sbatte nella listbox ad ogni "aggiungi". Quando ha finito preme "fine", l'userform si scarica e sotto ritrovi la maschera principale con i valori aggiornati. "

    Grazie del consiglio, tuttavia, il mio problema riguarda il tempo di realizzazione e il dover rimettere mani indietro al codice;
    visto che non ho ancora finito il programma e le persone dello stabilimento lo stanno già usando, volevo completare le sezioni mancanti prima di rimettere riprendere il codice da capo.
    Avrete notato che mancano quasi tutti i commenti, che vorrei inserire a fianco al codice in maniera ordinata e il più comprensibile possibile.

    Per quanto riguarda le regex, mi aveva dato un passaggio di codice gdito, che poi scossa ha perfezionato all'inverosimile, e che ho utilizzato pari pari, anche perchè non sono riuscito a capire esattamente tutte le righe che ha scritto (ho fatto solo qualche adattamento per quanto mi è stato possibile.

    A questo punto mi permetterei un'altra domando di un problema stupido, già postato parecchie settimane fa e rimasto senza risposte.

    Nel cercare di sistemare il più possibile il codice e renderlo il più leggibile, ho creato i vari moduli che vedete, dove ho trasferito il codice delle varie sezioni dalle userform (vedi Carico, Lavaggio, ecc); in questi giorni sto lavorando alla sezione finale per modo di dire, lo Scarico.

    In pratica, prima scrivo il codice sulla userform, e una volta testato, lo ripulisco, suddivido in sub, lo sposto nel modulo corrispondente alla sezione, e lo richiamo all'occorrenza con il comando Call.

    Ma nell'iniziare a trasferire il codice sto avendo qualche problema con un'istruzione che non riesco a spostare (non so se avete capito quello che intendo): faccio un'esempio con il codice.

    Andiamo sul codice userform1, riga 1022, ho la

    Private Sub SCARICO_CmbBox_Lotto_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    ...codice
    Cancel = True
    ...codice
    ...codice
    End Sub

    vorrei copiare il codice contenuto di questa sub, in una nuova sub nel modulo UF1_M4_SCARICO, è chiamare la nuova Sub AggLottoCat()

    per poi richiamarla cosi:

    Private Sub SCARICO_CmbBox_Lotto_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    Call AggLottoCat
    End Sub

    Il problema è alla voce Cancel = True
    e non riesco a risolvere, a quanto pare non la posso spostare perchè non agiste più nello stesso modo.

    Ci tengo a precisare che lasciandola nella userform, esegue perfettamente il lavoro, e questo spostamento era solo per dare una lettura migliore del codice.

    Grazie a tutti



  • di patel data: 06/07/2016 11:00:52

    non ti so aiutare, però mi sembra che ti piace proprio complicarti la vita.
    Personalmente non ritengo che lo spostamento migliori la lettura del codice anzi ...





  • di beppexile data: 06/07/2016 11:09:47

    infatti il mio è proprio un complicarmi la vita... e nel complicarmi la vita, imparo cose nuove.
    Grazie lo stesso patel