it-swarm.com.ru

Итерация по диапазону, добавление строки к каждому

У меня есть диапазон ячеек, выбранных в электронной таблице Google (activerange).

Я хочу перебрать каждую ячейку в этом диапазоне и добавить строку в конец. Строка всегда одинакова и может быть жестко закодирована в функцию.

Это кажется очень простой вещью, но я уже час напутал с кодом и не могу получить ничего полезного, а документы действительно не помогают. 

Вот что у меня сейчас. Я не кодирую JS (я знаю VBA, поскольку все это помогает ...).

function appendString() {
  var range = SpreadsheetApp.getActiveSheet().getActiveRange();
  for (var i = 0; i < range.length; i++) {
    var currentValue = range[i].getValue();
    var withString = currentValue + " string";
    range[i].setValue(withString);
  }
}

Любая помощь будет наиболее ценной.

36
ezuk

Вы можете попробовать что-то вроде этого:

function appendString() {
  var range = SpreadsheetApp.getActiveSheet().getActiveRange();
  var numRows = range.getNumRows();
  var numCols = range.getNumColumns();
  for (var i = 1; i <= numRows; i++) {
    for (var j = 1; j <= numCols; j++) {
      var currentValue = range.getCell(i,j).getValue();
      var withString = currentValue + " string";
      range.getCell(i,j).setValue(withString);
    }
  }
}
75
flyingjamus

Или альтернативно используйте setValues ​​() , который записывает все значения одновременно. Кажется, выполнить быстрее тоже.

var range = SpreadsheetApp.getActiveSheet().getActiveRange();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var writeValues = []
for (var i = 1; i <= numRows; i++) {
  var row = []
  for (var j = 1; j <= numCols; j++) {
    var currentValue = range.getCell(i,j).getValue();
    var withString = currentValue + " string";
    row.Push(withString)
  }
  writeValues.Push(row)
}
range.setValues(writeValues)
19
Voy

вот обновление для сообщение Воя , использует range.getValues ​​() , чтобы получить все значения и пропустить временный массив. должно быть еще быстрее, потому что range.getCell().getValue() опущен в двухмерном цикле. Обратите внимание, что индексы начинаются с 0 в этом фрагменте. Я также нахожу это более читабельным.

  var cells = range.getValues();
  var numRows = range.getNumRows();
  var numCols = range.getNumColumns();
  for (var i = 0; i < numRows; i++) {
    for (var j = 0; j < numCols; j++) {
      cells[i][j] += " string";
    }
  }

  range.setValues(cells);
3
Elan Ruusamäe

Вот очень универсальная функция, которая перебирает значения диапазона. Его также можно использовать для выполнения функции reduce (что полезно в вашем случае). Он также может выйти из цикла, если вы когда-нибудь захотите найти только первый элемент.

Его очень легко изменить, чтобы он принимал фактический экземпляр Range вместо массива значений.

function range_reduce(rangeValues,fn,collection) {
  collection = collection || [];
  var debug_rr = "<<";
  for(var rowIndex = 0, row=undefined; rowIndex<rangeValues.length && (row = rangeValues[rowIndex]); rowIndex++) { 
    for(var colIndex = 0, value=undefined; colIndex<row.length && (value = row[colIndex]); colIndex++) {
      try {
        collection = fn(collection, value, rowIndex, colIndex);
      } catch (e) {
        if(! e instanceof BreakException) {
          throw e;
        } else {
          return collection;
        }
      }
    }
  }
  return collection;
}

// this is a created, arbitrary function to serve as a way
// to break out of the reduce function. Your callback would
// `throw new BreakException()` and `rang_reduce` would stop
// there and not continue iterating over "rangeValues".
function BreakException();

В твоем случае:

var range = SpreadsheetApp.getActiveSheet().getActiveRange()
var writeValues = range_reduce(range.getValues(), function(collection, value, row, col) {
    collection[row] || collection.Push([]);
    collection[row].Push(value + " string");
});
range.setValues(writeValues)
2
Alexander Bird

Я предпочитаю метод Javascript 1.6 forEach циклам старой школы for. Вы можете:

function appendString() {
    var range = SpreadsheetApp.getActiveSheet().getActiveRange();
    var values = range.getValues();

    values.forEach(function(row, rowId) {
        row.forEach(function(col, colId) {
            values[rowId][colId] += " string";
            // Or: range.getCell(rowId + 1, colId + 1).setValue(col + " string");
            // Note: - '+1' to hit the cells, when using getCell
            //       - 'col' holds the current value of range.getCell(rowId + 1, colId + 1)
        });
    });

    range.setValues(values); // needless if using range.getCell(...).setValue(...);
}

Javascript 1.6 также предлагает map, который я предпочитаю даже больше:

function appendString() {
  var range = SpreadsheetApp.getActiveSheet().getActiveRange();
  var values = range.getValues();

  var modified = values.map(function (row) {
    return row.map(function (val) { 
      return val + " string"; 
    }); 
  })

  range.setValues(modified);
}

Я хотел бы использовать функции стрелок в обоих случаях, но они пока не поддерживаются в google-apps-script.

1
Stephan Stamm

Google-листы
Вы можете легко сделать это с помощью Find and Replace.

  • Выберите свой диапазон

  • Найти:

    ^(.*)$
    
  • Заменить: 

    $1AppendString
    
  • Пометить регулярные выражения 

  • Нажмите Заменить все

Я не вижу здесь никакого преимущества от использования скрипта, но, если необходимо, вы также можете выполнить Find Replace request с помощью API листов.

0
TheMaster