Conflict Matrix: C = conflict, A = accessible, X = same
Conflict Matrix is as below image
Using the above table as an example, if I wanted to find the access for A & B I would look down the first column for A, and across the first row for B.
The intersection of these two letters would return C for Conflict.
If your data table is in cells A1:I9 and your key lookup is in cells K1:L3 (i.e K1 contains C, L1 is Conflict) you can use a combination of VLOOKUP, INDEX and MATCH.
MATCH("A",$A$1:$A$9,0) will return the row number that A appears in on column A.
MATCH("B",$A$1:$I$1,0) will return the column number that B appears in on row 1.
INDEX($A$1:$I$9, RowNum, ColumnNum) will return the value at the intersection of RowNum & ColumnNum
VLOOKUP(ReturnedValue,$K$1:$L$3,2,FALSE) will return the looked up value of C, A or X.
Stick the four formula together to get your final result (change "A" & "B" to the access values you're looking for:
=VLOOKUP(INDEX($A$1:$I$9,MATCH("A",$A$1:$A$9,0),MATCH("B",$A$1:$I$1,0)),$K$1:$L$3,2,FALSE)
Further reading:
MATCH
INDEX
VLOOKUP
I have a number of narrative descriptions that I need to categorize automatically in Excel:
Description Category
I updated the o.s.
I installed the o.s.
I cleaned valve a
I cleaned valve b
I installed valve a
Today the o.s. was updated
I have another worksheet with keywords and the category the keywords are associated with:
Keyword 1 Keyword 2 Keyword 3 Category
cleaned valve a A
installed valve a B
updated os C
installed os D
My code so far can only search one keyword at a time and therefore will report incorrect answers because some keywords are used in multiple narratives:
Public Function Test21(nar As Range, ky As Range) As String
Dim sTmp As String, vWrd As Variant, vWrds As Variant
'Splits Fsr Narrative into individual words so it can be searched for keywords'
vWrds = Split(nar)
For Each vWrd In vWrds
If Not IsError(Application.VLookup(vWrd, ky, 3, False)) Then
sTmp = Application.VLookup(vWrd, ky, 3, False)
Exit For
End If
Next vWrd
Test21 = sTmp
End Function
I've seen algorithms like this but I feel that my goal could be simpler to accomplish as all narratives are relatively simple.
Thanks for reading!
You can match multiple columns with a VLOOKUP by creating a "match column" that concatenates the multiple values together, then searching that column for a match.
So if you use this formula in column A:
=B1 & "|" & C1 & "|" & D1
You can then VLOOKUP against that match column:
=VLOOKUP("blah|bleh|ugh", 'Sheet2!A1:E100', 5, FALSE)
Which will match the one row that has "blah" in column B, "bleh" in column C, and "ugh" in column D, and return the value in column E.
For your data though, I think you might also want to have a step to clean up your input before trying to match a set of keywords. The method I described above works best if the keywords are in a particular order, and where you won't have any non-keywords cluttering up things. (It also works excellently for vlookups where you want to match multiple pieces of data, ie. first name, middle name, and last name in different columns)
Otherwise you could end up needing an incredibly huge number of rows in your category table to cover every possible combination and permutation of your keywords and the other random words they might be accompanied by.
This is what I was looking for:
Public Function Test22(nar As Range, key As Range, cat As Range) As String
For r = 1 To key.Height
If InStr(nar, key(r, 1)) And InStr(nar, key(r, 2)) Then
Test22 = cat(r)
Exit For
End If
Next r
End Function
How can I set things up in google sheets such that it will take my input in, say cell B2, clean it up and put things in cells C2 and D2?
For example, say I put in cell B2 the string "ts 4 x 4 x 3/8 x 13'-5". I can of course write a script called std_shape that can parse this into the ouput array ["HSS4X4X3/8", "13'-5""] and when I put =std_shape(B2) into the cell C2, I'll get what I want: C2 will contain HSS4X4X3/8 and cell D2 will contain "13'-5"". But how to do this such that column C & D will automatically fill in from any row in B? Using an arrayformula() tends to fill downward on column C.
What would be the most efficient way of going about this? I want to be able to make a list of material in column B and then have columns C & D format my list in the way described. For instance columns C & D would be derived from my B column inputs as below (where I've separated the columns with the "|" symbol):
> B | C | D
> ------------------------+---------------+----------
> TS 4x4x1/4 x 13'-4 | HSS4X4X1/4 | 13'-4"
> L 5 x 3-1/2 x 5/16 x 6' | L5X3-1/2X5/16 | 6'-0"
> PL 1/2 x 8 x 10 | PL1/2X8 | 0'-10"
> W10x12 x 13' | W10X12 | 13'-0"
Columns C & D have standardized what was put into B. Further cells in the spreadsheet will work with these standard texts for vlookups and other calculations. I want to keep B as input though. I also wish to validate the input in B as well. For instance, say the W10x12 above cannot be found in a vlookup, then column C for that row would say something like "W10x12 is not a valid entry".
What I'm saying is that I don't know how to handle ranges in my script. I also would like to know the most efficient way of going about this. After all, for any given row, columns C & D only care about that particular row's B value - I don't want my function tossing arrays around willy nilly. Maybe some sort of "onEdit" type deal that creates columns C & D whenever the B entry is edited for any particular row?
I'm having brain stalls with this since user-defined functions can't touch any other cells except in overflow. There's GOT to be some way to do such a thing as I'm describing here?
So I'm neck deep in this macro that I've created. My peers are requesting more on outputs than I had originally displayed. I need a macro that can do the following. So the question I have could normally be solved with VLOOKUP. However, in this case it is very important to know if there are really two answers and what both would be, making VLOOKUP obsolete. So lets say I have 2 columns. One showing Run # and the other showing Vertical, Curve, or Lateral (they progress down the column in that order). lets say Run #1 is Vertical. Run #2 began vertical, but finished curved. Run #3 is curve, but finished lateral. Finally, run #4 is lateral.Example:
Run# Section
1 Vertical
1 Vertical
1 Vertical
2 Vertical
2 Vertical
2 Curve
2 Curve
3 Curve
3 Curve
3 Lateral
3 Lateral
4 Lateral
4 Lateral
4 Lateral
4 Lateral
What I need is this below. Basically before I would preform this, I would be using a pivot table with Run# in "Rows" and then collecting other data in it as well. I then will copy and paste the value's only to a different sheet where then I will need to add in the values in "section" as shown below.
Run# Section
1 Vertical
2 Vertical & Curve
3 Curve & Lateral
4 Lateral
Thanks for taking a look at this guys. I've tried finding something on this, but nothing shows multiple results in the same cell. Any help is greatly appreciated! Have a great day!
I have a udf called JOINDISTINCT (code below) - you can use this in conjunction with an array formula to do what you need.
For the formula, assuming that your run data is in columns A and B and that column E has the distinct run list, in F2 have the array formula (entered with Ctrl+Shift+Enter)
=JOINDISTINCT(IF($A$1:$A$16=E2,$B$1:$B$16,"")," & ")
Note that we don't use the whole column, just the populated range, in order to speed up execution. The array part checks column A values to be matching the run number in E2 and then will return the Section or blank. The JOINDISINCT takes that array and returns the distinct list, separated by (in this case) " & "
VBA Code for the function
Public Function JOINDISTINCT(rng As Variant, Optional separator = ", ") As String
JOINDISTINCT = ""
Dim v As String
'Dictionary needs REFERENCE: Microsoft Scripting Runtime
Dim dict As New Dictionary
For Each c In rng
If IsObject(c) Then
v = c.Text
Else
v = c
End If
If v <> "" Then
If Not (dict.Exists(v)) Then
dict.Add v, 1
If JOINDISTINCT = "" Then
JOINDISTINCT = v
Else
JOINDISTINCT = JOINDISTINCT & separator & v
End If
End If
End If
Next c
Set dict = Nothing
End Function
I am trying to improve a complex lookup procedure that I have inherited. The lookup was being generated through several UDF combined with some standard worksheet functions. However, the issue was that when the user updated some data in the source sheet, the re-calc time was unacceptable.
So, I took a look and thought I may be able to write a better Excel formula only solution. Well, I did find a solution, but it is too much for Excel to handle on large data sets, and it crashes (understandably so!) when my VBA runs the formulas against the dataset.
Now, I could implement this in VBA fully, but then the user would have to press a button or something to update after every change. What I would like is a more simpler approach, if there is one, using some of the advanced Excel 2007 formulas. Since I am not as well-versed on those formulas, I am reaching out for some help!
Okay, here is what I have to work with.
SourceSheet
Tid's, Settlement Dates, and month-end prices (layer periods identified by 1,2,3, etc) in columns like below
Tid SettleDate 1 2 3 4 5 6 7 8 9 10 ... n
FormulaSheet
Amongst other columns, I have the following columns
InitLayer LiqdLayer InstrClass Tid SettleDate InitPrice LiqdPrice Position
I also have the layer numbers in columns to the right of the entire data set, like this:
1 2 3 4 5 ... n
What I need to do is fill in the proper price changes in these columns based on some logic in the dataset by looking up the prices on the source sheet.
In psuedo-formula, this is what I need to happen for each layer column in the FormulaSheet
If Layer < InitLayer OR Layer > LiqdLayer Then Return "-"
ElseIf Layer = InitLayer Then (Layered Price - InitPrice) * Position
where Layered Price is obtained by finding the Intersect of the LayerNumber
Column and Tid Row in the SourceSheet
ElseIf Layer = LiqdLayer Then Previous Layered Price * Position
where Previous Layered Price is obtained by finding the Intersect of the Previous
LayerNumber Column and Tid Row in the SourceSheet
Else (LayeredPrice - Previous Layered Price) * 6
where Layered Price and Previous Layered Price are defined as above
End If
I did come up with this formula, which works well on small data sets, but its toooooooooo big and nasty for large data sets, or just too big and nasty period!
=IF(OR(CH$3<$AT6,CH$3>$AU6),"-",IF($AT6=CH$3,(HLOOKUP(CH$3,layered_prices,RIGHT(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4),LEN(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4))-1)-1,FALSE)-$AV6)*$C6,IF($AU6=CH$3,($AW6-HLOOKUP(CG$3,layered_prices,RIGHT(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4),LEN(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4))-1)-1,FALSE))*$C6,(HLOOKUP(CH$3,layered_prices,RIGHT(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4),LEN(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4))-1)-1,FALSE)-HLOOKUP(CG$3,layered_prices,RIGHT(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4),LEN(ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4))-1)-1,FALSE))*$C6)))
Formula Key
CH = Layer Number
CG = Previous Layer Number
AT = InitLayer
AU = LiqdLayer
AX = InstrClass (used to find a separate lookup for Currencies)
T = Tid
G = SettleDate (used to find a separate lookup for Currencies)
AV = InitPrice
AW = LiqPrice
C = Position
layered_prices = named range for the range of prices under the layer columns in SourceSheet
layered_tid = named range for tid rows in SourceSheet
layered_curtid = named range for currency tid rows in Source Sheet (just a separte lookup if InstrType = Currency, formula the same
Are there any other formulas, or combination of formulas that will allow me to get what I am seeking in a more efficient manner than the monstrosity I have created?
I agree with Kharoof's comment. You should break this formula into several columns. From my count, you need 4 more columns. The benefits are two-fold: 1) Your formula gets much shorter because you're not repeating the same function over and over and 2) You save memory because Excel will calculate it once instead of several times.
For instance, you call the exact same ADDRESS function four times. Excel doesn't "remember" what it was when evaluating a formula and so it calculates it anew each time. If you put it in it's own cell, then Excel will evaluate the cell before any cells that depend on it and store it as a value instead of the formula. When other cells reference it, Excel will provide the pre-evaluated result.
First, here's what your final formula should be: (The names in [brackets] indicate that a helper column fits there. It'll be some cell reference like CI$3 but I wasn't sure where you'd want to put it. You'll have to update those references based on where you add these columns.)
=IF(OR(CH$3<$AT6,CH$3>$AU6),"-",IF($AT6=CH$3,([LayerNumber]-$AV6)*$C6,IF($AU6=CH$3,($AW6-[PreviousLayerNumber])*$C6,([LayerNumber]-[PreviousLayerNumber])*$C6)))
And here are the four helper columns:
[ADDRESS] = ADDRESS(MATCH(IF($AX6="CUR",$T6 & " " & $G6,$T6),IF($AX6="CUR",layered_curtid,layered_tid),1),1,4)
[RIGHT] = RIGHT([ADDRESS],LEN([ADDRESS])-1)
[LayerNumber] = HLOOKUP(CH$3,layered_prices,[RIGHT]-1,FALSE)
[PreviousLayerNumber] = HLOOKUP(CG$3,layered_prices,[RIGHT]-1,FALSE)
By splitting it up, each step of the formula is easier to follow / debug as well as faster to process for Excel. If you want some quantitative improvement, the five formulas combined will be around 70% shorter than the single formula you have right now.