diff --git a/src/Model/Geometry/PointXYZ.py b/src/Model/Geometry/PointXYZ.py
index 7df8123c8c4d5b3d5bdf7ed636894b57313dda09..78d5a09fb5f8aee6001c212f44e65c3d2894e700 100644
--- a/src/Model/Geometry/PointXYZ.py
+++ b/src/Model/Geometry/PointXYZ.py
@@ -14,6 +14,29 @@ class PointXYZ(Point):
         self._y = float(y)
         self._z = float(z)
 
+    @classmethod
+    def from_data(cls, header, data):
+        point = None
+        try:
+            if len(header) == 0:
+                point = cls(
+                    *data
+                )
+            else:
+                valid_header = {'name', 'x', 'y', 'z'}
+                d = {}
+                for i, v in enumerate(data):
+                    h = header[i].strip().lower().split(' ')[0]
+                    if h in valid_header:
+                        d[h] = v
+
+                point = cls(**d)
+        except Exception as e:
+            raise ClipboardFormatError(header, data)
+
+        return point
+
+
     def __repr__(self):
         return f"({self._x}, {self._y}, {self._z}, {self._name})"
 
diff --git a/src/Model/Geometry/ProfileXYZ.py b/src/Model/Geometry/ProfileXYZ.py
index 1f2b0dddb43b69ed017e96f4e09d4181d84a7e61..5edff60dfc3b3aa8f43e65efeaf9f991b19f5f58 100644
--- a/src/Model/Geometry/ProfileXYZ.py
+++ b/src/Model/Geometry/ProfileXYZ.py
@@ -5,6 +5,7 @@ from typing import List
 
 from tools import timer
 
+from Model.Except import ClipboardFormatError
 from Model.Geometry.Profile import Profile
 from Model.Geometry.PointXYZ import PointXYZ
 from Model.Geometry.Vector_1d import Vector1d
diff --git a/src/View/ASubWindow.py b/src/View/ASubWindow.py
index 89fd37b3d6c624bfb95116242a85b0bce55e4a55..9dd04f123c82ca477681ccabf796aac258dccbb2 100644
--- a/src/View/ASubWindow.py
+++ b/src/View/ASubWindow.py
@@ -20,6 +20,8 @@ from PyQt5.QtCore import (
 )
 from PyQt5.uic import loadUi
 
+from Model.Except import ClipboardFormatError
+
 class WindowToolKit(object):
     def __init__(self, parent=None):
         super(WindowToolKit, self).__init__()
diff --git a/src/View/Geometry/GeometryWindow.py b/src/View/Geometry/GeometryWindow.py
index 3c162535f1871aa03a5bb8dcc2c571bbc503ef2f..7fc7f85164a9ffb86a3fe3d2c443983c173f458d 100644
--- a/src/View/Geometry/GeometryWindow.py
+++ b/src/View/Geometry/GeometryWindow.py
@@ -386,6 +386,9 @@ class GeometryWindow(QMainWindow, WindowToolKit):
     def paste(self):
         header, data = self.parseClipboardTable()
 
+        if len(data) == 0:
+            return
+
         if len(header) != 0:
             header.append("reach")
         for row in data:
diff --git a/src/View/Geometry/Profile/ProfileUndoCommand.py b/src/View/Geometry/Profile/ProfileUndoCommand.py
index 7036d6613311a844e280a3ef0a61d795b3451e5d..d0d45b990af3c56b1041c59bfbf57cbdcbaeff74 100644
--- a/src/View/Geometry/Profile/ProfileUndoCommand.py
+++ b/src/View/Geometry/Profile/ProfileUndoCommand.py
@@ -141,8 +141,8 @@ class PasteCommand(QUndoCommand):
         self._points.reverse()
 
     def undo(self):
-        for ind in range(len(self._profiles)):
-            self._profile.delete(self._row)
+        for ind in range(len(self._points)):
+            self._profile.delete([self._row])
 
     def redo(self):
         for point in self._points:
diff --git a/src/View/Geometry/Profile/ProfileWindow.py b/src/View/Geometry/Profile/ProfileWindow.py
index d17d98d0212b216457114c27f1f6838912ed7b7c..3654b8051050353bf9d1f94e0e03bc67f5b3471f 100644
--- a/src/View/Geometry/Profile/ProfileWindow.py
+++ b/src/View/Geometry/Profile/ProfileWindow.py
@@ -18,18 +18,17 @@ from PyQt5.QtWidgets import (
     QUndoStack, QShortcut,
 )
 
+from View.ASubWindow import WindowToolKit
 from View.Geometry.Profile.mainwindow_ui_profile import Ui_MainWindow
-
 from View.Geometry.Profile.Plot import Plot
-
+from View.Geometry.Profile.qtableview_profile import *
 from Model.Geometry.Reach import Reach
 from Model.Geometry.ProfileXYZ import ProfileXYZ
-from View.Geometry.Profile.qtableview_profile import *
 
 _translate = QCoreApplication.translate
 
 
-class ProfileWindow(QMainWindow):
+class ProfileWindow(QMainWindow, WindowToolKit):
     def __init__(self, profile=None, parent=None):
         self.parent = parent
         super(ProfileWindow, self).__init__(self.parent)
@@ -132,6 +131,12 @@ class ProfileWindow(QMainWindow):
         self.ui.tableView.model().blockSignals(False)
 
     def index_selected_row(self):
+        rows = self.ui.tableView\
+                      .selectionModel()\
+                      .selectedRows()
+        if len(rows) == 0:
+            return 0
+
         return self.ui.tableView\
                       .selectionModel()\
                       .selectedRows()[0]\
@@ -201,23 +206,36 @@ class ProfileWindow(QMainWindow):
         self.update_plot()
 
     def copy(self):
-        rows = self.tableView\
-                   .selectionModel()\
-                   .selectedRows()
-
-        self._clipboard = []
+        rows = self.ui.tableView\
+                      .selectionModel()\
+                      .selectedRows()
+        table = []
+        table.append(["x", "y", "z", "name"])
 
         for row in rows:
-            self._clipboard.append(
-                deepcopy(
-                    self._reach.profile(row.row())
-                )
+            point = self._profile.point(row.row())
+            table.append(
+                [
+                    point.x, point.y, point.z, point.name
+                ]
             )
 
+        self.copyTableIntoClipboard(table)
+
     def paste(self):
+        header, data = self.parseClipboardTable()
+
+        if len(data) == 0:
+            return
+
+        if len(header) != 0:
+            header.append("profile")
+        for row in data:
+            row.append(self._profile)
+
         row = self.index_selected_row()
-        self._model.paste(row, self._clipboard)
-        self.select_current_profile()
+        self._model.paste(row, header, data)
+        self.update_plot()
 
     def undo(self):
         self._model.undo()
diff --git a/src/View/Geometry/Profile/qtableview_profile.py b/src/View/Geometry/Profile/qtableview_profile.py
index 7ba364e96641a4761ef53ee15f96cc1df5f696a6..5cba2a16613e22f2cf85162a6224eefd48a231fb 100644
--- a/src/View/Geometry/Profile/qtableview_profile.py
+++ b/src/View/Geometry/Profile/qtableview_profile.py
@@ -1,6 +1,9 @@
 # -*- coding: utf-8 -*-
 
 import numpy as np
+
+from tools import timer, trace
+
 from PyQt5.QtGui import (
     QFont, QColor
 )
@@ -12,6 +15,7 @@ from PyQt5.QtCore import (
     QVariant, QCoreApplication
 )
 
+from Model.Geometry.PointXYZ import PointXYZ
 from Model.Geometry.ProfileXYZ import ProfileXYZ
 
 from View.Geometry.Profile.ProfileUndoCommand import *
@@ -259,18 +263,24 @@ class TableEditableModel(QAbstractTableModel):
         self.endMoveRows()
         self.layoutChanged.emit()
 
-    def paste(self, row, points):
+    def paste(self, row, header, data):
         if row > self._profile.number_points:
             return
 
-        if len(points) == 0:
+        if len(data) == 0:
             return
 
         self.layoutAboutToBeChanged.emit()
 
         self._undo_stack.push(
             PasteCommand(
-                self._profile, row, points
+                self._profile, row,
+                list(
+                    map(
+                        lambda d: PointXYZ.from_data(header, d),
+                        data
+                    )
+                )
             )
         )
 
diff --git a/src/View/Geometry/qtableview_reach.py b/src/View/Geometry/qtableview_reach.py
index bf6d28ef396c2930580a865d72ca5c8a27b18ce7..db4aba722af8140a78b8ea5d38d3615b55580752 100644
--- a/src/View/Geometry/qtableview_reach.py
+++ b/src/View/Geometry/qtableview_reach.py
@@ -212,7 +212,6 @@ class TableEditableModel(QAbstractTableModel):
         self.endMoveRows()
         self.layoutChanged.emit()
 
-    @trace
     def paste(self, row, header, data):
         if row > self._reach.number_profiles:
             return