Skip to content

Instantly share code, notes, and snippets.

@abhijeetchopra
Last active April 24, 2024 20:40
Show Gist options
  • Save abhijeetchopra/99a11fb6016a70287112 to your computer and use it in GitHub Desktop.
Save abhijeetchopra/99a11fb6016a70287112 to your computer and use it in GitHub Desktop.
Creating automatic scheduled backup copies of your Google Sheets using Google Apps Script

How to "Schedule Automatic Backups" of your Google Sheets

This tutorial demonstrates how to use Google Apps Script to:

  • Create copies of the Google Sheet in the desired destination folder automatically at set intervals.

  • Append the time stamp with each backup file's name.

  • Adjust time trigger for backing up every day/hour/minute.

  1. Open your Google Drive and create a new folder right where your Google Sheet is. You may name it anything you like. step 1

  2. Open the folder you just created. You will be able to see its ID in the URL displayed in your browser's address bar. We will need this later. step 2

  3. Open your Google Sheet and select menu item "Tools" --> "Script Editor" step 3

  4. Once the script editor opens, copy and paste the code from the 2-MakeCopy.gs file (see file below) into the "Code.gs" file, replacing the code that's already included. step 4

  5. Copy the ID of the folder you created earlier and paste in place of the xxxxxxxxxxxxxxxxxxxxxxx in the code. step 5

  6. Go to menu "File" --> "Save". step 6

  7. Click on the clocked shaped "Trigger" button. step 7

  8. Click on the blue link to add a trigger. step 8

  9. Select the time interval as per your desire. step 9

  10. Click on "Continue" to authorize running the script you just made. step 10

  11. Click on "Allow" to let the script run on your Google Sheet. step 11

  12. After the set interval(which was every minute in my case), you can see the automatic scheduled backup copies of your Google Sheet saved in the folder you created. step 12

// Abhijeet Chopra
// 26 February 2016
// Google Apps Script to make copies of Google Sheet in specified destination folder
function makeCopy() {
// generates the timestamp and stores in variable formattedDate as year-month-date hour-minute-second
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
// gets the name of the original file and appends the word "copy" followed by the timestamp stored in formattedDate
var name = SpreadsheetApp.getActiveSpreadsheet().getName() + " Copy " + formattedDate;
// gets the destination folder by their ID. REPLACE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx with your folder's ID that you can get by opening the folder in Google Drive and checking the URL in the browser's address bar
var destination = DriveApp.getFolderById("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
// gets the current Google Sheet file
var file = DriveApp.getFileById(SpreadsheetApp.getActiveSpreadsheet().getId())
// makes copy of "file" with "name" at the "destination"
file.makeCopy(name, destination);
}
@vehgroshop
Copy link

vehgroshop commented Feb 28, 2024

Hey, here's my version of the script that lets you back up several files in the same parent backup folder, and keep x backups of these files (it creates a folder in the parent folder for each file you want to backup, and store the different versions of the file in this folder). It works with any file (not just sheets). To use it you just have to create a project and create a trigger for the run function.

const filesToBackup = [
   'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',  // file id
   'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
]
const backupFolderId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'  // folder id
const limit = 10  // number of backups to keep

function run() {
   filesToBackup.forEach(fileId => makeCopy(fileId, backupFolderId))
   clearAll(backupFolderId, limit)
}

function makeCopy(fileId, backupFolderId) {
   var file = DriveApp.getFileById(fileId)
   var backupFolder = DriveApp.getFolderById(backupFolderId)

   var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
   var rootName = file.getName()
   var copyName = rootName + "_COPY_" + formattedDate

   destination = getDestinationFolder(rootName, backupFolder)
   file.makeCopy(copyName, destination)
}

function getDestinationFolder(rootName, backupFolder) {
   var children = backupFolder.getFoldersByName(rootName)
   if (!children.hasNext()) {
      var destination = DriveApp.createFolder(rootName)
      destination.moveTo(backupFolder)
   } else {
      var destination = children.next()
   }
   return destination
}

function clearAll(backupFolderId, limit = 10) {
   var backupFolder = DriveApp.getFolderById(backupFolderId);
   var folders = backupFolder.getFolders()

   while (folders.hasNext()) {
      const folder = folders.next()
      clearFolder(folder)
   }
}

function clearFolder(folder) {
   const files = folder.getFiles()
   const filesArray = [];
   while (files.hasNext()) {
      var file = files.next();
      filesArray.push(file);
   }

   filesArray.sort(function (a, b) {
      return b.getDateCreated() - a.getDateCreated(); // Sort in descending order of creation date
   });
   while (filesArray.length > limit) {
      var fileToDelete = filesArray.pop();
      destination.removeFile(fileToDelete);
   }
}

Hi estebanthi,

I created a new script and pasted your code in it, added 2 file-id's and the id of the google drive root folder, but when I run the code I get the following error:

Exception: Unexpected error while getting the method or property getFileById on object DriveApp.
makeCopy @ Backups.gs:15
(anoniem) @ Backups.gs:10
run @ Backups.gs:10

I suspect that I have made a slight error in the file ID, but it might be something else.
Am I correct in assuming, that the file ID of a google sheet is found in the url of the sheet between the following pieces?:
https://docs.google.com/spreadsheets/d/ FILE-ID-HERE /edit#gid=XXXXXXXXX
If I'm right about this assumption, could you tell me what else might be causing the error?

@irvtech
Copy link

irvtech commented Apr 24, 2024

Thanks, @abhijeetchopra This is great! You saved me a ton of time. The solution works like a charm and took moments to implement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment