feat(text-responses): add optional target sheet configuration for spreadsheet formulas#8488
Merged
Merged
Conversation
…eadsheet formulas - minor refactor for FE spreadsheet parsing
Contributor
There was a problem hiding this comment.
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_sheetnameand uses it as the default sheet for unqualified references (with fallback to first sheet) + adds tests. - Rails adds
target_sheet_nameto solution spreadsheets, permits/serializes it, and includes it in containertests.jsonmetadata + 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 ofalways 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)FormulaEvaluatoraccepts atarget_sheetname. It resolves case-insensitively against theworkbook's actual sheet names and falls back to the first sheet when unset or unrecognized.
self.default_sheetname, which the existingbook_reffallbackchain 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.
SHEET1!A1(encoded as
[filename.xlsx]SHEET1!A1), so it never collides with real sheets — only thereference-resolution default changes.
Backend (Rails)
target_sheet_namecolumn tocourse_assessment_question_text_response_solution_spreadsheets(NULL= first sheet, so nobackfill needed).
TextResponseSolutionSpreadsheet#assign_paramsand#initialize_duplicatehandle the new field(assignment + duplication).
targetSheetName), and the containertests.jsonmetadata (target_sheet_name) are threaded through.Frontend
the "Fixed date and time" section, directly above the randomization manager. Built with
FormSelectFieldfor consistency.nullvalue renders as the first sheet selected (what autograding actually uses), andselecting the first sheet stores
null— keeping the column nullable with no out-of-rangeSelect value. A previously-saved sheet still displays even if it is not among the parsed names.
SpreadsheetManagerPromptand the parsed
gridDatais shared with the dropdown,SpreadsheetRandomizationManager(via anew
gridDataprop, replacing its own internal parse), andSpreadsheetPreview(via a newoptional
gridprop that falls back to self-parsing for its standalone file-input usage).i18n
targetSheet/targetSheetDescriptionmessage descriptors and locale entries foren,zh, andko.