2

Does anyone know why this happens? It would be much more convenient to have all the files copied to the destination. I have a list of filenames and file ids 3 are spreadsheets and one is a standalone script which I deploy as a webapp. The three spreadsheet go to the correct place. The standalone webapp goes to the root. I don't think it's a duplicate as suggested.

  function backUpProjectFiles(){
  var backupFolder=DriveApp.getFolderById(getGlobal('BackupDirId'));
  var subFldrName='BackUpFiles_' + Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd_HH:mm:ss');
  var subFldr=backupFolder.createFolder(subFldrName);
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('BackUpFiles');
  var rg=sh.getDataRange();
  var vA=rg.getValues();//column1 is filenames column2 is file ids
  var s='<br />Files Backed Up:<br />';
  for(var i=1;i<vA.length;i++){
    var file=DriveApp.getFileById(vA[i][1]);
    file.makeCopy(vA[i][0],subFldr);
    s+=Utilities.formatString('%s FilePath:%s/%s/<strong>%s</strong><br />',i,backupFolder.getName(),subFldr.getName(),file.getName());
  }
  s+=Utilities.formatString('Total Files Copied: %s<br /><input type="button" value="Exit" onClick="google.script.host.close();" />',vA.length-1)
  var ui=HtmlService.createHtmlOutput(s).setWidth(600).setHeight(500);
  SpreadsheetApp.getUi().showModelessDialog(ui,'File Backup Complete');
}  
Cooper
  • 59,616
  • 6
  • 23
  • 54
  • Possible duplicate of [How do I make copy of spreadsheet and save it to particular folder?](https://stackoverflow.com/questions/31078758/how-do-i-make-copy-of-spreadsheet-and-save-it-to-particular-folder) – Rubén Aug 22 '18 at 04:29
  • Related [How to copy a file into a specific folder using DocsList?](https://stackoverflow.com/q/13328247/1595451) – Rubén Aug 22 '18 at 04:31
  • I think that it's a bug. And it is still not removed. So is this information useful for your situation? https://stackoverflow.com/questions/47512322/when-copying-files-using-apps-script-from-one-folder-to-another-any-apps-script Of course, you can also do it using the method of "update" for Drive API v3. I think that the batch request might be suitable for this situation. – Tanaike Aug 22 '18 at 05:45
  • @Tanaike Thank you very much for that info. I'll have to study that a while as I've not used the Drive API very much. – Cooper Aug 22 '18 at 05:53
  • 1
    @Rubén I think that OP's issue is that when Google Docs and the standalone projects are copied to a specific folder using ``makeCopy()``, although Google Docs can be copied to the folder, the standalone projects are copied to the root folder, while they cannot be copied to the folder. I think that this is a bug. – Tanaike Aug 22 '18 at 05:53
  • @Cooper Welcome. Because of this situation, in my application, when I copy the standalone scripts, I always use the "update" method of Drive API. I hope for removing this bug. – Tanaike Aug 22 '18 at 05:55
  • @Tanaike I just used the API explorer and I think I can figure this out. Thanks for comment. – Cooper Aug 22 '18 at 06:18
  • I posted it as an answer. I used your script, because using your script might help you understand about the "update" method. Could you please confirm it? If you have any questions, feel free to tell me. – Tanaike Aug 22 '18 at 06:20
  • I'm sorry for late reply. – Tanaike Aug 22 '18 at 06:21
  • @Tanaike Wow. Thanks so much for that. Yes I see how the update works. I already got it to work in the API Explorer and was beginning to see how it might work. Thank you so much for that. I feel like I owe a lot more than a few points. – Cooper Aug 22 '18 at 06:36
  • I'm glad for it. Thank you, too. – Tanaike Aug 22 '18 at 06:40
  • So you use the update to move the file from wherever it lands to the subFolder?Thanks again. It's working now. – Cooper Aug 22 '18 at 06:46
  • Yes. For example, for ``Drive.Files.update({"parents": [{"id": "### folderId ###"}]}, "### fileId ###")``, when ``{"parents": [{"id": "### folderId ###"}]}`` is used as the resource, the file of ``### fileId ###`` can be directly moved to the folder of ``### folderId ###``. Because the files in Google Drive are managed by each fileId. – Tanaike Aug 22 '18 at 07:08
  • But this can be done at Drive API v2. If you use Drive API v3, the file cannot be moved using ``{"parents": ["### folderId ###"]}``. In this case, ``addParents`` and ``removeParents`` are required to be used. I think that this is the difference between v2 and v3. – Tanaike Aug 22 '18 at 07:14

1 Answers1

2

I modified your script by using the "update" method of Drive API. When a file is copied, the flow of this script is as follows.

  1. Copy a file using makeCopy().
  2. If the mimeType of file is Google Apps Script, the file is moved to subFldr using the "update" method of Drive API.
  3. If the mimeType of file is not Google Apps Script, he "update" method is not used.

Modified script :

function backUpProjectFiles(){
  var backupFolder=DriveApp.getFolderById(getGlobal('BackupDirId'));
  var subFldrName='BackUpFiles_' + Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy-MM-dd_HH:mm:ss');
  var subFldr=backupFolder.createFolder(subFldrName);
  var ss=SpreadsheetApp.getActive();
  var sh=ss.getSheetByName('BackUpFiles');
  var rg=sh.getDataRange();
  var vA=rg.getValues();//column1 is filenames column2 is file ids
  var s='<br />Files Backed Up:<br />';
  for(var i=1;i<vA.length;i++){
    var file=DriveApp.getFileById(vA[i][1]);

    var res = file.makeCopy(vA[i][0],subFldr); // Modified
    if (file.getMimeType() == MimeType.GOOGLE_APPS_SCRIPT) { // Added
      Drive.Files.update({"parents": [{"id": subFldr.getId()}]}, res.getId()); // Added
    }

    s+=Utilities.formatString('%s FilePath:%s/%s/<strong>%s</strong><br />',i,backupFolder.getName(),subFldr.getName(),file.getName());
  }
  s+=Utilities.formatString('Total Files Copied: %s<br /><input type="button" value="Exit" onClick="google.script.host.close();" />',vA.length-1)
  var ui=HtmlService.createHtmlOutput(s).setWidth(600).setHeight(500);
  SpreadsheetApp.getUi().showModelessDialog(ui,'File Backup Complete');
}

Note :

  • In this modified script, Drive API of Advanced Google Services is used. So please enable Drive API at Advanced Google Services and API console. In the case of Advanced Google Services, the version of Drive API is v2.
    • You can see how to enable Drive API at here.

Reference :

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • @Cooper Welcome. Thank you, too. – Tanaike Aug 22 '18 at 22:15
  • I've used this `Drive.Files.update({"parents": [{"id": subFldr.getId()}]}, res.getId()); ` in a couple of places and it works good. But recently I've been trying to get it to allow me to save a Google Doc file in a team drive folder. Any suggestions? – Cooper Oct 03 '18 at 01:09
  • 1
    @Cooper Although I cannot confirm whether this sample works because I have no team drive, how about this script? ``Drive.Files.update({"parents": [{"id": subFldr.getId()}]}, res.getId(), null, {supportsTeamDrives: true, includeTeamDriveItems: true})`` The document is [here](https://developers.google.com/drive/api/v2/enable-teamdrives). I'm sorry I couldn't try to run it in my environment. So if this didn't work, I'm really sorry. – Tanaike Oct 03 '18 at 01:20
  • That was it. Thanks. I tried something similar but forgot to add the null in the third term. – Cooper Oct 03 '18 at 01:51
  • @Cooper I'm glad your issue was solved. Thank you for replying. – Tanaike Oct 03 '18 at 03:58