向项目所有者发送一封电子邮件 w/All 相关项目子任务和 w/All 项目说明
Send a Single Email to Project Owner w/All Related Project Subtasks & w/All Project Notes
我正在尝试为 Appsheet 应用编写 Javascript/appscript。我想不通,如果有人可以帮助。
我有三张纸:
项目
子任务
笔记
我希望能够向项目所有者发送一封电子邮件,其中包括项目名称、分配给该项目的所有任务(通过 PK/FK ID、项目名称建立的关系)和所有注释分配给该项目(与 Notes PK/FK ID、项目名称相同的关系),其中 last_update 列在现在的 24 小时内。 (即过去 24 小时内对任何任务或笔记所做的任何更改或创建)
我提供了所有表格的示例、它们的列以及理想的示例输出
Public link 到我的电子表格:
https://docs.google.com/spreadsheets/d/1FcOKVkhdjK-vGuFPWSR2ZreBYFI6EK7EnQj3yKPvttk/edit?usp=sharing
idealOutput
我相信你的目标如下。
您想通过从 3 sheet 中检索值来创建电子邮件,如下所示。 (下图来自你的问题。)
您想使用 Google Apps 脚本实现此目的。
根据您对 Task order does not matter. Notes preferablly sorted in the email by most recent (not required)
的评论,我认为您可能只想对“Notes”的值进行排序。
在这种情况下,下面的示例脚本怎么样?
示例脚本:
请将以下脚本复制粘贴到Spreadsheet的脚本编辑器中。并且,请检查 sheet 个名称。请 运行 myFunction
.
function myFunction() {
// Retrieve 3 sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [sheetITPM, sheetITPM_Tasks, sheetNotes] = ["ITPM", "ITPM_Tasks", "Notes"].map(e => ss.getSheetByName(e));
// Retrieve IDs, names and emails.
const values = sheetITPM.getRange("A2:J" + sheetITPM.getLastRow()).getValues().map(r => ({ id: r[0], name: r[1], email: r[9] }));
// Retrieve Tasks.
const tasks = sheetITPM_Tasks.getRange("A2:G" + sheetITPM_Tasks.getLastRow()).getValues().reduce((o, r) => (o[r[2]] = o[r[2]] ? [...o[r[2]], { description: r[3], status: r[4], dueDate: r[6] }] : [{ description: r[3], status: r[4], dueDate: r[6] }], o), {});
// Retrieve Notes.
const notes = sheetNotes.getRange("A2:E" + sheetNotes.getLastRow()).getValues().reduce((o, r) => (o[r[1]] = o[r[1]] ? [...o[r[1]], { note: r[2], date: r[4] }] : [{ note: r[2], date: r[4] }], o), {});
Object.entries(notes).forEach(([, v]) => v.sort((a, b) => a.date.getTime() < b.date.getTime() ? 1 : -1)); // If you don't want to sort the values of "Notes", please remove this line.
// Send emails.
values.forEach(({ id, name, email }) => {
const message = [
`Here is the project update for: ${name}`,
"",
`Assigned Tasks:`,
...tasks[id].map(({ description, status, dueDate }, i) => [`Task ${i + 1}:`, description, status, dueDate, ""].join("\n")),
"",
`Project Notes:`,
...notes[id].map(({ note }, i) => [`Note ${i + 1}:`, note, ""].join("\n")),
].join("\n");
MailApp.sendEmail({ to: email, subject: "Project update", body: message });
});
}
- 当此脚本为 运行 时,通过从 3 sheet 中检索值来发送电子邮件。电子邮件地址来自“ITPM”的“J”列 sheet。
注:
- 此示例脚本适用于您的示例 Spreadsheet。因此,当 Spreadsheet 的结构从您的示例 Spreadsheet 更改时,此脚本可能无法使用。所以请注意这一点。当您测试此脚本时,请使用您的示例 Spreadsheet.
参考文献:
已添加:
OP 的后续新问题,
Is it possible to have it only include the notes and tasks where their column last update is within 24 hours of right now?
示例脚本:
function myFunction() {
// Retrieve 3 sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [sheetITPM, sheetITPM_Tasks, sheetNotes] = ["ITPM", "ITPM_Tasks", "Notes"].map(e => ss.getSheetByName(e));
// Retrieve IDs, names and emails.
const values = sheetITPM.getRange("A2:J" + sheetITPM.getLastRow()).getValues().map(r => ({ id: r[0], name: r[1], email: r[9] }));
// Retrieve Tasks.
const tasks = sheetITPM_Tasks.getRange("A2:G" + sheetITPM_Tasks.getLastRow()).getValues().reduce((o, r) => (o[r[2]] = o[r[2]] ? [...o[r[2]], { description: r[3], status: r[4], dueDate: r[6] }] : [{ description: r[3], status: r[4], dueDate: r[6] }], o), {});
// Retrieve Notes.
const notes = sheetNotes.getRange("A2:E" + sheetNotes.getLastRow()).getValues().reduce((o, r) => (o[r[1]] = o[r[1]] ? [...o[r[1]], { note: r[2], date: r[4] }] : [{ note: r[2], date: r[4] }], o), {});
Object.entries(notes).forEach(([, v]) => v.sort((a, b) => a.date.getTime() < b.date.getTime() ? 1 : -1)); // If you don't want to sort the values of "Notes", please remove this line.
// By OP's new question, I added the following script.
const now = new Date().getTime();
const before24h = now - (24 * 60 * 60 * 1000);
Object.entries(tasks).forEach(([k, v]) => {
tasks[k] = v.filter(({dueDate}) => {
const temp = dueDate.getTime();
return now < temp && temp > before24h;
});
});
Object.entries(notes).forEach(([k, v]) => {
notes[k] = v.filter(({date}) => {
const temp = date.getTime();
return now < temp && temp > before24h;
});
});
// Send emails.
values.forEach(({ id, name, email }) => {
const message = [
`Here is the project update for: ${name}`,
"",
`Assigned Tasks:`,
...tasks[id].map(({ description, status, dueDate }, i) => [`Task ${i + 1}:`, description, status, dueDate, ""].join("\n")),
"",
`Project Notes:`,
...notes[id].map(({ note }, i) => [`Note ${i + 1}:`, note, ""].join("\n")),
].join("\n");
MailApp.sendEmail({ to: email, subject: "Project update", body: message });
});
}
- 但是,关于你的新问题,当你的样本 Spreadsheet 被使用时,在这种情况下,
tasks
和 notes
没有值。请注意这一点。
我正在尝试为 Appsheet 应用编写 Javascript/appscript。我想不通,如果有人可以帮助。
我有三张纸: 项目 子任务 笔记
我希望能够向项目所有者发送一封电子邮件,其中包括项目名称、分配给该项目的所有任务(通过 PK/FK ID、项目名称建立的关系)和所有注释分配给该项目(与 Notes PK/FK ID、项目名称相同的关系),其中 last_update 列在现在的 24 小时内。 (即过去 24 小时内对任何任务或笔记所做的任何更改或创建)
我提供了所有表格的示例、它们的列以及理想的示例输出
Public link 到我的电子表格: https://docs.google.com/spreadsheets/d/1FcOKVkhdjK-vGuFPWSR2ZreBYFI6EK7EnQj3yKPvttk/edit?usp=sharing
idealOutput
我相信你的目标如下。
您想通过从 3 sheet 中检索值来创建电子邮件,如下所示。 (下图来自你的问题。)
您想使用 Google Apps 脚本实现此目的。
根据您对
Task order does not matter. Notes preferablly sorted in the email by most recent (not required)
的评论,我认为您可能只想对“Notes”的值进行排序。
在这种情况下,下面的示例脚本怎么样?
示例脚本:
请将以下脚本复制粘贴到Spreadsheet的脚本编辑器中。并且,请检查 sheet 个名称。请 运行 myFunction
.
function myFunction() {
// Retrieve 3 sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [sheetITPM, sheetITPM_Tasks, sheetNotes] = ["ITPM", "ITPM_Tasks", "Notes"].map(e => ss.getSheetByName(e));
// Retrieve IDs, names and emails.
const values = sheetITPM.getRange("A2:J" + sheetITPM.getLastRow()).getValues().map(r => ({ id: r[0], name: r[1], email: r[9] }));
// Retrieve Tasks.
const tasks = sheetITPM_Tasks.getRange("A2:G" + sheetITPM_Tasks.getLastRow()).getValues().reduce((o, r) => (o[r[2]] = o[r[2]] ? [...o[r[2]], { description: r[3], status: r[4], dueDate: r[6] }] : [{ description: r[3], status: r[4], dueDate: r[6] }], o), {});
// Retrieve Notes.
const notes = sheetNotes.getRange("A2:E" + sheetNotes.getLastRow()).getValues().reduce((o, r) => (o[r[1]] = o[r[1]] ? [...o[r[1]], { note: r[2], date: r[4] }] : [{ note: r[2], date: r[4] }], o), {});
Object.entries(notes).forEach(([, v]) => v.sort((a, b) => a.date.getTime() < b.date.getTime() ? 1 : -1)); // If you don't want to sort the values of "Notes", please remove this line.
// Send emails.
values.forEach(({ id, name, email }) => {
const message = [
`Here is the project update for: ${name}`,
"",
`Assigned Tasks:`,
...tasks[id].map(({ description, status, dueDate }, i) => [`Task ${i + 1}:`, description, status, dueDate, ""].join("\n")),
"",
`Project Notes:`,
...notes[id].map(({ note }, i) => [`Note ${i + 1}:`, note, ""].join("\n")),
].join("\n");
MailApp.sendEmail({ to: email, subject: "Project update", body: message });
});
}
- 当此脚本为 运行 时,通过从 3 sheet 中检索值来发送电子邮件。电子邮件地址来自“ITPM”的“J”列 sheet。
注:
- 此示例脚本适用于您的示例 Spreadsheet。因此,当 Spreadsheet 的结构从您的示例 Spreadsheet 更改时,此脚本可能无法使用。所以请注意这一点。当您测试此脚本时,请使用您的示例 Spreadsheet.
参考文献:
已添加:
OP 的后续新问题,
Is it possible to have it only include the notes and tasks where their column last update is within 24 hours of right now?
示例脚本:
function myFunction() {
// Retrieve 3 sheets.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const [sheetITPM, sheetITPM_Tasks, sheetNotes] = ["ITPM", "ITPM_Tasks", "Notes"].map(e => ss.getSheetByName(e));
// Retrieve IDs, names and emails.
const values = sheetITPM.getRange("A2:J" + sheetITPM.getLastRow()).getValues().map(r => ({ id: r[0], name: r[1], email: r[9] }));
// Retrieve Tasks.
const tasks = sheetITPM_Tasks.getRange("A2:G" + sheetITPM_Tasks.getLastRow()).getValues().reduce((o, r) => (o[r[2]] = o[r[2]] ? [...o[r[2]], { description: r[3], status: r[4], dueDate: r[6] }] : [{ description: r[3], status: r[4], dueDate: r[6] }], o), {});
// Retrieve Notes.
const notes = sheetNotes.getRange("A2:E" + sheetNotes.getLastRow()).getValues().reduce((o, r) => (o[r[1]] = o[r[1]] ? [...o[r[1]], { note: r[2], date: r[4] }] : [{ note: r[2], date: r[4] }], o), {});
Object.entries(notes).forEach(([, v]) => v.sort((a, b) => a.date.getTime() < b.date.getTime() ? 1 : -1)); // If you don't want to sort the values of "Notes", please remove this line.
// By OP's new question, I added the following script.
const now = new Date().getTime();
const before24h = now - (24 * 60 * 60 * 1000);
Object.entries(tasks).forEach(([k, v]) => {
tasks[k] = v.filter(({dueDate}) => {
const temp = dueDate.getTime();
return now < temp && temp > before24h;
});
});
Object.entries(notes).forEach(([k, v]) => {
notes[k] = v.filter(({date}) => {
const temp = date.getTime();
return now < temp && temp > before24h;
});
});
// Send emails.
values.forEach(({ id, name, email }) => {
const message = [
`Here is the project update for: ${name}`,
"",
`Assigned Tasks:`,
...tasks[id].map(({ description, status, dueDate }, i) => [`Task ${i + 1}:`, description, status, dueDate, ""].join("\n")),
"",
`Project Notes:`,
...notes[id].map(({ note }, i) => [`Note ${i + 1}:`, note, ""].join("\n")),
].join("\n");
MailApp.sendEmail({ to: email, subject: "Project update", body: message });
});
}
- 但是,关于你的新问题,当你的样本 Spreadsheet 被使用时,在这种情况下,
tasks
和notes
没有值。请注意这一点。