CSV Imports - Kush-Kelaiya22/imPress GitHub Wiki

CSV Imports

Bulk-loading data from spreadsheets: quiz questions, courses and sections, students, and staff. Reference: docs/guides/csv-imports.md and the REST API.

Contents


Which import does what

Import Where Who Behaviour
Quiz questions Create Quiz page โ†’ Import questions from CSV teachers (their classes), admins preview first; all-or-nothing; duplicates skipped
Courses and sections Classrooms โ†’ Import CSV / Export CSV admins dry run first; all-or-nothing; create or update mode
Students Students โ†’ โฌ† Import CSV, or a class page teachers, admins row by row: valid rows are inserted, invalid rows listed
Users Users โ†’ โฌ† Import CSV admins row by row

The first two (added in v2.1) never store anything until you confirm, and refuse the whole file if any row is invalid. The other two insert the valid rows and report the rest.

Rules for every file

These apply to the quiz-question and course/section imports:

  • Encoding: UTF-8. A byte-order mark (Excel adds one) is fine; other encodings are refused, with a hint.
  • Header: the first row is the header. Column names are case-insensitive and may be in any order.
  • Unknown columns are refused, so a column you expect to be imported is never silently ignored. For example, a marks column is an error.
  • Size: at most 1 MB and 500 rows.
  • Quoting: values may contain commas, quotes (written "") and line breaks, inside double quotes.
  • Re-uploading is safe: rows that already exist are reported as duplicates and skipped.
  • Formula safety: on export, cells that start with =, +, -, @, a tab or a carriage return get a ' prefix, so a spreadsheet won't run them as formulas.

Quiz questions

Steps

  1. Open a class โ†’ + New Quiz.

  2. Under Import questions from CSV, click Download template, or drop your file on the box.

  3. Read the preview. Every row is one of:

    • valid;
    • invalid, with the reason;
    • duplicate, of an earlier line in the file or of a question already in the quiz. Matching ignores case and extra spaces.

    A note warns about text longer than a module can display.

  4. If every row is valid, click Add N questions to this quiz. They appear in the form, where you can still edit or delete them.

  5. Click Create Quiz.

Columns

Column Required Accepts Also accepted as
question_text yes 1โ€“1000 characters question, text
option_a yes 1โ€“200 characters a, option_1
option_b yes 1โ€“200 characters b, option_2
option_c no 1โ€“200 characters c, option_3
option_d no 1โ€“200 characters (only if C is filled) d, option_4
correct_option yes Aโ€“D or 1โ€“4, pointing at a filled option correct, correct_answer, answer

Example

question_text,option_a,option_b,option_c,option_d,correct_option
"What is 2 + 2?",3,4,5,6,B
"Which planet is closest to the Sun?",Mercury,Venus,,,A
"Capital of France, the city?",Paris,Rome,Berlin,,1

Errors you might see

Message Fix
correct_option 'E' must be a letter Aโ€“D or a number 1โ€“4 use Aโ€“D or 1โ€“4
the correct option points at an empty option fill that option, or change the answer
a gap (D filled, C empty) move D to C
unknown column marks remove the column
more than 500 rows / 1 MB split the file
not UTF-8 save as CSV UTF-8

Warnings (not errors): text longer than about 139 bytes (question) or 14 bytes (option) is cut off on modules.

Adding to an existing draft quiz

POST /api/quizzes/{id}/questions/import?dry_run=false with the file. It only works on draft quizzes (409 otherwise). It appends the questions after the existing ones and skips duplicates.

Two imports into the same quiz at the same moment can't interleave: the slower one gets 409. A database error returns 503 and stores nothing.

Courses and sections

Steps

  1. Classrooms โ†’ Import CSV (download the template if needed).
  2. Choose what happens to sections that already exist:
    • Skip them (default): only new sections are created. Uploading the same file twice changes nothing.
    • Update them: existing sections take the file's values. Empty cells keep the current value. The preview lists exactly which fields change. A different teacher becomes the primary teacher; other co-faculty stay.
  3. Drop the file and read the plan:
    • create (and (new course) where a course will be created);
    • duplicate or unchanged;
    • update, with the changes;
    • invalid, with the reason.
  4. Click Create N sections (or Create N, update M). The list refreshes.

Imported classes start inactive, like those created in the form.

Columns

One row per section:

