実際はgas内で完結するようなものにしたかったのですが、なかなか難しそうだったので、スプレッドシートを介する方法でコードを書いてみました。引き続きわかる方は教えていただきたいです。
まず実際やりたいのは次のとおりです。
GAS
1 let a = 3;
2 let b = "+ 3 ) / 2";
3 let d = ( a + b; //(3+3)/2のように、変数内の数式を別の数式内に組み込んで計算したい
4 Logger.log(d); //3
最終的に作ってみたコードが下のとおりです。(実際の使い方に当てはめて書いているので、本題と関係ない要素もありますがコードはこのままでも使えます。)
{前提: /< 切り上げ, /< 切り下げ, /_ 四捨五入}
GAS
1 const ss = SpreadsheetApp.getActiveSpreadsheet();
2 const sh4 = ss.getActiveSheet();
3 function a(){
4 let result = 13
5 let calculation = "( 120 - ( number * 3 ) ) /< ( 2 + 2 ) - 3"; //実際は利用者にシートのセルに書き込んでもらう
6 let element = calculation.split(" ");
7 let verification = 0;
8 for(let i = 0; i <= element.length; i++){
9 if(element[i] == "number"){
10 element[i] = result;
11 verification += 1;
12 }
13 }
14 if(verification == 0){
15 let title = "抽出番号の挿入位置が未設定か、各演算子・数値間に半角スペースが入力されていない可能性があります。";
16 let message = "処理を中断し、数式を入力し直しますか?";
17 let warning = Browser.msgBox(title, message, Browser.Buttons.YES_NO);
18 if(warning == "YES"){
19 let exampleTitle = "抽出番号の挿入位置に「number」と記入し、負数の符号と数値以外の演算子・数値間に半角スペースを入力";
20 let example = "例: 15 + ( ( 15 * ( -13 + number ) ) / 2 - 3 ) ** 2";
21 Browser.msgBox(exampleTitle, example, Browser.Buttons.OK);
22 return
23 }
24 }
25 for(let i = 0; i <= element.length; i++){
26 if(element[i] == "/<"){
27 let {formulaArray, numFormula, roundNumber} = round(element, i);
28 let formula = "ROUNDUP(" + numFormula + ")";
29 formulaArray[roundNumber] = formula;
30 element = formulaArray;
31 }
32 if(element[i] == "/>"){
33 let {formulaArray, numFormula, roundNumber} = round(element, i);
34 let formula = "ROUNDDOWN(" + numFormula + ")";
35 formulaArray[roundNumber] = formula;
36 element = formulaArray;
37 }
38 if(element[i] == "/_"){
39 let {formulaArray, numFormula, roundNumber} = round(element, i);
40 let formula = "ROUND(" + numFormula + ")";
41 formulaArray[roundNumber] = formula;
42 element = formulaArray;
43 }
44 }
45 let formulaContent = element.join("");
46 Logger.log(formulaContent);
47 let sheetFormula = "=" + formulaContent;
48 Logger.log(sheetFormula);
49 sh4.getRange("V2").setFormula(sheetFormula);
50 let calculationResult = sh4.getRange("V2").getDisplayValue();
51 Logger.log(calculationResult);
52 return calculationResult;
53 }
54
55 function round(element ,i){
56 let formulaArray = element;
57 if(element[i-1] == ")"){
58 for(let j = 0; j <= i - 2; j--){
59 let parenthese = 1;
60 if(element[j] == ")"){
61 parenthese += 1;
62 }
63 if(element[j] == "("){
64 parenthese -= 1;
65 }
66 if(parenthese == 0){
67 var frontStart = j;
68 var frontEnd = i - 1;
69 break
70 }
71 }
72 }
73 else{
74 var frontStart = i - 1;
75 var frontEnd = i - 1;
76 }
77 if(element[i+1] == "("){
78 for(let j = i + 2; j <= element.length; j++){
79 let parenthese = 1;
80 if(element[j] == "("){
81 parenthese += 1;
82 }
83 if(element[j] == ")"){
84 parenthese -= 1;
85 }
86 if(parenthese == 0){
87 var backStart = i + 1;
88 var backEnd = j;
89 break
90 }
91 }
92 }
93 else{
94 var backStart = i + 1;
95 var backEnd = i + 1;
96 }
97 let front = "";
98 for(let k = frontStart; k <= frontEnd; k++){
99 front += formulaArray[k];
100 }
101 formulaArray.splice(frontStart, frontEnd + 1);
102 let back = "";
103 for(let l = backStart - frontEnd - 1; l <= backEnd - frontEnd - 1; l++){
104 back += formulaArray[l];
105 }
106 formulaArray.splice(backStart - frontEnd - 1, backEnd - frontEnd - 1);
107 let roundNumber = backStart - frontEnd - 2;
108 let numFormula = front + "/" + back;
109 return {formulaArray, numFormula, roundNumber}
110 }
この方法が嫌な理由は
ご覧の通りfor文if文を多用してややこしいし処理に時間がかかる
途中でスプレッドシートに一旦書き込んでからまた取得しないといけない
です。