I am trying to append all spreadsheets from the same folder to a master sheet.
I have found a similar code here but I can append the spreadsheets only when the master sheet is also in the selected folder. How could it be modified so that it could be able to applicable to other folders?please advise~
function appendData() {
var sheet = SpreadsheetApp.getActiveSheet();
var folder = DriveApp.getFolderById("1UQ5J3xdNnqyHvC-CJ1vAu5YPSxq9Sya9");
var files = folder.getFiles();
var cnt=0;
while (files.hasNext()) {
var file = files.next();
cnt++;
// if the file is not a Sheet, skip it
if (file.getMimeType() != "application/vnd.google-apps.spreadsheet") {
continue;
}
var importSheet = SpreadsheetApp.openById(file.getId())
// assuming you only want to append the first sheet of each Spreadsheet:
var range = importSheet.getSheets()[0].getDataRange();
// extend the main sheet if you need to:
try {
sheet.getRange(1, 1, sheet.getDataRange().getNumRows() + range.getNumRows(), 1);
}
catch (e) {
sheet.insertRowsAfter(sheet.getDataRange().getNumRows(), range.getNumRows() + 1);
}
// remove the headers from the data to copy:
range = importSheet.getSheets()[0].getRange(2, 1, range.getNumRows() - 1, range.getNumColumns())
// copy the data:
sheet.getRange(sheet.getDataRange().getNumRows() + 1, 1, range.getNumRows(), range.getNumColumns()).setValues(range.getValues());
}
}
Try this:
function appendData() {
var sheet=SpreadsheetApp.getActiveSheet();
var folder=DriveApp.getFolderById("1UQ5J3xdNnqyHvC-CJ1vAu5YPSxq9Sya9");
var files=folder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (files.hasNext()) {
var file = files.next();
var importSheet=SpreadsheetApp.openById(file.getId())
var values=importSheet.getSheets()[0].getDataRange().getValues();
sheet.getRange(sheet.getLastRow()+1,1,values.length,values[0].length).setValues(values);
Logger.log(file.getName());
}
}
Append both spreadsheets and Excel files to the same master sheet
If you need to append not only sheets from Google spreadsheets, but also form Excel files, you need to convert the latter ones to Google Sheets first.
For this, you can modify your existing code as following:
function appendData() {
var sheet = SpreadsheetApp.getActiveSheet();
var folder = DriveApp.getFolderById("1fUpTphVpYGfLv6SjWxZdbcIK7PHCZOnt");
var files = folder.getFiles();
var cnt=0;
while (files.hasNext()) {
var file = files.next();
cnt++;
// if the file is an excel - convert it to sheet
if (file.getMimeType() != "application/vnd.google-apps.spreadsheet") {
Logger.log(file.getMimeType());
//here is the additional part
//define here mime-types of interest and convert them
if (file.getMimeType() == "application/vnd.ms-excel" || file.getMimeType() == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
var fileId = file.getId();
var folderId = folder.getId();
var blob = file.getBlob();
var resource = {
title: file.getName(),
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{id: folderId}],
};
var file = Drive.Files.insert(resource, blob);
}else{
continue;
}
}
var importSheet = SpreadsheetApp.openById(file.getId())
// assuming you only want to append the first sheet of each Spreadsheet:
var range = importSheet.getSheets()[0].getDataRange();
// extend the main sheet if you need to:
try {
sheet.getRange(1, 1, sheet.getDataRange().getNumRows() + range.getNumRows(), 1);
}
catch (e) {
sheet.insertRowsAfter(sheet.getDataRange().getNumRows(), range.getNumRows() + 1);
}
// remove the headers from the data to copy:
range = importSheet.getSheets()[0].getRange(2, 1, range.getNumRows() - 1, range.getNumColumns())
Logger.log("range.getA1Notation():" + range.getA1Notation());
// copy the data:
sheet.getRange(sheet.getDataRange().getNumRows() + 1, 1, range.getNumRows(), range.getNumColumns()).setValues(range.getValues());
}
}
Related
I have files on the folder and i import them to the google sheet.
I need to add filename to first column before import, but my script add it only to first cell before import
So it gives me:
Filename
Pencil
01/01/2022
Pen
01/02/2022
Hat
And i need
Filename
1/01/2022
Pencil
Filename
1/01/2022
Pen
Filename
01/02/2022
Hat
function Import_Kredo() {
var arr = [];
var files = DriveApp.getFolderById("13kymSiqX0-L6a9ev4It1_BEjH-xM8rnc").getFiles();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Table 1");
copySheet.getRange('A2:G').clear();
while (files.hasNext()) {
var file = files.next();
var mimeType = file.getMimeType();
var ss1 = null, id = null;
if (mimeType == MimeType.MICROSOFT_EXCEL) {
id = Drive.Files.copy({ mimeType: MimeType.GOOGLE_SHEETS }, file.getId()).id;
ss1 = SpreadsheetApp.openById(id);
} else if (mimeType == MimeType.GOOGLE_SHEETS) {
ss1 = SpreadsheetApp.open(file);
}
if (!ss1) continue;
var sheet = ss1.getSheetByName("Table 1");
if (!sheet) continue;
var sheetsRange = sheet.getDataRange();
var sheetsValues = sheetsRange.getValues().filter(r => r[1]).filter(e => e);
var v = sheetsValues.slice(1);
console.log([file.getName(), v])
arr = arr.concat([[file.getName(), ...Array(v[0].length - 1).fill(null)], ...v]);
if (id) DriveApp.getFileById(id).setTrashed(true); // or Drive.Files.remove(id);
}
copySheet.getRange(5, 1, arr.length, arr[0].length).setValues(arr);
}
In your situation, how about the following modification?
From:
arr = arr.concat([[file.getName(), ...Array(v[0].length - 1).fill(null)], ...v]);
To:
var filename = file.getName();
arr = arr.concat(v.map(e => [filename, ...e]));
By this modification, the filename is put into the 1st column of each row.
I have tried to amend the below script to essentially convert a entire google sheet to xlsx file, keeping tab names the same and locating them to a folder,
The issue I am experiencing with the below is that is is splitting out each tab into separate files but I would like to keep them all together in one file
https://webapps.stackexchange.com/questions/58615/export-all-sheets-in-a-spreadsheet-to-csv-in-google-apps
function saveAsxlsx() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// create a folder from the name of the spreadsheet
var folder = DriveApp.getFolderById('xxxxxxx');
for (var i = 0 ; i < sheets.length ; i++) {
var sheet = sheets[i];
// append ".xlsx" extension to the sheet name
fileName = sheet.getName() + ".xlsx";
// convert all available sheet data to xlsx format
var xlsxFile = convertRangeToxlsxFile_(fileName, sheet);
// create a file in the Docs List with the given name and the xlsx data
folder.createFile(fileName, xlsxFile);
}
Browser.msgBox('Files are waitig in a folder named ' + folder.getName());
}
function convertRangeToxlsxFile_(xlsxFileName, sheet) {
// get available data range in the spreadsheet
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var xlsxFile = undefined;
// loop through the data in the range and build a string with the xlsx data
if (data.length > 1) {
var xlsx = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// join each row's columns
// add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
xlsx += data[row].join(",") + "\r\n";
}
else {
xlsx += data[row];
}
}
xlsxFile = xlsx;
}
return xlsxFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
The script you're using was designed to get each sheet as a separate file. You can refer to this example instead that will convert Google Sheet to Excel XLSX Spreadsheet. I added a couple of lines to the code to save the file to a folder instead of sending an email as the example does.
function getGoogleSpreadsheetAsExcel() {
try {
var ss = SpreadsheetApp.getActive();
var url = 'https://docs.google.com/feeds/download/spreadsheets/Export?key=' + ss.getId() + '&exportFormat=xlsx';
var folder = DriveApp.getFolderById('folderID'); //Add the folder ID of the folder where you want to save the file
var params = {
method: 'get',
headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
muteHttpExceptions: true,
};
var blob = UrlFetchApp.fetch(url, params).getBlob();
blob.setName(ss.getName() + '.xlsx');
folder.createFile(blob)
} catch (f) {
Logger.log(f.toString());
}
}
Problem 1:
When I try to execute the below code it comes up with the error 'Exception: Invalid argument: name (line 37, file "Create New Project")'. I originally thought that it could be that the variable 'jobNumber' wasn't a string but now that it is, it still doesn't execute.
Problem 2:
When I don't use the variable 'jobNumber' for the folder name and just us a string value, it executes. However the new folder does not go into the source folders drive but into my personal drive.
function createProject(){
searchProject();
createFolder();
}
//Search for New Project and return values
function searchProject(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var search = "New Job";
for(var i = 0; i<data.length;i++){
if(data[i][9] == search){
Logger.log((i+1));
var jobNumber = sheet.getRange((i+1), 1).getDisplayValue()
var jobSite = sheet.getRange((i+1), 2).getDisplayValue()
var jobTitle = sheet.getRange((i+1), 3).getDisplayValue()
return i+1;
}
}
}
//Create New Project Folders
function createFolder(jobNumber, jobSite, jobTitle) {
var sourceFolder = "12345_Site Name_Commissioning Engineer Name";
var targetFolder = jobNumber
var source = DriveApp.getFoldersByName(sourceFolder);
var target = DriveApp.createFolder(targetFolder);
if (source.hasNext()) {
copyFolder(source.next(), target);
}
}
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);
}
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}
I have managed to find my own solution.
By adding the 'foler_ID' and 'folder' variable to get the folder to go into the correct folder in google drive.
I also missed calling the creatFolder function in searchProject function, with that now included the variables are carried over.
Thanks for all the contributors that helped :)
/**
* Create New Project
*/
//Search for New Project and return values
function createProject(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var search = "New Job";
for(var i = 0; i<data.length;i++){
if(data[i][9] == search){
Logger.log((i+1));
var jobNumber = sheet.getRange((i+1), 1).getDisplayValue()
var jobSite = sheet.getRange((i+1), 2).getDisplayValue()
var jobTitle = sheet.getRange((i+1), 3).getDisplayValue()
createFolder (jobNumber, jobSite, jobTitle);
Logger.log(jobNumber);
Logger.log(jobSite);
Logger.log(jobTitle);
return i+1;
}
}
}
//Create New Project Folders
function createFolder(jobNumber, jobSite, jobTitle) {
var sourceFolder = "12345_Site Name_Commissioning Engineer Name";
var targetFolder = (jobNumber + " " + jobSite + " " + jobTitle + "TESTING");
var foler_ID = '14QpCYc803GnDC_pR-7AqViePHBKyNNv_';
var folder = DriveApp.getFolderById(foler_ID);
var source = DriveApp.getFoldersByName(sourceFolder);
var target = folder.createFolder(targetFolder);
Logger.log(target);
if (source.hasNext()) {
copyFolder(source.next(), target);
}
}
function copyFolder(source, target) {
var folders = source.getFolders();
var files = source.getFiles();
while(files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), target);
}
while(folders.hasNext()) {
var subFolder = folders.next();
var folderName = subFolder.getName();
var targetFolder = target.createFolder(folderName);
copyFolder(subFolder, targetFolder);
}
}
I want to download all the sheets of an excel document in csv format. presently, only the first sheet data is accessible. code is given below:
function downloadGDriveFile (file) {
var request1 = gapi.client.drive.files.export({
'fileId': '1VLFgD8CNvXTVdHKyBdZPUmgFmhWMzg7qWLbxzLUTtSo',
'mimeType': 'text/csv'
})
request1.then(function(response) {
//console.log(response);
}, function(err) {
console.log('Error');
console.log(err.result.error);
});
}
presently I am using a static id. The excel gave two sheets. But the code shows only first sheet data. how to download all the sheets with in a workbook.
I've read from this tutorial blog that this is indeed the behavior when you try to export files.
However, there's a way to get all sheets from your spreadsheet using Apps Script. After executing custom menu "csv->export as csv file", the sheets will be placed inyour Google Drive inside a folder. Here's the code from the blog:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var csvMenuEntries = [{name: "export as csv files", functionName: "saveAsCSV"}];
ss.addMenu("csv", csvMenuEntries);
};
function saveAsCSV() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
// create a folder from the name of the spreadsheet
var folder = DriveApp.createFolder(ss.getName().toLowerCase().replace(/ /g,'_') + '_csv_' + new Date().getTime());
for (var i = 0 ; i < sheets.length ; i++) {
var sheet = sheets[i];
// append ".csv" extension to the sheet name
fileName = sheet.getName() + ".csv";
// convert all available sheet data to csv format
var csvFile = convertRangeToCsvFile_(fileName, sheet);
// create a file in the Docs List with the given name and the csv data
folder.createFile(fileName, csvFile);
}
Browser.msgBox('Files are waiting in a folder named ' + folder.getName());
}
function convertRangeToCsvFile_(csvFileName, sheet) {
// get available data range in the spreadsheet
var activeRange = sheet.getDataRange();
try {
var data = activeRange.getValues();
var csvFile = undefined;
// loop through the data in the range and build a string with the csv data
if (data.length > 1) {
var csv = "";
for (var row = 0; row < data.length; row++) {
for (var col = 0; col < data[row].length; col++) {
if (data[row][col].toString().indexOf(",") != -1) {
data[row][col] = "\"" + data[row][col] + "\"";
}
}
// join each row's columns
// add a carriage return to end of each row, except for the last one
if (row < data.length-1) {
csv += data[row].join(",") + "\r\n";
}
else {
csv += data[row];
}
}
csvFile = csv;
}
return csvFile;
}
catch(err) {
Logger.log(err);
Browser.msgBox(err);
}
}
I have a folder named "TEST FOLDER" I have two spreadsheets, TEST1 AND TEST2, I also have a spreadsheet called MASTER. I want to have a script in the MASTER Spreadsheet which will work on a Trigger to run once a day. It will run through any SPREADSHEET within "TEST FOLDER" and copy all new rows into the MASTER SHEET. I will put "Copied" in a column to have a value to check to make sure no rows are copied twice.
var folder = DocsList.getFolder("TEST FOLDER");
var contents = folder.getFiles();
var file;
var data;
for (var i = 0; i < contents.length; i++) { file = contents[i];
if (file.getFileType() == "SPREADSHEET") {
continue;
}
var s = SpreadsheetApp.getActiveSpreadsheet();
var startRow = 2;
var numRows = sheet.getLastRow();
var dataRange = sheet.getRange(startRow, 1, numRows, 6);
var data = dataRange.getValues();
var copied = row[5]; //copied indicator cell
if(copied != "Copied")
{
var target = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("MASTER");
var targetSheet = target.getRange(rowIndex, nameCol).getValue();
if (target.getSheetByName(targetSheet)) {
// set our target sheet and target range
var targetSheet = ss.getSheetByName(targetSheet);
var targetRange = targetSheet.getRange(targetSheet.getLastRow()+1, 1, 1, colNumber);
var sourceRange = s.getRange(rowIndex, 1, 1, colNumber);
sourceRange.copyTo(targetRange);
sheet.getRange(startRow + i, 6).setValue("Copied");
SpreadsheetApp.flush();
}
}
}
Here is my code so far. I
I change a bit the code and this one must work. Please adapt depending your file structure
function getDataToMaster() {
var folder = DriveApp.getFolderById("IdOfFolder"); //Define id of folder
var contents = folder.getFiles();
var file;
var data;
var sheetMaster = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0]; //first sheet of the file, change by getSheetByName("NAME") if you want
while(contents.hasNext()){
file = contents.next();
if (file.getMimeType() == "application/vnd.google-apps.spreadsheet") {
var sheet = SpreadsheetApp.openById(file.getId()).getSheets()[0];//first sheet of the file, change by getSheetByName("NAME") if you want
var startRow = 2;
var data = sheet.getDataRange().getValues();
var colToCheck = 6;
for(var j = 1; j < data.length;j++){
if(data[j][colToCheck-1] != "copied"){
sheetMaster.appendRow(data[j]);
sheet.getRange((j+1), colToCheck).setValue("copied");
SpreadsheetApp.flush();
}
}
}
}
}
Stéphane