Column Required Rules
course_code yes up to 16 characters; upper-cased. Matched by code; created if new
course_name yes up to 128 characters. For an existing course it must match its name exactly: a rename is reported as a conflict, never applied silently
section yes up to 16 characters; unique within the course
class_code yes up to 32 characters; the class's join code; unique
teacher_username yes an existing, active teacher; becomes the primary teacher and faculty
class_name no default <course_code> <section>
classroom_code no the physical room label (e.g. RM-201); unique
term no Monsoon, Winter or Summer
year no 2000โ€“2100
capacity no 0โ€“5000
location no free text

The layout from the v2.1 brief is also accepted: classroom_code, classroom_name, section_code, section_name (meaning course code, course name, section and class name), with the physical room in a room column.

Example

course_code,course_name,section,class_code,teacher_username,classroom_code,term,year
CS101,Introduction to Computing,A,CS101-A-2026,teacher1,RM-201,Monsoon,2026
CS101,Introduction to Computing,B,CS101-B-2026,teacher2,,Monsoon,2026

Conflicts reported as errors

  • a course code with a different name;
  • a section that already exists under another class code;
  • a class code used by another course or section;
  • a room assigned to another class;
  • duplicates within the file;
  • an unknown or inactive teacher, or an invalid term, year or capacity.

Export

Export CSV downloads every course section in the same layout. Edit it in a spreadsheet and import it in Update mode. Classrooms without a course are left out, because they couldn't be imported again; the page says how many.

Students

Students โ†’ โฌ† Import CSV (or a class page, which also enrolls them). Exactly these 7 columns, all required:

roll_number,student_name,email,phone,program,enrollment_year,graduation_year
ABCDE12345,Asha Rao,[email protected],+91 98765 43210,B.Tech CSE,2024,2028
FGHIJ67890,Ben Ito,[email protected],9876543210,B.Sc Physics,2025,2028
Column Rules
roll_number exactly 10 letters or digits; unique in the file and in the registry; stored upper-case
student_name up to 128 characters
email a valid address
phone 7โ€“15 characters: digits, spaces, + - ( )
program up to 128 characters
enrollment_year, graduation_year 2000โ€“2099; graduation โ‰ฅ enrollment

Behaviour:

  • Row by row: valid rows are inserted; invalid ones are listed with their row number and reason (for example roll_number already exists in database).
  • Columns: a missing or extra column, or a file that isn't .csv, gets a 400.
  • From a class page: new students are also enrolled in that class. Existing students are reported and not enrolled; enroll them with + Enroll Student.

Users (staff)

Users โ†’ โฌ† Import CSV. Columns, all required:

username,email,password,full_name,role
teacher1,[email protected],ChangeMe-1,Dr. Asha Rao,teacher

role is teacher, admin or super_admin. Creating admins needs a super admin. Passwords are at least 6 characters; ask users to change theirs after first sign-in.

Getting the file right in Excel, Google Sheets and LibreOffice

Tool Save as
Excel File โ†’ Save As โ†’ CSV UTF-8 (Comma delimited) (.csv)
Google Sheets File โ†’ Download โ†’ Comma-separated values (.csv) (always UTF-8)
LibreOffice Calc File โ†’ Save As โ†’ Text CSV, character set UTF-8, field delimiter ,, string delimiter "
Numbers File โ†’ Export To โ†’ CSV, encoding Unicode (UTF-8)

Common traps:

  • Enrollment numbers turned into numbers: a spreadsheet can strip leading zeros or turn 00001ABCDE-like values into scientific notation. Format the column as Text before typing.
  • Smart quotes or semicolons: some locales save with ; as the separator. Choose ,.
  • Hidden columns: they are still exported, and get refused as unknown columns.

Scripting imports with the API

TOKEN=โ€ฆ    # from POST /api/auth/login
# Questions: check only (nothing stored)
curl -s -H "Authorization: Bearer $TOKEN" -F [email protected] \
  https://impress.example.edu/api/quizzes/questions/parse
# Questions into draft quiz 12: commit
curl -s -H "Authorization: Bearer $TOKEN" -F [email protected] \
  "https://impress.example.edu/api/quizzes/12/questions/import?dry_run=false"
# Courses and sections: plan, then commit in update mode
curl -s -H "Authorization: Bearer $TOKEN" -F [email protected] \
  "https://impress.example.edu/api/admin/classes/import?mode=update"
curl -s -H "Authorization: Bearer $TOKEN" -F [email protected] \
  "https://impress.example.edu/api/admin/classes/import?mode=update&dry_run=false"
# Export
curl -s -H "Authorization: Bearer $TOKEN" -o sections.csv \
  https://impress.example.edu/api/admin/classes/export.csv

The question report and the section plan are described in API Reference.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