diff --git a/db/migrations/constraints/V2_0_5_1__form_logs_constraints.sql b/db/migrations/constraints/V2_0_5_1__form_logs_constraints.sql
new file mode 100644
index 0000000000000000000000000000000000000000..114627db7e9916dce13a308383323506e5e5d7c9
--- /dev/null
+++ b/db/migrations/constraints/V2_0_5_1__form_logs_constraints.sql
@@ -0,0 +1,6 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+ALTER TABLE `logs_discipline_forms`
+  ADD CONSTRAINT `logs_discipline_forms_ibfk_1` FOREIGN KEY (`AccountID`) REFERENCES `accounts` (`ID`),
+  ADD CONSTRAINT `logs_discipline_forms_ibfk_2` FOREIGN KEY (`DisciplineID`) REFERENCES `disciplines` (`ID`);
diff --git a/db/migrations/stored/R__functions.sql b/db/migrations/stored/R__functions.sql
index 917d0d7a7b6c0b355a0da6a5d78dd71a8b27a9ba..9b644ceb75b2a451baa93784456729e1df820277 100644
--- a/db/migrations/stored/R__functions.sql
+++ b/db/migrations/stored/R__functions.sql
@@ -2761,6 +2761,24 @@ NO SQL
         RETURN 0;
     END //
 
+DROP FUNCTION IF EXISTS LogFormDownload//
+CREATE FUNCTION LogFormDownload (
+    pAccountID INT,
+    pDisciplineID INT,
+    pStage INT,
+    pLocked INT
+) RETURNS int(11) # 0 - success, < 0 - failed
+NO SQL
+BEGIN
+    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+
+    INSERT INTO logs_discipline_forms
+        (AccountID, DisciplineID, Stage, Locked, Date)
+        VALUES (pAccountID, pDisciplineID, pStage, pLocked, CURRENT_TIMESTAMP );
+
+    RETURN ROW_COUNT()-1;
+END //
+
 DELIMITER ;
 
 # -------------------------------------------------------------------------------------------
@@ -2794,4 +2812,4 @@ BEGIN
 	RETURN vSemesterID;
 END//
 
