将电子表格导出为竖线分隔文件而不是 csv

Export spreadsheet as pipe-delimited file instead of csv

我正在尝试自动下载 Google 表格 -> 竖线分隔的文本文件。基本上,我想在 Google spreadsheet 上创建一个时间驱动的脚本 运行 以将其保存为带有 | 分隔符的 .txt。

传播sheet 本身是一个单一的作品sheet,它使用 IMPORTRANGE 从我的主文件中提取数据以供最终用户访问。

现在我手动下载它为.csv,在记事本中打开它,“将所有”逗号替换为|'s,并另存为.txt,然后将该文件上传到它所在的位置需要去(上传是无关紧要的,必须是手动的)。我想为自己自动化,但也希望其他用户在我不在时通过脚本获取最终的 .txt 文件。最重要的是,我希望它能够在没有用户输入或活动工作站的情况下 运行(它应该是在星期天早上 运行)所以它必须是时间触发的 Google Apps 脚本。

我JavaScript经验很少,所以我唯一能想到的解决办法就是两个嵌套的for循环(sheetIDsheetName版主):

  var ss= SpreadsheetApp.openById(sheetID)
  var pipeDelimitedString = ""
  var sheet = ss.getSheetByName(sheetName)
  var lastRow = sheet.getLastRow()
  var lastColumn = sheet.getLastColumn()
  var fileName = "PIPE DELIMITED TEST FILE"
  for (var i=1;i<=lastRow;i++){
        for(var j=1;j<=lastColumn;j++){
            if (j==lastColumn){
                 pipeDelimitedString = pipeDelimitedString + "|" + sheet.getRange(i,j).getValue()+"/n"
            } else {
                 pipeDelimitedString = pipeDelimitedString + "|" + sheet.getRange(i,j).getValue()
            }
        }
}
newFile = DriveApp.createFile(fileName,pipeDelimitedString);

然后是一个小脚本,用于将 newFile 通过电子邮件发送给其他用户(尚未编写该部分,但我在 google 上看到了很多解决方案,所以不要担心电子邮件部分)

这必须 运行 在 66 列和最多 200 行(>10k 总单元格)的 sheet 上。我在只有约 50 行的数据集上测试了它,我不得不停止它。即使它确实有效,它也会占用我太多的触发脚本的 Google Apps 脚本配额。

我确定我在这方面走错了方向。请帮忙?即使只是从哪里开始,我们也将不胜感激。

我无法共享实际文件,只能共享一个虚拟副本,但我很确定解决方案不应该是特定于内容的?除了原始文件数据中没有逗号或管道的事实之外,如果有帮助的话,只有文本和数字的混合?

如果您不喜欢嵌套循环,您可以使用更高级的工具:

var sheetID = "";
var sheetName = "";

function myFunction() {

  var ss         = SpreadsheetApp.openById(sheetID);
  var sheet      = ss.getSheetByName(sheetName);
  var lastRow    = sheet.getLastRow();
  var lastColumn = sheet.getLastColumn();
  var range      = sheet.getRange(1,1,lastRow,lastColumn).getValues(); <-- get all values

  var pipeDelimitedString = range.map(r => r.join("|")).join("\n"); <-- instead of loop

}

或者更短,没有 lastRowlastColumn 变量:

function myFunction() {

  var ss    = SpreadsheetApp.openById(sheetID);
  var sheet = ss.getSheetByName(sheetName);
  var range = sheet.getDataRange().getValues();
  var pipeDelimitedString = range.map(r => r.join("|")).join("\n");

}

要点是一次性对所有单元格使用getRange().getValues()

更新

要删除 table 之外的空行和单元格,您可以将 replace() 方法应用于字符串变量:

pipeDelimitedString = pipeDelimitedString.replace(/\|+\s*\|+/g, "");

这是最简单的解决方案。但请注意,如果您的 table 中有空单元格,replace() 方法将导致您得到错误的结果。 1| |A 将变为 1A。它需要一个更复杂的算法来保持内部空单元格的完整性。实施繁重取决于您的数据。

在:

输出:

function myFunction() {
  const ss = SpreadsheetApp.openById(gobj.globals.ssid);//Change your id
  let s = ""
  const sh = ss.getSheetByName('Sheet1');//change your sheet name
  let vs = sh.getRange(1,1,sh.getLastRow(),sh.getLastColumn()).getValues();//getting all of the data on the sheet
  vs.forEach(r=>{r.forEach(c=>{s+="|" + c;});s+='\n';});//two loops
  newFile = DriveApp.createFile("PIPE DELIMITED TEST FILE", s);//you could add a folder
}

ascii 文件如下所示:

|COL1|COL2|COL3|COL4|COL5|COL6|COL7|COL8|COL9|COL10
|6|2|4|9|5|0|5|9|4|0
|5|1|5|7|1|2|5|7|0|0
|6|8|7|2|4|7|6|3|0|9
|7|5|7|6|3|2|7|7|0|0
|3|1|9|4|2|2|5|6|1|8
|7|8|8|3|2|7|1|6|3|0
|4|5|2|4|6|8|5|4|6|2
|9|3|6|7|5|7|9|9|0|6
|3|2|3|0|1|4|3|6|8|0
|9|0|0|2|8|0|0|2|4|7

为此sheet:

COL1 COL2 COL3 COL4 COL5 COL6 COL7 COL8 COL9 COL10
6 2 4 9 5 0 5 9 4 0
5 1 5 7 1 2 5 7 0 0
6 8 7 2 4 7 6 3 0 9
7 5 7 6 3 2 7 7 0 0
3 1 9 4 2 2 5 6 1 8
7 8 8 3 2 7 1 6 3 0
4 5 2 4 6 8 5 4 6 2
9 3 6 7 5 7 9 9 0 6
3 2 3 0 1 4 3 6 8 0
9 0 0 2 8 0 0 2 4 7