使用JavaScript基于HTML表的选定行,动态计算每列的总数

发布于 2025-01-23 13:08:14 字数 2742 浏览 2 评论 0原文

“

从图片中,我试图计算所选行A和c的每列总数。如果我将其从函数计算中解开,则代码有效。是否可以使其在包装功能中起作用。我希望能够选择一个行的变体来对每列的总和,而无需复制和粘贴代码并为每个列进行多次编辑。

function calculateCols(ID, calculate) {
  var final = 0
  var tbody = document.querySelector('tbody');
  var howManyCols = tbody.rows[0].cells.length;
  var totalRow = document.getElementById(ID);

  for (var j = 1; j < howManyCols; j++) {
    final = calculate;
    const check = document.createElement('td');
    check.innerText = final;
    totalRow.appendChild(check);
  }

  function getRow(rowID) {

    var result = 0;

    try {
      var check = document.getElementById(rowID)
      var thisNumber = parseInt(check.cells[j].childNodes.item(0).data);

      if (!isNaN(thisNumber))
        result += thisNumber;

    } finally {
      return result;
    }
  }

}

calculateCols('total', getRow('a') + getRow('c'));
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <tbody>
      <tr>
        <td></td>
        <th scope="col">2013</th>
        <th scope="col">2014</th>
        <th scope="col">2015</th>
        <th scope="col">2016</th>
      </tr>
      <tr id="a">
        <th scope="row">a</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr id="b">
        <th scope="row">b</th>
        <td>5</td>
        <td>6</td>
        <td>4</td>
        <td>5</td>
      </tr>
      <tr id="c">
        <th scope="row">c</th>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
      </tr>
      <tr id="d">
        <th scope="row">d</th>
        <td>5</td>
        <td>6</td>
        <td>8</td>
        <td>5</td>
      </tr>

      <tr id="total">
        <th scope="row" id="Total">Total a + c</th>

      </tr>
    </tbody>
  </table>
  <script src="checkit.js"></script>

</body>

</html>

html table

From the picture, I am trying to calculate the total of each column for the selected rows a and c. The code works if I unwrap it from the function calculateCols. Is it possible to make it work in the wrapped function. I want to be able to choose a variation of rows to sum for each column without copy and pasting the code and editing it multiple times for each one.

function calculateCols(ID, calculate) {
  var final = 0
  var tbody = document.querySelector('tbody');
  var howManyCols = tbody.rows[0].cells.length;
  var totalRow = document.getElementById(ID);

  for (var j = 1; j < howManyCols; j++) {
    final = calculate;
    const check = document.createElement('td');
    check.innerText = final;
    totalRow.appendChild(check);
  }

  function getRow(rowID) {

    var result = 0;

    try {
      var check = document.getElementById(rowID)
      var thisNumber = parseInt(check.cells[j].childNodes.item(0).data);

      if (!isNaN(thisNumber))
        result += thisNumber;

    } finally {
      return result;
    }
  }

}

calculateCols('total', getRow('a') + getRow('c'));
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <tbody>
      <tr>
        <td></td>
        <th scope="col">2013</th>
        <th scope="col">2014</th>
        <th scope="col">2015</th>
        <th scope="col">2016</th>
      </tr>
      <tr id="a">
        <th scope="row">a</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr id="b">
        <th scope="row">b</th>
        <td>5</td>
        <td>6</td>
        <td>4</td>
        <td>5</td>
      </tr>
      <tr id="c">
        <th scope="row">c</th>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
      </tr>
      <tr id="d">
        <th scope="row">d</th>
        <td>5</td>
        <td>6</td>
        <td>8</td>
        <td>5</td>
      </tr>

      <tr id="total">
        <th scope="row" id="Total">Total a + c</th>

      </tr>
    </tbody>
  </table>
  <script src="checkit.js"></script>

</body>

</html>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情绪失控 2025-01-30 13:08:14

这应该做到:

function rpn(inps, D, i) { // Reverse Polish Notation calculator
  const st = [];
  inps.split(/\s+/).forEach(t => {
    let k = st.length - 2; // index of penultimate element on stack
    if (!isNaN(t)) st.push(+t);
    else switch (t) {
      case "+": st[k] += st.pop(); break;
      case "-": st[k] -= st.pop(); break;
      case "*": st[k] *= st.pop(); break;
      case "/": st[k] /= st.pop(); break;
      case "**": st[k] = st[k] ** st.pop(); break;
      default: st.push(+D[t][i]) // treat current value t as a "variable name" --> D[t][i]
    }
  });
  return st.pop()
}
// sample use (Pythagoras's theorem): rpn("3 2 ** 4 2 ** + .5 **") // = 5

