Speed up my VBA using arrays - arrays

I have hobby programmed this a VBA macro for extracting and plotting data from some text files in Excel. I recentyl tried it on a slightly bigger file, about 700 lines and 1 too three rows to be averaged and plotted. It is painfully slow and i think it can be inproved using arrays but my previous atempt at usings arrays in VBA was not very successfull so i thought i would ask you guys for some advice on how to turn the following code from a for loop into a array addition.
Here is the part I want to convert. Basically it goes line to line and averages the values from a specific but unknown number of columns.
' Add all Stribeckcurves
l = 8
For k = skriv + 4 To skriv + 45
meanSpeed = 0
meanTraction = 0
For m = 1 To NumberOfColumns
meanSpeed = meanSpeed + shtraw.Cells(k, i + 2 * m - 2)
meanTraction = meanTraction + shtraw.Cells(k, i + 2 * m - 1)
Next m
shtmean.Cells(l, 3 * j - 2) = meanSpeed / NumberOfColumns
shtmean.Cells(l, 3 * j - 1) = meanTraction / NumberOfColumns
l = l + 1
Next k
Here i the whole code block for reference:
Sub loppthroughfolder()
Dim mainwb As Workbook, Datwb As Workbook, filename As String, arrFileName() As String, shtraw As Worksheet, shtmean As Worksheet, lastrow As Long, lastColumn As Long, j As Integer, profile As String, duplicateArray As Variant, meanSpeed As Double, meanTraction As Double
Set mainwb = ActiveWorkbook
Worksheets("rawData").Cells.Clear
Worksheets("mean").Cells.Clear
Charts("plot").Activate
For Each s In ActiveChart.SeriesCollection
s.Delete
Next s
Set shtraw = ThisWorkbook.Worksheets("rawData")
Set shtmean = ThisWorkbook.Worksheets("mean")
Set shtcon = ThisWorkbook.Worksheets("configure")
Set shtplot = ThisWorkbook.Charts("plot")
With Application.FileDialog(msoFileDialogFolderPicker)
.Title = "Please select a folder"
.Show
.AllowMultiSelect = False
If .SelectedItems.Count = 0 Then
MsgBox "You did not select a folder"
Exit Sub
End If
MyFolder = .SelectedItems(1)
End With
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
Set folderObj = fileSystemObject.getfolder(MyFolder)
shtraw.Select
For Each fileObj In folderObj.Files 'loop through files
If (fileSystemObject.GetExtensionName(fileObj.Path) = "txt") Then
If Not fileObj.Attributes And 2 Then
arrFileName = Split(fileObj.Path, "\")
Path = "TEXT:" & fileObj.Path
filename = arrFileName(UBound(arrFileName))
'Get the filename without the.mtmd
CustName = Mid(filename, 1, InStr(filename, ".") - 1)
range("$A$1").value = CustName
With ActiveSheet.QueryTables.Add(Connection:="TEXT;" & fileObj.Path, Destination:=range("$A$2"))
.name = filename
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.RefreshStyle = xlInsertDeleteCells
.SavePassword = False
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.TextFilePromptOnRefresh = False
.TextFilePlatform = 437
.TextFileStartRow = 1
.TextFileParseType = xlDelimited
.TextFileTextQualifier = xlTextQualifierDoubleQuote
.TextFileConsecutiveDelimiter = False
.TextFileTabDelimiter = True
.TextFileSemicolonDelimiter = False
.TextFileCommaDelimiter = False
.TextFileSpaceDelimiter = False
.TextFileColumnDataTypes = Array(1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9)
.TextFileTrailingMinusNumbers = True
.Refresh BackgroundQuery:=False
End With
End If 'end if hidden if statement
End If 'end of txt
Next fileObj 'close loop
range("$A$1:$B$1").Delete shift:=xlToLeft
lastrow = shtraw.UsedRange.Rows.Count
lastColumn = shtraw.UsedRange.Columns.Count
' Some formating before the sorting
For i = 1 To lastColumn Step 2
shtraw.Cells(9, i + 1) = shtraw.Cells(9, i)
Next i
' Sort the result after the second line in the comments
shtraw.Sort.SortFields.Clear
shtraw.Sort.SortFields.Add Key:=range(shtraw.Cells(9, 1), shtraw.Cells(9, lastColumn)), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With shtraw.Sort
.SetRange range(Cells(1, 1), Cells(lastrow, lastColumn))
.Header = xlGuess
.MatchCase = False
.Orientation = xlLeftToRight
.Apply
End With
duplicateArray = findCopies(shtraw, lastColumn)
j = 1
For Each i In duplicateArray
' Find out how many columns there are for this FM
If j = UBound(duplicateArray) + 1 Then
NumberOfColumns = (lastColumn + 1 - duplicateArray(j - 1)) / 2
Else
NumberOfColumns = (duplicateArray(j) - duplicateArray(j - 1)) / 2
End If
' Find out how many rows of comments there are
commentsEnd = findFunc("rawData", i, "Number of steps in profile:", 0, "top") - 1
' Add the test name and sample name
shtmean.Cells(1, 3 * j - 2) = shtraw.Cells(1, i)
shtmean.Cells(2, 3 * j - 2) = shtraw.Cells(6, i + 1)
' Add all row of comments
l = 3
For k = 8 To commentsEnd
shtmean.Cells(l, 3 * j - 2) = shtraw.Cells(k, i)
l = l + 1
Next k
' Extract the profile name
profile = Mid(shtraw.Cells(4, i + 1).value, InStrRev(shtraw.Cells(4, i + 1).value, "Profiles\") + 9, InStrRev(shtraw.Cells(4, i + 1).value, "."))
shtmean.Cells(5, 3 * j - 2) = Mid(profile, 1, InStr(profile, ".") - 1)
' Add the time and date the test started
shtmean.Cells(6, 3 * j - 2) = Mid(shtraw.Cells(12, i).value, InStrRev(shtraw.Cells(12, i).value, "at") + 3)
' Find the last Stribeck curve
skriv = findFunc("rawData", i + 1, shtcon.Cells(9, 2), lastrow, "bottom")
' Time step or Stribeck curve
If shtcon.Cells(9, 2) = "STRIBECK" Then
' Add all Stribeckcurves
l = 8
For k = skriv + 4 To skriv + 45
meanSpeed = 0
meanTraction = 0
For m = 1 To NumberOfColumns
meanSpeed = meanSpeed + shtraw.Cells(k, i + 2 * m - 2)
meanTraction = meanTraction + shtraw.Cells(k, i + 2 * m - 1)
Next m
shtmean.Cells(l, 3 * j - 2) = meanSpeed / NumberOfColumns
shtmean.Cells(l, 3 * j - 1) = meanTraction / NumberOfColumns
l = l + 1
Next k
ElseIf shtcon.Cells(9, 2) = "BOD_TIMED" Then
l = 8
For k = skriv + 4 To skriv + 723
meanSpeed = 0
meanTraction = 0
For m = 1 To NumberOfColumns
meanSpeed = meanSpeed + shtraw.Cells(k, i + 2 * m - 2)
meanTraction = meanTraction + shtraw.Cells(k, i + 2 * m - 1)
Next m
shtmean.Cells(l, 3 * j - 2) = meanSpeed / NumberOfColumns
shtmean.Cells(l, 3 * j - 1) = meanTraction / NumberOfColumns
l = l + 1
Next k
Else
MsgBox "Skriv STRIBECK eller BOD_TIMED"
Exit Sub
End If
' Plot it
With Charts("plot")
.ChartType = xlXYScatterSmooth
.SeriesCollection.NewSeries
.SeriesCollection(j).name = shtmean.Cells(4, 3 * j - 2)
.SeriesCollection(j).XValues = range(shtmean.Cells(8, 3 * j - 2), shtmean.Cells(l - 1, 3 * j - 2))
.SeriesCollection(j).Values = range(shtmean.Cells(8, 3 * j - 1), shtmean.Cells(l - 1, 3 * j - 1))
.SeriesCollection(j).Format.Fill.Visible = msoFalse
.SeriesCollection(j).Format.Line.Visible = msoFalse
End With
j = j + 1
Next i
' Edit plot
If shtcon.Cells(9, 2) = "STRIBECK" Then
With Charts("plot")
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Speed (mm/s)"
'y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Friction coefficient"
'Scale Axis
.Axes(xlCategory).ScaleType = xlLogarithmic
.Axes(xlCategory).MinimumScale = 4.5
.Axes(xlCategory).MaximumScale = 3500
End With
ElseIf shtcon.Cells(9, 2) = "BOD_TIMED" Then
With Charts("plot")
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Time (s)"
'y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Friction coefficient"
'Scale Axis
.Axes(xlCategory).ScaleType = xlScaleLinear
.Axes(xlCategory).MinimumScale = 10
.Axes(xlCategory).MaximumScale = 7200
End With
End If
With Charts("plot")
'X axis name
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Speed (mm/s)"
'y-axis name
.Axes(xlValue, xlPrimary).HasTitle = True
.Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Friction coefficient"
'Scale Axis
.Axes(xlCategory).ScaleType = xlLogarithmic
.Axes(xlCategory).MinimumScale = 4.5
.Axes(xlCategory).MaximumScale = 3500
End With
ActiveWorkbook.Save
End Sub
Thank you very much for any input on this problem.
Best regards,
Rikard

I'm not sure that converting to arrays will help all that much.
A quick win will be to switch off calculation for the entire process:
Application.Calculation = xlCalculationManual
Don't forget to switch it back on again once you're done.
You can also switch off screen updating: Application.ScreenUpdating = False, but that doesn't improve things too much normally.
That all said, there's nothing in your VBA that can't be done directly on a worksheet with the built-in Excel formulas. That's probably best in terms of performance.

Related

Trying to store array values into cells in an excel sheet

I've been having some problems with storing some calculated values into an excel sheet in specific cells. The complete code is lengthy but I've posted it below. While running with the debugger what I've found is that it is failing when it tries to store this first value in the first step of the following for loop:
For i = 1 To 100
Cells(i, 1).Value = Cmatrix(i, 1)
Cells(i, 2).Value = Cmatrix(i, 2)
Next i
I've also tried it with ActiveSheet.Cells(i, 1).Value but I still just get a #VALUE! error during the first line of the for loop. I've also tried with and without the .Value
The Cmatrix is declared as a variant but I've also declared it as a double before just to see. It is an array from 1-100 and 1-2. I've even tried just setting it equal to 1 but the same problem arrises.
The overall code is rather lengthy but is here with the problem area being closer to the bottom:
Option Explicit
Public Function Test(check As Integer) As Integer
Dim Response As Integer
If check = 1 Then
Response = MsgBox("Boundary Condition 1 selected, is this correct (select No for boundary condition 2)?", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 1
Else
Test = 2
End If
ElseIf check = 2 Then
Response = MsgBox("Boundary Condition 2 selected, is this correct (select No for boundary condition 1)?", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 2
Else
Test = 1
End If
Else
Response = MsgBox("Incorrect Boundary Condition, select Yes for condition 1 and No for condition 2", vbYesNo, "Boundary Conditions")
If Response = 6 Then
Test = 1
Else
Test = 2
End If
End If
End Function
Public Sub Check2(x)
MsgBox ("Value given is outside data range, answer may not be correct, extrapolating from calculated polynomial")
End Sub
Public Function cubic(ByVal r As Range, x As Double, Optional check As Integer = 1) As Double
Dim data() As Double
Dim check1 As Integer
Dim Smatrix() As Double
Dim Tmatrix() As Double
Dim Xmatrix() As Double
Dim Amatrix() As Double
Dim Hmatrix() As Double
Dim Cmatrix(1 To 100, 1 To 2) As Variant
Dim m As Integer
Dim i As Integer, j As Integer
Dim step As Double
Dim chart As Range, c As Range
m = r.Rows.Count
ReDim data(1 To m, 2)
ReDim Smatrix(1 To m, 1 To m)
ReDim Tmatrix(1 To m, 4)
ReDim Xmatrix(1 To m)
ReDim Amatrix(1 To m - 1, 1 To 4)
ReDim Hmatrix(1 To m)
check1 = Test(check)
For i = 1 To m
data(i, 1) = r(i, 1).Value
data(i, 2) = r(i, 2).Value
Next i
Smatrix(1, 1) = 1
Smatrix(m, m) = 1
For i = 1 To m - 1
Hmatrix(i) = data(i + 1, 1) - data(i, 1)
Next i
If check1 = 2 Then
Smatrix(1, 2) = -1
Smatrix(m, m - 1) = -1
End If
For i = 2 To m - 1
Smatrix(i, i - 1) = Hmatrix(i - 1)
Smatrix(i, i + 1) = Hmatrix(i)
Smatrix(i, i) = 2 * (Hmatrix(i - 1) + Hmatrix(i))
Next i
For i = 2 To m - 1
Tmatrix(i, 4) = 6 * ((data(i + 1, 2) - data(i, 2)) / Hmatrix(i) - (data(i, 2) - data(i - 1, 2)) / Hmatrix(i - 1))
Next i
For i = 1 To m
If i <> 1 Then
Tmatrix(i, 1) = Smatrix(i, i - 1)
End If
Tmatrix(i, 2) = Smatrix(i, i)
If i <> m Then
Tmatrix(i, 3) = Smatrix(i, i + 1)
End If
Next i
For i = 2 To m
Tmatrix(i, 1) = Tmatrix(i, 1) / Tmatrix(i - 1, 2)
Tmatrix(i, 2) = Tmatrix(i, 2) - Tmatrix(i, 1) * Tmatrix(i - 1, 3)
Tmatrix(i, 4) = Tmatrix(i, 4) - Tmatrix(i, 1) * Tmatrix(i - 1, 4)
Next i
Xmatrix(m) = Tmatrix(m, 4) / Tmatrix(m, 2)
For i = m - 1 To 1 Step -1
Xmatrix(i) = (Tmatrix(i, 4) - Tmatrix(i, 3) * Xmatrix(i + 1)) / Tmatrix(i, 2)
Next i
For i = 1 To m - 1
Amatrix(i, 1) = (Xmatrix(i + 1) - Xmatrix(i)) / 6 * Hmatrix(i)
Amatrix(i, 2) = Xmatrix(i) / 2
Amatrix(i, 3) = (data(i + 1, 2) - data(i, 2)) / Hmatrix(i) - Hmatrix(i) * Xmatrix(i) / 2 - Hmatrix(i) * (Xmatrix(i + 1) - Xmatrix(i)) / 6
Amatrix(i, 4) = data(i, 2)
Next i
step = (data(m, 1) - data(1, 1)) / 100
For i = 0 To (m - 1)
Cmatrix(i + 1, 1) = data(1, 1) + i * step
Next i
For j = 1 To m
If Cmatrix(j, 1) = data(m, 1) Then
Cmatrix(j, 2) = data(m, 2)
Else
For i = 1 To m - 1
If data(i, 1) < Cmatrix(j, 1) And Cmatrix(j, 1) < data(i + 1, 1) Then
Cmatrix(j, 2) = Amatrix(i, 1) * (Cmatrix(j, 1) - data(i, 1)) ^ 3 + Amatrix(i, 2) * (Cmatrix(j, 1) - data(i, 1)) ^ 2 + Amatrix(i, 3) * (Cmatrix(j, 1) - data(i, 1)) + Amatrix(i, 4)
ElseIf Cmatrix(j, 1) = data(i, 1) Then
Cmatrix(j, 2) = data(i, 2)
End If
Next i
End If
Next j
If x < data(1, 1) Or x > data(m, 1) Then
Call Check2(x)
If x < data(1, 1) Then
cubic = Amatrix(1, 1) * (x - data(1, 1)) ^ 3 + Amatrix(1, 2) * (x - data(1, 1)) ^ 2 + Amatrix(1, 3) * (x - data(1, 1)) + Amatrix(1, 4)
ElseIf x > data(m, 1) Then
cubic = Amatrix(m - 1, 1) * (x - data(m - 1, 1)) ^ 3 + Amatrix(m - 1, 2) * (x - data(m - 1, 1)) ^ 2 + Amatrix(m - 1, 3) * (x - data(m - 1, 1)) + Amatrix(m - 1, 4)
End If
ElseIf x = data(m, 1) Then
cubic = data(m, 2)
Else
For i = 1 To m - 1
If data(i, 1) < x And x < data(i + 1, 1) Then
cubic = Amatrix(i, 1) * (x - data(i, 1)) ^ 3 + Amatrix(i, 2) * (x - data(i, 1)) ^ 2 + Amatrix(i, 3) * (x - data(i, 1)) + Amatrix(i, 4)
ElseIf x = data(i, 1) Then
cubic = data(i, 2)
End If
Next i
End If
For i = 1 To 100
Cells(i, 1).Value = Cmatrix(i, 1)
Cells(i, 2).Value = Cmatrix(i, 2)
Next i
Set chart = Range("A1:B100")
Dim cht As Object
Set cht = ActiveSheet.Shapes.AddChart2(XlChartType:=xlXYScatterSmooth)
cht.chart.SetSourceData Source:=chart
End Function

Optimize loop multiple variables

I have tons of data and I need to optimize this lines but i simply do not know how ...
Some lines of "x" will be black so I don't know how to use arrays without including this blank lines or how to write them without them.
x,a,b & d are variable numbers.
a = Sheets("MODULOS").Range("a1048576").End(xlUp).Row
b = Sheets("TODO").Range("a1048576").End(xlUp).Row
For x = 1 To b
Range("Z1").Select
ActiveCell.Offset(x, 0).Select
For i = 1 To (a - 1)
If ActiveCell.Value <> 0 Then
d = Sheets("AGREGADO").Range("a1048576").End(xlUp).Row
Sheets("AGREGADO").Cells(d + 1, 1).Value = Sheets("TODO").Cells(x + 1, 7).Value
Sheets("AGREGADO").Cells(d + 1, 3).Value = Sheets("TODO").Cells(x + 1, 25 + i).Value
Sheets("AGREGADO").Cells(d + 1, 2).Value = Sheets("TODO").Cells(1, 25 + i).Value
Sheets("AGREGADO").Cells(d + 1, 4).Value = Sheets("TODO").Cells(x + 1, 33 + a).Value
End If
ActiveCell.Offset(0, 1).Select
Next i
Next x
There are a few way to make your code faster:
Summary (ranked by importance):
dis-activate Automatic Calculation and screen updating (as in the
comment from Tomjohnriddle)
Avoid the .Select and ActiveCell
Use WITH where possible when working with objects
In your code it would look like this:
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Dim ra As Range
a = Sheets("MODULOS").Range("a1048576").End(xlUp).Row
b = Sheets("TODO").Range("a1048576").End(xlUp).Row
For x = 1 To b
ra = Cells(1 + x, 26)
With Sheets("AGREGADO")
For i = 1 To (a - 1)
If ra.Value <> 0 Then
d = Sheets("AGREGADO").Range("a1048576").End(xlUp).Row
.Cells(d + 1, 1).Value = Sheets("TODO").Cells(x + 1, 7).Value
.Cells(d + 1, 3).Value = Sheets("TODO").Cells(x + 1, 25 + i).Value
.Cells(d + 1, 2).Value = Sheets("TODO").Cells(1, 25 + i).Value
.Cells(d + 1, 4).Value = Sheets("TODO").Cells(x + 1, 33 + a).Value
End If
ra = Cells(1 + x, 26 + 1)
Next i
Next x
End With
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

Consolidating values on an unevenly spaced spreadsheet Excel VBA

Writing rudimentary VBA to populate a 2 dimensional array filled with two sums one consisting of the odd columns the other is the sum of the even columns, totaled over a variable amount of rows stored in another array. the two dimensional array then prints on a seperate worksheet. I wrote code which succesfully completed this task on two other worksheets in the same file with slightly different sized arrays, but it populates the destination range with zeros when adjusted for the new input and output.
code in question:
Sub dad()
Dim i As Integer, j As Integer, units As Double, value As Double, mr(1 To 655, 1 To 3) As Double, u As Integer, here As Range
Dim thisone As String, there As Range
thisone = Worksheets("MB52 for 1010").Cells(1, 1).Address
Set here = Range(thisone)
MsgBox (here(1, 1).Address)
thisone = Worksheets("1010totals").Cells(1, 1).Address
Set there = Range(thisone)
MsgBox (there(1, 1).Address)
For i = 1 To 655
mr(i, 1) = Worksheets("1010totals").Cells(i + 1, 4).value
Next i
MsgBox ("array made")
i = 1
u = 1
MsgBox (i & " " & u)
For i = 1 To 655
For j = 1 To mr(i, 1)
u = u + 1
units = here(u, 6) + here(u, 9) + here(u, 11).value + here(u, 13) + here(u, 15) + here(u, 17)
value = here(u, 8) + here(u, 10) + here(u, 12).value + here(u, 14) + here(u, 16) + here(u, 18)
Next j
mr(i, 2) = units
mr(i, 3) = value
Next i
For i = 1 To 655
For j = 2 To 3
Worksheets("1010totals").Cells(i + 1, j).value = mr(i, j)
Next j
Next i
End Sub
Original code that works on the other worksheets:
Sub ded()
Dim i As Integer, j As Integer, units As Double, value As Double, n As Integer, mr(1 To 756, 1 To 3) As Double, u As Integer, here As Range
Dim thisone As String, there As Range
thisone = Worksheets("MB52 for 1030").Cells(1, 1).Address
Set here = Range(thisone)
MsgBox (here(1, 1).Address)
thisone = Worksheets("1030totals").Cells(1, 1).Address
Set there = Range(thisone)
MsgBox (there(1, 1).Address)
For i = 1 To 756
mr(i, 1) = Worksheets("1030totals").Cells(i + 1, 4).value
Next i
MsgBox ("array made")
i = 1
u = 1
MsgBox (i & " " & u)
For i = 1 To 756
For j = 1 To mr(i, 1)
u = u + 1
units = here(u, 6) + here(u, 9) + here(u, 11).value + here(u, 13) + here(u, 15) + here(u, 17)
value = here(u, 8) + here(u, 10) + here(u, 12).value + here(u, 14) + here(u, 16) + here(u, 18)
Next j
mr(i, 2) = units
mr(i, 3) = value
Next i
For i = 1 To 756
For j = 2 To 3
Worksheets("1030totals").Cells(i + 1, j).value = mr(i, j)
Next j
Next i
End Sub

Listbox selected values paste to worksheet

i=19
With ListBox1
'clearing previous values from sheet
range(Cells(i + 2, 1).Address & ":" & Cells(endRwow, 7).Address).ClearContents
ListBoxArrSelected = vbNullString
For y = 0 To .ListCount - 1
If .Selected(y) Then
' concatenate all selected strings
ListBoxArrSelected = ListBoxArrSelected & "~" & ListBox1.List(y)
End If
Next y
' fill array with concatenated all selected strings spliting to rows
ListBoxArrSplitToRows = Split(ListBoxArrSelected, "~")
For UR = 1 To UBound(ListBoxArrSplitToRows, 1) + 1
' fill array with concatenated all selected strings spliting to colomuns
ListBoxArrSplitToCell = Split(ListBoxArrSplitToRows(UR - 1), "·")
For URc = 1 To UBound(ListBoxArrSplitToCell, 1) + 1
'paste to sheet
Cells(i + UR, 1).value = timeStr
Cells(i + UR, URc + 1).value = ListBoxArrSplitToCell(URc - 1)
Next URc
Next UR
End With
Then in listbox selected > 100 field excel responds very slow to copy them to worksheet
How to speed up this code?
You can reduce the number of cell writes using something like this:
i = 19
With ListBox1
Range(Cells(i + 2, 1), Cells(endRwow, 7)).ClearContents
ListBoxArrSelected = vbNullString
For y = 0 To .ListCount - 1
If .Selected(y) Then
ListBoxArrSelected = ListBoxArrSelected & "~" & ListBox1.List(y)
End If
Next y
ListBoxArrSplitToRows = Split(ListBoxArrSelected, "~")
Cells(i + 1, 1).Resize(UBound(ListBoxArrSplitToRows, 1) + 1).Value = timeStr
For UR = 1 To UBound(ListBoxArrSplitToRows, 1) + 1
ListBoxArrSplitToCell = Split(ListBoxArrSplitToRows(UR - 1), "·")
Cells(i + UR, 2).Resize(, UBound(ListBoxArrSplitToCell, 1) + 1).Value = ListBoxArrSplitToCell
Next UR
End With
If you have the same number of delimited items in each row of the listbox, you could create an array of arrays and then output that to the sheet in one write operation. Code would be something like this:
Dim ListBoxArrSplitToRows()
Dim counter As Long
Dim columnCount As Long
i = 19
Range(Cells(i + 2, 1), Cells(endRwow, 7)).ClearContents
With ListBox1
ReDim ListBoxArrSplitToRows(.ListCount - 1)
For y = 1 To .ListCount
If .Selected(y - 1) Then
' load subarray into array
ListBoxArrSplitToRows(counter) = Split(.List(y - 1), "·")
counter = counter + 1
End If
Next y
End With
' resize array to used extent
ReDim Preserve ListBoxArrSplitToRows(counter - 1)
' get column count using first subarray
columnCount = UBound(ListBoxArrSplitToRows(0)) + 1
Cells(i + 1, "B").Resize(counter, columnCount).Value = Application.Index(ListBoxArrSplitToRows, 0, 0)
or just Cells(i + 1, "B").Resize(counter, columnCount).Value = ListBoxArrSplitToRows

VBA code, run time error 9 subscript out of range

can someone help me to understand why i get a runtime error 9 (subscript out of range) from my code?
Dim prod(1 To 6) As String
prod(1) = "001"
prod(2) = "002"
prod(3) = "003"
prod(4) = "004"
prod(5) = "005"
prod(6) = "006"
Dim sum(1 To 6) As Double
For i = 1 to 6 Step 1
sum(i) = 0
Next i
Dim sumA(1 To 12) As Double
For i = 1 To 12 Step 1
sumA(i) = 0
Next i
Sheets("Punching").Activate
LR = Cells(Rows.Count, "G").End(xlUp).Row
For i = 4 To LR Step 1
For j = 1 To UBound(prod) Step 1
If Cells(i, 11) = prod(j) Then
sum(j) = sum(j) + Cells(i, 18).Value
Else
sum(j) = sum(j)
End If
Next j
Next i
For k = 4 To LR Step 1
For l = 1 To UBound(sumA) Step 2
**If Cells(k, 11) = prod(l) Then**
sumA(l) = sumA(l) + Cells(k, 19).Value
sumA(l + 1) = sumA(l + 1) + Cells(k, 20).Value
Else
sum(l) = sum(l)
End If
Next l
Next k
The error line is the asterix line.
Is it because i cannot reuse the array of prod? I dont get it why i get this error.
Any help will be appreciated!

Resources