cannot find method copyTo error after creating new file in sheet - javascript

Would really appreciate your help here.
I'm creating a two step process where:
1. Create a new file named after a cell from the file to be copied from.
2. Copy the sheet to the newly created file.
I'm doing this because we will be creating unique files for several clients and I'd like to automate it.
Since I'm still new, I've been putting together code from various sources and modifying it to put what I want. However, this code creates a new file perfectly, but refuses to copy the content to the newly created file. I keep on getting a "cannot find method CopyTo error" and despite a ton of research and tweaking, I cannot get it to work. Help!?
function copy2() {
var folder=DriveApp.getFoldersByName("Dummy").next();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0,1];
var cellWithFileName = ss.getRange("A1");
var name = cellWithFileName.getValue();
var file=SpreadsheetApp.create(name);
var fileID = file.getId()
var copyFile=DriveApp.getFileById(fileID);
var destination = DriveApp.getFileById(fileID)
folder.addFile(copyFile);
DriveApp.getRootFolder().removeFile(copyFile);
ss.getSheetByName("Sheet1").copyTo(fileID);
}
Thanks

At copyTo(destination), destination is not file ID. It's Spreadsheet. So how about the following modification?
From :
ss.getSheetByName("Sheet1").copyTo(fileID);
To :
ss.getSheetByName("sheet1").copyTo(file);
Reference :
copyTo(spreadsheet)
If this didn't work, please tell me. I would like to modify.

Related

Delete curent item in a Javascript while hasNext-loop?

