Google Script - return ContentService.createTextOutput? - google-apps-script

I would like to display a count of the rows in the return ContentService.createTextOutput() has that been appended rather than just "Data Collected Saved". Hopefully this is possible?
function doPost(e) {
var data = eval(e.postData.contents) ;
var usr = data[0][0];
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName(usr) ;
var now = new Date()// Variable for date
if ( sh == null ) {
ss.insertSheet(usr);
var sh = ss.getSheetByName(usr) ;
var pos = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(usr);
SpreadsheetApp.setActiveSheet(pos);
var sheets = ss.getSheets();
ss.moveActiveSheet(sheets.length);
sh.appendRow(["User","Asset ID","Project"]);
}
for (var i=0;i<data.length;i++) {
sh.appendRow(data[i]);
}
return ContentService.createTextOutput("Data Collected Saved") ;
}

return ContentService.createTextOutput("Data Collected Saved " + data.length);
JS Strings

Related

How to allow non-sheet owners run scripts that involve protected cells

I have the script below where some cells are protected because they contain formula but I can script linked to buttons that when executed, it updates the cell values in these protected cells, this is fine if you are the sheet owner but if you are not you get a error saying 'You are editing protected cells....'
I have seen some solutions where the script has been deployed as a web app and then set so it always runs as the owner but can't get this working for my use case, I deployed and set as to always run as me but this only seems like half the solution?
My code is below:
//
// Save Data
function submitData() {
var SPREADSHEET_NAME = "Data";
var SEARCH_COL_IDX = 0;
var RETURN_COL_IDX = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
var str = formSS.getRange("A10").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] != str ) {
//SpreadsheetApp.getUi().alert(' "Dmp #' + formSS.getRange("A4").getValue() + ' "');
// return row[RETURN_COL_IDX];
//} else {
//Input Values
var values1 = [[formSS.getRange("A10").getValue(),
formSS.getRange("B10").getValue(),
formSS.getRange("C10").getValue(),
formSS.getRange("D10").getValue(),
formSS.getRange("E10").getValue(),
formSS.getRange("F10").getValue(),
formSS.getRange("G10").getValue(),
formSS.getRange("H10").getValue(),
formSS.getRange("I10").getValue(),
formSS.getRange("J10").getValue(),
formSS.getRange("K10").getValue()]];
var values2 = [[formSS.getRange("A10").getValue(),
formSS.getRange("B10").getValue(),
formSS.getRange("C10").getValue(),
formSS.getRange("D10").getValue(),
formSS.getRange("E10").getValue(),
formSS.getRange("F10").getValue(),
formSS.getRange("G10").getValue(),
formSS.getRange("I10").getValue(),
formSS.getRange("J10").getValue(),
formSS.getRange("K10").getValue()]];
values2[0].forEach(function(val) {
if (val === "") {
throw new Error("Please fill in Project, Category, Subsystem, Description and Created By Fields.");
}
})
// Save New Data
datasheet.getRange(datasheet.getLastRow()+1, 1, 1, 11).setValues(values1);
SpreadsheetApp.getUi().alert(' New Record Created ');
formSS.getRange("D10").clearContent();
formSS.getRange("E10").clearContent();
formSS.getRange("F10").clearContent();
formSS.getRange("G10").clearContent();
formSS.getRange("H10").clearContent();
formSS.getRange("I10").clearContent();
formSS.getRange("J10").setValue(new Date())
return row[RETURN_COL_IDX];
}
}
}
//=========================================================
// Clear form
function clearCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
formSS.getRange("D10").clearContent();
formSS.getRange("E10").clearContent();
formSS.getRange("F10").clearContent();
formSS.getRange("G10").clearContent();
formSS.getRange("I10").clearContent();
formSS.getRange("J10").setValue(new Date())
return true ;
}
//=====================================================================
var SPREADSHEET_NAME = "Data";
var SEARCH_COL_IDX = 0;
var RETURN_COL_IDX = 0;
function searchStr() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var str = formSS.getRange("F4").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
formSS.getRange("A6").setValue(row[0]) ;
formSS.getRange("B6").setValue(row[1]);
formSS.getRange("C6").setValue(row[2]);
formSS.getRange("D6").setValue(row[3]);
formSS.getRange("E6").setValue(row[4]);
formSS.getRange("F6").setValue(row[5]);
formSS.getRange("G6").setValue(row[6]);
formSS.getRange("H6").setValue(row[7]);
formSS.getRange("I6").setValue(row[8]);
formSS.getRange("J6").setValue(row[9]);
return row[RETURN_COL_IDX];
}
}
}
//===================================================================
function rowDelete() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
var ui = SpreadsheetApp.getUi();
var response = ui.alert(
'Are you sure you want to delete this record?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
var str = formSS.getRange("F4").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
var INT_R = i+1
datasheet.deleteRow(INT_R) ;
formSS.getRange("A6").clearContent();
formSS.getRange("B6").clearContent();
formSS.getRange("C6").clearContent();
formSS.getRange("D6").clearContent();
formSS.getRange("E6").clearContent();
formSS.getRange("F6").clearContent();
formSS.getRange("G6").clearContent();
formSS.getRange("H6").clearContent();
formSS.getRange("I6").clearContent();
formSS.getRange("J6").clearContent();
return row[RETURN_COL_IDX];
}
}
}
}
//====================================================================
function updateData() {
var SPREADSHEET_NAME = "Data";
var SEARCH_COL_IDX = 0;
var RETURN_COL_IDX = 0;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formSS = ss.getSheetByName("Tool"); //Form Sheet
var datasheet = ss.getSheetByName("Data"); //Data Sheet
var str = formSS.getRange("A6").getValue();
var values = ss.getSheetByName(SPREADSHEET_NAME).getDataRange().getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
if (row[SEARCH_COL_IDX] == str) {
var INT_R = i+1
formSS.getRange("J6").setValue(new Date())
var values1 = [[formSS.getRange("A6").getValue(),
formSS.getRange("B6").getValue(),
formSS.getRange("C6").getValue(),
formSS.getRange("D6").getValue(),
formSS.getRange("E6").getValue(),
formSS.getRange("F6").getValue(),
formSS.getRange("G6").getValue(),
formSS.getRange("H6").getValue(),
formSS.getRange("I6").getValue(),
formSS.getRange("J6").getValue()]];
var values2 = [[formSS.getRange("A6").getValue(),
formSS.getRange("B6").getValue(),
formSS.getRange("C6").getValue(),
formSS.getRange("D6").getValue(),
formSS.getRange("E6").getValue(),
formSS.getRange("F6").getValue(),
formSS.getRange("G6").getValue(),
formSS.getRange("I6").getValue(),
formSS.getRange("J6").getValue()]];
values2[0].forEach(function(val) {
if (val === "") {
throw new Error("Please fill in Revisions, Project, Category, Subsystem, Description and Updated By Fields.");
}
})
datasheet.getRange(INT_R, 1, 1, 10).setValues(values1);
formSS.getRange("A6").clearContent();
formSS.getRange("B6").clearContent();
formSS.getRange("C6").clearContent();
formSS.getRange("D6").clearContent();
formSS.getRange("E6").clearContent();
formSS.getRange("F6").clearContent();
formSS.getRange("G6").clearContent();
formSS.getRange("H6").clearContent();
formSS.getRange("I6").clearContent();
formSS.getRange("J6").clearContent();
formSS.getRange("E4").clearContent();
SpreadsheetApp.getUi().alert(' Record Updated ');
return row[RETURN_COL_IDX];
}
}
}
There are several posts about this, I'll paste a response from one from yesterday. What I recommend specifically in your case is to run the script when there's an edit bye the user in a certain cell. For example a Tickbox, or a Drop-down menu (in a cell) that allows the user to select which function to run:
If you already have an onEdit function working, that's a simple trigger run by whoever is editing the sheet. Meaning that if you protect column A, it won't be editable by that simple trigger because the user won't have permissions
In order to work this out, I encourage you to protect your column as explained here, change your name function or extract in a new function the part about this specific code you're talking about; and set an installable trigger that runs on event. This way it'll be run as you used to but as it came from your own account. As you have permissions for editing ColA the timestamp will be set by the installable trigger but the other user won't be able to edit it since he/she doesn't have the permissions. Try it and let me know!

