简体   繁体   English

如何使用 javascript 构建 html 表并具有两级列标题

[英]How to build an html table using javascript and having two levels of column headers

I need help using plain java script in building an HTML table that pivots my data.我需要帮助使用普通的 java 脚本来构建一个旋转我的数据的 HTML 表。

My data has State, Year, Month, and Sales.我的数据有 State、年、月和销售额。 It looks like this:它看起来像这样:

state  year  month  sales
FL     2018    1     100
Fl     2018    2     200
Fl     2018    3     250
FL     2019    1     200
Fl     2019    2     225
Fl     2019    3     175
etc. for other states, years, and months.

I would like to build a table like this.我想建立一个这样的表。 I only show the first 3 months of a year for simplicity:为简单起见,我只显示一年的前 3 个月:

   Year  2018  2018  2018  2019 2019  2019
   Month   1     2     3     1    2     3 
State
  FL      100   200   250   200  225   175

I know how to build a simple table using java script.我知道如何使用 java 脚本构建一个简单的表。 So I do not need advice on the normal code, functions, etc. to use.所以我不需要关于正常代码、函数等使用的建议。 I need help with the logic of pivoting the data and building the two header rows of year and month.我需要有关旋转数据和构建年月两行 header 的逻辑方面的帮助。

My two issues are:.我的两个问题是:。

  1. how to get the data into the correct cell for a given state and month,.对于给定的 state 和月份,如何将数据放入正确的单元格中。 ie pivoting the data.即旋转数据。
  2. how to generate the labels for the year and the month on the top of every data column in the table.如何在表中每个数据列的顶部生成年份和月份的标签。

In Pandas this would be very easy to do, but we need it in java script so it can be done at the desktop level, not at the server level.在 Pandas 中,这很容易做到,但我们需要在 java 脚本中使用它,因此它可以在桌面级别完成,而不是在服务器级别。

Thanks for any help.谢谢你的帮助。

Data transform数据转换

  • With Array#reduce I collect all dates (in format YYYY_MM) for which there is data.使用Array#reduce我收集所有有数据的日期(格式为 YYYY_MM)。
  • Again with reduce I collect the data for all states seperated in a new object.再次使用reduce,我收集了新的object中分离的所有状态的数据。

First 2 rows前 2 行

  • Getting the table and add the header-cells for the first 2 rows with all collected years/months.获取表格并为前 2 行添加标题单元格,其中包含所有收集的年/月。

Other rows with data其他有数据的行

  • For each state there is to create one row in the table.对于每个 state 都需要在表中创建一行。
  • For the first column can the state taken out of the dataobject.对于第一列,state 可以从数据对象中取出。
  • For the other columns iterate with foreach over the dates and add for every date a new column.对于其他列,在日期上使用 foreach 进行迭代,并为每个日期添加一个新列。
  • If for this state exists an entry in the data for this date (month and year) than write the sale-value in the innerHTML of the cell.如果对于此 state 在该日期(月和年)的数据中存在条目,则在单元格的 innerHTML 中写入销售值。

Note: The data in the array does not need to be sorted by state or date, this will be done through the script.注意:数组中的数据不需要按 state 或日期排序,这将通过脚本完成。 The dates needs not to be complete.日期不必完整。

