This is a follow-up from this post.
It all works, but I think the code could be made to work faster and to be more stable. I have made improvements and updated the code in this new question.
Basically, when I activate the worksheet the weather information updates and three listboxes in the worksheet updates.
Public Sub Worksheet_Activate()
'Removes shapes already there that will be updated by the getWeather function
DeleteShapes
'Calls a function to get weather data from a web service
Call GetWeather("url", "Area1")
Call GetWeather("url", "Area2")
Call GetWeather("url", "Area3")
'fill lists with information
FillLists
End Sub
Then comes the DeleteShapes sub. This sub deletes a picture inserted by the GetWeather sub the last time it was updated. The reason for this is to not have a million pictures on top of eachother.
Public Sub DeleteShapes()
Dim delShape As Shape
For Each delShape In ARK_front.Shapes
If delShape.Type = msoAutoShape Then delShape.Delete
Next delShape
End Sub
Now the GetWeather sub. This sub gets weather information from worldweatheronline.com.
Public Sub GetWeather(APIurl As String, sted As String)
Dim i As Integer
Dim ws As Worksheet: Set ws = ActiveSheet
Dim city, omraade As String
Dim Req As New XMLHTTP
Dim Weather As IXMLDOMNode
Dim wShape As Shape
Dim thisCell As Range
Dim Resp As New DOMDocument
i = 0
omraade = ""
omraade = sted
Select Case omraade
Case "Area1"
i = 4
Case "Area2"
i = 6
Case "Area3"
i = 8
Case Else
Exit Sub
End Select
Req.Open "GET", "" & APIurl & "", False
Req.Send
Resp.LoadXML Req.responseText
For Each Weather In Resp.getElementsByTagName("current_condition")
Set thisCell = ws.Range(Cells(2, i), Cells(2, i))
Set wShape = ws.Shapes.AddShape(msoShapeRectangle, thisCell.Left, thisCell.Top, thisCell.Width, thisCell.Height)
wShape.Fill.UserPicture Weather.ChildNodes(4).Text 'img
Cells(3, i).Value = "" & Weather.ChildNodes(7).Text * 0.28 & " m/s" 'windspeedkmph
Cells(4, i).Value = Weather.ChildNodes(9).Text 'Direction
Cells(5, i).Value = Weather.ChildNodes(1).Text & " C" 'observation time
Next Weather
End Sub
Now the sub to fill three listboxes in a worksheet with information from a Access database using SQL.
Public Sub FillLists()
'I cannot run option explicit. It gives me the error message of "Invalid inside procedure". I cannot for the life of me figure out what or where it comes from.
'Option Explicit
' I have to declare formattedStartDate and formattedEndDate as string and not Date. If I declare them as Date, they follow the "dd.mm.yyy" format, even if I use format("expression", "mm/dd/yyyy"
Dim formattedStartDate As String
Dim formattedEndDate As String
Dim yourUserName As String
Dim i, j, u As Integer
Dim rs As ADODB.Recordset
Dim sql As ADODB.Connection
formattedStartDate = Month(Date) & "/" & Day(Date) - 7 & "/" & Year(Date)
formattedEndDate = Month(Date) & "/" & Day(Date) & "/" & Year(Date)
'I realize that this is a security issue, and that I should not trust my users to not mess it up. But I know that my users dont know how VBA or SQL even in the slightest. So I will let it pass.
yourUserName = Application.userName
'Create a new connection with sqlConnect and a new recordset with rs.
Set sqlConnect = New ADODB.Connection
Set rs = New ADODB.Recordset
'sqlConnect utilizes the connectionstring.
sqlConnect.connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\database.accdb;Persist Security Info=False;"
'Open the connection
sqlConnect.Open
'Set rs.Activeconnection to sqlConnect
rs.ActiveConnection = sqlConnect
'Query the Access database
rs.Open "SELECT [RefNr], [Registrert Av],[Nettstasjon], [Meldt Dato], [Sekundærstasjon], [Avgang], [Beskrivelse], [Til Dato] FROM [tblDatabase]" & _
"WHERE [Loggtype] = 'Beskjed' AND [Meldt Dato] >= DateAdd('d',-30,Date())" & _
"ORDER BY [Meldt Dato] DESC;", sqlConnect, adOpenStatic
'Set j value to 0 so that we know where it starts
j = 0
'Populate the first listbox
With ARK_front.lst_beskjeder
.Clear
Do While Not rs.EOF
.AddItem
If Not IsNull(rs!refnr) Then
.List(j, 0) = rs![refnr]
End If
If IsDate(rs![Meldt Dato]) Then
.List(j, 1) = Format(rs![Meldt Dato], "dd/mm/yy")
End If
.List(j, 4) = rs![nettstasjon]
If Not IsNull(rs![Sekundærstasjon]) Then
.List(j, 2) = rs![Sekundærstasjon]
End If
If Not IsNull(rs![Avgang]) Then
.List(j, 3) = rs![Avgang]
End If
If Not IsNull(rs![beskrivelse]) Then
.List(j, 5) = rs![beskrivelse]
End If
j = j + 1
rs.MoveNext
Loop
End With
'Close the recordset and reopen a new one with a different query
rs.Close
rs.Open "SELECT [RefNr], [Registrert Av],[Nettstasjon], [Meldt Dato] , [Bestilling], [Sekundærstasjon], [Avgang], [Hovedkomponent], [HovedÅrsak], [Status Bestilling] FROM [tblDatabase]" & _
"WHERE [Registrert Av] <> '" & yourUserName & "' AND [Meldt Dato] BETWEEN #" & formattedStartDate & "# AND #" & formattedEndDate & "#" & _
"ORDER BY [Meldt Dato] DESC;", sqlConnect, adOpenStatic
'Set u to 0 so that we know that it is zero at this point
u = 0
'Populate the second listbox
With ARK_front.lst_AlleFeil
.Clear
Do While Not rs.EOF
.AddItem
If Not IsNull(rs!refnr) Then
.List(u, 0) = rs![refnr]
End If
If IsDate(rs![Meldt Dato]) Then
.List(u, 1) = Format(rs![Meldt Dato], "dd/mm/yy")
End If
If Not IsNull(rs![nettstasjon]) Then
.List(u, 4) = rs![nettstasjon]
End If
If Not IsNull(rs![Sekundærstasjon]) Then
.List(u, 2) = rs![Sekundærstasjon]
End If
If Not IsNull(rs![Avgang]) Then
.List(u, 3) = rs![Avgang]
End If
If Not IsNull(rs![Hovedkomponent]) Then
.List(u, 5) = rs![Hovedkomponent]
End If
If Not IsNull(rs![HovedÅrsak]) Then
.List(u, 6) = rs![HovedÅrsak]
End If
If Not IsNull(rs![Status Bestilling]) Then
.List(u, 7) = rs![Status Bestilling]
End If
If Not IsNull(rs![bestilling]) Then
.List(u, 8) = rs![bestilling]
End If
u = u + 1
rs.MoveNext
Loop
End With
'Close and reopen a new recordset
rs.Close
rs.Open "SELECT [RefNr], [Registrert Av],[Nettstasjon], [Meldt Dato] , [Bestilling], [Sekundærstasjon], [Avgang], [Hovedkomponent], [HovedÅrsak], [Status Bestilling] FROM [tblDatabase]" & _
"WHERE [Registrert Av] = '" & yourUserName & "' AND [Loggtype] <> 'Beskjed' AND [Meldt Dato] BETWEEN #" & formattedStartDate & "# AND #" & formattedEndDate & "#" & _
"ORDER BY [Meldt Dato] DESC;", sqlConnect, adOpenStatic
'Set i to 0 so that we know that it is zero at this point
i = 0
'Populate the third listbox
With ARK_front.lst_mineFeil
.Clear
Do While Not rs.EOF
.AddItem
If Not IsNull(rs!refnr) Then
.List(i, 0) = rs![refnr]
End If
If IsDate(rs![Meldt Dato]) Then
.List(i, 1) = Format(rs![Meldt Dato], "dd/mm/yy")
End If
.List(i, 4) = rs![nettstasjon]
If Not IsNull(rs![Sekundærstasjon]) Then
.List(i, 2) = rs![Sekundærstasjon]
End If
If Not IsNull(rs![Avgang]) Then
.List(i, 3) = rs![Avgang]
End If
If Not IsNull(rs![Hovedkomponent]) Then
.List(i, 5) = rs![Hovedkomponent]
End If
If Not IsNull(rs![HovedÅrsak]) Then
.List(i, 6) = rs![HovedÅrsak]
End If
If Not IsNull(rs![Status Bestilling]) Then
.List(i, 7) = rs![Status Bestilling]
End If
If Not IsNull(rs![bestilling]) Then
.List(i, 8) = rs![bestilling]
End If
i = i + 1
rs.MoveNext
Loop
End With
'Close the recordset and the connection
rs.Close
sqlConnect.Close
'Set the recordset and connection values to nothing
Set rs = Nothing
Set sqlConnect = Nothing
End Sub
I would like tips on how to make my code more stable and faster. I am sure I am making tons of mistakes. Please point them out to me ;)
current_conditions
are you expecting to parse in theGetWeather
function? If it's any more than one condition, the only information you'll see is that last one in the list and (probably) a stack of images (shapes) one on top of the other, with only the last one visible. Is this intended? Only displaying the last condition could save time if there's a long list of conditions. Additionally, you're missing worksheet references for all yourCells
andRanges
in that sub. \$\endgroup\$