when i run my script to fetch data from other 2 sheets it is arranged the shown in picture of master sheet

master sheet
this is my code
the names are displayed under names numbers to be displayed under numbers but it is displayed under names ..I have 2 sheets named as{name,number} and a master sheet contains id,name number.
when i run the script it ftches data but not accordingly
function addMenu()
{
var menu = SpreadsheetApp.getUi().createMenu('Merge');
menu.addItem('Run Script', 'MergeSheets');
menu.addToUi();
}
function onOpen()
{
addMenu();
}
//combine data from multiple sheets
function MergeSheets() {
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var data = null;
var RetrieveSheet = null;
var PasteSheet = ss.getSheetByName("Master");
var sheets = ['Name','Number'];
PasteSheet.getRange(2,1,PasteSheet.getLastRow(),PasteSheet.getLastColumn()).clear();
for (var i =0; i<sheets.length; i++){
RetrieveSheet = ss.getSheetByName(sheets[i]);
if (RetrieveSheet.getName() != 'Master'){
data = RetrieveSheet.getRange(2,1,RetrieveSheet.getLastRow(),RetrieveSheet.getLastColumn());
data.copyTo(PasteSheet.getRange(parseInt(PasteSheet.getLastRow())+1,1));
}
}
}
//update data changes to each sheets
function updateBasedSheet()
{
var master = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Master');
var valueMaster = master.getRange(2, 1, master.getLastRow(), master.getLastColumn()).getValues();
var Name = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Name');
var Number = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Number');
var dataName = valueMaster.filter( function(item){
return item[2] === 'Name';
}
);
var Number = valueMaster.filter( function(item){
return item[2] === 'Number';
});
Name.getRange(1, 3, dataName.length, dataName[0].length).setValues(dataName);
Number.getRange(1, 3, dataNumber.length, dataNumber[0].length).setValues(dataNumber);
}
If you simply want to join 2 sheets, and they have same length and id correspondesce, you can use
var data1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Name').slice(1);
var data2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Number').slice(1);
var mergedData = data1.map( (index, row) => row.concat(data2[index]) );
SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Master')
.getRange(2, 1, mergedData.length, mergedData[0].length)
.setValues(mergedData);

