excel query append above row to cell - excel

I've tried the concatenate function but it wasn't really useful.
I'm trying to accomplish, so here's a screenshot/picture
Basically I need to be able to input data for the score, then have the cell autofill the data based on the users and their score with the corresponding tile, my confusion is how to do this if/with multiple users if they're on the same tile.

OK... i don't know if you have a mechanism for Tile 1 knowing that it is Tile 1 etc., but what I did was to put the numbers onto another sheet in the same cells. I.e. on sheet Tiles cell B18 has 1. In this way we can just reference that cell rather than any hardcoded values in the formula...
I also decided that if there were no names with that score, then we would just want the tile name (e.g. Tile 1)
So these give the first part of the formula that can be written into B18 and copied to the range B18:F31:
=IF(Tiles!B18="","",IF(ISERROR(MATCH(Tiles!B18,$B$7:$H$7,0)),"Tile "&Tiles!B18,...))
What this is doing is:
checking the Tiles sheet - if the corresponding cell is empty, then this isn't a tile and we just put ""
using MATCH to see if that score is held by any user - if it isn't found then it gives an error so the IF(ISERROR(...)) will return just the tile name
the ... is where the two options come in...
OPTION 1 - Loooong Formula
Replace the ... by:
MID(IF($B$7=Tiles!B18,", "&$B$2,"")&IF($C$7=Tiles!B18,", "&$C$2,"")&IF($D$7=Tiles!B18,", "&$D$2,"")&IF($E$7=Tiles!B18,", "&$E$2,""),3,9999)
...and copy the &IF($E$7=Tiles!B18,", "&$E$2,"") section with each needed column for your 22 players.
So the unit is "if the player's score is the same as the tile number, give me ", name" otherwise blank" and we join these with the & operator.
This is wrapped in a MID(...,3,9999) so we get rid of the ", " at the start of the first name we find (the joined IF statements would give e.g. ", Aaron, infinite user").
This option is a bit painful to write (and read!) but it only has to be done once and the formula can be copied and pasted...
OPTION 2 - VBA Function and Array Formulas
Public Function JOIN(rng As Variant, Optional separator = ", ") As String
JOIN = ""
Dim v As String
For Each c In rng
If IsObject(c) Then
v = c.Text
Else
v = c
End If
If v <> "" Then
If JOIN = "" Then
JOIN = v
Else
JOIN = JOIN & separator & v
End If
End If
Next c
End Function
This function will join either a range of cells' values, or an array of strings. Using it with an array formula (entered in Excel using Ctrl+Shift+Enter) means that we can do a conditional join...
So the ... becomes:
JOIN(IF($B$7:$H$7=Tiles!B18,$B$2:$H$2,""))
For this, each value in the scores range $B$7:$H$7 will be checked against the tile number. If it doesn't match, we return "", otherwise we return the corresponding name (in range $B$2:$H$2). This will give us an array of blanks and names which JOIN will join...
This option means a macro enabled workbook and using "more complex" array formulas. But array formulas are great, and I advise everyone to play with them ;-). cpearson has a good intro: http://www.cpearson.com/excel/arrayformulas.aspx
Have fun!

Related

How to filter rows based on column value without using FILTER function in excel?

Hi all,
I want to use a formula to filter the rows based on the name chosen in cell D2. From what I searched in google, I only can see people using FILTER function which is very easy. However, FILTER function is only available if we subscribe to 365 office. May I know is there any way to achieve what I want for non 365 office user? Any help will be greatly appreciated!
As far as I understand, hiding the values different than D2 will take care of your need. I am using a similar macro for this task and below I modified it for you to hide the values different than D2. It will start checking values from active cell and loop through until it finds a null value. You can try it and modify it according to your needs. Then you can assign a keyboard shortcut or put a button for it into quick access toolbar, if you are going to use this frequently.
Sub hideByD2()
Dim i, j
i = ActiveCell.Row
j = ActiveCell.Column
k = Cells(2, 4).Value
Do Until Cells(i, j) = ""
If Cells(i, j) <> k Then
Rows(i).Select
Selection.EntireRow.Hidden = True
Else
End If
i = i + 1
Loop
MsgBox "hide process completed successfully"
End Sub
Manage to find the solution.
Formula:
G5 = =IFERROR(INDEX($C$5:$C$14,AGGREGATE(15,6,1/($C$5:$C$14=$D$2)*(ROW($C$5:$C$14)-ROW($C$4)),ROW()-ROW($C$4))),"")
H5 = =IFERROR(INDEX($D$5:$D$14,AGGREGATE(15,6,1/($C$5:$C$14=$D$2)*(ROW($C$5:$C$14)-ROW($C$4)),ROW()-ROW($C$4))),"")
I5 = =IFERROR(INDEX($E$5:$E$14,AGGREGATE(15,6,1/($C$5:$C$14=$D$2)*(ROW($C$5:$C$14)-ROW($C$4)),ROW()-ROW($C$4))),"")
Drag down these 3 formula to the cells below and should work.
Say you have this layout (just the first two columns of your data, moved to a1). Here are two formulas, one that contains FALSES (if you don't care) and one that removes them (because you probably do):
=IF(A4:A13=B1,B4:B13)
=IFERROR(SMALL(IF(A4:A13=B1,B4:B13), ROW(A4:A13)-3), "")
The first one is pretty straightforward. The second one is very similar. It just passes those results to SMALL, which will return the kth smallest value form the array ignoring FALSE values. To get it to evaluate the entire array, you also send it an array of 1 to n, generated with ROW(), and since the range starts in A4 you have to adjust by -3 to make the array start at 1. If you didn't want to have to figure out the offset, you could do this, but we're rapidly losing readability:
=IFERROR(SMALL(IF(A4:A13=B1,B4:B13), ROW(A4:A13)-MIN(ROW(A4:A13))+1), "")
When SMALL gets your list of matching values (with the falses), it will a match for each number in the ROW array you send it, and if it runs out of actual numbers it will start returning errors, which is why you wrap the whole thing in IFERROR.
This will work for numeric values. If you have to support any value, you can still do it:
=IFERROR(
INDEX(
B:B,
SMALL(
IF(A4:A13=B1, ROW(A4:A13)),
ROW(INDIRECT("1:"&ROWS(A4:A13)))
),
0
),
"")
In this case, instead of returning the matching values with SMALL, you will return the matching row numbers, then you will pass those to INDEX, wrapping the whole thing in IFERROR. I used a slightly different method to generate the dynamic indexes:
ROW(INDIRECT("1:"&ROWS(A4:A13)))
which will return an array from 1 to the number of rows in the passed range, but any of the methods to generate the sequence will work.

combine all cells, numbers and symbols to a sum

Good day,
I'm at a loss on this problem.
I have a group of cells that contain words, like apple, this word would be the value. It is separated by a symbol for completing the math. They can be changed by the user to make custom calculations.
Cell A1 is "apple", B1 is "+", cell C1 is "apple", cell D1 is "*", cell E1 is "apple", call F1 is "=" and cell G1 is the suggested total, in this case would be "6".
It would be posted as | apple | + | apple | * | apple | = | 6 |
The legend holds the value for the word, so if you enter 2 in the legend, apple would be 2.
The logic would determine that the formula would be 2+2*2= if written in excel, I would like to combine all the cells and calculate this.
I tried using =sum, sumproduct, concate and the like to no avail.
Any head way I did make, I ended up getting BEDMAS wrong as it calculated it as 2+2=4*2=8, instead of the correct 2*2=4+2=6.
Anyone know of a way to combine these cells and properly sum the values to the correct total?
Thank you for your time!
Go to the Name manager and create named range Eval, into Refers to field add formula:
=EVALUATE(CONCATENATE(VLOOKUP(Sheet1!A1,Sheet1!$A$3:$B$5,2,0),Sheet1!B1,VLOOKUP(Sheet1!C1,Sheet1!$A$3:$B$5,2,0),Sheet1!D1,VLOOKUP(Sheet1!E1,Sheet1!$A$3:$B$5,2,0)))
In range A3:B5 I have legend.
Change references as you need. Then in cell G1 write formula =Eval.
Sample:
This is a UDF based solution. Its advantage is that it's more versatile and by far easier to maintain if you learn its elements of code. The disadvantage is in that you do have to learn the elements of code and you have an xlsm macro-enabled workbook which isn't welcome everywhere.
The setup is simple. I created a table with columns Item and Value. I placed it on another sheet than the task. In fact, you could make the sheet with the table VeryHidden so that the user can't look at it without access to the VBA project, which you can password protect. I called the table Legend. The item columns has names like apple, pear, orange. The Value column has the numeric values associated with each name.
Note that, since this is a VBA project, the entire list can be transferred to VBA leaving no trace on the sheet. You could have a function to display the value of each item as the user clicks on it and have it disappear as he clicks elsewhere.
Next I created a data validation drop-down in A1 with the List defined as =INDIRECT("Legend[Item]"). Copy this cell to C1 and E1.
Then I created another Data Validation drop-down in B1 with the list as +,-,*,/. This drop-down must be copied to D1.
Now the code below goes into a standard code module. Find the way to create it because it isn't any of those Excel sets up automatically. It's default name would be Module1. Paste the code there.
Function Evalue(Definition As Range) As Double
Dim Task As String
Dim Fact(2) As Double
Dim C As Long
Dim i As Long
With Definition
For C = 1 To 5 Step 2
On Error Resume Next
Fact(i) = Application.VLookup(.Cells(C).Value, Range("Legend"), 2, False)
i = i + 1
Next C
Task = "(" & Fact(0) & .Cells(2).Value _
& Fact(1) & ")" & .Cells(4).Value _
& Fact(2)
End With
Evalue = Evaluate(Task)
End Function
Now you are ready for testing. Call the function from the worksheet with a call like
=Evalue(A1:E1). You can use it in comparisons like =IF(G6 = Evalue(A1:E1), "Baravo!", "Try again"). As you change any of the components the cell with the function will change.
Remember to use absolute addressing if you copy formulas containing the range. If you need to get a result in VBA while testing, use this sub to call the function.
Private Sub TestEvalue()
Debug.Print Evalue(Range("A1:E1"))
End Sub
My Sheet
Here is what I have.
In cells M - U, i count all the instances of the word from cells E, G and I from the legend.
=SUMPRODUCT((LEN(E3)-LEN(SUBSTITUTE(E3,$B$3,"")))/LEN($B$3))
In cells W - AE, I multiply the instances with the value to give me a total each time the word appears.
=SUM(M3*$C$3)
In cell E8 - I8, i add the three possible values together.
=SUM(W3:Y3) so each worded cell is now a number.
I'd like to take the cells E8 - I8 to make a calculation in k8 and so on.
So, each cell is put together to make an
=SUM(E8:I8)
statement, which all works except E11 - I11 which equates to 26 instead of 43.

Pattern match and sum values in VBA

I have a spreadsheet where users enter their three character name code corresponding to everyday with number of hours that they plan to spend in a specific task (A, B, C) within brackets. What I want is these needs to be summed up for every user and get populated in rows corresponding to their names everyday.
Currently I am using an custom vba function to perform this sum, however I wanted to know if this can be done directly with any custom formula or VLOOKUP. Any help is appreciated!
Edit: I have been using the function, one specific to each user (the three character code) to calculate this sum.
Function SumJON(Target As Range) As Double
Dim xCell As Range
Dim xSum As Double
xSum = 0
For Each xCell In Target
If xCell.Value <> "" And InStr(xCell.Value, "JON") > 0 Then
Test = Split(xCell.Value, "JON")
Test1 = Test(1)
Test2 = Split(Test1, ")")
Test3 = Test2(0)
xSum = xSum + Test3
End If
Next
SumJON = xSum
End Function
You can try the following, with the below setup of data:
Formula in B2:
=SUM(IF(ISNUMBER(SEARCH(MID($A2,LEN($A2)-3,3),B$6:B$8)),MID(B$6:B$8,SEARCH(MID($A2,LEN($A2)-3,3),B$6:B$8)+4,SEARCH(")",B$6:B$8,SEARCH(MID($A2,LEN($A2)-3,3),B$6:B$8))-SEARCH(MID($A2,LEN($A2)-3,3),B$6:B$8)-4),0)*1)
NOTE: This is an array formula and should be confirmed through CtrlShiftEnter
Drag formula down and right.
It will also work on expending the amount of names in the list AND with decimals:
Note that my system decimal point is a comma.
Breakdown:
To extract the searchvalue, JON, DOE and PRK we can make use of MID since you have a certain pattern to take into account. It would always have to be:
=MID($A2,LEN($A2)-3,3)
This value needs to be used in a SEARCH function which will return a position of our searchvalue in the A,B,C rows. Since it's an array formula it will return all these numeric positions or an error.
Therefor we need to use ISNUMBER to check if the searchvalue is actually found through SEARCH. If so it will return a TRUE and if not it will return FALSE.
Because this is part of our IFstatement, the formula will do another MID function for the TRUE values. Again we will have to make use of our searchvalue formula, but this time we know it will be in these strings and therefor we can use the numerical position as our starting position (+4, because these strings are 3 positions long + the opening paranthesis) in this second MID.
Now we have a starting position to get the lookupvalues from, we just need to know the first position of the next closing paranthesis, and we can do that through SEARCH from this exact position.
Multiplying it by 1 in the end would turn these values in true numerical lookupvalues, which finally can be summed through SUM
Et voila, we got the total of values between the paranthesis where the searchcriteria meets the current user.

Excel conditional formatting for the entire row with more than one formula

After 3 hours of searching I still didn't find an answer, here is what I am trying to do:
I am trying to fill with green any row that has WBS in it and with Red any row that has ACT in it and Blue any row that has EPR in it. It works for the first formula then when I try to add the second one every thing get messed up.
what i have understood is that you need to search a keyword in a row and if its found in any cell of that row then color it.
May be we can do it with conditional formatting but i have another idea. We can create a simple search function in Excel VBA. Something like this:
=search_row(A1:F1,"EPR")
The function will return 1 if EPR is found in any cell of specified row. Now if you create two different columns at the end of data columns, name first with WPS and second with EPR and write this function in it. Like
G1 =search_row(A1:F1,"WPS")
H1 =search_row(A1:F1,"EPR")
Drag it to end. Now sort the columns. First for WPS from higher to lower. Then color all rows having 1 in a single select. Similarly do the same with EPR (H1) column.
To use this function you can download the macro file from the following URL:
http://asimishaq.com/myfiles/SearchHighlight.xlsm
Now to run it first of all enable macros, and then re-open your data file and then open this macro file. As long as this macro file is opened you can use this function. Following is the VBA code if you want to create the macro yourself:
Function search_row(sRow As Range, Keyword As String)
Dim i As Integer
Dim Found As Integer
For i = 1 To sRow.Columns.Count
If InStr(1, LCase(sRow.Cells(1, i)), LCase(Keyword)) > 0 Then
search_row = 1
End If
Next
End Function
I had a go at making a function similar to asim-ishaq to determine if your search term exists in the row for fun :) then tried to apply it to highlighting rows, turns out I dont know how to use conditional formatting very well! Figured it out in the end, hopefully I've explained it well enough.
With this you will have to have (one) extra column at the end of your data to contain the result.
It might be possible to not require the extra column by putting the function inside the conditional formatting, however I couldn't get it to work (didn't try very hard). This isn't a great loss as it's much simpler to edit the formula if its on the workbook, instead of having to go through each conditional rule to edit it, should you need to edit it in the future.
To get the formatting to work you will need to create a number of rules (one per keyword)
You want to create a rule of the type shown below, in the formula box you need something along the lines of: =INDIRECT("D" & ROW())=0 where D is the column containing the result of the function below and 0 is the index of the keyword you're highlighting.
In my example, the formula in the D Column is: =SearchRow(An:Cn,"ABS","KBS","JBS") (where n is the row the formula is on)
Set the formatting as desired then press OK, when you return to the rule manager you will need to update the Applies to value, which should be a range that covers all the data you want to highlight. In my example it was $A$1:$C$3
My function below takes 2+ Arguments, The first is the range to search. The second (and any subsequent ones) are search terms.
The function will return a number. -1 for no matches and 0+ for the found search term. The number depends on the position in the arguments.
A1 = "ABS"
B1 = "SBA"
A2 = "SBA"
B2 = "ABS"
A3 = ""
B3 = ""
C1 = "=SearchRow(A1:B1, "ABS", "SBA")"
C2 = "=SearchRow(A2:B2, "ABS", "SBA")"
C3 = "=SearchRow(A3:B3, "ABS", "SBA")"
C1 > 0
C2 > 1
C3 > -1
The function will always return the first result, searching left to right comparing each cell to the Keywords in order. Using my example, if a cell contained "SBA ABS" the result would be 0 (for ABS). I guess your cells will probably only contain one keyword though so this shouldn't be a problem?
Public Function SearchRow(ByVal Row As Range, ParamArray Keyword() As Variant) As Integer
Dim Column As Integer
Dim Value As String
Dim Index As Integer
Dim Result As Integer
For Column = 1 To Row.Columns.Count
Value = LCase(Row.Cells(1, Column))
Result = -1
For Index = LBound(Keyword) To UBound(Keyword)
If InStr(1, Value, LCase(Keyword(Index))) > 0 Then
Result = Index
Exit For
End If
Next Index
If Result > -1 Then
Exit For
End If
Next Column
SearchRow = Result
End Function

How to merge rows in a column into one cell in excel?

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

Resources