Ok so, I will arleady say that im not that good with excel and even worse on google sheets.
I would like to know if there is a formula that checks for the name of someone and then sums the points said person got to his total. Thank you very much!
https://docs.google.com/spreadsheets/d/1D4M8Dlao8yFHJulNDff-i2jZJeVGGY_gejbAfzWdhFo/edit?usp=sharing is the link if you want to check it out.
I assume you want Punti tot. (R:R) column to have the sum of all TA Brawl (column C:C), Notte (L:L) and 50 Shades (H:H; in this case any of the two players should be checked, right?) for every player.
You can use put this in R2 (do not forget to remove everything below R2):
={
"Punti tot.";
ARRAYFORMULA(
IF(
P3:P = ""; ;
SUMIF(A3:A; P3:P; C3:C)
+ SUMIF(E3:E; P3:P; H3:H)
+ SUMIF(F3:F; P3:P; H3:H)
+ SUMIF(J3:J; P3:P; L3:L)
)
)
}
Update: here is another solution using QUERY which is also sorts players by total points:
=QUERY(
{
FILTER({A3:A\ C3:C}; A3:A <> "");
FILTER({E3:E\ H3:H}; E3:E <> "");
FILTER({F3:F\ H3:H}; F3:F <> "");
FILTER({J3:J\ L3:L}; J3:J <> "")
};
"
select Col1, SUM(Col2)
group by Col1
order by SUM(Col2) desc,
Col1
label Col1 'Player',
SUM(Col2) 'Punti tot.'
";
-1
)
And you might want to use this in O2 for ranking:
={
"Posizioni Finali";
ARRAYFORMULA(
RANK(
FILTER(Q3:Q; Q3:Q <> "");
FILTER(Q3:Q; Q3:Q <> "")
)
)
}
This way same amount of points gives players the same place. Otherwise hysen would get 9th place and Imurshh would be 10th just because h goes before i.
Related
I have a table with some data. The sheet in question does have empty rows.
Sheet1:
date
id
name
col1
col2
col3
2022-01-01
31
one
yes
1
5
2022-02-01
26
two
yes
2
4
2022-03-01
150
three
no
3
9
...
...
...
...
...
...
[empty row]
[empty row]
For each row, I have two metrics:
is good = col1 = yes
% complete = col2 / col3
I want to use an ARRAYFORMULA or something to split each row into two rows, one for each metric. So, for example, the expected output is:
date
id
name
metric
value
2022-01-01
31
one
is good
true
2022-01-01
31
one
% complete
.2
2022-02-01
26
two
is good
true
2022-02-01
26
two
% complete
.5
2022-02-01
150
three
is good
false
2022-02-01
150
three
% complete
.33
I came up with this formula, but it puts a lot of blank lines in the middle since the source data has empty rows.
=ARRAYFORMULA(
{
IF(
Sheet1!A2:A = "",
,
{
Sheet1!A2:C,
Sheet1!D2:D = "yes"
}
);
IF(
Sheet1!A2:A = "",
,
{
Sheet1!A2:C,
Sheet1!E2:E / Sheet1!F2:F
}
)
}
)
My source data has a lot of rows, so I'm trying to find an efficient way to do this. I also considered ARRAYFORMULA with column concatenation (like an unpivot) but it's horribly slow because I have so much data.
My source data also has a lot of columns that translate to 10 different metrics/rows.
I thought to try something like this so I'm only processing rows with data, but it results in a Formula parse error.
=ARRAYFORMULA(
IF(
Sheet1!A2:A = "",
,
{
Sheet1!A2:C,
Sheet1!D2:D = "yes";
Sheet1!A2:C,
Sheet1!D2:D = "yes";
}
)
)
Updated: I have created a sheet with my example data: https://docs.google.com/spreadsheets/d/1FgQ40zLd99f1xxkTtpwHStp91u5OFilyT_eigs0nYng/edit#gid=0.
parse error is a result of having a semicolon after 2nd yes. change:
="yes";}))
to
="yes"}))
pro tip: don't use such JS syntax highlighting
update 1:
=SORT({
FILTER({Sheet1!A2:C,
IFERROR(N(Sheet1!A2:A)/0, "is good"), Sheet1!D2:D="yes"}, Sheet1!A2:A<>"");
FILTER({Sheet1!A2:C,
IFERROR(N(Sheet1!A2:A)/0, "% complete"), Sheet1!E2:E/Sheet1!F2:F}, Sheet1!A2:A<>"")})
update 2:
=LAMBDA(a, b, c, d, e, SORT({
FILTER({a, IFERROR(N(b)/0, "is good"), c="yes"}, b<>"");
FILTER({a, IFERROR(N(b)/0, "% complete"), d/e}, b<>"")}))
(Sheet1!A2:C, Sheet1!A2:A, Sheet1!D2:D, Sheet1!E2:E, Sheet1!F2:F)
Use REDUCE to loop and create two rows for every row:
=REDUCE(
{Sheet1!A1:C1,"metric","value"},
Sheet1!A2:INDEX(Sheet1!A2:A,COUNTA(Sheet1!A2:A)),
LAMBDA(
a,c,
{a;
OFFSET(c,0,0,1,3),"is good", OFFSET(c,,3,1,1)="yes";
OFFSET(c,0,0,1,3),"% complete", QUERY(OFFSET(c,0,4,1,2),"select E/F label E/F ''",0)
}
)
)
I have a sheets query that almost does what I want but I need a bit of help to get to the last step.
=QUERY(Sales!$A$2:$C,"SELECT B, SUM(C)
WHERE A='"&B3&"'
GROUP BY B
ORDER BY SUM(C) DESC
LIMIT 3
LABEL SUM(C) ''
FORMAT SUM(C) '$##,##0' "
,0)
This gives me the result in C3:D4. What I want is in E3.
I have two goals. First output the data stacked and joined like in cell E3. Second, the ideal solution is an array formula in C3 that does this for all the 'Partners'.
Sample Data
As always thanks in advance for the assistance and education!
Here is how I solved it. Maybe not the optimal solution because I need to duplicate the calculation, but it does exactly what I need. I've added my solution to the example data.
=REGEXREPLACE(REGEXREPLACE(textjoin(" ♦ ",0,
QUERY({Sales!$A$2:$A,Sales!$B$2:$B,Sales!$C$2:$C},"SELECT Col2, SUM(Col3)
WHERE Col1='"&B3&"'
GROUP BY Col2
ORDER BY SUM(Col3) DESC
LIMIT 3
LABEL SUM(Col3) ''
FORMAT SUM(Col3) '$##,##0' "
,0)
)," ♦ \$"," = \$")," ♦ ",CHAR(10))
One way to accomplish this is creating a custom function in Google Apps Script. To achieve this, follow these steps:
In your spreadsheet, select Tools > Script editor to open a script bound to your file.
Copy this function in the script editor, and save the project:
function GET_TOP_CUSTOMERS(partners) {
const sheet = SpreadsheetApp.getActive().getSheetByName("Sales");
const data = sheet.getRange(2, 1, sheet.getLastRow() - 1, 3).getValues();
return partners.map(row => row[0]).map(partner => {
const partnerRows = data.filter(row => row[0] === partner);
const uniqueCustomers = [...new Set(partnerRows.map(row => row[1]))];
const topCustomers = uniqueCustomers.map(customer => {
return [customer, partnerRows.filter(row => row[1] === customer)
.reduce((acc, current) => {
return acc + current[2] }, 0)];
}).sort((a,b) => b[1] - a[1]).slice(0, 3);
return topCustomers.map(customer => customer[0] + "; $" + customer[1].toFixed())
.join("\n");
});
}
Now, if you go back to your spreadsheet, you can use this function like any in-built one. You just have to provide the appropriate range (in this case it would be B3:B12), as you can see here:
Reference:
Custom Functions in Google Sheets
I've the below formula using ImportRange and Query along with Join and Split working correctly:
=join(" / ", QUERY(IMPORTRANGE("Google-Sheet-ID","RawData!A:AC"),"select Col25 where Col1 = " & JOIN(" OR Col1 = ", split(V2:V,"+")), 0))
Also, I've the below ArrayFormula with Split function working smoothly:
=ARRAYFORMULA(if(len(V2:V)=0,,split(V2:V,"+")))
But When I tried combining them together using the below formula:
=ARRAYFORMULA(if(len(V2:V)=0,,join(" / ", QUERY(IMPORTRANGE("Google-Sheet-ID","RawData!A:AC"),"select Col25 where Col1 = " & JOIN(" OR Col1 = ", split(V2:V,"+")), 0))))
It failed, and gave me the below error:
Error
Function SPLIT parameter 1 value should be non-empty.
Here is my sheet for your testing.
UPDATE
I changed it to:
=ARRAYFORMULA(if(len(C2:C)=0,,JOIN(" OR Col1 = ", ARRAYFORMULA(if(len(C2:C)=0,,split(C2:C,"+"))))))
So my full formula is:
=ARRAYFORMULA(
if(
len(C2:C)=0,,
join(" / ",
QUERY(
IMPORTRANGE("14iNSavtvjRU0XipPWIMKyHNwXTA85P_CafFTsIPHI6c","RawData!A:AC"),"select Col25 where Col1 = " &
ARRAYFORMULA(
if(len(C2:C)=0,,
JOIN(" OR Col1 = ",
ARRAYFORMULA(
if(
len(C2:C)=0,,split(C2:C,"+")
)
)
)
)
),
0
))))
And now getting the error:
Error
JOIN range must be a single row or a single column.
I believe this formula on the tab called MK.Testing will pull the info you're hoping for.
=QUERY(IMPORTRANGE("14iNSavtvjRU0XipPWIMKyHNwXTA85P_CafFTsIPHI6c","RawData!A:AC"),"select Col25 where Col1="&TEXTJOIN(" or Col1=",TRUE,A2:A))
I think you might have been overcomplicating things? This formula just forms a text string out of the shipment IDs to use in a query. one thing that may be tripping you up is that query() is very particular about the type of data in a column. Your shipment IDs can be numbers, or they can be number letter combos, but not both. That is, if you have some shipment IDs that contain letters and others that don't, it will be more difficult to get a query that works. (though not impossible). For the sake of helping you though, it's important that your sample IDs reflect the real ones in this way as accurately as possible.
How about doing this with Apps Script? You can get the values from the Sheet2, Shipment Ids, and the Ids from MK.Testing and compare them. If they coincide, the you copy the ETA into the Column C of MK. Testing:
function myFunction() {
var sprsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet2 = sprsheet.getSheetByName("Sheet2");
var mkTesting = sprsheet.getSheetByName("MK.Testing");
var shipmentId = sheet2.getRange("A2:A").getValues();
var idList = mkTesting.getRange("A2:A").getValues();
for (var i = 0; i < shipmentId.length; i++){
for (var j = 0; j < idList.length; j++){
if (idList[j][0] == ""){break;} //Stops if there is an empty cell in Mk.Testing's column A
if (idList[j][0] === shipmentId[i][0]){
var eta = sheet2.getRange("E"+(i+2)).getValue();
mkTesting.getRange("C"+(j+2)).setValue(eta);
}
}
}
}
References:
SpreadsheetApp Class
Range Class
I have a column with a bunch of ingredients lists in it. I'm trying to figure out how many times different individual ingredients appear. There are 73,000 rows. The answers on this question works for a small amount of data in Google Sheets.
Formula is =UNIQUE(TRANSPOSE(SPLIT(JOIN(", ";A2:A);", ";FALSE)))
But I've overwhelmed JOIN with more than 50000 characters here. Is there another way to tackle this?
Sheet: https://docs.google.com/spreadsheets/d/1t0P9hMmVpwhI2IbATmIMjobuALTg8VWhl8-AQaq3zIo/edit?usp=sharing
=ARRAYFORMULA(UNIQUE(TRIM(TRANSPOSE(SPLIT(TRANSPOSE(
QUERY(","&A1:A,,5000000)),",")))))
=QUERY(QUERY(ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(TRANSPOSE(
QUERY(","&A1:A,,5000000)),",")))),
"select Col1,count(Col1)
where Col1 is not null
group by Col1
label count(Col1)''"),
"order by Col2 desc")
demo spreadsheet
=UNIQUE(TRANSPOSE(SPLIT(REGEXREPLACE(TRANSPOSE(
QUERY(ARRAYFORMULA(","&A1:A),,5000000))," ,",","),",")))
but maybe you need this (?):
=QUERY(TRANSPOSE(SPLIT(REGEXREPLACE(TRANSPOSE(
QUERY(ARRAYFORMULA(","&A1:A),,5000000))," ,",","),",")),
"select Col1,count(Col1)
where Col1 is not null
group by Col1
label count(Col1)''")
I did a google scripting solution because I wanted to play with key map pairs.
function myFunction() {
var myMap = {"candy":0};
var sh = SpreadsheetApp.getActiveSpreadsheet();
var ss = sh.getSheetByName("FIRSTSHEETNAME");
var os = sh.getSheetByName("Ingredients");
var data = ss.getDataRange().getValues();
for (var i=0; i<data.length;i++)//full
//for (var i=1; i<4000;i++)//test
{
var array = data[i][0].split( ",");
for (var j=0; j<array.length;j++)
{
var item = array[j];
//Logger.log(array[j]);
if (myMap[item]>-1){
//Logger.log("REPEAT INGREDIENT");
var num = parseInt(myMap[item]);
num++;
myMap[item]=num;
//Logger.log(item +" "+num);
} else {
myMap[item]=1;
//Logger.log("New Ingredient: "+item);
//Logger.log(myMap);
}
}
}
//Logger.log(myMap);
var output=[];
for (var key in myMap){
//Logger.log("Ack");
output.push([key,myMap[key]]);
}
//Logger.log(output);
os.getRange(2,1,output.length,output[0].length).setValues(output);
}
You'll need to add an "Ingredients" tab for the output and change your first tab to be called FIRSTSHEETNAME (or change the code). In my testing it took 4 seconds for 4 items, 5 seconds for 400 items, and 6 seconds for 4000 items. there might be an issue with leading spaces but this gives you a place to start.
A fast running formula that works with columns of at least 40,000 rows:
=query(arrayformula(TRIM(flatten(split(A2:A20000,",")))),"select Col1,Count(Col1) Where NOT (Col1='' OR Col1 contains '#VALUE!') Group By Col1 order by Count(Col1) desc label Col1 'Ingredient',Count(Col1) 'Freq.'")
FLATTEN function, combined with SQL (QUERY function) can be a solution for fast filtering of values (such as empty or error messages).
TRIM function avoids artifacts in the result due to meaningless spaces before/after each string.
Sheet: https://docs.google.com/spreadsheets/d/1m9EvhQB1Leg2H7L52WhPe66_jRrTc8VsnZcliQsxJ7s/edit?usp=sharing
*In case of false case differences, you could normalize all characters of the strings to uppercase before within the same formula with UPPER(A2:A20000).
I have searched this, but can't seem to find an answer:
I use the query function in a spreadsheet to collect comments from work assosiates. There is 17 commenters and I query from this week and ten weeks ahead. BUT, I only want the comments and not empty fields in my end result. I am almost there, but with the formula I use now, I have to manually update number of columns in the last part of the query, because the number of columns vary acording to number of comments. Here is my formula:
=transpose(query(transpose(query(QUERY(
IMPORTRANGE("1oQVZDEKLqx6ruz2yzIzUgppkWvBEOB_Eo-a4NW1WTSQ";"Comments!A1:U");
"select Col2, Col3, Col4, Col5, Col6, Col7, Col8, Col9, Col10, Col11, Col12, Col13, Col14,
Col15, Col16, Col17, Col18, Col19 where todate(Col1) > date '"&text(today()-7;
"yyyy-mm-dd")&"' limit 10");"select * where Col2<>'' or Col3<>'' or Col4<>'' or
Col5<>'' or Col6<>'' or Col7<>'' or Col8<>'' or Col9<>'' or Col10<>'' or Col11<>'' or
Col12<>'' or Col13<>'' or Col14<>'' or Col15<>'' or Col16<>'' or Col17<>'' or Col18<>''"));
"select * where Col2<>'' or Col3<>'' or Col4<>''"))
Is there any way to get this formula to work no matter how many columns the two "innermost" querys returns?
Here is the spreadsheet with the queried comments. It collects comments from this sheet (in real life this is collected from 19 sheets with the importrange-formula).
I hope my question is understandable, and most of all, my problem solvable!
This function removes empty columns and rows from a range that has row and column headers.
You can call it like this:
=FILTERROWSANDCOLS(IMPORTRANGE("1oQVZDEKLqx6ruz2yzIzUgppkWvBEOB_Eo-a4NW1WTSQ";"Comments!B1:U"))
Please note that I excluded column A for this.
function FILTERROWSANDCOLS(input) {
function rowIsBlank(row) {
return row.slice(1, row.length).join("") !== "";
}
return input.filter(rowIsBlank).transpose().filter(rowIsBlank).transpose();
}
Object.defineProperty(Object.prototype, "transpose", {value: function(){
var output = [];
for (var row = 0; row < this.length; row++) {
for (var col = 0; col < this[row].length; col++) {
if (row === 0){
output.push([this[row][col]]);
} else {
output[col].push(this[row][col]);
}
}
}
return output;
}});