如何使用数据(Google 表)创建摘要
How to Create the Summary using the Data (Google Sheets)
我有一些数据,其中有 8 列。我想保留列、B、E、F、G、H 和 I。
在 B 列中我有一些职位,在其他列 E、F、G、H 中我有日期。我想将日期转换为 1 来计算角色,以了解日期在“角色”的“Headers”中重复了多少次。
我已经手动创建了结果数据。我有大量数据,我需要好几天才能得到这个结果。
如果可以使用公式实现,我将不胜感激。
数据
结果
尝试:
=INDEX({QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I19),
E4:I19&"×"&B4:B19&"×"&SEQUENCE(1, 5), ), "0×a×"&SEQUENCE(5)), "×"),
"select Col1,Col2,count(Col2)
where Col2 is not null
group by Col1,Col2
pivot Col3"),
"offset 2", 0); "Grand Total", "",
TRANSPOSE(MMULT(TRANSPOSE(N(ISDATE_STRICT(E4:I19))), ROW(B4:B19)^0))})
或:
=INDEX({SORT({QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I19),
E4:I19&"×"&B4:B19&"×"&SEQUENCE(1, 5), ), "0×a×"&SEQUENCE(5)), "×"),
"select Col1,Col2,count(Col2)
where Col2 is not null
group by Col1,Col2
pivot Col3"),
"offset 2", 0); QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I19),
E4:I19&"×"&SEQUENCE(1, 5), ), "0×"&SEQUENCE(5)), "×"),
"select Col1,'Total',count(Col1)
where Col1 is not null
group by Col1
pivot Col2"),
"offset 2", 0)}); "Grand Total", "",
TRANSPOSE(MMULT(TRANSPOSE(N(ISDATE_STRICT(E4:I19))), ROW(B4:B19)^0))})
或根据您的要求:
={"Date Sourced", B3, E3:I3;
INDEX({SORT({QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I),
E4:I&"×"&B4:B&"×"&SEQUENCE(1, 5), ), "0×a×"&SEQUENCE(5)), "×"),
"select Col1,Col2,count(Col2)
where Col2 is not null group by Col1,Col2 pivot Col3"),
"offset 2", 0); QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I),
E4:I&"×"&SEQUENCE(1, 5), ), "0×"&SEQUENCE(5)), "×"),
"select Col1,'Total',count(Col1)
where Col1 is not null group by Col1 pivot Col2"),
"offset 2", 0)}); "Grand Total", "",
TRANSPOSE(MMULT(TRANSPOSE(N(ISDATE_STRICT(E4:I))), ROW(B4:B)^0))})}
demo sheet
如果您仍对应用程序脚本解决方案持开放态度:
脚本:
function createSummary() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
var timezone = spreadsheet.getSpreadsheetTimeZone();
var locale = spreadsheet.getSpreadsheetLocale().replace('_', '-');
var lastRow = sheet.getLastRow();
// Assuming data starts at B3
var startRow = 4;
var startCol = 2;
// Get all data (B4:I)
var data = sheet.getRange(startRow, startCol, lastRow - startRow + 1, 8).getDisplayValues();
// Get unique dates to iterate later
var dates = uniqueDate(data.map(r => [r[3], r[4], r[5], r[6], r[7]]), timezone);
// Instantiate headers
var headers = ['Date Sourced', 'Role', 'Interested Date', 'Link', 'Screened', 'Interviewed', 'Offer'];
// Add headers as first row in the output later
var output = [headers];
// Variable to store daily Totals for Grand Total
var grandTotal = new Array(5).fill(0);
// Iterate dates
dates.forEach(date => {
// Dictionary to store data
var dateRoles = {};
// Iterate data
data.forEach(row => {
// Iterate headers with date values
headers.slice(2).forEach((header, index) => {
// If date iterated is equal to header value for that date
if(new Date(row[index + 3]).toDateString() == new Date(date).toDateString()) {
// Save data in dictionary
var role = row[0];
var key = `${date}_${role}_${header}`;
// If key is existing, iterate value
if (key in dateRoles)
dateRoles[key]++;
// Else, initialize to 1
else
dateRoles[key] = 1;
}
});
});
var subOutput = [];
// Roles present in current date with date values (sorted)
var roles = [...new Set(Object.keys(dateRoles).map(role => role.split('_')[1]))].sort();
// Iterate unique available roles for the date
roles.forEach((role, i) => {
// If first row, use date as first column, else blank
var first = '';
if(!i)
first = date;
subOutput.push([first, role, dateRoles[`${date}_${role}_${headers[2]}`], dateRoles[`${date}_${role}_${headers[3]}`],
dateRoles[`${date}_${role}_${headers[4]}`], dateRoles[`${date}_${role}_${headers[5]}`],
dateRoles[`${date}_${role}_${headers[6]}`]]);
});
// Sub Totals
var subTotals = [subTotal(subOutput, 2), subTotal(subOutput, 3), subTotal(subOutput, 4),
subTotal(subOutput, 5), subTotal(subOutput, 6)];
// Add Total per date
subOutput.push(['', 'Total'].concat(subTotals));
// Add sub Totals to Grand Total
grandTotal = grandTotal.map(function (num, idx) {
return num + parseInt(subTotals[idx] || 0);
});
// Add daily output to final output
output = output.concat(subOutput);
});
// Append Grand Total
output.push(['Grand Total', ''].concat(grandTotal));
// Write data starting at L3
sheet.getRange(3, 12, output.length, output[0].length).setValues(output)
}
// Function to get sub totals
function subTotal(data, index) {
var total = data.map(r => r[index]).reduce((a, b) => (a || 0) + (b || 0), 0);
if (total < 1)
return '';
return total;
}
// Get Unique Date
function uniqueDate(data, timezone) {
var dates = data.flat()
.map(date => new Date(date))
.filter(date => (date instanceof Date));
return dates.map(date => date.getTime())
.sort()
.filter((date, i, array) => array.indexOf(date) === i)
.map(time => Utilities.formatDate(new Date(time), timezone, "dd-MMM-yyyy"));
}
输出:
我有一些数据,其中有 8 列。我想保留列、B、E、F、G、H 和 I。
在 B 列中我有一些职位,在其他列 E、F、G、H 中我有日期。我想将日期转换为 1 来计算角色,以了解日期在“角色”的“Headers”中重复了多少次。
我已经手动创建了结果数据。我有大量数据,我需要好几天才能得到这个结果。
如果可以使用公式实现,我将不胜感激。
数据
结果
尝试:
=INDEX({QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I19),
E4:I19&"×"&B4:B19&"×"&SEQUENCE(1, 5), ), "0×a×"&SEQUENCE(5)), "×"),
"select Col1,Col2,count(Col2)
where Col2 is not null
group by Col1,Col2
pivot Col3"),
"offset 2", 0); "Grand Total", "",
TRANSPOSE(MMULT(TRANSPOSE(N(ISDATE_STRICT(E4:I19))), ROW(B4:B19)^0))})
或:
=INDEX({SORT({QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I19),
E4:I19&"×"&B4:B19&"×"&SEQUENCE(1, 5), ), "0×a×"&SEQUENCE(5)), "×"),
"select Col1,Col2,count(Col2)
where Col2 is not null
group by Col1,Col2
pivot Col3"),
"offset 2", 0); QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I19),
E4:I19&"×"&SEQUENCE(1, 5), ), "0×"&SEQUENCE(5)), "×"),
"select Col1,'Total',count(Col1)
where Col1 is not null
group by Col1
pivot Col2"),
"offset 2", 0)}); "Grand Total", "",
TRANSPOSE(MMULT(TRANSPOSE(N(ISDATE_STRICT(E4:I19))), ROW(B4:B19)^0))})
或根据您的要求:
={"Date Sourced", B3, E3:I3;
INDEX({SORT({QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I),
E4:I&"×"&B4:B&"×"&SEQUENCE(1, 5), ), "0×a×"&SEQUENCE(5)), "×"),
"select Col1,Col2,count(Col2)
where Col2 is not null group by Col1,Col2 pivot Col3"),
"offset 2", 0); QUERY(QUERY(SPLIT(FLATTEN(IF(ISDATE_STRICT(E4:I),
E4:I&"×"&SEQUENCE(1, 5), ), "0×"&SEQUENCE(5)), "×"),
"select Col1,'Total',count(Col1)
where Col1 is not null group by Col1 pivot Col2"),
"offset 2", 0)}); "Grand Total", "",
TRANSPOSE(MMULT(TRANSPOSE(N(ISDATE_STRICT(E4:I))), ROW(B4:B)^0))})}
demo sheet
如果您仍对应用程序脚本解决方案持开放态度:
脚本:
function createSummary() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getActiveSheet();
var timezone = spreadsheet.getSpreadsheetTimeZone();
var locale = spreadsheet.getSpreadsheetLocale().replace('_', '-');
var lastRow = sheet.getLastRow();
// Assuming data starts at B3
var startRow = 4;
var startCol = 2;
// Get all data (B4:I)
var data = sheet.getRange(startRow, startCol, lastRow - startRow + 1, 8).getDisplayValues();
// Get unique dates to iterate later
var dates = uniqueDate(data.map(r => [r[3], r[4], r[5], r[6], r[7]]), timezone);
// Instantiate headers
var headers = ['Date Sourced', 'Role', 'Interested Date', 'Link', 'Screened', 'Interviewed', 'Offer'];
// Add headers as first row in the output later
var output = [headers];
// Variable to store daily Totals for Grand Total
var grandTotal = new Array(5).fill(0);
// Iterate dates
dates.forEach(date => {
// Dictionary to store data
var dateRoles = {};
// Iterate data
data.forEach(row => {
// Iterate headers with date values
headers.slice(2).forEach((header, index) => {
// If date iterated is equal to header value for that date
if(new Date(row[index + 3]).toDateString() == new Date(date).toDateString()) {
// Save data in dictionary
var role = row[0];
var key = `${date}_${role}_${header}`;
// If key is existing, iterate value
if (key in dateRoles)
dateRoles[key]++;
// Else, initialize to 1
else
dateRoles[key] = 1;
}
});
});
var subOutput = [];
// Roles present in current date with date values (sorted)
var roles = [...new Set(Object.keys(dateRoles).map(role => role.split('_')[1]))].sort();
// Iterate unique available roles for the date
roles.forEach((role, i) => {
// If first row, use date as first column, else blank
var first = '';
if(!i)
first = date;
subOutput.push([first, role, dateRoles[`${date}_${role}_${headers[2]}`], dateRoles[`${date}_${role}_${headers[3]}`],
dateRoles[`${date}_${role}_${headers[4]}`], dateRoles[`${date}_${role}_${headers[5]}`],
dateRoles[`${date}_${role}_${headers[6]}`]]);
});
// Sub Totals
var subTotals = [subTotal(subOutput, 2), subTotal(subOutput, 3), subTotal(subOutput, 4),
subTotal(subOutput, 5), subTotal(subOutput, 6)];
// Add Total per date
subOutput.push(['', 'Total'].concat(subTotals));
// Add sub Totals to Grand Total
grandTotal = grandTotal.map(function (num, idx) {
return num + parseInt(subTotals[idx] || 0);
});
// Add daily output to final output
output = output.concat(subOutput);
});
// Append Grand Total
output.push(['Grand Total', ''].concat(grandTotal));
// Write data starting at L3
sheet.getRange(3, 12, output.length, output[0].length).setValues(output)
}
// Function to get sub totals
function subTotal(data, index) {
var total = data.map(r => r[index]).reduce((a, b) => (a || 0) + (b || 0), 0);
if (total < 1)
return '';
return total;
}
// Get Unique Date
function uniqueDate(data, timezone) {
var dates = data.flat()
.map(date => new Date(date))
.filter(date => (date instanceof Date));
return dates.map(date => date.getTime())
.sort()
.filter((date, i, array) => array.indexOf(date) === i)
.map(time => Utilities.formatDate(new Date(time), timezone, "dd-MMM-yyyy"));
}