Controllo report chiuso in ciclo stampa pdf

di il
30 risposte

Controllo report chiuso in ciclo stampa pdf

Ciao a tutti,
ho da tempo implementato un sistema di invio automatico ad una serie di Aziende (variabile in base a filtri in maschera) di email con allegato, anch'esso variabile e chiaramente filtrato per la singola azienda che sta ciclando.
In sè il sistema ha sempre funzionato ma saltuariamente (2-3 volte l'anno e solo per un report un pò "pesante") succede che ad una Azienda venga inviato il PDF creato per la precedente e questo è pessimo (a parte come anomalia ma anche per problemi di privacy).
Ho monitorato la problematica e mi pare di poter affermare che il problema consista nel fatto che il report venga aperto e stampato in pdf ma non si riesca a chiudere prima del ciclo successivo per cui viene poi salvato col nome che mi aspetto (con l'ID dell'azienda giusta per quel ciclo). Questo il codice

    On Error GoTo GestERRORE
    DoCmd.OpenReport NomeReport, acViewPreview, , myFILTRO, acHidden, Ordinamento
    DoCmd.OutputTo acOutputReport, NomeReport, acFormatPDF, fullPath, False, , , acExportQualityPrint
    DoCmd.Close acReport, NomeReport
    CreaPDF = True
    Sleep (1000)
Ho pure inserito un ritardo di un secondo ma evidentemente non basta.

Ora ... e chiedo opinione in merito ... vorrei procedere diversamente e controllare, prima di queste righe, che il report sia effettivamente chiuso.
Quindi pensavo di inserire un loop in cui controllo con
CurrentProject.AllReports(NomeReport).IsLoaded
se è aperto e nel caso rimando il comando di chiusura e ri-looppo (con un terminatore dopo un tot di attesa)
Vi sembra il modo giusto?

30 Risposte

  • Re: Controllo report chiuso in ciclo stampa pdf

    muttley005 ha scritto:


    ...Quindi pensavo di inserire un loop in cui controllo con
    CurrentProject.AllReports(NomeReport).IsLoaded
    se è aperto e nel caso rimando il comando di chiusura e ri-looppo (con un terminatore dopo un tot di attesa)
    Vi sembra il modo giusto?
    Ciao Mutt ...direi che può andare.
    Crei una funzione che effettua il loop sulla collection (ovviamente dentro il loop inserisci un sano DoEvents).
    L'uscita del loop è subordinata all'effettiva chiusra del report oppure ad un Timeout (i.e. 5 secondi).
    La funzione restituisce True (report chiuso) oppure False (Timeout) da gestire come meglio credi.
  • Re: Controllo report chiuso in ciclo stampa pdf

    Avevo buttato giù qualcosa del genere, considera che questa è già una FUNCTION che si chiama CreaPDF
    
        ...
    'controllo che il report da stampare in PDF sia chiuso
        cicloControllo = 1
        While CurrentProject.AllReports(NomeReport).IsLoaded
            On Error Resume Next
            DoCmd.Close acReport, NomeReport
            On Error GoTo 0
            Sleep (1000)
            cicloControllo = cicloControllo + 1
            If cicloControllo> 5 Then GoTo GestERRORI
        Wend
    'creo
        On Error GoTo GestERRORI
        DoCmd.OpenReport NomeReport, acViewPreview, , myFILTRO, acHidden, Ordinamento
        DoCmd.OutputTo acOutputReport, NomeReport, acFormatPDF, fullPath, False, , , acExportQualityPrint
        DoCmd.Close acReport, NomeReport
        CreaPDF = True
        Sleep (1000)
       ...
    
    quindi oltre a questo tu dici di mettere 2 DoEvents dopo i 2 DoCmd.Close acReport, NomeReport giusto?
    non so mai dove buttarli sti DoEvents ... mi sarò letto e riletto 10 volte la guida del comando DoEvents ma rimane che mi è "non chiarissimo", in genere li metto quando ho a che fare con passaggio a periferiche esterne ... accetto lezioni private
  • Re: Controllo report chiuso in ciclo stampa pdf

    muttley005 ha scritto:


    quindi oltre a questo tu dici di mettere 2 DoEvents dopo i 2 DoCmd.Close acReport, NomeReport giusto?
    non so mai dove buttarli sti DoEvents ...
    Aggiungeresti qualche riga per vedere come e dove parte l'invio dell'e-mail? segue immediatamente la creazione del pdf?
  • Re: Controllo report chiuso in ciclo stampa pdf

    muttley005 ha scritto:


    Avevo buttato giù qualcosa del genere ...
    No, non era il modo che intendevo io.
    - Chiudi il report
    - chiami la funzione che verifica che il report sia chiuso e che termina appunto per report chiuso o per timeout
    - fai le altre azioni
    
    Funcion IsReportClosed() as Boolean
    Dim InTime as date
    Dim FiTime as date
    Dim bTimeOut as Boolean
    
    InTime = now
    bTimeout = false
    
    Do While not CurrentProject.AllReports(NomeReport).IsLoaded or bTimeout = false 
        FiTime = now
        bTimeOut = datediff("s",InTime,FiTime) > 5
        Doevents
    Loop
    IsReportClosed = not bTimeout
    End Funcion
    
    Per la funzione qualcosa del genere (a parte errori di sintassi) ...
  • Re: Controllo report chiuso in ciclo stampa pdf

    Ciao Phill,
    schematicamente è così, c'è una function che crea l'SQL su cui ciclare e all'interno del ciclo fa:
    • aggiorna una form popup di progresso in cui si vede il nome dell'azienda per cui sta ciclando e la percentuale di avanzamento sia testo che grafica con barra luminosa
    • richiama la function CreaPDF (quella che contiene il codice in questione) che restituisce true/false
    • se True allora richiama la function EMAIL_CDO in cui creo la mail con allegato il file PDF creato dalla CreaPDF (ed eventuali altri fissi per tutte le aziende)
    • memorizza l'esito del singolo ciclo in un registro eventi consultabile dall' utente
    • passa all'azienda successiva
    Questo in sintesi il codice (l'ho ridotto)
    
        Set rs = DBEngine(0)(0).OpenRecordset(SQL, dbReadOnly, dbSeeChanges)
        If Not rs.EOF Then
            rs.MoveLast
            DoEvents
            Call PROGRESSO_Open("INVIO EMAIL", TITOLO, "inizializzazione ...", rs.RecordCount, 500)
            rs.MoveFirst
    
    'ciclo per ogni AZIENDA
            While Not rs.EOF
                Call PROGRESSO_Aggiorna(rs.AbsolutePosition + 1, vbNullString, rs!DES_AZIENDA)
                if CreaPDF(...) Then
                	If EMAIL_CDO(...) Then 
                		...
                	Else
    ERR_CICLO:
    	               	Call REGISTRA_INVIO(...)
                	End If
               Else
               	goto ERR_CICLO
                End If
    PROSSIMO:
                DoEvents
                Sleep (500)
                rs.MoveNext
            Wend
            Call PROGRESSO_Completamento(1000)
        End If
    
  • Re: Controllo report chiuso in ciclo stampa pdf

    max.riservo ha scritto:


    muttley005 ha scritto:


    Avevo buttato giù qualcosa del genere ...
    No, non era il modo che intendevo io.
    - Chiudi il report
    - chiami la funzione che verifica che il report sia chiuso e che termina appunto per report chiuso o per timeout
    - fai le altre azioni
    
    Funcion IsReportClosed() as Boolean
    Dim InTime as date
    Dim FiTime as date
    Dim bTimeOut as Boolean
    
    InTime = now
    bTimeout = false
    
    Do While not CurrentProject.AllReports(NomeReport).IsLoaded or bTimeout = false 
        FiTime = now
        bTimeOut = datediff("s",InTime,FiTime) > 5
        Doevents
    Loop
    IsReportClosed = not bTimeout
    End Funcion
    
    Per la funzione qualcosa del genere (a parte errori di sintassi) ...
    ah ok quindi tu lo faresti subito dopo il controllo... ok... mumble mumble... in effetti il controllo ha + senso che lo faccia quando si aspetta che effettivamente sia chiuso, non all'eventuale ciclo successivo.
    Ok graaaazie
  • Re: Controllo report chiuso in ciclo stampa pdf

    Questi benedetti REPORT hanno gli EVENTI...!!!
    Lo sapete che io sono più complicato... ma mi piace di più così...
    
    Private WithEvents rpt	As Access.Report
    Private ReportIsOpen         As Boolean
    Private ReportTimeOut       As Boolean
           
     DoCmd.OpenReport NomeReport, acViewPreview, , myFILTRO, acHidden, Ordinamento
     ReportIsOpen=True
     ReportTimeOut=false
     Set rpt=Reports(NomeReport)
     Me.TimerInterval=5000
     rpt.OnClose="[Event Procedure]"
     ..... bla bla...
     
    Private Sub Form_Timer()
    On Error Resume Next
      ReportTimeOut=true
      Me.TimerInterval = 0           
    End Sub
    
    Private Sub rpt_Close()
        ReportIsOpen=False         
        Me.TimerInterval = 0
    End Sub
    
  • Re: Controllo report chiuso in ciclo stampa pdf

    @Alex ha scritto:


    Questi benedetti REPORT hanno gli EVENTI...!!!
    Lo sapete che io sono più complicato... ma mi piace di più così...
    Per la serie 'Famolo strano'

    Si tratta oggettivamente di un altro approccio ... sicuramente interessante!
  • Re: Controllo report chiuso in ciclo stampa pdf

    Si si strano è bello... ma francamente se ci si ragiona bene... perché fare un LOOP per rendere sincrone le azioni quando si può evitare usando eventi...?
    La possibilità che poi quei 5 secondi di TimeOut possano essere dipendenti dalla rete o dal peso del report e richiederne 6 o 8... esiste... io generavo report che in fase di stampa, da non confondere con l'anteprima che non impiega lo stesso tempo in quanto genera solo la 1°pagina... , che richiedeva oltre 20 secondi.
    Quindi a scanso di ERRORI che però conviene gestire, l'evento del Report è sicuramente sincrono.
  • Re: Controllo report chiuso in ciclo stampa pdf

    @Alex ha scritto:


    Si si strano è bello... ma francamente se ci si ragiona bene... perché fare un LOOP per rendere sincrone le azioni quando si può evitare usando eventi...?
    La possibilità che poi quei 5 secondi di TimeOut possano essere dipendenti dalla rete o dal peso del report e richiederne 6 o 8... esiste... io generavo report che in fase di stampa, da non confondere con l'anteprima che non impiega lo stesso tempo in quanto genera solo la 1°pagina... , che richiedeva oltre 20 secondi.
    Quindi a scanso di ERRORI che però conviene gestire, l'evento del Report è sicuramente sincrono.
    Ho provato il tuo approccio e ovviamente funziona. Buono per il futuro.
    Rimango con una perplessità ovvero perché il problema (di Mutt) dovrebbe presentarsi sulla chiusura del report.
    In questo mio codice (ridotto all'essenziale) :
    
        '
        ' Run the PDF report (bisogna aprirlo in preview con il filtro, stamparlo e poi chiuderlo !!!
        '
        iRptClosed = 0
        For i = 1 To iRptPDF
        
            sReportName = Forms(sCallerForm).mFMP.ReportName
      
            Dummy = Forms(sCallerForm).mFMP.PDFPath(clsInit.DevPath)
            If Dummy Then
                
                DoCmd.OpenReport sReportName, acViewPreview, , Forms(sCallerForm).mFMP.ItemsPrint(i).sFilter, acHidden
                
                '
                ' Prova per intercettare Evento Close del report
                '
                bRptOpened = True
                bRptTimedOut = False
                Set rpt = Reports(sReportName)
                rpt.OnClose = "[Event Procedure]"
                Me.TimerInterval = 5000
                
                sPDFName = Forms(sCallerForm).mFMP.PDFFullPath & sPDFName
                  
                ' acFormatPDF oppure "PDFFormat(*.pdf)"
                DoCmd.OutputTo acOutputReport, sReportName, acFormatPDF, sPDFName, False
            
                'Salva n° Totale di pagine report prima di chiuderlo
                Forms(sCallerForm).mFMP.ItemsPrint(i).iPages = Reports(sReportName).Pages
                DoCmd.Close acReport, sReportName, acSaveNo
                
                Me.RptPrinted = i  'Mio contatore delle stampe eseguite
                Me.RptClosed = iRptClosed 'Contatore incrementato in evento rpt_Close
                DoEvents
           Else
                MsgBox("Errore nel percorso completo dove salvare i file PDF. Stampa non possibile.")
            End If
        
        Next i
    
    Come si può vedere, all'interno di un loop apro un report, lo esporto in pdf e lo chiudo.
    Ho testato il loop con 9 report e il mio contatore e il contatore di 'Alex' si seguono perfettamente facendomi pensare che in fondo il close del report sia sincrono e quindi non riesco ad realizzare il problema di Mutt.

    Al di là di questo Alex, complimenti per l'ennesimo spunto
  • Re: Controllo report chiuso in ciclo stampa pdf

    Adesso provoco, so che con te non solo posso permettermelo ma è spesso motivo di begli stimoli tecnici.

    Se usi una Form come Classe base, da aprire in modalità anche Hidden, passi come Args il nome Report, e detro alla Form, gestisci quanto serve per aprire, stampare ed il Timer... come esposto nel mio esempio...?

    Ora aggiungiamo un pezzo... dobbiamo stampare N reports, in un ciclo... quindi proviamo nel ciclo, ed aprire in MultiIstanza le form... ognuna gestirà stampa e tempi... in modo autonomo ed indipendente...?
    Non credo sia proprio assimilabile al MultiThread, ma potrebbe essere una discreta ottimizzazione del processo.

    Questa cosa fino quì è facile da provare..., unica cosa da aggiungere per gli effetti speciali, è se la fase di stampa del Report, può generare Eventi da sfruttare per l'eventuale "PROGRESSIONE"....

    Giochiamoci pure.
  • Re: Controllo report chiuso in ciclo stampa pdf

    @Alex ha scritto:


    Se usi una Form come Classe base, da aprire in modalità anche Hidden, passi come Args il nome Report, e detro alla Form, gestisci quanto serve per aprire, stampare ed il Timer... come esposto nel mio esempio...?
    Direi che questo approccio dovrebbe rendere asincrona l'elaborazione del report rispetto al form chiamante, rendendo più usabile il tuo approccio.

    @Alex ha scritto:


    Ora aggiungiamo un pezzo... dobbiamo stampare N reports, in un ciclo... quindi proviamo nel ciclo, ed aprire in MultiIstanza le form... ognuna gestirà stampa e tempi... in modo autonomo ed indipendente...?
    Non credo sia proprio assimilabile al MultiThread, ma potrebbe essere una discreta ottimizzazione del processo.
    E questo dovrebbe permettere la 'parallellizzazione' dei processi di stampa. Sicuramente molto interessante : dovrei però capire i limiti oltre i quali è meglio non andare. Nel mio caso non è infrequente generare anche 200 reports di verifica di calibrazione di strumenti (come generazione di singoli pdf - sebbene siano solo di 2-4 pagine ciascuno), temo di saturare le risorse di sistema. Utilizzare questo approccio per stampare i report (sulla stessa stampante) invece non mi sembra abbia un grande senso (il collo di bottiglia dovrebbe/potrebbe essere la stampante).

    @Alex ha scritto:


    Questa cosa fino quì è facile da provare..., unica cosa da aggiungere per gli effetti speciali, è se la fase di stampa del Report, può generare Eventi da sfruttare per l'eventuale "PROGRESSIONE"....
    Questo aspetto sarebbe da approfondire anche in relazione a quali info visualizzare ... è comunque un ottimo spunto da approfondire.

    @Alex ha scritto:


    Adesso provoco, so che con te non solo posso permettermelo ma è spesso motivo di begli stimoli tecnici.
    Sono gli stimoli che mi (ci) permettono di accrescere la conoscenza ...
  • Re: Controllo report chiuso in ciclo stampa pdf

    Alex ... non ti si può dare un dito che ti prendi il braccio
    Grazie dello spunto comunque lo terrò in considerazione

    Per rispondere a Max del fatto che sia sincrona la chiusura e del perchè accada ... sinceramente non so che dire... nemmeno io lo pensavo possibile ma evidentemente qualcosa si "sfasa".
    Almeno io l'ho interpretato così...
    allora visto che ci siamo vi spiego meglio perchè ho pensato così.
    la sequenza di aziende era A, B, C ... Z (per facilità)
    fino alla M tutto a posto, poi la mail di N l'ha mandata con l'intestazione giusta ("spett.le N, ...") e nome di allegato giusto (N.pdf) ma il contenuto di N.pdf era riferito al report filtrato per O, in più la mail ad O non l'ha mandata ...
    aiuto... ora che rileggo quello che sto scrivendo in effetti la spiegazione che mi sono dato è sbagliata! sembra che sia andato avanti! non che abbia mandato il precedente file ...
    Allora...
    lui è nel ciclo ed arriva a questa
    
    Ok = CreaPDF("ID_AZIENDA=" & rs!ID_AZIENDA, NomeReport, Percorso & "\" & rs!ID_AZIENDA & ".pdf", False, True, Ordinamento)
    
    e dentro la CreaPDF c'è questo
    
    Public Function CreaPDF(myFILTRO As String, NomeReport As String, fullPath As String, _
        Optional NotificaErrore As Boolean = False, Optional NotificaSovrascrive As Boolean = True, Optional Ordinamento As String) As Boolean
    ...
        DoCmd.OpenReport NomeReport, acViewPreview, , myFILTRO, acHidden, Ordinamento
        DoCmd.OutputTo acOutputReport, NomeReport, acFormatPDF, fullPath, False, , , acExportQualityPrint
        DoCmd.Close acReport, NomeReport, acSaveNo
        CreaPDF = True
    ...
    
  • Re: Controllo report chiuso in ciclo stampa pdf

    max.riservo ha scritto:


    ....
    Sono gli stimoli che mi (ci) permettono di accrescere la conoscenza ...
    Assolutamente... tempo permettendo butto giù un giochetto con una Collection per la multiistanza di Form e la stampa MultiReport poi vediamo dove si arriva.

    Condivido appena ho qualche cosa di utile.

    P.S. un problema su cui riflettere è l'apertura in MULTIISTANZA dei Report... si faccia riferimento a Report basati su Tabella da aprire con la WHERE CONDITION... sicuramente da ragionare...
Devi accedere o registrarti per scrivere nel forum
30 risposte