// get all table data into D first:
  const D = [...document.querySelectorAll("tr[id]")].reduce((da, tr) => {
      da[tr.id] = [...tr.children].slice(1).map(td => +td.textContent);
      return da;
    }, {});
  document.querySelectorAll("tr[data-eqn]").forEach(tr =>
    [...tr.children].slice(1).forEach((td,k)=>
      td.textContent=rpn(tr.dataset.eqn, D, k).toFixed(4).replace(/\.?0*$/,"")));
td,th {text-align: right; padding:4px}
td    {border:1px solid grey}
table {border-collapse:collapse}
<table id="tbl">
  <tbody>
    <tr>
      <th></th>
      <th scope="col">2013</th>
      <th scope="col">2014</th>
      <th scope="col">2015</th>
      <th scope="col">2016</th>
    </tr>
    <tr id="a">
      <th scope="row">a</th>
      <td>1</td><td>2</td><td>3</td><td>4</td>
    </tr>
    <tr id="b">
      <th scope="row">b</th>
      <td>5</td><td>6</td><td>4</td><td>5</td>
    </tr>
    <tr data-eqn="a 2 ** b 2 ** + .5 **">
      <th scope="row">sqrt(a²+b²)</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr id="c">
      <th scope="row">c</th>
      <td>4</td><td>5</td><td>6</td><td>7</td>
    </tr>
    <tr id="d">
      <th scope="row">d</th>
      <td>5</td><td>6</td><td>8</td><td>5</td>
    </tr>
    <tr data-eqn="2 a * d + c -">
      <th scope="row">2a + d - c</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="a b - a b + / c *">
      <th scope="row">(a - b) / (a + b) * c</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="b c /">
      <th scope="row">b/c</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="a b +">
      <th scope="row">a + b</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="c b +">
      <th scope="row">c + b</th>
      <td></td><td></td><td></td><td></td>
    </tr>
  </tbody>
</table>

我再次完全更改了答案:操作的中心部分现在是RPN计算器(函数rpn()),它贯穿了data-eqn属性提供的指令字符串。所有这些都确定的结果 - &lt; tr&gt; s。

在计算开始之前,我在全局对象d中收集所有提供的表数据。所有tr s都带有id -Attribute将其td.td.td.textcontent贡献到变为属性d [id] 。 d最终是数组的对象。

[[目前的结果限制为3位数字。可以再次删除。tofixed(3)可以轻松地关闭这。 ]]]]

This should do it:

function rpn(inps, D, i) { // Reverse Polish Notation calculator
  const st = [];
  inps.split(/\s+/).forEach(t => {
    let k = st.length - 2; // index of penultimate element on stack
    if (!isNaN(t)) st.push(+t);
    else switch (t) {
      case "+": st[k] += st.pop(); break;
      case "-": st[k] -= st.pop(); break;
      case "*": st[k] *= st.pop(); break;
      case "/": st[k] /= st.pop(); break;
      case "**": st[k] = st[k] ** st.pop(); break;
      default: st.push(+D[t][i]) // treat current value t as a "variable name" --> D[t][i]
    }
  });
  return st.pop()
}
// sample use (Pythagoras's theorem): rpn("3 2 ** 4 2 ** + .5 **") // = 5

// get all table data into D first:
  const D = [...document.querySelectorAll("tr[id]")].reduce((da, tr) => {
      da[tr.id] = [...tr.children].slice(1).map(td => +td.textContent);
      return da;
    }, {});
  document.querySelectorAll("tr[data-eqn]").forEach(tr =>
    [...tr.children].slice(1).forEach((td,k)=>
      td.textContent=rpn(tr.dataset.eqn, D, k).toFixed(4).replace(/\.?0*$/,"")));
td,th {text-align: right; padding:4px}
td    {border:1px solid grey}
table {border-collapse:collapse}
<table id="tbl">
  <tbody>
    <tr>
      <th></th>
      <th scope="col">2013</th>
      <th scope="col">2014</th>
      <th scope="col">2015</th>
      <th scope="col">2016</th>
    </tr>
    <tr id="a">
      <th scope="row">a</th>
      <td>1</td><td>2</td><td>3</td><td>4</td>
    </tr>
    <tr id="b">
      <th scope="row">b</th>
      <td>5</td><td>6</td><td>4</td><td>5</td>
    </tr>
    <tr data-eqn="a 2 ** b 2 ** + .5 **">
      <th scope="row">sqrt(a²+b²)</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr id="c">
      <th scope="row">c</th>
      <td>4</td><td>5</td><td>6</td><td>7</td>
    </tr>
    <tr id="d">
      <th scope="row">d</th>
      <td>5</td><td>6</td><td>8</td><td>5</td>
    </tr>
    <tr data-eqn="2 a * d + c -">
      <th scope="row">2a + d - c</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="a b - a b + / c *">
      <th scope="row">(a - b) / (a + b) * c</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="b c /">
      <th scope="row">b/c</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="a b +">
      <th scope="row">a + b</th>
      <td></td><td></td><td></td><td></td>
    </tr>
    <tr data-eqn="c b +">
      <th scope="row">c + b</th>
      <td></td><td></td><td></td><td></td>
    </tr>
  </tbody>
</table>

I changed my answer completely again: The centre piece of the operation is now an RPN calculator (function rpn()) that goes through instructions strings provided by data-eqn attributes in all so identified result-<tr>s.

Before the calculation can start I collect all provided table data in a global object D. All trs with an id-attribute contribute their td.textContent to a vector which becomes property D[id]. D ends up being an object of arrays.

[[ Currently the results are limited to 3 digits. This can easily be switched off by removing .toFixed(3) again. ]]

眼泪淡了忧伤 2025-01-30 13:08:14
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <tbody>
      <tr>
        <td></td>
        <th scope="col">2013</th>
        <th scope="col">2014</th>
        <th scope="col">2015</th>
        <th scope="col">2016</th>
      </tr>
      <tr id="a">
        <th scope="row">a</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr id="b">
        <th scope="row">b</th>
        <td>5</td>
        <td>6</td>
        <td>4</td>
        <td>5</td>
      </tr>
      <tr id="c">
        <th scope="row">c</th>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
      </tr>
      <tr id="d">
        <th scope="row">d</th>
        <td>5</td>
        <td>6</td>
        <td>8</td>
        <td>5</td>
      </tr>

      <tr id="total">
        <th scope="row" id="Total"></th>
      </tr>
    </tbody>
  </table>
  <script>
    function toIntOrZero(value) {
      let toInt = parseInt(value);
      return !isNaN(toInt) ? toInt : 0;
    }

    function getRowValues(rowID) {
      let children = document.getElementById(rowID).children;
      let values = [];
      for (let i = 1; i < children.length; i++) {
        values.push(toIntOrZero(children[i].innerText));
      }
      return values;
    }

    function getRows(rowIds) {
      return rowIds.map(id => getRowValues(id));
    }

    function calculateColSums(array) {
      return array.reduce(function (r, a) {
        a.forEach(function (b, i) {
          r[i] = (r[i] || 0) + b;
        });
        return r;
      }, []);
    }

    function appendResults(results, rowIds) {
      document.getElementById('Total').innerHTML = 'Total of ' + rowIds.join();
      var tableTotalRow = document.querySelector('tbody > #total');
      var totalColumns = document.querySelector('tbody').rows[0].cells.length;
      for (var j = 1; j < totalColumns; j++) {
        const colSum = document.createElement('td');
        colSum.innerText = results[j - 1];
        tableTotalRow.appendChild(colSum);
      }
    }

    function calculateSumOfSelectedRows(rowIds) {
      appendResults(calculateColSums(getRows(rowIds)), rowIds);
    }

    calculateSumOfSelectedRows(['b', 'd']);
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <tbody>
      <tr>
        <td></td>
        <th scope="col">2013</th>
        <th scope="col">2014</th>
        <th scope="col">2015</th>
        <th scope="col">2016</th>
      </tr>
      <tr id="a">
        <th scope="row">a</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr id="b">
        <th scope="row">b</th>
        <td>5</td>
        <td>6</td>
        <td>4</td>
        <td>5</td>
      </tr>
      <tr id="c">
        <th scope="row">c</th>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
      </tr>
      <tr id="d">
        <th scope="row">d</th>
        <td>5</td>
        <td>6</td>
        <td>8</td>
        <td>5</td>
      </tr>

      <tr id="total">
        <th scope="row" id="Total"></th>
      </tr>
    </tbody>
  </table>
  <script>
    function toIntOrZero(value) {
      let toInt = parseInt(value);
      return !isNaN(toInt) ? toInt : 0;
    }

    function getRowValues(rowID) {
      let children = document.getElementById(rowID).children;
      let values = [];
      for (let i = 1; i < children.length; i++) {
        values.push(toIntOrZero(children[i].innerText));
      }
      return values;
    }

    function getRows(rowIds) {
      return rowIds.map(id => getRowValues(id));
    }

    function calculateColSums(array) {
      return array.reduce(function (r, a) {
        a.forEach(function (b, i) {
          r[i] = (r[i] || 0) + b;
        });
        return r;
      }, []);
    }

    function appendResults(results, rowIds) {
      document.getElementById('Total').innerHTML = 'Total of ' + rowIds.join();
      var tableTotalRow = document.querySelector('tbody > #total');
      var totalColumns = document.querySelector('tbody').rows[0].cells.length;
      for (var j = 1; j < totalColumns; j++) {
        const colSum = document.createElement('td');
        colSum.innerText = results[j - 1];
        tableTotalRow.appendChild(colSum);
      }
    }

    function calculateSumOfSelectedRows(rowIds) {
      appendResults(calculateColSums(getRows(rowIds)), rowIds);
    }

    calculateSumOfSelectedRows(['b', 'd']);
  </script>
</body>
</html>

触ぅ动初心 2025-01-30 13:08:14

您会改组范围(帮助: https://davidwalsh.name/for-and-for-and-gainst-let- )。
例如check.cells [j]始终返回howmanycols-1
第一个错误(调试器也警告),getrow函数在calculatecols函数中,但是呼叫(calculatecols('total'getrow('getrow('a a a a a a a a a) '),getrow('c')))不是

我写了一个更简单的代码。

let results = {a: 0, b: 0, c: 0, d: 0};
rows = ['a', 'b', 'c', 'd'];
for (let i = 0; i < rows.length; i++) {
  document.querySelectorAll('#'+rows[i]+' td').forEach(
    function(elem) {
      results[rows[i]] += Number(elem.textContent)
    }
  )
}
for (let i=0;i<rows.length;i++) {
  let result = document.createElement('td');
  result.textContent = results[rows[i]];
  document.querySelector('#total').appendChild(result);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <tbody>
      <tr>
        <td></td>
        <th scope="col">2013</th>
        <th scope="col">2014</th>
        <th scope="col">2015</th>
        <th scope="col">2016</th>
      </tr>
      <tr id="a">
        <th scope="row">a</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr id="b">
        <th scope="row">b</th>
        <td>5</td>
        <td>6</td>
        <td>4</td>
        <td>5</td>
      </tr>
      <tr id="c">
        <th scope="row">c</th>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
      </tr>
      <tr id="d">
        <th scope="row">d</th>
        <td>5</td>
        <td>6</td>
        <td>8</td>
        <td>5</td>
      </tr>

      <tr id="total">
        <th scope="row" id="Total">Total</th>

      </tr>
    </tbody>
  </table>
  <script src="checkit.js"></script>

</body>

</html>

如果您只想获取ac行的金额,请设置列表 ['a'','c' ]

You shuffled the scopes (help: https://davidwalsh.name/for-and-against-let).
E.g.check.cells[j] always return howManyCols-1.
The first mistake (the debugger also warns), the getRow function is within the calculateCols function, but the call (calculateCols('total',getRow('a'),getRow('c'))) is not.

I have written a simpler code.

let results = {a: 0, b: 0, c: 0, d: 0};
rows = ['a', 'b', 'c', 'd'];
for (let i = 0; i < rows.length; i++) {
  document.querySelectorAll('#'+rows[i]+' td').forEach(
    function(elem) {
      results[rows[i]] += Number(elem.textContent)
    }
  )
}
for (let i=0;i<rows.length;i++) {
  let result = document.createElement('td');
  result.textContent = results[rows[i]];
  document.querySelector('#total').appendChild(result);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <table>
    <tbody>
      <tr>
        <td></td>
        <th scope="col">2013</th>
        <th scope="col">2014</th>
        <th scope="col">2015</th>
        <th scope="col">2016</th>
      </tr>
      <tr id="a">
        <th scope="row">a</th>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
      </tr>
      <tr id="b">
        <th scope="row">b</th>
        <td>5</td>
        <td>6</td>
        <td>4</td>
        <td>5</td>
      </tr>
      <tr id="c">
        <th scope="row">c</th>
        <td>4</td>
        <td>5</td>
        <td>6</td>
        <td>7</td>
      </tr>
      <tr id="d">
        <th scope="row">d</th>
        <td>5</td>
        <td>6</td>
        <td>8</td>
        <td>5</td>
      </tr>

      <tr id="total">
        <th scope="row" id="Total">Total</th>

      </tr>
    </tbody>
  </table>
  <script src="checkit.js"></script>

</body>

</html>

If you want to only get the a and c rows' amount, set the list rows ['a','c']

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文