如何以适当的方向构建多维数组。 (行/颜色在正确的位置)

时间:2019-02-13 08:37:42

标签: arrays multidimensional-array google-apps-script google-sheets

我正在构建基于Google表格的工具,以计算制造各种机加工零件的成本。按照目前的情况,每次估算时都会修改大约60个不同的变量。诸如“零件数”,“要切割成每个零件的条的长度”,“成本/条”,“加工时间”,“加工率”之类的东西。我已经将所有这些值填充在一张纸上并放置像这样我想制作一个将所有这些值“快照”的按钮,并将它们存储在另一张纸上,以供以后参考。然后,理想情况下,我将创建另一个按钮,该按钮使我可以根据唯一ID(例如部件号)重新填充所有单元格。这可以让我调整估算值,甚至可以有意义的方式参考材料尺寸等。

到目前为止,我已经为每个值创建了一个“命名范围”,以便在更改布局或添加值时,我的脚本代码应相应更新,而不是使用直接单元格引用。

我建立了一些函数来获取和设置这些命名范围的值。他们正在按我的预期工作。但是,当我尝试将命名范围的数组放置在具有各自值的命名范围的多维数组内时,我遇到了一个问题,其中每个命名范围是ROW且它们各自的值是第二列。我需要交换它

我对多维数组不是很满意,并且正在圈子里想着自己,试图弄清楚如何进行逻辑上的转置。我的直觉说,我尝试构建阵列的方式是我的问题,而不仅是如何遍历它们。

function saveCurrentValues(){
 //set master spreadhseet
 var ss = SpreadsheetApp.getActiveSpreadsheet(); 

 //set calc and save sheets to vars  
 var calcSheet = ss.getSheetByName('Part Cost Calculator')
 var saveSheet = ss.getSheetByName('Saved Parts');

 //set named ranges from calcSheet to array
 var namedRanges = calcSheet.getNamedRanges();
 var savedValues = new Array();

 //find next available row for save data (currently troubleshooting)
 var nextAvailSaveRange = saveSheet.getRange(1, 1, 60, 2);

 //iterate through array and call getNamedRange() function to return name and current value
 for(i = 0; i < namedRanges.length; i++){
  savedValues[i] = getNamedRange(namedRanges[i].getName());
 }
 nextAvailSaveRange.setValues(savedValues); 
}

function getNamedRange(name){
 var ss = SpreadsheetApp.getActiveSheet();
 var value = ss.getRange(name).getValue();
 Logger.log([name,value]);
 return [name, value];
}

如您所见,我必须临时格式化nextAvailSaveRange,由于数组的构造方式,它需要60个ROWS,并且只有两列。我想更好地了解如何垂直而不是水平地创建此多维数组,以及如何解决它!

完成此操作后,我想创建与保存表上的“命名范围”相匹配的标题,以允许我遍历函数并按名称查找与适当列的匹配。这样,如果我添加更多值或更改它们的顺序或数组的顺序,就没有关系了。如果可以更好地控制这些可恶的数组,我想我很容易就能弄清楚!

1 个答案:

答案 0 :(得分:0)

我同意OP。数组构建和迭代是当前的问题,它们是电子表格开发的绊脚石。

OP的问题数量有所增加,但是,最紧迫的问题是在此答案下要解决的问题,是将零件清单从一张纸复制到另一张纸。在OP的代码中,检索了命名范围,并将其用作创建零件清单副本的基础。但是,这也会在目标工作表上创建一组重复的命名范围。我认为,这很容易使零件清单的复制变得复杂,因为很容易以编程方式创建/更新命名范围清单。

以下代码包含三个功能:

  • so_5466573501()-将零件列表从一张纸复制到另一张纸。
    命名范围将被忽略; OP的绊脚石是原始数据的迭代和数组的管理。这段代码仅涉及该方面,以简化此问题。

  • createnamedranges()-以编程方式创建/更新命名范围。
    包含此代码是为了确保OP通过显示将零件列表以编程方式将一系列零件转换为一系列命名范围的难易程度,使命名范围成为重复的重点并不重要(为了开发,我创建了60个零件,整个代码将在1秒内执行)。该代码假定一个分为两列的列表(A列=参数名称,B列=参数值)。代码遍历列表,以创建/更新一组命名范围-范围名称是列A中的参数名称,范围本身是列B中的对应行。工作表名称设置在变量中,因此可以轻松调整此功能。

  • deletenamedranges()-以编程方式删除命名范围。
    此代码从给定的工作表中删除所有命名范围。包含此功能是因为OP的现有代码会创建重复的命名范围,并且可能有必要从工作表中快速删除它们。工作表名称存储为变量,因此可以轻松修改该功能。


