1

I am trying to get the scores for each question from a graded google quiz in to the corresponding sheet. There will be open ended questions that will need to be hand graded on a 1-3 point scale and the answers will vary greatly. I want to be able to hand grade them on google forms and then export just the scores. The scores and questions would be fine too!

This is what the form produces Form Responses

This is what I am hoping to do. Planned changes

Example form

Example Sheet

Thank you!

I tried running a different script, but could not get it to work at all. I also tried using the flubaroo addon

Tedinoz
  • 5,911
  • 3
  • 25
  • 35

1 Answers1

2

In your situation, how about the following sample script?

Sample script:

Unfortunately, in the case of your URL of the Google Form of https://docs.google.com/forms/d/e/###/viewform?usp=sharing, ### is not Google Form ID. So, in this sample script, the Google Form ID is retrieved from your Spreadsheet.

Before you use this script, please set the destination sheet name to dstSheetName. In this sample, the result values are put to a sheet in the same Spreadsheet of your provided Spreadsheet.

function sample() {
  const dstSheetName = "Sheet1"; // Please set the destination sheet name.

  const header1 = ["Timestamp", "Score"]; // This is from your question.
  const header2 = ["Name", "Q1 score", "Q2 score"]; // This is from your question.
  const spreadsheetId = "1YV6yMD4qVOy0Nn5lSXlYNNCLqJTMEo6j0lDnrqYByVE"; // This is from your question.

  // Retrieve values from Google Form.
  const ss = SpreadsheetApp.openById(spreadsheetId);
  const form = FormApp.openByUrl(ss.getSheets()[0].getFormUrl());
  const score = form.getItems().reduce((n, item) => {
    const type = item.getType();
    if (type == FormApp.ItemType.MULTIPLE_CHOICE) {
      n += item.asMultipleChoiceItem().getPoints();
    } else if (type == FormApp.ItemType.TEXT) {
      n += item.asTextItem().getPoints();
    }
    return n;
  }, 0);
  const values = [[...header1, ...header2], ...form.getResponses().map(r => {
    const itemResponses = r.getGradableItemResponses();
    const temp = header2.map((_, i) => {
      const res = itemResponses[i];
      return i == 0 ? res.getResponse() : res.getScore();
    });
    const total = temp.reduce((n, e) => {
      if (!isNaN(e)) n += e;
      return n;
    }, 0);
    return [r.getTimestamp(), `${total} / ${score}`, ...temp];
  })];

  // Put values to Spreadsheet.
  const sheet = ss.getSheetByName(dstSheetName);
  sheet.clearContents().getRange(1, 1, values.length, values[0].length).setValues(values);
}
  • When this script is run, I confirmed that your expected result is obtained.

  • I noticed that in your expecrted result image, the score of "Maggie" is "4 / 4". It seems that each score is 1 and 0. But, when this script is run, each score is 1 and 3. Please be careful about this.

Note:

  • This sample script is for your provided Google Form. So, please test this script on your provided Google Form and Google Spreadsheet. When you change the Google Form, please modify this script. Please be careful about this.

References:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • `const ss = SpreadsheetApp.openById(spreadsheetId);` I'm confused about this line. This implies that you have either a standalone script or a new bound script. But why not run `const ss = SpreadsheetApp.getActiveSpreadsheet()` from the "Responses" spreadsheet. After all, the output is being saved to that spreadsheet. Otherwise, I am in awe; I was stumbling along writing an old-school answer and without being 50% finished, you had written your complete, efficient answer. – Tedinoz Apr 21 '23 at 06:59
  • @Tedinoz Thank you for your comment. In this answer, from this question, I couldn't understand that the container-bound script of Spreadsheet or Form is used. So, from OP's provided sample Spreadsheet and Form, I proposed a simple sample script that can be used for both the container-bound type and the standalone type. This script can directly work by using the OP's provided Spreadsheet. – Tanaike Apr 21 '23 at 07:44
  • 1
    @Tedinoz For example, if OP is using the container-bound script of Spreadsheet, I think that `openById(spreadsheetId)` can be replaced with `getActiveSpreadsheet()` as you mentioned. And, if OP is using the container-bound script of Form, `openByUrl(ss.getSheets()[0].getFormUrl())` can be replaced with `getActiveForm()`. If this explanation was not useful, I apologize. – Tanaike Apr 21 '23 at 07:44
  • @Tedinoz In my case, unfortunately, I cannot understand most questions. In the case of this question, when I saw this, I thought that I might be able to correctly understand. So, I could prepare this answer. I would like to study more to understand various situations. – Tanaike Apr 21 '23 at 07:49
  • @Sami Melendez About `This is perfect!!! Thank you so much!!!`, welcome. Thank you for letting me know. I'm glad your issue was resolved. If your question was solved, please push an accept button. Other people who have the same issue with you can also base your question as a question that can be solved. And I think that your issue and solution will be useful for them. If you don't find the button, feel free to tell me. https://stackoverflow.com/help/accepted-answer – Tanaike Apr 21 '23 at 13:56
  • 1
    `perfect!!!` I thought this _question_ had value too. I couldn't find a duplicate or near duplicate, but this question enables the per-question scores to be analysed which can display trends within the class for question design, curricula, and student knowledge. – Tedinoz Apr 21 '23 at 23:09