Compare columns in MS Excel - excel

Following is a sample excel spreadsheet. The requirement is to compare each column (say B) with column C and count the number of rows in which both B and C have numbers. For instance, both B and C have values in the first and second rows but only B has a value in the third row, so the output should be 2.
I tried to use if condition in the following manner:
if(and(isnumber(b2),isnumber(c2)),1,0)
but it works only for one row not all rows.
How do I achieve this result in MS Excel?
╔═══╦════════╦═══╦═══╦═══╦═══╦═══╗
║ ║ A ║ B ║ C ║ D ║ E ║ F ║
╠═══╬════════╬═══╬═══╬═══╬═══╬═══╣
║ 1 ║ ║ 4 ║ 5 ║ ║ 6 ║ 5 ║
║ 2 ║ ║ 2 ║ 5 ║ ║ 2 ║ ║
║ 3 ║ ║ 1 ║ ║ 2 ║ 6 ║ 7 ║
║ 4 ║ ║ ║ ║ ║ ║ ║
║ 5 ║ Output ║ 2 ║ ║ 0 ║ 2 ║ 1 ║
╚═══╩════════╩═══╩═══╩═══╩═══╩═══╝

Place this formula where ever you want to see the results
=COUNTIFS(B1:B4,"<>",C1:C4,"<>")
The "<>" only counts non-blank cells, but it will count #NAME? ,#DIV/0, and #REF
This can be avoided if zero is also not an acceptable value by adding two more criteria
=COUNTIFS(B1:B4,"<>",C1:C4,"<>",B1:B4,">0",C1:C4,">0"!)

If you need to compare all column combinations then you can use SUMPRODUCT:
=SUMPRODUCT(--(ISNUMBER(INDIRECT($A6&"$1:"&$A6&"$3"))),--(ISNUMBER(B$1:B$3)))
See this link for explanation of "Using SUMPRODUCT as an array formula".

Related

Insert one table into another table, when column header names are not in the same order

I want to insert all the data from one table copy_tbl at the end of another table paste_tbl both in different worksheets, but in the same workbook.
The columns that have the same header name will not be in the same order in both tables, so I need to rearrange the order of the inserted data columns to match the destination.
The copy_tbl might have column header names that doesn't exist in paste_tbl, and I want those columns to be added to paste_tbl (this is optional and the columns that doesn't have a match in the destination table can be ignored, if it's a headache to do).
I've been trying to read up on ListObjects and also trying to code some kind of loop that matches column header names before inserting data, but I'm stuck.
This seems like a fairly simple task, and I was certain I would at least figure it out with the help of google, but I've been sitting here for 6 hours now and I'm not getting anywhere.
I did find a solution to this by using Power Query, but I'm on a Mac, and it hasn't been implemented in Excel for Mac yet :|
Is there someone willing to help me solve this problem?
Thanks in advance!
Edit:
I abandoned trying to use ListObjects and tried something else.
This is the code I've come up with so far:
Dim r As Range, c As Range, msg As String
Application.ScreenUpdating = False
With Sheets("copy_sht").Range("1:1").CurrentRegion
For Each r In Sheets("paste_sht").Range("1:1")
Set c = .Rows(1).Find(r.Value, , , xlWhole, , 0)
If Not c Is Nothing Then
.Columns(c.Column).copy
r.PasteSpecial xlPasteValues
Else
msg = msg & vbLf & r.Value
End If
Next
Application.CutCopyMode = False
Application.ScreenUpdating = True
End With
End Sub
This replaces some of the values into the correct cells, and it also overwrites the whole first column with data from the second table.
This is what I want to happen:
╔════════════╦═══════╦═══════╦═══════╦═══════╗
║ Number ║ info1 ║ info2 ║ info3 ║ info4 ║
╠════════════╬═══════╬═══════╬═══════╬═══════╣
║ 1 ║ abc ║ ║ xyz ║ 456 ║
║ 2 ║ ║ 123 ║ ║ ║
║ 3 ║ ║ ║ 456 ║ ║
║ 4 ║ ║ ║ ║ ║
║ 5 ║ abc ║ asd ║ zxc ║ ║
╚════════════╩═══════╩═══════╩═══════╩═══════╝
╔════════════╦═══════╦═══════╦═══════╦═══════╗
║ Number ║ info1 ║ info3 ║ info4 ║ info5 ║
╠════════════╬═══════╬═══════╬═══════╬═══════╣
║ 1 ║ def ║ www ║ 123 ║ a ║
║ 3 ║ ║ ║ ║ b ║
║ 5 ║ ║ ║ ║ c ║
║ 6 ║ ║ ║ ║ d ║
║ 7 ║ 123 ║ ║ ║ e ║
╚════════════╩═══════╩═══════╩═══════╩═══════╝
╔════════════╦════════╦═══════╦════════╦════════╦═══════╗
║ Number ║ info1 ║ info2 ║ info3 ║ info4 ║ info5 ║
╠════════════╬════════╬═══════╬════════╬════════╬═══════╣
║ 1 ║ abcdef ║ ║ xyzwww ║ 456123 ║ a ║
║ 2 ║ ║ 123 ║ ║ ║ ║
║ 3 ║ ║ ║ 456 ║ ║ b ║
║ 4 ║ ║ ║ ║ ║ ║
║ 5 ║ abc ║ asd ║ zxc ║ ║ c ║
║ 6 ║ ║ ║ ║ ║ d ║
║ 7 ║ 123 ║ ║ ║ ║ e ║
╚════════════╩════════╩═══════╩════════╩════════╩═══════╝
The first table paste_tbl will become the third table after the data has been added from the second table copy_tbl.
This is what the code actually does with the first table:
╔═════════╦═══════╦═══════╦═══════╦═══════╗
║ Number ║ info1 ║ info2 ║ info3 ║ info4 ║
╠═════════╬═══════╬═══════╬═══════╬═══════╣
║ 1 ║ def ║ ║ www ║ 123 ║
║ 3 ║ ║ 123 ║ ║ ║
║ 5 ║ ║ ║ ║ ║
║ 6 ║ ║ ║ ║ ║
║ 7 ║ 123 ║ asd ║ ║ ║
╚═════════╩═══════╩═══════╩═══════╩═══════╝
So what I'm still missing is:
Adding missing columns from copy_tbl to paste_tbl.
Making sure the data that is pasted from copy_tbl is matched with the same unique ID located in the first column in paste_tbl, and if that unique ID doesn't exist, instead paste the whole row at the bottom of the table.
If data already exists in a destination cell, I want to concatenate that with the data from copy_tbl.
Edit 2:
Realizing some parts of VBA I've never understand, I tried to do this the old fashioned way with formulas, and I succeeded.
It's probably not very optimized, because it takes a while to populate the table, and I was getting tired when I finished it. But it gets it done.
Sorry if it's a bit messy, but what it does is it populates a new table basen on the values of two other tables tabell1and tabell2. It merges any existing cells data with the same unique ID $A2 which needs to be in the first column of all tables.
You have to collect all the unique ID's and place them without duplicates in the table that is to be populated. Then just paste the following formula into the first row of every column of your table.
=IFERROR(
IF(
IF(
COUNTIF(tabell1;$A2)=1;
VLOOKUP($A2;tabell1;MATCH(B$1;tabell1[#Headers];0);FALSE);""
)
=
IF(
COUNTIF(tabell2;$A2)=1;
VLOOKUP($A2;tabell2;MATCH(B$1;tabell2[#Headers];0);FALSE);""
);
IF(
AND(COUNTIF(tabell1;$A2)=1;COUNTIF(tabell2;$A2)=1);
IFERROR(
VLOOKUP($A2;tabell1;MATCH(B$1;tabell1[#Headers];0);FALSE);
VLOOKUP($A2;tabell2;MATCH(B$1;tabell2[#Headers];0);FALSE));
CONCATENATE(VLOOKUP($A2;tabell1;MATCH(B$1;tabell1[#Headers];0);FALSE);" ";VLOOKUP($A2;tabell2;MATCH(B$1;tabell2[#Headers];0);FALSE)));
IF(
COUNTIF(tabell2;$A2)=1;
VLOOKUP($A2;tabell2;MATCH(B$1;tabell2[#Headers];0);FALSE);VLOOKUP($A2;tabell1;MATCH(B$1;tabell1[#Headers];0);FALSE)
));" ")

How can I search for an item within a cell that's also in a range?

I have Table A:
╔═══╦═════╦═════════════╦══════════════════╗
║ ║ a ║ b ║ c ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 1 ║ ID ║ LIST VALUES ║ Table B Values ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 2 ║ 123 ║ 231,583 ║ eggs,bacon ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 3 ║ 789 ║ 518,732 ║ bacon,bread ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 4 ║ 101 ║ 55,38 ║ tomato,onion ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 5 ║ 213 ║ 894,231 ║ ham,eggs ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 6 ║ 141 ║ 55,38,894 ║ tomato,onion,ham ║
╠═══╬═════╬═════════════╬══════════════════╣
║ 7 ║ 516 ║ 548,43 ║ milk,butter ║
╚═══╩═════╩═════════════╩══════════════════╝
And I have Table B:
╔═══╦═════╦═════════════╗
║ ║ a ║ b ║
╠═══╬═════╬═════════════╣
║ 1 ║ ID ║ LIST VALUES ║
╠═══╬═════╬═════════════╣
║ 2 ║ 231 ║ eggs ║
╠═══╬═════╬═════════════╣
║ 3 ║ 518 ║ bacon ║
╠═══╬═════╬═════════════╣
║ 4 ║ 732 ║ bread ║
╠═══╬═════╬═════════════╣
║ 5 ║ 55 ║ tomato ║
╠═══╬═════╬═════════════╣
║ 6 ║ 38 ║ onion ║
╠═══╬═════╬═════════════╣
║ 7 ║ 894 ║ ham ║
╠═══╬═════╬═════════════╣
║ 8 ║ 548 ║ milk ║
╠═══╬═════╬═════════════╣
║ 9 ║ 43 ║ butter ║
╚═══╩═════╩═════════════╝
These are representations of the data I have, and what I need help with. The actual data is a lot longer than these tables, and the delimited items can be very long.
What I'm trying to do is populate Table A, Column C. I need to search the items from TABLE B, Column A for the listed items in TABLE A, Column B within the cell through the whole range.
I guess this can be done vice versa as well. I am familiar with INDEX-MATCH function, but I'm not sure how to add searching within the cell.
Use TEXTJOIN and ISNUMBER/SEARCH:
=TEXTJOIN(",",TRUE,IF(ISNUMBER(SEARCH(","&$G$2:$G$9&",",","&B2&",")),$H$2:$H$9,""))
If you have Windows Excel, try:
C2: =TEXTJOIN(",",TRUE,VLOOKUP(FILTERXML("<t><s>"&SUBSTITUTE(B2,",","</s><s>")&"</s></t>","//s"),$G$2:$H$9,2,FALSE))
Table A
Table B
Results

Sum quantities based on two columns and multiple rows

In excel, I have three columns. Column A contains receipt numbers, Column B contains item numbers, and Column C contains the quantity of each item. Example ("Receipt#" is in cell A1):
╔══════════╦═══════╦══════════╗
║ Receipt ║ Item# ║ Quantity ║
╠══════════╬═══════╬══════════╣
║ x ║ a ║ 14 ║
║ x ║ a ║ 26 ║
║ x ║ b ║ 30 ║
║ x ║ c ║ 68 ║
║ y ║ a ║ 79 ║
║ y ║ c ║ 3 ║
║ y ║ c ║ 24 ║
║ z ║ b ║ 91 ║
║ z ║ a ║ 5 ║
║ z ║ a ║ 1 ║
╚══════════╩═══════╩══════════╝
I would like to sum the quantities belonging to the same Receipt# AND Item# in Column D.
I've tried SUMIFS(C:C,A:A,A3=A2,B:B,B3=B2) which returns 0.
I've tried IF(A3=A2,(IF(B3=B4,SUM(C5,C4),"")),"") which sums but not like I want, I only want one total per Item# AND Receipt#.
You might be using wrong criterias. See formula below.
=SUMIFS(C:C,A:A,A1,B:B,B1)
You can use SUMPRODUCT like this:
=SUMPRODUCT(--(A:A=E1),--(B:B=E2),C:C)

Looking for keywords within column of longer phrases

If a keyword on Sheet 1 is contained within a cell in a column on Sheet 2, I want to copy the value in another column in Sheet 2. How can I do this? I have tried VLookUp and other but without success as they only work when the keyword exactly matches the target cell.
Sheet 1
╔═══╦═══════════╦══════════╗
║ ║ A ║ B ║
╠═══╬═══════════╬══════════╣
║ 1 ║ Horse ║ Winnings ║
║ 2 ║ Shadowfax ║ ║ < should show $9000
║ 3 ║ Telefax ║ ║ < should show $0
║ 4 ║ Ceefax ║ ║ < should show $660
╚═══╩═══════════╩══════════╝
Sheet 2
╔═══╦══════════════════════════════════╦══════════╗
║ ║ A ║ B ║
╠═══╬══════════════════════════════════╬══════════╣
║ 1 ║ Race ║ Winnings ║
║ 2 ║ Ascot, Ed, 2014-06-10 ║ $50 ║
║ 3 ║ Goodwood, Shergar, 2016-05-11 ║ $80 ║
║ 4 ║ Doncaster, Shadowfax, 2015-06-30 ║ $9000 ║
║ 5 ║ Goodwood, Ceefax, 2016-07-21 ║ $660 ║
╚═══╩══════════════════════════════════╩══════════╝
You can use wildcards (the * character) in Excel formula string comparison.
Try a basic Index-Match:
In Sheet 1 B2:
=Index('Sheet 2'!B:B, Match("*" & A2 & "*", 'Sheet 2'!A:A, 0))
Or SumIfs to add up what's in 'Sheet 2'!B:B if there's more than one value per input on Sheet 1.
=SumIfs('Sheet 2'!B:B, `Sheet 2`!A:A, "*" & A2 & "*" )

Hide lines with zero values

I have the following table generated by a pivot:
╔════════╦══╦══════════╦════════════╦═════════╦═════════╦═════════╦═════════╦═════════╗
║ Line # ║ ║ Car ║ Sold/Stock ║ Store 1 ║ Store 2 ║ Store 3 ║ Store 4 ║ Store 5 ║
╠════════╬══╬══════════╬════════════╬═════════╬═════════╬═════════╬═════════╬═════════╣
║ 1 ║ ║ BMW ║ Sold ║ 5 ║ 1 ║ 0 ║ 6 ║ 4 ║
║ 2 ║ ║ BMW ║ Stock ║ 2 ║ 0 ║ 2 ║ 3 ║ 4 ║
║ 3 ║ ║ Audi ║ Sold ║ 3 ║ 4 ║ 5 ║ 5 ║ 8 ║
║ 4 ║ ║ Audi ║ Stock ║ 3 ║ 1 ║ 0 ║ 0 ║ 1 ║
║ 5 ║ ║ Mercedes ║ Sold ║ 2 ║ 0 ║ 4 ║ 5 ║ 6 ║
║ 6 ║ ║ Mercedes ║ Stock ║ 0 ║ 0 ║ 0 ║ 0 ║ 0 ║
╚════════╩══╩══════════╩════════════╩═════════╩═════════╩═════════╩═════════╩═════════╝
I want to hide the last row(6). Can it be done? I can't filter columns store 1 2 3 because i only want to filter when they all are blank.
Thanks
The filters for the pivot table should show you all available values including "blank". Set the drop-down to show multiple values, and turn that one off.
You can do this in VBA, like so:
Dim hideMe as Bool
hideMe = True
For Each c In Range("E7:I7")
If c.Value <> 0 Then
hideMe = False
End If
Next
Rows(7).EntireRow.Hidden = hideMe
The script assumes that you will want to hide the row (hideMe = True), and only decides otherwise if there is any cell in that range which is different from 0.

Resources