Google spreadsheet ImportRange - need to improve my workaround - javascript

I am pretty new to this forum and also to the google scripts. I have never actually learned JavaScript or any other programming language, however I was forced to start using then since the time I chose the google apps as my main platform for my small business.
My problem is in google ImportRange function limitation to 50 on every spreadsheet. I created a model, where every customer has his own spreadsheet with his personal data, deadlines, etc. located in his own folder in google drive.
I also created a spreadsheet called "Organizer", Organizer has two functions -
1) create automatic correspondention using autoCrat script,
2) show deadlines for every costumer and sort them by priority.
So i need to be able to share / import / copy data from all customer spreadsheets to the "Organizer". Because there are 50+ costumer spreadsheets, I had to give up on ImportRange function and instead of that I am using a simple script to copy files from every spreadsheet directly:
function ImportDataRange() {
// rown number.1
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
var range = sheet.getRange(2, 1)
var id = range.getValue()
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
sheet.getRange("B2:AC2").setValues(data)
// row number.2
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
var range = sheet.getRange(3, 1)
var id = range.getValue()
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
sheet.getRange("B3:AC3").setValues(data)
}
This script actually works well, but problem is, when I want to add new costumer spreadsheet to "Organizer" using this method, I have to manually add new copy of whole code for every new row and also change the output range of imported data and location of source file ID in "Organizer".
Does anybody know some kind of workaroud, which will help me to add new rows / costumer data easier / automatically ?
Thank you for your help!

You are going to want to use a loop of some sort. I haven't tested the code below, but based on your example, I think this should work for you.
function ImportOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
// Get the first column
// lastRow() - 1 because we're starting at row 2
var sheetIds = sheet.getRange(2, 1, sheet.getLastRow() - 1);
// For each ID in the id column
for (var i = 0; i < sheetIds.length; i++) {
var id = sheetIds[i]; // Get the id from the Array
// Get the new sheet, range and values
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
// Get the local range, and write the values
sheet.getRange(i + 1, 2, 1, data[0].length).setValues(data)
}
}
As you learn more about GAS and JS, take advantage of MDN and the GAS Documentation

I took the fooby´s code and after long trial-and-error procedure I came with code that is working for me, so if anyone is interested, here it is:
function ShowDataFromOtherSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Databaze");
var ids = sheet.getRange(2, 1, sheet.getLastRow() - 1).getValues();
for (var i = 0; i < ids.length; i++) {
var id = ids[i];
var ssraw = SpreadsheetApp.openById(id);
var sheetraw = ssraw.getSheetByName("Raw");
var range = sheetraw.getRange("A2:AB2");
var data = range.getValues();
sheet.getRange(i + 2, 2, 1, data[0].length).setValues(data)
}
}
And thank you fooby - i would not make it without your help!

Related

Google Apps Script is taking too much time, is there a way to reduce the runtime?

function dataManp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("My-Sheet-1");
var pasteSheet = ss.getSheetByName("My-Sheet-2");
var clearContentRange = pasteSheet.getRange("A1:Z100");
clearContentRange.clearContent();
var source = copySheet.getRange("a1:f100");
var destination = pasteSheet.getRange("a1:f100");
source.copyTo(destination, {formatOnly:true , contentsOnly:true});
source.copyTo(destination,SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS,false);
var rows = pasteSheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
if (row[3] == '') {
var deleteRowNum = (parseInt(i)+1) - rowsDeleted
pasteSheet.deleteRow(deleteRowNum);
// temp_array[i] = i
rowsDeleted++;
}
}
pasteSheet.deleteColumn(2)
}
Hi,
I have written the following script to perform the following operations,
Copy data from My-Sheet-1 and paste to My-Sheet-2
Deletion of rows that corresponds to empty cells in column 3.
After that deletion of column 2
Rigthnow, the My-Sheet-1 contains only 60 rows and 20, the script is taking approximately 7 secs to complete. However in future the number of rows may extend to some 1000. Is there a way to optimize the above code, so that it takes less time to complete.
My observation is that, copy and pasting the data takes just milli secs. The major time consuming part are the operations, I am performing in the pasteSheet after pasting it. It may be helpful, if we can copy My-Sheet-1 to a temporary variable (copy everything including the formulas, format specifications, values, text etc..) and perform all operations in the temporary variable and then paste everything in the temporary variable to the desired target sheet. But, I don't know, how to copy everything in a sheet to a temporary variable, also, I am not sure, whether this will reduce the time or not. I would be glad, if I can get some help on this as well (i.e. copying everything in a sheet to a temporary variable, perfrom operations on the variables and then paste data in the variable to a new sheet)
Thank you
Edit - 1
Would like to add that, My-Sheet-1 contains mixed data (i.e. numerics, color formatted text, formulas in some cells etc)
Explanation:
deleteRow() takes some time per execution, so it's not recommended to use on hundreds of rows in a loop.
Simple answer would be:
Make a 2D array for Sheet1 using getValues().
Delete / filter out array elements depending if row2 is blank.
Use setValues() to write the filtered array into Sheet2.
Sample Code:
function dataManp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("My-Sheet-1");
var pasteSheet = ss.getSheetByName("My-Sheet-2");
var lr = copySheet.getLastRow();
var clearContentRange = pasteSheet.getRange(1,1,lr,26);
clearContentRange.clearContent();
var source = copySheet.getRange(1,1,lr,6);
var destination = pasteSheet.getRange(1,1,lr,6);
source.copyTo(destination, {formatOnly:true , contentsOnly:true});
source.copyTo(destination,SpreadsheetApp.CopyPasteType.PASTE_COLUMN_WIDTHS,false);
destination.clearContent();
var values = source.getValues();
var temp_array = [];
for (var i = 0; i < lr; i++) {
var rowValue = values[i];
if (rowValue[2] != '') {
temp_array.push(rowValue);
}
}
var newDest = pasteSheet.getRange(1,1,temp_array.length,6)
newDest.setValues(temp_array);
pasteSheet.deleteColumn(2);
}
One caveat is that you need to have the same format for all rows in a column.
Sample Input:
Sample Output:

