Google Sheet 将范围容器特殊字符导出为 CSV

问题描述 投票:0回答:1

上一篇文章中,我能够实现部分目标,但我遇到了数据问题。该脚本旨在创建 CSV 导出,其中根据标题值导出特定数据列,并在导出的数据中更改标题值。

例如,我想从标题为“产品名称 - 完整”的列中导出列数据,但在导出中我需要将标题“产品名称 - 完整”更改为“描述 1”。

出现的问题是我有多个字段包含标点符号,例如逗号、引号等,目前引号会导致错误。该脚本将第一个引号更改为 ï,然后如果有第二个引号,则会将数据推送到下一列。

这里是测试工作簿的链接。脚本如下。

function Export_Database() {
  var ss = SpreadsheetApp.getActiveSpreadsheet(); 
  var sheet = ss.getSheetByName('Database');
  var folderTime = Utilities.formatDate(new Date(), "GMT-8", "yyyy-MM-dd'_'HH:mm:ss")   // Logger 1-3 
  var folder = DriveApp.createFolder(ss.getName().toLowerCase().replace(/ /g,'_') + '_csv_' + folderTime);
  var fileName = sheet.getName() + ".csv";
  var csvFile = Convert_Database(fileName, sheet);                              //****REF
  var file = folder.createFile(fileName, csvFile);
  var downloadURL = file.getDownloadUrl().slice(0, -8);
  Export_DatabaseURL(downloadURL);                                               //****REF
  //1 Logger.log("DEBUG: Folder date = "+folderTime) // DEBUG
  //2 Logger.log("DEBUG: Proposed folder name: "+ss.getName().toLowerCase().replace(/ /g,'_') + '_csv_' + folderTime) // DEBUG
  //3 Logger.log("DEBUG: Proposed file name: "+sheet.getName() + ".csv") // DEBUG
}

function Export_DatabaseURL(downloadURL) {                                       //****REF
  var link = HtmlService.createHtmlOutput('<a href="' + downloadURL + '">Click here to download</a>');
  SpreadsheetApp.getUi().showModalDialog(link, 'Your CSV file is ready!');
}


function Convert_Database(csvFileName, sheet) {
  const wb = SpreadsheetApp.getActiveSpreadsheet();  
  const sh = wb.getSheetByName("Database");
  const allvalues = sh.getRange(1,1,sh.getLastRow(),sh.getLastColumn()).getValues()         // Logger 1 | Get values (Row,Column,OptNumRows,OptNumColumns) 
  
  const header1 = allvalues[0].indexOf("SKU")                                               // get the column Index of the headers
  const header2 = allvalues[0].indexOf("Product Name - Full") 
  const header3 = allvalues[0].indexOf("Date Updated")  
  const header4 = allvalues[0].indexOf("Purchase Unit")
  const header5 = allvalues[0].indexOf("PRICE1")      
  const header6 = allvalues[0].indexOf("Conversion") 
  const header7 = allvalues[0].indexOf("Delivery Product Name")
  const header8 = allvalues[0].indexOf("Delivery Product Description")
                                           
  allvalues[0][header2] = "Description 1"                   // Assign replacement values
  allvalues[0][header3] = "Date"
  allvalues[0][header4] = "P. Unit"
  allvalues[0][header5] = "Price 1"
  allvalues[0][header6] = "Conv"
  allvalues[0][header7] = "Short Description"
  allvalues[0][header7] = "Long Description"

  // extract only the columns that relate to the headers 
  var data = allvalues.map(function(o){return [  
  o[header1],o[header2],o[header3],o[header4],o[header5],o[header6],o[header7],o[header8]
  ]})          
  
  // convert double quotes to unicode
  //loop over the rows in the array
  for (var row in data) {
    //use Array.map to execute a replace call on each of the cells in the row.
    var data_values = data[row].map(function(original_datavalue) {
      return original_datavalue.toString().replace('"', '"');
    })
    //replace the original row values with the replaced values
    data[row] = data_values;
  }

  // wrap any value containing a comma in double quotes
  data = data.map(function(e) {return e.map(function(f) {return ~f.indexOf(",") ? '"' + f + '"' : f})})
  
  // Logger.log("data rows = "+data.length+", data columns = "+data[0].length)

  var csvFile = undefined
  // loop through the data in the range and build a string with the csv data
    if (data.length > 1) {
      var csv = "";
      for (var dataRow = 0; dataRow < data.length; dataRow++) {

        // join each row's columns
        // add a carriage return to end of each row, except for the last one
        if (dataRow < data.length-1) {
          // valid data row
          csv += data[dataRow].join(",") + "\r\n";
          //Logger.log("DEBUG: row#"+dataRow+", csv = "+data[dataRow].join(",") + "\r\n")
        }
        else {
          csv += data[dataRow];
        }
      }
      csvFile = csv;
    }
    return csvFile;
}
csv google-sheets google-apps-script export-to-csv
1个回答
0
投票

在您的情况下,作为一个简单的修改,如何使用端点将工作表转换为 CSV 数据?当这反映在您的放映脚本中时,它会变成如下所示。

请修改您的函数

Convert_Database
如下。

修改后的脚本:

function Convert_Database(csvFileName, sheet) {
  const wb = SpreadsheetApp.getActiveSpreadsheet();
  const sh = wb.getSheetByName("Database");
  const allvalues = sh.getRange(1, 1, sh.getLastRow(), sh.getLastColumn()).getValues();

  const header1 = allvalues[0].indexOf("SKU");
  const header2 = allvalues[0].indexOf("Product Name - Full");
  const header3 = allvalues[0].indexOf("Date Updated");
  const header4 = allvalues[0].indexOf("Purchase Unit");
  const header5 = allvalues[0].indexOf("PRICE1");
  const header6 = allvalues[0].indexOf("Conversion");
  const header7 = allvalues[0].indexOf("Delivery Product Name");
  const header8 = allvalues[0].indexOf("Delivery Product Description");

  allvalues[0][header2] = "Description 1";
  allvalues[0][header3] = "Date";
  allvalues[0][header4] = "P. Unit";
  allvalues[0][header5] = "Price 1";
  allvalues[0][header6] = "Conv";
  allvalues[0][header7] = "Short Description";
  allvalues[0][header7] = "Long Description";

  var data = allvalues.map(function (o) { return [o[header1], o[header2], o[header3], o[header4], o[header5], o[header6], o[header7], o[header8]] });


  // --- I modified the below script.
  const temp = wb.insertSheet();
  temp.getRange(1, 1, data.length, data[0].length).setValues(data.map(r => r.map(c => c instanceof Date ? c.toString() : c)));
  SpreadsheetApp.flush();
  const url = `https://docs.google.com/spreadsheets/export?id=${wb.getId()}&exportFormat=csv&gid=${temp.getSheetId()}`;
  const csvFile = UrlFetchApp.fetch(url, { headers: { authorization: "Bearer " + ScriptApp.getOAuthToken() } }).getContentText();
  wb.deleteSheet(temp);
  return csvFile;
}
  • 当使用您提供的电子表格运行此脚本时,似乎每个单元格值都已正确转换。不过,请再确认一下。
  • 如果想使用日期值的显示值,请将
    data.map(r => r.map(c => c instanceof Date ? c.toString() : c))
    修改为
    date
  • 顺便说一下,在你的脚本中,似乎没有使用
    csvFileName, sheet
    的值。
© www.soinside.com 2019 - 2024. All rights reserved.