限制脚本以将单元格更改记录到特定行

时间:2016-11-23 16:41:22

标签: google-apps-script google-sheets

我刚刚开始愚弄谷歌脚本和超级新手,所以请在这里忍受我。

我目前正在使用此公式将更改记录到单独的电子表格中的特定列:

    function onEdit(event) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var s = event.source.getActiveSheet();

  var r = event.source.getActiveRange();

  if(s.getName() == "Sheet1" && r.getColumn() == 73 && r.getValue()) {

    var row = r.getRow();

    var numColumns = s.getLastColumn();

    var targetSheet = ss.getSheetByName("Quarterly Report");

    if(targetSheet.getLastRow() == targetSheet.getMaxRows()) {
      targetSheet.insertRowAfter(targetSheet.getLastRow());
    }

    var target = targetSheet.getRange(targetSheet.getLastRow()+1,1);

    s.getRange(row, 1, 1, numColumns).copyTo(target);
  }
}

但是我想将'getRange'限制为只有A列,E列和F列(即排除B,C,D列)

请参阅“Data Test”以供参考。

帮助?

2 个答案:

答案 0 :(得分:1)

要将这些列A,E和F复制到新位置,您可以执行以下操作:

function onEdit(event) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var s = event.source.getActiveSheet();

  var r = event.source.getActiveRange();

  if(s.getName() == "Sheet1" && r.getColumn() == 73 && r.getValue()) {

    var row = r.getRow();

    var numColumns = s.getLastColumn();

    var targetSheet = ss.getSheetByName("Quarterly Report");

    if(targetSheet.getLastRow() == targetSheet.getMaxRows()) {
      targetSheet.insertRowAfter(targetSheet.getLastRow());
    }

    //Changes Start Here
    var myRow = targetSheet.getLastRow()+1;

    s.getRange(row, 1).copyTo(targetSheet.getRange(myRow,1));
    s.getRange(row, 5).copyTo(targetSheet.getRange(myRow,5));
    s.getRange(row, 6).copyTo(targetSheet.getRange(myRow,6));
  }
}

硬编码复制位置。如果要将数据放在不同的列中,请更改1,5和6。您还可以使用代码in this tutorial来更好地确定要存储的列和数据。

下面的部分
//////////////////////////////////////////////////////////////////////////////////////////
//
// The code below is reused from the 'Reading Spreadsheet data using JavaScript Objects'
// tutorial.
//
//////////////////////////////////////////////////////////////////////////////////////////

从电子表格中读取数据,并且可以让您使用第一行作为工作表中的标题来检索并根据代码中的数据将数据放入列中。您可能希望在javascript中使用Objects来使用它。我只提到它为代码添加灵活性。如果您对列进行硬编码,则没有必要。

修改 请参阅@utphx响应,了解将值添加到行中特定列的有趣方法,将3行代码合并为一行。而不是

s.getRange(row, 1).copyTo(targetSheet.getRange(myRow,1));
s.getRange(row, 5).copyTo(targetSheet.getRange(myRow,5));
s.getRange(row, 6).copyTo(targetSheet.getRange(myRow,6));

我们可以使用

targetSheet.appendRow([s.getRange(row, 1).getValue(),"","","",s.getRange(row, 5).getValue(),s.getRange(row, 6).getValue()]); 

此外,通过使用从读取整行返回的对象来获得他所获得的速度,并进行一次调用以检索值而不是我在原始响应中所做的3:

//Retrieve the values if the entire row
var source = s.getRange(row, 1, 1, numColumns).getValues();
var targetSheet = ss.getSheetByName("Quarterly Report");
targetSheet.appendRow([source[0][0],"","","",source[0][4],source[0][5]]);

我可能不会在包含大量列的工作表上使用它,因为它定义了逗号之间每个单元格的内容,并且很难理解。因此,如果向Y列添加项目,最后会在括号内添加很多内容。它基本上是:

targetSheet.appendRow([column_A_Value,column_B_Value,column_C_Value,column_D_Value,column_E_Value,column_F_Value]);

在包含大量列的电子表格中,我绝对会使用上述教程中的信息来创建getRowsData()函数。在目标工作表中创建一个标题行,以下代码将允许您从任一工作表(选项卡)插入或重新排列列等。所以下面成为更灵活的解决方案。我并不是说它更有效率,也不是错误检查,只是更灵活。它包含来自链接教程的所需代码:

function onEdit(event) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var s = event.source.getActiveSheet();
//  var s =ss.getSheetByName("Current");

  var r = ss.getActiveRange();

  if(s.getName() == "Current" && r.getColumn() == 5 && r.getValue()) {
    var row = r.getRow();
    var rowIndex = row - 1;
    var numColumns = s.getLastColumn();
    var sourceRange = s.getRange(1, 1, row, numColumns);
    // Create one JavaScript object per row of data from the Source data (the Current tab)
    var data = getRowsData(s, sourceRange, 1);

    // Create a JavaScript object for the Target data (the Quarterly Report tab)
    var targetSheet = ss.getSheetByName("Quarterly Report");
    var numRows = targetSheet.getLastRow();
    numColumns = targetSheet.getLastColumn();
    var targetRange = s.getRange(1, 1, 1, numColumns);
    var targetHeaders = targetSheet.getDataRange().getValues().shift();
    var saveData = createArray(numColumns, null);

    //Save the data we will be adding to teh Target in the proper locations in the array
    saveData[targetHeaders.indexOf('Name')] = data[rowIndex].name;
    saveData[targetHeaders.indexOf('Subsidy')] = data[rowIndex].subsidy;
    saveData[targetHeaders.indexOf('Last Update')] = data[rowIndex].lastUpdate;

    //Save the data to teh Target
    targetSheet.appendRow(saveData);  
  }

}

//Create an array with a given number of items and a given common value
function createArray(len, itm) {
    var arr1 = [itm],
        arr2 = [];
    while (len > 0) {
        if (len & 1) arr2 = arr2.concat(arr1);
        arr1 = arr1.concat(arr1);
        len >>>= 1;
    }
    return arr2;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// The code below is reused from the 'Reading Spreadsheet data using JavaScript Objects'
// tutorial.
//
//////////////////////////////////////////////////////////////////////////////////////////

// getRowsData iterates row by row in the input range and returns an array of objects.
// Each object contains all the data for a given row, indexed by its normalized column name.
// Arguments:
//   - sheet: the sheet object that contains the data to be processed
//   - range: the exact range of cells where the data is stored
//   - columnHeadersRowIndex: specifies the row number where the column names are stored.
//       This argument is optional and it defaults to the row immediately above range;
// Returns an Array of objects.
function getRowsData(sheet, range, columnHeadersRowIndex) {
  columnHeadersRowIndex = columnHeadersRowIndex || range.getRowIndex() - 1;
  var numColumns = range.getEndColumn() - range.getColumn() + 1;
  var headersRange = sheet.getRange(columnHeadersRowIndex, range.getColumn(), 1, numColumns);
  var headers = headersRange.getValues()[0];
  return getObjects(range.getValues(), normalizeHeaders(headers));
}

// For every row of data in data, generates an object that contains the data. Names of
// object fields are defined in keys.
// Arguments:
//   - data: JavaScript 2d array
//   - keys: Array of Strings that define the property names for the objects to create
function getObjects(data, keys) {
  var objects = [];
  for (var i = 0; i < data.length; ++i) {
    var object = {};
    var hasData = false;
    for (var j = 0; j < data[i].length; ++j) {
      var cellData = data[i][j];
      if (isCellEmpty(cellData)) {
        continue;
      }
      object[keys[j]] = cellData;
      hasData = true;
    }
    if (hasData) {
      objects.push(object);
    }
  }
  return objects;
}

// Returns an Array of normalized Strings.
// Arguments:
//   - headers: Array of Strings to normalize
function normalizeHeaders(headers) {
  var keys = [];
  for (var i = 0; i < headers.length; ++i) {
    var key = normalizeHeader(headers[i]);
    if (key.length > 0) {
      keys.push(key);
    }
  }
  return keys;
}

// Normalizes a string, by removing all alphanumeric characters and using mixed case
// to separate words. The output will always start with a lower case letter.
// This function is designed to produce JavaScript object property names.
// Arguments:
//   - header: string to normalize
// Examples:
//   "First Name" -> "firstName"
//   "Market Cap (millions) -> "marketCapMillions
//   "1 number at the beginning is ignored" -> "numberAtTheBeginningIsIgnored"
function normalizeHeader(header) {
  var key = "";
  var upperCase = false;
  for (var i = 0; i < header.length; ++i) {
    var letter = header[i];
    if (letter == " " && key.length > 0) {
      upperCase = true;
      continue;
    }
    if (!isAlnum(letter)) {
      continue;
    }
    if (key.length == 0 && isDigit(letter)) {
      continue; // first character must be a letter
    }
    if (upperCase) {
      upperCase = false;
      key += letter.toUpperCase();
    } else {
      key += letter.toLowerCase();


   }
  }

  return key;
}

// Returns true if the cell where cellData was read from is empty.
// Arguments:
//   - cellData: string
function isCellEmpty(cellData) {
  return typeof(cellData) == "string" && cellData == "";
}

// Returns true if the character char is alphabetical, false otherwise.
function isAlnum(char) {
  return char >= 'A' && char <= 'Z' ||
    char >= 'a' && char <= 'z' ||
    isDigit(char);
}

// Returns true if the character char is a digit, false otherwise.
function isDigit(char) {
  return char >= '0' && char <= '9';
}

答案 1 :(得分:1)

您还可以使用追加行,这样您就不必继续检查最后一行是否为最大行:

function onEdit() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var s = ss.getActiveSheet();
  var r = s.getActiveRange();

  if(s.getName() == "Sheet1" && r.getColumn() == 73 && r.getValue()) {
    var row = r.getRow();
    var numColumns = s.getLastColumn();
    var source = s.getRange(row, 1, 1, numColumns).getValues();
    var targetSheet = ss.getSheetByName("Quarterly Report");
    targetSheet.appendRow([source[0][0],"","","",source[0][4],source[0][5]])  
  }
}