Move a static range of data to another sheet while getting other fields into columns next to the destination (Google Sheets)

The challenge has been getting cell values from the document header together with a range underneath this header to Sheet2, having it as a table, so that later, I can filter, update and delete records via scripts.
So far, I got the below code copying what's within the range underneath the header:
function copyrange() {
var sourceSheet = 'NewItem';
var destinationSheet = 'DW';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sourceSheet);
var LastRowSource = sheet.getLastRow();
var LastColumnSource = sheet.getLastColumn();
var values = sheet.getRange(11,1,LastRowSource,LastColumnSource).getValues();
var csh = ss.getSheetByName(destinationSheet);
var data = [];
var j =[];
//var itemheader = [sheet.getRange("C4:4").getValues(),sheet.getRange("A3:3").getValues(),sheet.getRange("i3:3").getValues(),sheet.getRange("i4:4").getValues(),sheet.getRange("c5:5").getValues(),sheet.getRange("e5:e").getValues(),sheet.getRange("i5:5").getValues(),
// sheet.getRange("C7:7").getValues(),sheet.getRange("c8:8").getValues(),sheet.getRange("c9:9").getValues(),sheet.getRange("e7:7").getValues(),sheet.getRange("e8:8").getValues(),sheet.getRange("i7:7").getValues(),sheet.getRange("i8:8").getValues(),
// sheet.getRange("e9:9").getValues()];
for (var i = 1; i < values.length; i++) {
if ( values[i][0] != '') {
data.push(values[i]);
//sheet.deleteRow(i+1)
}
}
//Copy data array to destination sheet
csh.getRange(csh.getLastRow()+1,17,data.length,data[0].length).setValues(data);
Now, getting different cell values from the header into a row and copying it to Sheet2 as many times/rows as there is in the range copied by the above script seems impossible to me.
Here is a link to a practical example:
https://docs.google.com/spreadsheets/d/1GlD_VIOFHj7PGfCCnfVZqdZbE22aVoUw91BSCZecsRc/edit?usp=sharing
Thanks a lot for your help. Believe me, I've hit my head against the wall enough with this one before I turn to you guys!

Google script time out

My script is timing out, I guess because it's going over the 6 minute limit. Does anyone have an idea how I can optimize it so it runs faster?
The purpose of this script is to copy all the data from one sheet to another sheet, and then fill down some formulas on the destination sheet.
The amount of data copied is quite large (20,000 rows and columns to R) but I don't think it's so much that it should time out? I'm very new to this, so any advice is appreciated!
Here's the script:
function copyPasteTo2ndSheet()
{
var copyURL = 'ThisIsTheOriginSheetURL';
var pasteURL = 'ThisIsTheDestinationSheetURL';
var ssCopy = SpreadsheetApp.openByUrl(copyURL);
var ssPaste = SpreadsheetApp.openByUrl(pasteURL);
var copySheet = ssCopy.getSheetByName('Orders');
var pasteSheet = ssPaste.getSheetByName('Orders');
var lr = copySheet.getLastRow();
var copyData = copySheet.getRange('A2:R'+lr).getDisplayValues();
var pasteLr = pasteSheet.getLastRow();
pasteSheet.getRange('A2:R'+pasteLr).clear();
pasteSheet.getRange('A2:R'+lr).setValues(copyData);
copyPasteFormula(pasteSheet)
}
function copyPasteFormula(sheet)
{
var formulas = sheet.getRange(2, 1, 1, sheet.getLastColumn()).getFormulas()[0];
var lr = sheet.getLastRow();
for(var i in formulas)
{
var formula = formulas[i];
if(formula !== '')
{
var j = parseInt(i)+1;
sheet.getRange(3, j, lr, 1).setFormula(formula);
}
}
}
From the experience that I have had, the sheet.getRange(3, j, lr, 1) line, that has to repeat for 20,000 cells is likely causing the issue.
Commands that get or set to the sheet often take longer and use more memory to run. As a result, it is recommended to either batch your gets or, in this case, you can likely copy an entire row paste it. Copying a formula and pasting it in a different cell will update cell references, just as it does in the UI.

