I'm reading an Excel file in javascript.
One of the cell has a VLOOKUP formula:
VLOOKUP(C40,D107:F114,3,FALSE) //(searched value, table range, returned value column, exact match)
What it's basically doing is searching for the the value on C40 in a table range of D107 -> F114 (starting point and end point) and returning the value on the 3 column, on this example- column F. FALSE indicates we are looking for an exact match.
I need to extract the table defined on the formula D107:F114 (3 columns (D, E, F), 8 cells (107, 108, 109, etc.)) and save its content in code.
This is what I did- works fine, I am wondering if there is a shorter way to do it:
const formula = sheet.cell('A40').formula()
var splittedFormula = formula.split(/[\s,]+/) //split formula by params -> splittedFormula = [C40, D107:F114, 3, FALSE]
const numOfColumns = splittedFormula[2] //geting the total number of columns by the third param- "returned value column" -> numOfColumns = 3
let numOfCells = splittedFormula[1].split(/[\s:]+/) //get the start point of the table -> numOfCells = [D107, F114]
let startingCell = numOfCells[0].replace(/\D/g, '') //extract the starting cell -> startingCell = 107
let startingColumn = numOfCells[0].replace(/\d+/g, '') //extract the starting column -> startingColumn = D
numOfCells =
numOfCells[1].replace(/\D/g, '') - numOfCells[0].replace(/\D/g, '') + 1 //calculate how many cells on each column by substracting the start point cell from the end point cell (`114 - 107`) -> numOfCells = 8
var table = new Array(numOfColumns) //defining an array of arrays -> table = [3]
let currentCell
//loop through the table in the excel sheet and save it's content each column is an array that store the cells value. table = [3][8]
for (var i = 0; i < numOfColumns; i++) { //numOfColumns=3
table[i] = new Array(numOfCells) //numOfCells=8
currentCell = startingCell
for (var j = 0; j < numOfCells; j++) {
table[i][j] = sheet.cell(startingColumn + currentCell).value()
currentCell = parseFloat(currentCell) + 1 //increment to the next cell i.e. 107 + 1 = 108 etc..
}
startingColumn = String.fromCharCode(startingColumn.charCodeAt() + 1) //increment to the next column i.e. D + 1 = F etc..
}
The first "minimization" (and most important one) is to check if your sheet instance allows to extract a slice (idem the submatrix or table you try to extract).
On a more generic way you can:
skip some lines about extracting the formula (or at least make it clearer)
let formula = 'D107:F114'
let [colStart, rowStart, colEnd, rowEnd] = formula.match(/([A-Z]+)(\d+):([A-Z]+)(\d+)/).slice(1);
//[ colStart='D', rowStart='107', colEnd='F', rowEnd='114' ]
rowStart = parseInt(rowStart);
rowEnd = parseInt(rowEnd);
colStart = colStart.charCodeAt()-65;
colEnd = colEnd.charCodeAt()-65;
note that here, you may have columns like AA or ZZ so you may want to adapt the transformation of colStart and colEnd accordingly
then use map instead of for loop
let table = Array(colEnd-colStart+1).fill(0).map((_, j)=>{
return Array(rowEnd-rowStart+1).fill(0).map((_, i)=>{
let col = colStart + j;
let row = rowStart + i;
return sheet.cell(String.fromCharCode(col+65)+row).value();
})
})
Regarding AA or ZZ, below an algorithm to convert them back and forth to int, but once again probably rely on your library since it would have to parse your string anyway..
let sheet = {
cell(x){return {value(){return x}}}
}
//not used, but enough to handle single letters...
function toColIdx(s){
return s.charCodeAt()-'A'.charCodeAt();
}
function idxToCol(idx){
return String.fromCharCode(idx+'A'.charCodeAt())
}
let base = (function(){
let idxToChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
let charToIdx = idxToChar.reduce((acc, f,i)=>(acc[f] = i+1, acc),{})
//I have checked the identity of idxToCol == idxToCol(toColIdx(idxToCol)) up to 16384
return {
toColIdx(s){
return s.split('')
.reverse()
.reduce((acc,c,i)=>acc+charToIdx[c]*Math.pow(26,i),0);
},
idxToCol(idx){
if(idx==1)return 'A';
let n = Math.ceil(Math.log(idx)/Math.log(26));
s = '';
for(let i = 0; i<n; ++i){
let x = idx % 26;
if(x != 0){
s = idxToChar[x-1] + s;
idx-=x;
idx /= 26;
}else{
s = 'Z' + s;
idx-=26;
idx /= 26;
if(idx==0) return s;
}
}
return s;
}
}
})();
function extract(sheet, formula){
let [colStart, rowStart, colEnd, rowEnd] = formula.match(/([A-Z]+)(\d+):([A-Z]+)(\d+)/).slice(1);
//[ colStart='D', rowStart='107', colEnd='F', rowEnd='114' ]
rowStart = parseInt(rowStart);
rowEnd = parseInt(rowEnd);
colStart = base.toColIdx(colStart)
colEnd = base.toColIdx(colEnd)
return Array(colEnd-colStart+1).fill(0).map((_, j)=>{
return Array(rowEnd-rowStart+1).fill(0).map((_, i)=>{
let col = colStart + j;
let row = rowStart + i;
return sheet.cell(base.idxToCol(col)+row).value();
})
})
}
console.log(JSON.stringify(extract(sheet, 'A107:D114'),null,2))
console.log(JSON.stringify(extract(sheet, 'BZ107:CA114'),null,2))
Related
I've a task to write a program that creates a multiplication table for the given variable n.
The results need to be saved to a two-dimensional array. In the console I need to display the entire table with appropriate data formatting (as below). I'm starting with Javascript and already know loops and arrays only, I haven't learnt functions yet so I need some really basic solution.
This is how the result should look like:
Here is my code that I wrote so far and I don't know what to do next:
const n = 3;
const calc = []
for (let i = 1; i <= n; i++) {
for (let j = 1; j <= n; j++) {
calc.push(i + " * " + j + " = " + (i * j));
}
console.log(calc)
}
You're almost there:
Not sure that you need the array calc if your aim is to print the table
Define a new variable row inside the outer loop as an empty array, [];
In the inner loop, instead of calc.push, use row.push
After the inner loop, you have a complete row, which you can output using the array .join() method
If you need to, then add the row to calc with calc.push(row); not necessary in my view.
const n = 3;
//const calc = []; //may not be necessary
for (let i = 1; i <= n; i++) {
const row = [];
for (let j = 1; j <= n; j++) {
row.push(i + " x " + j + " = " + (i * j));
}
console.log( row.join(' | ') );
//calc.push(row);//not sure if you still need this
}
/* OUTPUT
1 x 1 = 1 | 1 x 2 = 2 | 1 x 3 = 3
2 x 1 = 2 | 2 x 2 = 4 | 2 x 3 = 6
3 x 1 = 3 | 3 x 2 = 6 | 3 x 3 = 9
*/
From the code you've presented, it appears that you're yet to understand what a 2d array really is. The way you've done it, everything's just stuffed into a single 1d array.
You may think of the pixels on a screen as being part of a 2d array. The first array holds all of the horizontal lines. The horizontal lines contain the pixels.
So.. let's concentrate on that part first.
let result = [];
for (var y=0; y<n; y++)
{
result.push( [] );
for (var x=0; x<n; x++)
{
result[y].push( (x+1) * (y+1) );
}
}
First we create a result array, and then for every row in our table, we add an array that will hold the columns, then for each column in that row, we add the values.
Next, we just step through that table and turn the values into the original equations. We start by ascertaining the dimensions of the array, before we create a table the same size.
function printTable( tbl )
{
let nRows = tbl.length;
let nCols = tbl[0].length;
for (var y=0; y<nRows; y++)
{
let rowStr = '';
for (var x=0; x<nCols; x++)
{
if (x!=0) rowStr += " | ";
rowStr += `${y+1} x ${x+1} = ${tbl[y][x]}`;
}
console.log(rowStr);
}
}
Chucking it all together, I present the following code. Yes, I know you're not using functions yet - but you can still see the important concepts. You can change it so that the whole equation for each entry in the table is saved, instead of just the answer.
window.addEventListener('load', init, false);
function init()
{
let result = makeMultTable(3);
printTable(result);
}
function makeMultTable(n)
{
let result = [];
for (var y=0; y<n; y++)
{
result.push( [] );
for (var x=0; x<n; x++)
{
result[y].push( (x+1) * (y+1) );
}
}
return result;
}
function printTable( tbl )
{
let nRows = tbl.length;
let nCols = tbl[0].length;
for (var y=0; y<nRows; y++)
{
let rowStr = '';
for (var x=0; x<nCols; x++)
{
if (x!=0) rowStr += " | ";
rowStr += `${y+1} x ${x+1} = ${tbl[y][x]}`;
}
console.log(rowStr);
}
}
Here is a short version of putting those multiplications into a 2D array:
const arr=[...Array(4)].map((_,i)=>i+1),
arr2=arr.map(i=>arr.map(j=>`${i}*${j}=${i*j}`));
console.log(arr2);
Multiplication of table in two dimension array
Function name: multiplyNumber
Syntex multiplyNumber(n)
n Number to be passed to function to create table upto that number.
Snippet
function multiplyNumber(n){
let table = [];
let data = [];
for (var i = 1; i <= n; i++){
for (var j = 1; j <= n; j++){
data.push(`${i} x ${j} = ${i * j}`);
}
table.push(data); // pushing data to table.
data = []; //Resetting data array to store new data each time.
}
return table;
}
var result = multiplyNumber(3);
console.log(result);
For every line I created an array line, filling it with the calculations. after the line loop I pushed it into calc.
const n = 3;
const calc = [];
for (let i = 1; i <= n; i++) {
const line = [];
for (let j = 1; j <= n; j++) {
line.push(i + " * " + j + " = " + (i * j));
}
calc.push(line);
}
console.log(calc);
This is just a snippet of my code from Google App Script which iterates through each row in columns 1, 2, 3. If an edit is made in column 3, an incremental ID will be generated and a concatenation of the same row and different columns will also be generated - in this case Column D, E, and F. I am struggling with figuring out a way to change the formulas into values. What am I missing here?
// Location format = [sheet, ID Column, ID Column Row Start, Edit Column]
var locations = [
["Consolidated Media Plan",1,9,3]
];
function onEdit(e){
// Set a comment on the edited cell to indicate when it was changed.
//Entry data
var range = e.range;
var col = range.getColumn();
var row = range.getRow();
// Location Data
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
function getNewID(){
function IDrange(){
var dataRange = sheet.getDataRange();
var lastRow = dataRange.getLastRow();
return sheet.getRange(IDrowStart,IDcol,lastRow-IDrowStart).getValues();
};
//Get largest Value in range
function getLastID(range){
var sorted = range.sort();
var lastIDval = sorted[sorted.length-1][0];
return lastIDval;
};
//Stores leading letters and zeroes and trailing letters
function getLettersNzeroes(id){
//Get any letters or zeroes.
var re = new RegExp("^([a-zA-Z0])$");
var letterZero = [];
for(char = 0; char < id.length; char++){
if(re.test(id[char])){
letterZero.push([char,id[char]]);// [[position, letter or zero]]
};
};
// Categorize letters and zeroes into start and end blocks
var startLetterZero = "",
endLetter = "",
len = letterZero.length - 1;
for(j = 0; j < letterZero.length; j++){
if(letterZero[j][0] === j){
startLetterZero += letterZero[j][1];
}else if(letterZero[j][1] !== "0" && letterZero[len][0] - (len - j) == letterZero[j][0]){
endLetter += letterZero[j][1];
};
};
var startNend = {"start":startLetterZero,"end":endLetter};
return startNend;
};
//Gets last id number. Adds 1 an checks to set if its new length is greater than the lastNumber.
function getNewNumber(id){
var removeZero = false;
var lastNum = parseInt(id.replace(/\D/g,''),10);//Remove letters
var newNum = (lastNum+1).toString();
if(lastNum.toString().length !== newNum.length){
var removeZero = true;
};
var newNumSet = {"num":newNum, "removeZero": removeZero};
return newNumSet
};
var lastID = getLastID(IDrange());
var lettersNzeroes = getLettersNzeroes(lastID);
var newNumber = getNewNumber(lastID);
//If the number is 9,99,999,9999 etc we need to remove a zero if it exists.
if(newNumber.removeZero === true && lettersNzeroes.start.indexOf("0") !== -1.0){
lettersNzeroes.start = lettersNzeroes.start.slice(0,-1);
};
//Rejoin everything together
var newID = lettersNzeroes.start +
newNumber.num +
lettersNzeroes.end;
return newID;
};
for(i = 0; i < locations.length; i++){
var sheetID = locations[i][0],
IDcol = locations[i][1],
IDrowStart = locations[i][2],
EditCol = locations[i][3];
var offset = IDcol - EditCol;
var cell = sheet.getActiveCell();
if(sheetID === sheet.getName()){
if(EditCol === col){
//ID Already Exists the editing cell isn't blank.
if(cell.offset(0,offset).isBlank() && cell.isBlank() === false){
var newID = getNewID();
cell.offset(0,offset).setValue(newID);
cell.offset(0,-1).setFormulaR1C1('=concatenate(R[0]C[-1],"_",INDEX(Glossary!K:K,MATCH(R[0]C[2],Glossary!J:J,0)))');
};
};
};
};
};
EDIT:
This is my full code, I have been unsuccessful with trying to retrieve just the values of the formula within the same (i.e, If C9 gets edited, a formula with the values specific to the 9th row should be populated)
Also, I've tried to add an index/match formula to the concatenation formula at the bottom of the code - it works as expected on the google sheets, but when I run it with the script it pastes the correct formula but it returns a #NAME? error message. However, when I copy and paste the exact same formula in the cell, it works perfectly, any idea what could be causing this error?
This works for me. I know it's not exactly the same thing but I didn't have access to getNewId()
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()!='Sheet1')return;
//e.source.toast('flag1');
if(e.range.columnStart==3 && e.range.offset(0,1).isBlank() && e.value) {
//e.source.toast('flag2');
e.range.offset(0,1).setValue(e.value);
e.range.offset(0,2).setFormulaR1C1('=concatenate(R[0]C[-1],"_",R[0]C[-2],"_",R[0]C[-3],"_",R[0]C[-4])');
}
}
I want to put an array of words inside a table thats filled with random letters.
I just want to be simple where the words are positioned horizontally so that children can easily find them.
Example of expected output:
o r a n g e a
d h j d k k t
b e e r g h k
w r t u i o p
a f t y u o j
My current code:
function randomWord() {
var cols = 5;
var rows = 5;
var html = "";
var words = ['apple', 'beer'],
for(var i =0; i <= rows; i++) {
html += '<tr>';
for(var h=0; h<= cols; h++) {
var characters = 'ABCDEFGHIJKLMNOPQRSTUVXYZ';
var random = parseInt(Math.random()*characters.length);
var letter = characters.charAt(random); //returning random letter
html += '<td>' + letter + '</td>';
}
html += '</tr>';
}
document.getElementById('wsBox').innerHTML += html;
}
HTML
<table>
<tbody id="wsBox">
</tbody>
</table>
<button onclick="randomWord()">Click me</button>
One approach would be to implement the following algrothim:
initalise a 2D array of randomised characters from your alphabet and, write the words to hide into the that 2D array directly
randomise the order of the rows in the 2D array, which will randomly distribute word placement throughout the rows of the resulting table
build the actual table from the 2D array data
In code this could be expressed as:
function randomWord() {
var cols = 5;
var rows = 5;
var words = ['apple', 'beer', 'cow'];
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVXYZ';
// Array to store all letters for resulting table
const data = [];
// Populate 2D-array with characters
for (var i = 0; i <= rows; i++) {
// Array to store letters for current row
const row = [];
// Populate this row with random letters
for (var h = 0; h <= cols; h++) {
const letterIdx = Math.floor(Math.random() * alphabet.length);
const letter = alphabet[letterIdx];
row.push(letter);
}
// While there are words to be read, insert those
if (words.length > 0) {
// Current word to insert
const word = words.pop();
// If there's space to horizontally offset the word, then
// caluclate a random offset. Add 1 because loop range is
// 0 < i <= col
const offsetIdx = Math.floor((1 + cols - word.length) * Math.random());
for (let i = 0; i < word.length; i++) {
if(i + offsetIdx < cols) {
// Write each letter of the word into the 2D-array
row[i + offsetIdx] = word[i];
}
}
}
data.push(row);
}
// Randomise the order of rows in the 2D-array
data.sort(() => Math.random() - 0.5);
const table = document.getElementById('wsBox');
// Clear the tablet
table.innerHTML = '';
// Iterate both dimensions of the table and build table from 2D-array
data.forEach((rowData, i) => {
const row = table.insertRow(i);
rowData.forEach((cellData, j) => {
const cell = row.insertCell(j);
cell.innerText = cellData;
})
});
}
<table>
<tbody id="wsBox">
</tbody>
</table>
<button onclick="randomWord()">Click me</button>
I'm trying to build a script in google sheets script that will iterate down a sheet, row by row, and if it encounters an ID number in the first cell of that row that is identical to the one above it, it strips out the data from every cell EXCEPT Column A and B, and appends it to the line above. Ideally, this would work with an indeterminate number of duplicate row IDs, might be 2, might be 3, might be 4.
After stripping out the data I want to keep (eg colums C and onward), I then want to delete the entire contents of the processed duplicate ID row, but I just haven't put that in my script until after it copies the data correctly.
In this example, sheet rows 6, 7 and 8 have identical ID numbers (Column A)
Here is the result I'm trying to get:
And here is the result I'm getting:
I've tried a number of different ways, and torn down and rebuilt my script a couple of times without getting the result I want:
function stripMiner() {
var ss = SpreadsheetApp.openById("1WDPoTICQvdruxfhAwHLtA51fz05DqyZ-NhNfpAyPO6Y");
var mainSheet = ss.getSheetByName("Main");
var startRow = 5;
var numRows = mainSheet.getLastRow();//obtains the last row in the sheet
var setrgh = mainSheet
var dataRange = mainSheet.getRange(startRow, 1,4,120); //rowStart, columnStart, row count, column count, the columncount needs to be large enough to encompass all your ancillary data
var data = dataRange.getValues();
var iter = 0;
var maxItRow = 4;
var prevIdNum = 0;
var dupCount = 1;
var cc1 = "P5"; //Cells to dump check values into
var cc2 = "P6";
var dumpRow = startRow;
//if (numRows >= maxItRow){var maxIter = maxItRow;}
for (i in data){
if (iter != maxItRow){ //making sure we haven't gone over the iteration limit
var row = data[i];
var idNum = (row[0]);
var jCount = 0; //resets icount if the id number is different icount is used to skip some cells in a row
if (idNum == prevIdNum){//only proceed if we've hit another line with the same ID number
dupCount = +1; //increment the dupcount value
mainSheet.getRange(cc2).setValue("dupCount"+dupCount); //dupcount check value
var rowIterStart = 5; //RowIterStart is used to add to rowiter, EG if your data is 20 columns wide, and you start transposing from column 4, then this will want to be about 17
var rowIter = 1;
for (j in row){
if (jCount >= 2){ //the integer here is the column where it will begin to transpose data
mainSheet.getRange(dumpRow-1,(rowIterStart*dupCount)+(rowIter)).setValue(row[j]); //startRow+(iter-dupCount)
mainSheet.getRange(cc1).setValue("dumprow"+dumpRow);
}
rowIter+=1;
jCount +=1;
}
}
else{
var dupCount = 1;
dumpRow +=1;
}
prevIdNum = (row[0]); //sets the most recently processed rows ID number
}
iter +=1;
}
}
I'm not quite sure where I'm going wrong. Does anyone have any suggestions? Thanks!
(Also I'm still just a beginner with this so if I've overlooked anything obvious or taken the wrong approach to do this, I apologize!)
The results for the questioner's code in the case of copied data arise from a convoluted loop. In essence, though duplicates were identified, there was a mis-counting to assign the copied data to the correct rowID. So far as clearing data, no provision was included.
The following code works to meet the questioner's goals, though it is far from perfect.
At present, the recalculation of the "last column" after copy each duplicate is an absolute rather than than a row-based figure. So, if a duplicate was detected for, say, ID=3, the data would be copied to column 12 rather than column 6. This requires the addition of a simple dupID row counter.
The second factor is the calculation of the last column in the spreadsheet.
var dataRange = mainSheet.getRange(startRow, 1,Rowlast+1,120);
The questioner used 120 columns; and I have retained that number simply for the sake of consistency. The questioner should re-assess whether this is excessive.
function ejb_so_5284922701() {
var ss = SpreadsheetApp.openById("<< insert questioners spreadsheet ID>>");
var mainSheet = ss.getSheetByName("<< insert questioner's sheet name >>");
var startRow = 5;
// calculate the last row containing data
var Rowvals = ss.getRange("A5:A").getValues();
var Rowlast = Rowvals.filter(String).length; //6
Logger.log("last row = " + Rowlast); // DEBUG
// calculate the last column containing data
var cell = mainSheet.getRange("A5"); //or however you determine "cell"
var drCol = mainSheet.getDataRange().getLastColumn();
Logger.log('getLastColumn = ' + drCol); //DEBUG
for (var i = drCol; i >= 1; i--) {
if (mainSheet.getRange(cell.getRow(), i).getValue() != "") {
break;
}
}
var lastColumn = i;
Logger.log("Last column with data = " + lastColumn); //DEBUG
var setrgh = mainSheet
// numColumns neds to be reviewed
var dataRange = mainSheet.getRange(startRow, 1, Rowlast + 1, 120); //rowStart, columnStart, row count, column count, the column count needs to be large enough to encompass all your ancillary data
// start row = 5, 1= column A, 4, rows, 120, columns
Logger.log("startRow = " + startRow + ", and the datarange = " + dataRange.getA1Notation()); //DEBUG
var data = dataRange.getValues();
Logger.log("length of data =" + data.length); //DEBUG
var lastid = 0;
for (i = 0; i < data.length; i++) {
if (i == 0) {
// if this is the first row, then assign anything but zero to last id
lastid = 100;
Logger.log(" this is the first row; set last id to 100");
}
var thisid = data[i][0];
// evaluate whether this is a duplicate ID
if (thisid == lastid) {
// this is a dup
Logger.log("i=" + i + ". This is a dup" + ", name is " + data[i][2]); //DEBUG
var stufftocopyrange = mainSheet.getRange(startRow + i, 3, 1, 3);
var stufftocopy = stufftocopyrange.getValues();
Logger.log("the range to copy is " + stufftocopyrange.getA1Notation()); //DEBUG
var targetrange = mainSheet.getRange(startRow + lastid - 1, lastColumn + 1, 1, 3);
targetrange.setValues(stufftocopy);
lastColumn = lastColumn + 3;
var duprange = mainSheet.getRange(startRow + i, 1, 1, 5);
Logger.log("the range to clear is " + duprange.getA1Notation()); //DEBUG
duprange.clearContent();
} else {
// no dup
//assign lastid value
var lastid = thisid;
Logger.log("i=" + i + ". No dup. Last id set to " + lastid); // DEBUG
} // if
} // end for loop
}
BEFORE
AFTER
The solutions previously posted didn't quite get the result I needed, however I managed to cobble together something that works for my purposes. It expects to see data in the format like:
And turn it into something like this:
Where it uses duplicate ID numbers (with an indeterminite number of duplicates) to pull only certain columns of data from the duplicate lines and append it to the first line.
function stripMiner() {
var ss = SpreadsheetApp.openById("1WDPoTICQvdruxfhAwHLtA51fz05DqyZ-NhNfpAyPO6Y");
var mainSheet = ss.getSheetByName("Main");
var startRow = 5;
var numRows = mainSheet.getLastRow();//obtains the last row in the sheet
var setrgh = mainSheet
var dataRange = mainSheet.getRange(startRow, 1,3,120); //rowStart, columnStart, row count, column count, the columncount needs to be large enough to encompass all your ancillary data
var data = dataRange.getValues();
var iter = 0;
var maxItRow = 4;
var prevIdNum = 0;
var dupCount = 1;
var cc1 = "P5"; //Cells to dump check values into
var cc2 = "P6";
var dumpRow = startRow;
//if (numRows >= maxItRow){var maxIter = maxItRow;}
for (i in data){
if (iter != maxItRow){ //making sure we haven't gone over the iteration limit
var row = data[i];
var idNum = (row[0]);
var jCount = 0; //resets icount if the id number is different icount is used to skip some cells in a row
if (idNum == prevIdNum){//only proceed if we've hit another line with the same ID number
dupCount = +1; //increment the dupcount value
mainSheet.getRange(cc2).setValue("dupCount"+dupCount); //dupcount check value
var rowIterStart = 5; //RowIterStart is used to add to rowiter, EG if your data is 20 columns wide, and you start transposing from column 4, then this will want to be about 17
var rowIter = 1;
for (j in row){
if (jCount >= 2){ //the integer here is the column where it will begin to transpose data
mainSheet.getRange(dumpRow-2,(rowIterStart*dupCount)+(rowIter)).setValue(row[j]); //startRow+(iter-dupCount)
mainSheet.getRange(cc1).setValue("dumprow"+dumpRow);
}
rowIter+=1;
jCount +=1;
}
}
else{
var dupCount = 1;
dumpRow +=1;
}
prevIdNum = (row[0]); //sets the most recently processed rows ID number
}
iter +=1;
}
}
Hopefully someone else who wants to do a similar thing can make use of this too.
I am trying to create a multi dimensional array based off of the calculations of another 3D array.
Input array is in format [shift, start Num, end num]
I should be clear the "," is just for visual purposes.
I need each value in its own array location i.e. [value1]=location 0,0 [value2]=location 0,1 [value3]=location 0,2 etc.
Example:
aInput looks like this
[0,1,5]
[1,1,3]
[2,1,2]
aOutput should look like this
[1,1,1]
[1,1,2]
[1,2,1]
[1,2,2]
[1,3,1]
[1,3,2]
[2,1,1]
[2,1,2]
[2,2,1]
[2,2,2]
[2,3,1]
[2,3,2]
[1,3,2]
[3,1,1]
[3,1,2]
[3,2,1]
[3,2,2]
[3,3,1]
[3,3,2]
[etc]
It needs to increase the number of items in the array based on the shift. i.e 0 = shift would be 1 column, shift = 1 would be 2 columns, shift = 3 would be 3 columns, and so on. This is what I have so far, but I can not figure out how to make it calculate for anything with a shift.
var aInput = new Array();
aInput[0] = new Array("0", "1","5");
aInput[1] = new Array("1", "1","3");
aInput[2] = new Array("2", "1","2");
for (var x=0; x < aInput[x].length; x++){
//Calculate out number
if (aInput[x][0] == 0){ // Im sure this should be a loop of some sort, just not sure how to do it
var i=Number(aInput[x][1]);
while (i <= Number(aInput[x][2])){
//Write to output array
aOutput.push(i);
i++;
}
}
}
Thanks in advance for any help, I'm really stumped on this one.
var aInput = new Array();
aInput[0] = new Array("0", "1", "5");
aInput[1] = new Array("1", "1", "3");
aInput[2] = new Array("2", "1", "2");
var input_indexed = [],
elem = []; // elem holds the row to be added to the output
// Get aInput[] into a more useful arrangement
for (var i = 0; i < aInput.length; i++) {
// Save the range of each column
input_indexed[parseInt(aInput[i][0])] = {
start: parseInt(aInput[i][1]),
end: parseInt(aInput[i][2])
};
// Initialize elem with the start value of each column
elem[aInput[i][0]] = parseInt(aInput[i][1]);
}
// Produce the output
aOutput = [];
done = false;
while (!done) {
aOutput.push(elem.slice(0)); // push a copy of elem into result
for (i = elem.length - 1;; i--) { // Increment elements from right to left
if (i == -1) { // We've run out of columns
done = true;
break;
}
elem[i]++; // Increment the current column
if (elem[i] <= input_indexed[i].end) {
// If it doesn't overflow, we're done
break;
}
// When it overflows, return to start value and loop around to next column
elem[i] = input_indexed[i].start;
}
}
FIDDLE
var aOutput = [];
for (var i in aInput) {
var y = parseInt(aInput[i][1])
for (var x = y; x <= parseInt(aInput[i][2]); x++) {
aOutput.push([i, y, x]);
}
}