I'm absolutely not a dev or anything but I'm searching everywhere to make this work.
I run a swim club and I'd like the members to have a cool app to check everything about the organization. Events, calendar, best times,.. I'm currently building it with Glide and therefore I'm using GSheets as a database.
Trying to automate things a little bit, I've already managed that for every swimmer registering on the app, it creates a new line in my master worksheet with the name of the swimmer and the link to his profile on a swimming data bank website. When my script is executed, a new worksheet is created and the row with the name and the link are also appended to the right worksheet.
Well, I have two problems now.
I'd like to push an importhtml formula in a 3rd column
I'd also like that the row with the name and link in every worksheet doesn't duplicate each time the script is executed.
function createNewSheets() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var masterSheet = spreadsheet.getSheetByName('Liste de nageurs');
// Get range with data from original sheet:
var firstRow = 1;
var firstCol = 1;
var numRows = masterSheet.getLastRow();
var numCols = masterSheet.getLastColumn();
var data_range = masterSheet.getRange(firstRow, firstCol, numRows, numCols).getValues();
// Iterate through all rows of data from Sheet1:
for (var i = 1; i < data_range.length; i++) {
var col = data_range[i]; // Current row
var swimmerName = col[0]; // swimmer name
// Get sheet with current swimmer name:
var sheet = spreadsheet.getSheetByName(swimmerName);
// Check if sheet with current swimmer name exists. If it doesn't it creates it:
if (!sheet) {
sheet = spreadsheet.insertSheet(swimmerName);
}
// Appends current row of data to the new sheet:
sheet.appendRow(col)
}
}
Can anyone help me on that one ?
It would save me a huge time to focus on other important features
Code Change:
You need to insert the formula using the setFormula() method.
// Split your data range into values and formulae:
var data_range = masterSheet.getRange(firstRow, firstCol, numRows, numCols)
var data_values = data_range.getValues();
var data_formulae = data_range.getFormulas()
for (var i = 1; i < data_values.length; i++) {
var col = data_values[i]; // Current row
var swimmerName = col[0]; // swimmer name
// Get sheet with current swimmer name:
var sheet = spreadsheet.getSheetByName(swimmerName);
// Check if sheet with current swimmer name exists. If it doesn't it creates it:
if (!sheet) {
sheet = spreadsheet.insertSheet(swimmerName);
}
// Set the first row rather than append the data:
sheet.getRange(1, 1, 1, col.length).setValues([col])
sheet.getRange(1, 3).setFormula(data_formulae[i][2])
}
Related
I have a problem where I have two sheets. one sheet is the source spreadsheet and another is a target spreadsheet. The source spreadsheet has a source sheet has which is the master database and the target spreadsheet has the target where we want to fetch data from source sheet based on emails provided in the Emails tab in the target spreadsheet.
I want the following things to happen with a script and not with IMPORTRANGE or QUERY:
The target spreadsheet will have multiple copies so I want to connect the target spreadsheet with the source spreadsheet based on the source spreadsheet's id.
I want the email matches to be case insensitive so that the users of the target spreadsheet can type emails in any case.
The Emails can go up to 50 or let's say get the last row for that column.
It will be great if the script shows a pop up saying updated after it has fetched the data.
The source sheet might have data up to 15000 rows so I am thinking about speed too.
I have shared both of the spreadsheets with hyperlinks to their names. I am not really great at scripts so it will be helpful if you can leave comments in it wherever you feel like. I would truly appreciate your help.
Thanks in advance!
Script here:
function fetch() {
//get the sheets
var source_Ssheet = SpreadsheetApp.openById('19FkL3rsh5sxdujb6x00BUPvXEEhiXfAeURTeQi3YWzo');
var target_Ssheet = SpreadsheetApp.getActiveSpreadsheet();
//get the tabs
var email_sheet = target_Ssheet.getSheetByName("Emails");
var target_sheet = target_Ssheet.getSheetByName("Target Sheet");
var source_sheet = source_Ssheet.getSheetByName("Source Sheet");
//get ranges
var email_list = email_sheet.getRange("B2:B");
var target_sheet_range = target_sheet.getRange("A1:F100");
var source_sheet_range = source_sheet.getRange("A1:F100");
//get last rows
var last_email_name = email_list.getLastRow();
var last_target_sheet_range = target_sheet_range.getLastRow();
var last_source_sheet_range = source_sheet_range.getLastRow();
//start searching for emails
for (var i=3; i < last_email_name.length+1; i++)
{
for(varj=3; j< last_source_sheet_range.length+1; j++ )
{
if(source_sheet_range[j][3].getValue() == email_list[i][3].getValue())
{
//copy matches to target sheet
target_sheet.getRange((last_target_sheet_range + 1),1,1,10).setValues(master_sheet_range[j].getValues());
}
}
}
}
Several things
last_email_name and last_source_sheet_range are numbers - they do not have any length, this is why your first forloops are not working
You are missing a space in varj=3;
email_list[i][3].getValue() does not exist because email_list only includes B - that only one column. I assume you meant email_list[i][0].getValue()
ranges cannot be addressed with the indices [][], you need to retrieve the values first to have a 2D value range.
You email values in the different sheets do not follow the same case. Apps Script is case sensitive, to suee the == comparison you need to use the toLowerCase() method.
Also mind that defining getRange("B2:B") will include many empty rows that you don't need and will make your code very slow. Replace it through getRange("B2:B" + email_sheet.getLastRow());
Have a look here at the debugged code - keep in mind that there is still much room for improvement.
function fetch() {
//get the sheets
var source_Ssheet = SpreadsheetApp.openById('19FkL3rsh5sxdujb6x00BUPvXEEhiXfAeURTeQi3YWzo');
var target_Ssheet = SpreadsheetApp.getActiveSpreadsheet();
//get the tabs
var email_sheet = target_Ssheet.getSheetByName("Emails");
var target_sheet = target_Ssheet.getSheetByName("Target Sheet");
var source_sheet = source_Ssheet.getSheetByName("Source Sheet");
//get ranges
var email_list = email_sheet.getRange("B2:B" + email_sheet.getLastRow()).getValues();
var target_sheet_range = target_sheet.getRange("A1:F100").getValues();
var source_sheet_range = source_sheet.getRange("A1:F100").getValues();
var last_target_sheet_range = target_sheet.getLastRow();
//start searching for emails
for (var i=1; i < email_list.length; i++)
{
for(var j=1; j< source_sheet_range.length; j++ )
{
if(source_sheet_range[j][0].toLowerCase() == email_list[i][0].toLowerCase())
{
target_sheet.getRange((last_target_sheet_range + 1),1,1,6).setValues([source_sheet_range[j]]);
}
}
}
}
Sheet1
Sheet2
I'm wondering if anyone could help me create a appscript for terminal invoicing and database purposes? When I click "SUBMIT" as a button in sheet 1 image, it must reflect line by line like in Sheet 2 image. (see sheet 1 image and sheet 2 image)
-after clicking submit it sheet 1 must auto clear
-when I input another set of data after clearing it needs to keep going down line per line in sheet 2
You can use the following code for that:
function myFunction() {
// declarations
var ss = SpreadsheetApp.getActive();
var sourceSheet = ss.getSheetByName('YOUR_SOURCE_SHEET_NAME');
var database = ss.getSheetByName('YOUR_DATABASE_SHEET_NAME');
// obtain common variables for each item
var dateOfOrder = sourceSheet.getRange('B1').getValue();
var dateOfDelivery = sourceSheet.getRange('B2').getValue();
var agent = sourceSheet.getRange('B8').getValue();
var customer = sourceSheet.getRange('B3').getValue();
// compute variables to initiate reading item rows
var rows = [];
var lastItemRow = sourceSheet.getLastRow();
var firstItemRow = 11;
var nItems = lastItemRow - firstItemRow + 1;
if (nItems < 1) return;
// get row-level information and append to database sheet
var itemNames = sourceSheet.getRange(firstItemRow, 1, nItems, 1).getValues();
var itemQuantities = sourceSheet.getRange(firstItemRow, 2, nItems, 1).getValues();
var itemPrices = sourceSheet.getRange(firstItemRow, 3, nItems, 1).getValues();
for (var i=0; i<nItems; i++) {
var itemName = itemNames[i][0];
var itemQuantity = itemQuantities[i][0];
var itemPrice = itemPrices[i][0];
database.appendRow([dateOfOrder, dateOfDelivery, agent, customer, itemName,
itemQuantity, itemPrice, itemQuantity * itemPrice]);
}
// clear source sheet
sourceSheet.getRange("B1:B8").clear();
sourceSheet.getRange("A11:H").clear();
}
The idea is to first obtain data from your source sheet (using getRange() along with getValue() or getValues()) and afterwards insert it using appendRow().
Finally, you can clear the range using the clear() method.
In order to create a button that calls this script, I suggest you check out this (Google spreadsheet - Making buttons that add data into cells into another sheet when pressed) other Stackoverflow answer. When assigning the script to the image, the name of it should be "myFunction" (without the quotes).
I have the following app script associated with a Google Spreadsheet that is accepting data from a Google Form:
function writePatientData() {
var spreadsheet = SpreadsheetApp.openById("<spreadsheet id>");
var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
//get last row in active/main sheet
var numRows = sheet.getLastRow();
//get last row of data
var last_row = sheet.getSheetValues(numRows, 1, 1, 23);
//get patientID (column V) in last row of sheet
var lastPatientID = sheet.getRange(numRows,3).getValue();
//find patient sheet based on patientID and make it active, then write to it
var patientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
var activePatientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
activePatientSheet.getRange(activePatientSheet.getLastRow()+1, 1,1,23).setValues(last_row);
}
What this script is doing is writing data (a row) to another sheet within this spreadsheet based on the the patientID (column V). This works as it should when I manually run the script. However, when I set a trigger to run this script (either onSubmit or edit) nothing happens. I created another function that just writes a message to the logs and set a trigger for that function and it works, so I think there is something in the script that is causing it to fail. Any ideas appreciated.
There are a few issues with your code. I tried to fix it while commenting each line I changed. Hopefully that is clear enough, please comment if you have any questions and I'll try to clarify.
function writePatientData() {
var spreadsheet = SpreadsheetApp.getActive(); //no need for id if the script is on the same spreadsheet
//var sheet = SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
//setActiveSheet will not work from a trigger like on-form-submit (what if no-one has the sheet open, or multiple have)
var sheet = spreadsheet.getSheets()[0]; //if you want the first sheet, just get it, no need to "activate"
var numRows = sheet.getLastRow();
var last_row = sheet.getSheetValues(numRows, 1, 1, 23)[0]; //added [0] since it is just one row
//var lastPatientID = sheet.getRange(numRows,3).getValue(); //you already have this in memory
var lastPatientID = last_row[2]; //arrays are zero based, that's why 2 instead of 3
//btw, you mention column V, but this is actually C
//var patientSheet = SpreadsheetApp.getActive().getSheetByName(lastPatientID);
//you already have the spreadsheet, no need to get it again
var patientSheet = spreadsheet.getSheetByName(lastPatientID);
//var activePatientSheet = spreadsheet.getSheetByName(lastPatientID); //this is the exact same as above, why?
patientSheet.appendRow(last_row); //appendRow is just simpler than getRange(getLastRow).setValues
}
I'm writing a script to loop through each sheet in one spreadsheet and copy data from specific cells into a corresponding sheet on another spreadsheet. I am getting an error on line 18 of the below code, however, stating that it can't call the getLastRow method of null. I used a couple of Logger.log lines to check my variables and see that targetSheet is coming back as null. Any advice on what I've got wrong?
//Export each sheet's daily data to another sheet *Test Version*
function exportReports() {
var sourceSS = SpreadsheetApp.getActiveSpreadsheet();
//Open Back Production Record *Test Version*
var targetSS = SpreadsheetApp.openById("1ZJKZi-UXvqyGXW9V7KVx8whxulZmx0HXt7rmgIJpUY4");
var allSourceSheets = sourceSS.getSheets();
//For-Loop to loop through hourly production sheets, running the move data for-loop on each
for(var s in allSourceSheets){
var loopSheet = allSourceSheets[s];
var loopSheetName = loopSheet.getSheetName();
var targetSheet = targetSS.getSheetByName(loopSheetName);
Logger.log(s);
Logger.log(loopSheet);
Logger.log(targetSheet);
Logger.log(loopSheetName);
var targetRow = targetSheet.getLastRow()+1;
var currentDate = Utilities.formatDate(new Date(), "GMT-5", "MM/dd/yy");
targetSheet.getRange(targetRow, 1).setValue(currentDate);
//For-Loop to move data from source to target
for(var i=6;i<=10;i++){
var sourceRange = sourceSheet.getRange(i, 2);
var targetRange = targetSheet.getRange(targetRow, i-4);
var holder = sourceRange.getValue();
targetRange.setValue(holder);
}
}
}
Per the documentation on getSheetByName, if the target sheet name does not exist, then you get null as a return value.
getSheetByName(name)
Returns a sheet with the given name.
If multiple sheets have the same name, the leftmost one is returned. Returns null if there is no sheet with the given name.
So, the desired sheet with name specified by loopSheetName does not exist in the target workbook. Perhaps someone has created a new sheet, or renamed an existing sheet in the source workbook.
You haven't asked about it, but you can improve the performance of your copy code as well, by reading the inputs as a multi-row range array, creating a row array to hold the results, and writing that once:
var sourceData = sourceSheet.getRange(6, 2, 5, 1).getValues(); // (6,2) through (10, 2)
var output = [];
// Transpose row array to column array (could use other functions, but this is easier to understand)
for(var i = 0; i < sourceData.length; ++i) { output.push(sourceData[i][0]); }
targetSheet.getRange(targetRow, 2, 1, output.length).setValues([output]); // i0 = 6 -> 6 - 4 = 2
I have written a code for this but getting an error
The coordinates or dimensions of the range are invalid. (line 44)
Code:
function updateMaster() {
var repArray = new Array();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var allSheets = ss.getSheets();
// build array of all sheets
for (i in allSheets) {
if ((allSheets[i].getName()).match(/.*?\-Rep$/))
{repArray.push(allSheets[i].getName());}
}
// store all sheets in array
var sheetArray = [];
// loop through all rep sheets
for (var j in repArray) {
// get each sheet
var tempSheet = ss.getSheetByName(repArray[j]);
// get sheet data
var dataRange = tempSheet.getDataRange().getValues();
// remove the first header row
dataRange.splice(parseInt(0), 1);
// append sheet data to array
var sheetArray = sheetArray.concat(dataRange);
}
// Time to update the master sheet
var mSheet = ss.getSheetByName("summary");
// save top header row
var headerRow = mSheet.getRange(1,1,1,12).getValues();
// clear the whole sheet
mSheet.clear({contentsOnly:true});
// put back the header row
mSheet.getRange(1, 1, 1, 12).setValues(headerRow);
This is where i am getting error while writing to master sheet:
// write to the Master sheet via the array
mSheet.getRange(2, 1, sheetArray.length, 12).setValues(sheetArray);
// force spreadsheet updates
SpreadsheetApp.flush();
// pause (1,000 milliseconds = 1 second)
Utilities.sleep("200");
// delete empty rows at bottom
var last = mSheet.getLastRow();
var max = mSheet.getMaxRows();
if (last !== max) {mSheet.deleteRows(last+1,max-last);}
}
I am not able to figure out the error.
You need a sheet with "Rep" inside the name.
"The first array stores all the Sales Rep sheets. Since some sheets could be something other than Sales Rep sheets, the script stores sheets only if the sheet name has a “-Rep” suffix (e.g. “JohnDoe-Rep”)"
code source: http://blog.ditoweb.com/2012/01/consolidate-spreadsheet-sheets-with.html
That's why it's not working.
mSheet.getRange(2, 1, sheetArray.length, 12).setValues(sheetArray)
I faced the same issue and solved it by following the "Rep" solution. Then I ran into another problem and realized that my number of columns was different... so just go back in and change the no 12 to the number of rows you have in your sheet.
Also try to keep the format of the all sheets the same.
Rename the sheet where you would like the data to combine