Running the following code in VBA to call excel cells in an array and use it in FOR loop for calculation but getting "Subscript out of Range" error
Sub nestedLoopFor()
Dim i As Integer
Dim j As Integer
Dim Qty As Variant
Dim Cap As Variant
Qty = Range("C2:L2").Value 'call cells from 3rd row
Cap = Range("B3:B7").Value 'call cells from 2nd column
For i = 1 To 5
For j = 1 To 10
Cells(i + 2, j + 2).Value = WorksheetFunction.Min(Qty(j), Cap(i))
Qty(j) = Qty(j) - Cells(i + 2, j + 2).Value
Cap(i) = Cap(i) - Cells(i + 2, j + 2).Value
Next
Next
End Sub
FYI Qty and Cap are 2-D arrays, so you need to provide both indexes if you want to access an element in one of them.
Cap(i, 1)
Qty(1, j)
Related
I have a problem with the function CountIF when used with decimals.
Below the code I have:
Sub Compair()
Dim I As Double
Row = 3
For I = 139.5 To 141.5 Step 0.25
Cells(Row, 3) = I
Cells(Row, 4) = Application.WorksheetFunction.CountIf(Range("A:A"), "<" & Cells(Row, 3))
Row = Row + 1
Next I
End Sub
And below the output:
It seems that the code functions good when it is compairing integer value and not with decimals.
PS: I do not want to loop on column A cells, as there could be more than 100k values and it will be so slowly
You can pull everything into variant arrays, which will be quicker on larger datasets than COUNTIFS:
Sub Compair()
With ActiveSheet
Dim rngArr As Variant
rngArr = Intersect(.UsedRange, .Range("A2", .Cells(.Rows.Count, 1))).Value2
Dim outArr() As Variant
ReDim outArr(1 To Int((141.5 - 139.5) / 0.25) + 1, 1 To 2)
Dim I As Double
Row = 1
For I = 139.5 To 141.5 Step 0.25
outArr(Row, 1) = I
outArr(Row, 2) = 0
Dim j As Long
For j = 1 To UBound(rngArr, 1)
If rngArr(j, 1) < I Then outArr(Row, 2) = outArr(Row, 2) + 1
Next j
Row = Row + 1
Next I
.Range("C3").Resize(UBound(outArr, 1), 2).Value = outArr
End With
End Sub
Your code is correct
just confirm your region, if you need the comas as decimal separatos configure your Windows format, and your excel format
Windows Format
https://www.windowscentral.com/how-change-date-and-time-formats-windows-10
Excel Format
https://edu.gcfglobal.org/en/excel2013/formatting-cells/1/
Sub Compair()
Range("A16").Select
Dim I As Double
Row = 16
For I = 139.5 To 141.5 Step 0.25
Cells(Row, 3) = I
Cells(Row, 4) = Application.WorksheetFunction.CountIf(Range("A:A"), "<" & Cells(Row, 3))
Row = Row + 1
Next I
End Sub
Given three columns ID, S/E, and Date (there are two rows for each ID) we want to Split the Date column into two columns Start and End based on Matching ID and S/E.
I have tried a couple of options.
Approach 1
So, far I was doing it by using a table:
Column Start:
=IF([#[S/E]]="Start",[#[Date]],"")
Column End:
=IF([#[S/E]]="End",[#[Date]],"")
I would like for the Date under Start and End column to show on every row.
Like:
Then Add a column that calculates the difference between the dates:
Function TestDates(pDate1 As Date, pDate2 As Date) As Long
TestDates = DateDiff("d", pDate1, pDate2)
End Function
Column DateFif
=ABS(TestDates([#[End]],[#[Start]]))
Approach 2
I have also tried the following Macro
Sub ConcatenateCellsIfSameValues()
Dim xCol As New Collection
Dim xSrc As Variant
Dim xRes() As Variant
Dim I As Long
Dim J As Long
Dim xRg As Range
xSrc = Range("A1", Cells(Rows.Count, "A").End(xlUp)).Resize(, 2)
Set xRg = Range("D1")
On Error Resume Next
For I = 2 To UBound(xSrc)
xCol.Add xSrc(I, 1), TypeName(xSrc(I, 1)) & CStr(xSrc(I, 1))
Next I
On Error GoTo 0
ReDim xRes(1 To xCol.Count + 1, 1 To 2)
xRes(1, 1) = "No"
xRes(1, 2) = "Combined Date"
For I = 1 To xCol.Count
xRes(I + 1, 1) = xCol(I)
For J = 2 To UBound(xSrc)
If xSrc(J, 1) = xRes(I + 1, 1) Then
xRes(I + 1, 2) = xRes(I + 1, 2) & ", " & xSrc(J, 2)
End If
Next J
xRes(I + 1, 2) = Mid(xRes(I + 1, 2), 2)
Next I
Set xRg = xRg.Resize(UBound(xRes, 1), UBound(xRes, 2))
xRg.NumberFormat = "#"
xRg = xRes
xRg.EntireColumn.AutoFit
End Sub
Which could be a good start but not sure how to tune for this goal
THANKS and ANY help is appreciated it!
(Even better if the macro is for a table)
Use SUMIFS()
Start:
=SUMIFS([Date],[S/E],"Start",[Trade Id],[#Trade Id])
End:
=SUMIFS([Date],[S/E],"End",[Trade Id],[#Trade Id])
For the date diff, no need for vba:
=INT(ABS([#End]-[#Start]))
I am trying to fill a series from a higher number in cell G2 (e.g "512") down to a lower number in Cell H2 (e.g "500"). I need the VBA code to run in Column J, producing the following this series as an example 512, 511, 510, 509, 508 ... down the column.
Here's a screenshot that describes what I need
Most examples I've found seems to be built for an increasing series (512, 513, 514....)
Any help to get this right will be helpful
For a VBA general solution, try this
Sub CreateSequence(StartValue As Long, EndValue As Long, OutputStart As Range, Optional ByVal StepBy As Long = 1)
Dim NumValues As Long
Dim dat As Variant
Dim i As Long
StepBy = Abs(StepBy)
If StepBy <= 0 Then Exit Sub
NumValues = Abs(StartValue - EndValue) \ StepBy + 1
ReDim dat(1 To NumValues, 1 To 1)
For i = 0 To NumValues - 1
dat(i + 1, 1) = StartValue + i * IIf(StartValue > EndValue, -StepBy, StepBy)
Next
OutputStart.Resize(UBound(dat, 1), 1).Value = dat
End Sub
Use it like this
Sub Demo()
CreateSequence Range("G2").Value, Range("H2").Value, Range("K2")
End Sub
A formula solution (Excel version 365)
=SEQUENCE(G2-H2+1,1,G2,-1)
hlRange = Sheets(2).Cells(2, 7).Value - Sheets(2).Cells(2, 8).Value + 1
' Fill series from max to min value
For j = 1 To hlRange
Sheets(2).Cells(j + 1, 10).Value = Sheets(2).Cells(2, 7).Value - j + 1
Next j
You can use the following code, it lets you add a a values to specify the steps you want to have.
https://i.stack.imgur.com/vSan5.jpg
Sub createNumList()
Dim i As Integer
Dim count As Integer
Dim cellValue As Integer
count = (ActiveSheet.Cells(2, 1).Value - ActiveSheet.Cells(2, 2).Value) / ActiveSheet.Cells(2, 3).Value
For i = 1 To count + 1
If i = 1 Then
ActiveSheet.Cells(i + 2, 5).Value = ActiveSheet.Cells(2, 1).Value
Else
ActiveSheet.Cells(i + 2, 5).Value = ActiveSheet.Cells(i + 1, 5).Value - ActiveSheet.Cells(2, 3).Value
End If
Next i
End Sub
I have an Excel formula that operates on a pre-existing range of data.
The Excel formula is: =STDEV.S(IF(FREQUENCY(range,range),range)) , where "range" is the aforementioned range of data.
My goal is to convert this formula into VBA code.
The following code is my attempt at trying to convert the formula into VBA, as well as my visualization of the process to try and understand why it is not putting out the same result:
Private Sub CommandButton1_Click()
Dim diffArray() As Variant
Dim i As Integer
Dim x As Integer
Dim array1() As Variant, size As Integer, j As Integer
Dim freqArray1() As Variant
Dim freqArray2() As Variant, size2 As Integer, j2 As Integer
'assigns the data values to array1
size = 0
j = 0
ReDim array1(size)
For i = 3 To 15
size = size + 1
ReDim Preserve array1(size)
array1(j) = Cells(i, 2)
j = j + 1
Next i
Cells(20, 2).Value = UBound(array1)
Cells(21, 2).Value = LBound(array1)
If UBound(array1) > 1 Then Cells(19, 2).Value = WorksheetFunction.StDev_S(array1)
'setting freqArray1 to frequency(array1, array1)
freqArray1 = WorksheetFunction.Frequency(array1, array1)
Cells(20, 3).Value = UBound(freqArray1)
Cells(21, 3).Value = LBound(freqArray1)
For i = LBound(freqArray1) To (UBound(freqArray1))
Cells(2 + LBound(freqArray1) + i, 3).Value = freqArray1(i, 1)
Next i
If UBound(freqArray1) > 1 Then Cells(19, 3).Value = WorksheetFunction.StDev_S(freqArray1)
'setting freqArray2 to if(frequency(array1, array1), array1)
size2 = 0
j2 = 0
ReDim freqArray2(size2)
For i = LBound(freqArray1) To (UBound(freqArray1))
If freqArray1(i, 1) Then
size2 = size2 + 1
ReDim Preserve freqArray2(size2)
freqArray2(j2) = freqArray1(i, 1)
j2 = j2 + 1
End If
Next i
Cells(20, 4).Value = UBound(freqArray2)
Cells(21, 4).Value = LBound(freqArray2)
For i = (LBound(freqArray2)) To UBound(freqArray2)
Cells(2 + LBound(freqArray2) + i, 4).Value = freqArray2(i)
Next i
'takes the standard deviation of if(frequency(array1, array1), array1)
If UBound(freqArray2) > 1 Then Cells(19, 4).Value = WorksheetFunction.StDev_S(freqArray2)
End Sub
The data values being operated on are in the orange cells column B(array1).
The array 'frequency(array1, array1)' is in the yellow cells column C.
The array 'if(frequency(array1, array1), array1)' is in the green cells column D.
The goal is for the values in the two blue cells(B18 and D19) to be the same.
I don't understand two things:
Why are the values in the blue cells(B18 and D19) not the same?
Why do the indices of the arrays change?
One starts at '0', the next starts at '1', and the last starts at '-1'?
use a dictionary to create a unique list and use that in the StDev_S
Private Sub CommandButton1_Click()
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim rngArray As Variant
rngArray = ActiveSheet.Range("B3:B15")
Dim i As Long
For i = LBound(rngArray, 1) To UBound(rngArray, 1)
On Error Resume Next
dict.Add rngArray(i, 1), rngArray(i, 1)
On Error Resume Next
Next i
If dict.Count > 0 Then
Dim unqArr As Variant
ReDim unqArr(1 To dict.Count) As Variant
i = 1
Dim key As Variant
For Each key In dict.Keys
unqArr(i) = key
i = i + 1
Next key
ActiveSheet.Cells(19, 4).Value = Application.WorksheetFunction.StDev_S(unqArr)
End If
End Sub
In My office five Employee is working for example In my office Employ Entry Exit sheet is dere..
This is Main Sheet
Now my requirement
category wise data copy to this sheet to other sheet but it's do it automatically
Like Example
enter image description here
I hope I am interpreting your question correctly, but please let me know if I have misinterpreted your request.
Try the following code on your sheet:
Sub AutoCopyByName()
Dim Names() As String
Dim i As Long, NumRows As Long, NameRow() As Long
Dim j As Integer, NumNames As Integer
j = 0
NumSites = 0
'''''''''''''''''''''''''''''''''''''''''''
'''COUNT NUMBER OF ROWS WITH INFORMATION'''
'''''''''''''''''''''''''''''''''''''''''''
i = 2 'Standard Counter (counts all non-blank cells)
NumRows = 1 'Number of rows with information
Do While WorksheetFunction.IsText(Sheets("data").Range("A" & i))
If Sheets("data").Range("A" & i) <> " " Then NumRows = NumRows + 1
i = i + 1
Loop
'''''''''''''''''''''''''''
'''COUNT NUMBER OF NAMES'''
'''''''''''''''''''''''''''
For i = 3 To NumRows + 1
If Sheets("data").Cells(i, 1) <> Sheets("data").Cells(i - 1, 1) Then NumNames = NumNames + 1 'Works
Next i
''''''''''''''''''
'''REDIM ARRAYS'''
''''''''''''''''''
ReDim Names(NumNames)
ReDim NameRow(NumNames)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'''FINDING THE LOCATION OF EACH NAME IN THE SHEET AND STORING IT IN NameRow ARRAY'''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
For i = 2 To NumRows + 1
If Sheets("data").Cells(i, 1) <> Sheets("data").Cells(i - 1, 1) Then
Names(j) = Sheets("data").Cells(i, 1).Value
NameRow(j) = i
j = j + 1
End If
Next i
'''''''''''''''''''''''''''''''''''''''''
'''COPY ENTRIES PER NAME TO EACH SHEET'''
'''''''''''''''''''''''''''''''''''''''''
For i = 0 To NumNames - 1
Worksheets.Add
Worksheets(1).Name = Names(i)
Worksheets("data").Rows(1).Copy
Worksheets(Names(i)).Paste
Worksheets("data").Activate
Worksheets("data").Range(Cells(NameRow(i), 1), Cells(NameRow(i + 1) - 1, 1)).EntireRow.Copy
Worksheets(Names(i)).Activate
Worksheets(Names(i)).Range("A2").Select
Worksheets(Names(i)).Paste
Next i
End Sub
I've used the following as my input sheet