If matching content move to new sheet

I am writing a script that looks through a list of suppliers, then needs to create a new sheet for each of them and import the information for that supplier into that sheet.
So far, I have the following:
function getData() {
var masterSS = SpreadsheetApp.getActiveSpreadsheet() || SpreadsheetApp.openById("xxx");
var supSS = masterSS.getSheetByName("Suppliers");
masterSS.setActiveSheet(supSS)
var supSR = 2;
var supNoRows = supSS.getLastRow() - 1;
var supRange = supSS.getRange(supSR, 1, supNoRows, masterSS.getLastColumn());
var supData = supRange.getValues();
var orderSS = masterSS.getSheetByName("Orders");
var orderData = orderSS.getRange("A2:AB").getValues();
var templateSS = masterSS.getSheetByName("Template");
supData.forEach(function(name) {
var newSheet = masterSS.insertSheet(name, {template: templateSS});
console.log(name)
});
}
This is working as intended and is creating a sheet for each supplier listed on the Supplier sheet. I then need it to look through a range on a sheet called Orders, and if A2:A matches the supplier name used to create the new sheet, import that row to the newly created sheet.
I can't figure out quite how to get this working, as I would need to do it as each sheet is created. Anyone able to point me in the right direction?

Spreadsheet to copy informations from another sheets - Javascript

I'm looking way to create easier version of my code. I want to, copy information from every sheet to one sheet. First informations from first sheet, then below from second sheet etc. Now I have every each code for sheet, it is any way to make it easier? What code should use? Below my code and drawing with explanation.
function copy() {
var ur = SpreadsheetApp.getActiveSpreadsheet(); // sheet where we copy data
var urgents = ur.getSheetByName("List");
var lastRow = urgents.getLastRow();
var range = urgents.getRange("A2:B");
range.clear(); // every time script clear data
var importsh = SpreadsheetApp.openById('115nqlMpW3dhI-adpWvir5RZeayM01HqvjOcDc2_yLvQ');
var imbrak = importsh.getSheetByName('List_1'); // sheet from we copy data
var imbrak2 = importsh.getSheetByName('List_2'); // sheet from we copy data
var lastcol = importsh.getLastColumn();
var lastcol2 = imbrak2.getLastColumn();
var last = imbrak.getLastRow();
var last2 = imbrak2.getLastRow();
var urlast = last;
var urlast2 = last2;
var data = imbrak.getRange("A2:B"+last).getValues();
var data2 = imbrak2.getRange("A2:B"+last2).getValues();
urgents.getRange("A2:B"+last).setValues(data);
urgents.getRange(getFirstEmptyRowWholeRow3(),1,last2-1,2).setValues(data2);
}
Regards
How about this modification? Please think of this as one of several answers.
Modification points :
Use an array for sheet names.
By this, when it increases the number of sheets, you can use this script by importing the sheet names to the array.
All data of each sheets is imported to an array.
By this, the data can be imported to the destination sheet by one call of setValues().
Modified script :
function copy() {
var ur = SpreadsheetApp.getActiveSpreadsheet(); // sheet where we copy data
var urgents = ur.getSheetByName("List");
var lastRow = urgents.getLastRow();
var range = urgents.getRange("A2:B");
range.clear(); // every time script clear data
// Added
var importsh = SpreadsheetApp.openById('115nqlMpW3dhI-adpWvir5RZeayM01HqvjOcDc2_yLvQ');
var sheets = ['List_1', 'List_2']; // Please import sheet names here.
var data = [];
sheets.forEach(function(e){
var s = importsh.getSheetByName(e);
var values = s.getRange("A2:B"+s.getLastRow()).getValues();
Array.prototype.push.apply(data, values);
});
urgents.getRange(2, 1, data.length, data[0].length).setValues(data); // Please confirm this range.
}
Note :
Please confirm the range of urgents.getRange(2, 1, data.length, data[0].length).setValues(data);. Because I have no information about getFirstEmptyRowWholeRow3().
In the current range, the data is imported to "A2:B".
If I misunderstand your question, please tell me. I would like to modify.

Categories