diff --git a/src/Model/Geometry/Reach.py b/src/Model/Geometry/Reach.py
index 7c8ebcd5292ea9723c7fa495fae6a1c0afc08f0c..0fff437ce1cb305e7cddefb828bfcc8bb3a6cf73 100644
--- a/src/Model/Geometry/Reach.py
+++ b/src/Model/Geometry/Reach.py
@@ -23,9 +23,6 @@ class Reach:
         self._guidelines_is_valid = False
         self._guidelines = {}
 
-        # Copy/Paste
-        self.__list_copied_profiles = []
-
     def profile(self, i):
         """Returns profile at index i
 
diff --git a/src/View/Geometry/GeometryWindow.py b/src/View/Geometry/GeometryWindow.py
index 7fc7f85164a9ffb86a3fe3d2c443983c173f458d..e6ec58f988e93003da78debb79dd4e9143d4dd73 100644
--- a/src/View/Geometry/GeometryWindow.py
+++ b/src/View/Geometry/GeometryWindow.py
@@ -367,6 +367,24 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         self._tablemodel.move_row_down(row)
         self.select_current_profile()
 
+    def duplicate(self):
+        rows = [
+            row.row() for row in
+            self.tableView.selectionModel().selectedRows()
+        ]
+
+        profiles = []
+        for row in rows:
+            profiles.append(
+                self._reach.profile(row)
+            )
+
+        if len(profiles) == 0:
+            return
+
+        self._tablemodel.duplicate(rows, profiles)
+        self.select_current_profile()
+
     def copy(self):
         rows = self.tableView\
                    .selectionModel()\
diff --git a/src/View/Geometry/ReachUndoCommand.py b/src/View/Geometry/ReachUndoCommand.py
index 7fa630102f2cdaed61f25a068aaa110936fd938a..ed911c664fd05d06593b8f44882c852aeb03bd50 100644
--- a/src/View/Geometry/ReachUndoCommand.py
+++ b/src/View/Geometry/ReachUndoCommand.py
@@ -128,14 +128,33 @@ class PasteCommand(QUndoCommand):
                 profiles
             )
         )
+        self._profiles.reverse()
 
     def undo(self):
         self._reach.delete_profiles(self._profiles)
 
     def redo(self):
-        self._profiles.reverse()
+        for profile in self._profiles:
+            self._reach.insert_profile(self._row, profile)
 
-        for pro in self._profiles:
-            self._reach.insert_profile(self._row, pro)
 
+class DuplicateCommand(QUndoCommand):
+    def __init__(self, reach, rows, profiles):
+        QUndoCommand.__init__(self)
+
+        self._reach = reach
+        self._rows = rows
+        self._profiles = list(
+            map(
+                lambda p: deepcopy(p),
+                profiles
+            )
+        )
         self._profiles.reverse()
+
+    def undo(self):
+        self._reach.delete_profiles(self._profiles)
+
+    def redo(self):
+        for profile in self._profiles:
+            self._reach.insert_profile(self._rows[0], profile)
diff --git a/src/View/Geometry/qtableview_reach.py b/src/View/Geometry/qtableview_reach.py
index db4aba722af8140a78b8ea5d38d3615b55580752..43d96cdab8d7b01199b6231ab436e5cf777cce92 100644
--- a/src/View/Geometry/qtableview_reach.py
+++ b/src/View/Geometry/qtableview_reach.py
@@ -212,6 +212,20 @@ class TableEditableModel(QAbstractTableModel):
         self.endMoveRows()
         self.layoutChanged.emit()
 
+    def duplicate(self, rows, profiles):
+        self.layoutAboutToBeChanged.emit()
+
+        self._undo_stack.push(
+            DuplicateCommand(
+                self._reach, rows,
+                profiles
+            )
+        )
+
+        self.layoutAboutToBeChanged.emit()
+        self.layoutChanged.emit()
+
+
     def paste(self, row, header, data):
         if row > self._reach.number_profiles:
             return