I am a total script kitty at best and am trying to use google apps scripts to automate a process for me. Here a sample table like the one I am working with(data is in google sheets spreadsheet):
Variety
Category
Peter
Courtney
DP
HBC
0.00
4.5
DP
MNG
2.00
0
UB
THN
7.00
0
471H
THN
5.00
0
471H
THN
0.00
5
GRH
FST
4.00
0
GRH
THN
8.00
0
GRH
THN
0.00
8
GRH
THN
0.00
8
HM
HBC
6.50
0
HM
HBC
0.00
6.5
HM
MNG
2.00
0
HM
MNG
0.00
2
CL
HBC
8.50
0
CL
HBC
7.00
0
PSV
HBC
2.50
0
PSV
HBC
7.00
0
PSV
HBC
0.00
2.5
The table shows the employees reported hours broken down by Variety and category. My goal is to compile this data so if the employees work at the same category and same variety I want all hours expressed in a single line. For instance if you look at the last two rows of the data you'll notice that the Variety and Category columns are matching which means the data should be compiled. So instead of:
Variety
Category
Peter
Courtney
PSV
HBC
7.00
0
PSV
HBC
0.00
2.5
I want to compile the data like this:
Variety
Category
Peter
Courtney
PSV
HBC
7.00
2.5
I am trying to do this from the bottom up because I heard going from the top down can cause issues but I am open to any suggestions. I think I need to write a for loop that compares the variety box of the active row to the variety box of the above row AND compares if the category box of the active row is equal to the category box of the above row and if both are true add the hours of both the "Peter" column and "Courtney" column.
I know there is more to do on top of that but this for loop is what I really need help on, unless you can suggest a better way?
Thanks for looking at my work,
JP
Stackoverflow member Ruben has asked me to elaborate more, here is where I am at:
I found a stackoverflow answer that pushed me in the direction of how to parse the data with the for loop. Here is the for loop skeleton I am working with:
function project() {
var ss = SpreadsheetApp.getActiveSheet();
var sheet = ss.getSheetByName("gest");
var data = sheet.getRange('A2:F19').getValues();
// Category and Variety columns
var leadV = sheet.getRange('B18');
var followV = sheet.getRange('B19');
var leadC = sheet.getRange('C18');
var followC = sheet.getRange('C19');
// Hour columns
var leadH1 = sheet.getRange('E18');
var followH1 = sheet.getRange('E19');
var leadH2 = sheet.getRange('F18');
var followH2 = sheet.getRange('F19');
for (var i = 0 ;i < data.length ; i++)
if leadV === followV AND leadC === followC,
// add both hours columns together
leadH1.getValue()+followH1.getValue()
leadH2.getValue()+followH2.getValue();
//Delete active row(not made yet)
else continue;
sheet.getRange(18-i, 2).activate();
My idea was to have a "lead" row and a "follow" row that would compare themselves and work up the data one by one through the for loop. I realize I need to use getActiveCell(), rather then getRange() but I don't understand how to compare an adjacent cell to the active cell while wrapping it into the for loop. I am just a bit overwhelmed and I think I might be over complicating my situation.
If you are open to using a formula instead of script, I can propose a solution. (In my own practice of decades, I save script for only those times when formulas cannot produce the desired result; this cuts down greatly on potential problems.)
This solution uses information from the script in your post to ascertain that the name of the source sheet is 'gest' and the ranges of data to include in the new report are B:C and E:F.
Create a new sheet and place the following formula in cell A1:
=ArrayFormula({gest!B1:C1, gest!E1:F1; QUERY({gest!B2:C, E2:F},"Select Col1, Col2, SUM(Col3), SUM(Col4) WHERE Col1 Is Not Null GROUP BY Col1, Col2 LABEL SUM(Col3) '', SUM(Col4) ''")})
This single formula will produce all headers and results, and will "keep up" as you add new rows of data in the 'gest' sheet.
A virtual array is formed between the curly brackets { }. This is a way of "sticking together" non-contiguous data in new ways.
The headers are grabbed by the two references preceding the semicolon.
Then a QUERY is formed from the non-header information in the target columns.
In plain English, the Select clause of the QUERY reads "Return four columns: exactly what is in the first requested column and the second requested column followed by the categorized sums from the third and fourth requested columns, separating (i.e., "GROUPing") those sums by each unique pairing from the first two columns." The LABEL section just removes technical headers from the sum columns created (which would otherwise have placed stock headers of 'sum' above each of the summed columns).
Related
Script lab shows examples of how to get a range using rows, columns and cell values here:
https://learn.microsoft.com/en-us/office/dev/add-ins/excel/excel-add-ins-ranges-advanced
However, all the values in examples were hardcoded. I could not find on any page any example of how to use variables in the get range? Maybe its a simple javascript thing but I am totally new to it. Can anyone share an example of how to do say?
sheet.getRange("4:9") using variables for number 4 and number 9?
And if you do know that answer for above, can you also share, how to do this using cell references in the below example?
Assume that I can find the values of rows and column names and set them in some variables. How would I use it in below code replacing the values for G1, A1 and E1?
sheet.getRange("G1").copyFrom("A1:E1");
Thanking you in advance for your help!
P.S: I already tried searching on stack overflow with keywords for "script lab range variables" but found no answers. Hence asking here.
Excel.run(function (context) {
var sheet = context.workbook.worksheets.getItem("Sample");
// Group the larger, main level. Note that the outline controls
// will be on row 10, meaning 4-9 will collapse and expand.
sheet.getRange("4:9").group(Excel.GroupOption.byRows);
// Group the smaller, sublevels. Note that the outline controls
// will be on rows 6 and 9, meaning 4-5 and 7-8 will collapse and expand.
sheet.getRange("4:5").group(Excel.GroupOption.byRows);
sheet.getRange("7:8").group(Excel.GroupOption.byRows);
// Group the larger, main level. Note that the outline controls
// will be on column R, meaning C-Q will collapse and expand.
sheet.getRange("C:Q").group(Excel.GroupOption.byColumns);
// Group the smaller, sublevels. Note that the outline controls
// will be on columns G, L, and R, meaning C-F, H-K, and M-P will collapse and expand.
sheet.getRange("C:F").group(Excel.GroupOption.byColumns);
sheet.getRange("H:K").group(Excel.GroupOption.byColumns);
sheet.getRange("M:P").group(Excel.GroupOption.byColumns);
return context.sync();
}).catch(errorHandlerFunction);
So, I got an answer on this here: https://github.com/OfficeDev/office-js-docs-pr/issues/1699
Thanks to AlexJerabek (you can find his id on the above github link).
In summary:
The getRange method takes in a string representing a cell range in the worksheet, such as "A1:D4", "A:D" for just the columns, or "1:4" for just the rows. As long as your variables map to Excel rows or columns, you can use string concatenation to build the argument. You may need to use range.columnIndex, range.rowIndex, and range.getCell to translate to and from zero-based numbers into the letter-based columns.
Based on this answer, I tried below (and it worked):
const sheet = context.workbook.worksheets.getActiveWorksheet();
var firstrow = 1
var lastRow = 6
var range = sheet.getRange(firstrow + ":" + lastRow)
I'm trying to parse this telnet output from my game. I have tried to use regex but it will not capture anything and keeps returning null. I have tried several different examples from searching but none work. below would be my string, I want to capture between < motd> and < /motd> and later on I would like to capture all < item ...> in the < players> tag. I have sent the output of str to console and it all shows up as expected. This is the regex i am currently trying that returns null.
var result = str.match( /<motd>(.|\n|\r\n)*?<\/motd>/g );
console.log(result);
and the str:
<motd>
Welcome to MUD
***************
UPDATE May 11, 2018 Interface v31.2
***************
NEW INTERFACE: v31.2 is online!
Changes to INTERFACE:
Larger Message Queue
Built-in, auto-synced Tick Timer.
Junk/Sell/Drop on multiple items now works for entire stack of items.
New Mob Art
Ungroup Button fixed.
****
NEW EDITABLE COMMAND ENTRY BOX!!
****
Changes to GAME:
Miscellaneous small fixes to make the interface function cleaner.
Shop and Inventory Parsing bugs (overflow) improved heavily.
New items, it's a surprise. Hint: Think Orc Dreams.
Fixed small bugs in room art.
New character creation bug (chars being reset to level 1) fixed.
Score made more detailed on enchantments.
Large quantity junking fixed.
Follow Spam Removed. You're welcome. You may grovel now.
Stealing from newbies fixed. Thanks to the guy who reported that!
Limbo bugs fixed, including not being able to idle out.
Quicklevelling fixed. We don't recommend you make this code tell us what you're doing.
Dark showing properly on various spells/light/sleep/combat changes.
Orc jail meat collector fixed.
</motd>
<paiddays 0>
<players>
<item Time 1 ~ 1409 0 1 150532 171205 171959 150801 170762 152159 2556 1453 170023 0>
<item Mep 1 ~ 1509 0 1 555 0 1959 0 750 2153 2555 0 4 0>
<item ZugZug 1 ~ 9025 3 1 551 1210 142010 803 140750 142150 2550 171453 145 0>
<players>
<playername>
Try the regex:
/<motd>[^<>]*?<\/motd>/igm
Here:
i : is to ignore case
g : is for global search
m : for multiple line
matching
Use a DOM parser. The closest to your question is JQuery DOM parser.
var myOut = $.parseXML(str);
var items = $(myOut).find('item');
I have the following table in html built with json (there are columns that describe what the numbers are also):
1
2
7
10
11
15
Now from a button i want is when user enters a new row, I want the number to go in its place. E.g. if 4, it should be between 2 and 7. If 14, it should be between 11 and 15.
$('tbody#days > tr:nth-child(' + daynumber-1 + ')').after(new_row_data);
failed to work because the index couldn't be found. It works sometimes if for e.g. I have 3 and 5 and tried to insert 4.
I thought have looping the column top to bottom but i usually have 100-113 rows and I am wondering if there is a practical and efficient way of doing this.
Any tips?
The snippet you posted should work fine. However, this will throw an error if the all days are greater than the input.
For efficiency, you could maintain an array of already inserted days and populate it as more days are being inserted.
Before each insertion, look through the array of days and find a spot for that day and just insert it right away. Code for that will be
$('tbody#days > tr').eq( lowerIndex ).after( new_row_data );
I have a Google Spreadsheet with 13 sheets. Each sheet has the same formatting and layout but the data varies. The ranges I need from each sheet are F7:G13 and cell F2. Each row within the F7:G13 range should be paired with Cell F2 and placed into 3 adjacent columns in another workbook (we'll call it Workbook2). So if there is a data point in column F there will be a data point in the adjacent G cell. As long as there is data in the G:F range then the contents of cell F2 needs to be copied over too.
Some potential problems...
The number of rows in the F:G range will vary from 0 to 7 on any given sheet.
Workbook2 has some auto-populated cells (range F1:J14) which will do some calculations based on information copied over. I mention this because unless there is a way to use appendRow on a specific cell range (A:C) it will copy the data starting in row 15 which I do not want.
I think i've included everything but I will gladly clarify anything. Thanks in advance for any help.
I am using DataTables JQuery plugins and I would like to ask the following two questions.
Is it possible to have MIN or MAX or AVG values calculated (dynamically) at the end of each column?
For example:
A/A A B C
L1 2 3 4
L2 3 4 5
If I would like to prin line 3 with the Min Values of each columnt should have been:
L3 2 3 4
Is it possible to create another column D which will contain the result of a formula for each row? For example Di = Ai + Bi?
According to the above example the resulted table should be the following:
L1 2 3 4 5
L2 3 4 5 7
Can I somehow perform those operations through DataTables or I have to prepare the data before passing it to the DataTables?
Thanks.
PS:
I suppose I need something similar to this trirand.net/examples/grid/functionality/footer/default.aspx but for DataTables plugin. In addition to that I need some formulas for rows as well. – salamis just now edit
Use mRender ( http://datatables.net/ref#mRender ) for the last column. mRender, when used as a function, has access the the data source object for the row (third parameter), so you can easily do a quick sum and then return the calculated value :-).