VBA code which creates a daily report, based on data gathered in Worksheets in an Excel Workbook

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
0
down vote

favorite












I'm looking for some enlightening, since I'm still learning to code in VBA. I'm running code to create a daily report. It has to compare dates and check certain values in those dates and based on that I get my info. The info is gathered from three worksheets that are on the same workbook. It's working since it does what I wanted it to do, and at the start of the month it was working "fast". But now since my data is getting bigger, it also became slow and I think it's because I didn't optimize it and I'm running it on a desktop with an Intel Core i7-7700.



I will post a fragment of the code where I notice it's getting slow and the start of the code for variables.



Sub gen_informe()

Dim wsrgcmes As Worksheet
Dim wshtte As Worksheet
Dim wsstats As Worksheet
Dim rdate As Range
Dim celdate As Range
Dim idtask As Range
Dim rtask As Range
Dim idcaso As Range
Dim rcaso As Range
Dim rstats As Range
Dim idstats As Range
Dim x As Long
Dim i As Double
Dim fregistro As Double
Dim coninc As Integer
Dim conser As Integer
Dim fcierre As Double
Dim ansin As String
Dim ansout As String

Set wsrgcmes = ThisWorkbook.Worksheets("ResumenGeneralCasosMES")
Set wshtte = ThisWorkbook.Worksheets("HistoricoTareas")
Set wsstats = ThisWorkbook.Worksheets("SolucionadosTATS")

With wsrgcmes
Set rdate = .Range("W2", .Cells(.Rows.count, .Columns("W:W").Column).End(xlUp))
Set rcaso = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wshtte
Set rtask = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wsstats
Set rstats = .Range("E2", .Cells(.Rows.count, .Columns("E:E").Column).End(xlUp))
End With

Sheets("Informe").Range("B4").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
If fregistro = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B12").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B19").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

contask = 0
i = 0
x = 0

