I have a script that collects and updates data from a number of individual sheets and also a central master sheet. An individual sheet might contain 30 rows, whereas a master sheet will contain all the rows in all the sheets.
An individual sheet might contain a formula, say =A2+B2. On the individual sheet this formula is on row 2 but on the master sheet the formula might be in row 400. So that the formula works and yields correct data in the master sheet, the formula needs to be changed to =A400+B400.
I've tried to make this work by looking for cell references in a string that are delimited by an alphabetical character at the start, followed by one or more numbers and a space or a symbol at the end, iterating through and replacing every series of numerical characters that matches that condition with the new number value. With limited success.
Below is my attempts at this so far.
function isNumeric(n)
{
return !isNaN(parseFloat(n)) && isFinite(n);
}
function isAlpha(character)
{
if ((character.charCodeAt(0) >= 65 && character.charCodeAt(0) <= 90) ||(character.charCodeAt(0)>=97 && character.charCodeAt(0)<=122))
{
return true;
}
else
{
return false;
}
}
function correctFormula(formulaValue, destinationRow)
{
//parse through the string and identify cell references eg A2, AI77. (One or more consecutive letters followed by one or more consecutive numbers.
//Letters will never change but numbers will corresspond to the row in the array.
//ignore any text enclosed by ""
//ignore any text that does not start with =
var strFormulaValue = String(formulaValue);
if(strFormulaValue.charAt(0) === "=")
{
var i = 1;
var inQuotes = false;
var cellRef="";
var originalLength = strFormulaValue.length;
while (i<originalLength)
{
if (strFormulaValue.charAt(i)==="\"" || strFormulaValue.charAt(i)==="\'")
{
if (inQuotes)
{
inQuotes = false;
}
else
{
inQuotes = true;
}
}
if (strFormulaValue.charAt(i)==="!")
{
//this is a cell ref to another sheet. Get to the end of this ref
while((isAlpha(strFormulaValue.charAt(i)))||isNumeric(strFormulaValue.charAt(i)))
{
i++;
}
}
if (isNumeric(strFormulaValue.charAt(i)) &&(!inQuotes))
{
if(isAlpha(strFormulaValue.charAt(i - 1)))
{
//this looks like it could be the start of a cell ref
var numStart = i;
var numEnd = -1;
//find the last numerical digit in this sequence
while (isNumeric(strFormulaValue.charAt(i)))
{
if (isNumeric(strFormulaValue.charAt(i)))
{
numEnd = i;
}
i++
}
if ((!isAlpha(strFormulaValue.charAt(i)))||(i>=strFormulaValue.length))//if the sequence of numeric digits ends as a or the number digit was the last char in the string
{
//replace this string of numeric digits with the desired digits
var formulaStart = strFormulaValue.substring(0, numStart);
var formulaEnd = strFormulaValue.substring(numEnd + 1, strFormulaValue.length);
strFormulaValue = formulaStart+ String(destinationRow)+formulaEnd;
}
}
}
i++;
}
return strFormulaValue;
}
}
function testStrToFormula(stringval)
{
Logger.log ("Inputting =A12, should convert to A1000");
Logger.log (correctFormula("=A12", 1000));
Logger.log ("Inputting =A12 + B12, should convert to A1000 + B1000");
Logger.log (correctFormula("=A12 + B12 ", 1000));
Logger.log ("Inputting =sum(A12:D12), should convert to =sum(A1000:D1000)");
Logger.log (correctFormula("=sum(A12:D12)", 1000));
Logger.log("Inputting = A12 & \"D3\"");
Logger.log(correctFormula("=A12 & \"D3\""));
Logger.log("Inputting =Sheet1!A1 * B1")
Logger.log (correctFormula("=Sheet1!A1 * B1"))
}
This logs
[18-03-01 17:36:34:853 GMT] Inputting =A12, should convert to A1000
[18-03-01 17:36:34:854 GMT] =A1000
[18-03-01 17:36:34:854 GMT] Inputting =A12 + B12, should convert to A1000 + B1000
[18-03-01 17:36:34:855 GMT] =A1000 + B1000
[18-03-01 17:36:34:856 GMT] Inputting =sum(A12:D12), should convert to =sum(A1000:D1000)
[18-03-01 17:36:34:858 GMT] =sum(A1000:D1000)
[18-03-01 17:36:34:859 GMT] Inputting = A12 & "D3"
[18-03-01 17:36:34:860 GMT] =Aundefined & "D3"
[18-03-01 17:36:34:861 GMT] Inputting =Sheet1!A1 * B1
[18-03-01 17:36:34:862 GMT] =Sheetundefined!A1 * B1
Not sure why I'm getting undefined in the middle of the string when I'm dealing with values in quotes or references to cells in other sheets. (References to cells on other sheets should not be altered)