Questo e il link per scaricare il mio progetto ridotto :
https://app.box.com/s/fxplzlhp4x5auwaiusqzksu5kpit2ekjProvalo e vedrai che : forse la prima volta che lo provi ti funziona a meraviglia premendo il Tasto (Viola)
Poi dovresti premere il tasto (Celeste) per azzerare i Campi
E poi Ripetere l'operazione con quello (Viola) o (Verde) Per vederne gli effetti finali
Che è poi quello che capita a me !
Ho immaginato che volessi sottintendere che non tutto fila liscio... E in effetti qualcosa spesso va male...
I miei commenti:a)On Error Resume Next va usato con discrezione, perche' rischiamo di fargli nascondere situazioni di errore che non dovrebbero esserci (altre volte invece l'errore va messo in conto).
Quindi dal tuo codice della Sub Previsioni_Tabella ho eliminato il primo, subito in testa, riposizionandolo dove la macro comincia a leggere il contenuto della pagina web.
b)Ovviamente questo non avrebbe utilita' se la sessione IE restasse invisibile; per cui l'ho impostata "visibile" (.Visible = True).
Così facendo si vede che spesse volte subito dopo che una sessione IE viene terminata, per parecchi secondi non se ne riesce ad avviarne una nuova e viene aperto un errore su Set IE = CreateObject("internetExplorer.Application")
Premendo "Continua" su questo errore, l'errore puo' ripresentarsi oppure (alla fine) la sessione viene aperta e la macro continua.
c)Ho poi visto che molto spesso IE segnala "Impossibile raggiungere la pagina / Verifica che l'indirizzo Web
https://www.worldweatheronline.com sia corretto". Ho pertanto inserito nel codice un "Refresh"della navigazione e la ripetizione del ciclo (If InStr(1, "ZcZc" & IE.document.getelementsbytagname Etc Etc).
d)Inoltre ho visto che qualche volta CollB e' incompleta anche se l'attesa del "IE.Document" e' completata correttamente; d'altra parte questa tabella viene creata al momento via jscript, quindi puo' accadere. Ho pertanto inserito un ciclo che aspetta fino a 6 secondi (For JJ = 1 To 20 /Next JJ)
e)Ho anche inserito una serie di messaggi di Debug, che vengono visualizzati nella "finestra Immediata" del vba; per visualizzare questi messaggi, apri la finestra "Immediata", ogni blocco comincia con ">>>>" (dal vba: premi Contr-g; oppure Menu /Visualizza /Finestra Immediata). Possono essere utili (soprattutto a me) per ricostruire gli eventi.
f)Infine ho usato la funzione Sleep per gestire i timing che ritengo sensibili, previa la sua dichiarazione in testa al modulo (#If VBA7 Then /#Else /#End If)
Il nuovo codice della Sub Previsioni_Tabella con tutte queste modifiche:
- Codice: Seleziona tutto
#If VBA7 Then '!!! ON TOP OF THE VBA MODULE !!!!
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
#Else
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Sub Previsioni_Tabella()
'On Error Resume Next
Dim CollA As Object, CollB As Object
Dim cSrc As String, cIW As Single, myStart As Single
Dim IE As Object, SecFl As Boolean
myStart = Timer
Debug.Print ">>>>", Timer
X = Foglio1.Range("G1").Value & ""
Y = Foglio1.Range("I1").Value & ""
'
myURL = "https://www.worldweatheronline.com/" & X & "/" & Y & "" & "/it.aspx"
Set IE = CreateObject("internetExplorer.Application")
Debug.Print TypeName(IE)
'
With IE
Debug.Print myURL, Format(Timer - myStart, "0.00")
.Navigate myURL
'' .Visible = False 'meglio TRUE
.Visible = True
End With
ReDO:
With IE
Sleep 500
Do While .Busy: DoEvents: Loop
Do While .ReadyState <> 4: DoEvents: Loop
End With
Do
DoEvents
If Timer > myStart + 2 Or Timer < myStart Then Exit Do
Loop
'
'Importa la tabella "10 Day Weather Forecast"
On Error Resume Next
Debug.Print "Start Import", Format(Timer - myStart, "0.00")
Debug.Print Left(IE.document.getelementsbytagname("body")(0).innertext, 150)
If InStr(1, "ZcZc" & IE.document.getelementsbytagname("body")(0).innertext, "Impossibile raggiungere", vbTextCompare) > 0 And SecFl = False Then
SecFl = True
Else
SecFl = False
End If
If SecFl Then
Debug.Print "Second Chance", Format(Timer - myStart, "0.00")
IE.Refresh
Sleep 200
GoTo ReDO
End If
rbase = "A18" '<<< Dove scrivere
Set CollA = IE.document.GETelementbyid("lazy_load_14dayfx") 'id della tabella
Call RangeClear(Range(rbase).Resize(12, 9)) 'Cancella contenuto della tabella
'
For JJ = 1 To 20
Set CollB = CollA.getelementsbytagname("div")
ccnt = 99: j = 0
Debug.Print "AA", TypeName(CollB), CollB.Length, Format(Timer - myStart, "0.00"), JJ
If CollB.Length > 0 Then Exit For
Sleep 300
Next JJ
For I = 0 To CollB.Length - 1
ccl = CollB(I).className
If InStr(1, "ZcZc" & ccl, "w-100", vbTextCompare) > 0 Or ccnt < 8 Then
If InStr(1, "ZcZc" & ccl, "w-100", vbTextCompare) > 0 Then ccnt = 0: j = j + 1
If InStr(1, "ZcZc" & ccl, "w-100", vbTextCompare) = 0 Then
Range(rbase).Offset(j - 1, ccnt).Value = CollB(I).innertext
cSrc = "": cIW = 0
cSrc = CollB(I).getelementsbytagname("img")(0).getAttribute("src")
If cSrc <> "" Then
Debug.Print "BB", cSrc
Call GetShapeFromWeb("https:" & cSrc, Range(rbase).Offset(j - 1, ccnt))
cIW = ActiveSheet.Shapes(ActiveSheet.Shapes.Count).Width
With Range(rbase).Offset(j - 1, ccnt)
.ColumnWidth = 10
.ColumnWidth = cIW / .Width * 10
.EntireRow.RowHeight = cIW
End With
End If
ccnt = ccnt + 1
End If
End If
Next I
Debug.Print "CC", "I=" & I, "cCnt=" & ccnt, Format(Timer - myStart, "0.00")
'Chiusura IE
IE.Quit
Set IE = Nothing
On Error GoTo 0
'Call Weather_Immagini
End
End Sub
Il file così modificato e' scaricabile qui:
https://www.dropbox.com/s/tbv2ldx22uqzs ... .xlsm?dl=0Quanto alle tue domande:
1) A cosa Servono questi due parametri :
- Codice: Seleziona tutto
If InStr(1, "ZcZc" & ccl, "w-100", vbTextCompare) > 0 Or ccnt < 5 Then
Cioè da quello che ho capito io : Tu prelevi da quella griglia di dati solo fino alla (5) Riga
Pertanto se io volessi prendere anche le ultime tre ; Dovrei portare il tuo Cinque a (8)
Giusto ?
2 ) Idem per il parametro della Cancellazione che da :
- Codice: Seleziona tutto
Call RangeClear(Range(rbase).Resize(12, 6))
Andrebbe portata a (12,9) E cosi ?
La prima istruzione serve a controllare se l'elemento esaminato ha "classname" pari a "w-100" o se siamo all'interno delle prime 5 colonne (non "righe"); quindi corretto che se vuoi importare piu' elementi devi usare "< XX", con XX pari al numero di colonne da importare.
Idem, se importi piu' colonne allora e' corretto usare un "Resize" con piu' colonne nella Call RangeClear.
Come hai correttamente fatto nel codice che hai usato, confermato nel codice da me modificato sopra.
Ciao