Analyze sheet data to create a summary of values - google-apps-script

I have a spreadsheet for employee schedule (you can see a demo in the link below). As you can see in the "original table", I have 2 rows per day and columns for every shift (Shift A, Shift B ... ).
DEMO SHEET
I need to "reverse" the table, extracting every shift for any employee (as you can see in the right side of the demo table "calculated table").
I don't think it's possibile with normal formulas, I tried with JOIN formula and some IFs but it's not a working solution in my opinion.
Any idea on how can I write a custom formula in Google App Script? Do you know any workaround with formulas? Can you tell me where can I found some examples?
Notice that, sometimes, employee can have two shift in a single day.

J7:
=ARRAYFORMULA(TEXTJOIN(" ; ";1;IF(OFFSET($A$5;MATCH($I7;$A$6:$A$25;0);2;2;3)=J$6;$C$5:$E$5;)))
DragFill down and out.
OFFSET to offset the date to 2x3 Data array for the MATCHed date
IF to get Header Rows
TEXTJOIN to Join results.

Related

How to calculate total hours worked on an employee schedule with multiple different shift lengths

I am trying to create a new scheduling spreadsheet and would like to automatically calculate each bartender's total hours for the week in column K. However, there are multiple shift lengths each night. How can I automatically pull an individual's total hours based on the specific shifts they worked each night? Sometimes there would be a third 'mid-shift' between the opening and closing (as seen on night 3). The number of shifts per week, shift lengths, and bartenders working will vary from week to week so I would like it to be universal.
My initial thought would be to calculate based on cell color but that doesn't seem to exist in Google Sheets. I tried downloading an extension to pull cell color but that didn't do what I wanted it to. Any help would be much appreciated!
Thank you!
Spreadsheet HERE
The layout of your roster sheet doesn't lend itself to easily calculating shift hours by employee. That's not to say that it cannot be done with the layout as-is but the layout unecessarily complicates the task.
The main complicating factors are:
shift types are identified by background colour
the identification of shift types/hours/duration for each night is inconsistent (e.g. the "mid" shift is described only in "Night2") which makes it difficult to anticipate whether any given "night" will have a "mid" shift or not.
the roster sheet includes blanks - for example: Cell F19 (Night2, Bar2) - this seems to be for aethetics
Roster Layout
This answer relies on a different, highly structured layout. The snapshot shows an example of "Night 3"; other nights are repeated above or below this. Rows 1&2 are frozen and not repeated.
Roster assignments are made for each shift in each bar.
e.g Bar1-Opening, Bar1-Mid, Ba11-Closing, etc
data validation is used to select the barkeeper names for each/any shift.
Shift times for each night are fully described.
There is a summary of shifts/hours/total hours by shift type
there is also a "Total Hours" value.
Calculations
I've moved the calculations to a different sheet for the sake of convenience.
The formula for Night1 (Cell D15)is:
=ArrayFormula((if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$F$4:$F$13,1,0)),0,1*'Shift sheet'!$B$7)+if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$I$4:$I$13,1,0)),0,1*'Shift sheet'!$B$7)+if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$L$4:$L$13,1,0)),0,1*'Shift sheet'!$B$7))+(if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$G$4:$G$13,1,0)),0,1*'Shift sheet'!$C$7)+if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$J$4:$J$13,1,0)),0,1*'Shift sheet'!$C$7)+if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$M$4:$M$13,1,0)),0,1*'Shift sheet'!$C$7))+(if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$H$4:$H$13,1,0)),0,1*'Shift sheet'!$D$7)+if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$K$4:$K$13,1,0)),0,1*'Shift sheet'!$D$7)+if(iserror(vlookup($A$15:$A$34,'Shift sheet'!$N$4:$N$13,1,0)),0,1*'Shift sheet'!$D$7)))
Note: this uses "Arrayformula` so a single formula fills the entire column for all employees
The same structure is used for other Nights" but cell references are changed to reference values for the relevant Night.
The formula for the the sum of the Nights (Cell C15) is:
=ARRAYFORMULA(if(D15:D34="",0,D15:D34+E15:E34+F15:F34))
Again, this uses an Arrayformula but it sums columns D, E, F. You can edit it to add references to the column for other Nights.
Some other formulas are described in the snapshot.
The "Proof" is designed to ensure that values from the Calculation sheet agree to values from the Roster sheet.

Possible to filter SUMIF results based on if cells within a range match a specific cell?

