Как построить многомерные массивы в соответствующей ориентации.(Строки / колы в правильных местах) - PullRequest
0 голосов
/ 13 февраля 2019

Я работаю над созданием инструмента на основе Google Sheets для расчета стоимости изготовления различных обработанных и изготовленных деталей.В настоящее время существует около 60 различных переменных, которые я изменяю каждый раз, когда строю оценку.Такие вещи, как «количество деталей», «длина прутка для резки каждой детали», «стоимость / пруток», «время обработки», «скорость обработки» и т. Д. Все эти значения я заполнил на одном листе и положилтаким образом, как.Я хочу сделать кнопку, которая берет «снимок» всех этих значений и сохраняет их на другом листе для дальнейшего использования.Затем, в идеале, я бы создал другую кнопку, которая позволит мне заново заполнить все ячейки на основе уникального идентификатора (такого как Part #).Это позволило бы мне подстроить оценку или даже сослаться на размеры материала и т. Д. Осмысленно.

До сих пор я создавал «Именованный диапазон» для каждого из значений, чтобы при изменениикомпоновка или добавление значений, мой код скрипта должен обновляться соответствующим образом, вместо использования прямых ссылок на ячейки.

Я построил несколько функций для получения и установки значений этих именованных диапазонов.Они работают, как и ожидалось (я думаю) для того, что я пытаюсь сделать.Но когда я пытаюсь поместить массив именованных диапазонов в многомерный массив именованных диапазонов с их соответствующими значениями, я сталкиваюсь с проблемой, когда каждый именованный диапазон является строкой, а их соответствующее значение - вторым столбцом.И мне нужно поменять местами

Мне не очень комфортно с многомерными массивами, и я думаю, что я в кругах, пытаясь понять, как логически перенести это.Моя интуиция говорит, что моя попытка построить массивы - это моя проблема, а не то, как я их перебираю.

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 строк и только два столбца, из-за того, как построен массив.Я хотел бы лучше понять, как я создаю этот многомерный массив по вертикали, а не по горизонтали, и как это исправить!

Как только это будет сделано, я хотел бы создать заголовки, соответствующие именованнымДиапазоны на моем листе сохранения, чтобы позволить мне перебирать функции и искать совпадения с соответствующим столбцом по имени.Таким образом, если я добавлю больше значений или изменим их порядок или порядок массива, это не имеет значения.Я думаю, я смогу понять это довольно легко, если смогу лучше контролировать эти чертовы массивы!

1 Ответ

0 голосов
/ 15 февраля 2019

Я согласен с ОП.Построение массива И итерации - это насущные проблемы, и они являются камнем преткновения при разработке электронной таблицы

У ОП есть поднятый ряд вопросов, однако самая неотложная, и одна из них, которая должна быть решена в рамках этого ответа, - это копирование списка деталей с одного листа на другой.В коде ОП именованные диапазоны были извлечены и использованы в качестве основы для создания копии списка деталей.Однако это также создает дублированный набор именованных диапазонов на целевом листе.На мой взгляд, это неоправданно усложняет дублирование списка деталей, так как легко программно создать / обновить список именованных диапазонов.

Следующий код состоит из трех функций:

  • 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();
  }
}

ADDENDUM: - Копирование на основе именованных диапазонов

В оригинальном so_5466573501 предполагается, что детали находятся в простом списке из 2 столбцов;в этом случае именованные диапазоны не имеют значения.

В следующем коде предполагается, что детали находятся не в списке, а разбросаны в произвольном порядке по всему листу «Калькулятор стоимости детали».Этот код основан на получении NamedRanges, определении соответствующей строки и столбца Named Range, сопоставлении указанной строки и столбца с ВСЕМ диапазоном данных, а затем копировании результатов на лист «Сохраненные части».На листе «Сохраненные детали» по умолчанию не создаются именованные диапазоны, но это легко сделать с помощью функции 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
  });
}
...