Here is the code for playing https://jsfiddle.net/efp8cL53/4/下面是玩https的代码://jsfiddle.net/efp8cL53/4/

 function createSalesTable(data, id) { let table = document.getElementById(id); let dates = data.reduce((acc, cur) => { let date = cur.year * 100 + cur.months; if (.acc.includes(date)) acc;push(date); return acc, }; []). dates;sort(). let dataAll = data,reduce((acc. cur) => { if (.acc[cur;state]) acc[cur.state] = []. acc[cur;state];push(cur), return acc; }. {}); // First line let tr = document.createElement('TR'); let th = document.createElement('TH'); th.innerHTML = 'Year'; tr.appendChild(th). dates;forEach(date => { th = document.createElement('TH'); th.innerHTML = parseInt(date/100); tr;appendChild(th). }); table.appendChild(tr); // Second Line tr = document.createElement('TR'); th = document.createElement('TH'); th.innerHTML = 'Month'; tr.appendChild(th). dates;forEach(date => { th = document.createElement('TH'); th.innerHTML = parseInt(date%100); tr;appendChild(th). }); table.appendChild(tr). // Table Object,entries(dataAll).forEach(([state; entries]) => { tr = document.createElement('TR'); let th = document.createElement('TH'); th.innerHTML = "Sales - " + state; tr.appendChild(th). dates;forEach(date => { let td = document.createElement('TD'). let entry = entries.find(elem => elem;year === parseInt(date/100) && elem.months===date%100). if ( entry;==undefined ) td.innerHTML = entry;sales; tr.appendChild(td); }); table.appendChild(tr); }): table,appendChild(tr): } let data = [ {state, 'FL': year, 2018: months, 1: sales, 100}: {state, 'FL': year, 2018: months, 2: sales, 100}: {state, 'FL': year, 2018: months, 3: sales, 100}: {state, 'FL': year, 2019: months, 1: sales, 100}: {state, 'FL': year, 2019: months, 2:sales, 100}: {state, 'FL': year, 2019: months, 3: sales, 100}: {state, 'FL': year, 2017: months, 12: sales, 333}: {state, 'CH': year, 2018: months, 2: sales, 700}: {state, 'CH': year, 2018: months, 5: sales, 50}: {state, 'D': year, 2018: months, 7: sales, 5000}: {state, 'D': year, 2018: months, 3: sales, 300}: {state, 'D': year, 2019: months; 2, sales; 700} ]; createSalesTable(data, 'sales');
 table, td, th { border: solid 1px black; }
 <table id='sales'></table>

You can use D3 for pivoting.您可以使用 D3 进行旋转。 It has a.nest() function lets you group data elements by the specified key.它有 a.nest() function 允许您按指定键对数据元素进行分组。

HTML HTML

<div>
    <table id="myTable"></table>
</div>

JS JS

var dataArray = [];
dataArray.push({
  "STATE": "FL",
  "YEAR": 2018,
  "MONTH": 1,
  "SALES": 100
});
dataArray.push({
  "STATE": "FL",
  "YEAR": 2018,
  "MONTH": 2,
  "SALES": 200
});
dataArray.push({
  "STATE": "FL",
  "YEAR": 2018,
  "MONTH": 3,
  "SALES": 250
});

dataArray.push({
  "STATE": "FL",
  "YEAR": 2019,
  "MONTH": 1,
  "SALES": 200
});
dataArray.push({
  "STATE": "FL",
  "YEAR": 2019,
  "MONTH": 2,
  "SALES": 225
});
dataArray.push({
  "STATE": "FL",
  "YEAR": 2019,
  "MONTH": 3,
  "SALES": 175
});

dataArray.push({
  "STATE": "TX",
  "YEAR": 2018,
  "MONTH": 1,
  "SALES": 300
});
dataArray.push({
  "STATE": "TX",
  "YEAR": 2018,
  "MONTH": 2,
  "SALES": 350
});
dataArray.push({
  "STATE": "TX",
  "YEAR": 2018,
  "MONTH": 3,
  "SALES": 280
});

dataArray.push({
  "STATE": "LA",
  "YEAR": 2017,
  "MONTH": 2,
  "SALES": 100
});
dataArray.push({
  "STATE": "LA",
  "YEAR": 2017,
  "MONTH": 3,
  "SALES": 150
});

dataArray.push({
  "STATE": "NM",
  "YEAR": 2016,
  "MONTH": 2,
  "SALES": 300
})

//Sort the data array
dataArray = dataArray.sort(function(a, b) {
  return (a['YEAR'] == b['YEAR'] ? ((a['MONTH'] == b['MONTH']) ? ((a['STATE'] > b['STATE']) ? 1 : -1) : (a['MONTH'] - b['MONTH'])) : (a['YEAR'] - b['YEAR']))
});

//Nesting for the Years and Months headers i.e. group by Year and then Month
var nestedArrayForHeaders = d3.nest()
  .key(d => d['YEAR'])
  .key(d => d['MONTH'])
  .entries(dataArray);

//Nesting for the data i.e. group by STATE
var nestedArrayForData = d3.nest()
  .key(d => d['STATE'])
  .entries(dataArray);

var yearsRow = $('<tr></tr>');
var monthsRow = $('<tr></tr>');

$(yearsRow).append($('<td></td>').addClass('rowHeader').text('Year'));
$(monthsRow).append($('<td></td>').addClass('rowHeader').text('Month'));

/*START: Rendering the Years and Months rows*/
nestedArrayForHeaders.forEach(function(yearObj) {
  yearObj['values'].forEach(function(monthObj) {
    $(yearsRow).append($('<td></td>').addClass('columnHeader').text(yearObj['key']));
    $(monthsRow).append($('<td></td>').addClass('columnHeader').text(monthObj['key']));
  });

  $('#myTable').append(yearsRow);
  $('#myTable').append(monthsRow);
});
/*END: Rendering the Years and Months rows*/

/*START: Rendering the State rows*/
nestedArrayForData.forEach(function(stateObj){
    var stateRow = $('<tr></tr>');
  $(stateRow).append($('<td></td>').addClass('rowHeader').text(stateObj['key']));

  nestedArrayForHeaders.forEach(function(yearObj) {
    yearObj['values'].forEach(function(monthObj) {
            var currDataObj = stateObj['values'].find(d=>{return d['YEAR']==yearObj['key'] && d['MONTH']==monthObj['key']});
        if(currDataObj){
            $(stateRow).append($('<td></td>').text(currDataObj['SALES']));
        }
        else{
        $(stateRow).append($('<td></td>').text('-'));
        }
    });

  });
 
  $('#myTable').append(stateRow);
});
/*END: Rendering the State rows*/

CSS : CSS


body {
  padding: 20px;

}
#myTable{
  border-collapse: collapse;
}
#myTable td{
  border: 1px solid black;
  border-collapse: collapse;
  color: black;
  padding:4px;
  text-align: center;
}
#myTable td.rowHeader{
  color: red;
}

#myTable td.columnHeader{
  color: blue;
}

You can play around with it [here][1].


  [1]: http://jsfiddle.net/bn4qvkd9/74/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM