CSV Imports - Kush-Kelaiya22/imPress GitHub Wiki
Bulk-loading data from spreadsheets: quiz questions, courses and sections, students, and staff. Reference: docs/guides/csv-imports.md and the REST API.
- Which import does what
- Rules for every file
- Quiz questions
- Courses and sections
- Students
- Users (staff)
- Getting the file right in Excel, Google Sheets and LibreOffice
- Scripting imports with the API
| 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.
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
markscolumn 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.
-
Open a class โ + New Quiz.
-
Under Import questions from CSV, click Download template, or drop your file on the box.
-
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.
-
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.
-
Click Create Quiz.
| 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
|
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| 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.
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.
- Classrooms โ Import CSV (download the template if needed).
- 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.
- 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.
- Click Create N sections (or Create N, update M). The list refreshes.
Imported classes start inactive, like those created in the form.
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.
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- 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 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 โ โฌ 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 โ โฌ Import CSV. Columns, all required:
username,email,password,full_name,role
teacher1,[email protected],ChangeMe-1,Dr. Asha Rao,teacherrole 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.
| 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.
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.csvThe question report and the section plan are described in API Reference.