I have read 10+ questions about deleting items in Javascripts loops but they don't seem to apply to my situation.
I have this code
var childFolders = parent.getFolders();
// List folders inside the folder
while (childFolders.hasNext()) {
var childFolder = childFolders.next();
//processing childFolder
After this I want to delete the current item (childFolder) from the array childFolders. The reason is that I am doing some work in a Google Apps script but it often takes too long and times out so I need to be able to restart the loop and only have unprocessed items left in the array. To achieve this, in every loop, I copy the content of childFolders into a permanent storage that I can restore on the next run.
I believe your goal is as follows.
You want to stop the loop of the folder iterator, and when you run the script again, you want to start the folder iterator from the stopped iterator.
In this case, how about using "ContinuationToken"? When "ContinuationToken" is used, I thought that your goal might be able to be achieved by the native methods of Google Apps Script. When this is reflected in your script, how about the following script?
Sample script:
Please set var parent = DriveApp.getFolderById("###");.
// When you want to clear the token, please run this function.
function clearToken() {
PropertiesService.getScriptProperties().deleteProperty("token");
}
// This is the main function.
function main() {
var parent = DriveApp.getFolderById("###"); // Please set your parent folder.
var numberOfLoop = 2; // The folder iterator is run every this number.
var p = PropertiesService.getScriptProperties();
var token = p.getProperty("token");
var childFolders = token ? DriveApp.continueFolderIterator(token) : parent.getFolders();
var count = 0;
while (childFolders.hasNext()) {
count++;
var childFolder = childFolders.next();
//processing childFolder
console.log(childFolder.getName()); // This is a sample.
if (count == numberOfLoop) {
var token = childFolders.getContinuationToken();
p.setProperty("token", token);
break;
}
}
}
When you run main function, in this sample script, 2 folders are processed and the script is finished. When you run main again, the folder iterator is started from the continuation.
When you want to start from the 1st folder iterator, please run clearToken.
References:
getContinuationToken() of Class FolderIterator
continueFolderIterator(continuationToken) of Class DriveApp
Added:
From your following reply,
It is the script in step 3 here ourtechroom.com/fix/… I have problem with. I changed it to add all files to an array first and insert them into a sheet in a separate step at the end but that wasn't enough. Hence my question.
My issue is that your solution is a little too complicated for me. That is, I have a hard time applying your solution to the script in the link.
Do you want to retrieve the file metadata of all files in your Google Drive? If my understanding is correct, I think that the script in your link is a high process cost because appendRow is used in the loop. Ref I thought that this might be the reason for your actual situation. If my understanding is correct, how about the following sample script?
Usage:
1. Install Google Apps Script library.
You can see how to install Google Apps Script library of [FilesApp] at here.
2. Enable Drive API.
This modified script uses Drive API. So, please enable Drive API at Advanced Google services.
3. Sample script.
Please copy and paste the following script to the script editor of Spreadsheet. And, please set the top folder ID to folderId. If you use var folderId = "root";, all files in your Google Drive are retrieved.
function myFunction() {
var folderId = "###"; // Please set the top folder ID.
var header = ["parent", "folder", "name", "update", "Size", "URL", "ID", "description", "type"]; // This is from your script.
var obj = FilesApp.createTree(folderId, null, "files(name,modifiedTime,size,webViewLink,id,description,mimeType)");
var values = [header, ...obj.files.flatMap(({ folderTreeByName, filesInFolder }) => {
const f = [folderTreeByName.join("|"), folderTreeByName.pop()];
return filesInFolder.length == 0 ? [[...f, ...Array(7).fill(null)]] : filesInFolder.filter(({ mimeType }) => mimeType != MimeType.FOLDER).map(({ name, modifiedTime, size, webViewLink, id, description, mimeType }) => [...f, name || null, new Date(modifiedTime), size || 0, webViewLink, id, description || null, mimeType]);
})];
SpreadsheetApp.getActiveSheet().clear().getRange(1, 1, values.length, values[0].length).setValues(values);
}
References:
FilesApp of Google Apps Script library (Author me)
Files: list of Drive API v3

getDatecreated in Appps Script returning the time of creation an hour later

When I try to get the time of creation of a file in Google Drive with the built in function getDateCreated() in the apps script, it returns the time an hour after the creation.
My code is as follows
var folder = DriveApp.getFolderById(myFolderId);
var contents = folder.getFiles();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var var_file;
var var_name;
var var_link;
var var_owner;
var var_time;
while(contents.hasNext()){
var_file = contents.next();
var_name = var_file.getName();
var_link = var_file.getUrl();
var_owner = var_file.getOwner().getName();
var_time = var_file.getDateCreated();
sheet.appendRow([var_name,var_link,var_owner, var_time]);
}
If time of creation of a file is 25/06/2022 22:48:39
The output of my code returns 25/06/2022 23:48:39 which is an error.
Note: My time zone is UTC-5
I did some research on different built-in methods in Javascript and the .toLocaleTimeString() seems to work fine returning the actual time the file was created.
var_time = var_file.getDateCreated().toLocaleTimeString();
It's also quite important to check the appsscript.json file which can be accesed by going to Project Settings and toggling on the option Show the appsscripts.json file
The only reason could be the time zone setup of your script file. You can check out bi going to File > Project properties in the script editor.
Google developers docs
Also you can review this setting running this:
var timeZone = Session.getScriptTimeZone();
Logger.log(timeZone);

Use Functions from one Google Script in many different tables (google-sheets)

I wrote the google-script. In that script I have a function that I need to use in 250+ different tables (google-sheets). Question is - How can I make it function accessible in each table?
To make a script or custom function available across other Google Sheets, publish it as a library.
Bruce Mcpherson has a nice post on how to do this: http://ramblings.mcpher.com/Home/excelquirks/gooscript/lib
Yes, it is possible.
Two options:
Create a Apps Script project that calls the 250+ spreadsheet, makes the operations and updates each spreadsheet which the results.
On this you'll find a collection of tutorials to start with apps script.
https://developers.google.com/apps-script/articles/tutorials
Create a function that you can call from any cell of your spreadsheet just as you call any other default function like SUM()
On this documentation you'll find explained how to do this second option.
https://developers.google.com/apps-script/guides/sheets/functions#arguments
Ok, I fond the solution. In my case files that I need to change is placed in deferent folders and have similar name
// function that i need to execute
function updatePrices(sheetId){
// do some staff
var activeSpreadsheet = SpreadsheetApp.openById(sheetId);
var histPricesSheet = activeSpreadsheet.getSheetByName(someSheetName);
....
var cell = histPricesSheet.getRange(range);
cell.setValues(someData);
}
function walkFolders(folderId){
// function that walk by folders and get ids of spradsheeds
and call func that I need in each spradsheed that I need
var fin_fold = DriveApp.getFolderById(folderId);
var folders = fin_fold.getFolders();
while (folders.hasNext()) {
var folder = folders.next();
var files = folder.searchFiles('title contains "карточка"');
while (files.hasNext()){
var file = files.next();
updatePrices(file.getId()); // call my function to every spreadsheet
Logger.log("обновлено");
}
}
}
walkFolders("folder ID wich contain folders with files to change");

I need to overwrite an existing Google Sheets file with an attached Script

I have a Google Sheets file with an attached Script. The script does a number of things, one is it makes a clone of it self using makeCopy. This portion works. Now I want to be able to keep the same cloned Google file name and same Google file ID and just update the content which includes a Spreadsheet and the associated Google script.
if (!fileFound){
var file = masterSSFile.makeCopy(reportFileName, RepFolder);
} else {
oldFile.setContent(masterSSFile.getBlob());
}
When I use makeCopy with the same file name it creates a second file with the same name but with a different file ID.
The else portion fails because .setContent argument seems to just accept text. The result is the word "Blob" in the oldFile, everything else is gone.
I have other scripts that update the contents of a existing spreadsheet by overriding the contents of the various sheets, but I also want the associated script to also be included in the updated file keeping the same file ID.
I found this....
Overwrite an Image File with Google Apps Script
and tried using
var masterSpreadsheetID = SpreadsheetApp.getActiveSpreadsheet().getId();
var masterSpreadsheetFile = DriveApp.getFileById(masterSpreadsheetID);
var oldFileID = oldFile.getId();
var oldFileName = oldFile.getName();
var newBlob = masterSpreadsheetFile.getBlob();
var file = {
title: oldFileName,
mimeType: 'application/vnd.google-apps.spreadsheet'
};
var f = Drive.Files.update(file, oldFileID, newBlob);
I get error: "We're sorry, a server error occurred. Please wait a bit and try again. " on this line: "Drive.Files.update(file, oldFileID, newBlob);"
After reading this:
https://github.com/google/google-api-nodejs-client/issues/495
it looks like Drive.Files.update(), does not support bound scripts.

Add Spreadsheet file in a folder

Anyone know how create a Spreadsheet file in a specific folder on Google Drive?
I have already tried the answer from this link.
EDIT - Tried this answer :-D :
//"Move" file to folder-------------------------------//
var fileID = '12123123213321'
var folderID = '21321312312'
var file = DriveApp.getFileById(fileID).getName()
var folder = DriveApp.getFolderById(folderID)
var newFile = file.makeCopy(file, folder)
//Remove file from root folder--------------------------------//
DriveApp.getFileById(fileID).setTrashed(true)
But the "correct answer" gives me the follow error "Uncaught TypeError: Cannot find function makeCopy in object Spreadsheet."
I saw other answers but none of them work. I have already tried enable "Drive API" from "Advanced Google Services", but it's kind of complicate to work with.
UPDATE!
Just to explain, my problem is that I was creating the Spreadsheet
var sheetId = SpreadsheetApp.create("filename").getId();
And then trying to makeCopy, or addFile in a folder. Something like that:
<someFolder>.addFile(sheet);
What I detect is that to work I have to get a File type, not a string like after. So I change to the code;
var sheetId = SpreadsheetApp.create("filename").getId();
var file = DriveApp.getFileById(sheet);
<someFolder>.addFile(file);
Instead of making a copy, why don't you just move it?
var file = DriveApp.getFileById(fileID),
folder = DriveApp.getFolderById(folderID),
parents = file.getParents();
folder.addFile(file);
while( parents.hasNext() )
parents.next().removeFile(file);

Categories

Resources