Weighted Grades by Category, Multiple Students/Cats - google-apps-script

Looking for a way to track students grades in sheets and have their overall grades calculate depending on scores for each assignment/category.
So all assignments are 40% of the overall grade, Assessments- 40%, and Progress- 20%.
My thinking is that a script would make this much more useful and easier than a massive ifs formula.
Attached is a sample of what/how it would be set up...
sample of sheet
Thank you in advance.

So google sheets does have a AVERAGE.WEIGHTED formula which should make it possible for you to do what you want, hopefully. It also appears like you have set up data validation for the assignment type drop down menu and have the appropriate points displaying on the row above. (If you have not done this, then it is possible for the Pts header to be automatically updated based on your grade scale using a VLOOKUP).
Determining the weighted average should only require adding formulas to the "Overall Grade" column. Below is a formula you can use that should work for you:
=AVERAGE.WEIGHTED(D5:F5,$D$2:$F$2)
Basically, it takes the row of assignments (row 5 in my example) and compares it to a corresponding locked list where the weights appear in row 2. You will need to modify the array slightly for your purposes just so its long enough to reach as far as your row of data. This can be done by changing "F" in the formula example to be the farthest column of data. This formula can be drag-and-dropped as far down as you like on the overall grade column. It will display results like this:
EDIT:
To take into account maximum points allowed per unique assignment requires a little bit more set up but is still very doable. Basically, we can do the same thing as before but before we average the values we need to determine the values in consistent scale. For example, if a student makes an 15 on an assignment with a max points allowed of 15, they make 100%. Likewise if they make a 2.5 on an assignment with a max point allowed of 5 then they make a 50%.
We can determine this by taking the points earned / max points * 100. We need to determine these new values before applying the weights.
To make things much easier, it would be best to add a new header which provides the corresponding max points for the selected assignments. Again, this can be added to the legend and then referenced using a VLOOKUP with exact match. So something like this (if you don't like the max points row showing you can even hide the row):
Once this information is added, we will have an easier time referencing the max value per student entry. We can calculate the 100% grade scale automatically for the row with an =ARRAYFORMULA insertion. The same formula we used earlier to find the weighted average can be modified to the following:
=AVERAGE.WEIGHTED(ARRAYFORMULA(D5:F5/$D$3:$F$3*100),$D$2:$F$2)
With this new formula the new "Overall Grade" column will take into account both the grade weights as well as the max points allowed for each assignment type on a 100% point scale.

Related

Would like blank cells to show value of adjacent cell

I made a budgeting spreadsheet and have a "current" and "ideal" column. Current is what I'm spending now. Ideal is what I'd like to be spending. In some cases the "ideal" number is the same as "current."
What I would like to do is put in "ideal" values where necessary and otherwise just give the value of the "current" cell.
For example:
Expense
Current
Ideal
Rent
3000
Vacation
1000
5000
I don't plan to move so my rent would, ideally, still be 3000. But I'd like to spend more on vacation. So what I'd want is a formula for the ideal row that would show the value of the adjacent cell if the ideal cell is blank. I suppose it would be something like this:
if (isblank(this_cell), offset(this_cell, 0, -1))
So far I can't even find a way to reference the current cell at all - I found suggestions but they all gave me a circular reference error. And I don't know if offset is the best function but I've been googling around and it seems like a possibility.
Can this be done, and if so, how?

How can I reduce google sheets lag by replacing thousands of cell by cell formula calculations with an elegant script?

first time posting, so bear with me.
I have successfully designed a google sheet that automatically creates a crop map based on the crop plan in another tab ('Successions')
In 'Successions' the following columns are relevant:
Column A - Succession ID
Column C - Row ID
Column R - Planting Date
Column W - Harvest Date
In "Map 1A" I have created a map of our field, with Column B representing the Row ID and the columns to the right each representing a week of the year, whose start dates are defined in row 2.
My goal is to map each succession on the appropriate row for the duration that it will be in the ground (Planting Date to Harvest Date). I will have different successions occupying the same row during different date ranges.
I accomplished this in three steps:
Step 1
Every cell (except the left most column) contains a formula that returns and text joins (if multiple results) any successions in that row during that week - if an only if the value it would return is different than the value the cell to left would return. The result is that the succession ID is only displayed on the week that it starts. The formula in these cells is:
=Iferror(If((Textjoin(" / ",True,FILTER(Successions!$A$2:$A$647,RegExMatch(Successions!$C$2:$C$647,$B3),Successions!$R$2:$R$647<D$2,Successions!$W$2:$W$647>D$2)))=(Textjoin(" / ",True,Iferror(FILTER(Successions!$A$2:$A$647,RegExMatch(Successions!$C$2:$C$647,$B3),Successions!$R$2:$R$647<C$2,Successions!$W$2:$W$647>C$2),""))),"",(Textjoin(" / ",True,FILTER(Successions!$A$2:$A$647,RegExMatch(Successions!$C$2:$C$647,$B3),Successions!$R$2:$R$647<D$2,Successions!$W$2:$W$647>D$2)))),"")
The code for the leftmost column, which I did not want to check the cell to the left is:
=Iferror((Textjoin(" / ",True,FILTER(Successions!$A$2:$A$647,RegExMatch(Successions!$C$2:$C$647,$B3),Successions!$R$2:$R$647<C$2,Successions!$W$2:$W$647>C$2))),"")
Step 2
Because every cell contains a formula, I could not get the succession ID to spill into the adjacent cell and thus be readable. To solve this, I have an adjacent tab called "Map Final" that mirrors "Map 1A" via an Array Formula. Because it does not carry over formulas just values, it allows text to spill over.
Step 3
Conditional formatting is applied to "Map Final" via the Custom Formula function. There will be a rule for each crop type. Each succession is automatically colored the color of its crop type, and the color fills all cells for the duration of the succession.
My question is this:
How could I accomplish this same mapping in a more efficient way? Currently any update to Successions takes 30 seconds to a minute to update. The progress bars are killing me and basically make this really cool tool unusable for crop planning purposes, during which we are going back and forth from data to map frequently to make placement decisions.
Do you think this is possible using a custom script that pushes data rather than pulling data?
Would it render faster, or is the way I'm doing it the most efficient way?
While that is my main question, I am certainly open to any advice you have for improving speed by simply refining my current method.
Thanks in advance for any help you can provide!

Cumulative sum running on all the columns in a spreadsheet

I have a spreadsheet with a lot of columns for each year, and I need a formula that I can apply on the entire table to update the cumulative sum. Better explanation in the picture below:
The top part is how I have the table currently. The bottom part is how I need the table to be, and be able to make updates any time to any cell.
At the moment I am just having a separate 'table' of all that, where I run this formula:
=ArrayFormula(SUMIF(COLUMN(B3:J3),"<="&COLUMN(B3:J3),B3:J3))
What I need is this applied to the entire table, so whenever I make an update in any cell, it will update and run the entire cumulative sum across the years for each user.
your current solution is best you can have in Google Sheets by using internal formula functions. a small improvement can be done to have it under one formula if you stack individual rows (in your case pasted in B11 cell - based on image) like this:
=ARRAYFORMULA({
SUMIF(COLUMN(B3:J3),"<="&COLUMN(B3:J3),B3:J3);
SUMIF(COLUMN(B4:J4),"<="&COLUMN(B4:J4),B4:J4);
SUMIF(COLUMN(B5:J5),"<="&COLUMN(B5:J5),B5:J5)})
if you seek for instant cumulative calculation on a given range fully editable - it could be (if) possible only with a script.

How to create a dynamic table in Excel?

I am trying to create a dynamic table - I have tried a Pivot Table, but cannot get it to work. So I thought that maybe it could be done with an IF-statement, but that did not work for me neither.
Basically, I have 2 tables, 1 table containing the information (data source table) and 1 table that should be dynamic according to the data in the first table.
So if I change the data in the E-column, the Fruit table (image below) must be updated accordingly.
So if I write 2 instead of 1 in the count of Apples, then it should create 2 apples under the "Fruit"-column". Data in the remaining columns will be calculated with a formula/fixed data - so that is not important.
I am open to any solutions; formulas, pivot tables, VBA, etc.
Have a nice weekend.
I have both Excel 2010 and 2013.
If you want to repeat some text a number of times you can use a somewhat complicated formula to do it. It relies on there not being duplicate entries in the Fruits table and no entries with 0 count.
Picture of ranges and results
Formulas involved include a starter cell E2 and a repeating entry E3 and copied down. These are actually normal formulas, no array required. Note that I have created a Table for the data which allows me to use named fields to get the whole column.
E2 = INDEX(Table1[Fruits],1)
E3 = IF(
INDEX(Table1[Count],MATCH(E2,Table1[Fruits],0))>COUNTIF($E$2:E2,E2),
E2,
INDEX(Table1[Fruits],MATCH(E2,Table1[Fruits],0)+1))
How it works
This formula relies on checking the number of entries above the current one and comparing to the desired count. Some notes:
The starter cell is needed to get the first result.
After the first cell, it counts how often the value above appears in the total list. This is compared to the desired count. If less than desired, it will repeat the value from above. If greater, it will go to the next item in the list. There is a dual relative/absolute reference in here to count cells above.
Since it goes to the next item in the list, don't put a 0 for a count or it will get included once.
You can copy this down for as many cells as you want. It will #REF! when it runs out of data. You can wrap in an IFERROR(..., "") to make these display pretty.
If the non-0 rule is too much, it can probably be removed with a little effort. If there are duplicates, that will be much harder to deal with.

MySQL: Use aggregate result in further calculation

I'm currently working on writing report generators. For one report I need to do a breakdown by a given characteristic (supplier, logging user, language, etc which for each row includes the name of the characteristic I'm interested in, the number of items that match that characterastic, and the percentage of total items this figure represents. The first two aren't a problem, the third is.
For example, to get a breakdown by language I'd be using a query like this.
SELECT lang_id,
COUNT(IF(open=TRUE,1,NULL)) AS lang_total
FROM table
GROUP BY lang_id;
This gives me the number of items per language.
I can get the total number of items in the table and store it in a variable simply enough with a plain count.
SELECT #totalOpen:=COUNT(*) FROM table WHERE open = TRUE;
Now I want to add a third column, which is the figure in lang_total divided by the value in #totalOpen multiplied by 100 (in other words, the percentage of all items that fit the criteria). Something along the lines of the following:
This is the bit I'm having trouble with, as because as far as I can tell you can't use aggregate columns in calculations.
SELECT lang_id,
COUNT(IF(open=true,1,NULL)) AS lang_total
(lang_total/#totalOpen)*100 as lang_percent
FROM table
GROUP BY lang_id;
I'm sure that there must be a way of doing this in MySQL, but I've not been able to track it down. Can anyone help out with this?
I read this question now for the first time. I know that probably it's too late to be useful for you but I would have solved in this way.
select lang_id,
sum(if(open= true,1,0)) as lang_total,
coalesce(sum(if(open= true,1,null)) / #r,0) as percentage
from table,(select #r:=count(*) from table where open = TRUE) as t
group by lang_id;