我在 Handsontable 中设计了一个表格来计算每个月每个任务和工单的工作时间总和。我想在表格的最后一行显示全年的工作时间总和,但我不知道如何仅将父项相加。
我的代码:https://jsfiddle.net/5pr3cvw9/
const container = document.querySelector('#example');
const hyperformulaInstance = HyperFormula.buildEmpty({
licenseKey: 'internal-use-in-handsontable',
});
const hot = new Handsontable(container, {
columnSummary() {
const endpoints = [];
const nestedRowsPlugin = this.hot.getPlugin('nestedRows');
const getRowIndex = nestedRowsPlugin.dataManager.getRowIndex.bind(nestedRowsPlugin.dataManager);
const resultColumn = 3;
let tempEndpoint = null;
let nestedRowsCache = null;
if (nestedRowsPlugin.isEnabled()) {
nestedRowsCache = this.hot.getPlugin('nestedRows').dataManager.cache;
} else {
return;
}
for (let i = 0; i < nestedRowsCache.levels[0].length; i++) {
tempEndpoint = {};
if (!nestedRowsCache.levels[0][i].__children || nestedRowsCache.levels[0][i].__children.length === 0) {
continue;
}
tempEndpoint.destinationColumn = resultColumn;
tempEndpoint.destinationRow = getRowIndex(nestedRowsCache.levels[0][i]);
tempEndpoint.type = 'sum';
tempEndpoint.forceNumeric = true;
tempEndpoint.ranges = [];
tempEndpoint.ranges.push([
getRowIndex(nestedRowsCache.levels[0][i].__children[0]),
getRowIndex(nestedRowsCache.levels[0][i].__children[nestedRowsCache.levels[0][i].__children.length - 1])
]);
endpoints.push(tempEndpoint);
tempEndpoint = null;
}
return endpoints;
},
data,
columns,
colHeaders: ['Month', 'Tasks', 'Tickets', 'Total hours'],
columnSorting: {
indicator: true
},
formulas: {
engine: hyperformulaInstance,
sheetName: 'Sheet1',
},
rowHeaders: false,
stretchH: 'all',
autoWrapRow: true,
licenseKey: 'non-commercial-and-evaluation',
autoColumnSize: true,
width: '100%',
height: 'auto',
dropdownMenu: true,
mergeCells: true,
contextMenu: true,
manualRowMove: true,
manualColumnMove: true,
multiColumnSorting: {
indicator: true
},
filters: true,
manualRowResize: true,
manualColumnResize: true,
comments: true,
nestedRows: true
});
<script src="https://cdn.jsdelivr.net/npm/handsontable@latest/dist/handsontable.full.js"></script>
<link href="https://cdn.jsdelivr.net/npm/handsontable@latest/dist/handsontable.full.css" rel="stylesheet" />
<div id="example"></div>
<script>
const data = [{
month: 'January',
tasks: '#54, #76',
tickets: '#546',
total_hours: 0,
__children: [{
tasks: '#54 - test task 1',
tickets: '#546 - support ticket 1',
total_hours: 10.03
},
{
tasks: '#76 - test task 2',
tickets: '#546 - support ticket 1',
total_hours: 3.40
},
]
},
{
month: 'February',
tasks: '#65',
tickets: '',
total_hours: 0,
__children: [{
tasks: '#65 - test task 3',
tickets: '',
total_hours: 2.35
}, ]
},
{
month: 'March',
tasks: '',
tickets: '#451',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#451 - support ticket 3',
total_hours: 12.7
}, ]
},
{
month: 'April',
tasks: '#12, #87',
tickets: '',
total_hours: 0,
__children: [{
tasks: '#12 - test task 5',
tickets: '',
total_hours: 2
},
{
tasks: '#87 - test task 8',
tickets: '',
total_hours: 4.2
},
]
},
{
month: 'May',
tasks: '',
tickets: '#567',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
month: 'June',
tasks: '#98, #54, #128',
tickets: '#783, #981',
total_hours: 0,
__children: [{
tasks: '#98 - test task 12',
tickets: '',
total_hours: 0.45
},
{
tasks: '#54 - test task 15',
tickets: '',
total_hours: 4
},
{
tasks: '#128 - test task 23',
tickets: '',
total_hours: 6.4
},
{
tasks: '',
tickets: '#783 - test support 11',
total_hours: 3.3
},
{
tasks: '',
tickets: '#981 - test support 12',
total_hours: 3.4
},
]
},
{
month: 'July',
tasks: '',
tickets: '',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
month: 'August',
tasks: '',
tickets: '',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
month: 'September',
tasks: '',
tickets: '',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
month: 'October',
tasks: '',
tickets: '',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
month: 'November',
tasks: '',
tickets: '',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
month: 'December',
tasks: '',
tickets: '',
total_hours: 0,
__children: [{
tasks: '',
tickets: '#567 - test support 7',
total_hours: 10
}, ]
},
{
// Add a new row for the total hours
month: 'Year Total',
tasks: '',
tickets: '',
total_hours: 0,
__children: []
}
]
const columns = [{
'data': 'month',
'type': 'text',
'readOnly': true
},
{
'data': 'tasks',
'type': 'text',
'readOnly': false
},
{
'data': 'tickets',
'type': 'text',
'readOnly': false
},
{
'data': 'total_hours',
'type': 'numeric',
'numericFormat': {
'pattern': '0.00'
},
'readOnly': false
},
];
</script>
这不是小事。
https://jsfiddle.net/mplungjan/abzefdhL/
这是一个解决方案,将在加载后和更改后添加行和求和
let hotInstance; // we need this to be global to not get errors when we pass it while creating the instance
const calculateYearlyTotal = (hot) => {
const data = hot.getSourceData();
let yearTotalRowIndex = data.findIndex(row => row.month === 'Year Total');
// Check if 'Year Total' row exists
if (yearTotalRowIndex === -1) {
// Create 'Year Total' row and add it to the data
const yearTotalRow = {
month: 'Year Total',
tasks: '',
tickets: '',
total_hours: 0
};
hot.alter('insert_row', data.length);
hot.setDataAtRowProp(data.length, 'month', yearTotalRow.month, 'calculateYearlyTotal');
yearTotalRowIndex = data.length;
}
// Use reduce to sum up the total hours, excluding 'Year Total' row
const yearlyTotal = data.slice(0, yearTotalRowIndex).reduce((total, row) => {
return total + (row.total_hours || 0);
}, 0);
// Update the 'Year Total' row
hot.setDataAtRowProp(yearTotalRowIndex, 'total_hours', yearlyTotal, 'calculateYearlyTotal');
};
hotInstance = new Handsontable(container, {
afterChange: (changes, source) => {
if (source !== 'loadData' && source !== 'calculateYearlyTotal') {
setTimeout(() => calculateYearlyTotal(hotInstance), 100);
}
},
afterLoadData: function() {
setTimeout(() => calculateYearlyTotal(hotInstance), 100)
},
columnSummary() {
....