Change Cell Reference Within a Repetition - arrays

I need to transpose data on a single row into a table. What I'm doing is taking a base inventory item and creating 6 more items from it. For example, my base inventory item is a ball, and I want to create 6 different balls from that of various colours (blue ball, black ball, and so forth). To do so, I've used the REPT function to repeat a process 6 times to create my list of inventory items.
=transpose(split(rept(C4&""&F4&""&";",6),";"))
C4 contains my base inventory item code (ie: ball) while F4 contains the subcode (ie: -blue). The formula combines these values in "ball-blue" etc.
This works just fine. The problem I'm running into is that I want to change the F4 cell reference each time it repeats. I want to shift it to the right so that I can pick up the rest of subcodes into the table.

try:
=INDEX(TRANSPOSE(IF(F4:J4<>""; C4&"-"&F4:J4; )))

Related

Use array to vary the row/column in an offset in Excel formula

Looking for a way to use an array of numbers as the offset entry in an OFFSET formula.
Data setup:
- I have a table with three columns that represent low/medium/high options
- I want to add a fourth column where the user enters 1/2/3 as their low/medium/high selection
- I want to then have a cell at the bottom that sums up the selection options
Example
User inputs in yellow cells
Formula goes in orange cell
Formula should output the sum of the green cells which are the choices in each row per the yellow cell
I have tried array formula variations of {=SUM(OFFSET([column 0],0,[column 4]))} i.e. set the anchor for the offset as one column left of the "low" options column and then the numbers 1/2/3 in column 4 to feed in as the column offset
Any ideas?
You need to force INDEX to use an array as input:
=SUM(INDEX(B:D,N(IF({1},ROW(B3:D5))),N(IF({1},(F3:F5)))))
Depending on ones's version of Excel this will need to confirmed with Ctrl-Shift-Enter instead of Enter when exiting edit mode.
If one has a subscription to Office 365 that has the dynamic array formula, Microsoft fixed the need for the forcing the array:
=SUM(INDEX(B:D,ROW(B3:D5),F3:F5))

Create lists excluded duplicates in excel

I have a MS Excel list with only 5 values in column A. There will always be one random duplicated value within this list. For example:
A1:A5
Heart
Finger
Hair
Heart
Nose
Here Heart is listed twice. I need a formula that detects the value that occurs twice in the list, and type this formula into colum B1:B3 to create a new list. The outcome of the new list should be the remaining three values - hence should not include Heart since it occurs twice.
Another example with preferred outcome...
A1:A5 Heart, Nose, Hair, Finger, Finger
B1:B3 Heart, Nose, Hair
In this example Finger is listed twice (in colum A) and therefore excluded in colum B (the new list).
Would really appreciate all hjelp and adwice with respect to how this could be solved with a formula in Excel.
If you are OK with helper columns, which you should be, you can use this solution:
Helper column 1 (enter in cell B1 and drag down):
= COUNTIF(A:A,A1)
Helper column 2 (enter in cell C1 and drag down):
= IF(B1=1,RANK(B1,B:B,1)+COUNTIF(B$1:B1,B1)-1,0)
Output column (enter in cell D1 and drag down):
= INDEX(A:A,MATCH(ROW(),C:C,0))
See below working example:
If necessary, you can use IFERROR to handle the errors in the D column.
Two formulas:
You can use:
=IFERROR(INDEX($A$1:$A$5,AGGREGATE(15,6,1/(COUNTIF($A$1:$A$5,$A$1:$A$5)=1)*ROW($A$1:$A$5),ROWS($1:1))),"")
If you have Excel 2016 with the TEXTJOIN function, you can use:
=IFERROR(INDEX(FILTERXML("<t><s>" & TEXTJOIN("</s><s>",TRUE,$A$1:$A$5) & "</s></t>","//s[not(.=preceding::*) and not(.=following::*)]"),ROWS($1:1)),"")
and fill down.
create an XML where each row is a separate node.
use FILTERXML with an xPath that filters out any node that is followed by or preceded by it's identical twin.
EDIT: If your version of Excel is prior to 2010, and lacks the AGGREGATE function, you can use the following array formula:
=IFERROR(INDEX($A$1:$A$5,SMALL(IFERROR(1/(COUNTIF($A$1:$A$5,$A$1:$A$5)=1)*ROW($A$1:$A$5),10^6),ROWS($1:1))),"")
Since this is an array formula, you need to "confirm" it by holding down ctrl + shift while hitting enter. If you do this correctly, Excel will place braces {...} around the formula as observed in the formula bar
Couple options:
If you don't care about position of the outputted elements, then this formula works:
=IF(COUNTIF($A1:$A$5,A1)>1,"",A1)
A VBA approach:
Public Function GetUniqueEntries(InputRange As Range) As Variant
Dim Cell As Range
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
For Each Cell In InputRange
If Not dict.exists(Cell.Value2) Then dict.Add Cell.Value2, Cell.Value2
Next
GetUniqueEntries = Application.Transpose(dict.Items())
End Function
Enter this as =GetUniqueEntries(A1:A5). This is an array based formula, so remember to select a wide enough output selection and press Ctrl+Shift+Enter.

Nest an Excel Array Function In a Non-Array Function and Return an Array

I am trying to create a spreadsheet that will be used to provide quotes to customers. Some part-numbers apply to a single item. Some part-numbers are bundles of up to 4 items. I am trying to create a formula that returns all of the values associated with a given part-number.
Initially, I had two section in the quote - one that uses VLOOKUP to return part-numbers with single items and one that uses an array formula that returns an array of items.
The first formula is
=IF(ISNA(VLOOKUP(B12,PriceList,2,FALSE)),"",VLOOKUP(B12,PriceList,2,FALSE))
The second is
{=IFERROR(INDEX(Bundles!$B$2:$B$101, SMALL(IF($B$33=Bundles!$A$2:$A$101, ROW(Bundles!$B$2:$B$101 ) - 1,""), ROW() - 32 )),"")}
Screenshot showing results of first two formulas
Both work fine on their own. They rely on two data tables "PriceList" and "Bundles"
I want the sales reps to be able to type a part-number in column B and get the correct part descriptions - whether it is 1, 2, 3, or 4 items - to display in column C. I want them to be able to enter multiple part numbers on the same quote.
I tried to base this on the part number
=IF(LEFT(B29,4)="BUND",IFERROR(INDEX(Bundles!$B$2:$B$101,SMALL(IF($B$29=Bundles!$A$2:$A$101,ROW(Bundles!$B$2:$B$101)-1,""),ROW()-28)),""),VLOOKUP(B29,PriceList,2,FALSE))}
This works for bundled items, but repeats single items.
I would like to have a single data source (PriceList) and a single formula.
Partnumbers in Datasource
What I am now trying to do is use COUNTIF. For example if COUNTIF returns more than 1, use the array formula, else use the VLOOKUP formula.
I picture it to be something like
IF((COUNTIF(PriceList,Quote!B11)>1),"BUNDLE",IF(ISNA(VLOOKUP(Quote!B11,PriceList,2,FALSE)),"",VLOOKUP(Quote!B11,PriceList,2,FALSE)))
where "BUNDLE" is replaced by an array function. I can't seem to come up with the right array formula.
I tried
{=IF((COUNTIF(PriceList,Quote!B11)>1),IFERROR(INDEX(Bundles!$B$2:$B$101, SMALL(IF($B$11=Bundles!$A$2:$A$101, ROW(Bundles!$B$2:$B$101 ) - 1,""), ROW() - 32 )),""),IF(ISNA(VLOOKUP(Quote!B11,PriceList,2,FALSE)),"",VLOOKUP(Quote!B11,PriceList,2,FALSE)))}
This returns four rows of the same item for single items and nothing for bundles
I had thought about placing the array function in another cell and referencing that cell, but this does not help if the bundle contains more than one item.
Any thoughts or advice would be welcome.

How do you find the corresponding value of the top item in a list with variable length?

I need to find the value corresponding with the first item in a list.
For example, below is a database with item name and it's value.
And further below is an invoice with items purchased. Cell C4 needs to bring up the first item's value only i.e. 101 for item2. Each invoice can have any number of items and I need the value only from the top item.
Below is what I'd like the result to finally look like.
I'm able to use VLOOKUP to find the last value in each list but because the length of each invoice list varies it's difficult to create a formula that finds the first that doesn't become overly complicated.
Please let me know if there is any details I can add to help.
Put this formula in C1 and copy down, (you will need to change the reference to match your data set):
=IF(B1="Value",INDEX($I$1:$I$3,IFERROR(MATCH(INDEX(A:A,AGGREGATE(14,6,ROW($B$1:INDEX(B:B,ROW()-1))/($B$1:INDEX(B:B,ROW()-1)="Value"),1)+1),$H$1:$H$3,0),1)),"")
Scott beat me to it but:
In C1
=IF(B1="Value",
VLOOKUP(OFFSET(A$1,LARGE((B$1:B1="Value")*ROW(B$1:B1),2),0),
$I$1:$J$20,2,FALSE),
"")
Where $I$1:$J$20 has your lookup table

Finding Most Common Word In A Tally/Ledger System

I currently use the following array formula to find the most common word or number in a range, ignoring any blank cells:
{=(INDEX(D1:D10,MODE(IF((D1:D10<>"")*ISNA(MATCH(D1:D10,$A$1:$A1,0)),MATCH(D1:D10,D1:D10,0)))))}
I am now looking to do something slightly different. I still want to find the most common word or number in a range, however I now have 2 lists: the first is a list of 'positive' words/numbers and the second is a list of 'negative' words/numbers.
To illustrate using an example: the colour green appears in the 'positive' list 4 times and the colour blue appears twice in the 'positive list', but green appears 3 times in the 'negative' list and blue does not appear at all in the 'negative' list. Using the above formula on the first list would return green as the most common word. However I now want it to take into account that green is not the most common word given the combined lists (i.e. 4 positives - 3 negatives = 1 green, and 2 positives - 0 negatives = 2 blue).
In the below image, using the formula under each list shows green to be the most common word. I would like to combine these lists and cancel out any instances where the colour appears on both instances - so 3 of the greens on the positive list would be cancelled out with the 3 greens on the negative list, leaving only one left.
In essence, I suppose I am trying to create a tally or ledger of some kind where rather than numbers that add or subtract I have words whose frequency is added or subtracted.
Thanks for the help, and apologies if I haven't been too clear in the task!
This should work:
=IF(SUMPRODUCT((MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1})=MAX(MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1})))/COUNTIF(B2:B11,B2:B11&""))>1,"No Favourite",INDEX(B2:B11,MATCH(MAX(MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1})),MMULT(COUNTIF(OFFSET(B2:B11,,{0,1}),B2:B11),{1;-1}),0)))
And for non-contiguous, dynamically-defined ranges, assumed to be stored as Defined Names Positive and Negative, array formula**:
=IF(SUM((COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive)=MAX(COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive)))/COUNTIF(Positive,Positive&""))>1,"No Favourite",INDEX(Positive,MATCH(MAX(COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive)),COUNTIF(Positive,Positive)-COUNTIF(Negative,Positive),0)))
Regards
**Array formulas are not entered in the same way as 'standard' formulas. Instead of pressing just ENTER, you first hold down CTRL and SHIFT, and only then press ENTER. If you've done it correctly, you'll notice Excel puts curly brackets {} around the formula (though do not attempt to manually insert these yourself).
First list your candidates in column D starting at D2
Then in E2 enter:
=COUNTIF(B$2:B$12,D2)-COUNTIF(C$2:C$12,D2)
and copy down.
Finally in F2 enter:
=INDEX(D:D,MATCH(MAX(E:E),E:E,0))
With your data:

Resources