Skip to content

feat(text-responses): add optional target sheet configuration for spreadsheet formulas#8488

Merged
adi-herwana-nus merged 1 commit into
masterfrom
adi/spreadsheet-formula-target-sheet
Jul 18, 2026
Merged

feat(text-responses): add optional target sheet configuration for spreadsheet formulas#8488
adi-herwana-nus merged 1 commit into
masterfrom
adi/spreadsheet-formula-target-sheet

Conversation

@adi-herwana-nus

Copy link
Copy Markdown
Contributor

Summary

Adds an optional target sheet setting to spreadsheet-formula (Excel) autograding.
When configured, a student/solution formula is evaluated as if it lived on that sheet, so
unqualified cell references (e.g. =A1+A2) resolve against the chosen sheet instead of
always the first one.

Previously we assumed a formula's result was independent of its location, so no sheet could
be configured. That holds for most formulas, but not when the same cell address exists on
multiple sheets — this closes that gap.

Changes

Autograder (lib/evaluator_scripts/python/autograde_spreadsheet.py)

  • FormulaEvaluator accepts a target_sheetname. It resolves case-insensitively against the
    workbook's actual sheet names and falls back to the first sheet when unset or unrecognized.
  • The resolved sheet becomes self.default_sheetname, which the existing book_ref fallback
    chain already applies to both unqualified formula references and variable-cell overrides —
    so the formula's reads and its randomized inputs stay on the same sheet automatically.
  • The formula cell itself is still injected into the isolated scratch cell SHEET1!A1
    (encoded as [filename.xlsx]SHEET1!A1), so it never collides with real sheets — only the
    reference-resolution default changes.

Backend (Rails)

  • Migration adds a nullable target_sheet_name column to
    course_assessment_question_text_response_solution_spreadsheets (NULL = first sheet, so no
    backfill needed).
  • TextResponseSolutionSpreadsheet#assign_params and #initialize_duplicate handle the new field
    (assignment + duplication).
  • Permitted params, the solution-details jbuilder (targetSheetName), and the container
    tests.json metadata (target_sheet_name) are threaded through.

Frontend

  • New Target sheet dropdown in the spreadsheet solution's Advanced Options, placed under
    the "Fixed date and time" section, directly above the randomization manager. Built with
    FormSelectField for consistency.
  • A null value renders as the first sheet selected (what autograding actually uses), and
    selecting the first sheet stores null — keeping the column nullable with no out-of-range
    Select value. A previously-saved sheet still displays even if it is not among the parsed names.
  • The dropdown is disabled when there is no spreadsheet or the workbook has only one sheet.
  • Single-parse refactor: the spreadsheet file is now parsed once in SpreadsheetManagerPrompt
    and the parsed gridData is shared with the dropdown, SpreadsheetRandomizationManager (via a
    new gridData prop, replacing its own internal parse), and SpreadsheetPreview (via a new
    optional grid prop that falls back to self-parsing for its standalone file-input usage).

i18n

  • Added targetSheet / targetSheetDescription message descriptors and locale entries for
    en, zh, and ko.
Screenshot 2026-07-19 at 02 03 56

…eadsheet formulas

- minor refactor for FE spreadsheet parsing

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional “target sheet” configuration for spreadsheet-formula autograding so unqualified cell references resolve against a chosen sheet (case-insensitive), while keeping existing scratch-cell evaluation behavior. This threads the new field end-to-end across Rails persistence/serialization, Python evaluation, and the React authoring UI (including a single-parse refactor for the spreadsheet grid).

Changes:

  • Python spreadsheet evaluator now accepts an optional target_sheetname and uses it as the default sheet for unqualified references (with fallback to first sheet) + adds tests.
  • Rails adds target_sheet_name to solution spreadsheets, permits/serializes it, and includes it in container tests.json metadata + adds specs.
  • Frontend adds a Target sheet dropdown and refactors spreadsheet parsing so the Advanced Options prompt parses once and shares gridData.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
spec/services/course/assessment/answer/text_response_auto_grading_service_spec.rb Adds coverage to ensure container test metadata includes target_sheet_name.
spec/models/course/assessment/question/text_response_solution_spreadsheet_spec.rb Adds model-level tests for assigning/duplicating target_sheet_name.
lib/evaluator_scripts/python/tests/test_autograde_spreadsheet.py Adds tests for target sheet behavior, case-insensitivity, and fallback.
lib/evaluator_scripts/python/autograde_spreadsheet.py Implements target_sheetname support and threads it through evaluation.
db/schema.rb Updates schema to include the new target_sheet_name column.
db/migrate/20260701000000_add_target_sheet_name_to_text_response_solution_spreadsheets.rb Adds nullable target_sheet_name column.
client/locales/zh.json Adds Target sheet i18n strings (zh).
client/locales/ko.json Adds Target sheet i18n strings (ko).
client/locales/en.json Adds Target sheet i18n strings (en).
client/app/types/course/assessment/question/text-responses.ts Threads targetSheetName / target_sheet_name through TS types.
client/app/lib/components/form/fields/SingleFileInput/SpreadsheetPreview.tsx Allows supplying pre-parsed grid to avoid re-parsing; refactors internal parsing state.
client/app/bundles/course/assessment/translations.ts Adds message descriptors for target sheet label/description.
client/app/bundles/course/assessment/question/text-responses/operations.ts Includes target_sheet_name in post payload adaptation.
client/app/bundles/course/assessment/question/text-responses/components/SpreadsheetRandomizationManager.tsx Accepts shared gridData prop and removes internal spreadsheet parsing.
client/app/bundles/course/assessment/question/text-responses/components/SpreadsheetManagerPrompt.tsx Adds target sheet dropdown and centralizes spreadsheet parsing for Advanced Options.
client/app/bundles/course/assessment/question/text-responses/components/Solution.tsx Hydrates targetSheetName into the editable form state.
app/views/course/assessment/question/text_responses/_solution_details.json.jbuilder Serializes targetSheetName in solution details JSON.
app/services/course/assessment/answer/text_response_auto_grading_service.rb Emits target_sheet_name into tests.json metadata passed to the container.
app/models/course/assessment/question/text_response_solution_spreadsheet.rb Permits assignment/duplication of target_sheet_name.
app/controllers/course/assessment/question/text_responses_controller.rb Permits target_sheet_name in strong params.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@adi-herwana-nus
adi-herwana-nus merged commit 416a6de into master Jul 18, 2026
15 checks passed
@adi-herwana-nus
adi-herwana-nus deleted the adi/spreadsheet-formula-target-sheet branch July 18, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants