SUMPRODUCT with wildcard - excel-2010

I have the SUMPRODUCT working with hardcoded values however I want to use a wild card for the B clomun in my example.
Here is my data
+----------+----------+-----------+
| A COLUMN | B COLUMN | C COLUMN |
+----------+----------+-----------+
| Status | Fruit | Quanitity |
| | | |
| Fresh | Apple | 6 |
| | | |
| Fresh | Apricot | 7 |
| | | |
| Stale | Apple | 4 |
+----------+----------+-----------+
I would like to match Fresh, AP* and then sum the matches form Column C.
I have the following
=SUMPRODUCT(--($B$2:$B$840="AP*"),--($A$2:$A$840="Fresh"),$C$2:$C$840)
Working code with the Wildcard but the count is off
=SUMPRODUCT(ISNUMBER(SEARCH"AP",$B$2:$B$840,1))*($A$2:$A$840="Fresh")*($C$2:$C$840))

The SUMPRODUCT() function does not support wildcards within an array-type expression. The same result can be achieved with:
=SUMPRODUCT((A2:A1000="Fresh")*(LEFT(B2:B1000,2)="Ap")*(C2:C1000))

Related

How to use FILTER to return rows if its value is different than the above row in Google Sheets?

I'm trying to make a "friendly" view of a more complicated sheet by filtering out unnecessary data. I want one of the filter conditions to be to return a value only if that value is different than the previous row's value.
I've tried doing a filter, such as =filter(B:B, B2 <> B1) which obviously doesn't resolve. How do I do an offset reference so that the results are similar to as follows:
Sample Data
| Row | Category | Subcategory |
| --- | -------- | ----------- |
| 1 | Accounts | Ac1 |
| 2 | Accounts | Ac2 |
| 3 | Accounts | Ac3 |
| 4 | Accounts | Ac4 |
| 5 | Feedback | FbA |
| 6 | Feedback | FbB |
| 7 | Feedback | FbC |
| 8 | Feedback | FbD |
| 9 | Profile | PfOne |
| 10 | Profile | PfTwo |
| 11 | Profile | PfThree |
Desired Result
| Row | Category | Subcategory |
| --- | -------- | ----------- |
| 1 | Accounts | Ac1 |
| 5 | Feedback | FbA |
| 9 | Profile | PfOne |
Here is another approach (assuming that your posted "Row" column is not actually part of your data, but that your "Category" header is, in fact, in A1):
=ArrayFormula({A1:B1;FILTER(A2:B,A2:A<>INDIRECT("A1:A"&ROWS(A:A)-1))})
Try:
={A1:C1;FILTER(A2:C,B1:INDEX(B:B,COUNTA(B:B),1)<>B2:B)}
go for:
=SORTN(A1:C, 9^9, 2, 2, 1)

Google Sheets - Conditional Formatting a dynamically resizing `Total` Row

I am trying to conditional format a dynamically resizing Total row of multiple tables stacked one above the other. The number of cells in the Total row may change depending upon the selection in a Year dropdown.
A | B | C | D | E | F | G | H | I | J | K | L | M |
<Year dropdown>
|Issues|2020-Jan|2020-Feb|2020-Mar|2020-Apr|2020-May|2020-Jun| | | | | | |
--------------------------------------------------------------------------------
| abc | 9 | 2 | 2 | 1 | 3 | 8 | | | | | | |
| def | 1 | 3 | 7 | 1 | 5 | 3 | | | | | | |
| ghi | 2 | 1 | 3 | 1 | 1 | 2 | | | | | | |
--------------------------------------------------------------------------------
|Total | 12 | 6 | 12 | 3 | 9 | 13 | | | | | | |
--------------------------------------------------------------------------------
I am using this formula to highlight the Total row. However, it is highlighting the entire row depending upon what range is set in the Conditional Formatting > Apply to Range box. I want to highlight only the numeric cells i.e. exclude blank cells.
=ISNUMBER(SEARCH("total",$B1))
This highlights the entire Total row including any blank cells. I modified it to exclude any blank cells in row, but no joy!
=AND(ISNUMBER(SEARCH("total",$B1)), SEARCH("total",$B1)<>""))
You can also do it like this, relying on relative addressing to modify the formula as it's effectively dragged across the formatted area:
=and(isnumber(search("Total",$B3)),B3<>"")
Use formula:
=(ISNUMBER(SEARCH("total",$B1))+(($B1:$Z1<>"")))>1

Formula to randomly assign names in a given group with Google Sheets

I would like to create a formula in the below column Assigned so that a random name matching the same group as the current name is automatically inserted.
Names in the Assigned column must match the group of the current name and must not repeat throughout the list. I can't assign the current name with it's own name either. Any suggestions on how to do this?
I guess it is worth posting this. Although it might not be practical for large groups, it is a formula solution that works in Excel and Google sheets:
=INDEX($A$2:$A$8,SMALL(IF(($B$2:$B$8=B2)*($A$2:$A$8<>A2)*(COUNTIF(C$1:C1,$A$2:$A$8)=0),ROW($A$2:$A$8)-1),
RANDBETWEEN(1,SUM(($B$2:$B$8=B2)*($A$2:$A$8<>A2)*(COUNTIF(C$1:C1,$A$2:$A$8)=0)))))
entered as an array formula using CtrlShiftEnter
Here is an example of a successful match:
and an unsuccessful one:
As you can see, Mike, Jack and Fred have paired up together leaving Dave on his own, likewise with Lucy and Harry.
In Excel you may have to press F9 a few times to get a successful result - in Google sheets you just have to keep changing something, or set it to update every minute while you make a cup of tea.
It was my first time to work on something related to unique values, it took time but I learned lot from this question.
Answer of #Tom-Sharpe gave me an inspiration that it can be done, thanks to Tom for that. I tried and here it is.
I have checked it on some random data
+------------+-------+-------------+------------+
| Name | Group | RAND | Assigned |
| Malynda | 1 | 0.644382728 | Boonie |
| Boonie | 1 | 0.167369621 | Venus |
| Venus | 1 | 0.547165865 | Malynda |
| Jamal | 2 | 0.193081046 | Cora |
| Cora | 2 | 0.399459181 | Jamal |
| Alaster | 2 | 0.910498559 | Enrika |
| Enrika | 2 | 0.45819549 | Melisandra |
| Melisandra | 2 | 0.612592303 | Alaster |
| Petunia | 3 | 0.957104883 | Lawton |
| Mariam | 3 | 0.602293619 | Grenville |
| Caterina | 3 | 0.695342797 | Mariam |
| Stace | 3 | 0.942926886 | Caterina |
| Perle1 | 3 | 0.787227158 | Stace |
| Lawton | 3 | 0.315403693 | Perle1 |
| Grenville | 3 | 0.515276361 | Petunia |
| Elia | 4 | 0.655404975 | Catarina |
| Agosto | 4 | 0.322045058 | Fidela |
| Fidela | 4 | 0.490635045 | Agosto |
| Catarina | 4 | 0.121053081 | Elia |
| Elliot | 5 | 0.994137138 | Eddie |
| Mae | 5 | 0.349103119 | Wadsworth |
| Farleigh | 5 | 0.645375865 | Mae |
| Trudey | 5 | 0.473849475 | Farleigh |
| Gwenneth | 5 | 0.678186154 | Trudey |
| Wadsworth | 5 | 0.254168853 | Gwenneth |
| Eddie | 5 | 0.02103249 | Elliot |
| Denyse | 6 | 0.294801945 | Fayina |
| Tracie | 6 | 0.113670327 | Denyse |
| Aili | 6 | 0.901562575 | Tracie |
| Fayina | 6 | 0.029515522 | Alain |
| Mort | 6 | 0.938536467 | Perle |
| Alain | 6 | 0.389741125 | Aili |
| Perle | 6 | 0.513800791 | Mort |
| Mathew | 6 | 0.972656521 | #N/A |
| Benton | 7 | 0.423710316 | Bret |
| Bret | 7 | 0.127478128 | Benton |
| Mayne | 7 | 0.701027869 | Kirbee |
| Derry | 7 | 0.564710572 | Marje |
| Kirbee | 7 | 0.510258205 | Derry |
| Marje | 7 | 0.600908601 | Mayne |
| Devin | 7 | 0.718740939 | #N/A |
| Wilbert | 8 | 0.763761013 | Griswold |
| Brandice | 8 | 0.482092682 | Marty |
| Griswold | 8 | 0.111418464 | Brandice |
| Brandais | 8 | 0.594020577 | Fair |
| Kim | 8 | 0.727863883 | Brandais |
| Cam | 8 | 0.858246187 | Kim |
| Fair | 8 | 0.640979168 | Wilbert |
| Ardath | 8 | 0.883008322 | Cam |
| Marty | 8 | 0.339506717 | Ardath |
+------------+-------+-------------+------------+
D2 contains the below formula
=INDEX(
$A$2:$A$51,
MATCH(
MIN(IF(
(COUNTIF($D$1:D1,$A$2:$A$51)=0)*
($B$2:$B$51=B2)*
($A$2:$A$51<>A2),
$C$2:$C$51)
),
$C$2:$C$51,0)
)
C2 contains just the RAND() function but it is pasted as values so that it doesn't update on every calculation, but if you want you can keep it as a function
There are some #N/A values returned by the formula, it arrives when there is no other person left that can be assigned.
Check it on your data and let me know if it working correctly.
Note that the formula is assuming that names are unique and are sorted based on the groups.
If you're fluent with javascript you could attempt to use Google Apps Script to handle this by going to the toolbar Tools > Script Editor. Another way would be to record a macro via Tools > Macros > Record Macro. The script I generated via this method is below, however I couldn't figure out how to prevent assigning the current name with it's own name. My workaround for that is to select the range of assigned names in the same group and applying Data > Randomize Range until the assignment is satisfactory.
function AppendRandomNameByGroup() {
//Sort based on integer in group column
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
spreadsheet.getActiveRange().offset(1, 0, spreadsheet.getActiveRange().getNumRows() - 1).sort({column: spreadsheet.getActiveRange().getColumn() + 1, ascending: true});
spreadsheet.getRange('C2').activate();
//Duplicate names to assigned names column
spreadsheet.getRange('A2:A1000').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
//Filter for each group and randomize items in 'assigned' column
sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).createFilter();
spreadsheet.getRange('B1').activate();
var criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(['', '2', '3'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(2, criteria);
spreadsheet.getRange('C2:C1000').activate();
spreadsheet.setCurrentCell(spreadsheet.getRange('C4'));
spreadsheet.getActiveRange().randomize();
spreadsheet.getRange('B1').activate();
criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(['1', '', '3'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(2, criteria);
spreadsheet.getRange('C2:C1000').activate()
.randomize();
spreadsheet.getRange('B1').activate();
criteria = SpreadsheetApp.newFilterCriteria()
.setHiddenValues(['2', '', '1'])
.build();
spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(2, criteria);
spreadsheet.getRange('C2:C1000').activate();
spreadsheet.setCurrentCell(spreadsheet.getRange('C8'));
spreadsheet.getActiveRange().randomize();
spreadsheet.getActiveSheet().getFilter().remove();
};
If you're trying to set-up a secret santa of some kind, another possible alternative to using scripts would be this Google Sheets Add-On that does something similar including the group functionality that you desire. However instead of assigning a recipient name in-sheet, it requires you to input corresponding e-mail addresses for each name and proceeds to email each participant with their assigned name.
Secret Santa
Sorry that this doesn't fit all your criteria.

Try to match string in column and print matching column name

I am trying to build an expense dashboard in google sheets for my personal use.
I have data that I will pull from my receipts like so:
First sheet: "Expenses Feb 18"
+------------+--------+--------+
| Item | Amount | Type |
+------------+--------+--------+
| Tomatoes | 2.39 | veggie |
| Joghurt | 1.45 | dairy |
| mozzarella | 1.99 | dairy |
| macadamia | 4.59 | nuts |
+------------+--------+--------+
Second table: "Categories"
+------------+----------+-----------+---------------+
| dairy | veggie | nuts | uncategorised |
+------------+----------+-----------+---------------+
| joghurt | tomatoes | macadamia | a |
| mozzarella | cucumber | pecan | b |
| feta | | | c |
| | | | d-z |
| | | | 0-9 |
| | | | - |
| | | | _ |
+------------+----------+-----------+---------------+
I want to automatically fill out the type column based on the item name.
So far I have a regex that is able to match an item. It will print the matched string. But what I need is the column name (header). And it has to be able to loop through the columns. This only works for a single column.
=REGEXEXTRACT(C11, JOIN("|", INDIRECT("Categories!A1:A"&COUNTA(Categories!A:A))))
The second table is not a desirable way to enter data. Data should be entered preferably with more rows than columns ( not in a pivoted manner).
=ARRAYFORMULA(CONCATENATE(IF(A16=$C$24:$E$25,C$23:E$23,)))
A16 : 🍅
C24:E25: Category table
C23:E23: Category header.

How can I capture and store data from a repeating HL7 segement?

We currently capture data from HL7 messages like below and then insert the same in database. This is easy as it is value from a single segment
var vACC_NO =checkSize("ACC",msg['PID']['PID.3']['PID.3.1'].toString(),20);
INSERT INTO adt_tab ( SITEID,ACC_NO) VALUES (vSITEID,vACC_NO);
Now I need to capture DG1 segment data, where we have multiple DG1 segments in HL7 message. And also need to store in Database
| DG1 | 1 | ICD10 | I22.8^MYOCARDIAL INFARCT^ICD10 | MYOCARDIAL | | | | | | | | | | | |
| INFARCTION | 201702010437 | B | | | | | | | | | 7 | | | | |
| DG1 | 2 | ICD10 | A44.9^ORGANISM^ICD10 | ORGANISM | 20170201 0437 | B | | | | | | | | | 7 |
So in my database table I have now more columns - SITEID, ACC_NO, CODE1, CODE2...
From the above message I need to insert I22.8 into CODE 1, A44.9 into CODE2 and so on ..
How I should first capture these codes in loop from multiple DG1 segments in the message ?
And then how I should store it in the database ?
Thanks
You can iterate over the segments like this
for each (dg1 in msg['DG1']){
variable1 = dg1['DG1.3']['DG1.3.1'];
variable2 = dg1['DG1.3']['DG1.3.2'];
// database call with the previus
databaseCall(variable1,variable2, ...
}
For each segment you are going to do an insert.
Apart from this, I do not think is a good idea to make more columns in the same row by adding variable1, variable2, variable3 ... as it is not normalized and it not a good database design practice.

Resources