-DELIMITER ;
\ No newline at end of file
+DELIMITER ;
diff --git a/db/migrations/structure/V2_0_5_0__add_form_logs.sql b/db/migrations/structure/V2_0_5_0__add_form_logs.sql
new file mode 100644
index 0000000000000000000000000000000000000000..20b32e2db7978f32f1d74ef17bb7c16e53256e41
--- /dev/null
+++ b/db/migrations/structure/V2_0_5_0__add_form_logs.sql
@@ -0,0 +1,14 @@
+SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+CREATE TABLE IF NOT EXISTS `logs_discipline_forms` (
+  `ID` int(11) NOT NULL AUTO_INCREMENT,
+  `AccountID` int(11) NOT NULL,
+  `DisciplineID` int(11) NOT NULL,
+  `Stage` int(11) NOT NULL,
+  `Locked` tinyint(1) NOT NULL,
+  `Date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  PRIMARY KEY (`ID`),
+  KEY `AccountID` (`AccountID`),
+  KEY `DisciplineID` (`DisciplineID`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
\ No newline at end of file
diff --git a/deploy/phpConfig/security.php b/deploy/phpConfig/security.php
index b8a15018ddef00be7adf58eddcc7c680687fea5c..d07f27c9484a1dd0122b32513879aa9d5b370adf 100644
--- a/deploy/phpConfig/security.php
+++ b/deploy/phpConfig/security.php
@@ -24,6 +24,10 @@ return array(
             'recoveryToken' => array(
                 'lifetime' => 2*3600,
             )
-        )
+        ),
 
+    'excelProtection' => array(
+        'usePassword' => 'true',
+        'password' => 'Pefnesdy'
+    )
 );
\ No newline at end of file
diff --git a/deploy/phpConfig/sidePanel/dean.json b/deploy/phpConfig/sidePanel/dean.json
index 345304260b9385c16001f5ed1b3dba86a7724f2c..75462af82e6a50a537a63caf8b77992404f636da 100644
--- a/deploy/phpConfig/sidePanel/dean.json
+++ b/deploy/phpConfig/sidePanel/dean.json
@@ -19,7 +19,6 @@
 	{
 		"Title": "Отчеты",
 		"Items": [
-			{ "Title": "Ведомости", "Anchor": "reports/sheets" },
 			{ "Title": "Сводная ведомость", "Anchor": "reports/bill" }
 		]
 	},
diff --git a/media/js/dean/dean.js b/media/js/dean/dean.js
index c821a8bf1e5c69e961811082ecef452d212acf6c..a4db6d814b038aa450c40cda29a15218f3405cba 100644
--- a/media/js/dean/dean.js
+++ b/media/js/dean/dean.js
@@ -98,8 +98,9 @@ $(function () {
         $.fileDownload(g_URLdir + 'handler/FileCreator/GenerateFinalFormsForGroup', {
             httpMethod: "POST",
             data: {
-                "GroupID": parseInt($("#SelectGroup").val())//,
-                //"ExamType": $("input[name=DisciplineType]:checked").val()
+                "GroupID": parseInt($("#SelectGroup").val()),
+                //"ExamType": $("input[name=DisciplineType]:checked").val(),
+                "lock": $("input[name=Lock]").prop("checked")
             },
             successCallback: function () {
 
@@ -116,7 +117,8 @@ $(function () {
             httpMethod: "POST",
             data: {
                 "disciplineID": parseInt($("#SelectDiscipline").val()),
-                "studyGroupID": parseInt($("#SelectGroup").val())
+                "studyGroupID": parseInt($("#SelectGroup").val()),
+                "lock": $("input[name=Lock]").prop("checked")
             },
             successCallback: function () {
 
diff --git a/media/js/discipline/rating.js b/media/js/discipline/rating.js
index 8ad3e84aab73e4f3b9e8e199336c037d15036f0a..b0e24d7912e454d567bdc52b77528a358428c897 100644
--- a/media/js/discipline/rating.js
+++ b/media/js/discipline/rating.js
@@ -329,6 +329,7 @@ class Rating {
                     'disciplineID': self.settings.discipline.id,
                     'groupID': Base.parseid($(this)),
                     'stage': parseInt($(this).siblings('select').val()),
+                    'lock': true
                 },
             });
         });
diff --git a/~dev_rating/application/classes/Controller/Handler/FileCreator.php b/~dev_rating/application/classes/Controller/Handler/FileCreator.php
index 299edd454280dcf1e68493816830aaf8edbf5684..13526d68a5e0989689d1d128115f8ca7772c5a1c 100644
--- a/~dev_rating/application/classes/Controller/Handler/FileCreator.php
+++ b/~dev_rating/application/classes/Controller/Handler/FileCreator.php
@@ -190,7 +190,8 @@ class Controller_Handler_FileCreator extends Controller_Handler
             ->rule('groupID', 'not_empty')
             ->rule('groupID', 'digit')
             ->rule('stage', 'not_empty')
-            ->rule('stage', 'digit', [0, 1, 2, 3]);
+            ->rule('stage', 'digit', [0, 1, 2, 3])
+            ->rule('lock', 'not_empty');
 
         if (!$this->post->check())
             throw HTTP_Exception::factory(417, "Некорректные параметры запроса!");
@@ -199,6 +200,7 @@ class Controller_Handler_FileCreator extends Controller_Handler
         $disciplineID = $this->post['disciplineID'];
         $groupID = $this->post['groupID'];
         $stage = $this->post['stage'];
+        $doLock = $this->post['lock'];
 
         // make form from template
         $info = Model_Rating::getFinalFormInfo($disciplineID, $groupID);
@@ -213,6 +215,14 @@ class Controller_Handler_FileCreator extends Controller_Handler
         $subjName = str_replace(' ', '_', $subjName);
         $filename = $subjName . "_" . $grade . "_" . $group;
         $this->GetHeaders($filename);
+
+        if($doLock === "true") {
+            $this->lockWorkbook($objPHPExcel);
+        }
+
+        // Лог выгрузки ведомости, защищенной паролем
+        Model_Logs::logFormDownload($this->user->ID, $disciplineID, $stage, 1);
+
         $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
         $objWriter->save('php://output');
     }
@@ -591,6 +601,7 @@ class Controller_Handler_FileCreator extends Controller_Handler
         // parameters
         //$gradeID = $this->post['gradeID'];
         $groupID = $this->post['GroupID'];
+        $doLock = $this->post['lock'];
 
         // preparation
         $listDisciplines = Model_Group::with($groupID)->getDisciplines();
@@ -648,6 +659,9 @@ class Controller_Handler_FileCreator extends Controller_Handler
                 $groupNum = $info['GroupNum'];
             }
 
+            if($doLock === "true") {
+                $this->lockWorkbook($objPHPExcel);
+            }
             # fixme: $stage param is missing
             $this->printDisciplineToExcelFile($objPHPExcel, $discipline->ID, $groupID, $info);
             $index++;
@@ -776,4 +790,22 @@ class Controller_Handler_FileCreator extends Controller_Handler
         return $result;
     }
 
+    protected function lockWorkbook($workbook) {
+        $config = Kohana::$config->load('security.excelProtection');
+        if ($config == null) throw HTTP_Exception::factory(400, 'Неправильная конфигурация security');
+        $password = $config['password'];
+        $usePassword = $config['usePassword'];
+        if ($usePassword === 'true') {
+
+            foreach ($workbook->getAllSheets() as $sheet) {
+                $sheet->getProtection()->setSheet(true);
+                $sheet->getProtection()->setSort(true);
+                $sheet->getProtection()->setSelectLockedCells(true);
+                $sheet->getProtection()->setInsertRows(true);
+                $sheet->getProtection()->setFormatCells(true);
+                $sheet->getProtection()->setPassword($password);
+            }
+        }
+    }
+
 }
diff --git a/~dev_rating/application/classes/Model/Logs.php b/~dev_rating/application/classes/Model/Logs.php
index cec32ebc39b952b1fdfc9a232f2a71f8c9f1cfa8..a9ec4d54358e675ec065fff263fb4e2111d53bfc 100644
--- a/~dev_rating/application/classes/Model/Logs.php
+++ b/~dev_rating/application/classes/Model/Logs.php
@@ -16,5 +16,16 @@ class Model_Logs extends Model
         return DB::query(Database::SELECT, $query)->execute()->as_array();
     }
 
+    public static function logFormDownload($accountID, $disciplineID, $stage, $locked) {
+        $query = 'SELECT `LogFormDownload`(:account, :discipline, :stage, :locked)';
+
+        $result = DB::query(Database::UPDATE, $query)
+            ->param(':account', $accountID)
+            ->param(':discipline', $disciplineID)
+            ->param(':stage', $stage)
+            ->param(':locked', $locked)
+            ->execute();
+        return $result;
+    }
 
 }
diff --git a/~dev_rating/application/views/office/sheets/index.twig b/~dev_rating/application/views/office/sheets/index.twig
index 577eb1c45dd75ddb31775dd52551b9ed6b66969b..b91553d856906bb0a4a56f02da6905ea75d0cec8 100644
--- a/~dev_rating/application/views/office/sheets/index.twig
+++ b/~dev_rating/application/views/office/sheets/index.twig
@@ -98,6 +98,16 @@
                 {% endfor %}
             </div>
         </div>
+
+        <div class="LayerSection">
+            <style>.CheckBoxDiv { text-align: left; clear: both;}</style>
+            <div class="CheckBoxDiv">
+                <label>
+                    <input id="Lock" name="Lock" type="checkbox" checked="true">
+                    Защищать таблицы в Excel
+                </label>
+            </div>
+        </div>
     </div>
     <div id="hidden_div" style="display: none">{ "facultyID" : {{ User.FacultyID }} }</div>