Coloring Excel Cell based on a table condition - vba

I am going through the users of a system and reviewing if they have appropriate role names. I then completed an excel table that looks abit like this:
I'm trying to turn the table into a more readable format. I have made a pivot that looks like this:
But I'm not sure how to highlight the cells to reflect the 'Access Appropriate? Yes/No' column. Ideally, it should be colored yellow if the 'Access Appropriate?' = 'No'. I'm thinking of using VBA, but was wondering if there is an easier solution using formulas or pivot table?

Your pivoted data isn't an actual excel pivot table, is it? I know what the x mean, but where do they come from?
Two possibilities come to mind if you want a flexible setup without VBA, aswell as an rather simple VBA-approach that uses an UDF.
Quick'n'dirty (really dirty) would be to
use 1/0 instead of yes/no (you could write that into a helper column with an if-function)
create a new pivot with ROLE_NAME for columns, USER_NAME for rows and SUM or MAX of [Access appropriate] for values
that means: instead of your x you will end up having 1 and 0. Empty cells will still be empty.
conditional format the value-range, e.g. If 1 then green If 0 then yellow if "" then Nothing
Alternatively, you could build your output-table with formulas like INDEX, MATCH and VLOOKUP-formulas.
An additional Key-Column with USERNAME&ROLE_NAME will be needed
conditional format the value-range
VBA: Provided your Rows are distinct a user defined function could do the following
read data into a recordset IF that hasnt been done already (meaning: declared on module-level, the first function call will fill it)
access the data in your recordset with a Recordset.Filter based on your input parameters - USERNAME and ROLE_NAME, in your case
output a certain Field.Value based on your input parameter - Access Appropriate in your case
conditional format the TRUE/FALSE values you get (since this can't easily be done inside an UDF)

Related

Excel Named Range Formula - Not Automatic Updating

I have a table in Excel that has column heading names (e.g. data_type1, data_type2, etc.). The data in this table changes based on parameters entered on another sheet, and they are pulled to charts which update dynamically.
As a convenience to a user who might be using this sheet I have added a 'user specified function' (non-vba) which also plots to one of the charts. By user specified function I mean I have three cells with dropdown lists. Two correspond to the table headings and one has a short list of operations that can be applied between the two selected data types (e.g. a user might select 'dataype1', '+', 'datatype2' which would produce a sum of the two in the final column of my table).
The user specified function is achieved by defining a named 'range/function' to match the drop downs with their respective column headers and then calls evaluate. See below:
=EVALUATE("="&ADDRESS(ROW('Raw Data'!XFD5),MATCH(user_in1,'Raw Data'!$A$4:$AF$4,0)) & user_operation & ADDRESS(ROW('Raw Data'!XFD5),MATCH(user_in2,'Raw Data'!$A$4:$AF$4,0)))
I name this 'user1_result' and then enter =user1_result in the final column of my table. This approach is nice because it calculates much faster than doing the same thing through building a UDF in VBA and then applying that UDF to every cell in a fairly long column.
Now here is my hangup, this works fine initially, but if the user makes a parameter change that affects one or both of the selected datatypes, the user specified column does not recalculate on-the-fly with the updated data. If the user re-toggles any of the dropdowns the data does recalculate. I am speculating this is from one of two things:
1) Excel does not recognize that a precedent of 'user1_result' has changed, and so for efficiency sake doesn't bother to recompute the column;
2) The 'Evaluate' function used in the named definition of 'user1_result' is not checked for updating, because it's not a normal function (doesn't show up through intellisense if you try to just add that to a cell).
So I am looking for some either confirmation or refutation of these speculations. In the case of confirmation I am hoping to get some advice on how to force the user specified column to update if its precedents change.
One solution is to have VBA do this checking for me and force the computation, but I would like to leave that as a last resort. So, non-VBA solutions preferred.
For posterity I'll answer the above question based on Mat'sMug's feedback:
Regarding the cause of the problem:
The reason the user specified column does not update is because the 'Evaluate' portion of the 'user1_result' named formula is intended to be used at the application level and not as a worksheet function. Because of this, Excel doesn't bother checking to see if its precedents change and ignores it for recalculation.
The problem's solution:
It was suggested to use VBA to watch for worksheet_change events, however, my problem requires that I do NOT use VBA. So, an alternative workaround that forces Excel to check precedents and recalculate the user specified function uses two steps. This functions as a pseudo worksheet_change stand-in.
First, I use a helper cell that performs a countif with an arbitrary counting condition. I don't need it to change, I just need it to share precedents with the inputs of 'user1_result'. So I have it count the number of cells in the first row of data that are larger than some constant:
=COUNTIF(A5:AK5,">100000")
The result of this computation doesn't matter, but in my case my data have small values and so this returns 0 always.
Second, I use a condition for the computation in the user specified column (the last column in my data table).
=IF($AO$1=$AO$1,user1_result)
Now, anytime my data table updates, the final column using the named function recomputes. Simple, and if using macros is not viable (for example due to a client/user's security concerns), this can sort of substitute for a worksheet change event.
I hope somebody out there gets use from this!

extract data in exel sheet using macro

you most probably going to think "what an idiot" but remember i never done any type of coding before so this is all new to me,
My problem are that i'm working on a HUGE excel sheet with loads of data that is not needed. i need to sort the data into a few columns, i only need column "A,K,AN,AQ" but in column "AS" i only need certain values (yes,no,blank) i only want the yes and blank values. like i said never done any coding before but i know that you can use an macro to do it so please help, how do i go about this?
before trying to get into macros, try to use functions with if else statements. They are quite easy to handle. Like: If (yes) then put it into X. Later, you could select all needed. Also, check the, how the dollar sign is used
use this links to see, if it is something for you.
One quick and dirty way of getting this job done would be to:
Delete the columns you don't need.
Select all cells in the range you're interested in, click the Insert menu, and choose "Table". If your columns have titles, select the box for "My Table has Headers."
-This turns your data into an array so that Excel recognizes that each row is an entry (instead of thinking that the cells are unrelated).
Now you can use the filter icon in the column headers to select and display only the rows containing the values in column X that you're interested in.
Note that there are some limitations to what the table feature is good for, so, as always, whether this is a good solution for you depends on what you want to do with the data.

Query several ranges and add automatically a column to know the source of each row

I am trying to achieve the following in Google Spreadsheets.
First, I want to query several ranges (in different sheets from the same spreadsheet). I tried a formula like this =query(arrayformula({indirect(E2:E10)}),"select * where Col1 <>''") with no success
In E2:E10 I have a list of ranges. Column F contains a name that describes the source of the value in Column E.
My second problem is that I need to add a column to the output of that query that tells me the origin of each row.
If the sources are ranges of 3 columns by country I need to merge those tables and add that country to each row.
All credits to +Ben Liebrand who helped me out here: https://support.google.com/docs/profile/3464
"I just want to start of by saying that the indirect() function does not work in an arrayformula() function as expected. So you will need to take another approach. I can understand what you are trying to do so I added another TAB in your spreadsheet to demonstrate another approach. I know it was initially a specific design you were trying so I made some changes to what you had. Maybe you can take a look at what I have offered and maybe you can tweak your design.
I know what I am offering is just very rough but you will also notice that I removed the end row specifier from your ranges in the range table.
Don't assume my example to be the final result but I was just trying to show that the range you were trying to use with the indirect() function will not work.
So hopefully this will give you a new idea of how you can maybe handle this.
My formula also adds the country to each of the tables in the output. My formula looks like this
=query(ArrayFormula({
if(len(indirect(regexextract(F2,"\w+\!\w+")&":A")),G2,),indirect(F2);
if(len(indirect(regexextract(F3,"\w+\!\w+")&":A")),G3,),indirect(F3);
if(len(indirect(regexextract(F4,"\w+\!\w+")&":A")),G4,),indirect(F4);
if(len(indirect(regexextract(F5,"\w+\!\w+")&":A")),G5,),indirect(F5);
if(len(indirect(regexextract(F6,"\w+\!\w+")&":A")),G6,),indirect(F6);
if(len(indirect(regexextract(F7,"\w+\!\w+")&":A")),G7,),indirect(F7)
})," select * where Col1 <> '' ")
Hope this is of some help to you"
And I hope is useful to the community
GerĂ³nimo

Need a simple search function to display most common value in a column. (with ambiguous choices)

I have a very large array of data with many columns that display different outputs for the values presented. I would like to add a row above the data that will display the most common occurring value or word below.
Generally I would like to have each top of the column (right under the column label in row 1) have the most common value below. I will then use this value for various data analysis functions!
Is this possible, and if so, how? Preferably this will not require VBA, but simply a short code in the cell.
One caveat: The exact values may vary, so there is no set list where I can say "it will be one of these."
Any ideas appreciated!
Try a series of =COUNTIF(A:A,"VALUE TO SEARCH") functions if you want to stay away from VBA.
Otherwise, the best method would be to iterate through each column via VBA. With this method, you can even count the "varying" values and return the count and/or the value itself.
http://www.excel-easy.com/examples/most-frequently-occurring-word.html
This is a single formula you would write at the top of each column. Does not require VBA. You can replace the set range to an entire column, such as (A:A) instead of (A1:A7).
If you mean an array as in a data type, it could work differently but it depends what you're trying to do.
With data from A3 through A16, in A2 enter:
=INDEX($A$3:$A$16,MODE(MATCH($A$3:$A$16,$A$3:$A$16,0)))
This will work for text as well as numbers. Adjust this to match the column size.

Use columns.add(...) in Word with non-uniform column widths?

Problem I'm having is that table.Columns.add(ref Object BeforeColumn) requires a reference to another column in the table. However, when I try to access the last column in the table to pass as a reference using table.Columns.Add(table.Columns[table.Columns.Count])
I get the error:
"Cannot access individual columns in this collection because the table has mixed cell widths."
As my current work around, I catch the error, and call table.Columns.DistributeWidth() to make sure the columns are uniform and run the rest of the code. However, I lose the formatting of my cell widths this way, which is unfortunate.
Is there any way I can workaround this without losing the cell width?
(I realize one way is to store every cell's width before running this process, and then re-applying the widths afterward, but this seems like a very costly solution to something that should be simpler)
I've found one way to do it. Here's how I approached it.
*Caution, I'm assuming that the table is uniform. i.e. The number of columns is the same across all the rows. (Note, the API has a Table.uniform function, but the description is not complete. In the API it says "True if all the rows in a table have the same number of columns." However, it also checks if the columns have uniform width).
Instead of using table.Columns.Add(table.Columns[table.Columns.Count]) to add a column before the last below, I select a cell in the table and used the insert command:
//assuming table is the name of the table you want to add columns to
table.Cell(1, table.Columns.Count).Select();
word.Selection selection = table.Application.ActiveWindow.Selection;
selection.InsertColumns();
This might actually be a better way to add columns, as the api gives you way more options on how to insert (i.e. use InsertColumnsRight to insert to the right of the column). The Columns.Add(...) function by default inserts to the left of the select