Get Spreadsheets from a folder and modify them - google-apps-script

I have a folder called "Adform" in my Drive and I want to take all the spreadsheets from there and modify them by adding new columns, change headers.
At this point I managed to get the files name, one by one, but I don't know how to use SpreadSheetApp to modify those Spreadsheets.
var folders = DriveApp.getFoldersByName('Adform');
while (folders.hasNext()) {
var files = folders.next().getFiles();
while (files.hasNext()) {
var file = files.next();
Logger.log(file.getName());
}
}

How to loop through all the Spreadsheets in a Drive folder
You are almost there. The best way in my opinion is to check if the mime type of the file is application/vnd.google-apps.spreadsheet, and if so, get the id. Then pass this id to another function that will modify the Spreadsheet in any way that you want.
function myFunction() {
var folders = DriveApp.getFoldersByName('Adform');
while (folders.hasNext()) {
var files = folders.next().getFiles();
while (files.hasNext()) {
var file = files.next();
// Check if file is a spreadsheet
if (file.getMimeType() === "application/vnd.google-apps.spreadsheet") {
// Call the function to modify the spreadsheet with the file id
modifySpreadhsheet(file.getId())
}
}
}
}
function modifySpreadsheet(id) {
// Open the file with the id
var file = SpreadsheetApp.openById(id);
// Get all the sheets
var sheets = file.getSheets()
// Get the first sheet
var firstSheet = sheets[0]
// Get the range that contains all the data in that sheet
var range = firstSheet.getDataRange();
// Get all the values in that range
var values = range.getValues();
Logger.log(values)
}
This sample function will just get the first sheet of the spreadsheet and then Log all the data within that spreadsheet to the logger.
Then you can use functions like setValues(values) to modify the content as needed.
References
getMimeType()
getId()
openById(id)
getSheets()
getDataRange()
getValues()

Related

Google Apps Script, Google Sheets - Getting Spreadsheet ID and Sheet ID programmatically

I've been reading this without making any headway:
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app
Is there a way to programmatically get the Spreadsheet ID and Sheet ID of a particular Google SpreadSheet's sheet without manually typing or copying the URL?
1.) If the script is bound to the spreadsheet then you can just use getID and getSheetID as mentioned by TheMaster in the comments. See codes below:
function getIDs() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var spreadSheetID = ss.getId();
var sheetID = sheet.getSheetId();
console.log(spreadSheetID);
console.log(sheetID);
}
Result:
Take note that the first sheet always has an ID of 0 (gid=0) as the default value.
2.) Otherwise if what you are trying to do is get the Spreadsheet ID and Sheet ID from different spreadsheets it is not possible without copying the URL since there is no way it can identify which spreadsheet to refer to.
3.) Suggestion
What you can do if you need to get IDs of different files is to move them to a folder in your drive, then you can use the code below:
function listFilesInFolder(folderName) {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).clearContent();
sheet.appendRow(["Name", "Spreadsheet ID", "Sheet ID"]);
//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
var folder = DriveApp.getFolderById("HIS_SHOULD_BE_YOUR_FOLDER_ID");
var contents = folder.getFiles();
var cnt = 0;
var file;
while (contents.hasNext()) {
var file = contents.next();
cnt++;
data = [
file.getName(),
file.getId(),
];
var spreadsheetSheets = SpreadsheetApp.openById(data[1]).getSheetByName("Sheet2").getSheetId();
data.push(spreadsheetSheets);
sheet.appendRow(data);
};
};
Folder:
Result:
Note: In my example code I've made use of Sheet2 to see that it is working as expected. Please set accordingly to the name of the sheet which you are trying to get the ID.
Let me know if this works for you or if you have other questions.
References:
Are Google Spreadsheets' first sheets always given an ID of 0?
Getting all files ID in drive folder

GoogleSheets with GoogleApps. A little loss with Creating and copying

A month into google apps/googlesheets. I've got some of the basics down, however struggling to put a lot of basic concepts together.
Step 1) Create and check if Spreadsheet exists in folder. If it doesn't exist create one based on the name in Cell A1 and COPY ActiveSpreadsheet() data to that new FILE with sheet name TODAY() date.
Step 2) If a spreadsheet with name exists, copy from ActiveSpreadsheet() to the spreadsheet named in Cell A1 with a NEW SHEET named after today's date.
So far I have got pieces of stuff together but I am MISSING basic knowledge of trying to put it altogether. Sorry if its a COMPLETE mess I'm trying to piece it together as I go. ANY HELP WILL be appreciated or websites/resources to lead me in the right direction.
function saveAsSpreadsheet(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var range = sheet.getRange('Sheet1!A1');
var destFolder = DriveApp.getFolderById("XXXXXXXXXX");
DriveApp.getFileById(sheet.getId()).makeCopy(NAME CHECK, destFolder);
if( ss.getSheetByName('') == null)
//if returned null means the sheet doesn't exist, so create it
var val = Utilities.formatDate(new Date(A2), "GMT+1", "MM/dd/yyyy");
ss.insertSheet(val, ss.getSheets().length, {template: templateSheet});
sheet2 = ss.insertSheet(A2);
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName('Sheet1');
var sh2=ss.getSheetByName(new Date(A2));
var C2=sh1.getRange('C2').getValue();
var L2=sh1.getRange('L2').getValue();
sh2.appendRow([new Date(),C2,L2]);
}
Probably you need something like this:
function main() {
// get current date
var date = Utilities.formatDate(new Date(), 'UTC', 'YYYY-MM-dd');
// get current spreadsheet
var cur_ss = SpreadsheetApp.getActiveSpreadsheet();
// get folder
var folder = DriveApp.getFolderById('###'); // <--- your folder ID goes here
// get file name from the cell 'Sheet1!A1'
var name = cur_ss.getSheetByName('Sheet1').getRange('A1').getValue();
// seach for the file in the folder and get it if it exists
var file = get_file_from_folder(folder, name);
// if file exists: copy current sheet to this file
// and rename copied sheet
if (file != null) {
var dest_ss = SpreadsheetApp.openById(file.getId());
cur_ss.getActiveSheet().copyTo(dest_ss).setName(date);
}
// if file doesn't exists: make а copy of current spreadsheet,
// and rename the sheet with the same name as your active sheet
else {
var file = DriveApp.getFileById(cur_ss.getId()).makeCopy(folder).setName(name);
var dest_ss = SpreadsheetApp.openById(file.getId());
dest_ss.getSheetByName(cur_ss.getActiveSheet().getName()).setName(date);
}
}
// functions searches for the file with given name in given folder and returns the file.
// In case the folder has no such file the function returns 'null'
function get_file_from_folder(folder, name) {
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
if (file.getName() == name) return file;
}
return null;
}
Keep in mind, sometimes the destination spreadsheet can have a sheet with the same name already. It will get an error. Probably you need to handle that collision somehow.

Merge n Google spreadsheets files to n sheets

Say, I have 100 google spreadsheets file and I need to merge into one file with 100 tabs(sheets). Is it possible with app script. Currently I have a code below,
function popForm() {
var ss = SpreadsheetApp.getActive();
for(var b = 0; b<100; b++){
var sheet = ss.getSheetByName('Sheet '+b);
var numberRows = sheet.getDataRange().getNumRows();
....
....
The above code will work with spreadsheets with 100 tabs(Sheets). But I have 100 sreadsheets with one tab(Sheet).
Explanation:
You have a folder with FolderId that contains all the spreadsheet
files. You find this folder using the getFolderById() method.
You get the files of this folder using the getFiles() method and
you use a while loop to iterate over these files.
For every file, you get the first sheet and you copy it using the
copyTo() method to the source (active) spreadsheet file.
The newly create sheet will be named after the name of the spreadsheet file that it came from. Feel free to change this part or let me know so I can modify it.
Solution:
You must be looking for this:
function myFunction() {
const source_sh = SpreadsheetApp.getActive();
const folder = DriveApp.getFolderById('FolderId');
const files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
var target_ss = SpreadsheetApp.openById(file.getId());
var target_sh = target_ss.getSheets()[0];
target_sh.copyTo(source_sh).setName(file.getName());
}
}

Get list of folders on Gsuite google drive, list them alphabetically on a Google Sheet

Trying to get a list of folders (not sub folders or files) in a Gsuite shared drive to populate a Google Sheet worksheet, but the script below fails after first time and will not overwrite the list when I re-run.
I have tried quite a few variations, but my problem is:
1. I would love to have a 3rd column produced showing the html
2. Script works once, but when I refresh or place a trigger on the sheet it no longer works or updates.
Here is my current code:
function listFilesInFolder(folderName) {
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow(["Name", "File-Id"]);
//change the folder ID below to reflect your folder's ID (look in the URL when you're in your folder)
var folder = DriveApp.getFolderById("0ADTcDD3ZSaa5Uk9PVA");
var contents = folder.getFolders()
var cnt = 0;
var file;
while (contents.hasNext()) {
var file = contents.next();
cnt++;
data = [
file.getName(),
file.getId(),
];
sheet.appendRow(data);
};
};
Any suggestions on how to:
1. Get the folder list to update each hour on the Google sheet?
2. Fix error where the folder list is not updating/overwriting?
3. Add the html of each folder into a third column?
4. Have the list produced in alphabetical order?
Many thanks in advance if you have made it this far!
function listFoldersInAFolder() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.clearContents();
sh.appendRow(["Name", "Folder-URL"]);
var fA=[];
var folders=DriveApp.getFolderById("folder id").getFolders();//Enter folder id
while (folders.hasNext()) {
var folder= folders.next();
fA.push([folder.getName(),folder.getUrl()]);
}
sh.getRange(sh.getLastRow()+1,1,fA.length,2).setValues(fA);
sh.getRange(2,1,sh.getLastRow()-1,2).sort({column:1,ascending:true});
}
If you want to get all folders and sub folders you will have to recurse them. Here's an example of that: https://stackoverflow.com/a/55248127/7215091

