When calculating series in Excel, most tutorials begin by setting sequence values to certain range of cells, say
A1=1, A2=2, A3=3,..., A10=10
and to get the value of 1+2+...+10, execute
A11=SUM(A1:A10)
But I don't want the "generate the sequence in worksheet cells first" part because initially I don't know the 'n' (10 in the above) and I want to define a custom function that takes n as a function argument.
So, is there a way to do something like this?
B1 = SUM([1:10]) // adding array of 'constants', not cell reference
EDIT: If I could 'summon' some (array of) big number(s) without any cell/ROW/COL operation as in calling rand(), that would be great.
Try using Array Formula as below
=SUM(ROW(A1:A10)) and then press CTRL+SHIFT+ENTER
Row(A1:A10) will become {1,2,3,4,5,6,7,8,9,10}.
Usage:
If you want to sum cells A20 to A50
sumjeff("A", 20,50)
Code
Function sumJeff(letter As String, nFrom As Integer, nTo As Integer) As Double
Dim strAddress As String
strAddress = letter & nFrom & ":" & letter & nTo
sumJeff = Application.WorksheetFunction.Sum(Range(strAddress))
End Function
Related
I'm trying to reassemble some data that was loss for my office. One thing that could make life exponentially better is the ability to count the number of variables in a formula. For example:
=500+500+500
Ideally, I would like to return "3" in this situation, as there are three "variables" in the above formula. Right now I'm using a formula to pull the exact value from the particular cell, but I'd like to add something that would allow me to also output the number of variables in the formula/calculation.
If the only operator is + then this will get the count:
=LEN(FORMULATEXT(A1))-LEN(SUBSTITUTE(FORMULATEXT(A1),"+",""))+1
Since you may have different operators beside a + sign, you could do something like this in VBA:
Function count_parts(rngFormula As Range) As Integer
'Create an array with all the operators you want to account for
Dim operatorArray As Variant, operator As Variant
operatorArray = Array("+", "-", "/", "*")
'Capture the formula in the cell passed in
Dim strFormIn As String: strFormIn = rngFormula.Formula
Dim strFormOut As String: strFormOut = strFormIn
'Loop through the operators in the array and swap them out
'So the strFormOut is completely rid of them all
For Each operator In operatorArray
strFormOut = Replace(strFormOut, operator, "")
Next
'Count the difference in characters between our starting
'formula and the formula without operators, subtracting 1.
count_parts = Len(strFormIn) - Len(strFormOut) + 1
End Function
If + is the only operator you have to account for, then a much more simple function could be used:
Function count_parts(rngFormula As Range) As Integer
count_parts = UBound(Split(rngFormula.Formula, "+")) + 1
End Function
You can stick either of these in a new module in your VBE and after saving the workbook you can use this formula in a cell like =count_parts(A1)
I am trying to write a simple formula to count how many times a particular name appears in a column. I am using COUNTIF as it is a pretty straight forward process but I cannot work out how to make it happen for a name in particular. This is the case:
The column named Age will display cells with one or more names, separated by commas in case there are more than one value. Putting "Young" as an example is easy to tell the COUNTIF formula to give me the number representing how many times this word appears, either being the only value in cell or as a part of a cell with a longer string value by giving the formula the "Young" statement.
The problem comes when I want the formula to count how many times "Mature" appears in my column. I cannot work out the way to make it count only when it says "Mature" without also taking all the "Early_Mature" or "Semi_Mature"
I know this is easy for whoever knows the basics of Excel so I don't think there is need to give more details.
Thanks
Most of the times I succeed solving such problems by adding the same delimiter (of our string) at the beginning and end of the main string.
So since your data is at COL:Y, you may create a new helper COL:Z and enter this formula:
="," & Y1 & ","
I did not use any spaces before or after comma since your data seems not having any space. Depending on your case, you may have to use spaces.
Now your string is wrapped with commas, which you may alter COUNTIF formula to such:
=COUNTIF(Z:Z,"*,"&B1&",*")
* characters are jokers which stand for "anything" in this context.
With an UDF. Code goes in a standard module added by opening the VBE with Alt + F11 then right-click in project explorer and add module.
Code
Option Explicit
Public Function GetCount(ByRef selectRange As Range, ByVal searchTerm As String) As Long
Application.Volatile
With selectRange
Dim arr(), joinedString As String, i As Long, outputCount As Long
arr = .Value
joinedString = Join(Application.WorksheetFunction.Transpose(Application.WorksheetFunction.Index(arr, 0, 1)), ",")
Dim arr2() As String
arr2 = Split(joinedString, ",")
For i = LBound(arr2) To UBound(arr2)
If Trim$(arr2(i)) = "Mature" Then
outputCount = outputCount + 1
End If
Next i
End With
GetCount = outputCount
End Function
Usage in sheet
To get the number of occurrences of Mature excluding those that have prefix you can use this array formula:
=SUM(((LEN(A2:A7)-LEN(SUBSTITUTE(A2:A7,"Mature",""))) / LEN("Mature"))-((LEN(A2:A7)-LEN(SUBSTITUTE(A2:A7,"_Mature",""))) / LEN("_Mature")))
Please take note that this formula is applied with Ctrl + Shift + Enter.
Given that your range is in Y:Y column, just change the range to one you need.
An alternative would be to change "Mature" to "Fully_Mature". Then you could just use Countif().
You'd have to do this in steps:
1) Change "Early_Mature" to "E_M"
2) Change "Semi_Mature" to "S_M"
3) Change "Mature" to "Fully_Mature"
4) reverse of step 1).
5) reverse of step 2).
I have a simple array formula in excel that doesn't work in the way I wish. In columns A and B there is data (A1 is paired with B1 and so on) while in column F there is the calculation based on the parameter in column E.
In cell F1 the formula is:
{=SUM(MAX(A$1:A$9, E1)*B$1:B$9)}
What this formula does is:
=MAX(A$1:A$9, E1)*B$1 + MAX(A$1:A$9, E1)*B$2 + ...
Instead, I need a formula that does this:
=MAX(A$1, E1)*B$1 + MAX(A$2, E1)*B$2 + ...
In words, the formula I wrote (the first one) always finds the max between the values from A1 to A9 and E1, multiplies it by the i-th B value and sums the results. What I need is a formula that finds the max between the i-th A value and E1, and not between all the A values.
What I'm looking for is easily done by adding in column C the formula =MAX(A1;E$1)*B1 and then in F1 just =SUM(A1:A9), but I can't use this solution because in column F the same formula is repeated, with the E parameter changing every time.
I can use a IF instruction: in F1 I can write
{=SUM(IF(A$1:A$9>E1, A$1:A$9, E1)*B$1:B$9)}
While this formula does what I need in this case, I think it's a bad solution because I find it difficult to read and to expand. For example, if there is another parameter in column D and the factor is MIN(MAX(A$1:A$9;E1);D1), using IF will result in a very long and very unreadable and complicated formula.
Are there better solutions to my problem? Thank you all!
NOTE: syntax may vary a little because I am using the italian version of excel.
The problem is that MAX takes an array as an argument. Functions that normally take an array never return an array - they were designed to turn an array into one number. No matter how many arrays you throw at MAX, it's always just going to return one number.
I couldn't come up with a good solution, so here's a bad one
=SUMPRODUCT(((A1:A9*(A1:A9>E1))+(E1*(A1:A9<=E1)))*B1:B9)
I don't think that really increases the maintainability of the IF-based formula that you're trying to avoid. I think you're stuck with IF or a helper column.
Another possibility is a VBA function.
Public Function SumMaxMin(rRng1 As Range, rRng2 As Range, ParamArray vaMinMax() As Variant) As Double
Dim rCell As Range
Dim dReturn As Double
Dim aMult() As Double
Dim lCnt As Long
Dim i As Long
ReDim aMult(1 To rRng1.Cells.Count)
For Each rCell In rRng1.Cells
lCnt = lCnt + 1
aMult(lCnt) = rCell.Value
For i = LBound(vaMinMax) To UBound(vaMinMax) Step 2
If Not Evaluate(aMult(lCnt) & vaMinMax(i + 1) & vaMinMax(i)) Then
aMult(lCnt) = vaMinMax(i)
End If
Next i
Next rCell
For i = LBound(aMult) To UBound(aMult)
dReturn = dReturn + aMult(i) * rRng2.Cells(i).Value
Next i
SumMaxMin = dReturn
End Function
For your example
=SumMaxMin(A1:A9,B1:B9,E1,">")
Adding another condition
=SumMaxMin(A1:A9,B1:B9,E1,">",D1,"<")
It will error if your ranges aren't the same number of cells or you pass arguments that don't work with Evaluate.
Another possibility for avoiding repetitions of cell references is:
=SUM(B1:B9*ABS(A1:A9-E1*{1,-1}))/2
assuming values are non-negative. More generally to return an array of pairwise max values:
=MMULT((A1:A9-E1*{1,-1})^{2,1}^{0.5,1},{1;1}/2)
which returns:
MAX(A1,E1)
MAX(A2,E1)
...
MAX(A9,E1)
I don't remember ever cracking this problem, but for maintainability I'd probably do something like this:
{=SUM((A1:A9<E1)*E1*B$1:B$9) + SUM((A1:A9>=E1)*A1:A9*B$1:B$9)}
If I understand the problem correctly, using IF instead of MAX should do:
=SUM(IF($A$1:$A$9>E1;$A$1:$A$9;E1)*$B$1:$B$9)
I am trying to perform the following in one steps (one formula):
Strip a letter from a column of elements and add them up.
Example:
Data:
1x
2y
3x
I want to strip letters and add up numbers all in one formula.
I understand that I could have a helper column in which I strip letters x,y,z and then have a formula to add up the numbers, but I don't want to do this.
Thanks for any suggestions.
Assuming one entry per cell:
Is there only one letter at the end? If so, you can use:
=SUMPRODUCT(--LEFT(A1:A100,LEN(A1:A100)-1))
If there might be multiple letters at the end, a simple UDF would be simpler:
Option Explicit
Function AddStrings(rg As Range)
Dim L As Long
Dim I As Long
For I = 1 To rg.Count
L = L + Val(rg(I))
Next I
AddStrings = L
End Function
EDIT: If some of the cells might be blank, you can use either the UDF, or, if you prefer the formula, this array-entered formula:
=SUM(IFERROR(--LEFT(A1:A100,LEN(A1:A100)-1),0))
To array-enter a formula, after entering
the formula into the cell or formula bar, hold down
ctrl-shift while hitting enter. If you did this
correctly, Excel will place braces {...} around the formula.
Assuming that the format is consistent, you can do something like
=VALUE(LEFT(A1,1))+VALUE(MID(A1,4,1))+VALUE(MID(A1,7,1))
If the format is not consistent, things get more difficult. Let me know and I will expand the answer.
EDIT:
This function works with a variable length text, assuming that the fields are separated by the spaces and have one letter after the number:
Function AddValues(Text As String)
Dim Tokens() As String, I As Integer
Tokens = Split(Text)
For I = 0 To UBound(Tokens)
AddValues = AddValues + Val(Left(Tokens(I), Len(Tokens(I)) - 1))
Next I
End Function
E.g
A1:I
A2:am
A3:a
A4:boy
I want to merge them all to a single cell "Iamaboy"
This example shows 4 cells merge into 1 cell however I have many cells (more than 100), I can't type them one by one using A1 & A2 & A3 & A4 what can I do?
If you prefer to do this without VBA, you can try the following:
Have your data in cells A1:A999 (or such)
Set cell B1 to "=A1"
Set cell B2 to "=B1&A2"
Copy cell B2 all the way down to B999 (e.g. by copying B2, selecting cells B3:B99 and pasting)
Cell B999 will now contain the concatenated text string you are looking for.
I present to you my ConcatenateRange VBA function (thanks Jean for the naming advice!) . It will take a range of cells (any dimension, any direction, etc.) and merge them together into a single string. As an optional third parameter, you can add a seperator (like a space, or commas sererated).
In this case, you'd write this to use it:
=ConcatenateRange(A1:A4)
Function ConcatenateRange(ByVal cell_range As range, _
Optional ByVal separator As String) As String
Dim newString As String
Dim cell As Variant
For Each cell in cell_range
If Len(cell) <> 0 Then
newString = newString & (separator & cell)
End if
Next
If Len(newString) <> 0 Then
newString = Right$(newString, (Len(newString) - Len(separator)))
End If
ConcatenateRange = newString
End Function
Inside CONCATENATE you can use TRANSPOSE if you expand it (F9) then remove the surrounding {}brackets like this recommends
=CONCATENATE(TRANSPOSE(B2:B19))
Becomes
=CONCATENATE("Oh ","combining ", "a " ...)
You may need to add your own separator on the end, say create a column C and transpose that column.
=B1&" "
=B2&" "
=B3&" "
In simple cases you can use next method which doesn`t require you to create a function or to copy code to several cells:
In any cell write next code
=Transpose(A1:A9)
Where A1:A9 are cells you would like to merge.
Without leaving the cell press F9
After that, the cell will contain the string:
={A1,A2,A3,A4,A5,A6,A7,A8,A9}
Source: http://www.get-digital-help.com/2011/02/09/concatenate-a-cell-range-without-vba-in-excel/
Update: One part can be ambiguous. Without leaving the cell means having your cell in editor mode. Alternatevly you can press F9 while are in cell editor panel (normaly it can be found above the spreadsheet)
Use VBA's already existing Join function. VBA functions aren't exposed in Excel, so I wrap Join in a user-defined function that exposes its functionality. The simplest form is:
Function JoinXL(arr As Variant, Optional delimiter As String = " ")
'arr must be a one-dimensional array.
JoinXL = Join(arr, delimiter)
End Function
Example usage:
=JoinXL(TRANSPOSE(A1:A4)," ")
entered as an array formula (using Ctrl-Shift-Enter).
Now, JoinXL accepts only one-dimensional arrays as input. In Excel, ranges return two-dimensional arrays. In the above example, TRANSPOSE converts the 4×1 two-dimensional array into a 4-element one-dimensional array (this is the documented behaviour of TRANSPOSE when it is fed with a single-column two-dimensional array).
For a horizontal range, you would have to do a double TRANSPOSE:
=JoinXL(TRANSPOSE(TRANSPOSE(A1:D1)))
The inner TRANSPOSE converts the 1×4 two-dimensional array into a 4×1 two-dimensional array, which the outer TRANSPOSE then converts into the expected 4-element one-dimensional array.
This usage of TRANSPOSE is a well-known way of converting 2D arrays into 1D arrays in Excel, but it looks terrible. A more elegant solution would be to hide this away in the JoinXL VBA function.
For those who have Excel 2016 (and I suppose next versions), there is now directly the CONCAT function, which will replace the CONCATENATE function.
So the correct way to do it in Excel 2016 is :
=CONCAT(A1:A4)
which will produce :
Iamaboy
For users of olders versions of Excel, the other answers are relevant.
For Excel 2011 on Mac it's different. I did it as a three step process.
Create a column of values in column A.
In column B, to the right of the first cell, create a rule that uses the concatenate function on the column value and ",". For example, assuming A1 is the first row, the formula for B1 is =B1. For the next row to row N, the formula is =Concatenate(",",A2). You end up with:
QA
,Sekuli
,Testing
,Applitools
,Visual Testing
,Test Automation
,Selenium
In column C create a formula that concatenates all previous values. Because it is additive you will get all at the end. The formula for cell C1 is =B1. For all other rows to N, the formula is =Concatenate(C1,B2). And you get:
QA,Sekuli
QA,Sekuli,Testing
QA,Sekuli,Testing,Applitools
QA,Sekuli,Testing,Applitools,Visual Testing
QA,Sekuli,Testing,Applitools,Visual Testing,Test Automation
QA,Sekuli,Testing,Applitools,Visual Testing,Test Automation,Selenium
The last cell of the list will be what you want. This is compatible with Excel on Windows or Mac.
I use the CONCATENATE method to take the values of a column and wrap quotes around them with columns in between in order to quickly populate the WHERE IN () clause of a SQL statement.
I always just type =CONCATENATE("'",B2,"'",",") and then select that and drag it down, which creates =CONCATENATE("'",B3,"'",","), =CONCATENATE("'",B4,"'",","), etc. then highlight that whole column, copy paste to a plain text editor and paste back if needed, thus stripping the row separation. It works, but again, just as a one time deal, this is not a good solution for someone who needs this all the time.
I know this is really a really old question, but I was trying to do the same thing and I stumbled upon a new formula in excel called "TEXTJOIN".
For the question, the following formula solves the problem
=TEXTJOIN("",TRUE,(a1:a4))
The signature of "TEXTJOIN" is explained as TEXTJOIN(delimiter,ignore_empty,text1,[text2],[text3],...)
I needed a general purpose Concatenate With Separator (since I don't have TEXTJOIN) so I wrote this:
Public Function ConcatWS(separator As String, ParamArray cell_range()) As String
'---concatenate with seperator
For n = LBound(cell_range) To UBound(cell_range)
For Each cell In cell_range(n)
If Len(cell) <> 0 Then
ConcatWS = ConcatWS & IIf(ConcatWS <> "", separator, "") & cell
End If
Next
Next n
End Function
Which allows us to go crazy with flexibility in including cell ranges:
=ConcatWS(" ", Fields, E1:G2, L6:M9, O6)
NOTE: "Fields" is a Named Range and the separator may be blank