Google App Script to Search data from multiple files and displaying multiple row

I want users to search for their info from multiple sheet files and display multiple results boxes(row) but currently it's searching from one sheet and displaying only the first result(row) and not displaying the rest results.
What do I need to change in the script?
function submitData(obj){
var ss = SpreadsheetApp.openById("SHEETID");
var sheet = ss.getSheetByName("SHEETNAME");
var flag = 1 ;
var lr = sheet.getLastRow();
for(var i = 1;i <= lr;i++){
var id = sheet.getRange(i, 1).getValue();
if(id == obj){
flag = 0;
var B = sheet.getRange(i, 2).getValue();
var C = sheet.getRange(i, 3).getDisplayValue();
var data ="<div class="card"><h3>Info1:"+B+"</h3><p>Info2:"+C+"</p></div>";
return data;
}
}
if(flag==1){
var data = '<div class="carderror">Data not found</div>';
return data;
}
index.html
<input id="id" class="form-control">
<button type="submit" onclick="info()"> search</button>
<div id="result"></div>
<script>
function info () {
let obj = document.querySelector('#id').value;
let updateLocation = document.querySelector('#result');
updateLocation.innerHTML = "Searching...";
function onFailure(error){
let warning = error;
updateLocation.innerHTML = warning;
};
function onSuccess(response){
let result = response;
updateLocation.innerHTML = result;
};
google.script.run.withFailureHandler(onFailure)
.withSuccessHandler(onSuccess)
.submitData(obj);
};
</script>
You're only opening a single sheet file in your example. If you want to search multiple you'll have to specify which files you want to open and loop through them. My example below assumes all the files have the same sheet name.
Right now you're returning the first matched result, which is causing your search function to exit prematurely. To display multiple results you can push the matched lines to an array, then return that array once all the scanning is complete.
function submitData(obj) {
//specify what sheet IDs you want to search
var sheetNames = ['foo', 'bar', 'bla']
//create an array to push results to
var inject = []
for (var i = 0; i < sheetNames.length; i++) {
var sheetName = sheetNames[i]
var ss = SpreadsheetApp.openById(sheetName);
var sheet = ss.getSheetByName("SHEETNAME");
var flag = 1;
var lr = sheet.getLastRow();
for (var i = 1; i <= lr; i++) {
var id = sheet.getRange(i, 1).getValue();
if (id == obj) {
flag = 0;
var B = sheet.getRange(i, 2).getValue();
var C = sheet.getRange(i, 3).getDisplayValue();
var data = "<div class='card'><h3>Info1:" + B + "</h3><p>Info2:" + C + "</p></div>";
//push result to array
inject.push(data)
}
}
}
if (flag == 1) {
var data = '<div class="carderror">Data not found</div>';
return data;
} else {
//return joined array as string
return inject.join()
}
}
Multi-spreadsheet search
function MultiSearch() {
const ss = SpreadsheetApp.getActive();
const idsh = ss.getSheetByName("ssids");
const rsh = ss.getSheetByName("Results");
rsh.getRange(2,1,rsh.getLastRow() - 1, rsh.getLastColumn()).clearContent()
const ids = idsh.getRange(2,1,idsh.getLastRow() - 1,idsh.getLastColumn()).getValues().filter(r => r[2] == "TRUE").map(r => r[1]);
const r = SpreadsheetApp.getUi().prompt("Search Dialog","Enter Search String",SpreadsheetApp.getUi().ButtonSet.OK_CANCEL);
if(r.getSelectedButton() == SpreadsheetApp.getUi().Button.OK && r.getResponseText().length > 0) {
ids.forEach(id => {
let ss = SpreadsheetApp.openById(id);
let tf = ss.createTextFinder(r.getResponseText()).findAll();
tf.forEach(f =>{
rsh.appendRow([ss.getName,f.getSheet().getName(),f.getRow(),f.getColumn()]);
})
})
}
}
ssids Sheet:
Results Sheet:

RefreshImport function not working in Google Sheets

I tried to fill it with my sheet data, but that
var dataRange = sheet.getDataRange();
get an error. What should I do?
function RefreshImports() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(5000)) return; // Wait up to 5s for previous refresh to end.
var id = "1r7TgCWXfjmcjufT0yz9qcFDlr482SdHDHlZYblXyAt0"; // [YOUR SPREADSHEET ID]
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName("crypto"); // sheet name
var dataRange = sheet.getDataRange();
var formulas = dataRange.getFormulas();
var content = "";
var now = new Date();
var time = now.getTime();
var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
var re2 = /((\?|&)(update=[0-9]*))/gi;
var re3 = /(",)/gi;
for (var row=0; row<formulas.length; row++) {
for (var col=0; col<formulas[0].length; col++) {
content = formulas[row][col];
if (content != "") {
var match = content.search(re);
if (match !== -1 ) {
// import function is used in this cell
var updatedContent = content.toString().replace(re2,"$2update=" + time);
if (updatedContent == content) {
// No querystring exists yet in url
updatedContent = content.toString().replace(re3,"?update=" + time + "$1");
}
// Update url in formula with querystring param
sheet.getRange(row+1, col+1).setFormula(updatedContent);
}
}
}
}
// Done refresh; release the lock.
lock.releaseLock();
// Show last updated time on sheet somewhere
sheet.getRange(7,2).setValue("Rates were last updated at " + now.toLocaleTimeString())
}
I set up the trigger.
Not sure what you trying to do and you explanation leaves a lot to be desired.
So this is a simple way to put your formulas into a sheet named "Destination".
function RefreshImports() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("crypto");
const rg = sh.getDataRange();
const formulas = rg.getFormulas();
sh.getRange(1,1,formulas.length,formulas[0].length).setFormulas(formulas);
}

