diff --git a/frontend/src/components/export/DataExport.vue b/frontend/src/components/export/DataExport.vue
index 4bed957d5d887366c03bd0b9235ccb3dea2bd02e..8fd23f3174eba2cb1134519b56419c2da0fd2212 100644
--- a/frontend/src/components/export/DataExport.vue
+++ b/frontend/src/components/export/DataExport.vue
@@ -42,7 +42,7 @@
             @click="exportDialog = false"
           >close</v-btn>
           <v-spacer/>
-          <v-btn id="export-data-download-btn" flat outline @click="getExportFile"
+          <v-btn id="export-data-download-btn" flat outline @click="getExportFile('data')"
           >{{mapFile || mapFileLoaded ? 'Download and apply mapping' : 'Download without mapping'}}</v-btn>
         </v-card-actions>
       </v-card-text>
@@ -56,105 +56,40 @@ import { getters } from '@/store/getters'
 import ax, { StudentExportItem, fetchStudentExportData } from '@/api'
 import FileSelect from '@/components/util/FileSelect.vue'
 import { mutations as mut } from '@/store/mutations'
-import { parseCSVMapMixin } from '@/components/mixins/mixins'
-
-enum ExportType {
-  JSON = 'JSON',
-  CSV = 'CSV'
-}
+import { exportMixin, ExportType } from '@/components/mixins/mixins'
 
 @Component({
   components: { FileSelect }
 })
-export default class DataExport extends Mixins(parseCSVMapMixin) {
+export default class DataExport extends Mixins(exportMixin) {
   exportDialog = true
   mapFile: File | null = null
   setPasswords = false
   exportType = ExportType.CSV
 
-  get corrected () { return getters.corrected }
   get studentMap () { return getters.state.studentMap }
-  get mapFileLoaded () {
-    return Object.keys(getters.state.studentMap).length > 0
-  }
-  get exportColor () {
-    return this.corrected ? 'green darken-1' : 'red lighten-1'
-  }
-  get availableExportTypes (): ExportType[] {
-    return Object.values(ExportType)
-  }
-
-  showDialog () {
-    this.exportDialog = true
-  }
-
-  readMapFileAndCommit () {
-    const fileReader = new FileReader()
-    return new Promise((resolve, reject) => {
-      // @ts-ignore
-      fileReader.onload = event => {
-        // @ts-ignore typings of EventTarget seem to be wrong
-        const studentMap = this.parseCSVMap(event.target.result)
-        mut.SET_STUDENT_MAP(studentMap)
-        resolve()
-      }
-      fileReader.onerror = () => {
-        fileReader.abort()
-        reject(new Error('Problem parsing input file.'))
-      }
-
-      if (!this.mapFile) {
-        reject(new Error('Can only call' +
-          ' readMapFileAndCommit when mapFile is not undefined'))
-      } else {
-        fileReader.readAsText(this.mapFile)
-      }
-    })
-  }
 
   applyMapping (studentExport: StudentExportItem[]) {
-    return studentExport.map(student => {
-      return {
-        ...student,
-        Matrikel: this.studentMap[student.Matrikel].matrikelNo,
-        Name: this.studentMap[student.Matrikel].name
-      }
-    })
-  }
-
-  jsonToCSV (studentExport: StudentExportItem[], delimeter = ';') {
-    let headerLine = Object.keys(studentExport[0]).reduce((acc: string, curr) => {
-      if (curr === 'Scores') {
-        return acc
-      }
-      return acc ? `${acc};${curr}` : `${curr}`
-    }, '')
-    headerLine += Object.values(studentExport[0].Scores)
-      .reduce((acc: string, curr) => {
-        return `${acc};${curr.type}`
-      }, '')
-
-    const lines = studentExport.map(student => {
-      const normalFields = Object.values(student).reduce((acc: string, curr): string => {
-        // skip  the Scores field
-        if (typeof curr === 'object') {
-          return acc
+    console.log(studentExport)
+    studentExport.forEach(student => {
+      if (this.studentMap[student.Matrikel]) {
+        student = {
+          ...student,
+          Matrikel: this.studentMap[student.Matrikel].matrikelNo,
+          Name: this.studentMap[student.Matrikel].name
         }
-        return acc ? `${acc};${curr}` : `${curr}`
-      }, '')
-
-      const scoreFields = Object.values(student.Scores).reduce((acc: string, curr) => {
-        return `${acc};${curr.score}`
-      }, '')
-      return normalFields + scoreFields
+      } else {
+        this.$notify({
+          title: `Unknown student: ${student.Name}`,
+          text: `Student ${student.Name} is missing in mapping file`,
+          type: 'error',
+          duration: -1
+        })
+      }
     })
-
-    return headerLine + lines.reduce((acc, curr) => {
-      return `${acc}\n${curr}`
-    }, '') + '\n' // add trailing newline
   }
 
-  createDownloadPopup (content: string | StudentExportItem[], fileType: ExportType) {
+  createDownloadPopup (content: string | StudentExportItem[], fileType: ExportType): void {
     const blobProperties: BlobPropertyBag = {}
     if (fileType === ExportType.JSON) {
       blobProperties.type = 'application/json'
@@ -165,39 +100,6 @@ export default class DataExport extends Mixins(parseCSVMapMixin) {
     const blobData = new Blob([<string> content], blobProperties)
     window.open(window.URL.createObjectURL(blobData))
   }
-
-  optionalConvertAndCreatePopup (studentData: StudentExportItem[]) {
-    const convertedData = this.exportType === ExportType.CSV
-      ? this.jsonToCSV(studentData) : studentData
-
-    this.createDownloadPopup(convertedData, this.exportType)
-  }
-
-  async getMappedExportFile (studentData: StudentExportItem[]) {
-    if (!this.mapFile && !this.mapFileLoaded) {
-      throw new Error('Either mapFile must be selected or already loaded ' +
-                      'to call getMappedExportFile')
-    }
-    if (this.mapFile) {
-      await this.readMapFileAndCommit()
-    }
-    const mappedData = this.applyMapping(studentData)
-    this.optionalConvertAndCreatePopup(mappedData)
-  }
-
-  async getExportFile () {
-    const studentData = await fetchStudentExportData({ setPasswords: this.setPasswords })
-
-    if (this.mapFile || this.mapFileLoaded) {
-      this.getMappedExportFile(studentData)
-    } else {
-      this.optionalConvertAndCreatePopup(studentData)
-    }
-  }
-
-  hide () {
-    this.$emit('hide')
-  }
 }
 </script>
 
diff --git a/frontend/src/components/export/InstanceExport.vue b/frontend/src/components/export/InstanceExport.vue
index 91c63ba69a5a05e6fb508026c64a223729b74bf1..681e0e6b9958f92c2c2db814a320b2362d90ed1a 100644
--- a/frontend/src/components/export/InstanceExport.vue
+++ b/frontend/src/components/export/InstanceExport.vue
@@ -20,7 +20,7 @@
             @click="exportDialog = false"
           >close</v-btn>
           <v-spacer/>
-          <v-btn id="instance-export-dl" flat outline @click="getExportFile"
+          <v-btn id="instance-export-dl" flat outline @click="getExportFile('instance')"
           >{{mapFile || mapFileLoaded ? 'Download and apply mapping' : 'Download without mapping'}}</v-btn>
         </v-card-actions>
       </v-card-text>
@@ -34,50 +34,17 @@ import { getters } from '@/store/getters'
 import ax, { StudentExportItem, fetchStudentExportData, fetchInstanceExportData, InstanceExportData } from '@/api'
 import FileSelect from '@/components/util/FileSelect.vue'
 import { mutations as mut } from '@/store/mutations'
-import { parseCSVMapMixin } from '@/components/mixins/mixins'
+import { exportMixin, ExportType } from '@/components/mixins/mixins'
 
 @Component({
   components: { FileSelect }
 })
-export default class DataExport extends Mixins(parseCSVMapMixin) {
+export default class DataExport extends exportMixin {
   exportDialog = true
   mapFile: File | null = null
+  exportType = ExportType.JSON     // instance export is only available as JSON
 
-  get corrected () { return getters.corrected }
   get studentMap () { return getters.state.studentMap }
-  get mapFileLoaded () {
-    return Object.keys(getters.state.studentMap).length > 0
-  }
-  get exportColor () {
-    return this.corrected ? 'green darken-1' : 'red lighten-1'
-  }
-
-  showDialog () {
-    this.exportDialog = true
-  }
-
-  readMapFileAndCommit () {
-    const fileReader = new FileReader()
-    return new Promise((resolve, reject) => {
-      fileReader.onload = event => {
-        // @ts-ignore typings of EventTarget seem to be wrong
-        const studentMap = this.parseCSVMap(event.target.result)
-        mut.SET_STUDENT_MAP(studentMap)
-        resolve()
-      }
-      fileReader.onerror = () => {
-        fileReader.abort()
-        reject(new Error('Problem parsing input file.'))
-      }
-
-      if (!this.mapFile) {
-        reject(new Error('Can only call' +
-          ' readMapFileAndCommit when mapFile is not undefined'))
-      } else {
-        fileReader.readAsText(this.mapFile)
-      }
-    })
-  }
 
   applyMapping (instanceExport: InstanceExportData) {
     instanceExport.students.forEach(student => {
@@ -96,39 +63,13 @@ export default class DataExport extends Mixins(parseCSVMapMixin) {
     })
   }
 
-  createDownloadPopup (content: string | InstanceExportData) {
+  createDownloadPopup (content: string | InstanceExportData): void {
     const blobProperties: BlobPropertyBag = {}
     blobProperties.type = 'application/json'
     content = JSON.stringify(content)
     const blobData = new Blob([<string> content], blobProperties)
     window.open(window.URL.createObjectURL(blobData))
   }
-
-  async getMappedExportFile (studentData: InstanceExportData) {
-    if (!this.mapFile && !this.mapFileLoaded) {
-      throw new Error('Either mapFile must be selected or already loaded ' +
-                      'to call getMappedExportFile')
-    }
-    if (this.mapFile) {
-      await this.readMapFileAndCommit()
-    }
-    this.applyMapping(studentData)
-    this.createDownloadPopup(studentData)
-  }
-
-  async getExportFile () {
-    const instanceData = await fetchInstanceExportData()
-
-    if (this.mapFile || this.mapFileLoaded) {
-      this.getMappedExportFile(instanceData)
-    } else {
-      this.createDownloadPopup(instanceData)
-    }
-  }
-
-  hide () {
-    this.$emit('hide')
-  }
 }
 </script>
 
diff --git a/frontend/src/components/mixins/mixins.ts b/frontend/src/components/mixins/mixins.ts
index caae87fff23b45ef41a8dcdd20a0135233e541bb..972371d08fd6f147cd4264f6836e1b75413c655a 100644
--- a/frontend/src/components/mixins/mixins.ts
+++ b/frontend/src/components/mixins/mixins.ts
@@ -1,7 +1,28 @@
 import { Vue, Component } from 'vue-property-decorator'
+import { fetchStudentExportData, StudentExportItem, InstanceExportData, fetchInstanceExportData } from '@/api'
+import { getters } from '@/store/getters'
+import { mutations as mut } from '@/store/mutations'
+
+export enum ExportType {
+  JSON = 'JSON',
+  CSV = 'CSV'
+}
 
 @Component
-export class parseCSVMapMixin extends Vue {
+export class exportMixin extends Vue {
+  exportDialog = true
+  mapFile: File | null = null
+  setPasswords = false
+  exportType = ExportType.CSV
+
+  get mapFileLoaded () {
+    return Object.keys(getters.state.studentMap).length > 0
+  }
+
+  get availableExportTypes (): ExportType[] {
+    return Object.values(ExportType)
+  }
+
   parseCSVMap (csvMap: string) {
     let lines = csvMap.split('\n')
     lines.shift() // drop the first line since it contains only headings
@@ -14,4 +35,107 @@ export class parseCSVMapMixin extends Vue {
       return acc
     }, {})
   }
+
+  async getExportFile (type: string) {
+    let studentData
+    if (type === 'data') {
+      studentData = await fetchStudentExportData({ setPasswords: this.setPasswords })
+    } else if (type === 'instance') {
+      studentData = await fetchInstanceExportData()
+    } else {
+      throw new Error('Unsupported export type')
+    }
+    
+    if (this.mapFile || this.mapFileLoaded) {
+      this.getMappedExportFile(studentData)
+    } else {
+      this.optionalConvertAndCreatePopup(studentData)
+    }
+  }
+
+  jsonToCSV (studentExport: StudentExportItem[], delimeter = ';') {
+    let headerLine = Object.keys(studentExport[0]).reduce((acc: string, curr) => {
+      if (curr === 'Scores') {
+        return acc
+      }
+      return acc ? `${acc};${curr}` : `${curr}`
+    }, '')
+    headerLine += Object.values(studentExport[0].Scores)
+      .reduce((acc: string, curr) => {
+        return `${acc};${curr.type}`
+      }, '')
+
+    const lines = studentExport.map(student => {
+      const normalFields = Object.values(student).reduce((acc: string, curr): string => {
+        // skip  the Scores field
+        if (typeof curr === 'object') {
+          return acc
+        }
+        return acc ? `${acc};${curr}` : `${curr}`
+      }, '')
+
+      const scoreFields = Object.values(student.Scores).reduce((acc: string, curr) => {
+        return `${acc};${curr.score}`
+      }, '')
+      return normalFields + scoreFields
+    })
+
+    return headerLine + lines.reduce((acc, curr) => {
+      return `${acc}\n${curr}`
+    }, '') + '\n' // add trailing newline
+  }
+
+  optionalConvertAndCreatePopup(studentData: StudentExportItem[] | InstanceExportData) {
+    const convertedData = this.exportType === ExportType.CSV
+      ? this.jsonToCSV(studentData as StudentExportItem[]) : studentData
+      // we have a cast here because only student export may be converted to csv
+
+    this.createDownloadPopup(convertedData, this.exportType)
+  }
+
+  async getMappedExportFile (studentData: StudentExportItem[] | InstanceExportData) {
+    if (!this.mapFile && !this.mapFileLoaded) {
+      throw new Error('Either mapFile must be selected or already loaded ' +
+                      'to call getMappedExportFile')
+    }
+    if (this.mapFile) {
+      await this.readMapFileAndCommit()
+    }
+    this.applyMapping(studentData)
+    this.optionalConvertAndCreatePopup(studentData)
+  }
+
+  readMapFileAndCommit () {
+    const fileReader = new FileReader()
+    return new Promise((resolve, reject) => {
+      fileReader.onload = event => {
+        // @ts-ignore typings of EventTarget seem to be wrong
+        const studentMap = this.parseCSVMap(event.target.result)
+        mut.SET_STUDENT_MAP(studentMap)
+        resolve()
+      }
+      fileReader.onerror = () => {
+        fileReader.abort()
+        reject(new Error('Problem parsing input file.'))
+      }
+
+      if (!this.mapFile) {
+        reject(new Error('Can only call' +
+          ' readMapFileAndCommit when mapFile is not undefined'))
+      } else {
+        fileReader.readAsText(this.mapFile)
+      }
+    })
+  }
+
+  hide () {
+    this.$emit('hide')
+  }
+
+  showDialog () {
+    this.exportDialog = true
+  }
+
+  applyMapping (exportData: StudentExportItem[] | InstanceExportData): void { throw new Error("Not implemented.") }
+  createDownloadPopup (content: string | StudentExportItem[] | InstanceExportData, fileType: ExportType): void { throw new Error("Not implemented.") }
 }