I'm trying to automate my time tracking a bit more, and making it a bit more thorough.
Here's a link to my example that I'm working on
Basically, I want to add values in another tab based on the selection in the drop down menu, but filtered by specific weeks of the year.
Explanation:
In the C or D column of tab "Top 2023", calculate minutes based on the minutes in column G and the drop down in column C tab "2023"
Currently, I have that part working. I used SUMIF to look at column C on tab "2023", check if it matches "Work" (or "Off"), then add the hours based on either criteria.
I want to then filter that data based on the week of the year, listed in columns A in both tabs
I want to automate this so I don't need to touch it or manually select what rows are included, only to move the formula down. So if 3 rows on tab "2023" show week 1 in column A, then they're all added to C2 and D2 on tab "Top 2023", so on for the rest of the weeks of the year.
Is this possible? I was playing around with a few formulas trying to make it work (I'm still learning and researching!) in column F on the "Top 2023" tab, but couldn't quite figure it out.
I tried:
My formula to calculate the hours from tab "2023" to tab "Top 2023" is =SUMIF('2023'!C3:C,"Work",'2023'!G3:G) which works fine.
I understand doing G3:G is going to grab the whole column, so I want to filter it down further without having to manually update the G3:G portion every week.
I tried this (I know it doesn't work, and I'm having hard time understanding if it will work): =ArrayFormula(sumifs('2023'!C3:C,"Work",'2023'!G3:G)(FILTER('2023'!A3:A)A2))
Which of course brings back an error, because it doesn't work like that.
this is single cell formula + drag-down and goes in cell C2:
=SUMIFS('2023'!G3:G,'2023'!C3:C,"Work",INDEX(WEEKNUM('2023'!B3:B)),WEEKNUM(B2),INDEX(YEAR('2023'!B3:B)),YEAR(B2))
this is arrayformula within C2 (auto-applies to whole column C):
=BYROW(B2:B,LAMBDA(bx,IF(bx="",,SUM(IFERROR(FILTER('2023'!G:G,'2023'!C:C="Work",WEEKNUM('2023'!B:B)=WEEKNUM(bx),YEAR('2023'!B:B)=YEAR(bx)))))))
change 'Work' to 'Off' within the formula for Colum D (time off) values
also took into account direct 'Date' Columns in both tabs instead of
the helper columns created exclusively to extract WeekNumber.

Google script custom function for different column [duplicate]

I'm trying to do a couple of different things with a spreadsheet in Google and running into some problems with the formulas I am using. I'm hoping someone might be able to direct me to a better solution or be able to correct the current issue I'm having.
First off all, here is a view of the data on Sheet 1 that I am pulling from:
Example Spreadsheet
The first task I'm trying to accomplish is to create a sheet that lists all of these shift days with the date in one column and the subject ("P: Ben" or S: Nicole") in another column. This sheet would be used to import the data via a CSV into our calendar system each month. I tried doing an Index-Match where it used the date to pull the associated values however I found that I had to keep adjusting the formula offsets in order to capture new information. It doesn't seem like Index-Match works when multiple rows/columns are involved. Is there a better way to pull this information?
The second task I am trying to accomplish is to create a new tab which lists all the dates a specific person is assigned too (that way this tab will update in real time and everyone can just look at their own sheet to see what days they are on-call). However, I run into the same problem here because for each new row I have to change the formula to reflect the correct information otherwise it doesn't pull the correct cell when it finds a match.
I would appreciate any and all information/advice on how to accomplish these tasks with the formula combination I mentioned or suggestions on other formulas to use that I have not been able to find.
Thanks in advance!
Brandon. There are a few ways to attack your tasks, but looking at the structure of your data, I would use curly brackets {} to create arrays. Here is an excerpt of how Google explains arrays in Sheets:
You can also create your own arrays in a formula in your spreadsheet
by using brackets { }. The brackets allow you to group together
values, while you use the following punctuation to determine which
order the values are displayed in:
Commas: Separate columns to help you write a row of data in an array.
For example, ={1, 2} would place the number 1 in the first cell and
the number 2 in the cell to the right in a new column.
Semicolons: Separate rows to help you write a column of data in an array. For
example, ={1; 2} would place the number 1 in the first cell and the
number 2 in the cell below in a new row.
Note: For countries that use
commas as decimal separators (for example €1,00), commas would be
replaced by backslashes () when creating arrays.
You can join multiple ranges into one continuous range using this same
punctuation. For example, to combine values from A1-A10 with the
values from D1-D10, you can use the following formula to create a
range in a continuous column: ={A1:A10; D1:D10}
Knowing that, here's a sample sheet of your data.
First Task:
create a sheet that lists all of these shift days with the date in one
column and the subject ("P: Ben" or S: Nicole") in another column.
To organize dates and subjects into discrete arrays, we'll collect them using curly brackets...
Dates: {A3:G3,A7:G7,A11:G11,A15:G15}
Subjects: {A4:G4,A5:G5,A8:G8,A9:G9,A12:G12,A13:G13,A16:G16,A17:G17}
This actually produces two rows rather than columns, but we'll deal with that in a minute. You'll note that, because there are two subjects per every one date, we need to effectively double each date captured.
Dates: {A3:G3,A3:G3,A7:G7,A7:G7,A11:G11,A11:G11,A15:G15,A15:G15}
Subjects: {A4:G4,A5:G5,A8:G8,A9:G9,A12:G12,A13:G13,A16:G16,A17:G17}
Still with me? If so, all that's left is to (a) turn these two rows into two columns using the TRANSPOSE function, (b) combine our two columns using another pair of curly brackets and a semicolon and (c) add a SORT function to list the dates in chronological order...
=SORT(TRANSPOSE({{A3:G3,A3:G3,A7:G7,A7:G7,A11:G11,A11:G11,A15:G15,A15:G15};{A4:G4,A5:G5,A8:G8,A9:G9,A12:G12,A13:G13,A16:G16,A17:G17}}),1,TRUE)
Second Task:
create a new tab which lists all the dates a specific person is
assigned too (that way this tab will update in real time and everyone
can just look at their own sheet to see what days they are on-call).
Assuming the two-column array we just created lives in A2:B53 on a new sheet called "Shifts," then we can use the FILTER function and SEARCH based on each name. The formula at the top of Ben's sheet would look like this:
=FILTER(Shifts!A2:B53,SEARCH("Ben",Shifts!B2:B53))
Hopefully this helps, but please let me know if I've misinterpreted anything. Cheers.

Setting array formula until last column in Google Sheets

I have a formula as follows in google sheets:
=ARRAYFORMULA(IF(LEN(F2:F),IFERROR(SPLIT(REPT("PAID ",F2:F)&REPT("- ",(24-F2:F))," ")),))
This formula will show paid according to number of paid in the cell and show "-" to the cells in the rest column. For now, this formula is only applicable for columns. I dont want like that, I want this formula to be used until the last column because the number of columns will be increased every year. I dont know whether this should be done in Google App Script or what. Anything should be fine to solve my problems. I have attached some images to explain myself clearly. Thanks in advance.
https://docs.google.com/spreadsheets/d/1bM8l6JefFsPrlJnTWf56wOhnuSjdIwg3hMbY1tN1Zp8/edit#gid=1775459006 - Link to google sheets
I will use the sheet "JALAN SANGGUL 4" as an example. Then you will need to apply to all of the other sheets that have the same structure.
Replace your current G1 formula with this:
=TRANSPOSE(FILTER(Configuration!P2:P,Configuration!P2:P<>""))
Replace your current G2 formula with this:
=ARRAYFORMULA(IF(LEN(F2:F),IFERROR(SPLIT(REPT("PAID ",F2:F)&REPT("- ",(COUNTA(FILTER(G1:1,G1:1<>""))-F2:F))," ",1,1)),))
The added FILTER in each constrains things to only areas where data exists. By counting where only data exists instead of using a set "24" in the second REPT clause, you'll always get dashes going only as far as there are months in Row 1.

How to add a function referencing another column to libreoffice-calc?

Sorry for the simple question, I was expecting this to be a 2 minute job but it has proved much trickier to figure out than I planned, and the 'Function Wizard' has been no help.
I have a spreadsheet of products (one row = one product, columns = product name | stock | RRP etc).
Column D gives cost price excluding vat, I need to add another column giving cost including vat ( column D + 20% ).
I've figured out how to add functions to, and reference specific cels, so I can do it on a cel by cel basis =SUM(D2*(1.2)) but for obvious reasons, I'd rather do this once for the column instead of doing 10k+ products one by one! What am I missing?
The "Fill Down" feature may be useful in your case:
Select the first cell holding your formula and all the cells down your sheet where the formula should get inserted;
Select Menu "Edit" -> "Fill" -> "Down", or hit CTRL+D
This will make Calc to copy the formula into all selected cells, updating the cell references (except if you have absolute references using the dollar sign).
For 10k+ rows, this may take a short time, since Calc will calculate the results, too, but it should work at least.