Errore call macro



  • Errore call macro
    di Carletto (utente non iscritto) data: 06/02/2015 09:19:09

    Ciao a tutti,
    ho scritto il seguente codice per inviare dei range predefiniti di celle a secondo del destinatario presente nella colonna A e del CC nella colonna C.
    Se provo a chiamarla con le ultime righe di codice (che si trovano in un modulo a parte), mi restituisce l'errore "argomento non facoltativo".
    Come posso risolvere? Succede la stessa cosa se utilizzo la funzione Call.
    Grazie a tutti in anticipo!
     
    Sub Inviamail(mail As String, file As String, ccmail As String, j As Integer)
    
        Dim rng As Range
        Dim OutApp As Object
        Dim OutMail As Object
        Dim bodymail As String
        Dim c As Integer
        Dim i As Integer
        Dim mail As String
        Dim ccmail As String
        Dim file As String
        Dim percorso As String
        Range("D:D").ClearContents
        percorso = Cells(1, 6)
        If Right$(percorso, 1) <> "" Then percorso = percorso & ""
     
            'Set rng = Sheets("YourSheet").Range("D4:D12").SpecialCells(xlCellTypeVisible)
            Set OutApp = CreateObject("Outlook.Application")
            OutApp.Session.Logon
            Set OutMail = OutApp.CreateItem(0)
            firma = "C:UsersITFontanAn1AppDataRoamingMicrosoftSignaturesAndrea.Htm"
        If Dir(firma) <> "" Then
            Sign = GetBoiler(firma)
        Else
            Sign = ""
        End If
     
              
            j = 2
            On Error Resume Next
            With OutMail
            While Trim(Cells(j, 1)) <> ""
            conta = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(j, 1))
            Set rng = Sheets("Foglio1").Range("Cells(j, 2), Cells (j + conta - 1, 3)").SpecialCells(xlCellTypeVisible)
                .From = "carletto@dominio.com"
                .To = Cells(j, 1)
                .CC = Trim(Cells(j, 3))
                .Subject = Cells(12, 6)
                file = percorso + Cells(j, 2)
                .BodyFormat = olFormatHTML
                bodymail = ""
                bodymail = bodymail + Cells(13, 6) + "
    " bodymail = bodymail + "
    " + RangetoHTML(rng) + "
    " .HTMLbody = bodymail + "


    " + Sign .Attachments.Add file .Send j = j + conta Wend End With On Error GoTo errore Cells(i, 4) = "INVIATA !" With Application .EnableEvents = True .ScreenUpdating = True End With Set OutMail = Nothing Set OutApp = Nothing Exit Sub errore: Cells(i, 4) = "ERRORE !" End Sub --------------------- Sub Telaio2_Click() Inviamail End Sub



  • di lepat (utente non iscritto) data: 06/02/2015 11:39:16

    La prima sub è in un modulo standard ? o in un foglio ?
    Prova a mettere tutto nello stesso modulo, se non risolvi allega un file di esempio



  • di lepat (utente non iscritto) data: 06/02/2015 11:41:24

    non avevo letto attentamente, la prima sub hiede dei parametri per funzionare, non puoi chiamarla senza darglieli.
     
    Sub Inviamail(mail As String, file As String, ccmail As String, j As Integer)



  • di Vecchio Frac data: 06/02/2015 11:42:42

    Ma guarda la firma della sub principale:
    Sub Inviamail(mail As String, file As String, ccmail As String, j As Integer)
    e adesso guarda come la richiami:
    Sub Telaio2_Click()
    Inviamail
    End Sub


    L'errore che ricevi è davvero autoesplicativo. Significa che non richiami la sub con il necessario passaggio di parametri.
    Riflettici un po' su e se non ne vieni a capo (magari ho accennato a cose che non hai mai incontrato) riscrivi, che te lo spiego meglio.





  • di Carletto (utente non iscritto) data: 06/02/2015 15:21:23

    @ lepat: la sub è in un modulo.
    @ Vecchio frac: grazie. Riesco a comprendere il problema ma non come risolverlo.
    Ho provato ad inserire i parametri nel richiamo nei modi descritti nei codici qui sotto.
    Nel primo caso l'errore che restituisce è "previsto separatore di elenco oppure )"
    Nel secondo caso l'errore è "previsto: ="
    Dove sto sbagliando?
    Grazie ancora!
     
    Inviamail(mail as String, file as String, ccmail as String, j as Integer)
    ----------------------------------------
    Inviamail(mail, file, ccmail, j)



  • di lepat (utente non iscritto) data: 06/02/2015 15:35:54

    ora la sintassi è corretta, ma nelle variabili mail, file, ccmail, j ci hai messo i contenuti delle rispettive celle ?
    Forse è meglio che tu alleghi il file



  • di Vecchio Frac data: 06/02/2015 15:37:15

    Prima deve esserti chiaro che:
    Sub Inviamail(mail As String, file As String, ccmail As String, j As Integer)
    è una subroutine che accetta dei parametri (cioè dei valori passati attraverso delle variabili) e la cui "firma" prevede in ingresso tre parametri di tipo testo e uno di tipo numerico.

    Una sub (abbreviazione per subroutine o sottoprocedura) può essere invocata in due modi:
    - semplicemente per nome: Inviamail
    - con la parola riservata Call: Call Inviamail

    Una sub con parametri deve essere invocata facendo seguire al nome della sub tutti i parametri richiesti, nell'ordine in cui compaiono nella firma, o anche non nello stesso ordine ma in tal caso deve essere specificato il nome del parametro cui si riferiscono. Ci sono sempre due modi per invocare la sub parametrica ma con un'importante differenza:
    - la chiamata per nome non richiede le parentesi: Inviamail param1, param2, param3, param4
    - la chiamata con Call richiede le parentesi tra i parametri: Call Inviamail(param1, param2, param3, param4)

    Ci sono poi Sub che vengono generate automaticamente per rispondere a determinati eventi, e le cui firme sono quindi prefissate.
    Nel tuo caso la sub Telaio2_Click() corrisponde alla gestione dell'evento Click (sinistro) del mouse su un pulsante chiamato Telaio2.
    Questa sub invoca "Inviamail" ma deve farlo passandole dei parametri nell'ordine e del tipo che la firma di "Inviamail" si aspetta:
    Sub Telaio2_Click()
    Inviamail "primo parametro stringa (mail)", "secondo parametro stringa (file)", "terzo parametro stringa (ccmail)", 99

    Quando questo codice viene eseguito, la sub Inviamail riceve i parametri attesi e li associa alle variabili locali mail, file, ccmail e j.
    Dovrà quindi trattare di conseguenza queste variabili nel corpo della sua esecuzione (e non devono essere ulteriormente ridimensionate: file per esempio è dimensionata nuovamente e provocherà errore).

    Ragionaci su un po' e poi ci risentiamo :)






  • di Carletto (utente non iscritto) data: 06/02/2015 18:03:15

    Caro Vecchio Frac, grazie per la tua spiegazione che mi ha fatto risolvere il mio problema e fatto capire qualcosa di più!
    Ora però ne ho un altro...la funzione che devo chiamare serve a mandare delle mail con dei range di celle inseriti nel testo del messaggio.
    Oltre al codice allego un esempio, con la descrizione del risultato sperato.
    Il codice mi sembrava corretto, ma ovviamente così non è..
    Posso approfittare ancora una volta del tuo aiuto?
    Grazie davvero infinite!
     
    Sub Inviamail(mail As String, file As String, ccmail As String, j As Integer, conta As Integer)
    
        Dim rng As Range
        Dim OutApp As Object
        Dim OutMail As Object
        Dim bodymail As String
        Dim c As Integer
        Dim i As Integer
        Dim percorso As String
        Range("D:D").ClearContents
        percorso = Cells(1, 6)
        If Right$(percorso, 1) <> "" Then percorso = percorso & ""
     
            'Set rng = Sheets("YourSheet").Range("D4:D12").SpecialCells(xlCellTypeVisible)
            Set OutApp = CreateObject("Outlook.Application")
            OutApp.Session.Logon
            Set OutMail = OutApp.CreateItem(0)
            firma = "firma"
        If Dir(firma) <> "" Then
            Sign = GetBoiler(firma)
        Else
            Sign = ""
        End If
     
              
            j = 2
            On Error Resume Next
            With OutMail
            While Trim(Cells(j, 1)) <> ""
            conta = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(j, 1))
            Set rng = Range("Cells(j, 2), Cells(j + conta - 1, 3)").Select
                .From = "mionome@dominio.com"
                .To = Cells(j, 1)
                .CC = Trim(Cells(j, 3))
                .Subject = Cells(12, 6)
                file = percorso + Cells(j, 2)
                .BodyFormat = olFormatHTML
                bodymail = ""
                bodymail = bodymail + Cells(13, 6) + "
    " bodymail = bodymail + "
    " + RangetoHTML(rng) + "
    " .HTMLbody = bodymail + "


    " + Sign .Attachments.Add file .Send j = j + conta Wend End With On Error GoTo errore Cells(j, 4) = "INVIATA !" With Application .EnableEvents = True .ScreenUpdating = True End With Set OutMail = Nothing Set OutApp = Nothing Exit Sub errore: Cells(j, 4) = "ERRORE !" End Sub



  • di Vecchio Frac data: 06/02/2015 21:08:00

    Fermiamoci ancora un attimo.

    Quando richiami InviaMail, se non usi Call devi scrivere la chiamata così:
    Sub Telaio2_Click()
    Inviamail mail, file, ccmail, j, conta
    End Sub

    e cioè *senza* le parentesi intorno ai parametri altrimenti li converti *tutti* in stringa.

    Inoltre, da dove li peschi i valori dei parametri mail, file, ecc., quando clicchi sul pulsante Invia?
    Cioè, immagina di essere il pulsante: vieni premuto e sai che devi eseguire "Inviamail" alla quale devi passare una serie di valori (mail, file, ecc.). Ma tu sei solo un povero pulsante isolato, senza nessun'altra informazione nella tua valigetta... la valigetta è vuota, che cosa mai potrai passare alla sub da chiamare? niente... passerai tutta una serie di valori default (ossia: strighe vuote e valori zero).
    Quindi la sub Inviamail verrà sì eseguita, ma senza valori nei parametri... che quindi è come se non esistessero nemmeno... codice buttato nel bidone del residuo ^_^
    Perciò: mail cosa dovrebbe essere? e file? e conta, che prima non c'era? a cosa corrispondono? come potrebbe fare il pulsante a recuperare questi valori da passare alla sub da eseguire?

    Dici che il codice ti sembra corretto ma così non è... perchè? che errori o che anomalie hai riscontrato?

    Fai un passettino indietro e scrivi *in italiano* per me, quindi per un estraneo che non sa niente del tuo progetto, il risultato che devi ottenere (es. voglio che la macro quando invocata peschi il nome dalla cella A2, alleghi il file il cui nome è in cella B2, e il cui percorso è questo qui, aggiunga un destinatario cc se il campo non è vuoto, ecc.). Quando avrai steso questi passi da eseguire (il che si chiama "algoritmo": ricerca della soluzione) non solo io sarò in grado di aiutarti nel caso concreto, ma tu stesso ti renderai conto che raggiungere la soluzione sarà solo nua banale questione di applicare la corretta sintassi del linguaggio. Per esempio (visto che ho ben capito cosa vuoi ottenere guardando il file ^_^), vorrai spedire una mail a più destinatari con più allegati? o una mail per ogni riga di destinatari? Il codice cambierà di conseguenza!

    p.s. io qui a casa non posso testarlo appieno, non ho installato Outlook, quindi vado a memoria, il resto del codice mi sembra ok anche se quell'istruzione firma = "firma" e if Dir(firma) <> "" ... bè è un non senso, lo vedi? ^_^





  • di Carletto (utente non iscritto) data: 08/02/2015 20:07:19

    Vecchio Frac, ti ringrazio ancora una volta per il tuo aiuto, e soprattutto per la tua pazienza nello spiegarmi tutte queste cose. Allego ancora un file ("invia più mail"), in cui ho descritto il mio problema, la soluzione che desidero e il modo in cui ho ragionato per ottenerlo. Contiene anche l'ultimo codice che ho scritto prima, a questo punto mi hai fatto giustamente venire il dubbio che si tratti di un errore nel mio modo di richiamare la macro senza specificare i diversi riferimenti.. Grazie di nuovo!



  • di Vecchio Frac data: 08/02/2015 20:21:25

    Per cortesia Carletto riallega il tuo file ma NON mettere la "ù" nel nome del file. Lascia la "u" semplice, che si capisce lo stesso. Il server ha problemi a elaborare questo tipo di allegati (con Unicode nel nome intendo).





  • di Vecchio Frac data: 08/02/2015 20:25:23

    Non che non si possa scaricare... io l'ho fatto... ma bisogna cercarsi la codifica ASCII della ù accentata (%F9) e inserirla direttamente nel link del browser: non tutti hanno tempo o voglia di farlo.





  • di Vecchio Frac data: 08/02/2015 20:27:38

    Come dicevo l'altra sera, a casa non posso testare il codice (non ho Outlook), ma domani n ufficio ci darò un'occhiata volentieri.
    Intanto ti posso dire che nel tuo codice manca ancora Option Explicit... ricordati di inserirlo sempre nei tuoi moduli :)





  • di Vecchio Frac data: 08/02/2015 20:33:44

    Ma Carletto, la tua sub Telaio2_Click(), dove richiami InviaMail con vari parametri, è ancora desolatamente vuota e io invece mi aspettavo che l'avresti riempita, dopo la spiegazione della valigetta vuota e tutto il resto ^_^
    E' evidente che non sono riuscito ad essere chiaro abbastanza.
    Forse stasera riesco a scriverti qualche altra riga di spiegazione decente, altrimenti ci risentiamo domani.
    Comunque il ragionamento da fare appena premuto il pulsante chiamato "Telaio2" è:
    - per ogni riga della tabella,
    costruisco i parametri da passare a "inviamail"
    invoco "inviamail" con i parametri giusti
    e passo alla riga successiva.





  • di Carletto (utente non iscritto) data: 08/02/2015 20:58:33

    Ciao Vecchio Frac, anche io a casa non ho outlook e non ho lavorato sul file nel weekend, domani a mente lucida mi ributto a riempire il povero telaio :) nel caso non riuscissi, so che posso contare sul tuo aiuto! :)
    Grazie veramente un sacco!



  • di Carletto (utente non iscritto) data: 09/02/2015 10:29:00

    Buondì Vecchio Frac, ho fatto delle prove di modifica al file dell'altra volta.
    Con queste modifiche riscontro un nuovo errore: "Metodo 'Range' dell'oggetto'_Global non riuscito".
    Con il debug mi seleziona la riga Set rng = Range("Cells(j, 4), Cells(j + conta - 1, 5)"), del modulo 2 contentente la sub del telaio.
    Riallego un file (senza accento sulla "u"), dove c'è il codice modificato da me?
    Puoi aiutarmi?
    Grazie mille!



  • di Carletto (utente non iscritto) data: 09/02/2015 10:31:25

    Scusa, non mi fa caricare l'allegato... copio tutto il codice qui sotto...grazie ancora!
     
    Function RangetoHTML(rng As Range)
        Dim fso As Object
        Dim ts As Object
        Dim TempFile As String
        Dim TempWB As Workbook
    
        TempFile = Environ$("temp") & "" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
    
        rng.Copy
        Set TempWB = Workbooks.Add(1)
        With TempWB.Sheets(1)
            .Cells(1).PasteSpecial Paste:=8
            .Cells(1).PasteSpecial xlPasteValues, , False, False
            .Cells(1).PasteSpecial xlPasteFormats, , False, False
            .Cells(1).Select
            Application.CutCopyMode = False
            On Error Resume Next
            .DrawingObjects.Visible = True
            .DrawingObjects.Delete
            On Error GoTo 0
        End With
    
        'Publish the sheet to a htm file
        With TempWB.PublishObjects.Add( _
             SourceType:=xlSourceRange, _
             Filename:=TempFile, _
             Sheet:=TempWB.Sheets(1).Name, _
             Source:=TempWB.Sheets(1).UsedRange.Address, _
             HtmlType:=xlHtmlStatic)
            .Publish (True)
        End With
    
        'Read all data from the htm file into RangetoHTML
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
        RangetoHTML = ts.readall
        ts.Close
        RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
                              "align=left x:publishsource=")
    
        'Close TempWB
        TempWB.Close savechanges:=False
    
        'Delete the htm file we used in this function
        Kill TempFile
    
        Set ts = Nothing
        Set fso = Nothing
        Set TempWB = Nothing
    End Function
    
    
    Function GetBoiler(ByVal sFile As String) As String
        Dim fso As Object
        Dim ts As Object
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
        GetBoiler = ts.readall
        ts.Close
    End Function
    
    Sub Inviamail(mail As String, file As String, ccmail As String, j As Integer, conta As Integer, rng As Range)
    
    
        Dim OutApp As Object
        Dim OutMail As Object
        Dim bodymail As String
    
    
     
            'Set rng = Sheets("YourSheet").Range("D4:D12").SpecialCells(xlCellTypeVisible)
            Set OutApp = CreateObject("Outlook.Application")
            OutApp.Session.Logon
            Set OutMail = OutApp.CreateItem(0)
            firma = "C:UsersCarlettoAppDataRoamingMicrosoftSignaturesCarletto.Htm"
        If Dir(firma) <> "" Then
            Sign = GetBoiler(firma)
        Else
            Sign = ""
        End If
     
            On Error Resume Next
            With OutMail
            
                .From = "carletto@dominio.com"
                .To = mail
                .cc = Trim(ccmail)
                .Subject = Cells(12, 6)
                .BodyFormat = olFormatHTML
                bodymail = ""
                bodymail = bodymail + Cells(13, 6) + "
    " bodymail = bodymail + "
    " + RangetoHTML(rng) + "
    " .HTMLbody = bodymail + "


    " + Sign .Attachments.Add file .Send End With On Error GoTo errore Cells(j, 4) = "INVIATA !" With Application .EnableEvents = True .ScreenUpdating = True End With Set OutMail = Nothing Set OutApp = Nothing Exit Sub errore: Cells(j, 4) = "ERRORE !" End Sub ----------------------- Sub Telaio2_Click() Dim mail As String Dim file As String Dim ccmail As String Dim j As Integer Dim conta As Integer Dim percorso As String Dim rng As Range Range("D:D").ClearContents percorso = Cells(1, 6) If Right$(percorso, 1) <> "" Then percorso = percorso & "" j = 2 While Trim(Cells(j, 1)) <> "" conta = Application.WorksheetFunction.CountIf(Range("A:A"), Cells(j, 1)) Set rng = Range("Cells(j, 4), Cells(j + conta - 1, 5)") mail = Cells(j, 1) file = percorso + Cells(j, 2) ccmail = Cells(j, 3) Inviamail mail, file, ccmail, j, conta, rng j = j + conta Wend End Sub



  • di Vecchio Frac data: 09/02/2015 10:31:26

    Sì riallega il file senza lettere accentate così lo commentiamo insieme tra una telefonata di lavoro e l'altra :)





  • di Vecchio Frac data: 09/02/2015 10:32:18

    Hai provato a zippare il file e chiamarlo ad esempio "prova.zip" per allegarlo?





  • di Carletto (utente non iscritto) data: 09/02/2015 10:39:19

    File zippato allegato



  • di Vecchio Frac data: 09/02/2015 11:18:16

    Set rng = Range("Cells(j, 4), Cells(j + conta - 1, 5)")
    E' sbagliata la sintassi cioè il modo di scrivere l'istruzione.
    Dopo Range puoi avere:
    - una stringa letterale (cioè qualcosa racchiuso tra virgolette) che indica un indirizzo di riga e colonna, ad esempio Range("A4"); oppure
    - un riferimento indicato da due oggetti Cells a loro volta costituiti da due parametri (riga e colonna, la quale può essere un numero o una stringa che identifica una colonna), e che rappresenta un range costituito da più celle; ad esempio per indicare Range("A1:A10") si può scrivere in forma equivalente Range(Cells(1, 1), Cells(10, "A")).
    La tua riga quindi deve essere scritta *senza* le virgolette:
    Set rng = Range(Cells(j, 4), Cells(j + conta - 1, 5))

    - Dimentichi ancora Option Explicit in testa ai moduli :)
    - Però vedo che hai costruito bene la sub di Telaio2 (nome orribile che non dice niente sul funzionamento).
    - La variabile "conta" non ha senso ricalcolarla ogni volta dentro il While, visto che è fissa e non cambia la puoi passare e basta quando invochi Inviamail.
    - Il ragionamento che hai seguito mi pare corretto.
    - Sulla costruzione del modello invece:
    da dove arrivano i dati? da un inserimento manuale o mediante altro meccanismo? non puoi evitare di scrivere su righe diverse destinatari uguali e allegati uguali, magari mettendo in un'unica cella datoX e datoY separati da virgola?





  • di Vecchio Frac data: 09/02/2015 11:27:25

    percorso = Cells(1, 6)
    Questa istruzione è sbagliata, ma l'errore qui è di logica e non di sintassi 8cioè la riga è giusta ma punta a una clela diversa da quella che deve per il corretto funzionamento).
    Se la riscrivi in notazione stringa letterale ti accorgi subito del perchè è logicamente sbagliata:
    percorso = Range("F1")





  • di Vecchio Frac data: 09/02/2015 11:28:19

    Errori di battitura! Tastiera nuova e troppo morbida ^_^
    ---> "(cioè la riga è giusta ma punta a una cella diversa da quella che deve per il corretto funzionamento)."





  • di Vecchio Frac data: 09/02/2015 11:31:15

    Non tenere in considerazione l'osservazione precedente sulla variabile "conta"... adesso ho capito cosa sta facendo ^_^





  • di Carletto (utente non iscritto) data: 09/02/2015 11:56:22

    Caro Vecchio Frac, ne sai una più del diavolo! ;) grazie al tuo aiuto ho risolto il mio problema, riesco ad inviare più mail con un'unica macro inserendo il range che voglio nel corpo del messaggio, con l'allegato desiderato.
    Purtroppo il file su cui devo applicarlo ha circa 2000 record, e con il nome del destinatario ripetuto più volte per record diversi.
    Quindi volevo evitare di perdere tempo a dividere manualmente i record di ogni destinatario e far partire più macro: con questo sistema mi basta ordinare alfabeticamente i destinatari e far partire la macro.
    Ultima cosa che ti chiedo: è possibile mantenere l'intestazione di colonna nel range che inserisco nel corpo del messaggio?
    Grazie ancora una volta per tutti i tuoi consigli e per il tuo preziosissimo aiuto!



  • di Vecchio Frac data: 09/02/2015 12:00:09

    Ho capito il problema. A questo punto aspetti un secondo in più e tutto si risolve ;)

    Per le intestazioni di colonna basta che fai questa piccolissima modifica nella sub di telaio2_click():
    Inviamail mail, file, ccmail, j, conta, Union(Range("D1:E1"), rng)
    Peccato però che l'istruzione:
    Range("D:D").ClearContents
    ti elimina l'intestazione di "Dati X"... come puoi risolvere?





  • di Carletto (utente non iscritto) data: 09/02/2015 12:04:48

    Colto il suggerimento ;) sei davvero un grande, grazie infinite per tutto il tuo aiuto e per la tua pazienza, non solo hai risolto i miei problemi ma mi hai fatto capire passo per passo cosa sbagliavo! GRAZIE!!!