I am looking for a VBA code which will help me in calculating the no of characters in the range of cells.
If i use the excel option of LEN, it does gives me the no of characters in the particular cell.
Do we have any code which will give me the no of characters in a range of cells.
For ex; A1 = "Night" , B1 = "Day" C1 = "Noon"
The result should be 12 ( 5 + 3 + 4 )
Can any one help me with this
You can create a custom UDF, that using a loop will calculate the number of characters in a range, something like the code below:
Function SumLeninRange(Rng As Range) As Long
Dim C As Range
For Each C In Rng ' loop through all cells in Range
SumLeninRange = SumLeninRange + Len(C.Value2)
Next C
End Function
And use the Test Sub code below:
Sub Test()
MsgBox "Num of Characters in Range is : " & SumLeninRange(Range("A1:C1"))
End Sub
You do not need VBA to do this, just array formula
=SUM(LEN(A1:C1))
type it and then press Ctrl-Shift-Enter
Related
Here is my VBA
Function CellColour(Irow As Integer, Icol As Integer) As Long
CellColour = Cells(Irow, Icol).Interior.ColorIndex
End Function
The color of the grey cells I am using is, -4142
I found this by =CellColour(5,11)
I currently have Two rows that contain monthly Sales data, Once the month ends I manually color the row gray, ""-4142"
I have a section for totals D6 which is a sum of a few cells
D6 = Sum(D9:D12)
What I want to accomplish is inside the D6 cell... subtract this gray number.
Cell D6 Formula:
Sum(D9:D12)-If(Cellcolour *IN ROWS F11:Q12* = *GRAY "-4142)
End result SUM D9:D12 MINUS WHATEVER NUMBERS ARE GRAY FROM ROWS F11:Q12
I think my problem lies within my inability to create the proper formula.
I feel like just doing conditional formatting might be easier?
Any help would be awesome.
Thanks!
Using a cell color to encode information is not a great approach: you'd be much better off with a "Status" column (which could then drive conditional formatting to add the color, but also can be more-easily used in other formulas)
That aside, your function has a problem:
Function CellColour(Irow As Integer, Icol As Integer) As Long
CellColour = Cells(Irow, Icol).Interior.ColorIndex
End Function
...here the Cells() will always apply to the ActiveSheet, which may or may not be the one you expect/want.
This might explain why your "grey" cells give -4142, which is actually the code for "no fill" (xlNone)
This is more explicit in referencing the correct sheet, because you're using a Range parameter in place of numeric arguments:
Function CellColour(r As Range) As Long
CellColour = r.Cells(1).Interior.ColorIndex
End Function
EDIT: This might be more what you need:
Function SumByColour(r As Range, indx As Long) As Long
Dim c As Range, t As Double, v
Application.Volatile
For Each c In r.Cells
v = c.Value
If IsNumeric(v) And c.Interior.ColorIndex = indx Then
t = t + v
End If
Next c
SumByColour = t
End Function
Then you can do something like:
=SUM(D9:D12)-SumByColour(F11:Q12, 15)
I have converted a Vlookup formula in a macro in order to avoid filling out the cell with the formula content. The following code worked only with a table with fixed number:
Sub NumberVLookup()
Dim num As Long
num = 4
Set shData = Sheet2
Dim sRes As Variant
sRes = Application.VLookup( _
num, shData.Range("A1:B6"), 2, True)
Debug.Print sRes
Sheet2.Range("C4") = sRes
End Sub
Instead I would like to create a code that gives me more flexibility in the way
it returns its text values by using VLookup function.
For example I would like that all numbers included in the range between:
0-9 return text value Red
10-15 return text value Yellow
16-20 return text value Green
The table to which I am referring to is the following:
A B
1 0-9 Red
2 10-15 Yellow
3 16-20 Green
For example if the value is 4 the VLookup macro will return text value "Red".
I hope the question is enough clear. Many thanks
You can use a range, with a non-Exact match.
Set up the data in three columns, with your ranges on the left in Ascending order.
Then use
=VLOOKUP(A7,$A$2:$C$4,3,TRUE)
Assuming your data is like this:
So for VBA (adjust as necessary):
Application.VLookup(num, shData.Range("$A$2:$C$4"), 3, True)
Edit: Or you can just follow #nutsch's great suggestion!
Sub NumberVLookup()
Dim num As Long
num = 16
Dim sRes As Variant
sRes = Application.VLookup( _
num, Sheet2.Range("A56:B58"), 2, True)
Debug.Print sRes
Sheet2.Range("J15") = sRes
End Sub
=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, " ")
=IF(N2=" ", " ",NETWORKDAYS(H2,TODAY()))
=IF(OR(O2 = " ", O2 <= 0), " ", (O2/N2)*100)
These are the three formulas, I want to make sure that as they are inserted into the worksheet the cell references will still change to match the rows they are on, as they would in a normal spreadsheet. Any advice would be much appreciated! (To clarify, I need to fill the ranges using VBA as the code I'm using clears the worksheet every time it is run.)
you could use FormulaR1C1 property of range object, which uses the "R1C1" notation for range addresses
for instance inserting your first formula in "A1" would be:
Range("A1").FormulaR1C1 = "=IF(AND(RC7<>100,TODAY()>=RC8, TODAY()<=RC9), RC5, "" "")"
where the pure R would assume the current cell row index, while C7 stands for a fixed (not varying with host cell position) 7th column index reference, and so on
If i have interpreted your question correctly, you need something like the below:
Option Explicit
Sub InsertFormula()
Dim i As Long
Dim n As Long
n = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To n
Cells(i, 1).Formula = "=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, "" "")"
Next i
End Sub
replace the 1 in n=... with whichever column has the most rows of data
replace for i = 1 to whichever row it must begin form
You will notice i have added extra quotations to the end of the formula, this is needed as quotes in a formula in VBA must be enclosed... in more quotes lol
Apply this concept for the other formulas :)
Instead of absolute references like G2 you can use something along
.FormulaR1C1 = "=SUM(RC[-2]:R[5]C[-2])"
where R and C reference the offset from the current cell (positive: right or down, negative: up or left).
Use it in a way similar to this:
Dim c
For Each c In Selection
c.FormulaR1C1 = "=SUM(RC[-2]:R[5]C[-2])"
Next c
Relative References are adjusted when you set the formula to range of cells:
[A1:B2].Formula = "=C$1" ' now the formula in B2 will become "=D$1"
You can also set multiple formulas at once:
Range("K2:M9").Formula = Array("=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, "" "")", _
"=IF(N2="" "", "" "",NETWORKDAYS(H2,TODAY()))", _
"=IF(OR(O2 = "" "", O2 <= 0), "" "", (O2/N2)*100)" )
or if each row has different formula:
[A1:Z3] = [{"=1";"=2";"=3"}]
This code is just to calculate simple moving average. Opened an excel, created dummy array in C row from 1 to 20. I want to create a function for eg: SMA(C7,3) = which should give average of C5:C7.
Coming back to VBA after long time, not able to figure whats the error in the below code.
Function sma1(rng As Range, N As Integer)
Set rng = rng.Resize(-N + 1, 0)
sma1 = Application.WorksheetFunction.average(rng)
End Function
avoid using a cell name as a function
fixed the RESIZE()
used an internal range variable
Function smal(rng As Range, N As Integer) As Variant
Dim rng2 As Range
Set rng2 = rng.Resize(N, 1)
smal = Application.WorksheetFunction.Average(rng2)
End Function
EDIT#1:
Based on Scott's comment:
Function smal(rng As Range, N As Integer) As Variant
Dim rng2 As Range
Set rng2 = rng.Offset(1 - N, 0).Resize(N, 1)
smal = Application.WorksheetFunction.Average(rng2)
End Function
I assume you want the column along side it to give you're SMA (as shown below?):
If so, the below will do it and drag it autocomplete it to the bottom of you column C array:
Sub SMA3()
Range("D7").FormulaR1C1 = "=AVERAGE(R[-2]C[-1]:RC[-1])" 'This is a relative reference (left one cell and up two cells) - This give your three inputs
Range("D7").AutoFill Destination:=Range("D7:D" & Range("C1048576").End(xlUp).Row) 'Autofills the SMA
End Sub
Just an FYI this can be done with existing formula:
=IF(ROW(C1)<$E$1,"",AVERAGE(INDEX(C:C,ROW(C1)-$E$1+1):C1))
E1 contains the number of rows to include.
I have created my own function to determine count the values in between to given values in increments of 30 as seen here
Function InBetween(First As Integer, Last As Integer)
Dim i As Long, F As String, a() As String
F = First
For i = First + 30 To Last Step 30
F = F & "|" & i
Next i
InBetween = F
End Function
When I use this function, I currently have it returning the result array in the cell the formula was entered into in the format of "1|2|3|4". Is there a way I can get this array to populate into the cell below the one containing the formula?
Note: I don't want the formula in the cell as I need to refer to the cell in a future equation that will use the result and not the equation.
This was surprisingly difficult. At first I tried calling a sub from the function to affect the cell below using application.caller but this always returned a #value error. It seems a UDF can't run anything that affects the worksheet.
Eventually I came up with this:
Create a worksheet change event by pasting this into the worksheet object in vb:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
On Error Resume Next
If Left(Target.Offset(-1, 0).Formula, 10) = "=InBetween" Then Call DoX(Target.Offset(-1, 0), InBetween(10, 60))
On Error GoTo 0
End Sub
Then paste this into a module
Sub DoX(r As Range, val As String)
Sheets(r.Parent.Name).Cells(r.Row, r.Column) = ""
Sheets(r.Parent.Name).Cells(r.Row + 1, r.Column) = val
End Sub
Then use your function as normal, but remember to hit return after you enter it so the active cell is the cell below where you entered the formula.