0

The Requirements: I am trying to write a script to enable users to archive a spreadsheet - and its linked form - at the end of each year by:

  1. creating a folder for the year inside a pre-defined archives folder
  2. Making a copy of the spreadsheet to be archived inside the newly created folder.

The Problem: When the sheet is copied and moved to the archive folder, the linked form is also copied but does not automatically move with its associated sheet. It remains in its original folder. I needed to find how to get the copy of the form to also be moved with the spreadsheet?

The solution: I initially wrote a function to create a new folder for each year in a pre-defined archives folder and create a copy of the sheet to archive within that folder. With the much appreciated suggestions from @doubleunary and the feedback from @Rubén, I made few changes to improve my question, and the script. Any idea on how to improve it further would be greatly appreciated.


function archiveSpreadSheet() {

  // Main Spreadsheet to be archived 
  var mainSheet = SpreadsheetApp.openById("Spreadsheet ID");
  // Form responses/data sheet 
  var formData = mainSheet.getSheetByName("Sheet name");

  // 1 - Find the date of the last entry in the form responses sheet
  var timestamp = formData.getRange(formData.getLastRow() - 1, 1).getValue();
  // 2 - Get the year in a string format
  var archiveYear = new Date(timestamp).getFullYear().toString();
  // 3 - Create a new folder using the year as name and store its id
  // Note: createNewFolder is a function that takes the id of the
  // parent folder and the chosen name for the folder to create and only creates it if it doesn't already exist.
  var archiveFolderId = createNewFolder("1XTW9WA35PWDUPy8TVpH3xJ4hWbqqk9nj", archiveYear);
  // 4 - Get the name of the newly created folder
  let archiveFolder = DriveApp.getFolderById(archiveFolderId);
  // 5 - create a named copy of the spreadsheet to archive inside the archive folder
  var archiveSheet = DriveApp.getFileById(mainSheet.getId())
                             .makeCopy("Archive Sheet - " + archiveYear, archiveFolder); 
  // 6 - Get the url of the linked form of the copied spreadsheet
  let relatedFormUrl = SpreadsheetApp.openByUrl(archiveSheet.getUrl()).getFormUrl();
  // 7 - Store the form id in a string format 
  let relatedFormId = FormApp.openByUrl(relatedFormUrl).getId().toString();
  // 8 - Rename the form to match its related sheet
  let archiveForm = DriveApp.getFileById(relatedFormId).setName("Archive Form - " + archiveYear);
  // 9 - Using the id, check if the form exists in the in the drive
  if(relatedFormId) {
    // 9.1 - Move the linked form to the same archive folder as its associated sheet
    archiveForm.moveTo(archiveFolder);
  }


}
  • Welcome to [Stack Overflow](https://stackoverflow.com/tour). Use [Spreadsheet.getFormUrl()](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet#getformurl) or [Sheet.getFormUrl(https://developers.google.com/apps-script/reference/spreadsheet/sheet#getFormUrl())] to discover the URL of the newly created form, then use Drive methods to get the file and move it. See if [getFilesByType(mimeType)](https://developers.google.com/apps-script/reference/drive/drive-app#getfilesbytypemimetype) helps. – doubleunary Dec 14 '22 at 06:28
  • Not a duplicate of [Moving Files In Google Drive Using Google Script](https://stackoverflow.com/questions/38808875/moving-files-in-google-drive-using-google-script) because copying vs. moving and the need to manage the form that gets created along the spreadsheet when a new copy of the spreadsheet is made. – doubleunary Dec 14 '22 at 06:30
  • @doubleunary Thank you for your suggestions! with your help, I finished the function and it seems to do the job. It can probably be improved but it works for now. – mustpha2ieme Dec 14 '22 at 22:16
  • Glad you got it to work. – doubleunary Dec 14 '22 at 22:33

1 Answers1

0

Here's a bit simplified version of the solution. It could be simplified further by making the createNewFolder() return a Folder object instead of a folder ID.

function archiveSpreadSheetAndLinkedForm() {
  const ss = SpreadsheetApp.openById('...put spreadsheet ID here...');
  const formSheet = ss.getSheetByName('Form Responses 1');
  const timestamp = formSheet.getRange(formSheet.getLastRow() - 1, 1).getValue();
  const archiveYear = String(timestamp.getFullYear());
  const archiveFolder = DriveApp
    .getFolderById(createNewFolder('1XTW9WA35PWDUPy8TVpH3xJ4hWbqqk9nj', archiveYear));
  const linkedFormUrl = DriveApp
    .getFileById(ss.getId())
    .makeCopy(`Archive Sheet - ${archiveYear}`, archiveFolder)
    .getFormUrl();
  const linkedFormId = FormApp.openByUrl(linkedFormUrl).getId();
  if (linkedFormId) {
    DriveApp
      .getFileById(linkedFormId)
      .setName(`Archive Form - ${archiveYear}`)
      .moveTo(archiveFolder);
  }
}
doubleunary
  • 13,842
  • 3
  • 18
  • 51
  • Thank you @doubleunary for this lovely contribution. With your permission, I would love to bounce on your idea and add some comments, and replace the id used in the createNewFolder function with a more descriptive text for more clarity. This would help me cement my knowledge and help other beginners like me find their way around the code. – mustpha2ieme Dec 20 '22 at 11:58
  • Sure. See [What is the license for the content I post?](https://stackoverflow.com/help/licensing). – doubleunary Dec 20 '22 at 12:57
  • First question indeed. – mustpha2ieme Dec 22 '22 at 06:37