Google Script: When cell is filled, have prompt ask if user wants to run script

I have written a script to clean up and move data between 3 different sheets. A user first paste a data extract on to the "Extract" page, and then runs the script.
When a user paste the data into cell A1 on the "Extract" page, I would like a prompt box to ask the user if they would like to run the script; if Yes, run script, if No, don't run script and show message. How would I go about doing this?
This is what I have so far...everything after the first function works.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Extract");
if(ss.s().getRange("A1").getValue() != ""){
var ui = SpreadsheetApp.getUi()
var response = ui.alert('Would you jbot to find new claims for you?', ui.ButtonSet.OK_CANCEL);
if (response == ui.Button.OK) {
jbot();
} else {
Logger.log('The user clicked "No" or the close button in the dialog\'s title bar.');
}
}
}
function jbot(){
movetobot();
deleteRows();
removeDupesInOtherSheets();
deleteCol();
cleanup();
movetoqueue();
message();
};
function movetobot() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Extract");
var ts = ss.getSheetByName("bot");
s.getRange("A1:BW").moveTo(ts.getRange("A1"));
}
function deleteRows() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("bot");
var r = s.getRange("BO:BO");
var v = r.getValues();
for(var i=v.length-1;i>=0;i--)
if(v[0,i]=='#POSTLESSEE' || v[0,i]=='#TDI CRC_OANKURA' || v[0,i]=='#Partpaymentoffer' || v[0,i]=='#TDI_CRC_DVANKURA' || v[0,i]=='#partpaymentdupe' )
s.deleteRow(i+1);
}
function removeDupesInOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("bot").getDataRange().getValues();
var s2 = ss.getSheetByName("Queue").getDataRange().getValues();
// iterate 'Queue' and check in 'bot' if duplicate values exist
var nS1 = [];
var s2Col1 = [];// data in column1 of Queue
for(var n in s2){
s2Col1.push(s2[n][0]);
}
for(var n in s1){ // iterate '180418970' and test col 1 vs col 1 in 'Queue'
var noDup1 = checkForDup(s1[n],s2Col1)
if(noDup1){nS1.push(noDup1)};// if not present in 'Queue' then keep
}
Logger.log(nS1);// view result
ss.getSheetByName("bot").getDataRange().clear();// clear and update sheets
ss.getSheetByName("bot").getRange(1,1,nS1.length,nS1[0].length).setValues(nS1);
}
function checkForDup(item,s){
Logger.log(s+' = '+item[0]+' ?')
if(s.indexOf(item[0])>-1){
return null;
}
return item;
}
function deleteCol() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var lastCol = sheet.getLastColumn();
var keep = [1,2,3,4,45,53,74, 75]; // array of column numbers to keep
for (var col=lastCol; col > 0; col--) {
if (keep.indexOf(col) == -1) {
// This isn't a keeper, delete it
sheet.deleteColumn(col);
}
}
}
function cleanup() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
sheet.getRange("B1:B").moveTo(sheet.getRange("H1"));
sheet.deleteColumn(2)
sheet.deleteRow(1)
var cell = sheet.getRange("D:D");
cell.setNumberFormat("m/d/yy");
var cell = sheet.getRange("F:F");
cell.setNumberFormat("m/d/yy");
var cell = sheet.getRange("A:A");
cell.setHorizontalAlignment("center");
var cell = sheet.getRange("C:D");
cell.setHorizontalAlignment("center");
var cell = sheet.getRange("F:G");
cell.setHorizontalAlignment("center");
sheet.autoResizeColumn(2)
sheet.autoResizeColumn(5)
sheet.autoResizeColumn(7)
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var cell = sheet.getRange("BW1");
cell.setFormula("=COUNT(A:A)");
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var range = sheet.getRange("A1:G");
range.sort({column: 4, ascending: true})
}
function movetoqueue() {
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
// skip row 1 (header) and beyond column G
var range = sheet.getRange(1,1,sheet.getLastRow()-1,7);
sheet = spread.getSheetByName("Queue");
var rows = sheet.getRange(1,1,sheet.getLastRow(),1).getValues();
// search for first blank row column 1
for( var i=0; i<rows.length; i++ ) {
if( rows[i][0] === "" ) {
var offset = sheet.getRange(1,1).offset(i,0);
range.copyTo(offset);
break;
}
}
}
function message() {
SpreadsheetApp.getActive().getSheetByName("Queue").activate();
var spread = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spread.getSheetByName("bot");
var range = sheet.getRange("bot!BW1:BW1");
var data = range.getValue();
Browser.msgBox(data + " new claims have been added to the queue. Thank you for using jBot!");
}
Your onEdit(e) will trigger the alert regardless of which cell is edited. You need to check the event range to limit it to cell A1 of Extract like this.
function onEdit(e) {
if( e.range.getSheet().getName() === "Extract" ) {
if( e.range.getA1Notation() === "A1" ) {
if( e.value !== "" ) {
var ui = SpreadsheetApp.getUi();
// Do the rest of your stuff here
}
}
}
}