最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to copy a folder from Google Drive to create a new folder in Google drive using JS - Stack Overflow

programmeradmin5浏览0评论

I want to copy folders into a Master Folder within Google Drive. My main issue is creating a function when one column is not blank and another column is blank. Once, a new folder is created it has to paste in the folder URL in one of the columns.

This is what I have so far:

function addData(){
  var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
  var lr = activeSheet.getLastRow();
  var lc = activeSheet.getLastColumn();
  var sourceData = sourceSheet.getRange(1, 1, lr, lc).getValues();
  for (row in sourceData) {
    if (sourceData[row][0] !== "" && sourceData[row][19] !== "") {
      var rowNum = parseInt(row);

     //code will go here for Folder copying and renaming and getting the new folder url

     activeSheet.getRange(rowNum+1,lc).setValue("Completed"); //we will eventually change Completed with the new Folder URL
  }
 }
}

I want to copy folders into a Master Folder within Google Drive. My main issue is creating a function when one column is not blank and another column is blank. Once, a new folder is created it has to paste in the folder URL in one of the columns.

This is what I have so far:

function addData(){
  var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
  var lr = activeSheet.getLastRow();
  var lc = activeSheet.getLastColumn();
  var sourceData = sourceSheet.getRange(1, 1, lr, lc).getValues();
  for (row in sourceData) {
    if (sourceData[row][0] !== "" && sourceData[row][19] !== "") {
      var rowNum = parseInt(row);

     //code will go here for Folder copying and renaming and getting the new folder url

     activeSheet.getRange(rowNum+1,lc).setValue("Completed"); //we will eventually change Completed with the new Folder URL
  }
 }
}
Share Improve this question edited Mar 4, 2021 at 0:39 Coach212 asked Mar 3, 2021 at 21:05 Coach212Coach212 211 silver badge5 bronze badges 9
  • Unfortunately, I cannot understand about I'm stuck with my coding on automating folder creation in Google Drive. I want to copy one folder to the next all within Google Drive. My main issue is creating a function when column A is not blank and column S is blank. Once, the new folder is created it pastes in the folder URL in column S.. I apologize for this. Can I ask you about the detail of your current issue and your goal? – Tanaike Commented Mar 4, 2021 at 0:25
  • @Tanaike, my current issue is copying folders in Google Drive and adding them to a master folder that I've set up. – Coach212 Commented Mar 4, 2021 at 0:35
  • Thank you for replying. I would like to confirm my understading of your actual question. In your current issue, you want to copy the specific folder which has subfolders and files to the other specific folder using Google Apps Script. In this case, you don't want to move them. You want to copy them. And, you have the permissions for retrieving the source folder. Is my understanding correct? – Tanaike Commented Mar 4, 2021 at 0:38
  • @Tanaike, yes that is correct. – Coach212 Commented Mar 4, 2021 at 1:04
  • Thank you for replying. I could understand that my understanding of I want to copy folders into a Master Folder within Google Drive. is correct. I have one more question. I cannot understand the relationship between I want to copy folders into a Master Folder within Google Drive. and My main issue is creating a function when one column is not blank and another column is blank. Once, a new folder is created it has to paste in the folder URL in one of the columns.. I apologize for this. Can I ask you about the detail of your goal? – Tanaike Commented Mar 4, 2021 at 1:07
 |  Show 4 more ments

2 Answers 2

Reset to default 9

The main idea would be to iterate files using Folder.getFiles() and folders with Folder.getFolders(). Make new folders with Folder.createFolder(name) and copy files using File.makeCopy(name, destination):

/**
 * Copies all the files in a folder to another one.
 */
function copyFolderContents_(source, target) {
  // Iterate files in source folder
  const filesIterator = source.getFiles()
  while (filesIterator.hasNext()) {
    const file = filesIterator.next()

    // Make a copy of the file keeping the same name
    file.makeCopy(file.getName(), target)
  }
}

/**
 * Recursivelly copies a folder and all its subfolders with all the files
 */
function copyFolder_(toCopy, copyInto) {
  // Makes the new folder (with the same name) into the `copyInto`
  const newFolder = copyInto.createFolder(toCopy.getName())

  // Copy the contents
  copyFolderContents_(toCopy, newFolder)

  // Iterate any subfolder
  const foldersIterator = toCopy.getFolders()
  while (foldersIterator.hasNext()) {
    const folder = foldersIterator.next()

    // Copy the folder and it's contents (recursive call)
    copyFolder_(folder, newFolder)
  }
}

/**
 * Entry point to execute with the Google Apps Script UI
 */
function copyFolder() {
  // Get the folders (by ID in this case)
  const toCopy = DriveApp.getFolderById('')
  const copyInto = DriveApp.getFolderById('')

  // Call the function that copies the folder
  copyFolder_(toCopy, copyInto)
}

You need to add the ids of the folder to be copied and the folder to copy it from on copyFolder().

foldersIterator and filesIterator are Google Apps Script Iterators. They have a method hasNext() that returns if there is another item, and a next() that retrieves it.

Note that copyFolder_(toCopy, copyInto) uses itself to copy its subfolders.

