Sorting raw data from one sheet into separate tabs on a new sheet in Google App Script - javascript

I have a large data file that I want to be separated/filtered out into separate tabs on a new sheet. They need to be filtered by a certain column containing "BGT" within the string.
I am very new to using Google Apps Script so this is a work in progress. I am able to pull the data from one sheet into another, convert it to an array and assign the column I want to sort by. I just can't properly set up the filter.
function CreativeReport() {
  var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var sheet = ss.getSheetByName(SHEET_NAME);
var folder = getDriveFolderFromPath("Daily Creative Audit");
var fileId = folder.getFiles().next().getId();
var RawMM = SpreadsheetApp.openById(fileId);
var ArrayRawData = RawMM.getRange(2,1,RawMM.getLastRow()-1,5).getValues();
var ConceptName = RawMM.getRange('A:A').getValues();
var BGTFilter = ConceptName.includes("BGT");
var BGTFilteredData = ArrayRawData.filter(function(item){ return item [6] === BGTFilter;});
Logger.log(BGTFilteredData);
The column I want to sort buy contains cells formatted like this
2019_BGT_Bigsale_300x50
2019_SWT_Bigsale_300x50
2019_AI_Bigsale_300x50
2019_SWO_Bigsale_300x50
2019_DCO_Bigsale_300x50.
The goal is to have the script filter this raw data, and sort it into separate sheets depending on the cells containing:
BGT
SWO
SWT
AI
DCO
The code I how SHOULD log out just the concepts containing "BGT" in the string but I get
TypeError: Cannot find function includes in object ,concept_name,

You have values at "Sheet1" in the source Spreadsheet.
You want to separate the values by checking whether the column "A" has the values of BGT, SWO, SWT, AI, DCO.
You want to put the separated values to the sheet names of BGT, SWO, SWT, AI, DCO in the destination Spreadsheet.
I could understand like above. If my understanding is correct, how about this modification? Unfortunately, the modified script was largely changed from your original script. I apologize for this. I think that there are several answers for your situation. So please think of this as just one of them.
The flow of the modified script is as follows.
Retrieve values from the source sheet.
Create an object for retrieving values for each destination sheet.
The object is like {"BGT": [values], "SWO": [values],,,}.
Put values for the destination sheets.
Modified script:
Before you run the script, please set srcSpreadsheetId, dstSpreadsheetId and srcSheetName.
function CreativeReport() {
// Variables: Please set them for your situation.
var srcSpreadsheetId = "###"; // Please set the source Spreadsheet ID. In your sample, the Spreadsheet name is "Sample Raw Data".
var dstSpreadsheetId = "###"; // Please set the destination Spreadsheet ID. In your sample, the Spreadsheet name is "Sorted Data".
var srcSheetName = "Sheet1"; // Please modify this. In this sample, it's the same with your sample Spreadsheet.
var dstSheetNames = ["BGT", "SWO", "DCO", "AI", "SWT"];
// Open Spreadsheets
var srcSS = SpreadsheetApp.openById(srcSpreadsheetId);
var dstSS = SpreadsheetApp.openById(dstSpreadsheetId);
// Retrieve values from the source sheet.
var srcSheet = srcSS.getSheetByName(srcSheetName);
var srcValues = srcSheet.getRange(2, 1, srcSheet.getLastRow() - 1, 5).getValues();
// Create an object for retrieving values for each destination sheet.
var object = srcValues.reduce(function(obj, e) {
dstSheetNames.forEach(function(f) {
if (e[0].indexOf(f) > -1) obj[f] = obj[f] ? obj[f].concat([e]) : [e];
});
return obj;
}, {});
// Put values for the destination sheets.
dstSheetNames.forEach(function(e) {
var sheet = dstSS.getSheetByName(e);
sheet.getRange(sheet.getLastRow() + 1, 1, object[e].length, object[e][0].length).setValues(object[e]);
});
}
Note:
As mentioned at my comment, the values retrieved by getValues() is 2 dimensional array. So if Array.includes() can be used at Google Apps Script, in your script, ConceptName.includes("BGT") is always false. And, unfortunately, Array.includes() cannot be used at Google Apps Script. Ref
This modified script was prepared using the sample Spreadsheets of "Sample Raw Data" and "Sorted Data" you shared. So if your actual Spreadsheet is different from these samples, please modify above script.
When the values of source Spreadsheet and the number of destination sheets are much increased, I recommend to use Sheets API for putting the values for each destination sheet.
References:
getValues()
Basic JavaScript features
includes()
indexOf()
reduce()
for​Each()

Related

How to get a new table with keys and sum results in Google Spreadsheets?

I got a script to count sum for each column in my Google sheet. I'm getting correct result in a Dialog message.
Now I need to make a chart from this data. So I need to extract keys and values and insert to sheet in active spreadsheet.
function countNutrients(){
var sh=SpreadsheetApp.getActiveSheet();
var hA=sh.getRange(2,23,1,sh.getLastColumn()-22).getValues()[0];
var sum={};
hA.forEach(function(h,i){sum[h]=0;})
var vA=sh.getRange(3,23,sh.getLastRow()-1,sh.getLastColumn()-22).getValues();
vA.forEach(function(r,i){
r.forEach(function(c,j){
if(!isNaN(c)) {
sum[hA[j]]+=c;
Logger.log(sum);
}
});
});
var html="";
var keys=Object.keys(sum);
keys.forEach(function(k,i){
html+=Utilities.formatString('<br />sum[%s]=%s',k,sum[k]);
})
var ui=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(ui,'The dish contains');
}
Any ideas how to get it?
Thank you!
Understanding
You want to retrieve the keys and values from the object of sum as an array.
You want to put the retrieved values to a sheet in the active Spreadsheet.
You want to achieve this by modifying your script.
Modification point:
In this answer, the keys and values are retrieved from the object of sum using Object.entries().
Modified script:
When your script is modified, it becomes as follows. Before you run the script, please set the sheet name that you want to put the values.
From:
var html="";
var keys=Object.keys(sum);
keys.forEach(function(k,i){
html+=Utilities.formatString('<br />sum[%s]=%s',k,sum[k]);
})
var ui=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(ui,'The dish contains');
To:
var values = Object.entries(sum);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
Note:
In this case, the keys and values are put to the column "A" and "B", respectively. If you want to put the keys and values to other columns, please tell me.
When you use this modified script, please enable V8 at the script editor.
Reference:
Object.entries()

How to make a loop of an Spreadsheet copier (Copies an entire Spreadsheet into a new one with a new name)

I have an script that copies an entire Spreadsheet to a new one with a selected name, but I would like to make a loop so I can set a list of all the new spreadsheets that I need to make (10 aprox.)
I already tried to delete the ID sheet from the copied sheet but it didn't worked... So I want the script to use the names on Col A and places the new copy ID on the Col B
function setupSheet() {
var s = SpreadsheetApp.getActive().getSheetByName('ID');
var sheet_name = s.getRange("A1").getValue(); // Get the value of cell A1, used to name the new spreadsheet.
var ID = DriveApp.getFileById("XXXXXXXX").makeCopy(sheet_name, DriveApp.getFolderById("XXXXXXXX")).getId(); //Copies the specific Spreadsheet into an specific folder.
Logger.log(ID); //Saves the ID of the new Spreadsheet into the Log.
var stringToWrite = Logger.getLog();
SpreadsheetApp.getActive().getActiveSheet().getRange("B1").setValue(stringToWrite); //Writes the ID of the sheet from the Log.
//ID.deleteSheet(ID.getSheetByName('ID')); // remove "ID" sheet which was created by default in new spreadsheet.
}
We can use JavaScript loops in Google Apps Script like for, do..while, etc. Also we could use Array.protoype.forEach.
To use the names in column A use getValues() to get the values.
To set the names of the copies on column B use setValues().
NOTE: Both of the above methods are methods of Class Range.
For further details, please read https://developers.google.com/apps-script/guides/sheets

Google Apps Script - how to reference object in loop in function

I am trying to create a small invoicing organization system using google sheets/drive. I have one sheet I call "tasks", where I plan to control everything from. Some of my columns include, "Client", "Project", "Requirements", "Details", "subcontractor"... As I acquire new tasks/clients, i'd find and append information respective of the task ("Project", "Requirements") to other sheets or, if none exist, create the folders, sheets, and append the respective necessary information from the "tasks" sheet to the new sheets. Some of the sheets will be sent to subcontractors, dependent on whether or not their tasks were updated or new ones were assigned to them in the original "tasks" sheet.
Within the sheets I send to subcontractors, there will be fields for them to fill out (rate, eta..), once filled, I will send that info to a third sheet to apply some margins, extra fees, and then send the info back to the original "tasks" sheet where it will fill appropriate cells.. Once all of the necessary information in a row is filled, it will be prepared and organized into an invoice for the client specified in the "client" column...
Anyways, i've been trying to learn javascript to implement all of this. As I plan to create folders, sheets, and append information based on the values entered in the rows and columns of the "tasks" sheet... I've placed a for loop in an onEdit function that does the following:
function onEdit(e) {
var ss = e.range.getSheet().getParent();
var sheet = e.range.getSheet();
var row = e.range.getRow();
var columns = [1, 2, 3, 4, 5, 6, 7, 8, 9];
//assign titles as 'keys' to array
var titles = []
//assign values of edited row to array
var values = []
//create an object to associate the title to the new edited values
var task = {}
for(var i in columns){
titles.push(sheet.getRange(1, columns[i]).getValue()); //push titles
values.push(sheet.getRange(row, columns[i]).getValue()); //push values of updated row
task[titles[i]] = values[i]; //add the values to their property names in task object
}
This works, and I can reference task["Client"], but i'd like to put this loop in a function so that I can use it again. I suppose I could do without it, but array "columns" only represents the columns I will be inputting on the "first round" --- when im sending information out...I will be inputting new information to columns 10-15, then 16-20, as the tasks progress.. and i'd like to run the for loop for those columns without having to create separate loops. To do this i've created the GetInfo function below:
function GetInfo(row,column){
for(var i in column){
titles.push(sheet.getRange(1, column[i]).getValue()); //push titles
values.push(sheet.getRange(row, column[i]).getValue()); //push values of updated row
this.task[titles[i]] = values[i]; //add the values to their task
}
}
What I am trying to accomplish is similar to what is outlined here. However, the "for(var..in..") is not mentioned in the examples and I think im missing something. In attempt to use the function for the first array of columns ive done this:
var list = new GetInfo(row,columns);
i'd like to reference the task as follows
list.task["client"]
Or var.task["name"], but the above doesn't work. When I toast list.task["Client] or try to append it to another cell, nothing happens - its blank. What am I doing wrong? How do I accomplish this correctly? What should I do?
Any help or guidance would be greatly appreciated. Please.
(other toasts are working, and the respective cell is not blank, without the function the for var in works)

How Can I Use setValue() Based Off Of 2 Arrays That Match Value?

I should start with letting you know that I'm an extreme novice in JS. My background is almost solely in SQL/VBA. So, any tips you could provide would be greatly appreciated, whether it's in coding or in Stack Overflow etiquette.
Problem Background:
I've got a Script that I use for sending outbound e-mails from Google Form responses, hosted within a Google Sheet and set to OnFormResponse(). Typically, I'm only asked to send back specific bits of information from the form responses within a HTML template e-mail. However, the business case I have now is that I need to look up the values from another sheet, where an adjacent column's value matches a form response value. With the value that's matched, I need to set the value of a specific column/row (F:F) within the Form Response sheet with it.
Example:
Here's a simplified version of what the Form Responses sheet looks like, along with the formula that I would typically use:
Here's what the other tab, 'Unique Databases!', looks like:
So, my understanding of JavaScript arrays is that on the Form Responses Sheet, I would load all columns (A:E in this example) into a variable, and get the values. Then, get columns A:B of 'Unique Databases!', which loads those values into another array. If that is accurate, how do you compare the index of 1 array against the index of another, and return an adjacent match?
Thanks!
You can try this function:
function dbmanager(dbname) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Unique Databases!');
var rg=sh.getDataRange();
var vA=rg.getValues();
var r='';
for(var i=0;i<vA.length;i++){
if(dbname==vA[i][0]){
r=vA[i][1];
break;
}
}
return r;
}
I'm not sure you need to use a apps script to make a comparison like this. Perhaps a much faster way would be to use a query in the sheet. Something like this maybe:
=QUERY(Sheet1!A1:B3,"SELECT B WHERE A ='"&E2&"'",0)
The first part of the query is looking up the unique databases data. The second part selects column B in the unique databases data where column A is equal to the data base name in the form responses data. Note this query goes in column F of the responses data.
Another alternative using code might be something like this. with the code below running.
function getFormData(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet2');
var getRange = sheet.getRange('E2:E');
var data = getRange.getValues();
var lookup = getLookupData();
data.forEach(function(item,index){
sheet.getRange(index + 2 , 6).setValue(lookup[item])
})
}
function getLookupData() {
var obj = {};
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var range = sheet.getRange('A2:B6');
var data = range.getValues();
data.forEach(function(item){
obj[item[0]] = item[1];
})
Logger.log(obj)
return obj;
}

Copy data from one sheet to another; creating a table with the copied data in the target sheet

I'm trying to find a script where I can copy data from a spreadsheet in specific cells, then paste it in a different tab within the same spreadsheet.
Once the info is copied and pasted, I will run a script to erase the data in the SOURCE tab, so new info can be typed in. (I already have the code for erasing)
function EraseInfo() {
var sheet = SpreadsheetApp.getActive().getSheetByName('SOURCE');
sheet.getRange('B2').clearContent();
sheet.getRange('C4').clearContent();
sheet.getRange('D6').clearContent();
}
The idea is that a table could be generated on the TARGET sheet with the information entered in the SOURCE sheet.
Example:
I want to copy cells B2, C4 and D6 from the SOURCE sheet to cells B2, B3 and B4 in the TARGET sheet, respectively.
Then on the second instance the copied data should be pasted in the SOURCE sheet, but in cells C2, C3 and C4, and so forth.
I would first put the data from your SOURCE sheet into an array. Then send it through to the range you want on TARGET sheet.
This is one way to do it, I am fairly new to programming, so there might be a better way.
I assumed you had data in TARGET sheet on A2,A3, and A4.
function myFunction() {
var sSheet = SpreadsheetApp.getActive().getSheetByName('SOURCE')
var tSheet = SpreadsheetApp.getActive().getSheetByName('TARGET')
var SourceD = sSheet.getDataRange().getValues()
var SourceArray = [[SourceD[1][1]],[SourceD[3][2]],[SourceD[5][3]]]
var LastC = tSheet.getLastColumn()
tSheet.getRange(2, LastC+1,3).setValues(SourceArray)
}
This should get you started. This script is putting all data on the SOURCE sheet into an array, then it is picking out what it needs. After this you just need to insert EraseInfo() at the end of this function, and once it has copied the data over, it will erase the information on the SOURCE sheet.
Again there are many ways to do this, this is the one I would use.
EDIT: Answer to comment below
You would have to change the three bottom lines of code to do so. This is the easy way, and assumes you have the same data for A and B columns, and have titles in at least A1. You would put in whatever data you needed for columns A and B in "Data A" and "Data B"
function myFunction() {
var sSheet = SpreadsheetApp.getActive().getSheetByName('SOURCE')
var tSheet = SpreadsheetApp.getActive().getSheetByName('TARGET')
var SourceD = sSheet.getDataRange().getValues()
var SourceArray = [["Data A", "Data B",SourceD[1][1],SourceD[3][2],SourceD[5][3]]]
var LastR = tSheet.getLastRow()
tSheet.getRange(LastR+1, 1,1,5).setValues(SourceArray)
}

Categories