0

The code provided convert files from Excel to Google Sheet. The code from here but it does not overwrite/replace current existing spreadsheet files in the destination folder. Is it possible to convert everything including the ones inside the subfolders altogether and replace any existing Google Spreadsheet files with the same name?

function convertCollection1() 
{
  var user = Session.getActiveUser(); // Used for ownership testing.1aJcbdGhwliTs_CZ-3ZUvQmGRDzBM7fv9
  var origin = DriveApp.getFolderById("1dPsDfoqMQLCokZK4RN0C0VRzaRATr9AN");
  var dest = DriveApp.getFolderById("1M6lDfc_xEkR4w61pUOG4P5AXmSGF1hGy");

  // Index the filenames of owned Google Sheets files as object keys (which are hashed).
  // This avoids needing to search and do multiple string comparisons.
  // It takes around 100-200 ms per iteration to advance the iterator, check if the file
  // should be cached, and insert the key-value pair. Depending on the magnitude of
  // the task, this may need to be done separately, and loaded from a storage device instead.
  // Note that there are quota limits on queries per second - 1000 per 100 sec:
  // If the sequence is too large and the loop too fast, Utilities.sleep() usage will be needed.
  var gsi = dest.getFilesByType(MimeType.GOOGLE_SHEETS), gsNames = {};
  while (gsi.hasNext())
  {
    var file = gsi.next();
    if(file.getOwner().getEmail() == user.getEmail())
      gsNames[file.getName()] = true;

    Logger.log(JSON.stringify(gsNames))
  }

  // Find and convert any unconverted .xls, .xlsx files in the given directories.
  var exceltypes = [MimeType.MICROSOFT_EXCEL, MimeType.MICROSOFT_EXCEL_LEGACY];
  for(var mt = 0; mt < exceltypes.length; ++mt)
  {
    var efi = origin.getFilesByType(exceltypes[mt]);
    while (efi.hasNext())
    {
      var file = efi.next();
      // Perform conversions only for owned files that don't have owned gs equivalents.
      // If an excel file does not have gs file with the same name, gsNames[ ... ] will be undefined, and !undefined -> true
      // If an excel file does have a gs file with the same name, gsNames[ ... ] will be true, and !true -> false
      if(file.getOwner().getEmail() == user.getEmail() && !gsNames[file.getName().replace(/\.[^/.]+$/, "")])
      {
        Drive.Files.insert (
          {title: file.getName(), parents: [{"id": dest.getId()}]},
          file.getBlob(),
          {convert: true}
        );
        // Do not convert any more spreadsheets with this same name.
        gsNames[file.getName()] = true;
      }
    }
  }
  Logger.log(JSON.stringify(gsNames))
}
Daniel
  • 3
  • 1
  • 5
  • You can only convert one file at a time, I am not sure that batching works with covert. Either way you will have to loop though your folders. – Linda Lawton - DaImTo Apr 01 '19 at 11:14
  • I did some research on other posts, maybe it can be done using DriveApp.searchFiles – Daniel Apr 01 '19 at 11:20
  • 1
    Search files doesn't covert files. It just returns a list of them. – Linda Lawton - DaImTo Apr 01 '19 at 11:34
  • I'm sorry, just thinking of how to convert this... – Daniel Apr 01 '19 at 11:37
  • The simplest change is to pass in the desired "origin" folder ID and destination folder ID from some other function. This is elementary refactoring. A more difficult yet massively rewarding change would be to then memoize the retrieved Google Sheets files between calls (since the function providing the origin ID probably has several IDs with the same desired destination, and recomputing them is wasteful). – tehhowch Apr 01 '19 at 19:20
  • @Daniel Can you update your question? Because from your script, it seems that you want to converts excel files to Spreadsheet as new Spreadsheet. In order to avoid to misunderstand by other users, if you cooperate, I'm glad. – Tanaike Apr 11 '19 at 00:52
  • Sure thing @Tanaike, thanks for the comment. – Daniel Apr 11 '19 at 00:53
  • @Daniel Thank you for updating your question. 1. There are Excel files in a folder with several subfolders. 2. There are Spreadsheet files in a folder without subfolders. 3. You want to overwrite the existing Spreadsheet files with the converted Spreadsheet from Excel files. 4. Filenames and number of Spreadsheet files are the same with those of Excel files. If my understanding is correct, can I ask you about ``the same name``? Does the filename of Spreadsheet had the extension of "xlsx"? Or doesn't the filename of Excel file have the extension? Are there same filenames in Spreadsheet files? – Tanaike Apr 11 '19 at 01:35
  • Hi @Tanaike, sorry for the late reply. Lets say file "A" has been converted to Google Spreadsheet into the destination folder, when the script is re-executed, file"A" would be converted yet again but replace the existing Google Spreadsheet "A" file. The excel files are either in .xls or .xlsx only. – Daniel Apr 12 '19 at 00:10
  • @Daniel Thank you for replying. Unfortunately, I cannot still understand about the relationship between the filename of Spreadsheet and Excel. For example, when the filenames of Spreadsheet and Excel are "sample" and "sample.xlsx", these filenames are different. Can you explain the detail situation? I apologize for my poor English skill. – Tanaike Apr 12 '19 at 00:31
  • Hi @Tanaike, I've found a question similar to mine. [link](https://stackoverflow.com/questions/49841697/convert-any-xls-xlsm-files-to-google-sheet-format-and-overwrite-the-oldest-exist?noredirect=1&lq=1) – Daniel Apr 12 '19 at 00:35
  • @Daniel Thank you for replying. From the link, unfortunately, I cannot still understand about the same filename. I apologize for my poor English skill. – Tanaike Apr 12 '19 at 00:37
  • Its fine @Tanaike, I want to convert any xls. or xlsx. files in a folder to Google Sheet format and replace the existing Google Sheet file with the same name. – Daniel Apr 12 '19 at 00:40
  • @Daniel Can I ask you about the same filename that you think? For example, when the filenames of Spreadsheet and Excel are "sample" and "sample.xlsx", these filenames are different. – Tanaike Apr 12 '19 at 00:40
  • @Daniel For example, when the filenames of Spreadsheet and Excel are "sample" and "sample.xlsx", you want to use "sample" as the same filename by removing the extension. Is my understanding correct? – Tanaike Apr 12 '19 at 00:44
  • Hi @Tanaike, yes, is it possible? – Daniel Apr 12 '19 at 00:50
  • @Daniel I would like to confirm to completely understand your question. Please be careful this time. 1. There are Excel files (filename **with** the extensions of .xlsx or .xls) in a folder with several subfolders. 2. There are Spreadsheet files (filename **without** the extensions of .xlsx or .xls) in a folder without subfolders. 3. You want to overwrite the existing Spreadsheet files with the converted Spreadsheet from Excel files. 4. **Number of Spreadsheet and Excel files are the same.** Is my understanding correct? – Tanaike Apr 12 '19 at 01:01
  • @Tanaike 1. Correct 2.Correct 3.Correct 4.Correct. spot on. – Daniel Apr 12 '19 at 01:05
  • @Daniel I think that I could understand your question. If you give me a time to think of your solution, I'm glad. – Tanaike Apr 12 '19 at 01:07
  • @Tanaike, thank you for helping me out a lot, I appreciate it very much. – Daniel Apr 12 '19 at 01:08
  • @Daniel I apologize for my late response. I proposed a sample script. Could you please confirm it? I tested above situation. As the result, it was found that the update of file cannot be achieved by the batch request. So I used Drive API of Advanced Google Services. If this was not what you want, I apologize. – Tanaike Apr 12 '19 at 05:33

1 Answers1

1
  1. There are Excel files (filename with the extensions of .xlsx or .xls) in a folder with several subfolders.
  2. There are Spreadsheet files (filename without the extensions of .xlsx or .xls) in a folder without subfolders.
  3. You want to overwrite the existing Spreadsheet files with the converted Spreadsheet from Excel files.
  4. Number of Spreadsheet and Excel files are the same.

From your question and comments, I could understand like above.

At first, I tested to update files by the batch request. As the result, it seems that the update of file cannot be achieved by the batch request, when the file blob is used for updating. About this, if I found the workaround for this situation, I would like to update my answer.

So in this sample script, I propose the method for using Drive API of Advanced Google Services for above situation.

When you use this script, please enable Drive API at Advanced Google Services and API console. You can see about this at here.

Flow:

The flow of this script is as follows.

  1. Retrieve files in the source and destination folder.
  2. When the filenames in the source folder are existing in the destination folder, those files overwrite the existing Spreadsheet files.
  3. When the filenames in the source folder are not existing in the destination folder, those files are converted to Spreadsheet as new files.

Sample script:

Before run the script, please set sourceFolderId and destinationFolderId.

function myFunction() {
  var sourceFolderId = "###"; // Folder ID including source files.
  var destinationFolderId = "###"; // Folder ID that the converted files are put.

  var getFileIds = function (folder, fileList, q) {
    var files = folder.searchFiles(q);
    while (files.hasNext()) {
      var f = files.next();
      fileList.push({id: f.getId(), fileName: f.getName().split(".")[0].trim()});
    }
    var folders = folder.getFolders();
    while (folders.hasNext()) getFileIds(folders.next(), fileList, q);
    return fileList;
  };
  var sourceFiles = getFileIds(DriveApp.getFolderById(sourceFolderId), [], "mimeType='" + MimeType.MICROSOFT_EXCEL + "' or mimeType='" + MimeType.MICROSOFT_EXCEL_LEGACY + "'");
  var destinationFiles = getFileIds(DriveApp.getFolderById(destinationFolderId), [], "mimeType='" + MimeType.GOOGLE_SHEETS + "'");
  var createFiles = sourceFiles.filter(function(e) {return destinationFiles.every(function(f) {return f.fileName !== e.fileName});});
  var updateFiles = sourceFiles.reduce(function(ar, e) {
    var dst = destinationFiles.filter(function(f) {return f.fileName === e.fileName});
    if (dst.length > 0) {
      e.to = dst[0].id;
      ar.push(e);
    }
    return ar;
  }, []);
  if (createFiles.length > 0) createFiles.forEach(function(e) {Drive.Files.insert({mimeType: MimeType.GOOGLE_SHEETS, parents: [{id: destinationFolderId}], title: e.fileName}, DriveApp.getFileById(e.id))});
  if (updateFiles.length > 0) updateFiles.forEach(function(e) {Drive.Files.update({}, e.to, DriveApp.getFileById(e.id))});
}