References

  • Folder.getFiles() (Google Apps Script reference)
  • Folder.getFolders() (Google Apps Script reference)
  • Folder.createFolder(name) (Google Apps Script reference)
  • File.makeCopy(name, destination) (Google Apps Script reference)
  • Iterators (Google Ads Script concepts) (same implementation as Google Apps Script)

This solution is a variation that checks to see if the file or folder has already been copied.

Useful if you have to restart the execution.

It uses includes to check if a file/folder has been copied:

  • https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes

It goes only one level deep, so won't copy subfolders of subfolders.

I've added a sort using Intl.Collator because it helps me read the console output. Neither sort nor console are needed but may be useful. references:

  • https://stackoverflow./a/54427214/16465606
  • https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator
  • https://tc39.es/ecma402/#sec-collator-parestrings

/** Use with copyFolderContents */
function copyFolder() {
  const topFolderFrom = DriveApp.getFolderById(''); // enter folder ID
  const topFolderTo   = DriveApp.getFolderById(''); // enter folder ID

  // Get the subfolder names and IDs
  const ffTopFolder = topFolderFrom.getFolders();
  const subfolders  = [];
  while (ffTopFolder.hasNext()) {
    let folder      = ffTopFolder.next();
    let ffnameid    = [];
    ffnameid.push(folder.getName(), folder.getId());
    subfolders.push(ffnameid);
  }
  subfolders.sort((a, b) => collator.pare(a[0], b[0]));

  // Get target subfolder names
  const folderstarget = topFolderTo.getFolders();
  const listtarget    = [];
  while (folderstarget.hasNext()) {
    let foldertarget  = folderstarget.next();
    let ffname        = [];
    ffname.push(foldertarget.getName());
    listtarget.push(ffname);
  }
  listtarget.sort(collator.pare);

  // Check if subfolder has already been created
  const alreadycreated = listtarget.flat();
  const stilltocreate  = subfolders.filter(e => !alreadycreated.includes(e[0]));
  console.log('subfolders already created:\n', alreadycreated);
  console.log('subfolders still to create:\n', stilltocreate.map(e => e[0]));

  // Create subfolders
  for (let i = 0, len = stilltocreate.length; i < len; i++) {
    topFolderTo.createFolder(stilltocreate[i][0]);
  }

  // Get the name and ID of subfolders in target folder (needed in case subfolders have been created)
  const ffTopFolderTo = topFolderTo.getFolders();
  const subfoldersTo  = [];
  // Get the subfolders
  while (ffTopFolderTo.hasNext()) {
    let folder        = ffTopFolderTo.next();
    let ffnameid      = [];
    ffnameid.push(folder.getName(), folder.getId());
    subfoldersTo.push(ffnameid);
  }
  subfoldersTo.sort((a, b) => collator.pare(a[0], b[0]));

  // Add the top level folders to arrays to copy files in top level
  subfolders.push([topFolderFrom.getName(), topFolderFrom.getId()]);
  subfoldersTo.push([topFolderTo.getName(), topFolderTo.getId()]);
  console.log('subfolders and top folder:\n', subfolders);
  console.log('subfolders and top folder (target):\n', subfoldersTo);

  for (let i = 0, len = subfolders.length; i < len; i++) {
    let copyFrom = DriveApp.getFolderById(subfolders[i][1]);
    let indx      = subfoldersTo.map(e => e[0]).indexOf(subfolders[i][0]);
    let copyTo    = DriveApp.getFolderById(subfoldersTo[indx][1]);
    // Call the function that copies the folder
    copyFolderContents_(copyFrom, copyTo);
  }
}

/** Copies all the files in a folder to another one, checking for duplicates */
function copyFolderContents_(source, target) {
  Logger.log('copy from: ' + source);
  Logger.log('copy to: ' + target);

  // Get source filenames and IDs
  const files      = source.getFiles();
  const listsource = [];
  while (files.hasNext()) {
    let file       = files.next();
    let ssnameid   = [];
    ssnameid.push(file.getName(), file.getId());
    listsource.push(ssnameid);
  }
  listsource.sort((a, b) => collator.pare(a[0], b[0]));

  // Get target filenames
  const filestarget = target.getFiles();
  const listtarget  = [];
  while (filestarget.hasNext()) {
    let filetarget  = filestarget.next();
    let ssname      = [];
    ssname.push(filetarget.getName());
    listtarget.push(ssname);
  }
  listtarget.sort(collator.pare);

  // Check if file has already been copied
  const alreadycopied = listtarget.flat();
  const stilltocopy   = listsource.filter(e => !alreadycopied.includes(e[0]));
  console.log('files already copied:\n', alreadycopied);
  console.log('files still to copy:\n', stilltocopy.map(e => e[0]));

  // Copy files still to copy
  for (let i = 0, len = stilltocopy.length; i < len; i++) {
    let fileid = stilltocopy[i][1];
    let ss     = DriveApp.getFileById(fileid);
    Logger.log(i + ' - ' + ss);
    ss.makeCopy(stilltocopy[i][0], target);
  }
}

/** Used for sorting alpha/numeric arrays */
const collator = new Intl.Collator('en', {
  numeric: true,
  sensitivity: 'base'
})

发布评论

评论列表(0)

  1. 暂无评论