function so_5466573501() {

  //set master spreadsheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  //create variables for calc and save sheets
  var calcSheet = ss.getSheetByName('Part Cost Calculator')
  var saveSheet = ss.getSheetByName('Saved Parts');

  //get the Parts Parameters from Part Cost Calculator
  //var namedRanges = calcSheet.getNamedRanges();
  //Logger.log("DEBUG: Number of named ranges on Parts Cost Calculator = "+namedRanges.length);

  // get the number of parts in the list on Parts Cost Calculator
  var Avals = calcSheet.getRange("A1:A").getValues();
  var Alast = Avals.filter(String).length;
  //Logger.log("DEBUG: Number of parts in the list: "+Alast); //DEBUG

  // get the parts list
  var partsRange = calcSheet.getRange(1, 1, Alast, 2);
  var partsRangeValues = partsRange.getValues();
  //Logger.log("DEBUG: The parts range is: "+partsRange.getA1Notation());//DEBUG
  //Logger.log("DEBUG: Parts List Row #1: Name: "+partsRangeValues[0][0]+", Value: "+partsRangeValues[0][1]);//DEBUG


  // create an array to use for saving results and updating new Saved Parts sheet
  var savedValues = new Array();

  // Loop through the Parts List, row by row
  for (i = 0; i < Alast; i++) {

    // push the part name and part value onto the array 
    savedValues.push([partsRangeValues[i][0], partsRangeValues[i][1]]);
    //Logger.log("DEBUG: Parts List: i = "+i+", Name: "+partsRangeValues[i][0]+", Value: "+partsRangeValues[i][1]);//DEBUG

  }

  // identify the range on the Saved Parts sheet to copy the parts list array.
  var saveRange = saveSheet.getRange(1, 1, Alast, 2);
  saveRange.setValues(savedValues);
}

 function createnamedranges() {

  //set master spreadhseet
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  //create variables for calc and save sheets
  var calcSheetName = "Part Cost Calculator";
  var calcSheet = ss.getSheetByName(calcSheetName);

  // get the number of parts in the list on Parts Cost Calculator
  var AVals = calcSheet.getRange("A1:A").getValues();
  var ALast = AVals.filter(String).length;

  // get the parts range and values
  var partsRange = calcSheet.getRange(1, 1, ALast, 2);
  //Logger.log("DEBUG: The Parts range is "+partsRange.getA1Notation());//DEBUG
  var partsRangeValues = partsRange.getValues();

  // Loop through the parts list row by row
  for (var i = 0; i < ALast; i++) {

    // get the Part name and assign as the range name
    var nrpartname = partsRangeValues[i][0];
    //Logger.log("DEBUG: PartName = "+nrpartname+", value: "+partsRangeValues[i][1]);//DEBUG

    // get the range to be named -note (i+1) because the loop starts at 0 (zero) but `getrange` starts at 1 (one)
    var rng_to_name = ss.getSheetByName(calcSheetName).getRange((i + 1), 2);
    //Logger.log("DEBUG: rng_to_name: "+rng_to_name+", range details: "+rng_to_name.getA1Notation());

    // set (and/or update) the named range
    ss.setNamedRange(nrpartname, rng_to_name);

    // DEBUG: check that the range was created //DEBUG
    // var rangeCheck = ss.getRangeByName(nrpartname);//DEBUG
    // var rangeCheckName = rangeCheck.getA1Notation(); //DEBUG
    // Logger.log("DEBUG: Rangename: "+nrpartname+", Range: "+rangeCheckName);//DEBUG
    // credit megabyte1024 https://stackoverflow.com/a/12325103/1330560 "setNamedRange() outside of the spreadsheet container?"

  }

}

function deletenamedranges() {

  //set master spreadhseet
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  //create variables for calc and save sheets
  var calcSheet = ss.getSheetByName('Part Cost Calculator');

  // get the named ranges
  var namedRanges = calcSheet.getNamedRanges();

  // loop through the list of named ranges and delete them
  for (var i = 0; i < namedRanges.length; i++) {
    namedRanges[i].remove();
  }
}

附录:-根据命名范围进行复制

原始的so_5466573501假定零件位于简单的2列列表中;在这种情况下,命名范围是不相关的。

下面的代码假定零件不在列表中,而是以“零件成本计算器”的形式按特定顺序散布。该代码基于获取NamedRanges,标识相应的Named Range行和列,将所述行和列与ENTIRE数据范围相关联,然后将结果复制到“ Saved Parts”表中。默认情况下,“保存的零件”页面上没有创建命名范围,但是可以使用createnamedranges函数(正确编辑正确的表名)来轻松地完成此操作。

function so_5466573502() {

  //set master spreadhseet
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  //create variables for calc and save sheets
  var calcSheet = ss.getSheetByName('Part Cost Calculator')
  var saveSheet = ss.getSheetByName('Saved Parts');

  //get the Parts Parameters from Part Cost Calculator
  var namedRanges = calcSheet.getNamedRanges();
  var numNR = namedRanges.length
  //Logger.log("DEBUG: Number of named ranges on Parts Cost Calculator = "+numNR);

  // get all the data
  var dataRangeValues = calcSheet.getDataRange().getValues();

  // create an array to temporarily store results
  var resultsarray = [];

  // Loop through the array of Named Ranges
  for (var x = 0; x < numNR; x++) {

    var nrName = namedRanges[x].getName();
    var nrRange = namedRanges[x].getRange();
    var nrRangerow = nrRange.getRow();
    var nrRangecol = nrRange.getColumn();
    var nrRangeValue = dataRangeValues[nrRangerow - 1][nrRangecol - 1];
    //Logger.log("DEBUG: Named Range-Name: "+nrName+", Range: "+nrRange.getA1Notation()+", Row: "+nrRangerow+", Column: "+nrRangecol+", Value-"+nrRangeValue);//DEBUG

    // populate the array with the part name and the part value
    resultsarray.push([nrName, nrRangeValue]);
  }

  // identify the range on the Saved Parts sheet to copy the parts list array.
  var saveRange = saveSheet.getRange(1, 1, numNR, 2);
  saveRange.setValues(resultsarray);

  // sort the results  on "Saved Parts"
  saveRange.activate().sort({
    column: 1,
    ascending: true
  });
}