Sheets("Informe").Range("B27").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
If fregistro = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(0, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(1, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(2, x).Value = contask
x = x + 1
contask = 0
Next i


From here on, it starts getting slower, these last two for-loops are iterating a lot it seems. I used similar for-loops along the code, maybe poor optimization on my part.



i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B42").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i

i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B49").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Requerimiento" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i


End Sub






share|improve this question

















  • 1




    Please post the entirety of the code rather than a fragment, the bottleneck could be the result of something else. If this is all of the code, please clarify that instead of just "fragment"
    – Raystafarian
    Apr 13 at 21:26











  • @Raystafarian hey, thanks a lot for your input! And your answer! It explains a lot of what I need to do, I will start checking it asap. And that's pretty much all the sub. I have another sub tho, that sub reads all the info from 3 files and copy the info to the current workbook in 3 different sheets. Don't know if I should post that as well. Thanks a lot again!
    – user167105
    Apr 17 at 13:59
















up vote
0
down vote

favorite












I'm looking for some enlightening, since I'm still learning to code in VBA. I'm running code to create a daily report. It has to compare dates and check certain values in those dates and based on that I get my info. The info is gathered from three worksheets that are on the same workbook. It's working since it does what I wanted it to do, and at the start of the month it was working "fast". But now since my data is getting bigger, it also became slow and I think it's because I didn't optimize it and I'm running it on a desktop with an Intel Core i7-7700.



I will post a fragment of the code where I notice it's getting slow and the start of the code for variables.



Sub gen_informe()

Dim wsrgcmes As Worksheet
Dim wshtte As Worksheet
Dim wsstats As Worksheet
Dim rdate As Range
Dim celdate As Range
Dim idtask As Range
Dim rtask As Range
Dim idcaso As Range
Dim rcaso As Range
Dim rstats As Range
Dim idstats As Range
Dim x As Long
Dim i As Double
Dim fregistro As Double
Dim coninc As Integer
Dim conser As Integer
Dim fcierre As Double
Dim ansin As String
Dim ansout As String

Set wsrgcmes = ThisWorkbook.Worksheets("ResumenGeneralCasosMES")
Set wshtte = ThisWorkbook.Worksheets("HistoricoTareas")
Set wsstats = ThisWorkbook.Worksheets("SolucionadosTATS")

With wsrgcmes
Set rdate = .Range("W2", .Cells(.Rows.count, .Columns("W:W").Column).End(xlUp))
Set rcaso = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wshtte
Set rtask = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wsstats
Set rstats = .Range("E2", .Cells(.Rows.count, .Columns("E:E").Column).End(xlUp))
End With

Sheets("Informe").Range("B4").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
If fregistro = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B12").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B19").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

contask = 0
i = 0
x = 0

Sheets("Informe").Range("B27").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
If fregistro = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(0, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(1, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(2, x).Value = contask
x = x + 1
contask = 0
Next i


From here on, it starts getting slower, these last two for-loops are iterating a lot it seems. I used similar for-loops along the code, maybe poor optimization on my part.



i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B42").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i

i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B49").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Requerimiento" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i


End Sub






share|improve this question

















  • 1




    Please post the entirety of the code rather than a fragment, the bottleneck could be the result of something else. If this is all of the code, please clarify that instead of just "fragment"
    – Raystafarian
    Apr 13 at 21:26











  • @Raystafarian hey, thanks a lot for your input! And your answer! It explains a lot of what I need to do, I will start checking it asap. And that's pretty much all the sub. I have another sub tho, that sub reads all the info from 3 files and copy the info to the current workbook in 3 different sheets. Don't know if I should post that as well. Thanks a lot again!
    – user167105
    Apr 17 at 13:59












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm looking for some enlightening, since I'm still learning to code in VBA. I'm running code to create a daily report. It has to compare dates and check certain values in those dates and based on that I get my info. The info is gathered from three worksheets that are on the same workbook. It's working since it does what I wanted it to do, and at the start of the month it was working "fast". But now since my data is getting bigger, it also became slow and I think it's because I didn't optimize it and I'm running it on a desktop with an Intel Core i7-7700.



I will post a fragment of the code where I notice it's getting slow and the start of the code for variables.



Sub gen_informe()

Dim wsrgcmes As Worksheet
Dim wshtte As Worksheet
Dim wsstats As Worksheet
Dim rdate As Range
Dim celdate As Range
Dim idtask As Range
Dim rtask As Range
Dim idcaso As Range
Dim rcaso As Range
Dim rstats As Range
Dim idstats As Range
Dim x As Long
Dim i As Double
Dim fregistro As Double
Dim coninc As Integer
Dim conser As Integer
Dim fcierre As Double
Dim ansin As String
Dim ansout As String

Set wsrgcmes = ThisWorkbook.Worksheets("ResumenGeneralCasosMES")
Set wshtte = ThisWorkbook.Worksheets("HistoricoTareas")
Set wsstats = ThisWorkbook.Worksheets("SolucionadosTATS")

With wsrgcmes
Set rdate = .Range("W2", .Cells(.Rows.count, .Columns("W:W").Column).End(xlUp))
Set rcaso = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wshtte
Set rtask = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wsstats
Set rstats = .Range("E2", .Cells(.Rows.count, .Columns("E:E").Column).End(xlUp))
End With

Sheets("Informe").Range("B4").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
If fregistro = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B12").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B19").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

contask = 0
i = 0
x = 0

Sheets("Informe").Range("B27").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
If fregistro = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(0, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(1, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(2, x).Value = contask
x = x + 1
contask = 0
Next i


From here on, it starts getting slower, these last two for-loops are iterating a lot it seems. I used similar for-loops along the code, maybe poor optimization on my part.



i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B42").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i

i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B49").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Requerimiento" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i


End Sub






share|improve this question













I'm looking for some enlightening, since I'm still learning to code in VBA. I'm running code to create a daily report. It has to compare dates and check certain values in those dates and based on that I get my info. The info is gathered from three worksheets that are on the same workbook. It's working since it does what I wanted it to do, and at the start of the month it was working "fast". But now since my data is getting bigger, it also became slow and I think it's because I didn't optimize it and I'm running it on a desktop with an Intel Core i7-7700.



I will post a fragment of the code where I notice it's getting slow and the start of the code for variables.



Sub gen_informe()

Dim wsrgcmes As Worksheet
Dim wshtte As Worksheet
Dim wsstats As Worksheet
Dim rdate As Range
Dim celdate As Range
Dim idtask As Range
Dim rtask As Range
Dim idcaso As Range
Dim rcaso As Range
Dim rstats As Range
Dim idstats As Range
Dim x As Long
Dim i As Double
Dim fregistro As Double
Dim coninc As Integer
Dim conser As Integer
Dim fcierre As Double
Dim ansin As String
Dim ansout As String

Set wsrgcmes = ThisWorkbook.Worksheets("ResumenGeneralCasosMES")
Set wshtte = ThisWorkbook.Worksheets("HistoricoTareas")
Set wsstats = ThisWorkbook.Worksheets("SolucionadosTATS")

With wsrgcmes
Set rdate = .Range("W2", .Cells(.Rows.count, .Columns("W:W").Column).End(xlUp))
Set rcaso = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wshtte
Set rtask = .Range("B2", .Cells(.Rows.count, .Columns("B:B").Column).End(xlUp))
End With

With wsstats
Set rstats = .Range("E2", .Cells(.Rows.count, .Columns("E:E").Column).End(xlUp))
End With

Sheets("Informe").Range("B4").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
If fregistro = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B12").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

coninc = 0
conser = 0
i = 0
x = 0

Sheets("Informe").Range("B19").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
For Each celdate In rdate
fregistro = CDbl(Int(celdate.Value))
fcierre = CDbl(Int(celdate.Offset(0, 2).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
Select Case celdate.Offset(0, -19).Value
Case "INCIDENTE"
coninc = coninc + 1
Case "LLAMADA DE SERVICIO"
conser = conser + 1
End Select
End If
Next celdate
ActiveCell.Offset(0, x).Value = coninc
ActiveCell.Offset(1, x) = conser
x = x + 1
coninc = 0
conser = 0
Next i

contask = 0
i = 0
x = 0

Sheets("Informe").Range("B27").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
If fregistro = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(0, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(1, x).Value = contask
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(2, x).Value = contask
x = x + 1
contask = 0
Next i


From here on, it starts getting slower, these last two for-loops are iterating a lot it seems. I used similar for-loops along the code, maybe poor optimization on my part.



i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B42").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i

i = 0
x = 0
ansin = 0
ansout = 0

Sheets("Informe").Range("B49").Select

For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idstats In rstats
With Application
Set idcaso = .Index(rcaso, .Match(idstats.Value, rcaso, 0))
End With
fcierre = CDbl(Int(idcaso.Offset(0, 23).Value))
If fcierre = i And idstats.Offset(0, -1).Value = "Requerimiento" Then
Select Case idstats.Offset(0, 20).Value
Case "S"
ansin = ansin + 1
Case "N"
ansout = ansout + 1
End Select
End If
Next idstats
ActiveCell.Offset(0, x).Value = ansin
ActiveCell.Offset(1, x) = ansout
x = x + 1
ansin = 0
ansout = 0
Next i


End Sub








share|improve this question












share|improve this question




share|improve this question








edited Apr 13 at 22:41









Jamal♦

30.1k11114225




30.1k11114225









asked Apr 13 at 16:19









user167105

11




11







  • 1




    Please post the entirety of the code rather than a fragment, the bottleneck could be the result of something else. If this is all of the code, please clarify that instead of just "fragment"
    – Raystafarian
    Apr 13 at 21:26











  • @Raystafarian hey, thanks a lot for your input! And your answer! It explains a lot of what I need to do, I will start checking it asap. And that's pretty much all the sub. I have another sub tho, that sub reads all the info from 3 files and copy the info to the current workbook in 3 different sheets. Don't know if I should post that as well. Thanks a lot again!
    – user167105
    Apr 17 at 13:59












  • 1




    Please post the entirety of the code rather than a fragment, the bottleneck could be the result of something else. If this is all of the code, please clarify that instead of just "fragment"
    – Raystafarian
    Apr 13 at 21:26











  • @Raystafarian hey, thanks a lot for your input! And your answer! It explains a lot of what I need to do, I will start checking it asap. And that's pretty much all the sub. I have another sub tho, that sub reads all the info from 3 files and copy the info to the current workbook in 3 different sheets. Don't know if I should post that as well. Thanks a lot again!
    – user167105
    Apr 17 at 13:59







1




1




Please post the entirety of the code rather than a fragment, the bottleneck could be the result of something else. If this is all of the code, please clarify that instead of just "fragment"
– Raystafarian
Apr 13 at 21:26





Please post the entirety of the code rather than a fragment, the bottleneck could be the result of something else. If this is all of the code, please clarify that instead of just "fragment"
– Raystafarian
Apr 13 at 21:26













@Raystafarian hey, thanks a lot for your input! And your answer! It explains a lot of what I need to do, I will start checking it asap. And that's pretty much all the sub. I have another sub tho, that sub reads all the info from 3 files and copy the info to the current workbook in 3 different sheets. Don't know if I should post that as well. Thanks a lot again!
– user167105
Apr 17 at 13:59




@Raystafarian hey, thanks a lot for your input! And your answer! It explains a lot of what I need to do, I will start checking it asap. And that's pretty much all the sub. I have another sub tho, that sub reads all the info from 3 files and copy the info to the current workbook in 3 different sheets. Don't know if I should post that as well. Thanks a lot again!
– user167105
Apr 17 at 13:59










1 Answer
1






active

oldest

votes

















up vote
1
down vote













I think your idea here with your code is a good one. Your execution, though, as you see, is not optimized. But that's okay!



Refactoring



The first concept I'd like to bring up is refactoring. When you do something more than once it's usually a lot cleaner to write it once and use it several times. How? Create another function or sub. You have 8 For with some loops doing, I think, the same basic thing. As far as I can tell, there are basically three loops. I'll name them -



Select Loop




Select Case celdate.Offset(0, -19).Value



fregistro loop




If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3



fcierre loop




If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then 'this line changes in 2



I hope that's clear. If we look at the fregistro loop -



Sheets("Informe").Range("B27").Select 'this line changes
For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0)) 'optional
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this changes
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3
contask = contask + 1
End If
Next idtask
ActiveCell.Offset(1, x).Value = contask 'this line changes in 3
x = x + 1
contask = 0
Next i

contask = 0
i = 0
x = 0


A few things change loop to loop -



fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this happens in 2 of 3 
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then '>, <, =
ActiveCell.Offset(2, x).Value = contask '0, 1, 2


As you see, the basic thing that's changing is your if condition and your target cell. Those would be your parameters because they are variable. Let's say nothing else changes for now, you would use this:



Private Sub fregistro(ByVal testCondition As Long, ByVal targetRow As Long, ByVal targetDate As Date, Optional ByVal fcierreTest As Long = 0)
Sheets("Informe").Range("B27").Select
For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
On Error Resume Next
For Each idtask In rtask
With Application
Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
End With
fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
If Not fcierreTest = 0 Then
fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
End If

Select Case testCondition
Case 0
If fregistro = i Then
contask = contask + 1
End If
Case 1
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
contask = contask + 1
End If
Case 2
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
contask = contask + 1
End If
Case Else
End Select

Next idtask
ActiveCell.Offset(targetRow, x).Value = contask
x = x + 1
contask = 0
Next i
End Sub


And then you would just do this from the main sub -



fregistro 1, 0, Date
fregistro 2, 1, Date, True
fregistro 2, 2, Date, True


Right? You could do that for all three loops and your code would be more clear. That's the first concept.




Optimizing



So refactoring is a big part of optimization, but the refactoring isn't going to fix your bottleneck. Let's look at the fregistro sub again. Your basic procedure is



For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
For Each idtask In rtask
With Application
End With
If isFcierreTest Then
End If
Select Case testCondition
End Select
Next
ActiveCell.Offset(targetRow, x).Value = contask
x = x + 1
contask = 0
Next i


So you see you have a For Each loop inside a For loop. For every value. That's slow, let me tell you. You're also needing to reset x and contask every time.



How would we fix this? Probably with arrays:



Dim lastRow As Long

Dim rdate As Variant
lastRow = wsrgcmes.Cells(Rows.Count, 23).End(xlUp).Row
rdate = wsrgcmes.Range(wsrgcmes.Cells(1, 23), wsrgcmes.Cells(lastRow, 23))

Dim rcaso As Variant
lastRow = wsrgcmes.Cells(Rows.Count, 2).End(xlUp).Row
rcaso = wsrgcmes.Range(wsrgcmes.Cells(1, 2), wsrgcmes.Cells(lastRow, 2))

Dim rtask As Variant
lastRow = wshtee.Cells(Rows.Count, 2).End(xlUp).Row
rtask = wshtee.Range(wshtee.Cells(1, 2), wshtee.Cells(lastRow, 2))


Now those three variants are populated with all the data you need and you only queried the sheet one time each. Now you can work with the data in the arrays (variants in this case) in VBA without touching the sheet.



For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
On Error Resume Next
For j = LBound(rtask) To UBound(rtask)
idcaso = rcaso(j - 1)
fregistro = CDbl(Int(rcaso(j + 21)))
If isFcierreTest Then
fcierre = CDbl(Int(rcaso((j + 7))))
End If
Select Case testCondition
Case 1
If fregistro = i Then
contask = contask + 1
End If
Case 2
If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
contask = contask + 1
End If
Case 3
If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
contask = contask + 1
End If
Case Else
End Select


I think I got that right, but I didn't test it so make sure. You could also create a resultArray to populate the ActiveCell.Offset(targetRow,x).Value by storing it all and then writing it once to the sheet.



targetSheet.range('targetRange) = resultArray


Once again, that's pretty generic, so don't rely on it. Backup all your data before trying any of this.






share|improve this answer





















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191993%2fvba-code-which-creates-a-daily-report-based-on-data-gathered-in-worksheets-in-a%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote













    I think your idea here with your code is a good one. Your execution, though, as you see, is not optimized. But that's okay!



    Refactoring



    The first concept I'd like to bring up is refactoring. When you do something more than once it's usually a lot cleaner to write it once and use it several times. How? Create another function or sub. You have 8 For with some loops doing, I think, the same basic thing. As far as I can tell, there are basically three loops. I'll name them -



    Select Loop




    Select Case celdate.Offset(0, -19).Value



    fregistro loop




    If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3



    fcierre loop




    If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then 'this line changes in 2



    I hope that's clear. If we look at the fregistro loop -



    Sheets("Informe").Range("B27").Select 'this line changes
    For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
    On Error Resume Next
    For Each idtask In rtask
    With Application
    Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0)) 'optional
    End With
    fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
    fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this changes
    If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3
    contask = contask + 1
    End If
    Next idtask
    ActiveCell.Offset(1, x).Value = contask 'this line changes in 3
    x = x + 1
    contask = 0
    Next i

    contask = 0
    i = 0
    x = 0


    A few things change loop to loop -



    fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this happens in 2 of 3 
    If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then '>, <, =
    ActiveCell.Offset(2, x).Value = contask '0, 1, 2


    As you see, the basic thing that's changing is your if condition and your target cell. Those would be your parameters because they are variable. Let's say nothing else changes for now, you would use this:



    Private Sub fregistro(ByVal testCondition As Long, ByVal targetRow As Long, ByVal targetDate As Date, Optional ByVal fcierreTest As Long = 0)
    Sheets("Informe").Range("B27").Select
    For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
    On Error Resume Next
    For Each idtask In rtask
    With Application
    Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
    End With
    fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
    If Not fcierreTest = 0 Then
    fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
    End If

    Select Case testCondition
    Case 0
    If fregistro = i Then
    contask = contask + 1
    End If
    Case 1
    If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
    contask = contask + 1
    End If
    Case 2
    If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
    contask = contask + 1
    End If
    Case Else
    End Select

    Next idtask
    ActiveCell.Offset(targetRow, x).Value = contask
    x = x + 1
    contask = 0
    Next i
    End Sub


    And then you would just do this from the main sub -



    fregistro 1, 0, Date
    fregistro 2, 1, Date, True
    fregistro 2, 2, Date, True


    Right? You could do that for all three loops and your code would be more clear. That's the first concept.




    Optimizing



    So refactoring is a big part of optimization, but the refactoring isn't going to fix your bottleneck. Let's look at the fregistro sub again. Your basic procedure is



    For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
    For Each idtask In rtask
    With Application
    End With
    If isFcierreTest Then
    End If
    Select Case testCondition
    End Select
    Next
    ActiveCell.Offset(targetRow, x).Value = contask
    x = x + 1
    contask = 0
    Next i


    So you see you have a For Each loop inside a For loop. For every value. That's slow, let me tell you. You're also needing to reset x and contask every time.



    How would we fix this? Probably with arrays:



    Dim lastRow As Long

    Dim rdate As Variant
    lastRow = wsrgcmes.Cells(Rows.Count, 23).End(xlUp).Row
    rdate = wsrgcmes.Range(wsrgcmes.Cells(1, 23), wsrgcmes.Cells(lastRow, 23))

    Dim rcaso As Variant
    lastRow = wsrgcmes.Cells(Rows.Count, 2).End(xlUp).Row
    rcaso = wsrgcmes.Range(wsrgcmes.Cells(1, 2), wsrgcmes.Cells(lastRow, 2))

    Dim rtask As Variant
    lastRow = wshtee.Cells(Rows.Count, 2).End(xlUp).Row
    rtask = wshtee.Range(wshtee.Cells(1, 2), wshtee.Cells(lastRow, 2))


    Now those three variants are populated with all the data you need and you only queried the sheet one time each. Now you can work with the data in the arrays (variants in this case) in VBA without touching the sheet.



    For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
    On Error Resume Next
    For j = LBound(rtask) To UBound(rtask)
    idcaso = rcaso(j - 1)
    fregistro = CDbl(Int(rcaso(j + 21)))
    If isFcierreTest Then
    fcierre = CDbl(Int(rcaso((j + 7))))
    End If
    Select Case testCondition
    Case 1
    If fregistro = i Then
    contask = contask + 1
    End If
    Case 2
    If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
    contask = contask + 1
    End If
    Case 3
    If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
    contask = contask + 1
    End If
    Case Else
    End Select


    I think I got that right, but I didn't test it so make sure. You could also create a resultArray to populate the ActiveCell.Offset(targetRow,x).Value by storing it all and then writing it once to the sheet.



    targetSheet.range('targetRange) = resultArray


    Once again, that's pretty generic, so don't rely on it. Backup all your data before trying any of this.






    share|improve this answer

























      up vote
      1
      down vote













      I think your idea here with your code is a good one. Your execution, though, as you see, is not optimized. But that's okay!



      Refactoring



      The first concept I'd like to bring up is refactoring. When you do something more than once it's usually a lot cleaner to write it once and use it several times. How? Create another function or sub. You have 8 For with some loops doing, I think, the same basic thing. As far as I can tell, there are basically three loops. I'll name them -



      Select Loop




      Select Case celdate.Offset(0, -19).Value



      fregistro loop




      If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3



      fcierre loop




      If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then 'this line changes in 2



      I hope that's clear. If we look at the fregistro loop -



      Sheets("Informe").Range("B27").Select 'this line changes
      For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
      On Error Resume Next
      For Each idtask In rtask
      With Application
      Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0)) 'optional
      End With
      fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
      fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this changes
      If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3
      contask = contask + 1
      End If
      Next idtask
      ActiveCell.Offset(1, x).Value = contask 'this line changes in 3
      x = x + 1
      contask = 0
      Next i

      contask = 0
      i = 0
      x = 0


      A few things change loop to loop -



      fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this happens in 2 of 3 
      If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then '>, <, =
      ActiveCell.Offset(2, x).Value = contask '0, 1, 2


      As you see, the basic thing that's changing is your if condition and your target cell. Those would be your parameters because they are variable. Let's say nothing else changes for now, you would use this:



      Private Sub fregistro(ByVal testCondition As Long, ByVal targetRow As Long, ByVal targetDate As Date, Optional ByVal fcierreTest As Long = 0)
      Sheets("Informe").Range("B27").Select
      For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
      On Error Resume Next
      For Each idtask In rtask
      With Application
      Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
      End With
      fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
      If Not fcierreTest = 0 Then
      fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
      End If

      Select Case testCondition
      Case 0
      If fregistro = i Then
      contask = contask + 1
      End If
      Case 1
      If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
      contask = contask + 1
      End If
      Case 2
      If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
      contask = contask + 1
      End If
      Case Else
      End Select

      Next idtask
      ActiveCell.Offset(targetRow, x).Value = contask
      x = x + 1
      contask = 0
      Next i
      End Sub


      And then you would just do this from the main sub -



      fregistro 1, 0, Date
      fregistro 2, 1, Date, True
      fregistro 2, 2, Date, True


      Right? You could do that for all three loops and your code would be more clear. That's the first concept.




      Optimizing



      So refactoring is a big part of optimization, but the refactoring isn't going to fix your bottleneck. Let's look at the fregistro sub again. Your basic procedure is



      For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
      For Each idtask In rtask
      With Application
      End With
      If isFcierreTest Then
      End If
      Select Case testCondition
      End Select
      Next
      ActiveCell.Offset(targetRow, x).Value = contask
      x = x + 1
      contask = 0
      Next i


      So you see you have a For Each loop inside a For loop. For every value. That's slow, let me tell you. You're also needing to reset x and contask every time.



      How would we fix this? Probably with arrays:



      Dim lastRow As Long

      Dim rdate As Variant
      lastRow = wsrgcmes.Cells(Rows.Count, 23).End(xlUp).Row
      rdate = wsrgcmes.Range(wsrgcmes.Cells(1, 23), wsrgcmes.Cells(lastRow, 23))

      Dim rcaso As Variant
      lastRow = wsrgcmes.Cells(Rows.Count, 2).End(xlUp).Row
      rcaso = wsrgcmes.Range(wsrgcmes.Cells(1, 2), wsrgcmes.Cells(lastRow, 2))

      Dim rtask As Variant
      lastRow = wshtee.Cells(Rows.Count, 2).End(xlUp).Row
      rtask = wshtee.Range(wshtee.Cells(1, 2), wshtee.Cells(lastRow, 2))


      Now those three variants are populated with all the data you need and you only queried the sheet one time each. Now you can work with the data in the arrays (variants in this case) in VBA without touching the sheet.



      For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
      On Error Resume Next
      For j = LBound(rtask) To UBound(rtask)
      idcaso = rcaso(j - 1)
      fregistro = CDbl(Int(rcaso(j + 21)))
      If isFcierreTest Then
      fcierre = CDbl(Int(rcaso((j + 7))))
      End If
      Select Case testCondition
      Case 1
      If fregistro = i Then
      contask = contask + 1
      End If
      Case 2
      If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
      contask = contask + 1
      End If
      Case 3
      If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
      contask = contask + 1
      End If
      Case Else
      End Select


      I think I got that right, but I didn't test it so make sure. You could also create a resultArray to populate the ActiveCell.Offset(targetRow,x).Value by storing it all and then writing it once to the sheet.



      targetSheet.range('targetRange) = resultArray


      Once again, that's pretty generic, so don't rely on it. Backup all your data before trying any of this.






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        I think your idea here with your code is a good one. Your execution, though, as you see, is not optimized. But that's okay!



        Refactoring



        The first concept I'd like to bring up is refactoring. When you do something more than once it's usually a lot cleaner to write it once and use it several times. How? Create another function or sub. You have 8 For with some loops doing, I think, the same basic thing. As far as I can tell, there are basically three loops. I'll name them -



        Select Loop




        Select Case celdate.Offset(0, -19).Value



        fregistro loop




        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3



        fcierre loop




        If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then 'this line changes in 2



        I hope that's clear. If we look at the fregistro loop -



        Sheets("Informe").Range("B27").Select 'this line changes
        For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
        On Error Resume Next
        For Each idtask In rtask
        With Application
        Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0)) 'optional
        End With
        fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
        fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this changes
        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3
        contask = contask + 1
        End If
        Next idtask
        ActiveCell.Offset(1, x).Value = contask 'this line changes in 3
        x = x + 1
        contask = 0
        Next i

        contask = 0
        i = 0
        x = 0


        A few things change loop to loop -



        fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this happens in 2 of 3 
        If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then '>, <, =
        ActiveCell.Offset(2, x).Value = contask '0, 1, 2


        As you see, the basic thing that's changing is your if condition and your target cell. Those would be your parameters because they are variable. Let's say nothing else changes for now, you would use this:



        Private Sub fregistro(ByVal testCondition As Long, ByVal targetRow As Long, ByVal targetDate As Date, Optional ByVal fcierreTest As Long = 0)
        Sheets("Informe").Range("B27").Select
        For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
        On Error Resume Next
        For Each idtask In rtask
        With Application
        Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
        End With
        fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
        If Not fcierreTest = 0 Then
        fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
        End If

        Select Case testCondition
        Case 0
        If fregistro = i Then
        contask = contask + 1
        End If
        Case 1
        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
        contask = contask + 1
        End If
        Case 2
        If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
        contask = contask + 1
        End If
        Case Else
        End Select

        Next idtask
        ActiveCell.Offset(targetRow, x).Value = contask
        x = x + 1
        contask = 0
        Next i
        End Sub


        And then you would just do this from the main sub -



        fregistro 1, 0, Date
        fregistro 2, 1, Date, True
        fregistro 2, 2, Date, True


        Right? You could do that for all three loops and your code would be more clear. That's the first concept.




        Optimizing



        So refactoring is a big part of optimization, but the refactoring isn't going to fix your bottleneck. Let's look at the fregistro sub again. Your basic procedure is



        For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
        For Each idtask In rtask
        With Application
        End With
        If isFcierreTest Then
        End If
        Select Case testCondition
        End Select
        Next
        ActiveCell.Offset(targetRow, x).Value = contask
        x = x + 1
        contask = 0
        Next i


        So you see you have a For Each loop inside a For loop. For every value. That's slow, let me tell you. You're also needing to reset x and contask every time.



        How would we fix this? Probably with arrays:



        Dim lastRow As Long

        Dim rdate As Variant
        lastRow = wsrgcmes.Cells(Rows.Count, 23).End(xlUp).Row
        rdate = wsrgcmes.Range(wsrgcmes.Cells(1, 23), wsrgcmes.Cells(lastRow, 23))

        Dim rcaso As Variant
        lastRow = wsrgcmes.Cells(Rows.Count, 2).End(xlUp).Row
        rcaso = wsrgcmes.Range(wsrgcmes.Cells(1, 2), wsrgcmes.Cells(lastRow, 2))

        Dim rtask As Variant
        lastRow = wshtee.Cells(Rows.Count, 2).End(xlUp).Row
        rtask = wshtee.Range(wshtee.Cells(1, 2), wshtee.Cells(lastRow, 2))


        Now those three variants are populated with all the data you need and you only queried the sheet one time each. Now you can work with the data in the arrays (variants in this case) in VBA without touching the sheet.



        For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
        On Error Resume Next
        For j = LBound(rtask) To UBound(rtask)
        idcaso = rcaso(j - 1)
        fregistro = CDbl(Int(rcaso(j + 21)))
        If isFcierreTest Then
        fcierre = CDbl(Int(rcaso((j + 7))))
        End If
        Select Case testCondition
        Case 1
        If fregistro = i Then
        contask = contask + 1
        End If
        Case 2
        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
        contask = contask + 1
        End If
        Case 3
        If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
        contask = contask + 1
        End If
        Case Else
        End Select


        I think I got that right, but I didn't test it so make sure. You could also create a resultArray to populate the ActiveCell.Offset(targetRow,x).Value by storing it all and then writing it once to the sheet.



        targetSheet.range('targetRange) = resultArray


        Once again, that's pretty generic, so don't rely on it. Backup all your data before trying any of this.






        share|improve this answer













        I think your idea here with your code is a good one. Your execution, though, as you see, is not optimized. But that's okay!



        Refactoring



        The first concept I'd like to bring up is refactoring. When you do something more than once it's usually a lot cleaner to write it once and use it several times. How? Create another function or sub. You have 8 For with some loops doing, I think, the same basic thing. As far as I can tell, there are basically three loops. I'll name them -



        Select Loop




        Select Case celdate.Offset(0, -19).Value



        fregistro loop




        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3



        fcierre loop




        If fcierre = i And idstats.Offset(0, -1).Value = "Incidente" Then 'this line changes in 2



        I hope that's clear. If we look at the fregistro loop -



        Sheets("Informe").Range("B27").Select 'this line changes
        For i = CDbl(DateSerial(Year(Date), Month(Date), 1)) To CDbl(Date)
        On Error Resume Next
        For Each idtask In rtask
        With Application
        Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0)) 'optional
        End With
        fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
        fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this changes
        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then 'this line changes in 3
        contask = contask + 1
        End If
        Next idtask
        ActiveCell.Offset(1, x).Value = contask 'this line changes in 3
        x = x + 1
        contask = 0
        Next i

        contask = 0
        i = 0
        x = 0


        A few things change loop to loop -



        fcierre = CDbl(Int(idtask.Offset(0, 7).Value)) 'this happens in 2 of 3 
        If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then '>, <, =
        ActiveCell.Offset(2, x).Value = contask '0, 1, 2


        As you see, the basic thing that's changing is your if condition and your target cell. Those would be your parameters because they are variable. Let's say nothing else changes for now, you would use this:



        Private Sub fregistro(ByVal testCondition As Long, ByVal targetRow As Long, ByVal targetDate As Date, Optional ByVal fcierreTest As Long = 0)
        Sheets("Informe").Range("B27").Select
        For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
        On Error Resume Next
        For Each idtask In rtask
        With Application
        Set idcaso = .Index(rcaso, .Match(idtask.Offset(0, -1).Value, rcaso, 0))
        End With
        fregistro = CDbl(Int(idcaso.Offset(0, 21).Value))
        If Not fcierreTest = 0 Then
        fcierre = CDbl(Int(idtask.Offset(0, 7).Value))
        End If

        Select Case testCondition
        Case 0
        If fregistro = i Then
        contask = contask + 1
        End If
        Case 1
        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
        contask = contask + 1
        End If
        Case 2
        If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
        contask = contask + 1
        End If
        Case Else
        End Select

        Next idtask
        ActiveCell.Offset(targetRow, x).Value = contask
        x = x + 1
        contask = 0
        Next i
        End Sub


        And then you would just do this from the main sub -



        fregistro 1, 0, Date
        fregistro 2, 1, Date, True
        fregistro 2, 2, Date, True


        Right? You could do that for all three loops and your code would be more clear. That's the first concept.




        Optimizing



        So refactoring is a big part of optimization, but the refactoring isn't going to fix your bottleneck. Let's look at the fregistro sub again. Your basic procedure is



        For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
        For Each idtask In rtask
        With Application
        End With
        If isFcierreTest Then
        End If
        Select Case testCondition
        End Select
        Next
        ActiveCell.Offset(targetRow, x).Value = contask
        x = x + 1
        contask = 0
        Next i


        So you see you have a For Each loop inside a For loop. For every value. That's slow, let me tell you. You're also needing to reset x and contask every time.



        How would we fix this? Probably with arrays:



        Dim lastRow As Long

        Dim rdate As Variant
        lastRow = wsrgcmes.Cells(Rows.Count, 23).End(xlUp).Row
        rdate = wsrgcmes.Range(wsrgcmes.Cells(1, 23), wsrgcmes.Cells(lastRow, 23))

        Dim rcaso As Variant
        lastRow = wsrgcmes.Cells(Rows.Count, 2).End(xlUp).Row
        rcaso = wsrgcmes.Range(wsrgcmes.Cells(1, 2), wsrgcmes.Cells(lastRow, 2))

        Dim rtask As Variant
        lastRow = wshtee.Cells(Rows.Count, 2).End(xlUp).Row
        rtask = wshtee.Range(wshtee.Cells(1, 2), wshtee.Cells(lastRow, 2))


        Now those three variants are populated with all the data you need and you only queried the sheet one time each. Now you can work with the data in the arrays (variants in this case) in VBA without touching the sheet.



        For i = CDbl(DateSerial(Year(targetDate), Month(targetDate), 1)) To CDbl(targetDate)
        On Error Resume Next
        For j = LBound(rtask) To UBound(rtask)
        idcaso = rcaso(j - 1)
        fregistro = CDbl(Int(rcaso(j + 21)))
        If isFcierreTest Then
        fcierre = CDbl(Int(rcaso((j + 7))))
        End If
        Select Case testCondition
        Case 1
        If fregistro = i Then
        contask = contask + 1
        End If
        Case 2
        If fregistro > CDbl(DateSerial(Year(Date), Month(Date), 0)) And fcierre = i Then
        contask = contask + 1
        End If
        Case 3
        If fregistro < CDbl(DateSerial(Year(Date), Month(Date), 1)) And fcierre = i Then
        contask = contask + 1
        End If
        Case Else
        End Select


        I think I got that right, but I didn't test it so make sure. You could also create a resultArray to populate the ActiveCell.Offset(targetRow,x).Value by storing it all and then writing it once to the sheet.



        targetSheet.range('targetRange) = resultArray


        Once again, that's pretty generic, so don't rely on it. Backup all your data before trying any of this.







        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Apr 13 at 22:34









        Raystafarian

        5,4331046




        5,4331046






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191993%2fvba-code-which-creates-a-daily-report-based-on-data-gathered-in-worksheets-in-a%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Greedy Best First Search implementation in Rust

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            C++11 CLH Lock Implementation