Note:

  • When you have many files for converting and the execution time of the script is over, please divide the files and run the script.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • Hi @Tanaike, Thank you very much, even though i can't update the files simultaneously, only using batches. The code runs perfectly, thank you once again. – Daniel Apr 12 '19 at 05:43
  • I wanted the code to be convert and overwrite existing files in a single execution, but i see it can't handle too many files at one time, i will have to separate it in different batches. @Tanaike – Daniel Apr 12 '19 at 05:47
  • @Daniel Thank you for replying. Unfortunately, in the current stage, the file cannot be updated using the file blob by the batch request, yet. So this workaround is the current workaround. I apologize for this situation. – Tanaike Apr 12 '19 at 05:50
  • I understand @Tanaike, thanks for your great support and time :) – Daniel Apr 12 '19 at 05:52
  • @Daniel If this situation is changed by Google's update or I found the other workaround, I would like to report it here. Also I could study from your question. Thank you, too. – Tanaike Apr 12 '19 at 05:53
  • 1
    for sure. Just comment here, i'll be here @Tanaike – Daniel Apr 12 '19 at 05:54
  • @Daniel Can I ask you about the number of files of Excel file and the total file size of the Excel files? – Tanaike Apr 12 '19 at 07:38
  • Hi @Tanaike I have 60 excel files and each of them is 15mb. So total is 900mb – Daniel Apr 12 '19 at 23:36
  • @Daniel Thank you for replying. In order to test the script using other workaround, can you provide a sample excel file? Of course, please remove your personal information. Because I have no such large file. – Tanaike Apr 12 '19 at 23:38
  • @Daniel I couldn't find the method for using file blob at the batch request. And I found this at [the official document](https://developers.google.com/drive/api/v3/batch). ``Note: Currently, Google Drive does not support batch operations for media, either for upload or download.`` This is the specification. By this, unfortunately, it seems that in the current stage, the proposed method is a workaround. So when you have many files for converting and the execution time of the script is over, please divide the files and run the script. This is my answer. I apologize for this situation. – Tanaike Apr 14 '19 at 23:12
  • Hi Tanaike, its okay. You did a great job helping me already. – Daniel Apr 16 '19 at 06:07