Real-Statistics Excel Add-on LJUNG formula - excel

I'm using LJUNG formula from the Real-Statistics add-on. The issue is that the formula uses the empty cells in its calculation. Can anyone advise how to exclude empty cells?
=LJUNG(AXW3:AXW377)
The result for this is 0.000
While the manual highlight of the data specific array =LJUNG(AXW280:AXW340), provides the result of: 0.152.

A brilliant answer provided by Jeremy Hodge
Sub test(sht As Worksheet)
Dim c As Integer
Dim startCell As Range
Dim endCell As Range
Dim lastRow As Integer
lastRow = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Offset(1, 0).Row
For c = 1 To Range("XFD1").End(xlToLeft).Column
If IsEmpty(sht.Cells(2, c).Value) = False Then
Set startCell = sht.Cells(2, c)
Else
Set startCell = sht.Cells(1, c).End(xlDown)
End If
Set endCell = sht.Cells(1048576, c).End(xlUp)
sht.Cells(lastRow, c).Formula = "=AVERAGE(" & startCell.Address & ":" & endCell.Address & ")"
Next c
End Sub

Related

Find the last filled row in a filtered column without dropping the Autofilter

How do I get the position of the last non-empty cell in a filtered column without dropping the applied Autofilter? I understand it's easy to get the number of the last visible row with
Dim ws as Worksheet, rng As Range
Set rng = Range(Letter & 1 & ":" & Letter & 1) ' where Letter is the letter code of the column
GetLastVisibleRow = ws.Range(Split(ws.Cells(, rng.Column).Address, "$")(1) & ws.Rows.count).End(xlUp).row
but I need the number of the last filled row instead. At the same time, I'd like to avoid setting
ws.AutoFilterMode = False
if it's possible.
Thanks in advance.
Probably not the most efficient or fastest method, but this appears to work:
Function GetLastCellOfColumn(ColLetter As String) As Range
Dim Col As Range
Dim Rw As Long
Set Col = Range(ColLetter & ":" & ColLetter)
Set GetLastCellOfColumn = Intersect(ActiveSheet.UsedRange, Col)
For Rw = GetLastCellOfColumn.Cells.Count To 1 Step -1
If Len(GetLastCellOfColumn.Cells(Rw).Value) > 0 Then
Set GetLastCellOfColumn = GetLastCellOfColumn.Cells(Rw)
Exit Function
End If
Next
End Function
A charming solution by #jkpieterse plus a useful comment by #BigBen is exactly what I was looking for. Just to finalize the thread, the function returning the row number is
Function GetLastFilledCellOfColumn(ws As Worksheet, ColLetter As String) As Long
Dim Col As Range, Urng As Range, Rw As Long
Set Col = ws.Range(ColLetter & ":" & ColLetter)
Set Urng = Intersect(ws.UsedRange, Col)
For Rw = Urng.Cells.count To 1 Step -1
If Not IsEmpty(Urng.Cells(Rw)) Then
GetLastFilledCellOfColumn = Rw
Exit Function
End If
Next
End Function
Problem solved.
So maybe this is an alternative way to look into:
Sub Test()
Dim rng As Range
Dim col As Long: col = 2 'Change to whichever column you interested in
Dim rw as Long
With Sheet1 'Change to whichever sheets CodeName you need
Set rng = .Range("_FilterDatabase").Columns(col)
rw = .Evaluate("MAX(IF(" & rng.Address & "<>"""",ROW(" & rng.Address & ")))")
End With
End Sub
I'm afraid I rushed this a little and might have made a mistake but will have to get going. Hopefully you understand whats going on =)
Edit:
The above would definately work, but as figured out through the chat, there is actually a ListObject involved, called Table1, which throws of the AutoFilter range. So here are two alternative ways of doing the same thing:
Sub Test()
Dim rng As Range
Dim col As Long: col = 2 'Change to whichever column you interested in
Dim rw as Long
With Sheet1 'Change to whichever sheets CodeName you need
Set rng = .Range("Table1")
rw = .Evaluate("MAX(IF(" & rng.Address & "<>"""",ROW(" & rng.Address & ")))")
End With
End Sub
Or, when you don't know the name of the table:
Sub Test()
Dim rng As Range
Dim col As Long: col = 2 'Change to whichever column you interested in
Dim rw as Long
With Sheet1 'Change to whichever sheets CodeName you need
Set rng = .ListObjects(1).Range
rw = .Evaluate("MAX(IF(" & rng.Address & "<>"""",ROW(" & rng.Address & ")))")
End With
End Sub

want to convert Excel formula into VBA code

I wanted to convert below formula to VBA code.
=C1&"`"&K1&"`"&L1&"`"&J1
=VLOOKUP(M1,Data!$A:$J,9,)
=SUMPRODUCT(SUMIF(B1:B,B1,G1:G))
Currently i have enter this formula in 1st row and than copying this formula till the last row used which is taking lot time to apply formula because it has more than million row.
LR1 = Sheets("CRIMS").UsedRange.Rows.Count
Sheets("CRIMS").Range("M1:P1").AutoFill Destination:=Sheets("CRIMS").Range("M1:P" & LR1)
is there any way to convert this formula into VBA code?
For first formula the easiest way would be:
Range("M" & i).FormulaR1C1 = "=RC[-10]&""`""&K&""`""&L&""`""&J"
But for vlookup I prefer dictionaries/collections! It is much much faster.
If You have source data in Data sheet and You want to put that to CRIMS sheet to column M:
Sub vlookup()
Dim names As Range, values As Range
Dim lookupNames As Range, lookupValues As Range
Dim vlookupCol As Object
Dim lastRow As Long
Dim lastRow2 As Long
Dim objekt as Object
With Sheets("Data")
lastRow = Sheets("Data").Cells(Rows.Count, 1).End(xlUp).row
Set names = Sheets("Data").Range("A1:A" & lastRow)
Set values = Sheets("Data").Range("I1:A" & lastRow)
End With
Set objekt = BuildLookupCollection(names, values)
With Sheets("CRIMS")
lastRow2 = 1000000
Set lookupNames = .Range("M1:M" & lastRow)
Set lookupValues = .Range("N1:N" & lastRow)
End With
VLookupValues lookupNames, lookupValues, objekt
Set objekt = Nothing
End Sub
Function BuildLookupCollection(categories As Range, values As Range)
Dim vlookupCol As Object, i As Long
Set vlookupCol = CreateObject("Scripting.Dictionary")
On Error Resume Next
For i = 1 To categories.Rows.Count
Call vlookupCol.Add(CStr(categories(i)), values(i))
Next i
On Error GoTo 0
Set BuildLookupCollection = vlookupCol
End Function
Sub VLookupValues(lookupCategory As Range, lookupValues As Range, vlookupCol As Object)
Dim i As Long, resArr() As Variant
ReDim resArr(lookupCategory.Rows.Count, 1)
For i = 1 To lookupCategory.Rows.Count
resArr(i - 1, 0) = vlookupCol.Item(CStr(lookupCategory(i)))
Next i
lookupValues = resArr
End Sub
Quotation Marks need to be doubled in VBA
Try this:
For i = 1 To LR1
Range("M" & i).Formula = "=C" & i & "&""`""&K" & i & "&""`""&L" & i & "&""`""&J" & i
Range("N" & i).Formula = "=VLOOKUP(M" & i & ",Data!$A:$J,9,)"
Next i
(replace column letters with actual target column)
As mentioned in the comments Looping in this case is highly inefficient.
Use this Code to insert the formulas all at once. It still takes some time for 1 Milion rows though.
Range("M1:M" & LR1).Formula = "=C:C & ""`"" & K:K & ""`"" & L:L & ""`"" & J:J"
Range("N1:N" & LR1).Formula = "=VLOOKUP(M:M,Data!$A:$J,9,)"

Search cell for matching value then copy

I would like to filter my Excel table with VBA code.
A1, B1, C1 are titles
Column A = All (A2: xx)
Column B = Search Content`s (B2: xx)
Column C = (C2: xx)
Everything in column B should be searched for column A and if one or more is found then column C should be written.
I tried the following.
Sheets("Tabelle2").Range("A2:A2000").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range("B2:B2000"), CopyToRange:=Range("C2:C2000")
So that everything in column A is copied to column C but not to be compared to column B.
How can I make this work?
I suggest you to use a helping column, then you can easily do that without VBA coding.
Helping column formula:
=IF(ISERROR(MATCH(A2,$B$2:$B$9,0)),ROW(),"")
Then use following formula to extract not backuped servers list.
=IFERROR(INDEX($A$2:$A$31,SMALL($D$2:$D$31,ROW(1:1))),"")
See the file
You have to include Title.
Sub test()
Dim rngDB As Range
Dim rngCria As Range
Dim rngTo As Range
Dim Ws As Worksheet
Set Ws = Sheets("Tabelle2")
With Ws
Set rngDB = .Range("a1:a2000")
Set rngCria = .Range("B1", .Range("b" & Rows.Count).End(xlUp))
Set rngTo = .Range("c1")
End With
rngDB.AdvancedFilter xlFilterCopy, rngCria, rngTo
End Sub
Option Explicit
Sub ListMatches()
Dim rngColumnA As Range, celColumnB As Range, rngColumnB As Range
Set rngColumnA = Range("A2:A" & Range("A1000000").End(xlUp).Row)
Set rngColumnB = Range("B2:B" & Range("B1000000").End(xlUp).Row)
For Each celColumnB In rngColumnB
If Not rngColumnA.Find(What:=celColumnB) Is Nothing Then Range("C" & Range("C1000000").End(xlUp).Row + 1) = celColumnB.Value
Next celColumnB
End Sub
Using A Collection might be even faster in your application:
Sub ListMatches()
Dim R1 As Range, R2 As Range, R As Range, Nc As New Collection
Set R1 = Range("A2:A" & Range("A" & Rows.Count).End(xlUp).Row)
Set R2 = Range("B2:B" & Range("B" & Rows.Count).End(xlUp).Row)
On Error Resume Next
For Each R In R1
Nc.Add R.Value, R.Value
Next R
For Each R In R2
Err = 0
Nc.Add R.Value, R.Value, 1
If Err = 0 Then
Range("C" & Range("C" & Rows.Count).End(xlUp).Row + 1) = R.Value
Nc.Remove 1
End If
Next R
On Error GoTo 0
End Sub

Excel VBA offset function

I have an Excel file with information in column A and column B. Since these columns could vary in the number of rows I would like to use the function offset so that I could print the formula in one time as an array rather than looping over the formula per cell (the dataset contains almost 1 million datapoints).
My code is actually working the way I want it to be I only can't figure out how to print the code in Range(D1:D5). The outcome is now printed in Range(D1:H1). Anybody familiar how to use this offset within a for statement?
Sub checkOffset()
Dim example As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Set example = Range("A1:A1")
For i = 1 To LastRow
example.Offset(0, i + 2).Formula = "=SUM(A" & i & ":B" & i & ")"
Next i
End Sub
Using the Offset(Row, Column), you want to offset with the increment of row (i -1), and 3 columns to the right (from column "A" to column "D")
Try the modified code below:
Set example = Range("A1")
For i = 1 To LastRow
example.Offset(i - 1, 3).Formula = "=SUM(A" & i & ":B" & i & ")"
Next i
One way of outputting the formula in one step, without looping, to the entire range, is to use the R1C1 notation:
Edit: Code modified to properly qualify worksheet references
Option Explicit
Sub checkOffset()
Dim example As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
With sht
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Set example = .Range(.Cells(1, 1), .Cells(LastRow, 1))
End With
example.Offset(columnoffset:=3).FormulaR1C1 = "=sum(rc[-3],rc[-2])"
End Sub
You don't need to use VBA for this. Simply type =sum(A1:B1) in cell D1 and then fill it down.
If you're going to use VBA anyway, use this:
Sub checkOffset()
Dim example As Range
Dim sht As Worksheet
Dim LastRow As Long
Set sht = ThisWorkbook.Worksheets("Sheet1")
LastRow = sht.Cells(sht.Rows.Count, "A").End(xlUp).Row
Set example = Range("A1:A1")
For i = 1 To LastRow
example.Offset(i - 1, 3).Formula = "=SUM(A" & i & ":B" & i & ")"
Next i
End Sub
The way offset works is with row offset, column offset. You want the column to always be fixed at 3 to the right.

IF statement including VLOOKUP

Looking for a way to do an IF cell says (this) then VLOOKUP here, IF cell says (thiselse) then VLOOKUP different area.
Might be a super obvious way to do this, so far have this:
Pretty simple but not working
Sub categoryVLOOKUP()
'IF col D says STAR then enter VLOOKUP formula into column K
'IF col D says SUN then enter other VLOOKUP formula into column K
Dim lRow As Long, lCol As Long
Dim lRow2 As Long
Dim sht As Worksheet
Set sht = ThisWorkbook.Worksheets("STARSUN")
For lRow = 2 To LastRow
If sht.Cells(lRow, 4) = "SUN" Then
sht.Cells(lRow, 10).Formula = _
"=VLOOKUP(A3&G3,OF_MOON!A:D, 4,0)"
Else
End If
If sht.Cells(lRow, 4) = "STAR" Then
sht.Cells(lRow, 10).Formula = _
"=VLOOKUP(A3&G3,OFWORLD!A:D, 4,0)"
Else
End If
Next lRow
End Sub
If it is getting the formula for multiple cells that is the struggle, I would recommend R1C1 formatting:
Sub categoryVLOOKUP()
'IF col D says STAR then enter VLOOKUP formula into column K
'IF col D says SUN then enter other VLOOKUP formula into column K
Dim lRow As Long, lCol As Long
Dim lRow2 As Long
Dim sht As Worksheet
Dim LastRow as long
LastRow = Cells(Rows.Count, "D").End(xlUp).Row
Set sht = ThisWorkbook.Worksheets("STARSUN")
For lRow = 2 To LastRow
If sht.Cells(lRow, 4) = "SUN" Then
sht.Cells(lRow, 10).FormulaR1C1 = _
"=VLOOKUP(R[1]C[-8]&R[1]C[-1],OF_MOON!RC:RC[3], 4,0)"
ElseIf
If sht.Cells(lRow, 4) = "STAR" Then
sht.Cells(lRow, 10).FormulaR1C1 = _
"=VLOOKUP(R[1]C[-8]&R[1]C[-1],OFWORLD!RC:RC[3], 4,0)"
End If
Next lRow
End Sub
I think this train of thought should get you started. Remember that R1C1 has to be done in reference to the active cell that the formula will go in. I may need to check the rules for referring to new sheets but again, this should get you on the right line :) hope it helps
EDIT : Also, I believe you do need to set LastRow
I have added to the code
Dim LastRow as long
and
LastRow = Cells(Rows.Count, "D").End(xlUp).Row
Looks like you are missing definition and value of LastRow.
Use option explicit at the beginning of your modules to enforce variable declaration. Or simply Tools -> Options -> check Require Variable Declaration. It will be done automatically.
Also I do not understand why you would even use VBA for this. Can't you just use formula
=IF(cell="SUN",1st vlookup, if(cell="STAR", 2nd vlookup,NA())
Also I suggest using INDEX + MATCH instead of VLOOKUP.
And 3rd "also": you are hardcoding the key you will be looking up for: A3&G3. Thus You will get max of 3 values from your actions: Whatever is associated with A3&G3 in OF_MOON sheet or in OFWORLD sheet or #N/A.
Another way to get the result as below
Sub categoryVLOOKUP()
Dim lRow As Long, lCol As Long
Dim lRow2 As Long
Dim sht As Worksheet
LastRow = Range("D" & Rows.Count).End(xlUp).Row
Set sht = ThisWorkbook.Worksheets("STARSUN")
For lRow = 2 To LastRow
If sht.Cells(lRow, 4) = "SUN" Then
Range("K" & lRow).Value = Application.WorksheetFunction.VLookup(Range("A" & lRow) & Range("G" & lRow), Worksheets("OF_MOON").Range("A:D"), 4, 0)
ElseIf sht.Cells(lRow, 4) = "STAR" Then
Range("K" & lRow).Value = Application.WorksheetFunction.VLookup(Range("A" & lRow) & Range("G" & lRow), Worksheets("OF_MOON").Range("A:D"), 4, 0)
End If
Next lRow
End Sub

Resources