解决方案
因此,基本上,您希望在单击按钮时按所述顺序生成对象、任务和事件的层次结构报告。
在此解决方案中,我提供了最复杂部分所需的代码,然后提供了其余步骤的指导。
- 用Insert->Drawing中的数据向您的工作表添加一个按钮,然后绘制您的按钮。
- 创建一个新工作表并插入以下公式,如图所示:
=iferror(ArrayFormula(lookup(unique(Sheet1!A1:A),Sheet1!A1:A,row(Sheet1!A1:A)+1)))
和
=iferror(ArrayFormula(lookup(unique(Sheet1!E2:E),Sheet1!E2:E,row(Sheet1!E2:E)+1)))
这些论坛基本上会检测指定列(在我们的例子中是对象 ID 和任务 ID 的列)中值的任何变化,这将有助于生成报告。
- 在此之后,通过脚本编辑器并使用以下函数生成对象数组,其中包含按层次排序的正确数据。以下代码包含自我解释的 cmets。这是最棘手的部分,它利用之前创建的工作表来了解我们的对象和任务 ID 在哪里发生变化,并将正确的信息存储在正确的位置。
对于这个数据:
这将是运行函数后生成的对象:
[{ObjectId=1.0, 1={TaskId=S02, Events=[[3242.0]], TaskMore=ppp, Description=ppp}, 0={TaskId=S01, Description=qqq, Events=[[1.0], [23.0], [324.0]], TaskMore=qqq}, ObjectMore=aaaa, ObjectDesc=aaaa, 2={TaskMore=lll, Events=[[3.0]], TaskId=S03, Description=lll}, ObjectProgress=0.7}, {3={Description=www, Events=[[43.0]], TaskMore=www, TaskId=T01}, 5={TaskId=T03, Events=[[5.0]], TaskMore=ttt, Description=ttt}, ObjectMore=bbbb, 4={Description=eee, TaskId=T02, TaskMore=eee, Events=[[54.0], [4.0]]}, ObjectDesc=bbbb, 6={Description=yyy, Events=[[345.0], [343.0]], TaskId=T04, TaskMore=yyy}, ObjectProgress=0.33, ObjectId=2.0}]
function myFunction() {
// Get sheets
var sheetData = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var sheetHelp = SpreadsheetApp.getActive().getSheetByName('Sheet2');
// This is the array where we will be storing our info
var Objects = []
// Get the ranges of values from our helper sheet that detect changes in that column
var ObjectIds = sheetHelp.getRange(2, 1,sheetHelp.getLastRow(),1).getValues().flat();
var TaskIds = sheetHelp.getRange(2, 2,sheetHelp.getLastRow(),2).getValues().flat();
// Delete all the blank elements in the flaten array of values
ObjectIds = ObjectIds.filter(item => item);
TaskIds = TaskIds.filter(item => item);
// Delete the last item as this would just be the change between a value and a blank cell
ObjectIds.pop();
TaskIds.pop();
// Lets iterate through all our main objects detected
for(i=0;i<ObjectIds.length;i++){
// for each object insert its details and information
Objects.push({
ObjectId: sheetData.getRange(parseInt(ObjectIds[i]), 1).getValue(),
ObjectDesc : sheetData.getRange(parseInt(ObjectIds[i]), 2).getValue(),
ObjectMore : sheetData.getRange(parseInt(ObjectIds[i]), 3).getValue(),
ObjectProgress : sheetData.getRange(parseInt(ObjectIds[i]), 4).getValue()
});
// for each object iterate through all its possible tasks
for(j=0;j<TaskIds.length;j++){
// get the last row value as for the last element of the tasks if we do not have anything it will
// have issues in the following if condition if this is null
var lastRow = sheetHelp.getLastRow();
ObjectIds.push(lastRow);
// If the task is within the object index range (i.e for an object between indices 8 and 12
// his tasks are those between these indices as well
if(TaskIds[j]<ObjectIds[i+1] && TaskIds[j]>=ObjectIds[i]){
TaskIds.push(lastRow);
// get all the events for this specific task checking that they are within the indices
// of the task itself (only events that are within the index boundaries of the task
var events = sheetData.getRange(TaskIds[j], 8,TaskIds[j+1]-TaskIds[j],1).getValues();
// add the new task object
Objects[i][j] = {
TaskId : sheetData.getRange(parseInt(TaskIds[j]),5).getValue(),
Description : sheetData.getRange(parseInt(TaskIds[j]),6).getValue(),
TaskMore : sheetData.getRange(parseInt(TaskIds[j]),7).getValue(),
Events : events
};
TaskIds.pop();
}
ObjectIds.pop();
}
}
downloadReport(Objects);
}
- 返回到您创建的按钮并在其分配脚本下的选项中选择我们的函数
myFunction。
- 一旦您拥有了包含正确分层信息的对象数组,您就可以自行决定使用它来生成报告的方式。您可以:
- 使用 JSON 对象数组生成 HTML 电子邮件,以便在您单击工作表按钮时通过 Gmail 发送报告。
- 生成一个新工作表并使用您在图片中显示的结构粘贴此数据(由于您已对数据进行了排序,因此更容易自动化),导出为 PDF 并删除此工作表,因为其目的只是生成此 PDF 报告.
- 将其作为 JSON 数组发送给其他服务,以便他们轻松使用。
对于第五步的第二个场景,我在这里提供一些指导,作为如何实施的示例(一个最小的示例)。如果您需要进一步的指导,请告诉我。
基本上,您可以在电子表格中创建这个新工作表,然后遍历我们的对象数组和 json 对象,以将新工作表的单元格值设置在适当的位置。 请注意,我还编辑了之前的代码,我必须从 myFunction() 调用这个新函数。
以下代码具有自我解释的 cmets,它基本上会打印工作表中存在的对象 ID:
function downloadReport(object){
// Check if this sheet already exists from generating previous reports
// and if so delete it to create a new report
if(SpreadsheetApp.getActive().getSheetByName('Download')){SpreadsheetApp.getActive().deleteSheet(SpreadsheetApp.getActive().getSheetByName('Download'))}
// Create your new sheet
var sheet = SpreadsheetApp.getActive().insertSheet().setName('Download');
// Iterate over each object in your array of objects
for(i=0;i<object.length;i++){
// print each object id of your series of objects. For doing so first access the array
// element and then in that object access the key of the json object. Do the same for the
// rest of the fields you are interested to print in your report.
sheet.getRange(i+1, 1).setValue(object[i]['ObjectId']);
}
}
我希望这对您有所帮助。让我知道您是否需要其他任何内容,或者您是否不理解某些内容。 :)