I have data in Excel in following format
Employee Company
John A
George A
Bob A
Peter B
Luke B
and I would need:
Company Employees
A John,George,Bob
B Peter,Luke
Is there an easy way of doing it in Excel?
I posted an answer to something similar a while ago. The same principle could apply here, though it's easier in your case.
First, make sure that the list is sorted by column B.
In cell C2, you can put:
=IF(B2=B3,0,1)
We'll use this later on. In cell D2, put:
=IF(B1=B2,CONCATENATE(D1,", ",A2),A2)
Drag/Fill the two formulae down and you should get a full list on each cell where you have 1 in column C. Copy/Paste values on the formulae, then apply a filter. Select all the 0 in column C and delete all the records (in columns A through D). After that remove the filter and sort by any column.
I think you want the concatenate function:
http://office.microsoft.com/en-ca/excel-help/concatenate-HP005209020.aspx
So! You'd like to do a concatenate if match style comparison/lookup. Unfortunately there's nothing out-of-the-box in Excel for this, but this slightly more complex Q&A thread outlines two potential approaches:
Using the MoreFunctions add-in for Excel
Using a custom "MultiLookup" VBA function
http://answers.microsoft.com/en-us/office/forum/office_2003-excel/if-vlookup-is-match-then-concatenate/26f6794d-8663-4e59-9a1b-a598c78f3bed
Both approaches require a little advanced knowledge of Excel (VLOOKUP, compound functions, etc). If you're not familiar with these things then VLOOKUP is a good place to start!
String concatenation over more than a few cells is best left to a VBA User Defined Function (aka UDF) even without setting criteria. Your situation of an unknown number of strings and applying revolving criteria would certainly fit this category.
Tap Alt+F11 and when the VBE opens, immediately use the pull-down menus to Insert ► Module (Alt+I,M). Paste the following into the new pane titled something like Book1 - Module1 (Code).
Public Function conditional_concat(rSTRs As Range, rCRITs As Range, rCRIT As Range, Optional sDELIM As String = ", ")
Dim c As Long, sTMP As String
For c = 1 To Application.Min(rSTRs.Cells.Count, rCRITs.Cells.Count)
If rCRITs(c).Value2 = rCRIT.Value2 Then _
sTMP = sTMP & rSTRs(c).Value & sDELIM
Next c
conditional_concat = Left(sTMP, Application.Max(Len(sTMP) - Len(sDELIM), 0))
End Function
Tap Alt+Q to return to your worksheet. Use this UDF like any native Excel worksheet function. The syntax is,
conditional_concat(<range of strings>, <range of conditions>, <cell with condition>, [optional] <delimiter as string>)
The formula in E2 is,
=conditional_concat(A$2:A$99, B$2:B$99, D2)
Fill down as necessary. I've used the optional sDELIM parameter to provide semi-colon delimination in E3 with,
=conditional_concat(A$2:A$99, B$2:B$99, D3, "; ")
Related
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.
There are some food names and prices as you can see between I2 and J22. For instance AYÇICEK YAĞI(SUNFLOWER OIL IN ENGLISH) is 4$ per kg. In the left of the sheet, you can see other list. What I need is;
I want to compare all A* columns with Strings between I2:I22 and get the price which is written between J2:J22 then write it to the D* columns.
There are more than 500 rows and I need to do it for all rows.
And there are some headings as u can see in bold font, they should be protected.
You seem to have come up with a formula; now you need a way to dispense it. Your worksheet design does not lend itself to simply filling down a formula. However, with the numbers in column C identifying valid entries that require a formula in columns D and E, a short sub procedure can make quick work of putting the formulas into the correct places.
Sub fillFormula()
Dim w As Long, vWSs As Variant, vFRMLs As Variant
vWSs = Array("ogle_aksam_gramaj", "kahvalt" & ChrW(305) & "_gramaj", _
"araogun_gramaj")
For w = LBound(vWSs) To UBound(vWSs)
With Worksheets(vWSs(w))
With .Columns(3) '<~~ going to look at column C for numbers
With .SpecialCells(xlCellTypeConstants, xlNumbers)
.Offset(0, 1).FormulaR1C1 = _
"=IFERROR(VLOOKUP(RC1, 'urunler'!C1:C2, 2, FALSE), """")"
.Offset(0, 2).FormulaR1C1 = _
"=IFERROR(RC4*RC3, """")"
End With
End With
End With
Next w
End Sub
The IFERROR function has been used to 'wrap' the lookup and mulltiplication formulas. It catches errors and offers alternative results; in this case, zero-length strings that look blank.
The kahvaltı_gramaj worksheet causes problems in VBA due to the unicode character. You might try other methods of cycling through the worksheets.
That binary (macro-enabled) workbook is available from my own public dropbox here.
In the workbook you have attached, VLOOKUP will return #N/A when there is no available value.
In Sheet ogle_aksam_gramaj Cell D4 use the following Formula:
=SUMIF($I:$I,$A4,$J:$J)
You can then drag it down and it should be giving you the prices based on the details provided in the same sheet (Range I:J)
The good thing (or bad, depends on you) of sum if is that it will return 0 if there is nothing to sum. in your sheet, the items must be unique in the list, otherwise, it will keep summing every instance. So if AYÇICEK YAĞI is there 2 times, it will be summed twice.
You can use Advanced Filter with (unique values only) to make sure that all the ingredients are accounted for and are mentioned only once.
Thanks.
I have an excel table were A1 = "YES", B1 = "YES" and C1 = "YES". I want to know how many "YES" are in my table, which is easily solved with =COUNTIF(A1:C1,"YES") and it will accurately give me the answer of 3.
A B C
1 YES YES YES
But if want to know how many "YES" are in A1 and C1 and ignore whatever B1 has it becomes tricky. The same function gives me 3 while I want it to give me 2 as an answer since I want to count only A1 and C1.
I want to know if there is a way to manage data so I can work only with that kind of non-consecutive cells? I found that a solution would be using something like =if(A1="YES",1)+if(C1="YES",1) and it works like a charm since it will always give me the right answer; however, that is not a satisfying solution because despite the simplicity in my example, my real situation requires to write around 100 cells from a 500 range for several different combinations which can become somewhat heavy.
I tried using name ranges but it seems the if functions doesn't let me use them the way I want. So any help will be apreciated, thanks.
If VBA is an option and "non-consecutive ranges in excel functions" is the question, then you could create a User Defined Function which takes a ParamArray and returns an array out of all given parameters.
Example
Public Function getMatrix(ParamArray aValues() As Variant) As Variant
Dim i As Long
Dim aReturnValues() As Variant
For Each vValue In aValues
For Each vSingleValue In vValue ' possible the vValue is also an array
ReDim Preserve aReturnValues(i)
aReturnValues(i) = vSingleValue
i = i + 1
Next
Next
getMatrix = aReturnValues
End Function
This could then be used like:
Formula in A4:
=SUMPRODUCT(--(getMatrix(A1,C1,E1:G1,D2:E3)="Yes"))
Note, the UDF is returning an array, not a Range. Thats why we cannot use COUNTIF. COUNTIF needs a Range as first parameter.
Why looking for a formula when you have other features in Excel? Add a row (#2), and have A2=1, B2=0, C2=1 till the last column [Drag it to populate, Make sure to Copy Cells]. Then select row and see the Sum in Status Bar.
Have a look at this thread. Basically what you need is something like this:
=SUM(COUNTIF(INDIRECT({"A1:A10","C1:c10"}),"a"))
Or just use multiple COUNTIFs, and add them. (Countif(...) + countif(...) etc.)
I'd like to use something like the EVALUATE-Function in Excel for if-statements.
I've got the following issue: I'd like to use Excel to validate my data. I've got three sheets:
the real data I'd like to check. Each row represents a customer and each column some data. The columns have specific names like “age”, “name”, …
the description of the checks I’d like to perform. Each row represents one check and I’ve got 3 columns: 1 check_id – an identifier of each check; 2 check_desc – a description of the check that every normal person can understand like “Age below 18”; 3 rule – the Excel Formula as a string like If(age<18, “error”, “no error”)
the place where sheet 1 and 2 should come together. Each row should represent one customer and each column one check.
Now, if I’ve got for example check_1 “If(age<18, “error”, “no error”)” and the customer data 10 and 20, then the check for the first customer should fire and the check for the second shouldn’t.
If the data is changed, and the age is set from 10 to 18, then everything should be fine, or if the rule is changes to “If(age<21, “error”, “no error”)” then the new condition should be applied to all data.
Is something like this possible?
With the evaluate function only ‘simple’ formulas work.
Thanks in advance,
Martin
Attached you can find the
Excel-Sample File
You will definitely need some VBA here. Make a custom EVAL function:
Public Function EVAL(ByRef Rng As Range, Formula As String) As Variant
Dim RngAddress As String
RngAddress = "'" & Rng.Parent.Name & "'!" & Rng.Address(External:=False)
EVAL = Evaluate(Replace(Formula, "$", RngAddress))
End Function
Then you can easily evaluate your values with formulas passed as text ($ is for parameter):
=EVAL(A1, "IF($<21,""error"",""no error"")")
(note the escaped double quotes). But you would rather pass formula from another cell - then you can specify formula in cell with single quotes:
IF($<21,"error","no error")
=EVAL(A1, B1)
I personally would rename check_desc!B2 to "Check_1" (named range) and then refer to that. You can use the INDIRECT function as well once you've renamed your column header "Check_1" as well.
Note: the value in this case should be "18" instead of "age below 18". You can of course change the number format to "age below "0.
If the relations are changing too I would insert a table that would have uniform formulae changing in each cell when changed in one cell.
The only issue you would then face is the non-expanding nature of your table. You can use VBA for this, but maintaining formulae increases your accountability even if it would be slightly easier not to deal with nasty nested functions.
I have a sheet with a lots of columns ordered in a hierarchical way with the cells merged:
I'd like to name those columns (in example: row 5) like this:MainGroupA-SubGroupA-SubSubGroupA.
Simply referencing the columns above in the classic way won't work as the field above isn't available anymore. (In the example: the fields B1 to F1) (i.e. I can't enter A1&A2&A3 / R[-4]C&R[-3]C&R[-2]C as this formula tries to read from the "hidden" cells).
Is there a way to do this without manual work or the need to un-merge the parent-cells? I might be able to do this with some external text editor or even VBA but would prefer an "Excel formula solution" as it would stay updated for new groups and columns.
To Clarify: I'd like all columns in Line 5 to have the text like in A5
If you want:
MainGroupA-SubGroupA-SubSubGroupA
in A5 then this should work:
=A1&"-"&A2&"-"&A3
Edit Then try:
=OFFSET(A1,0,1-MOD(COLUMN(),6))&"-"&OFFSET(A2,0,MOD(COLUMN(),2)-1)&"-"&A3
though this won't give the same text as in A5 across the complete row.
The answer from pnuts is great and helped me solve some test cases. It was however a little difficult to adapt and produced empty strings for the last column, so I also wrote a VBA-Function to do exactly what I need.
Open the VBA Editor (ALT + F11) and enter the following code in a new module:
Public Function checkLeftIfEmpty(start As range) As String
If start.Cells.Count > 1 Then
checkLeftIfEmpty = "Only a single cell allowed as parameter"
Exit Function
End If
Dim currentRange As range
Set currentRange = start
Do While currentRange.Column >= 1
If currentRange.Value <> "" Then
checkLeftIfEmpty = currentRange.Value
Exit Function
Else
Set currentRange = currentRange.Offset(0, -1)
End If
Loop
End Function
You can now use the function checkLeftIfEmpty to find the first cell left-side from your parameter which contains text: (This will be the text of the merged cell itself, if applied to a "hidden by merge" cell)
And also in combination to concatenate a string: