【问题标题】:Google Apps Script Utilities.parseCsv() and replacement character - �Google Apps Script Utilities.parseCsv() 和替换字符 - �
【发布时间】:2016-02-13 06:55:08
【问题描述】:

我正在开展一个项目,该项目涉及 Google Drive 中的一个 csv 文件,该文件每分钟左右都会用新数据更新一次。

我已经构建了一个电子表格仪表板,以使 csv 中的数据更有意义。

我错误地假设我可以使用 Google 电子表格函数 =importdata(url) 将 Google Drive 中的 CSV 中的数据获取到我的 Google 电子表格中,但是,除非我将 CSV 公开,否则会产生错误,出于安全和隐私原因,这是不可行的。即使我确实公开了 CSV 并使用了 importdata,进来的数据也是完全格式错误且无法使用的——它看起来与实际的 CSV 完全不同。

malformed data with importdats(url)

我正在尝试编写一个脚本来自动导入 csv 数据,使用 DriveApp 打开 csv 文件,Utilities.parseCsv 将 csv 转换为数据数组,然后 setValues 将数据写入工作表。

function importData() {
  var ss = SpreadsheetApp.getActive();
  var file = DriveApp.getFilesByName("Agent Performance.csv")
  var csv = file.next().getBlob().getDataAsString();
  var csvData = Utilities.parseCsv(csv);
  var sheet = ss.getSheetByName('CSV Import TEST');
  for (var i = 0; i < csvData.length; i++) {
    sheet.getRange(i+1, 1, 1, csvData[i].length).setValues(new Array(csvData[i]));
  }
}

问题是我得到了替换字符,例如:所有写入工作表的数据。太奇怪了。工作表看起来很正常,但是如果您单击一个单元格来查看它的值,则公式栏会显示单元格中的任何文本,但每个字符之间是一个�。这使得在 Google 表格中进行任何计算都是不可能的。

Notice replacement characters in formula bar

如果我只是使用 Google 表格“文件”、“导入”和“替换当前工作表”导入相同的 CSV,数据就可以了。这不是一个好的解决方案,因为我真的希望在 CSV 更新和 Google 表格中的仪表板更新之间有几分钟的延迟。如果我必须手动上传 CSV,它就违背了系统的目的。

任何帮助将不胜感激。谢谢!

【问题讨论】:

  • 您如何将 csv 文件上传到您的 Google 云端硬盘?您可以使用 Google 的 Drive Rest API,并发出 HTTPS POST 请求以上传 csv 文件。 Apps 脚本可以使用 UrlFetchApp.fetch() 发出 HTTPS POST 请求。您是在寻找一种不同的上传文件的方式,还是一种解析内容的方式?
  • 我正在寻找一种方法来解析内容。我不是 100% 清楚 csv 是如何更新的,但也许 https 发布请求会起作用。

标签: csv google-apps-script google-sheets


【解决方案1】:

您检查过文件字符集吗?您可以在调用getDataAsString(charset) 时指定它。试试这个:

function importData() {
  var ss = SpreadsheetApp.getActive();
  var file = DriveApp.getFilesByName("Agent Performance.csv")
  var csv = file.next().getBlob().getDataAsString('ISO-8859-1'); //note the charset
  var csvData = Utilities.parseCsv(csv);
  //unless you csv has variable amount of columns per line, you should do this
  if(csvData.length > 0) {
    ss.getSheetByName('CSV Import TEST')
      .getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
  } else
    throw 'Blank file';
}

【讨论】:

  • 谢谢!当我尝试代码时,我得到了同样的奇怪字符。我还尝试使用 'utt-8' 和 ascii 作为字符集,但无济于事。再次感谢您的建议。还有其他想法吗?
  • 你知道生成这个 csv 的人使用的编码吗?如果不这样做,请尝试使用程序来检测字符集(例如 linux 中的file)。或者你能分享一个示例文件吗?
  • 我已联系了解所使用的编码。我无法共享该文件,因为它包含私人信息。是否会在 excel 中打开 CSV 或下载并将其导入 Google 表格(两者都可以正常工作),以便我可以匿名化数据会影响该线程的编码?
【解决方案2】:

这可能会有所帮助,但您可能需要调查它是否会导致您的数据出现其他问题:

我在导入包含银行交易数据的 .txt 文件时遇到了同样的问题,因为银行不提供 CSV 下载文件。我发现奇数字符是 FFFD,它似乎是由 fileXYZ.getblob() 方法插入的,以替代无法识别的代码的 unrecognized 字符,在我的情况下,这些字符被替换为空格。

加载文件后,我的(非常基本的)解决方案如下..

function getBankTransactionFile(fileNameToGet) {
// fileNameToGet is .txt and stored in folder specified in Var list

 var  inputFileFolderID = '0B2XXX insert your folder ID',
     fldrID = DriveApp.getFolderById(inputFileFolderID),
     theFileRetrieved = fldrID.getFilesByName('yourFileName'),
     csvFile, cntFiles = 0;

// Even if it's only one file, must iterate a while loop in order to access the file. Google drive will allow multiple files of the same name.
  while (theFileRetrieved.hasNext()) {
    var fileXYZ = theFileRetrieved.next();
    cntFiles = cntFiles + 1;
    csvFile = Utilities.parseCsv(fileXYZ.getBlob()
              .getDataAsString().replace('\uFFFD'," ",'g'), "\n")
    // Utilities.parseCsv(csv, delimiter) returns 2D array but the fileXYZ 
    // text loaded has FFFD characters inserted so these are substituted for
    // 'space' using the .replace method and 'g' for global flag
  }
  return csvFile;
}

我是 GAS 的新手(从 VBA 转换),所以很确定有一种更精致的方法,但它适用于我的数据。请注意 \n 是换行符,作为我的数据的指定分隔符。我通过使用 Logger 显示原始数据字符串,然后提取代码.charCodeAt(n) 计算字符以找到 n,从而发现了奇数字符是什么。正如.txtimport 一样,您可以看到无法识别的字符应该是什么......在我的情况下是空格。

【讨论】:

    【解决方案3】:

    我对 csv 文件有同样的要求和同样的问题。我所做的可能是一种解决方法,但至少对我来说效果很好。

    “�”实际上可能是无法识别的任何类型的 ASCII 字符,因此在我的情况下,搜索“\uFFFD”并不能解决问题。所以我所做的基本上是将有效载荷转换为二进制数据。在那里,我设法注意到在所有字符之间传递了一个 NULL(ASCII 代码 0)。这是在我的情况下。所以我所做的是重建没有 0 的字节数组,然后再次将其复制到电子表格中。

    var response = UrlFetchApp.fetch(theUrl);
    var payload = response.getContentText();
    //Get byte Array 
    var bytes= response.getContent();
    var myArray = [];
    //Build byte array without the faulty characters
    for ( var i =1 ; i<bytes.length; i++){
      if (bytes[i] != 0){
       myArray.push(bytes[i]);
      }
    }
    //Reconvert to string.
    var newArray = Utilities.newBlob(myArray).getDataAsString();
    

    如果我要导入数字并在公式中使用它们,这个脚本也可以正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      相关资源
      最近更新 更多