Как вычислить выражение, данное в строке? JS - PullRequest
1 голос
/ 09 июля 2020

Я экспортировал большую электронную таблицу Excel как html и хочу вычислить значения некоторых ячеек в JavaScript. Я протащил выражения, используемые в excel, в качестве информации data-xxx в каждом PI, который намеревается заполнить.

Есть ли способ перевести data-xxx в код JavaScript, чтобы он дал мне желаемое значение ?

Примеры строк:

06A02
min(06C02;06C03)
max(03B04;03B05;03B06)
max(min(07A01;07A02;08F01);min(09A01;09A02))
max(min(03B01;03B02;03B03);08C02;09B01;09C02)
max(min(07A03;07A04;08F02);min(09A03;09A04);09C02)
max(09B05;min(07A01;07A02;08F01);min(09A01;09A02))
max(09B05;min(07A03;07A04;08F02);min(09A03;09A04);09B01;09C02)

06A02 и аналогичные - это просто ключи значений, хранящиеся в localStorage, сохраненные через форму другой страницы.

Я думал, что могу просто используйте if s и else s и разрежьте строку по частям, но в результате получится гигантское дерево, в котором я могу сделать слишком много ошибок.

Я подумал о регулярных выражениях, чтобы сократить дерево, но Я не уверен, что это намного лучше.

Возможно, есть способ, которого я еще не знаю.

Пример HTML:

<TR>
<TD>Prolonged lack of access...</TD>
<TD>A</TD>
<TD>A</TD>
<TD><p id="ar1_11e" data-eks="AC.E.Inc"></p></TD>
<TD>1</TD>
<TD><p id="ar1_11za" data-zap="03D01"></p></TD>
<TD><p id="ar1_11i" data-imp="ar1"></p></TD>
<TD><p id="ar1_11og" data-ogr="min(03D02;03D03)"></p></TD>
<TD><p id="ar1_11la" data-lag="04A05"></p></TD>
<TD><p id="Par1_11"></p></TD>
<TD><p id="War1_11"></p></TD>
<TD><p id="Rar1_11"></p></TD>
<TD><p id="Oar1_11"></p></TD>
</TR>

Ответы [ 2 ]

3 голосов
/ 09 июля 2020

@ hev1 предоставил отличное решение. Если вы хотите использовать регулярное выражение, вы можете сделать что-то вроде этого:

function evalExcel(rawString) {
  // match expected format, prevent easy eval injection
  const safeMatch = /^(min|max|[();]|[A-F0-9]{5})*$/;

  if (rawString.match(safeMatch) && window.localStorage) {
    const regexNum = /[A-F0-9]{5}/g;
    const jsCode = rawString.replace(/;/g, ", ")
      .replace(/min/g, "Math.min")
      .replace(/max/g, "Math.max")
      .replace(regexNum, "+localStorage.getItem(\"$&\")");
    return eval(jsCode);
  }
  return null;
}

Demo

1 голос
/ 09 июля 2020

Вы можете использовать простую рекурсивную внутреннюю функцию.

function getValue(str){
    let idx = 0;
  function helper(){
    let op = Math[str.slice(idx,idx+3)];
    let opened = 1, closed = 0;
    let args = [];
    for(idx += 3; idx < str.length && opened != closed; idx++){
        if(str.indexOf("min", idx) == 0 || str.indexOf("max", idx) == 0){
        args.push(helper());
      } else {
        let delimIdx = str.indexOf(";", idx);
        if(delimIdx != -1){
            args.push(+localStorage.getItem(str.slice(idx, delimIdx)));
        } else {
            args.push(+localStorage.getItem(str.slice(idx,str.indexOf(')', idx))));
        }
      }
    }
    return op(...args);
  }
  return str.startsWith("min") || str.startsWith("max") ? helper(): +localStorage.getItem(str);
}

Demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...