Сценарий Google Sheets: получить A1Notation для каждой ячейки в именованном диапазоне

#google-apps-script #google-sheets

#Google-apps-script #Google-Sheets

Вопрос:

Функция, над которой я работаю, оптимизирует усилие, необходимое для рулевой фольги (стабилизатора) на яхте America’s Cup AC75, чтобы сбалансировать продольные моменты сил паруса. Это делается путем изменения угла наклона стабилизатора, начиная с первоначального обеспечения восходящей (положительной) силы, затем по мере увеличения силы паруса стабилизатор должен создавать нисходящую (отрицательную) силу.

Углы стабилизатора указаны в столбце, и при его изменении выполняются другие вычисления, если они уравновешивают силы паруса. Если это не так, есть столбец «Дельта», который указывает значение, должна ли фольга руля обеспечивать большее / меньшее усилие, через его угол.

Я попытался использовать именованные диапазоны для столбца углов, а другой — для дельты. Код должен повторяться, добавляя немного больший (или меньший) угол к стабилизатору, и каждый раз проверять дельту. Мой код неверен.

Что мне нужно сделать, это получить значение угла одной угловой ячейки, постепенно увеличивать / уменьшать его, а затем установить значение этой ячейки. Далее нужно получить значение соответствующей дельта-ячейки, чтобы узнать, нахожусь ли я на нуле (плюс / минус небольшая сумма). Если нет, с помощью цикла while я снова увеличиваю / уменьшаю угол, устанавливаю значение, перепроверяю дельту и так далее.

Моя проблема в том, что я не знаю, как получить A1Notation для каждой ячейки в именованных диапазонах, когда я перебираю ее, чтобы я мог многократно получать значение и устанавливать значение только для одной ячейки за раз?

 function c_Optimise_Stabilator() {
// Author: Max Hugen
// Date: 20102-12-07
// Purpose: Attempt to optimise Stab Angle to balance with Stab Target Force

/* WARNING: This function may eventually cause a circular reference, so ensure there is an "escape".
 *          May occur if other optimisation functions are also run?
 * OPTIMISATION: Try in this order:
 *          1. Optimise Transverse Moments 
 *          2. Optimise Stabilator 
 *          3. Check, and if necessary, rerun Optimise Transverse Moments 
 *          4. Check, and if necessary, rerun Optimise Stabilator
 *             If Optimise Stabilator returns all Angles OK, we're good!
*/

  const ui = SpreadsheetApp.getUi();
  const ss = SpreadsheetApp.getActiveSpreadsheet();

//  var target_sheet = "Analysis";
//  var sheet = ss.getSheetByName("Analysis");
  var msg = ""; // gather input for Logger
  var s = "";   // short info for testing alerts, then added to msg
  var log = true; // whether to output msg to the Logger

  // angle range
  const maxAngle = 2.0, minAngle = -0.2, incAngle = 0.1;
  //limits
  var maxLoopIterations=10;  // to avoid excessive iterations
  var minDelta=0.02;          // to limit the minimum size of Delta tested
  // counters
  var i=0, loopIterations=0;
  // Original and New Vals
  var originalAngle=0.0, newAngle=0.0, originalDelta=0.0, newDelta=0.0;

  // ranges used in getRange - variable here, for testing. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/* 
  var sAngle = "Optimise_Stab_Angle";
  var sDelta = "Optimise_Stab_Delta";
 
  var sAngle = "Analysis!AF14:AG14";   // 1 rows (but only 2 cols now) - failing
  var sDelta = "Analysis!AM14:AM14";
*/  
  var sAngle = "Analysis!AF10:AG13";   // 4 rows
  var sDelta = "Analysis!AM10:AM13";

  var rAngle = ss.getRange(sAngle);
  var dAngle = rAngle.getValues();
  var rDelta = ss.getRange(sDelta);
  var dDelta = rDelta.getValues();
  
  originalAngle = Math.round(dAngle[i][1]*1000)/1000;
  originalDelta = Math.round(dDelta[i][0]*1000)/1000;

  var iLen = rAngle.getNumRows();

  for(i=0; i<iLen; i  ){
    s = "";

    newAngle = originalAngle;
    s  = "    Vb: "   dAngle[i][0]   "; Original Angle: "   originalAngle   "; originalDelta: "   originalDelta   "rn";

    // if stabilator force is below target (negative Delta), increase stab angle unless at maxAngle.
    if ( Math.abs(Math.round(dDelta[i][0]*100)/100) > minDelta amp;amp; originalAngle < maxAngle) {

      loopIterations = 1; 
      while (newAngle <= maxAngle) {
        try {
          if ( newAngle == maxAngle ) {
            s  = "                 MAX.ANGLE: newDelta"   newDelta   "; originalDelta: "   originalDelta;
            break;
          }
          // Have to update the Delta range, to check if Delta still too high/low
          var rDelta = ss.getRange(sDelta);
          var dDelta = rDelta.getValues();
          newDelta = Math.round(dDelta[i][0]*1000)/1000;
          
          if ( Math.abs(Math.round(newDelta*100)/100) < minDelta ) {
            s  = "                 COMPLETED: newDelta"   newDelta   "; originalDelta: "   originalDelta;
            break;
          }
          if ( loopIterations > maxLoopIterations ) {
            s  = "                 EXCEEDED maxLoopIterations of "   maxLoopIterations;
            break;
          }
        } catch(err) {
          Logger.log (c_ErrorToString (err)   "n"   "Vb: "   dAngle[i][0]);
        }
        newAngle  = incAngle;  // for some reason, this may STILL produce a number like 1.400000003 (example only)
        newAngle = Math.round(newAngle*1000)/1000;
        
        // set the new angle
        dAngle[i][1] = newAngle;
        // update the iteration count
        loopIterations   
      } 
    }
    
    // if stabilator force is above target (positive Delta), decrease stab angle unless at minAngle.
    else if ( Math.abs(Math.round(dDelta[i][0]*100)/100) > minDelta amp;amp; originalAngle > minAngle) {
      loopIterations = 1; 
      
      while (newAngle >= minAngle) {

        try {
          if ( newAngle == minAngle ) {
            s  = "                 MIN.ANGLE: newDelta"   newDelta   "; originalDelta: "   originalDelta;
            break;
          }
          // Have to update the Delta range, to check if Delta still too high/low
          var rDelta = ss.getRange(sDelta);
          var dDelta = rDelta.getValues();
          newDelta = Math.round(dDelta[i][0]*1000)/1000;
          
          if ( Math.abs(Math.round(newDelta*100)/100) < minDelta ) {
            s  = "                 COMPLETED: newDelta"   newDelta   "; originalDelta: "   originalDelta;
            break;
          }
          if ( loopIterations > maxLoopIterations ) {
            s  = "                 EXCEEDED maxLoopIterations of "   maxLoopIterations;
            break;
          }
        } catch(err) {
          Logger.log (c_ErrorToString (err)   "n"   "Vb: "   dAngle[i][0]);
        }

        newAngle -= incAngle;  // for some reason, this may STILL produce a number like 1.400000003 (example only)
        newAngle = Math.round(newAngle*1000)/1000;
        
        // set the new angle
        dAngle[i][1] = newAngle;
        // update the iteration count
        loopIterations   
      } 
    }
    
    msg  = s   "rn";
  }
  rAngle.setValues(dAngle);
  
  msg = "c_Optimise_Stabilator rn"   msg
  Logger.log(msg);
  ui.alert(msg);
}
 

Ответ №1:

Нашел способ получить ячейку A1Notation, используйте getCell() для диапазона, затем getA1Notation .

 cellA1 = range.getCell(1, 1).getA1Notation();