google sheet script editor import multiple sheets

Objective
I am trying to use the google script editor to import csv files on google drive into my google sheet. Can someone clarify to me what I'm misunderstanding about the script and what I need to tweak to allow me to paste multiple sheet requests into the below? Apologies if this is something straight forward, this is my first time using the script editor, and I'm not familiar with a lot of this.
Issue
At current my code only populates 1 sheets worth of data. as opposed to treating the second part as the next sheet that I want populated, with a different csv sheet ID.
What I've tried
Changing the variables to be more unique to get the sheet to treat my variables as different, as I thought it was wiping each time.
Reviewing other online help forums without luck of finding something
similar that I can understand.
Current Code
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('RefreshData')
.addItem('Run getCSV', 'getCSV')
.addToUi()
}
function getCSV() {
//ENTER YOUR CSV FILE ID IN THE getFileByID in the ""
var file = DriveApp.getFileById("<file_id>");
var csvFile = file.getBlob().getDataAsString();
var csvData = Utilities.parseCsv(csvFile);
//CHANGE SHEET NAME TO WHATEVER YOUR SHEET IS CALLED
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
sheet.clear();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
function getCSV() {
//ENTER YOUR CSV FILE ID IN THE getFileByID in the ""
var file = DriveApp.getFileById("<file_id2>");
var csvFile = file.getBlob().getDataAsString();
var csvData = Utilities.parseCsv(csvFile);
//CHANGE SHEET NAME TO WHATEVER YOUR SHEET IS CALLED
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
sheet.clear();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
You have getCSV() defined twice and that will cause problems. Function names, like variables, should be unique. Otherwise, they'll get rewritten.
Take the case of two test() functions. Every time you run testAll(), the output will always be 2.
function testAll() {
test(); // 2.0
test(); // 2.0
}
function test() {
Logger.log(1);
}
function test() {
Logger.log(2);
}
What you could do is modify getCSV() so that it accepts inputs and then create a new function that will pass the data into it. Then call that new function in your menu.
/**
* Add a custom menu to the spreadsheet.
*/
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu("RefreshData")
.addItem("Get CSVs", "importSheets")
.addToUi();
}
/**
* Imports all CSV files.
*/
function getCSVs() {
// Define the CSV files and where you want them to be saved
var csvs = [
{ fileId: "FILE_ID_1", sheetName: "Sheet1" },
{ fileId: "FILE_ID_2", sheetName: "Sheet2" }
];
// Import the CSVs
for (var i = 0; i < csvs.length; i++) {
getCSV_(csvs[i].fileId, csvs[i].sheetName);
}
}
/**
* Get the CSV data from a specified file and import into the desired
* sheet of the active spreadsheet.
* #param {String} fileId - The file ID of the CSV file
* #param {String} sheetName - The name of the destination sheet
*/
function getCSV_(fileId, sheetName) {
//ENTER YOUR CSV FILE ID IN THE getFileByID
var file = DriveApp.getFileById(fileId);
var csvFile = file.getBlob().getDataAsString();
var csvData = Utilities.parseCsv(csvFile);
//CHANGE SHEET NAME TO WHATEVER YOUR SHEET IS CALLED
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
sheet.clear().getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
Created an additional function getCSV2 which states the sheet name and ID which is then populated and looped in the getCSV function.
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('RefreshData')
.addItem('Run getCSV', 'getCSV')
.addToUi()
}
function getCSV() {
getCSV2("sheet1", "<file_id1>");
getCSV2("sheet2", "<file_id2>");
}
function getCSV2(name, id) {
var file = DriveApp.getFileById(id);
var csvFile = file.getBlob().getDataAsString();
var csvData = Utilities.parseCsv(csvFile);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name);
sheet.clear();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}