diff --git a/soitool/modules/code_table_base.py b/soitool/modules/code_table_base.py
index ff219f4062f50561849a31791bb6660723a8a3e8..7f3e2b9ec47cec3e23689b4d67a2f70847128a36 100644
--- a/soitool/modules/code_table_base.py
+++ b/soitool/modules/code_table_base.py
@@ -1,5 +1,8 @@
 """..."""
 from PySide2.QtWidgets import QTableWidget, QTableWidgetItem
+from PySide2 import QtGui
+from PySide2.QtCore import Qt
+from soitool.coder import get_code_set, get_code
 from soitool.modules.module_base import (
     ModuleBase,
     get_table_size,
@@ -7,6 +10,9 @@ from soitool.modules.module_base import (
     HEADLINE_FONT,
 )
 
+AUTHENTICATIONBOARDMODULE = "AuthenticationBoardModule"
+SUBTRACTORCODESMODULE = "SubtractorcodesModule"
+
 
 class Meta(type(ModuleBase), type(QTableWidget)):
     """Used as a metaclass to enable multiple inheritance."""
@@ -15,6 +21,154 @@ class Meta(type(ModuleBase), type(QTableWidget)):
 class CodeTableBase(ModuleBase, QTableWidget, metaclass=Meta):
     """..."""
 
-    def __init__(self):
+    def __init__(self, size, data):
+        if self.type not in [
+            AUTHENTICATIONBOARDMODULE,
+            SUBTRACTORCODESMODULE,
+        ]:
+            raise ValueError(
+                "Invalid value for class-variable type: "
+                "'{}'".format(self.type)
+            )
         QTableWidget.__init__(self)
         ModuleBase.__init__(self)
+
+        # Remove headers and scrollbars
+        self.horizontalHeader().hide()
+        self.verticalHeader().hide()
+        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+
+        # If parameters are None, generate new table
+        if size is None and data is None:
+            self.generate_table()
+            self.resizeColumnsToContents()
+            self.insert_headline()
+
+            # Resize height of rows and set size of window
+            resize_table(self, resize_column=False)
+        else:
+            self.setColumnCount(len(data[1]))
+            self.setRowCount(len(data) - 1)  # - 1 to skip headline
+
+            # Set cell-items
+            for i in range(self.rowCount()):
+                for j in range(self.columnCount()):
+                    item = QTableWidgetItem(data[i + 1][j])  # +1 skip headline
+                    self.setItem(i, j, item)
+
+            self.resizeColumnsToContents()
+            resize_table(self, resize_column=False)
+            self.setFixedWidth(size["width"])
+            self.setFixedHeight(size["height"])
+
+            self.insert_headline(data[0])
+
+    def generate_table(self):
+        """Insert row identifiers and authentication codes..........."""
+        # Set number of rows and columns
+        self.setRowCount(self.start_no_of_codes)
+        self.setColumnCount(3)
+
+        # Generate codes
+        codes = list(
+            get_code_set(
+                self.start_no_of_codes,
+                self.code_length,
+                self.code_character_type,
+                self.space_interval,
+            )
+        )
+
+        # Insert table data
+        for i in range(self.start_no_of_codes):
+            if self.type == AUTHENTICATIONBOARDMODULE:
+                # Insert non-editable row identifier in first column
+                item_first = QTableWidgetItem(self.row_identifiers[i])
+                item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
+                self.setItem(i, 0, item_first)
+
+                # Insert non-editable row identifier (int) in second column
+                item_second = QTableWidgetItem(str(i))
+                item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
+                self.setItem(i, 1, item_second)
+
+                # Insert non-editable code in third column
+                item_third = QTableWidgetItem(codes[i])
+                item_third.setFlags(item_third.flags() ^ Qt.ItemIsEditable)
+                self.setItem(i, 2, item_third)
+            elif self.type == SUBTRACTORCODESMODULE:
+                print("NOPE")
+
+    def insert_headline(self):
+        """Insert headline text."""
+        item_headline = QTableWidgetItem(self.headline)
+        item_headline.setTextAlignment(Qt.AlignHCenter)
+        item_headline.setFont(HEADLINE_FONT)
+
+        self.insertRow(0)
+        self.setItem(0, 0, item_headline)
+        self.setSpan(0, 0, 1, self.columnCount())  # Make cell span all columns
+
+    def generate_unique_authentication_code(self):
+        """Generate authentication-code that does not already exist.
+
+        Returns
+        -------
+        string
+            Generated, unique authentication-code
+        """
+        # Get existing codes
+        existing_codes = self.get_codes()
+
+        # Randomly generate a new code until it is unique
+        unique_code = False
+        while not unique_code:
+            code = get_code(
+                self.code_length, self.code_character_type, self.space_interval
+            )
+            unique_code = code not in existing_codes
+
+        return code
+
+    def get_codes(self):
+        """Get all authentication-codes in table.
+
+        Returns
+        -------
+        List
+            List containing authentication-codes.
+        """
+        codes = []
+
+        # Start with row 1 to skip headline-row
+        for i in range(1, self.rowCount()):
+            codes.append(self.item(i, 2).text())
+
+        return codes
+
+    def get_size(self):
+        """Return size of widget."""
+        return get_table_size(self)
+
+    def get_data(self):
+        """Return list containing all data.
+
+        Returns
+        -------
+        List
+            List[0] contains headline,
+            list[x][y] represents value of row x, column y.
+        """
+        data = []
+        item_headline = self.item(0, 0)
+        if item_headline is not None:
+            data.append(item_headline.text())
+
+        for i in range(1, self.rowCount()):
+            row = []
+            for j in range(self.columnCount()):
+                row.append(self.item(i, j).text())
+            data.append(row)
+
+        return data
diff --git a/soitool/modules/module_authentication_board.py b/soitool/modules/module_authentication_board.py
index 260a0f919ba432ed7329781047ecc86186074550..6dc6912475e5c7a1315a0df3e904513b982fdf69 100644
--- a/soitool/modules/module_authentication_board.py
+++ b/soitool/modules/module_authentication_board.py
@@ -1,20 +1,14 @@
 """Module containing SOI-module 'Autentifiseringstavle'."""
 import string
-from PySide2.QtWidgets import QTableWidget, QTableWidgetItem
+from PySide2.QtWidgets import QTableWidgetItem
 from PySide2 import QtGui
 from PySide2.QtCore import Qt
-from soitool.coder import get_code_set, get_code
-from soitool.modules.module_base import (
-    ModuleBase,
-    get_table_size,
-    resize_table,
-    HEADLINE_FONT,
-)
+from soitool.modules.module_base import resize_table
 from soitool.modules.code_table_base import CodeTableBase
 
-START_NO_OF_AUTHENTICATION_CODES = 10
+START_NO_OF_CODES = 10  # Maximum value is len(ROW_IDENTIFIERS)
 CODE_LENGTH = 25
-CODE_CHARACTERS = "ascii"  # Has to be 'ascii', 'digits' or 'combo'
+CODE_CHARACTER_TYPE = "ascii"  # Has to be 'ascii', 'digits' or 'combo'
 # Codes will consist of A-Z if 'ascii', 0-9 if 'digits' and A-Z+0-9 if 'combo'.
 ROW_IDENTIFIERS = string.ascii_uppercase  # Characters for first column,
 # it's length determines maximum number of codes (rows).
@@ -24,10 +18,6 @@ SPACE_INTERVAL = 5  # Adds space between sets of characters, 0 => no spaces
 HEADLINE_TEXT = "Autentiseringstavle"
 
 
-# class Meta(type(ModuleBase), type(QTableWidget)):
-#    """Used as a metaclass to enable multiple inheritance."""
-
-
 class AuthenticationBoardModule(CodeTableBase):
     """Modified QTableWidget representing a 'Autentifiseringstavle'.
 
@@ -51,120 +41,27 @@ class AuthenticationBoardModule(CodeTableBase):
 
     def __init__(self, size=None, data=None):
         self.type = "AuthenticationBoardModule"
-        # QTableWidget.__init__(self)
-        # ModuleBase.__init__(self)
-        CodeTableBase.__init__(self)
 
-        if CODE_CHARACTERS == "ascii":
+        self.start_no_of_codes = START_NO_OF_CODES
+        self.code_length = CODE_LENGTH
+        self.space_interval = SPACE_INTERVAL
+        self.row_identifiers = ROW_IDENTIFIERS
+
+        if CODE_CHARACTER_TYPE == "ascii":
             self.code_characters = string.ascii_uppercase
-        elif CODE_CHARACTERS == "digits":
+        elif CODE_CHARACTER_TYPE == "digits":
             self.code_characters = string.digits
-        elif CODE_CHARACTERS == "combo":
+        elif CODE_CHARACTER_TYPE == "combo":
             self.code_characters = string.ascii_uppercase + string.digits
         else:
             raise ValueError(
-                "Invalid value for CONSTANT 'CODE_CHARACTERS': "
-                "'{}'".format(CODE_CHARACTERS)
+                "Invalid value for CONSTANT 'CODE_CHARACTER_TYPE': "
+                "'{}'".format(CODE_CHARACTER_TYPE)
             )
+        self.code_character_type = CODE_CHARACTER_TYPE
+        self.headline = HEADLINE_TEXT
 
-        # Remove headers and scrollbars
-        self.horizontalHeader().hide()
-        self.verticalHeader().hide()
-        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
-        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
-
-        # If parameters are None, generate new table
-        if size is None and data is None:
-            self.generate_table()
-            self.resizeColumnsToContents()
-            self.insert_headline()
-
-            # Resize height of rows and set size of window
-            resize_table(self, resize_column=False)
-        else:
-            self.setColumnCount(len(data[1]))
-            self.setRowCount(len(data) - 1)  # - 1 to skip headline
-
-            # Set cell-items
-            for i in range(self.rowCount()):
-                for j in range(self.columnCount()):
-                    item = QTableWidgetItem(data[i + 1][j])  # +1 skip headline
-                    self.setItem(i, j, item)
-
-            self.resizeColumnsToContents()
-            resize_table(self, resize_column=False)
-            self.setFixedWidth(size["width"])
-            self.setFixedHeight(size["height"])
-
-            self.insert_headline(data[0])
-
-    def generate_table(self):
-        """Insert row identifiers and authentication codes."""
-        # Set number of rows and columns
-        self.setRowCount(START_NO_OF_AUTHENTICATION_CODES)
-        self.setColumnCount(3)
-
-        # Generate codes
-        codes = list(
-            get_code_set(
-                START_NO_OF_AUTHENTICATION_CODES,
-                CODE_LENGTH,
-                CODE_CHARACTERS,
-                SPACE_INTERVAL,
-            )
-        )
-
-        # Insert table data
-        for i in range(START_NO_OF_AUTHENTICATION_CODES):
-            # Insert non-editable row identifier in first column
-            item_first = QTableWidgetItem(ROW_IDENTIFIERS[i])
-            item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
-            self.setItem(i, 0, item_first)
-
-            # Insert non-editable row identifier (int) in second column
-            item_second = QTableWidgetItem(str(i))
-            item_second.setFlags(item_second.flags() ^ Qt.ItemIsEditable)
-            self.setItem(i, 1, item_second)
-
-            # Insert non-editable code in third column
-            item_third = QTableWidgetItem(codes[i])
-            item_third.setFlags(item_third.flags() ^ Qt.ItemIsEditable)
-            self.setItem(i, 2, item_third)
-
-    def insert_headline(self, text=HEADLINE_TEXT):
-        """Insert headline text.
-
-        Parameters
-        ----------
-        text : string, optional
-            The headline text, by default HEADLINE_TEXT
-        """
-        item_headline = QTableWidgetItem(text)
-        item_headline.setTextAlignment(Qt.AlignHCenter)
-        item_headline.setFont(HEADLINE_FONT)
-
-        self.insertRow(0)
-        self.setItem(0, 0, item_headline)
-        self.setSpan(0, 0, 1, self.columnCount())  # Make cell span all columns
-
-    def generate_unique_authentication_code(self):
-        """Generate authentication-code that does not already exist.
-
-        Returns
-        -------
-        string
-            Generated, unique authentication-code
-        """
-        # Get existing codes
-        existing_codes = self.get_codes()
-
-        # Randomly generate a new code until it is unique
-        unique_code = False
-        while not unique_code:
-            code = get_code(CODE_LENGTH, CODE_CHARACTERS, SPACE_INTERVAL)
-            unique_code = code not in existing_codes
-
-        return code
+        CodeTableBase.__init__(self, size, data)
 
     def keyPressEvent(self, event):
         """Add or remove row when 'Ctrl + +' and 'Ctrl + -' are pressed."""
@@ -228,48 +125,6 @@ class AuthenticationBoardModule(CodeTableBase):
                 self.item(i, 1).setText(str(i - 1))
         resize_table(self, resize_column=False)
 
-    def get_codes(self):
-        """Get all authentication-codes in table.
-
-        Returns
-        -------
-        List
-            List containing authentication-codes.
-        """
-        codes = []
-
-        # Start with row 1 to skip headline-row
-        for i in range(1, self.rowCount()):
-            codes.append(self.item(i, 2).text())
-
-        return codes
-
-    def get_size(self):
-        """Return size of widget."""
-        return get_table_size(self)
-
-    def get_data(self):
-        """Return list containing all data.
-
-        Returns
-        -------
-        List
-            List[0] contains headline,
-            list[x][y] represents value of row x, column y.
-        """
-        content = []
-        item_headline = self.item(0, 0)
-        if item_headline is not None:
-            content.append(item_headline.text())
-
-        for i in range(1, self.rowCount()):
-            row = []
-            for j in range(self.columnCount()):
-                row.append(self.item(i, j).text())
-            content.append(row)
-
-        return content
-
     @staticmethod
     def get_user_friendly_name():
         """Get user-friendly name of module."""
diff --git a/soitool/modules/module_subtractorcodes.py b/soitool/modules/module_subtractorcodes.py
new file mode 100644
index 0000000000000000000000000000000000000000..3233b65ed8a476c624a638b7392bdf4931e972f6
--- /dev/null
+++ b/soitool/modules/module_subtractorcodes.py
@@ -0,0 +1,41 @@
+"""Module containing SOI-module 'Subtraktorkoder'."""
+import string
+from PySide2.QtWidgets import QTableWidgetItem
+from PySide2 import QtGui
+from PySide2.QtCore import Qt
+from soitool.modules.module_base import resize_table
+from soitool.modules.code_table_base import CodeTableBase
+
+START_NO_OF_CODES = 7
+CODE_LENGTH = 8
+SPACE_INTERVAL = 4
+
+HEADLINE_TEXT = "Subtraktorkoder"
+
+
+class SubtractorcodesModule(CodeTableBase):
+    """..."""
+
+    def __init__(self, size=None, data=None):
+        self.type = "SubtractorcodesModule"
+
+        self.start_no_of_codes = START_NO_OF_CODES
+        self.code_length = CODE_LENGTH
+        self.space_interval = SPACE_INTERVAL
+        # Characters for first and second column,
+        # it's length/2 it the maximum number of codes (rows).
+        self.row_identifiers = string.ascii_uppercase
+        self.code_character_type = "digits"
+        self.headline = HEADLINE_TEXT
+
+        CodeTableBase.__init__(self, size, data)
+
+    @staticmethod
+    def get_user_friendly_name():
+        """Get user-friendly name of module."""
+        return "Autentiseringstavle"
+
+    @staticmethod
+    def get_icon():
+        """Get icon of module."""
+        return QtGui.QIcon("soitool/media/authenticationboardmodule.png")
diff --git a/soitool/new_module_dialog.py b/soitool/new_module_dialog.py
index acc3746ca017a7d8869694a71d58ee7788843338..c0b33101cbae9df2a79d25d94c3bd22933575236 100644
--- a/soitool/new_module_dialog.py
+++ b/soitool/new_module_dialog.py
@@ -16,6 +16,7 @@ from soitool.modules.module_table import TableModule
 from soitool.modules.module_authentication_board import (
     AuthenticationBoardModule,
 )
+from soitool.modules.module_subtractorcodes import SubtractorcodesModule
 from soitool.modules.module_freetext import FreeTextModule
 
 
@@ -25,6 +26,7 @@ from soitool.modules.module_freetext import FreeTextModule
 MODULE_CHOICES = [
     TableModule,
     AuthenticationBoardModule,
+    SubtractorcodesModule,
     FreeTextModule,
 ]