【问题标题】:Convert excel files to Google Spreadsheet and replace existing spreadsheet files automatically将 excel 文件转换为 Google 电子表格并自动替换现有的电子表格文件
【发布时间】:2019-04-01 10:55:23
【问题描述】:

提供的代码将文件从 Excel 转换为 Google 表格。 The code from here 但它不会覆盖/替换目标文件夹中当前现有的电子表格文件。 是否可以完全转换包括子文件夹内的所有内容并替换任何现有的同名 Google 电子表格文件?

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))
}

【问题讨论】:

  • 一次只能转换一个文件,我不确定批处理是否可以隐藏。无论哪种方式,您都必须循环浏览您的文件夹。
  • 我对其他帖子做了一些研究,也许可以使用 DriveApp.searchFiles 完成
  • 搜索文件不会隐藏文件。它只是返回它们的列表。
  • 不好意思,正在考虑怎么转换这个...
  • 最简单的更改是从其他函数传入所需的“原始”文件夹 ID 和目标文件夹 ID。这是基本的重构。一个更困难但获得巨大回报的更改是在调用之间记住检索到的 Google 表格文件(因为提供源 ID 的函数可能具有多个具有相同所需目的地的 ID,并且重新计算它们是浪费的)。

标签: javascript excel google-apps-script google-drive-api


【解决方案1】:
  1. 包含多个子文件夹的文件夹中有 Excel 文件(文件扩展名为 .xlsx 或 .xls)。
  2. 没有子文件夹的文件夹中有电子表格文件(文件名不带 .xlsx 或 .xls 的扩展名)。
  3. 您想用从 Excel 文件转换的电子表格覆盖现有的电子表格文件。
  4. 电子表格和 Excel 文件的数量相同。

从您的问题和 cmets 中,我可以像上面那样理解。

起初,我测试了通过批处理请求更新文件。结果,当使用文件blob进行更新时,似乎无法通过批处理请求来实现文件的更新。关于这一点,如果我找到了解决这种情况的方法,我想更新我的答案。

所以在这个示例脚本中,我针对上述情况提出了使用高级 Google 服务的 Drive API 的方法。

使用此脚本时,请在高级 Google 服务和 API 控制台启用 Drive API。您可以在 here 上查看相关信息。

流程:

这个脚本的流程如下。

  1. 检索源文件夹和目标文件夹中的文件。
  2. 当源文件夹中的文件名存在于目标文件夹中时,这些文件会覆盖现有的电子表格文件。
  3. 当源文件夹中的文件名在目标文件夹中不存在时,这些文件将作为新文件转换为电子表格。

示例脚本:

在运行脚本之前,请设置sourceFolderIddestinationFolderId

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))});
}

注意:

  • 当需要转换的文件较多,脚本执行时间结束时,请分割文件运行脚本。

参考资料:

【讨论】:

  • 嗨@Tanaike,非常感谢,尽管我不能同时更新文件,只能使用批处理。代码运行完美,再次感谢。
  • 我希望代码在一次执行中转换并覆盖现有文件,但我发现它一次无法处理太多文件,我将不得不将它分成不同的批次。 @田池
  • @Daniel 感谢您的回复。不幸的是,在当前阶段,还不能通过批处理请求使用文件 blob 更新文件。因此,此解决方法是当前的解决方法。对于这种情况,我深表歉意。
  • 我了解@Tanaike,感谢您的大力支持和时间 :)
  • 当然。在这里评论,我会在这里@Tanaike
猜你喜欢
  • 2013-05-04
  • 2020-07-19
  • 1970-01-01
  • 2012-11-02
  • 1970-01-01
  • 2021-09-18
  • 1970-01-01
  • 2014-06-18
  • 2021-05-27
相关资源
最近更新 更多