diff --git a/HowToBuild.txt b/HowToBuild.txt index 9da144106..70bbe4308 100644 --- a/HowToBuild.txt +++ b/HowToBuild.txt @@ -19,7 +19,7 @@ Microsoft Visual Studio 2017 is needed. Visual Studio Community is OK. OpenPlugins, ScadaScheme, ScadaTable, - ScadaAdmin. + ScadaAdmin5. Switch to the Release configuration so that the references are correct. diff --git a/ScadaComm/OpenKPs/KpEnronModbus/EnronModbus/Protocol/EnronCmd.cs b/ScadaComm/OpenKPs/KpEnronModbus/EnronModbus/Protocol/EnronCmd.cs index 9e93fc35c..9d14b0c3d 100644 --- a/ScadaComm/OpenKPs/KpEnronModbus/EnronModbus/Protocol/EnronCmd.cs +++ b/ScadaComm/OpenKPs/KpEnronModbus/EnronModbus/Protocol/EnronCmd.cs @@ -43,13 +43,5 @@ public override ElemType GetDefElemType(TableType tableType) return tableType == TableType.DiscreteInputs || tableType == TableType.Coils ? ElemType.Bool : ElemType.Float; } - - /// - /// Gets the default number of command elements depending on the element type. - /// - public override int GetDefElemCnt(ElemType elemType) - { - return 1; - } } } diff --git a/ScadaComm/OpenKPs/KpHttpNotif/KpHttpNotif.csproj b/ScadaComm/OpenKPs/KpHttpNotif/KpHttpNotif.csproj index 41f3c26bf..2c2ba48a1 100644 --- a/ScadaComm/OpenKPs/KpHttpNotif/KpHttpNotif.csproj +++ b/ScadaComm/OpenKPs/KpHttpNotif/KpHttpNotif.csproj @@ -74,7 +74,7 @@ - + Lang\AddressBook.en-GB.xml PreserveNewest diff --git a/ScadaComm/OpenKPs/KpModbus/KpModbusLogic.cs b/ScadaComm/OpenKPs/KpModbus/KpModbusLogic.cs index 17faf66f3..96487998e 100644 --- a/ScadaComm/OpenKPs/KpModbus/KpModbusLogic.cs +++ b/ScadaComm/OpenKPs/KpModbus/KpModbusLogic.cs @@ -402,6 +402,17 @@ public override void OnAddedToCommLine() // определение режима передачи данных transMode = CustomParams.GetEnumParam("TransMode", false, TransMode.RTU); + // определение возможности отправки команд + CanSendCmd = deviceTemplate != null && deviceTemplate.Cmds.Count > 0; + } + + /// + /// Выполнить действия при запуске линии связи + /// + public override void OnCommLineStart() + { + // инициализация запрашиваемых элементов и команд + // располагается в OnCommLineStart, т.к. здесь Address окончательно определён if (deviceTemplate == null) { elemGroups = null; @@ -428,15 +439,6 @@ public override void OnAddedToCommLine() } } - // определение возможности отправки команд - CanSendCmd = deviceTemplate != null && deviceTemplate.Cmds.Count > 0; - } - - /// - /// Выполнить действия при запуске линии связи - /// - public override void OnCommLineStart() - { // инициализация объекта для опроса КП InitModbusPoll(); diff --git a/ScadaComm/OpenKPs/KpModbus/KpModbusView.cs b/ScadaComm/OpenKPs/KpModbus/KpModbusView.cs index c44243191..455469745 100644 --- a/ScadaComm/OpenKPs/KpModbus/KpModbusView.cs +++ b/ScadaComm/OpenKPs/KpModbus/KpModbusView.cs @@ -41,7 +41,7 @@ public class KpModbusView : KPView /// /// The driver version. /// - internal const string KpVersion = "5.1.3.0"; + internal const string KpVersion = "5.1.3.1"; /// /// The UI customization object. diff --git a/ScadaComm/OpenKPs/KpModbus/Modbus/Protocol/ModbusCmd.cs b/ScadaComm/OpenKPs/KpModbus/Modbus/Protocol/ModbusCmd.cs index e0887e67c..807cc94ab 100644 --- a/ScadaComm/OpenKPs/KpModbus/Modbus/Protocol/ModbusCmd.cs +++ b/ScadaComm/OpenKPs/KpModbus/Modbus/Protocol/ModbusCmd.cs @@ -1,5 +1,5 @@ /* - * Copyright 2018 Mikhail Shiryaev + * Copyright 2021 Mikhail Shiryaev * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2012 - * Modified : 2018 + * Modified : 2021 */ using System; @@ -144,16 +144,26 @@ public override void InitReqPDU() if (Multiple) { // формирование PDU для команды WriteMultipleCoils или WriteMultipleRegisters - int dataLength = TableType == TableType.Coils ? - ((ElemCnt % 8 == 0) ? ElemCnt / 8 : ElemCnt / 8 + 1) : - ElemCnt * ModbusUtils.GetDataLength(ElemType); + int quantity; // quantity of registers + int dataLength; // data length in bytes + + if (TableType == TableType.Coils) + { + quantity = ElemCnt; + dataLength = (ElemCnt % 8 == 0) ? ElemCnt / 8 : ElemCnt / 8 + 1; + } + else + { + quantity = ElemCnt * ModbusUtils.GetQuantity(ElemType); + dataLength = quantity * 2; + } ReqPDU = new byte[6 + dataLength]; ReqPDU[0] = FuncCode; ReqPDU[1] = (byte)(Address / 256); ReqPDU[2] = (byte)(Address % 256); - ReqPDU[3] = (byte)(ElemCnt / 256); - ReqPDU[4] = (byte)(ElemCnt % 256); + ReqPDU[3] = (byte)(quantity / 256); + ReqPDU[4] = (byte)(quantity % 256); ReqPDU[5] = (byte)dataLength; ModbusUtils.ApplyByteOrder(Data, 0, ReqPDU, 6, dataLength, ByteOrder, false); @@ -218,14 +228,6 @@ public override bool DecodeRespPDU(byte[] buffer, int offset, int length, out st } } - /// - /// Gets the default number of command elements depending on the element type. - /// - public virtual int GetDefElemCnt(ElemType elemType) - { - return ModbusUtils.GetQuantity(elemType); - } - /// /// Loads the command from the XML node. /// diff --git a/ScadaComm/OpenKPs/KpModbus/Modbus/UI/CtrlCmd.cs b/ScadaComm/OpenKPs/KpModbus/Modbus/UI/CtrlCmd.cs index b0d4dd36f..1e1c47b07 100644 --- a/ScadaComm/OpenKPs/KpModbus/Modbus/UI/CtrlCmd.cs +++ b/ScadaComm/OpenKPs/KpModbus/Modbus/UI/CtrlCmd.cs @@ -287,8 +287,7 @@ private void cbCmdElemType_SelectedIndexChanged(object sender, EventArgs e) else { modbusCmd.ElemType = newElemType; - numCmdElemCnt.SetValue(modbusCmd.GetDefElemCnt(newElemType)); - OnObjectChanged(TreeUpdateTypes.None); + OnObjectChanged(TreeUpdateTypes.CurrentNode); } } } diff --git a/ScadaComm/OpenKPs/KpModbus/Modbus/UI/FrmDevTemplate.cs b/ScadaComm/OpenKPs/KpModbus/Modbus/UI/FrmDevTemplate.cs index 83bf8c3da..c6166a15f 100644 --- a/ScadaComm/OpenKPs/KpModbus/Modbus/UI/FrmDevTemplate.cs +++ b/ScadaComm/OpenKPs/KpModbus/Modbus/UI/FrmDevTemplate.cs @@ -1,5 +1,5 @@ /* - * Copyright 2020 Mikhail Shiryaev + * Copyright 2021 Mikhail Shiryaev * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ * * Author : Mikhail Shiryaev * Created : 2012 - * Modified : 2020 + * Modified : 2021 */ using Scada.Comm.Devices.Modbus.Protocol; @@ -231,7 +231,8 @@ private string GetCmdCaption(ModbusCmd modbusCmd) { return (string.IsNullOrEmpty(modbusCmd.Name) ? KpPhrases.DefCmdName : modbusCmd.Name) + " (" + ModbusUtils.GetTableTypeName(modbusCmd.TableType) + ", " + - ModbusUtils.GetAddressRange(modbusCmd.Address, modbusCmd.ElemCnt, + ModbusUtils.GetAddressRange(modbusCmd.Address, + modbusCmd.ElemCnt * ModbusUtils.GetQuantity(modbusCmd.ElemType), template.Sett.ZeroAddr, template.Sett.DecAddr) + ")"; } diff --git a/ScadaComm/OpenKPs/KpOpcUa/KpOpcUaView.cs b/ScadaComm/OpenKPs/KpOpcUa/KpOpcUaView.cs index 4e770ff37..b2413b797 100644 --- a/ScadaComm/OpenKPs/KpOpcUa/KpOpcUaView.cs +++ b/ScadaComm/OpenKPs/KpOpcUa/KpOpcUaView.cs @@ -28,7 +28,7 @@ public class KpOpcUaView : KPView /// /// The driver version. /// - internal const string KpVersion = "5.0.0.1"; + internal const string KpVersion = "5.0.0.2"; /// diff --git a/ScadaComm/OpenKPs/KpOpcUa/OpcUa/Config/ConnectionOptions.cs b/ScadaComm/OpenKPs/KpOpcUa/OpcUa/Config/ConnectionOptions.cs index 1cd26c513..8c6a091ae 100644 --- a/ScadaComm/OpenKPs/KpOpcUa/OpcUa/Config/ConnectionOptions.cs +++ b/ScadaComm/OpenKPs/KpOpcUa/OpcUa/Config/ConnectionOptions.cs @@ -1,5 +1,5 @@ /* - * Copyright 2019 Mikhail Shiryaev + * Copyright 2021 Mikhail Shiryaev * All rights reserved * * Product : Rapid SCADA @@ -8,7 +8,7 @@ * * Author : Mikhail Shiryaev * Created : 2019 - * Modified : 2019 + * Modified : 2021 */ using Opc.Ua; @@ -80,7 +80,7 @@ public void LoadFromXml(XmlNode xmlNode) SecurityMode = xmlNode.GetChildAsEnum("SecurityMode", MessageSecurityMode.None); SecurityPolicy = xmlNode.GetChildAsEnum("SecurityPolicy"); AuthenticationMode = xmlNode.GetChildAsEnum("AuthenticationMode"); - Username = xmlNode.GetChildAsString("User"); + Username = xmlNode.GetChildAsString("Username"); Password = ScadaUtils.Decrypt(xmlNode.GetChildAsString("Password")); } diff --git a/ScadaComm/OpenKPs/KpOpcUa/OpcUa/UI/FrmSecurityOptions.cs b/ScadaComm/OpenKPs/KpOpcUa/OpcUa/UI/FrmSecurityOptions.cs index 7cd11463c..21f0f4444 100644 --- a/ScadaComm/OpenKPs/KpOpcUa/OpcUa/UI/FrmSecurityOptions.cs +++ b/ScadaComm/OpenKPs/KpOpcUa/OpcUa/UI/FrmSecurityOptions.cs @@ -44,7 +44,7 @@ namespace Scada.Comm.Devices.OpcUa.UI /// public partial class FrmSecurityOptions : Form { - private ConnectionOptions connectionOptions; // the OPC server connection options + private readonly ConnectionOptions connectionOptions; // the OPC server connection options /// diff --git a/ScadaDoc/ScadaDoc/content/latest/en/additional-applications/app-auto-report.html b/ScadaDoc/ScadaDoc/content/latest/en/additional-applications/app-auto-report.html index b2f7ab7f6..21af5bf61 100644 --- a/ScadaDoc/ScadaDoc/content/latest/en/additional-applications/app-auto-report.html +++ b/ScadaDoc/ScadaDoc/content/latest/en/additional-applications/app-auto-report.html @@ -62,7 +62,7 @@

Configuring

Users

The settings of Automatic Control Module (item 4) are shown below:

-

Automatic control module

+

Automatic control module

An example of Communicator settings for sending emails (item 5) is contained in the DemoProject.en-GB.rsproj project. The following figure shows the device properties:

Email settings

diff --git a/ScadaDoc/ScadaDoc/content/latest/en/version-history/communicator-drivers-history.html b/ScadaDoc/ScadaDoc/content/latest/en/version-history/communicator-drivers-history.html index a1100ffcf..0e901a7e1 100644 --- a/ScadaDoc/ScadaDoc/content/latest/en/version-history/communicator-drivers-history.html +++ b/ScadaDoc/ScadaDoc/content/latest/en/version-history/communicator-drivers-history.html @@ -48,7 +48,11 @@

HTTP Notifications

Modbus

-
KpModbus 5.1.3.0 (May 17, 2021)
+    
KpModbus 5.1.3.1 (November 15, 2021)
+- Fixed data packet format for multiple commands
+  Warning: no backward compatibility for multiple commands having elements of 4 bytes or more
+
+KpModbus 5.1.3.0 (May 17, 2021)
 - Improved the flexibility of classes that implement the communication protocol
 
 KpModbus 5.1.2.0 (January 28, 2020)
@@ -68,7 +72,10 @@ 

Modbus

Modbus Slave

-
KpModbusSlave 5.0.0.0 (June 23, 2020)
+    
KpModbusSlave 5.0.0.1 (November 15, 2021)
+- Update due to changes in KpModbus
+
+KpModbusSlave 5.0.0.0 (June 23, 2020)
 - Initial development of the driver
 
@@ -82,7 +89,10 @@

OPC

OPC UA

-
KpOpcUa 5.0.0.1 (May 17, 2021)
+    
KpOpcUa 5.0.0.2 (November 15, 2021)
+- Fixed saving security options
+
+KpOpcUa 5.0.0.1 (May 17, 2021)
 - Fixed a bug when browsing OPC server nodes
 
 KpOpcUa 5.0.0.0 (January 28, 2020)
diff --git a/ScadaDoc/ScadaDoc/content/latest/en/version-history/scada-history.html b/ScadaDoc/ScadaDoc/content/latest/en/version-history/scada-history.html
index be85c2619..4617a38ec 100644
--- a/ScadaDoc/ScadaDoc/content/latest/en/version-history/scada-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/en/version-history/scada-history.html
@@ -10,12 +10,26 @@
 
 
     

Rapid SCADA History

-
Rapid SCADA 5.8.3 (May 17, 2021)
+    
Rapid SCADA 5.8.4 (November 15, 2021)
+  Server 5.1.4.2
+    DB Export Module 5.1.0.1
+  Communicator 5.2.1.2
+    Modbus Driver 5.1.3.1
+    OPC UA Driver 5.0.0.2
+  Webstation 5.1.3.0
+  Agent 5.0.2.0
+  Administrator 5.5.2.2
+  Table Editor 5.1.0.1
+  Scheme Editor 5.3.1.1
+
+Rapid SCADA 5.8.3 (May 17, 2021)
   Server 5.1.4.2
     DB Export Module 5.0.1.3
   Communicator 5.2.1.2
     DB Import Driver 5.0.3.0
     Email Driver 5.0.4.0
+    Enron Modbus Driver 5.0.0.0
+    HTTP Notifications Driver 5.0.1.0
     Modbus Driver 5.1.3.0
     OPC UA Driver 5.0.0.1
   Webstation 5.1.3.0
diff --git a/ScadaDoc/ScadaDoc/content/latest/en/version-history/server-modules-history.html b/ScadaDoc/ScadaDoc/content/latest/en/version-history/server-modules-history.html
index 18de5e2e0..44d170048 100644
--- a/ScadaDoc/ScadaDoc/content/latest/en/version-history/server-modules-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/en/version-history/server-modules-history.html
@@ -21,7 +21,10 @@ 

Active DirectoryModule

Automatic Control Module

-
ModAutoControl 5.2.5.2 (May 17, 2021)
+    
ModAutoControl 5.2.5.3 (May 31, 2021)
+- Channel value is checked only if status is positive
+
+ModAutoControl 5.2.5.2 (May 17, 2021)
 - Fixed saving state if module is not configured
 
 ModAutoControl 5.2.5.1 (December 14, 2020)
@@ -46,7 +49,10 @@ 

Automatic Control Module

DB Export

-
ModDBExport 5.0.1.3 (May 17, 2021)
+    
ModDbExport 5.1.0.1 (November 15, 2021)
+- The module is completely redesigned
+
+ModDBExport 5.0.1.3 (May 17, 2021)
 - Updated DB connectors
 
 ModDBExport 5.0.1.2 (January 13, 2021)
diff --git a/ScadaDoc/ScadaDoc/content/latest/en/version-history/webstation-plugins-history.html b/ScadaDoc/ScadaDoc/content/latest/en/version-history/webstation-plugins-history.html
index 2aa665f18..e4d4b9c27 100644
--- a/ScadaDoc/ScadaDoc/content/latest/en/version-history/webstation-plugins-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/en/version-history/webstation-plugins-history.html
@@ -78,8 +78,11 @@ 

Dashboard

- Build due to changes in the base libraries

Elastic Report

-
PlgElasticReport 5.0.5.1 (May 17, 2021)
-- Fixed a bug  when using the BeginEnd detalization
+    
PlgElasticReport 5.0.5.2 (November 15, 2021)
+- Fixed a bug when a page format cannot be set
+
+PlgElasticReport 5.0.5.1 (May 17, 2021)
+- Fixed a bug when using the BeginEnd detalization
 
 PlgElasticReport 5.0.5.0 (December 14, 2020)
 - Calculate minimum and maximum values by columns and rows
diff --git a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/communicator-drivers-history.html b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/communicator-drivers-history.html
index 19ac47e7b..72fe42dee 100644
--- a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/communicator-drivers-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/communicator-drivers-history.html
@@ -55,7 +55,11 @@ 

HTTP уведомления

Modbus

-
KpModbus 5.1.3.0 (17.05.2021)
+    
KpModbus 5.1.3.1 (15.11.2021)
+- Исправлен формат пакета данных для множественных команд
+  Внимание: отсутствует обратная совместимость множественных команд для элементов от 4 байт
+
+KpModbus 5.1.3.0 (17.05.2021)
 - Улучшена гибкость классов, реализующих протокол обмена данными
 
 KpModbus 5.1.2.0 (28.01.2020)
@@ -93,7 +97,10 @@ 

Modbus

Modbus Slave

-
KpModbusSlave 5.0.0.0 (23.06.2020)
+    
KpModbusSlave 5.0.0.1 (15.11.2021)
+- Обновление в связи с изменениями в KpModbus
+
+KpModbusSlave 5.0.0.0 (23.06.2020)
 - Первоначальная разработка драйвера
 
@@ -116,7 +123,10 @@

OPC

OPC UA

-
KpOpcUa 5.0.0.1 (17.05.2021)
+    
KpOpcUa 5.0.0.2 (15.11.2021)
+- Исправлено сохранение параметров безопасности
+
+KpOpcUa 5.0.0.1 (17.05.2021)
 - Исправлена ошибка обзора узлов OPC-сервера
 
 KpOpcUa 5.0.0.0 (28.01.2020)
diff --git a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/scada-history.html b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/scada-history.html
index cd740376c..c4b1577ee 100644
--- a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/scada-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/scada-history.html
@@ -11,12 +11,26 @@
 
     

История Rapid SCADA

-
Rapid SCADA 5.8.3 (17.05.2021)
+    
Rapid SCADA 5.8.4 (15.11.2021)
+  Сервер 5.1.4.2
+    Модуль Экпорт в БД 5.1.0.1
+  Коммуникатор 5.2.1.2
+    Драйвер Modbus 5.1.3.1
+    Драйвер OPC UA 5.0.0.2
+  Вебстанция 5.1.3.0
+  Агент 5.0.2.0
+  Администратор 5.5.2.2
+  Редактор таблиц 5.1.0.1
+  Редактор схем 5.3.1.1
+
+Rapid SCADA 5.8.3 (17.05.2021)
   Сервер 5.1.4.2
     Модуль Экпорт в БД 5.0.1.3
   Коммуникатор 5.2.1.2
     Драйвер Импорт из БД 5.0.3.0
-    Драйвер 5.0.4.0
+    Драйвер Email 5.0.4.0
+    Драйвер Enron Modbus 5.0.0.0
+    Драйвер HTTP уведомления 5.0.1.0
     Драйвер Modbus 5.1.3.0
     Драйвер OPC UA 5.0.0.1
   Вебстанция 5.1.3.0
diff --git a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/server-modules-history.html b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/server-modules-history.html
index 4e3a4f64a..a6ca9db7e 100644
--- a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/server-modules-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/server-modules-history.html
@@ -21,7 +21,10 @@ 

Модуль Active Directory

Модуль автоматического управления

-
ModAutoControl 5.2.5.2 (17.05.2021)
+    
ModAutoControl 5.2.5.3 (31.05.2021)
+- Значение канала проверяется только при положительном статусе
+
+ModAutoControl 5.2.5.2 (17.05.2021)
 - Исправлена ошибка при сохранении состояния, если модуль не настроен
 
 ModAutoControl 5.2.5.1 (14.12.2020)
@@ -76,7 +79,10 @@ 

Модуль автоматического управления

Экпорт в БД

-
ModDBExport 5.0.1.3 (17.05.2021)
+    
ModDbExport 5.1.0.1 (15.11.2021)
+- Модуль полностью перепроектирован
+
+ModDBExport 5.0.1.3 (17.05.2021)
 - Обновлены библиотеки для соединения с БД
 
 ModDBExport 5.0.1.2 (13.01.2021)
diff --git a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/webstation-plugins-history.html b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/webstation-plugins-history.html
index 4e2271720..e88010c94 100644
--- a/ScadaDoc/ScadaDoc/content/latest/ru/version-history/webstation-plugins-history.html
+++ b/ScadaDoc/ScadaDoc/content/latest/ru/version-history/webstation-plugins-history.html
@@ -127,7 +127,10 @@ 

Дэшборды

- Первоначальная разработка плагина

Гибкий отчёт

-
PlgElasticReport 5.0.5.1 (17.05.2021)
+    
PlgElasticReport 5.0.5.2 (15.11.2021)
+- Исправлена ошибка установки формата страницы
+
+PlgElasticReport 5.0.5.1 (17.05.2021)
 - Исправлена ошибка при использовании детализации BeginEnd
 
 PlgElasticReport 5.0.5.0 (14.12.2020)
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/DataSource.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/DataSource.cs
deleted file mode 100644
index bbc50c891..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/DataSource.cs
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : The base class for interacting with database
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using System;
-using System.Data.Common;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// The base class for interacting with database
-    /// Базовый класс для взаимодействия с БД
-    /// 
-    internal abstract class DataSource : IComparable
-    {
-        /// 
-        /// The string to hide a password. 0x25CF character is uded.
-        /// 
-        protected const string HiddenPassword = "●●●●●";
-
-
-        /// 
-        /// Конструктор
-        /// 
-        public DataSource()
-        {
-            DBType = DBType.Undefined;
-            Server = "";
-            Database = "";
-            User = "";
-            Password = "";
-            ConnectionString = "";
-
-            Connection = null;
-            ExportCurDataCmd = null;
-            ExportArcDataCmd = null;
-            ExportEventCmd = null;
-        }
-
-
-        /// 
-        /// Получить или установить тип БД
-        /// 
-        public DBType DBType { get; set; }
-
-        /// 
-        /// Получить или установить сервер БД
-        /// 
-        public string Server { get; set; }
-
-        /// 
-        /// Получить или установить имя БД
-        /// 
-        public string Database { get; set; }
-
-        /// 
-        /// Получить или установить пользователя БД
-        /// 
-        public string User { get; set; }
-
-        /// 
-        /// Получить или установить пароль пользователя БД
-        /// 
-        public string Password { get; set; }
-
-        /// 
-        /// Получить или установить строку соединения с БД
-        /// 
-        public string ConnectionString { get; set; }
-
-        /// 
-        /// Получить наименование источника данных
-        /// 
-        public string Name
-        {
-            get
-            {
-                return DBType + (string.IsNullOrEmpty(Server) ? "" : " - " + Server);
-            }
-        }
-
-
-
-        /// 
-        /// Получить соединение с БД
-        /// 
-        public DbConnection Connection { get; protected set; }
-
-        /// 
-        /// Получить команду экспорта текущих данных
-        /// 
-        public DbCommand ExportCurDataCmd { get; protected set; }
-
-        /// 
-        /// Получить команду экспорта архивных данных
-        /// 
-        public DbCommand ExportArcDataCmd { get; protected set; }
-
-        /// 
-        /// Получить команду экспорта события
-        /// 
-        public DbCommand ExportEventCmd { get; protected set; }
-
-
-        /// 
-        /// Создать соединение с БД
-        /// 
-        protected abstract DbConnection CreateConnection();
-
-        /// 
-        /// Очистить пул соединений
-        /// 
-        protected abstract void ClearPool();
-
-        /// 
-        /// Создать команду
-        /// 
-        protected abstract DbCommand CreateCommand(string cmdText);
-
-        /// 
-        /// Добавить параметр команды со значением
-        /// 
-        protected abstract void AddCmdParamWithValue(DbCommand cmd, string paramName, object value);
-
-        /// 
-        /// Извлечь имя хоста и порт из имени сервера
-        /// 
-        protected void ExtractHostAndPort(string server, int defaultPort, out string host, out int port)
-        {
-            int ind = server.IndexOf(':');
-
-            if (ind >= 0)
-            {
-                host = server.Substring(0, ind);
-                try { port = int.Parse(server.Substring(ind + 1)); }
-                catch { port = defaultPort; }
-            }
-            else
-            {
-                host = server;
-                port = defaultPort;
-            }
-        }
-
-
-        /// 
-        /// Построить строку соединения с БД на основе остальных свойств соединения
-        /// 
-        public abstract string BuildConnectionString(bool hidePassword = false);
-
-        /// 
-        /// Инициализировать соединение с БД
-        /// 
-        public void InitConnection()
-        {
-            Connection = CreateConnection();
-            if (string.IsNullOrEmpty(ConnectionString))
-                ConnectionString = BuildConnectionString();
-            Connection.ConnectionString = ConnectionString;
-        }
-
-        /// 
-        /// Соединиться с БД
-        /// 
-        public void Connect()
-        {
-            if (Connection == null)
-                throw new InvalidOperationException("Connection is not initialized.");
-
-            try
-            {
-                Connection.Open();
-            }
-            catch 
-            {
-                Connection.Close();
-                ClearPool();
-                throw;
-            }
-        }
-
-        /// 
-        /// Разъединиться с БД
-        /// 
-        public void Disconnect()
-        {
-            if (Connection != null)
-                Connection.Close();
-        }
-
-        /// 
-        /// Инициализировать команды экспорта данных
-        /// 
-        public void InitCommands(string exportCurDataQuery, string exportArcDataQuery, string exportEventQuery)
-        {
-            ExportCurDataCmd = string.IsNullOrEmpty(exportCurDataQuery) ? null : CreateCommand(exportCurDataQuery);
-            ExportArcDataCmd = string.IsNullOrEmpty(exportArcDataQuery) ? null : CreateCommand(exportArcDataQuery);
-            ExportEventCmd = string.IsNullOrEmpty(exportEventQuery) ? null : CreateCommand(exportEventQuery);
-        }
-
-        /// 
-        /// Установить значение параметра команды
-        /// 
-        public void SetCmdParam(DbCommand cmd, string paramName, object value)
-        {
-            if (cmd == null)
-                throw new ArgumentNullException("cmd");
-
-            if (cmd.Parameters.Contains(paramName))
-                cmd.Parameters[paramName].Value = value;
-            else
-                AddCmdParamWithValue(cmd, paramName, value);
-        }
-
-        /// 
-        /// Клонировать источник данных
-        /// 
-        public virtual DataSource Clone()
-        {
-            DataSource dataSourceCopy = (DataSource)Activator.CreateInstance(this.GetType());
-            dataSourceCopy.DBType = DBType;
-            dataSourceCopy.Server = Server;
-            dataSourceCopy.Database = Database;
-            dataSourceCopy.User = User;
-            dataSourceCopy.Password = Password;
-            dataSourceCopy.ConnectionString = ConnectionString;
-            return dataSourceCopy;
-        }
-
-
-        /// 
-        /// Получить строковое представление объекта
-        /// 
-        public override string ToString()
-        {
-            return Name;
-        }
-
-        /// 
-        /// Сравнить текущий объект с другим объектом такого же типа
-        /// 
-        public int CompareTo(DataSource other)
-        {
-            int comp = DBType.CompareTo(other.DBType);
-            return comp == 0 ? Name.CompareTo(other.Name) : comp;
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/MySqlDataSource.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/MySqlDataSource.cs
deleted file mode 100644
index d129dec66..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/MySqlDataSource.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : MySQL interacting traits
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using MySql.Data.MySqlClient;
-using System;
-using System.Data.Common;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// MySQL interacting traits
-    /// Особенности взаимодействия с MySQL
-    /// 
-    internal class MySqlDataSource : DataSource
-    {
-        /// 
-        /// Порт по умолчанию
-        /// 
-        private const int DefaultPort = 3306;
-
-
-        /// 
-        /// Конструктор
-        /// 
-        public MySqlDataSource()
-            : base()
-        {
-            DBType = DBType.MySQL;
-        }
-
-
-        /// 
-        /// Проверить существование и тип соединения с БД
-        /// 
-        private void CheckConnection()
-        {
-            if (Connection == null)
-                throw new InvalidOperationException("Connection is not inited.");
-            if (!(Connection is MySqlConnection))
-                throw new InvalidOperationException("MySqlConnection is required.");
-        }
-
-
-        /// 
-        /// Создать соединение с БД
-        /// 
-        protected override DbConnection CreateConnection()
-        {
-            return new MySqlConnection();
-        }
-
-        /// 
-        /// Очистить пул приложений
-        /// 
-        protected override void ClearPool()
-        {
-            CheckConnection();
-            MySqlConnection.ClearPool((MySqlConnection)Connection);
-        }
-
-        /// 
-        /// Создать команду
-        /// 
-        protected override DbCommand CreateCommand(string cmdText)
-        {
-            CheckConnection();
-            return new MySqlCommand(cmdText, (MySqlConnection)Connection);
-        }
-
-        /// 
-        /// Добавить параметр команды со значением
-        /// 
-        protected override void AddCmdParamWithValue(DbCommand cmd, string paramName, object value)
-        {
-            if (cmd == null)
-                throw new ArgumentNullException("cmd");
-            if (!(cmd is MySqlCommand))
-                throw new ArgumentException("MySqlCommand is required.", "cmd");
-
-            MySqlCommand mySqlCmd = (MySqlCommand)cmd;
-            mySqlCmd.Parameters.AddWithValue(paramName, value);
-        }
-
-
-        /// 
-        /// Построить строку соединения с БД на основе остальных свойств соединения
-        /// 
-        public override string BuildConnectionString(bool hidePassword)
-        {
-            ExtractHostAndPort(Server, DefaultPort, out string host, out int port);
-
-            MySqlConnectionStringBuilder csb = new MySqlConnectionStringBuilder
-            {
-                Server = host,
-                Port = (uint)port,
-                Database = Database,
-                UserID = User,
-                Password = hidePassword ? HiddenPassword : Password
-            };
-
-            return csb.ToString();
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/OleDbDataSource.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/OleDbDataSource.cs
deleted file mode 100644
index 10eb33c02..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/OleDbDataSource.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : OLE DB interacting traits
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using System;
-using System.Data.Common;
-using System.Data.OleDb;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// OLE DB interacting traits
-    /// Особенности взаимодействия с OLE DB
-    /// 
-    internal class OleDbDataSource : DataSource
-    {
-        /// 
-        /// Конструктор
-        /// 
-        public OleDbDataSource()
-            : base()
-        {
-            DBType = DBType.OLEDB;
-        }
-
-
-        /// 
-        /// Проверить существование и тип соединения с БД
-        /// 
-        private void CheckConnection()
-        {
-            if (Connection == null)
-                throw new InvalidOperationException("Connection is not inited.");
-            if (!(Connection is OleDbConnection))
-                throw new InvalidOperationException("OleDbConnection is required.");
-        }
-
-
-        /// 
-        /// Создать соединение с БД
-        /// 
-        protected override DbConnection CreateConnection()
-        {
-            return new OleDbConnection();
-        }
-
-        /// 
-        /// Очистить пул приложений
-        /// 
-        protected override void ClearPool()
-        {
-            // метод очистки пула соединений OLE DB отсутствует
-        }
-
-        /// 
-        /// Создать команду
-        /// 
-        protected override DbCommand CreateCommand(string cmdText)
-        {
-            CheckConnection();
-            return new OleDbCommand(cmdText, (OleDbConnection)Connection);
-        }
-
-        /// 
-        /// Добавить параметр команды со значением
-        /// 
-        protected override void AddCmdParamWithValue(DbCommand cmd, string paramName, object value)
-        {
-            if (cmd == null)
-                throw new ArgumentNullException("cmd");
-            if (!(cmd is OleDbCommand))
-                throw new ArgumentException("OleDbCommand is required.", "cmd");
-
-            OleDbCommand oleDbCmd = (OleDbCommand)cmd;
-            oleDbCmd.Parameters.AddWithValue(paramName, value);
-        }
-
-
-        /// 
-        /// Построить строку соединения с БД на основе остальных свойств соединения
-        /// 
-        public override string BuildConnectionString(bool hidePassword)
-        {
-            return "";
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/OraDataSource.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/OraDataSource.cs
deleted file mode 100644
index c0cd849fd..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/OraDataSource.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Oracle interacting traits
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using System;
-using System.Data.Common;
-using System.Data.OracleClient;
-using System.Data.SqlClient;
-
-#pragma warning disable 618 // отключить предупреждение об устаревших классах Oracle
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Oracle interacting traits
-    /// Особенности взаимодействия с Oracle
-    /// 
-    internal class OraDataSource : DataSource
-    {
-        /// 
-        /// Конструктор
-        /// 
-        public OraDataSource()
-            : base()
-        {
-            DBType = DBType.Oracle;
-        }
-
-
-        /// 
-        /// Проверить существование и тип соединения с БД
-        /// 
-        private void CheckConnection()
-        {
-            if (Connection == null)
-                throw new InvalidOperationException("Connection is not inited.");
-            if (!(Connection is OracleConnection))
-                throw new InvalidOperationException("OracleConnection is required.");
-        }
-
-
-        /// 
-        /// Создать соединение с БД
-        /// 
-        protected override DbConnection CreateConnection()
-        {
-            return new OracleConnection();
-        }
-
-        /// 
-        /// Очистить пул приложений
-        /// 
-        protected override void ClearPool()
-        {
-            CheckConnection();
-            OracleConnection.ClearPool((OracleConnection)Connection);
-        }
-
-        /// 
-        /// Создать команду
-        /// 
-        protected override DbCommand CreateCommand(string cmdText)
-        {
-            CheckConnection();
-            return new OracleCommand(cmdText, (OracleConnection)Connection);
-        }
-
-        /// 
-        /// Добавить параметр команды со значением
-        /// 
-        protected override void AddCmdParamWithValue(DbCommand cmd, string paramName, object value)
-        {
-            if (cmd == null)
-                throw new ArgumentNullException("cmd");
-            if (!(cmd is OracleCommand))
-                throw new ArgumentException("OracleCommand is required.", "cmd");
-
-            OracleCommand oraCmd = (OracleCommand)cmd;
-            oraCmd.Parameters.AddWithValue(paramName, value);
-        }
-
-
-        /// 
-        /// Построить строку соединения с БД на основе остальных свойств соединения
-        /// 
-        public override string BuildConnectionString(bool hidePassword)
-        {
-            return string.Format("Server={0}{1};User ID={2};Password={3}", 
-                Server, string.IsNullOrEmpty(Database) ? "" : "/" + Database, 
-                User, hidePassword ? HiddenPassword : Password);
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/PgSqlDataSource.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/PgSqlDataSource.cs
deleted file mode 100644
index f4721e7d8..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/PgSqlDataSource.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : PostgreSQL interacting traits
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using Npgsql;
-using System;
-using System.Data.Common;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// PostgreSQL interacting traits
-    /// Особенности взаимодействия с PostgreSQL
-    /// 
-    internal class PgSqlDataSource : DataSource
-    {
-        /// 
-        /// Порт по умолчанию
-        /// 
-        private const int DefaultPort = 5432;
-
-
-        /// 
-        /// Конструктор
-        /// 
-        public PgSqlDataSource()
-            : base()
-        {
-            DBType = DBType.PostgreSQL;
-        }
-
-
-        /// 
-        /// Проверить существование и тип соединения с БД
-        /// 
-        private void CheckConnection()
-        {
-            if (Connection == null)
-                throw new InvalidOperationException("Connection is not inited.");
-            if (!(Connection is NpgsqlConnection))
-                throw new InvalidOperationException("NpgsqlConnection is required.");
-        }
-
-
-        /// 
-        /// Создать соединение с БД
-        /// 
-        protected override DbConnection CreateConnection()
-        {
-            return new NpgsqlConnection();
-        }
-
-        /// 
-        /// Очистить пул приложений
-        /// 
-        protected override void ClearPool()
-        {
-            NpgsqlConnection.ClearAllPools();
-        }
-
-        /// 
-        /// Создать команду
-        /// 
-        protected override DbCommand CreateCommand(string cmdText)
-        {
-            CheckConnection();
-            return new NpgsqlCommand(cmdText, (NpgsqlConnection)Connection);
-        }
-
-        /// 
-        /// Добавить параметр команды со значением
-        /// 
-        protected override void AddCmdParamWithValue(DbCommand cmd, string paramName, object value)
-        {
-            if (cmd == null)
-                throw new ArgumentNullException("cmd");
-            if (!(cmd is NpgsqlCommand))
-                throw new ArgumentException("NpgsqlCommand is required.", "cmd");
-
-            NpgsqlCommand pgSqlCmd = (NpgsqlCommand)cmd;
-            pgSqlCmd.Parameters.AddWithValue(paramName, value);
-        }
-
-
-        /// 
-        /// Построить строку соединения с БД на основе остальных свойств соединения
-        /// 
-        public override string BuildConnectionString(bool hidePassword)
-        {
-            ExtractHostAndPort(Server, DefaultPort, out string host, out int port);
-            return string.Format("Server={0};Port={1};Database={2};User Id={3};Password={4}", 
-                host, port, Database, User, hidePassword ? HiddenPassword : Password);
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/SqlDataSource.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/SqlDataSource.cs
deleted file mode 100644
index 194458000..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/SqlDataSource.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Microsoft SQL Server interacting traits
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using System;
-using System.Data.Common;
-using System.Data.SqlClient;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Microsoft SQL Server interacting traits
-    /// Особенности взаимодействия с Microsoft SQL Server
-    /// 
-    internal class SqlDataSource : DataSource
-    {
-        /// 
-        /// Конструктор
-        /// 
-        public SqlDataSource()
-            : base()
-        {
-            DBType = DBType.MSSQL;
-        }
-
-
-        /// 
-        /// Проверить существование и тип соединения с БД
-        /// 
-        private void CheckConnection()
-        {
-            if (Connection == null)
-                throw new InvalidOperationException("Connection is not inited.");
-            if (!(Connection is SqlConnection))
-                throw new InvalidOperationException("SqlConnection is required.");
-        }
-
-
-        /// 
-        /// Создать соединение с БД
-        /// 
-        protected override DbConnection CreateConnection()
-        {
-            return new SqlConnection();
-        }
-
-        /// 
-        /// Очистить пул приложений
-        /// 
-        protected override void ClearPool()
-        {
-            CheckConnection();
-            SqlConnection.ClearPool((SqlConnection)Connection);
-        }
-
-        /// 
-        /// Создать команду
-        /// 
-        protected override DbCommand CreateCommand(string cmdText)
-        {
-            CheckConnection();
-            return new SqlCommand(cmdText, (SqlConnection)Connection);
-        }
-
-        /// 
-        /// Добавить параметр команды со значением
-        /// 
-        protected override void AddCmdParamWithValue(DbCommand cmd, string paramName, object value)
-        {
-            if (cmd == null)
-                throw new ArgumentNullException("cmd");
-            if (!(cmd is SqlCommand))
-                throw new ArgumentException("SqlCommand is required.", "cmd");
-
-            SqlCommand sqlCmd = (SqlCommand)cmd;
-            sqlCmd.Parameters.AddWithValue(paramName, value);
-        }
-
-
-        /// 
-        /// Построить строку соединения с БД на основе остальных свойств соединения
-        /// 
-        public override string BuildConnectionString(bool hidePassword)
-        {
-            return string.Format("Server={0};Database={1};User ID={2};Password={3}", 
-                Server, Database, User, hidePassword ? HiddenPassword : Password);
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/Exporter.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/Exporter.cs
deleted file mode 100644
index c51fb1953..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/Exporter.cs
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Exporter for one export destination
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- * 
- * Description
- * Server module for real time data export from Rapid SCADA to DB.
- */
-
-using Scada.Data.Tables;
-using System;
-using System.Collections.Generic;
-using System.Data.Common;
-using System.Text;
-using System.Threading;
-using Utils;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Exporter for one export destination.
-    /// Экспортёр для одного назначения экспорта.
-    /// 
-    internal class Exporter
-    {
-        private const int BundleSize = 10;    // количество объектов очереди, экспортируемых за один проход цикла
-        private const int ErrorDelay = 1000;  // задержка в случае ошибки экспорта, мс
-
-        private readonly Log log;             // журнал работы модуля
-        private readonly int maxQueueSize;    // максимальный размер очередей экспортируемых данных
-
-        private Queue curSrezQueue; // очередь экспортируемых текущих срезов
-        private Queue arcSrezQueue; // очередь экспортируемых архивных срезов
-        private Queue evQueue;    // очередь экспортируемых событий
-        private Thread thread;                           // поток работы экспортёра
-        private volatile bool terminated;                // необходимо завершить работу потока
-        private volatile bool running;                   // поток работает
-
-        // Состояние и статистика
-        private bool fatalError;    // фатальная ошибка экспортёра
-        private bool exportError;   // ошибка экспорта последнего объекта
-        private int expCurSrezCnt;  // количество экспортированных текущих срезов
-        private int expArcSrezCnt;  // количество экспортированных архивных срезов
-        private int expEvCnt;       // количество экспортированных событий
-        private int skipCurSrezCnt; // количество пропущенных текущих срезов
-        private int skipArcSrezCnt; // количество пропущенных архивных срезов
-        private int skipEvCnt;      // количество пропущенных событий
-
-
-        /// 
-        /// Конструктор, ограничивающий создание объекта без параметров
-        /// 
-        private Exporter()
-        {
-        }
-
-        /// 
-        /// Конструктор
-        /// 
-        public Exporter(ModConfig.ExportDestination expDest, Log log)
-        {
-            if (expDest == null)
-                throw new ArgumentNullException("expDest");
-
-            this.log = log ?? throw new ArgumentNullException("log");
-            maxQueueSize = expDest.ExportParams.MaxQueueSize;
-
-            curSrezQueue = new Queue(maxQueueSize);
-            arcSrezQueue = new Queue(maxQueueSize);
-            evQueue = new Queue(maxQueueSize);
-            thread = null;
-            terminated = false;
-            running = false;
-
-            ResetStats();
-
-            DataSource = expDest.DataSource;
-            ExportParams = expDest.ExportParams;
-        }
-
-
-        /// 
-        /// Получить источник данных
-        /// 
-        public DataSource DataSource { get; private set; }
-
-        /// 
-        /// Получить параметры экспорта
-        /// 
-        public ModConfig.ExportParams ExportParams { get; private set; }
-
-        /// 
-        /// Получить признак, что экспортёр работает
-        /// 
-        public bool Running
-        {
-            get
-            {
-                return running;
-            }
-        }
-
-
-        /// 
-        /// Инициализировать источник данных
-        /// 
-        private bool InitDataSource()
-        {
-            try
-            {
-                DataSource.InitConnection();
-                DataSource.InitCommands(
-                    ExportParams.ExportCurData ? ExportParams.ExportCurDataQuery : "",
-                    ExportParams.ExportArcData ? ExportParams.ExportArcDataQuery : "",
-                    ExportParams.ExportEvents ? ExportParams.ExportEventQuery : "");
-                return true;
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(string.Format(Localization.UseRussian ?
-                    "Ошибка при инициализации источника данных {0}: {1}" :
-                    "Error initializing data source {0}: {1}", DataSource.Name, ex.Message));
-                return false;
-            }
-        }
-
-        /// 
-        /// Сбросить статистику
-        /// 
-        private void ResetStats()
-        {
-            fatalError = false;
-            exportError = false;
-            expCurSrezCnt = 0;
-            expArcSrezCnt = 0;
-            expEvCnt = 0;
-            skipCurSrezCnt = 0;
-            skipArcSrezCnt = 0;
-            skipEvCnt = 0;
-        }
-
-        /// 
-        /// Безопасно откатить транзакцию
-        /// 
-        private void SafeRollback(DbTransaction trans)
-        {
-            if (trans != null)
-            {
-                try { trans.Rollback(); } catch { }
-            }
-        }
-
-        /// 
-        /// Цикл работы менеждера (метод вызывается в отдельном потоке)
-        /// 
-        private void Execute()
-        {
-            try
-            {
-                while (!terminated)
-                {
-                    try
-                    {
-                        // экспорт данных
-                        if (Connect())
-                        {
-                            ExportCurData();
-                            ExportArcData();
-                            ExportEvents();
-                        }
-                    }
-                    catch (ThreadAbortException)
-                    {
-                        log.WriteAction(Localization.UseRussian ?
-                            "Экспорт прерван. Не все данные экспортированы" :
-                            "Export is aborted. Not all data is exported");
-                    }
-                    finally
-                    {
-                        Disconnect();
-                    }
-
-                    Thread.Sleep(ScadaUtils.ThreadDelay);
-                }
-            }
-            finally
-            {
-                running = false;
-            }
-        }
-
-        /// 
-        /// Соединиться с БД с выводом возможной ошибки в журнал
-        /// 
-        private bool Connect()
-        {
-            try
-            {
-                DataSource.Connect();
-                return true;
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при соединении с БД {0}: {1}" :
-                    "Error connecting to DB {0}: {1}", DataSource.Name, ex.Message));
-                exportError = true;
-                Thread.Sleep(ErrorDelay);
-                return false;
-            }
-        }
-
-        /// 
-        /// Разъединиться с БД с выводом возможной ошибки в журнал
-        /// 
-        private void Disconnect()
-        {
-            try
-            {
-                DataSource.Disconnect();
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(string.Format(Localization.UseRussian ? "Ошибка при разъединении с БД {0}: {1}" :
-                    "Error disconnecting from DB {0}: {1}", DataSource.Name, ex.Message));
-            }
-        }
-
-        /// 
-        /// Экспортировать текущие данные
-        /// 
-        private void ExportCurData()
-        {
-            if (ExportParams.ExportCurData)
-            {
-                DbTransaction trans = null;
-                SrezTableLight.Srez srez = null;
-
-                try
-                {
-                    trans = DataSource.Connection.BeginTransaction();
-                    DataSource.ExportCurDataCmd.Transaction = trans;
-
-                    for (int i = 0; i < BundleSize; i++)
-                    {
-                        // извлечение среза из очереди
-                        lock (curSrezQueue)
-                        {
-                            if (curSrezQueue.Count > 0)
-                                srez = curSrezQueue.Dequeue();
-                            else
-                                break;
-                        }
-
-                        // экспорт
-                        ExportSrez(DataSource.ExportCurDataCmd, srez);
-
-                        expCurSrezCnt++;
-                        exportError = false;
-                    }
-
-                    trans.Commit();
-                }
-                catch (Exception ex)
-                {
-                    SafeRollback(trans);
-
-                    // возврат среза в очередь
-                    if (srez != null)
-                    {
-                        lock (curSrezQueue)
-                            curSrezQueue.Enqueue(srez);
-                    }
-
-                    log.WriteAction(string.Format(Localization.UseRussian ?
-                        "Ошибка при экспорте текущих данных в БД {0}: {1}" :
-                        "Error export current data to DB {0}: {1}", DataSource.Name, ex.Message));
-                    exportError = true;
-                    Thread.Sleep(ErrorDelay);
-                }
-            }
-        }
-
-        /// 
-        /// Экспортировать архивные данные
-        /// 
-        private void ExportArcData()
-        {
-            if (ExportParams.ExportArcData)
-            {
-                DbTransaction trans = null;
-                SrezTableLight.Srez srez = null;
-
-                try
-                {
-                    trans = DataSource.Connection.BeginTransaction();
-                    DataSource.ExportArcDataCmd.Transaction = trans;
-
-                    for (int i = 0; i < BundleSize; i++)
-                    {
-                        // извлечение среза из очереди
-                        lock (arcSrezQueue)
-                        {
-                            if (arcSrezQueue.Count > 0)
-                                srez = arcSrezQueue.Dequeue();
-                            else
-                                break;
-                        }
-
-                        // экспорт
-                        ExportSrez(DataSource.ExportArcDataCmd, srez);
-
-                        expArcSrezCnt++;
-                        exportError = false;
-                    }
-
-                    trans.Commit();
-                }
-                catch (Exception ex)
-                {
-                    SafeRollback(trans);
-
-                    // возврат среза в очередь
-                    if (srez != null)
-                    {
-                        lock (arcSrezQueue)
-                            arcSrezQueue.Enqueue(srez);
-                    }
-
-                    log.WriteAction(string.Format(Localization.UseRussian ?
-                        "Ошибка при экспорте архивных данных в БД {0}: {1}" :
-                        "Error export archive data to DB {0}: {1}", DataSource.Name, ex.Message));
-                    exportError = true;
-                    Thread.Sleep(ErrorDelay);
-                }
-            }
-        }
-
-        /// 
-        /// Экспортировать события
-        /// 
-        private void ExportEvents()
-        {
-            if (ExportParams.ExportEvents)
-            {
-                DbTransaction trans = null;
-                EventTableLight.Event ev = null;
-
-                try
-                {
-                    trans = DataSource.Connection.BeginTransaction();
-                    DataSource.ExportEventCmd.Transaction = trans;
-
-                    for (int i = 0; i < BundleSize; i++)
-                    {
-                        // извлечение события из очереди
-                        lock (evQueue)
-                        {
-                            if (evQueue.Count > 0)
-                                ev = evQueue.Dequeue();
-                            else
-                                break;
-                        }
-
-                        // экспорт
-                        ExportEvent(DataSource.ExportEventCmd, ev);
-
-                        expEvCnt++;
-                        exportError = false;
-                    }
-
-                    trans.Commit();
-                }
-                catch (Exception ex)
-                {
-                    SafeRollback(trans);
-
-                    // возврат события в очередь
-                    if (ev != null)
-                    {
-                        lock (evQueue)
-                            evQueue.Enqueue(ev);
-                    }
-
-                    log.WriteAction(string.Format(Localization.UseRussian ?
-                        "Ошибка при экспорте событий в БД {0}: {1}" :
-                        "Error export events to DB {0}: {1}", DataSource.Name, ex.Message));
-                    exportError = true;
-                    Thread.Sleep(ErrorDelay);
-                }
-            }
-        }
-        
-        /// 
-        /// Экспортировать срез
-        /// 
-        private void ExportSrez(DbCommand cmd, SrezTableLight.Srez srez)
-        {
-            DataSource.SetCmdParam(cmd, "dateTime", srez.DateTime);
-
-            foreach (int cnlNum in srez.CnlNums)
-            {
-                SrezTableLight.CnlData cnlData;
-                if (srez.GetCnlData(cnlNum, out cnlData))
-                {
-                    DataSource.SetCmdParam(cmd, "cnlNum", cnlNum);
-                    DataSource.SetCmdParam(cmd, "val", cnlData.Val);
-                    DataSource.SetCmdParam(cmd, "stat", cnlData.Stat);
-                    cmd.ExecuteNonQuery();
-                }
-            }
-        }
-
-        /// 
-        /// Экспортировать событие
-        /// 
-        private void ExportEvent(DbCommand cmd, EventTableLight.Event ev)
-        {
-            DataSource.SetCmdParam(cmd, "dateTime", ev.DateTime);
-            DataSource.SetCmdParam(cmd, "objNum", ev.ObjNum);
-            DataSource.SetCmdParam(cmd, "kpNum", ev.KPNum);
-            DataSource.SetCmdParam(cmd, "paramID", ev.ParamID);
-            DataSource.SetCmdParam(cmd, "cnlNum", ev.CnlNum);
-            DataSource.SetCmdParam(cmd, "oldCnlVal", ev.OldCnlVal);
-            DataSource.SetCmdParam(cmd, "oldCnlStat", ev.OldCnlStat);
-            DataSource.SetCmdParam(cmd, "newCnlVal", ev.NewCnlVal);
-            DataSource.SetCmdParam(cmd, "newCnlStat", ev.NewCnlStat);
-            DataSource.SetCmdParam(cmd, "checked", ev.Checked);
-            DataSource.SetCmdParam(cmd, "userID", ev.UserID);
-            DataSource.SetCmdParam(cmd, "descr", ev.Descr);
-            DataSource.SetCmdParam(cmd, "data", ev.Data);
-            cmd.ExecuteNonQuery();
-        }
-
-
-        /// 
-        /// Запустить работу экспортёра
-        /// 
-        public void Start()
-        {
-            if (InitDataSource())
-            {
-                ResetStats();
-                terminated = false;
-                running = true;
-                thread = new Thread(new ThreadStart(Execute));
-                thread.Start();
-            }
-            else
-            {
-                fatalError = true;
-            }
-        }
-
-        /// 
-        /// Начать остановку работы экспортёра
-        /// 
-        public void Terminate()
-        {
-            terminated = true;
-        }
-
-        /// 
-        /// Прервать работу экспортёра
-        /// 
-        public void Abort()
-        {
-            if (thread != null)
-                thread.Abort();
-        }
-
-        /// 
-        /// Добавить текущие данные в очередь экспорта
-        /// 
-        public void EnqueueCurData(SrezTableLight.Srez curSrez)
-        {
-            if (ExportParams.ExportCurData)
-            {
-                lock (curSrezQueue)
-                {
-                    if (curSrezQueue.Count < maxQueueSize)
-                    {
-                        curSrezQueue.Enqueue(curSrez);
-                    }
-                    else
-                    {
-                        skipCurSrezCnt++;
-                        log.WriteAction(string.Format(Localization.UseRussian ?
-                            "Невозможно добавить в очередь текущие данные. Максимальный размер очереди {0} превышен" :
-                            "Unable to enqueue current data. The maximum size of the queue {0} is exceeded",
-                            maxQueueSize));
-                    }
-                }
-            }
-        }
-
-        /// 
-        /// Добавить архивные данные в очередь экспорта
-        /// 
-        public void EnqueueArcData(SrezTableLight.Srez arcSrez)
-        {
-            if (ExportParams.ExportArcData)
-            {
-                lock (arcSrezQueue)
-                {
-                    if (arcSrezQueue.Count < maxQueueSize)
-                    {
-                        arcSrezQueue.Enqueue(arcSrez);
-                    }
-                    else
-                    {
-                        skipArcSrezCnt++;
-                        log.WriteAction(string.Format(Localization.UseRussian ?
-                            "Невозможно добавить в очередь архивные данные. Максимальный размер очереди {0} превышен" :
-                            "Unable to enqueue archive data. The maximum size of the queue {0} is exceeded",
-                            maxQueueSize));
-                    }
-                }
-            }
-        }
-
-        /// 
-        /// Добавить событие в очередь экспорта
-        /// 
-        public void EnqueueEvent(EventTableLight.Event ev)
-        {
-            if (ExportParams.ExportEvents)
-            {
-                lock (evQueue)
-                {
-                    if (evQueue.Count < maxQueueSize)
-                    {
-                        evQueue.Enqueue(ev);
-                    }
-                    else
-                    {
-                        skipEvCnt++;
-                        log.WriteAction(string.Format(Localization.UseRussian ?
-                            "Невозможно добавить в очередь событие. Максимальный размер очереди {0} превышен" :
-                            "Unable to enqueue an event. The maximum size of the queue {0} is exceeded",
-                            maxQueueSize));
-                    }
-                }
-            }
-        }
-
-        /// 
-        /// Получить информацию о работе экспортёра
-        /// 
-        public string GetInfo()
-        {
-            StringBuilder sbInfo = new StringBuilder(DataSource.Name);
-            string stateStr;
-
-            // получение длин очередей
-            int curSrezQueueCnt;
-            lock (curSrezQueue)
-                curSrezQueueCnt = curSrezQueue.Count;
-
-            int arcSrezQueueCnt;
-            lock (arcSrezQueue)
-                arcSrezQueueCnt = arcSrezQueue.Count;
-
-            int evQueueCnt;
-            lock (evQueue)
-                evQueueCnt = evQueue.Count;
-
-            // формирование текста
-            if (Localization.UseRussian)
-            {
-                if (fatalError)
-                    stateStr = "фатальная ошибка";
-                else if (exportError)
-                    stateStr = "ошибка экспорта";
-                else
-                    stateStr = "норма";
-
-                sbInfo
-                    .Append("; состояние: ").Append(stateStr)
-                    .Append("; в очереди тек/арх/соб: ")
-                    .Append(curSrezQueueCnt).Append("/").Append(arcSrezQueueCnt).Append("/").Append(evQueueCnt)
-                    .Append("; экспортировано тек/арх/соб: ")
-                    .Append(expCurSrezCnt).Append("/").Append(expArcSrezCnt).Append("/").Append(expEvCnt)
-                    .Append("; пропущено тек/арх/соб: ")
-                    .Append(skipCurSrezCnt).Append("/").Append(skipArcSrezCnt).Append("/").Append(skipEvCnt);
-            }
-            else
-            {
-                if (fatalError)
-                    stateStr = "fatal error";
-                else if (exportError)
-                    stateStr = "export error";
-                else
-                    stateStr = "normal";
-
-                sbInfo
-                    .Append("; state: ").Append(stateStr)
-                    .Append("; in queue cur/arc/ev: ")
-                    .Append(curSrezQueueCnt).Append("/").Append(arcSrezQueueCnt).Append("/").Append(evQueueCnt)
-                    .Append("; exported cur/arc/ev: ")
-                    .Append(expCurSrezCnt).Append("/").Append(expArcSrezCnt).Append("/").Append(expEvCnt)
-                    .Append("; skipped cur/arc/ev: ")
-                    .Append(skipCurSrezCnt).Append("/").Append(skipArcSrezCnt).Append("/").Append(skipEvCnt);
-            }
-
-            return sbInfo.ToString();
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/ModConfig.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/ModConfig.cs
deleted file mode 100644
index 1062eb61f..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/ModConfig.cs
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Module configuration
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Xml;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Module configuration.
-    /// Конфигурация модуля.
-    /// 
-    internal class ModConfig
-    {
-        /// 
-        /// Параметры экспорта.
-        /// 
-        public class ExportParams
-        {
-            /// 
-            /// Конструктор
-            /// 
-            public ExportParams()
-            {
-                ExportCurData = false;
-                ExportCurDataQuery = "";
-                ExportArcData = false;
-                ExportArcDataQuery = "";
-                ExportEvents = false;
-                ExportEventQuery = "";
-                MaxQueueSize = 100;
-            }
-
-            /// 
-            /// Получить или установить признак, экспортировать ли текущие данные
-            /// 
-            public bool ExportCurData { get; set; }
-            /// 
-            /// Получить или установить SQL-запрос для экспорта текущих данных
-            /// 
-            public string ExportCurDataQuery { get; set; }
-            /// 
-            /// Получить или установить признак, экспортировать ли архивные данные
-            /// 
-            public bool ExportArcData { get; set; }
-            /// 
-            /// Получить или установить SQL-запрос для экспорта архивных данных
-            /// 
-            public string ExportArcDataQuery { get; set; }
-            /// 
-            /// Получить или установить признак, экспортировать ли события
-            /// 
-            public bool ExportEvents { get; set; }
-            /// 
-            /// Получить или установить SQL-запрос для экспорта событий
-            /// 
-            public string ExportEventQuery { get; set; }
-            /// 
-            /// Gets or sets the maximum queue size.
-            /// 
-            public int MaxQueueSize { get; set; }
-
-            /// 
-            /// Loads the parameters from the XML node.
-            /// 
-            public void LoadFromXml(XmlNode xmlNode)
-            {
-                if (xmlNode == null)
-                    throw new ArgumentNullException("xmlNode");
-
-                ExportCurDataQuery = xmlNode.GetChildAsString("ExportCurDataQuery");
-                ExportCurData = !string.IsNullOrEmpty(ExportCurDataQuery) && xmlNode.GetChildAsBool("ExportCurData");
-                ExportArcDataQuery = xmlNode.GetChildAsString("ExportArcDataQuery");
-                ExportArcData = !string.IsNullOrEmpty(ExportArcDataQuery) && xmlNode.GetChildAsBool("ExportArcData");
-                ExportEventQuery = xmlNode.GetChildAsString("ExportEventQuery");
-                ExportEvents = !string.IsNullOrEmpty(ExportEventQuery) && xmlNode.GetChildAsBool("ExportEvents");
-                MaxQueueSize = xmlNode.GetChildAsInt("MaxQueueSize", MaxQueueSize);
-            }
-
-            /// 
-            /// Saves the parameters into the XML node.
-            /// 
-            public void SaveToXml(XmlElement xmlElem)
-            {
-                if (xmlElem == null)
-                    throw new ArgumentNullException("xmlElem");
-
-                xmlElem.AppendElem("ExportCurData", ExportCurData);
-                xmlElem.AppendElem("ExportCurDataQuery", ExportCurDataQuery);
-                xmlElem.AppendElem("ExportArcData", ExportArcData);
-                xmlElem.AppendElem("ExportArcDataQuery", ExportArcDataQuery);
-                xmlElem.AppendElem("ExportEvents", ExportEvents);
-                xmlElem.AppendElem("ExportEventQuery", ExportEventQuery);
-                xmlElem.AppendElem("MaxQueueSize", MaxQueueSize);
-            }
-
-            /// 
-            /// Клонировать параметры экспорта
-            /// 
-            public ExportParams Clone()
-            {
-                return new ExportParams()
-                    {
-                        ExportCurData = ExportCurData,
-                        ExportCurDataQuery = ExportCurDataQuery,
-                        ExportArcData = ExportArcData,
-                        ExportArcDataQuery = ExportArcDataQuery,
-                        ExportEvents = ExportEvents,
-                        ExportEventQuery = ExportEventQuery,
-                        MaxQueueSize = MaxQueueSize
-                    };
-            }
-        }
-
-        /// 
-        /// Назначение экспорта
-        /// 
-        public class ExportDestination : IComparable
-        {
-            /// 
-            /// Конструктор, ограничивающий создание объекта без параметров
-            /// 
-            private ExportDestination()
-            {
-            }
-            /// 
-            /// Конструктор
-            /// 
-            public ExportDestination(DataSource dataSource, ExportParams exportParams)
-            {
-                if (dataSource == null)
-                    throw new ArgumentNullException("dataSource");
-                if (exportParams == null)
-                    throw new ArgumentNullException("exportParams");
-                
-                this.DataSource = dataSource;
-                this.ExportParams = exportParams;
-            }
-
-            /// 
-            /// Получить источник данных
-            /// 
-            public DataSource DataSource { get; private set; }
-            /// 
-            /// Получить параметры экспорта
-            /// 
-            public ExportParams ExportParams { get; private set; }
-
-            /// 
-            /// Клонировать назначение экспорта
-            /// 
-            public ExportDestination Clone()
-            {
-                return new ExportDestination(DataSource.Clone(), ExportParams.Clone());
-            }
-            /// 
-            /// Сравнить текущий объект с другим объектом такого же типа
-            /// 
-            public int CompareTo(ExportDestination other)
-            {
-                return DataSource.CompareTo(other.DataSource);
-            }
-        }
-
-
-        /// 
-        /// Имя файла конфигурации
-        /// 
-        private const string ConfigFileName = "ModDBExport.xml";
-
-
-        /// 
-        /// Конструктор, ограничивающий создание объекта без параметров
-        /// 
-        private ModConfig()
-        {
-        }
-
-        /// 
-        /// Конструктор
-        /// 
-        public ModConfig(string configDir)
-        {
-            FileName = ScadaUtils.NormalDir(configDir) + ConfigFileName;
-            SetToDefault();
-        }
-
-
-        /// 
-        /// Получить полное имя файла конфигурации
-        /// 
-        public string FileName { get; private set; }
-
-        /// 
-        /// Получить назначения экспорта
-        /// 
-        public List ExportDestinations { get; private set; }
-
-        /// 
-        /// Получить или установить номер канала управления для экспорта текущих данных в ручном режиме
-        /// 
-        public int CurDataCtrlCnlNum { get; set; }
-
-        /// 
-        /// Получить или установить номер канала управления для экспорта архивных данных в ручном режиме
-        /// 
-        public int ArcDataCtrlCnlNum { get; set; }
-
-        /// 
-        /// Получить или установить номер канала управления для экспорта событий в ручном режиме
-        /// 
-        public int EventsCtrlCnlNum { get; set; }
-
-
-        /// 
-        /// Установить значения параметров конфигурации по умолчанию
-        /// 
-        private void SetToDefault()
-        {
-            if (ExportDestinations == null)
-                ExportDestinations = new List();
-            else
-                ExportDestinations.Clear();
-
-            CurDataCtrlCnlNum = 1;
-            ArcDataCtrlCnlNum = 2;
-            EventsCtrlCnlNum = 3;
-        }
-
-        /// 
-        /// Загрузить конфигурацию модуля
-        /// 
-        public bool Load(out string errMsg)
-        {
-            SetToDefault();
-
-            try
-            {
-                XmlDocument xmlDoc = new XmlDocument();
-                xmlDoc.Load(FileName);
-
-                // загрузка назначений экспорта
-                XmlNode expDestsNode = xmlDoc.DocumentElement.SelectSingleNode("ExportDestinations");
-                if (expDestsNode != null)
-                {
-                    XmlNodeList expDestNodeList = expDestsNode.SelectNodes("ExportDestination");
-                    foreach (XmlElement expDestElem in expDestNodeList)
-                    {
-                        // загрузка источника данных
-                        DataSource dataSource = null;
-
-                        if (expDestElem.SelectSingleNode("DataSource") is XmlNode dataSourceNode)
-                        {
-                            // получение типа источника данных
-                            if (!Enum.TryParse(dataSourceNode.GetChildAsString("DBType"), out DBType dbType))
-                                dbType = DBType.Undefined;
-
-                            // создание источника данных
-                            switch (dbType)
-                            {
-                                case DBType.MSSQL:
-                                    dataSource = new SqlDataSource();
-                                    break;
-                                case DBType.Oracle:
-                                    dataSource = new OraDataSource();
-                                    break;
-                                case DBType.PostgreSQL:
-                                    dataSource = new PgSqlDataSource();
-                                    break;
-                                case DBType.MySQL:
-                                    dataSource = new MySqlDataSource();
-                                    break;
-                                case DBType.OLEDB:
-                                    dataSource = new OleDbDataSource();
-                                    break;
-                                default:
-                                    dataSource = null;
-                                    break;
-                            }
-
-                            if (dataSource != null)
-                            {
-                                dataSource.Server = dataSourceNode.GetChildAsString("Server");
-                                dataSource.Database = dataSourceNode.GetChildAsString("Database");
-                                dataSource.User = dataSourceNode.GetChildAsString("User");
-                                dataSource.Password = ScadaUtils.Decrypt(dataSourceNode.GetChildAsString("Password"));
-                                dataSource.ConnectionString = dataSourceNode.GetChildAsString("ConnectionString");
-
-                                if (string.IsNullOrEmpty(dataSource.ConnectionString))
-                                    dataSource.ConnectionString = dataSource.BuildConnectionString();
-                            }
-                        }
-
-                        if (dataSource != null && 
-                            expDestElem.SelectSingleNode("ExportParams") is XmlNode exportParamsNode)
-                        {
-                            // загрузка параметров экспорта
-                            ExportParams exportParams = new ExportParams();
-                            exportParams.LoadFromXml(exportParamsNode);
-
-                            // создание назначения экспорта
-                            ExportDestination expDest = new ExportDestination(dataSource, exportParams);
-                            ExportDestinations.Add(expDest);
-                        }
-                    }
-
-                    // сортировка назначений экспорта
-                    ExportDestinations.Sort();
-                }
-
-                // загрузка номеров каналов управления для экспорта в ручном режиме
-                if (xmlDoc.DocumentElement.SelectSingleNode("ManualExport") is XmlNode manExpNode)
-                {
-                    CurDataCtrlCnlNum = manExpNode.GetChildAsInt("CurDataCtrlCnlNum");
-                    ArcDataCtrlCnlNum = manExpNode.GetChildAsInt("ArcDataCtrlCnlNum");
-                    EventsCtrlCnlNum = manExpNode.GetChildAsInt("EventsCtrlCnlNum");
-                }
-
-                errMsg = "";
-                return true;
-            }
-            catch (FileNotFoundException ex)
-            {
-                errMsg = ModPhrases.LoadModSettingsError + ": " + ex.Message + 
-                    Environment.NewLine + ModPhrases.ConfigureModule;
-                return false;
-            }
-            catch (Exception ex)
-            {
-                errMsg = ModPhrases.LoadModSettingsError + ": " + ex.Message;
-                return false;
-            }
-        }
-
-        /// 
-        /// Сохранить конфигурацию модуля
-        /// 
-        public bool Save(out string errMsg)
-        {
-            try
-            {
-                XmlDocument xmlDoc = new XmlDocument();
-
-                XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
-                xmlDoc.AppendChild(xmlDecl);
-
-                XmlElement rootElem = xmlDoc.CreateElement("ModDBExport");
-                xmlDoc.AppendChild(rootElem);
-
-                // сохранение назначений экспорта
-                XmlElement expDestsElem = rootElem.AppendElem("ExportDestinations");
-
-                foreach (ExportDestination expDest in ExportDestinations)
-                {
-                    XmlElement expDestElem = expDestsElem.AppendElem("ExportDestination");
-
-                    // сохранение источника данных
-                    DataSource dataSource = expDest.DataSource;
-                    XmlElement dataSourceElem = expDestElem.AppendElem("DataSource");
-                    dataSourceElem.AppendElem("DBType", dataSource.DBType);
-                    dataSourceElem.AppendElem("Server", dataSource.Server);
-                    dataSourceElem.AppendElem("Database", dataSource.Database);
-                    dataSourceElem.AppendElem("User", dataSource.User);
-                    dataSourceElem.AppendElem("Password", ScadaUtils.Encrypt(dataSource.Password));
-                    string connStr = dataSource.ConnectionString;
-                    string bldConnStr = dataSource.BuildConnectionString();
-                    dataSourceElem.AppendElem("ConnectionString", 
-                        !string.IsNullOrEmpty(bldConnStr) && bldConnStr == connStr ? "" : connStr);
-
-                    // сохранение параметров экспорта
-                    expDest.ExportParams.SaveToXml(expDestElem.AppendElem("ExportParams"));
-                }
-
-                // сохранение номеров каналов управления для экспорта в ручном режиме
-                XmlElement manExpElem = rootElem.AppendElem("ManualExport");
-                manExpElem.AppendElem("CurDataCtrlCnlNum", CurDataCtrlCnlNum);
-                manExpElem.AppendElem("ArcDataCtrlCnlNum", ArcDataCtrlCnlNum);
-                manExpElem.AppendElem("EventsCtrlCnlNum", EventsCtrlCnlNum);
-
-                xmlDoc.Save(FileName);
-                errMsg = "";
-                return true;
-            }
-            catch (Exception ex)
-            {
-                errMsg = ModPhrases.SaveModSettingsError + ": " + ex.Message;
-                return false;
-            }
-        }
-
-        /// 
-        /// Клонировать конфигурацию модуля
-        /// 
-        public ModConfig Clone()
-        {
-            ModConfig configCopy = new ModConfig
-            {
-                FileName = FileName,
-                ExportDestinations = new List()
-            };
-
-            foreach (ExportDestination expDest in ExportDestinations)
-            {
-                configCopy.ExportDestinations.Add(expDest.Clone());
-            }
-
-            configCopy.CurDataCtrlCnlNum = CurDataCtrlCnlNum;
-            configCopy.ArcDataCtrlCnlNum = ArcDataCtrlCnlNum;
-            configCopy.EventsCtrlCnlNum = EventsCtrlCnlNum;
-
-            return configCopy;
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.Designer.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.Designer.cs
deleted file mode 100644
index b2bbdb35f..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.Designer.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-namespace Scada.Server.Modules.DBExport
-{
-    partial class CtrlExportQuery
-    {
-        ///  
-        /// Required designer variable.
-        /// 
-        private System.ComponentModel.IContainer components = null;
-
-        ///  
-        /// Clean up any resources being used.
-        /// 
-        /// true if managed resources should be disposed; otherwise, false.
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Component Designer generated code
-
-        ///  
-        /// Required method for Designer support - do not modify 
-        /// the contents of this method with the code editor.
-        /// 
-        private void InitializeComponent()
-        {
-            this.txtQuery = new System.Windows.Forms.TextBox();
-            this.lblQuery = new System.Windows.Forms.Label();
-            this.chkExport = new System.Windows.Forms.CheckBox();
-            this.SuspendLayout();
-            // 
-            // txtQuery
-            // 
-            this.txtQuery.Location = new System.Drawing.Point(0, 36);
-            this.txtQuery.Multiline = true;
-            this.txtQuery.Name = "txtQuery";
-            this.txtQuery.ScrollBars = System.Windows.Forms.ScrollBars.Both;
-            this.txtQuery.Size = new System.Drawing.Size(465, 319);
-            this.txtQuery.TabIndex = 2;
-            this.txtQuery.WordWrap = false;
-            this.txtQuery.TextChanged += new System.EventHandler(this.txtQuery_TextChanged);
-            // 
-            // lblQuery
-            // 
-            this.lblQuery.AutoSize = true;
-            this.lblQuery.Location = new System.Drawing.Point(-3, 20);
-            this.lblQuery.Name = "lblQuery";
-            this.lblQuery.Size = new System.Drawing.Size(28, 13);
-            this.lblQuery.TabIndex = 1;
-            this.lblQuery.Text = "SQL";
-            // 
-            // chkExport
-            // 
-            this.chkExport.AutoSize = true;
-            this.chkExport.Location = new System.Drawing.Point(0, 0);
-            this.chkExport.Name = "chkExport";
-            this.chkExport.Size = new System.Drawing.Size(109, 17);
-            this.chkExport.TabIndex = 0;
-            this.chkExport.Text = "Экспортировать";
-            this.chkExport.UseVisualStyleBackColor = true;
-            this.chkExport.CheckedChanged += new System.EventHandler(this.chkExport_CheckedChanged);
-            // 
-            // CtrlExportQuery
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.Controls.Add(this.txtQuery);
-            this.Controls.Add(this.lblQuery);
-            this.Controls.Add(this.chkExport);
-            this.Name = "CtrlExportQuery";
-            this.Size = new System.Drawing.Size(465, 355);
-            this.Load += new System.EventHandler(this.CtrlExportQuery_Load);
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.TextBox txtQuery;
-        private System.Windows.Forms.Label lblQuery;
-        private System.Windows.Forms.CheckBox chkExport;
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.cs
deleted file mode 100644
index b80ca2831..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2015 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Query configuration control
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2015
- */
-
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Linq;
-using System.Text;
-using System.Windows.Forms;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Query configuration control
-    /// Элемент управления для конфигурации запроса
-    /// 
-    internal partial class CtrlExportQuery : UserControl
-    {
-        /// 
-        /// Конструктор
-        /// 
-        public CtrlExportQuery()
-        {
-            InitializeComponent();
-        }
-
-
-        /// 
-        /// Получить или установить признак выполнения экспорта
-        /// 
-        public bool Export
-        {
-            get
-            {
-                return chkExport.Checked;
-            }
-            set
-            {
-                chkExport.CheckedChanged -= chkExport_CheckedChanged;
-                chkExport.Checked = value;
-                chkExport.CheckedChanged += chkExport_CheckedChanged;
-                SetQueryBackColor();
-            }
-        }
-
-        /// 
-        /// Получить или установить SQL-запрос
-        /// 
-        public string Query
-        {
-            get
-            {
-                return txtQuery.Text;
-            }
-            set
-            {
-                txtQuery.TextChanged -= txtQuery_TextChanged;
-                txtQuery.Text = value;
-                txtQuery.TextChanged += txtQuery_TextChanged;
-            }
-        }
-
-
-        /// 
-        /// Установить цвет фона текстового поля запроса
-        /// 
-        private void SetQueryBackColor()
-        {
-            txtQuery.BackColor = Color.FromKnownColor(chkExport.Checked ? KnownColor.Window : KnownColor.Control);
-        }
-
-        /// 
-        /// Вызвать событие TriggerChanged
-        /// 
-        private void OnPropChanged()
-        {
-            if (PropChanged != null)
-                PropChanged(this, EventArgs.Empty);
-        }
-
-
-        /// 
-        /// Событие возникающее при изменении свойств элемента управления
-        /// 
-        [Category("Property Changed")]
-        public event EventHandler PropChanged;
-
-
-        private void CtrlExportQuery_Load(object sender, EventArgs e)
-        {
-            SetQueryBackColor();
-        }
-
-        private void chkExport_CheckedChanged(object sender, EventArgs e)
-        {
-            SetQueryBackColor();
-            OnPropChanged();
-        }
-
-        private void txtQuery_TextChanged(object sender, EventArgs e)
-        {
-            Export = txtQuery.Text != "";
-            OnPropChanged();
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.Designer.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.Designer.cs
deleted file mode 100644
index 4b7c807a0..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.Designer.cs
+++ /dev/null
@@ -1,542 +0,0 @@
-namespace Scada.Server.Modules.DBExport
-{
-    partial class FrmDBExportConfig
-    {
-        /// 
-        /// Required designer variable.
-        /// 
-        private System.ComponentModel.IContainer components = null;
-
-        /// 
-        /// Clean up any resources being used.
-        /// 
-        /// true if managed resources should be disposed; otherwise, false.
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Windows Form Designer generated code
-
-        /// 
-        /// Required method for Designer support - do not modify
-        /// the contents of this method with the code editor.
-        /// 
-        private void InitializeComponent()
-        {
-            this.components = new System.ComponentModel.Container();
-            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmDBExportConfig));
-            this.treeView = new System.Windows.Forms.TreeView();
-            this.ilTree = new System.Windows.Forms.ImageList(this.components);
-            this.btnSave = new System.Windows.Forms.Button();
-            this.btnCancel = new System.Windows.Forms.Button();
-            this.btnClose = new System.Windows.Forms.Button();
-            this.tabControl = new System.Windows.Forms.TabControl();
-            this.pageConnection = new System.Windows.Forms.TabPage();
-            this.txtConnectionString = new System.Windows.Forms.TextBox();
-            this.lblConnectionString = new System.Windows.Forms.Label();
-            this.lblPassword = new System.Windows.Forms.Label();
-            this.txtPassword = new System.Windows.Forms.TextBox();
-            this.txtUser = new System.Windows.Forms.TextBox();
-            this.lblUser = new System.Windows.Forms.Label();
-            this.txtDatabase = new System.Windows.Forms.TextBox();
-            this.lblDatabase = new System.Windows.Forms.Label();
-            this.txtServer = new System.Windows.Forms.TextBox();
-            this.lblServer = new System.Windows.Forms.Label();
-            this.pageExportCurDataQuery = new System.Windows.Forms.TabPage();
-            this.ctrlExportCurDataQuery = new Scada.Server.Modules.DBExport.CtrlExportQuery();
-            this.pageExportArcDataQuery = new System.Windows.Forms.TabPage();
-            this.ctrlExportArcDataQuery = new Scada.Server.Modules.DBExport.CtrlExportQuery();
-            this.pageExportEventQuery = new System.Windows.Forms.TabPage();
-            this.ctrlExportEventQuery = new Scada.Server.Modules.DBExport.CtrlExportQuery();
-            this.pageMisc = new System.Windows.Forms.TabPage();
-            this.numMaxQueueSize = new System.Windows.Forms.NumericUpDown();
-            this.lblMaxQueueSize = new System.Windows.Forms.Label();
-            this.toolStrip = new System.Windows.Forms.ToolStrip();
-            this.ddbAddDataSource = new System.Windows.Forms.ToolStripDropDownButton();
-            this.miAddSqlDataSource = new System.Windows.Forms.ToolStripMenuItem();
-            this.miAddOraDataSource = new System.Windows.Forms.ToolStripMenuItem();
-            this.miAddPgSqlDataSource = new System.Windows.Forms.ToolStripMenuItem();
-            this.miAddMySqlDataSource = new System.Windows.Forms.ToolStripMenuItem();
-            this.miAddOleDbDataSource = new System.Windows.Forms.ToolStripMenuItem();
-            this.btnDelDataSource = new System.Windows.Forms.ToolStripButton();
-            this.sep1 = new System.Windows.Forms.ToolStripSeparator();
-            this.btnManualExport = new System.Windows.Forms.ToolStripButton();
-            this.lblInstruction = new System.Windows.Forms.Label();
-            this.tabControl.SuspendLayout();
-            this.pageConnection.SuspendLayout();
-            this.pageExportCurDataQuery.SuspendLayout();
-            this.pageExportArcDataQuery.SuspendLayout();
-            this.pageExportEventQuery.SuspendLayout();
-            this.pageMisc.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numMaxQueueSize)).BeginInit();
-            this.toolStrip.SuspendLayout();
-            this.SuspendLayout();
-            // 
-            // treeView
-            // 
-            this.treeView.HideSelection = false;
-            this.treeView.ImageIndex = 0;
-            this.treeView.ImageList = this.ilTree;
-            this.treeView.Location = new System.Drawing.Point(0, 28);
-            this.treeView.Name = "treeView";
-            this.treeView.SelectedImageIndex = 0;
-            this.treeView.ShowRootLines = false;
-            this.treeView.Size = new System.Drawing.Size(200, 392);
-            this.treeView.TabIndex = 1;
-            this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView_AfterSelect);
-            // 
-            // ilTree
-            // 
-            this.ilTree.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ilTree.ImageStream")));
-            this.ilTree.TransparentColor = System.Drawing.Color.Transparent;
-            this.ilTree.Images.SetKeyName(0, "mssql.png");
-            this.ilTree.Images.SetKeyName(1, "oracle.png");
-            this.ilTree.Images.SetKeyName(2, "postgresql.png");
-            this.ilTree.Images.SetKeyName(3, "mysql.png");
-            this.ilTree.Images.SetKeyName(4, "oledb.png");
-            // 
-            // btnSave
-            // 
-            this.btnSave.Location = new System.Drawing.Point(435, 427);
-            this.btnSave.Name = "btnSave";
-            this.btnSave.Size = new System.Drawing.Size(75, 23);
-            this.btnSave.TabIndex = 4;
-            this.btnSave.Text = "Сохранить";
-            this.btnSave.UseVisualStyleBackColor = true;
-            this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
-            // 
-            // btnCancel
-            // 
-            this.btnCancel.Location = new System.Drawing.Point(516, 427);
-            this.btnCancel.Name = "btnCancel";
-            this.btnCancel.Size = new System.Drawing.Size(75, 23);
-            this.btnCancel.TabIndex = 5;
-            this.btnCancel.Text = "Отмена";
-            this.btnCancel.UseVisualStyleBackColor = true;
-            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
-            // 
-            // btnClose
-            // 
-            this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
-            this.btnClose.Location = new System.Drawing.Point(597, 427);
-            this.btnClose.Name = "btnClose";
-            this.btnClose.Size = new System.Drawing.Size(75, 23);
-            this.btnClose.TabIndex = 6;
-            this.btnClose.Text = "Закрыть";
-            this.btnClose.UseVisualStyleBackColor = true;
-            // 
-            // tabControl
-            // 
-            this.tabControl.Controls.Add(this.pageConnection);
-            this.tabControl.Controls.Add(this.pageExportCurDataQuery);
-            this.tabControl.Controls.Add(this.pageExportArcDataQuery);
-            this.tabControl.Controls.Add(this.pageExportEventQuery);
-            this.tabControl.Controls.Add(this.pageMisc);
-            this.tabControl.Location = new System.Drawing.Point(200, 28);
-            this.tabControl.Name = "tabControl";
-            this.tabControl.SelectedIndex = 0;
-            this.tabControl.Size = new System.Drawing.Size(485, 393);
-            this.tabControl.TabIndex = 3;
-            // 
-            // pageConnection
-            // 
-            this.pageConnection.Controls.Add(this.txtConnectionString);
-            this.pageConnection.Controls.Add(this.lblConnectionString);
-            this.pageConnection.Controls.Add(this.lblPassword);
-            this.pageConnection.Controls.Add(this.txtPassword);
-            this.pageConnection.Controls.Add(this.txtUser);
-            this.pageConnection.Controls.Add(this.lblUser);
-            this.pageConnection.Controls.Add(this.txtDatabase);
-            this.pageConnection.Controls.Add(this.lblDatabase);
-            this.pageConnection.Controls.Add(this.txtServer);
-            this.pageConnection.Controls.Add(this.lblServer);
-            this.pageConnection.Location = new System.Drawing.Point(4, 22);
-            this.pageConnection.Name = "pageConnection";
-            this.pageConnection.Padding = new System.Windows.Forms.Padding(3);
-            this.pageConnection.Size = new System.Drawing.Size(477, 367);
-            this.pageConnection.TabIndex = 3;
-            this.pageConnection.Text = "Соединение";
-            this.pageConnection.UseVisualStyleBackColor = true;
-            // 
-            // txtConnectionString
-            // 
-            this.txtConnectionString.Location = new System.Drawing.Point(6, 136);
-            this.txtConnectionString.Multiline = true;
-            this.txtConnectionString.Name = "txtConnectionString";
-            this.txtConnectionString.Size = new System.Drawing.Size(465, 50);
-            this.txtConnectionString.TabIndex = 9;
-            this.txtConnectionString.TextChanged += new System.EventHandler(this.txtConnectionString_TextChanged);
-            // 
-            // lblConnectionString
-            // 
-            this.lblConnectionString.AutoSize = true;
-            this.lblConnectionString.Location = new System.Drawing.Point(3, 120);
-            this.lblConnectionString.Name = "lblConnectionString";
-            this.lblConnectionString.Size = new System.Drawing.Size(106, 13);
-            this.lblConnectionString.TabIndex = 8;
-            this.lblConnectionString.Text = "Строка соединения";
-            // 
-            // lblPassword
-            // 
-            this.lblPassword.AutoSize = true;
-            this.lblPassword.Location = new System.Drawing.Point(239, 81);
-            this.lblPassword.Name = "lblPassword";
-            this.lblPassword.Size = new System.Drawing.Size(45, 13);
-            this.lblPassword.TabIndex = 6;
-            this.lblPassword.Text = "Пароль";
-            // 
-            // txtPassword
-            // 
-            this.txtPassword.Location = new System.Drawing.Point(242, 97);
-            this.txtPassword.Name = "txtPassword";
-            this.txtPassword.Size = new System.Drawing.Size(229, 20);
-            this.txtPassword.TabIndex = 7;
-            this.txtPassword.UseSystemPasswordChar = true;
-            this.txtPassword.TextChanged += new System.EventHandler(this.txtPassword_TextChanged);
-            // 
-            // txtUser
-            // 
-            this.txtUser.Location = new System.Drawing.Point(6, 97);
-            this.txtUser.Name = "txtUser";
-            this.txtUser.Size = new System.Drawing.Size(230, 20);
-            this.txtUser.TabIndex = 5;
-            this.txtUser.TextChanged += new System.EventHandler(this.txtUser_TextChanged);
-            // 
-            // lblUser
-            // 
-            this.lblUser.AutoSize = true;
-            this.lblUser.Location = new System.Drawing.Point(3, 81);
-            this.lblUser.Name = "lblUser";
-            this.lblUser.Size = new System.Drawing.Size(80, 13);
-            this.lblUser.TabIndex = 4;
-            this.lblUser.Text = "Пользователь";
-            // 
-            // txtDatabase
-            // 
-            this.txtDatabase.Location = new System.Drawing.Point(6, 58);
-            this.txtDatabase.Name = "txtDatabase";
-            this.txtDatabase.Size = new System.Drawing.Size(465, 20);
-            this.txtDatabase.TabIndex = 3;
-            this.txtDatabase.TextChanged += new System.EventHandler(this.txtDatabase_TextChanged);
-            // 
-            // lblDatabase
-            // 
-            this.lblDatabase.AutoSize = true;
-            this.lblDatabase.Location = new System.Drawing.Point(3, 42);
-            this.lblDatabase.Name = "lblDatabase";
-            this.lblDatabase.Size = new System.Drawing.Size(72, 13);
-            this.lblDatabase.TabIndex = 2;
-            this.lblDatabase.Text = "База данных";
-            // 
-            // txtServer
-            // 
-            this.txtServer.Location = new System.Drawing.Point(6, 19);
-            this.txtServer.Name = "txtServer";
-            this.txtServer.Size = new System.Drawing.Size(465, 20);
-            this.txtServer.TabIndex = 1;
-            this.txtServer.TextChanged += new System.EventHandler(this.txtServer_TextChanged);
-            // 
-            // lblServer
-            // 
-            this.lblServer.AutoSize = true;
-            this.lblServer.Location = new System.Drawing.Point(3, 3);
-            this.lblServer.Name = "lblServer";
-            this.lblServer.Size = new System.Drawing.Size(44, 13);
-            this.lblServer.TabIndex = 0;
-            this.lblServer.Text = "Сервер";
-            // 
-            // pageExportCurDataQuery
-            // 
-            this.pageExportCurDataQuery.Controls.Add(this.ctrlExportCurDataQuery);
-            this.pageExportCurDataQuery.Location = new System.Drawing.Point(4, 22);
-            this.pageExportCurDataQuery.Name = "pageExportCurDataQuery";
-            this.pageExportCurDataQuery.Padding = new System.Windows.Forms.Padding(3);
-            this.pageExportCurDataQuery.Size = new System.Drawing.Size(477, 367);
-            this.pageExportCurDataQuery.TabIndex = 0;
-            this.pageExportCurDataQuery.Text = "Текущие данные";
-            this.pageExportCurDataQuery.UseVisualStyleBackColor = true;
-            // 
-            // ctrlExportCurDataQuery
-            // 
-            this.ctrlExportCurDataQuery.Export = false;
-            this.ctrlExportCurDataQuery.Location = new System.Drawing.Point(6, 6);
-            this.ctrlExportCurDataQuery.Name = "ctrlExportCurDataQuery";
-            this.ctrlExportCurDataQuery.Query = "";
-            this.ctrlExportCurDataQuery.Size = new System.Drawing.Size(465, 355);
-            this.ctrlExportCurDataQuery.TabIndex = 0;
-            this.ctrlExportCurDataQuery.PropChanged += new System.EventHandler(this.ctrlExportCurDataQuery_PropChanged);
-            // 
-            // pageExportArcDataQuery
-            // 
-            this.pageExportArcDataQuery.Controls.Add(this.ctrlExportArcDataQuery);
-            this.pageExportArcDataQuery.Location = new System.Drawing.Point(4, 22);
-            this.pageExportArcDataQuery.Name = "pageExportArcDataQuery";
-            this.pageExportArcDataQuery.Padding = new System.Windows.Forms.Padding(3);
-            this.pageExportArcDataQuery.Size = new System.Drawing.Size(477, 367);
-            this.pageExportArcDataQuery.TabIndex = 1;
-            this.pageExportArcDataQuery.Text = "Архивные данные";
-            this.pageExportArcDataQuery.UseVisualStyleBackColor = true;
-            // 
-            // ctrlExportArcDataQuery
-            // 
-            this.ctrlExportArcDataQuery.Export = false;
-            this.ctrlExportArcDataQuery.Location = new System.Drawing.Point(6, 6);
-            this.ctrlExportArcDataQuery.Name = "ctrlExportArcDataQuery";
-            this.ctrlExportArcDataQuery.Query = "";
-            this.ctrlExportArcDataQuery.Size = new System.Drawing.Size(465, 355);
-            this.ctrlExportArcDataQuery.TabIndex = 1;
-            this.ctrlExportArcDataQuery.PropChanged += new System.EventHandler(this.ctrlExportArcDataQuery_PropChanged);
-            // 
-            // pageExportEventQuery
-            // 
-            this.pageExportEventQuery.Controls.Add(this.ctrlExportEventQuery);
-            this.pageExportEventQuery.Location = new System.Drawing.Point(4, 22);
-            this.pageExportEventQuery.Name = "pageExportEventQuery";
-            this.pageExportEventQuery.Padding = new System.Windows.Forms.Padding(3);
-            this.pageExportEventQuery.Size = new System.Drawing.Size(477, 367);
-            this.pageExportEventQuery.TabIndex = 2;
-            this.pageExportEventQuery.Text = "События";
-            this.pageExportEventQuery.UseVisualStyleBackColor = true;
-            // 
-            // ctrlExportEventQuery
-            // 
-            this.ctrlExportEventQuery.Export = false;
-            this.ctrlExportEventQuery.Location = new System.Drawing.Point(6, 6);
-            this.ctrlExportEventQuery.Name = "ctrlExportEventQuery";
-            this.ctrlExportEventQuery.Query = "";
-            this.ctrlExportEventQuery.Size = new System.Drawing.Size(465, 355);
-            this.ctrlExportEventQuery.TabIndex = 2;
-            this.ctrlExportEventQuery.PropChanged += new System.EventHandler(this.ctrlExportEventQuery_PropChanged);
-            // 
-            // pageMisc
-            // 
-            this.pageMisc.Controls.Add(this.numMaxQueueSize);
-            this.pageMisc.Controls.Add(this.lblMaxQueueSize);
-            this.pageMisc.Location = new System.Drawing.Point(4, 22);
-            this.pageMisc.Name = "pageMisc";
-            this.pageMisc.Padding = new System.Windows.Forms.Padding(3);
-            this.pageMisc.Size = new System.Drawing.Size(477, 367);
-            this.pageMisc.TabIndex = 4;
-            this.pageMisc.Text = "Разное";
-            this.pageMisc.UseVisualStyleBackColor = true;
-            // 
-            // numMaxQueueSize
-            // 
-            this.numMaxQueueSize.Location = new System.Drawing.Point(6, 19);
-            this.numMaxQueueSize.Maximum = new decimal(new int[] {
-            10000,
-            0,
-            0,
-            0});
-            this.numMaxQueueSize.Minimum = new decimal(new int[] {
-            100,
-            0,
-            0,
-            0});
-            this.numMaxQueueSize.Name = "numMaxQueueSize";
-            this.numMaxQueueSize.Size = new System.Drawing.Size(120, 20);
-            this.numMaxQueueSize.TabIndex = 1;
-            this.numMaxQueueSize.Value = new decimal(new int[] {
-            100,
-            0,
-            0,
-            0});
-            this.numMaxQueueSize.ValueChanged += new System.EventHandler(this.numMaxQueueSize_ValueChanged);
-            // 
-            // lblMaxQueueSize
-            // 
-            this.lblMaxQueueSize.AutoSize = true;
-            this.lblMaxQueueSize.Location = new System.Drawing.Point(3, 3);
-            this.lblMaxQueueSize.Name = "lblMaxQueueSize";
-            this.lblMaxQueueSize.Size = new System.Drawing.Size(122, 13);
-            this.lblMaxQueueSize.TabIndex = 0;
-            this.lblMaxQueueSize.Text = "Макс. размер очереди";
-            // 
-            // toolStrip
-            // 
-            this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.ddbAddDataSource,
-            this.btnDelDataSource,
-            this.sep1,
-            this.btnManualExport});
-            this.toolStrip.Location = new System.Drawing.Point(0, 0);
-            this.toolStrip.Name = "toolStrip";
-            this.toolStrip.Size = new System.Drawing.Size(684, 25);
-            this.toolStrip.TabIndex = 0;
-            this.toolStrip.Text = "toolStrip1";
-            // 
-            // ddbAddDataSource
-            // 
-            this.ddbAddDataSource.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.ddbAddDataSource.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.miAddSqlDataSource,
-            this.miAddOraDataSource,
-            this.miAddPgSqlDataSource,
-            this.miAddMySqlDataSource,
-            this.miAddOleDbDataSource});
-            this.ddbAddDataSource.Image = ((System.Drawing.Image)(resources.GetObject("ddbAddDataSource.Image")));
-            this.ddbAddDataSource.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.ddbAddDataSource.Name = "ddbAddDataSource";
-            this.ddbAddDataSource.Size = new System.Drawing.Size(29, 22);
-            this.ddbAddDataSource.ToolTipText = "Добавить источник данных";
-            // 
-            // miAddSqlDataSource
-            // 
-            this.miAddSqlDataSource.Image = ((System.Drawing.Image)(resources.GetObject("miAddSqlDataSource.Image")));
-            this.miAddSqlDataSource.Name = "miAddSqlDataSource";
-            this.miAddSqlDataSource.Size = new System.Drawing.Size(184, 22);
-            this.miAddSqlDataSource.Text = "Microsoft SQL Server";
-            this.miAddSqlDataSource.Click += new System.EventHandler(this.miAddDataSource_Click);
-            // 
-            // miAddOraDataSource
-            // 
-            this.miAddOraDataSource.Image = ((System.Drawing.Image)(resources.GetObject("miAddOraDataSource.Image")));
-            this.miAddOraDataSource.Name = "miAddOraDataSource";
-            this.miAddOraDataSource.Size = new System.Drawing.Size(184, 22);
-            this.miAddOraDataSource.Text = "Oracle";
-            this.miAddOraDataSource.Click += new System.EventHandler(this.miAddDataSource_Click);
-            // 
-            // miAddPgSqlDataSource
-            // 
-            this.miAddPgSqlDataSource.Image = ((System.Drawing.Image)(resources.GetObject("miAddPgSqlDataSource.Image")));
-            this.miAddPgSqlDataSource.Name = "miAddPgSqlDataSource";
-            this.miAddPgSqlDataSource.Size = new System.Drawing.Size(184, 22);
-            this.miAddPgSqlDataSource.Text = "PostgreSQL";
-            this.miAddPgSqlDataSource.Click += new System.EventHandler(this.miAddDataSource_Click);
-            // 
-            // miAddMySqlDataSource
-            // 
-            this.miAddMySqlDataSource.Image = ((System.Drawing.Image)(resources.GetObject("miAddMySqlDataSource.Image")));
-            this.miAddMySqlDataSource.Name = "miAddMySqlDataSource";
-            this.miAddMySqlDataSource.Size = new System.Drawing.Size(184, 22);
-            this.miAddMySqlDataSource.Text = "MySQL";
-            this.miAddMySqlDataSource.Click += new System.EventHandler(this.miAddDataSource_Click);
-            // 
-            // miAddOleDbDataSource
-            // 
-            this.miAddOleDbDataSource.Image = ((System.Drawing.Image)(resources.GetObject("miAddOleDbDataSource.Image")));
-            this.miAddOleDbDataSource.Name = "miAddOleDbDataSource";
-            this.miAddOleDbDataSource.Size = new System.Drawing.Size(184, 22);
-            this.miAddOleDbDataSource.Text = "OLE DB";
-            this.miAddOleDbDataSource.Click += new System.EventHandler(this.miAddDataSource_Click);
-            // 
-            // btnDelDataSource
-            // 
-            this.btnDelDataSource.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.btnDelDataSource.Image = ((System.Drawing.Image)(resources.GetObject("btnDelDataSource.Image")));
-            this.btnDelDataSource.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.btnDelDataSource.Name = "btnDelDataSource";
-            this.btnDelDataSource.Size = new System.Drawing.Size(23, 22);
-            this.btnDelDataSource.ToolTipText = "Удалить источник данных";
-            this.btnDelDataSource.Click += new System.EventHandler(this.btnDelDataSource_Click);
-            // 
-            // sep1
-            // 
-            this.sep1.Name = "sep1";
-            this.sep1.Size = new System.Drawing.Size(6, 25);
-            // 
-            // btnManualExport
-            // 
-            this.btnManualExport.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
-            this.btnManualExport.Image = ((System.Drawing.Image)(resources.GetObject("btnManualExport.Image")));
-            this.btnManualExport.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.btnManualExport.Name = "btnManualExport";
-            this.btnManualExport.Size = new System.Drawing.Size(23, 22);
-            this.btnManualExport.ToolTipText = "Экспорт в ручном режиме";
-            this.btnManualExport.Click += new System.EventHandler(this.btnManualExport_Click);
-            // 
-            // lblInstruction
-            // 
-            this.lblInstruction.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
-            this.lblInstruction.ForeColor = System.Drawing.SystemColors.GrayText;
-            this.lblInstruction.Location = new System.Drawing.Point(200, 250);
-            this.lblInstruction.Name = "lblInstruction";
-            this.lblInstruction.Size = new System.Drawing.Size(485, 23);
-            this.lblInstruction.TabIndex = 2;
-            this.lblInstruction.Text = "Добавьте источники данных";
-            this.lblInstruction.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
-            // 
-            // FrmDBExportConfig
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.CancelButton = this.btnClose;
-            this.ClientSize = new System.Drawing.Size(684, 462);
-            this.Controls.Add(this.lblInstruction);
-            this.Controls.Add(this.toolStrip);
-            this.Controls.Add(this.tabControl);
-            this.Controls.Add(this.btnClose);
-            this.Controls.Add(this.btnCancel);
-            this.Controls.Add(this.btnSave);
-            this.Controls.Add(this.treeView);
-            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
-            this.MaximizeBox = false;
-            this.MinimizeBox = false;
-            this.Name = "FrmDBExportConfig";
-            this.ShowInTaskbar = false;
-            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
-            this.Text = "Экспорт в БД";
-            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmDBExportConfig_FormClosing);
-            this.Load += new System.EventHandler(this.FrmDBExportConfig_Load);
-            this.tabControl.ResumeLayout(false);
-            this.pageConnection.ResumeLayout(false);
-            this.pageConnection.PerformLayout();
-            this.pageExportCurDataQuery.ResumeLayout(false);
-            this.pageExportArcDataQuery.ResumeLayout(false);
-            this.pageExportEventQuery.ResumeLayout(false);
-            this.pageMisc.ResumeLayout(false);
-            this.pageMisc.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numMaxQueueSize)).EndInit();
-            this.toolStrip.ResumeLayout(false);
-            this.toolStrip.PerformLayout();
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.TreeView treeView;
-        private System.Windows.Forms.Button btnSave;
-        private System.Windows.Forms.Button btnCancel;
-        private System.Windows.Forms.Button btnClose;
-        private System.Windows.Forms.TabControl tabControl;
-        private System.Windows.Forms.TabPage pageExportCurDataQuery;
-        private System.Windows.Forms.TabPage pageExportArcDataQuery;
-        private System.Windows.Forms.TabPage pageExportEventQuery;
-        private System.Windows.Forms.ToolStrip toolStrip;
-        private System.Windows.Forms.ToolStripDropDownButton ddbAddDataSource;
-        private System.Windows.Forms.ToolStripMenuItem miAddSqlDataSource;
-        private System.Windows.Forms.ToolStripButton btnDelDataSource;
-        private System.Windows.Forms.Label lblInstruction;
-        private CtrlExportQuery ctrlExportCurDataQuery;
-        private CtrlExportQuery ctrlExportArcDataQuery;
-        private CtrlExportQuery ctrlExportEventQuery;
-        private System.Windows.Forms.ToolStripMenuItem miAddOraDataSource;
-        private System.Windows.Forms.ToolStripMenuItem miAddPgSqlDataSource;
-        private System.Windows.Forms.ToolStripMenuItem miAddMySqlDataSource;
-        private System.Windows.Forms.ToolStripMenuItem miAddOleDbDataSource;
-        private System.Windows.Forms.TabPage pageConnection;
-        private System.Windows.Forms.TextBox txtServer;
-        private System.Windows.Forms.Label lblServer;
-        private System.Windows.Forms.TextBox txtDatabase;
-        private System.Windows.Forms.Label lblDatabase;
-        private System.Windows.Forms.TextBox txtPassword;
-        private System.Windows.Forms.TextBox txtUser;
-        private System.Windows.Forms.Label lblUser;
-        private System.Windows.Forms.Label lblPassword;
-        private System.Windows.Forms.Label lblConnectionString;
-        private System.Windows.Forms.TextBox txtConnectionString;
-        private System.Windows.Forms.ImageList ilTree;
-        private System.Windows.Forms.ToolStripSeparator sep1;
-        private System.Windows.Forms.ToolStripButton btnManualExport;
-        private System.Windows.Forms.TabPage pageMisc;
-        private System.Windows.Forms.Label lblMaxQueueSize;
-        private System.Windows.Forms.NumericUpDown numMaxQueueSize;
-    }
-}
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.cs
deleted file mode 100644
index 6f590ac0a..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.cs
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * Copyright 2021 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Module configuration form
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2021
- */
-
-using Scada.Client;
-using Scada.UI;
-using System;
-using System.Drawing;
-using System.IO;
-using System.Windows.Forms;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Module configuration form.
-    /// Форма конфигурации КП.
-    /// 
-    internal partial class FrmDBExportConfig : Form
-    {
-        private AppDirs appDirs;       // директории приложения
-        private ServerComm serverComm; // объект для обмена данными со SCADA-Сервером
-
-        private ModConfig config;         // конфигурация модуля
-        private ModConfig configCopy;     // копия конфигурации модуля для реализации отмены изменений
-        private bool modified;         // признак изменения конфигурации
-        private bool changing;         // происходит изменение значений элементов управления
-        private ModConfig.ExportDestination selExpDest; // выбранное назначение экспорта
-        private TreeNode selExpDestNode;             // узел дерева выбранного назначения экспорта
-
-
-        /// 
-        /// Конструктор, ограничивающий создание формы без параметров
-        /// 
-        private FrmDBExportConfig()
-        {
-            InitializeComponent();
-
-            config = null;
-            configCopy = null;
-            modified = false;
-            changing = false;
-            selExpDest = null;
-            selExpDestNode = null;
-        }
-
-
-        /// 
-        /// Получить или установить признак изменения конфигурации
-        /// 
-        private bool Modified
-        {
-            get
-            {
-                return modified;
-            }
-            set
-            {
-                modified = value;
-                btnSave.Enabled = modified;
-                btnCancel.Enabled = modified;
-            }
-        }
-
-
-        /// 
-        /// Отобразить форму модально
-        /// 
-        public static void ShowDialog(AppDirs appDirs, ServerComm serverComm)
-        {
-            FrmDBExportConfig frmDBExportConfig = new FrmDBExportConfig
-            {
-                appDirs = appDirs,
-                serverComm = serverComm
-            };
-            frmDBExportConfig.ShowDialog();
-        }
-
-
-        /// 
-        /// Создать узел дерева, соответствующий назначению экспорта
-        /// 
-        private TreeNode NewExpDestNode(ModConfig.ExportDestination expDest)
-        {
-            TreeNode node = new TreeNode(expDest.DataSource.Name) { Tag = expDest };
-            string imageKey;
-
-            switch (expDest.DataSource.DBType)
-            {
-                case DBType.MSSQL:
-                    imageKey = "mssql.png";
-                    break;
-                case DBType.Oracle:
-                    imageKey = "oracle.png";
-                    break;
-                case DBType.PostgreSQL:
-                    imageKey = "postgresql.png";
-                    break;
-                case DBType.MySQL:
-                    imageKey = "mysql.png";
-                    break;
-                case DBType.OLEDB:
-                    imageKey = "oledb.png";
-                    break;
-                default:
-                    imageKey = "";
-                    break;
-            }
-
-            node.ImageKey = node.SelectedImageKey = imageKey;
-            return node;
-        }
-
-        /// 
-        /// Отобразить конфигурацию
-        /// 
-        private void ConfigToControls()
-        {
-            // обнуление выбранного объекта
-            selExpDest = null;
-            selExpDestNode = null;
-
-            // очистка и заполнение дерева
-            treeView.BeginUpdate();
-            treeView.Nodes.Clear();
-
-            foreach (ModConfig.ExportDestination expDest in config.ExportDestinations)
-                treeView.Nodes.Add(NewExpDestNode(expDest));
-
-            treeView.ExpandAll();
-            treeView.EndUpdate();
-
-            // выбор первого узла дерева
-            if (treeView.Nodes.Count > 0)
-                treeView.SelectedNode = treeView.Nodes[0];
-
-            SetControlsEnabled();
-        }
-
-        /// 
-        /// Отобразить параметры экспорта для выбранного назначения
-        /// 
-        private void ShowSelectedExportParams()
-        {
-            if (selExpDest != null)
-            {
-                changing = true;
-
-                // вывод параметров соединения с БД
-                tabControl.SelectedIndex = 0;
-                DataSource dataSource = selExpDest.DataSource;
-                txtServer.Text = dataSource.Server;
-                txtDatabase.Text = dataSource.Database;
-                txtUser.Text = dataSource.User;
-                txtPassword.Text = dataSource.Password;
-
-                // вывод строки соединения
-                string bldConnStr = dataSource.BuildConnectionString();
-
-                if (!string.IsNullOrEmpty(bldConnStr) && bldConnStr == dataSource.ConnectionString)
-                {
-                    txtConnectionString.Text = dataSource.BuildConnectionString(true);
-                    SetConnControlsBackColor(KnownColor.Window, KnownColor.Control);
-                }
-                else
-                {
-                    txtConnectionString.Text = dataSource.ConnectionString;
-                    SetConnControlsBackColor(KnownColor.Control, KnownColor.Window);
-                }
-
-                // вывод параметров экспорта
-                ModConfig.ExportParams expParams = selExpDest.ExportParams;
-                ctrlExportCurDataQuery.Export = expParams.ExportCurData;
-                ctrlExportCurDataQuery.Query = expParams.ExportCurDataQuery;
-                ctrlExportArcDataQuery.Export = expParams.ExportArcData;
-                ctrlExportArcDataQuery.Query = expParams.ExportArcDataQuery;
-                ctrlExportEventQuery.Export = expParams.ExportEvents;
-                ctrlExportEventQuery.Query = expParams.ExportEventQuery;
-
-                // вывод разных параметров
-                numMaxQueueSize.SetValue(expParams.MaxQueueSize);
-
-                changing = false;
-            }
-        }
-
-        /// 
-        /// Установить цвет фона элементов управления параметров соединения с БД
-        /// 
-        private void SetConnControlsBackColor(KnownColor connParamsColor, KnownColor connStrColor)
-        {
-            txtServer.BackColor = txtDatabase.BackColor = txtUser.BackColor = txtPassword.BackColor = 
-                Color.FromKnownColor(connParamsColor);
-            txtConnectionString.BackColor = Color.FromKnownColor(connStrColor);
-        }
-
-        /// 
-        /// Установить и отобразить автоматически построенную строку соединения
-        /// 
-        private void SetConnectionString()
-        {
-            if (selExpDest != null)
-            {
-                string bldConnStr = selExpDest.DataSource.BuildConnectionString();
-
-                if (!string.IsNullOrEmpty(bldConnStr))
-                {
-                    selExpDest.DataSource.ConnectionString = bldConnStr;
-                    changing = true;
-                    txtConnectionString.Text = selExpDest.DataSource.BuildConnectionString(true);
-                    changing = false;
-                    SetConnControlsBackColor(KnownColor.Window, KnownColor.Control);
-                }
-            }
-        }
-
-        /// 
-        /// Установить доступность и видимость кнопок и параметров экспорта
-        /// 
-        private void SetControlsEnabled()
-        {
-            if (selExpDest == null) // конфигурация пуста
-            {
-                btnDelDataSource.Enabled = false;
-                btnManualExport.Enabled = false;
-                lblInstruction.Visible = true;
-                tabControl.Visible = false;
-            }
-            else
-            {
-                btnDelDataSource.Enabled = true;
-                btnManualExport.Enabled = true;
-                lblInstruction.Visible = false;
-                tabControl.Visible = true;
-            }
-        }
-
-        /// 
-        /// Сохранить конфигурацию модуля
-        /// 
-        private bool SaveConfig()
-        {
-            if (Modified)
-            {
-                if (config.Save(out string errMsg))
-                {
-                    Modified = false;
-                    return true;
-                }
-                else
-                {
-                    ScadaUiUtils.ShowError(errMsg);
-                    return false;
-                }
-            }
-            else
-            {
-                return true;
-            }
-        }
-
-
-        private void FrmDBExportConfig_Load(object sender, EventArgs e)
-        {
-            // локализация модуля
-            string errMsg;
-            if (!Localization.UseRussian)
-            {
-                if (Localization.LoadDictionaries(appDirs.LangDir, "ModDBExport", out errMsg))
-                    Translator.TranslateForm(this, "Scada.Server.Modules.DBExport.FrmDBExportConfig");
-                else
-                    ScadaUiUtils.ShowError(errMsg);
-            }
-
-            // настройка элементов управления
-            lblInstruction.Top = treeView.Top;
-
-            // загрузка конфигурации
-            config = new ModConfig(appDirs.ConfigDir);
-            if (File.Exists(config.FileName) && !config.Load(out errMsg))
-                ScadaUiUtils.ShowError(errMsg);
-
-            // создание копии конфигурации
-            configCopy = config.Clone();
-
-            // отображение конфигурации
-            ConfigToControls();
-
-            // снятие признака изменения конфигурации
-            Modified = false;
-        }
-
-        private void FrmDBExportConfig_FormClosing(object sender, FormClosingEventArgs e)
-        {
-            if (Modified)
-            {
-                DialogResult result = MessageBox.Show(ModPhrases.SaveModSettingsConfirm,
-                    CommonPhrases.QuestionCaption, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
-
-                switch (result)
-                {
-                    case DialogResult.Yes:
-                        if (!SaveConfig())
-                            e.Cancel = true;
-                        break;
-                    case DialogResult.No:
-                        break;
-                    default:
-                        e.Cancel = true;
-                        break;
-                }
-            }
-        }
-
-
-        private void treeView_AfterSelect(object sender, TreeViewEventArgs e)
-        {
-            // определение и отображение свойств выбранного объекта
-            TreeNode selNode = e.Node;
-            selExpDest = selNode.Tag as ModConfig.ExportDestination;
-            selExpDestNode = selExpDest == null ? null : selNode;
-            ShowSelectedExportParams();
-        }
-
-        private void miAddDataSource_Click(object sender, EventArgs e)
-        {
-            // добавление назначения экспорта
-            DataSource dataSource = null;
-
-            if (sender == miAddSqlDataSource)
-                dataSource = new SqlDataSource();
-            else if (sender == miAddOraDataSource)
-                dataSource = new OraDataSource();
-            else if (sender == miAddPgSqlDataSource)
-                dataSource = new PgSqlDataSource();
-            else if (sender == miAddMySqlDataSource)
-                dataSource = new MySqlDataSource();
-            else if (sender == miAddOleDbDataSource)
-                dataSource = new OleDbDataSource();
-
-            if (dataSource != null)
-            {
-                ModConfig.ExportDestination expDest = new ModConfig.ExportDestination(dataSource, new ModConfig.ExportParams());
-                TreeNode treeNode = NewExpDestNode(expDest);
-
-                int ind = config.ExportDestinations.BinarySearch(expDest);
-                if (ind >= 0)
-                    ind++;
-                else
-                    ind = ~ind;
-
-                config.ExportDestinations.Insert(ind, expDest);
-                treeView.Nodes.Insert(ind, treeNode);
-                treeView.SelectedNode = treeNode;
-
-                SetConnectionString();
-                SetControlsEnabled();
-                Modified = true;
-            }
-        }
-
-        private void btnDelDataSource_Click(object sender, EventArgs e)
-        {
-            // удаление назначения экспорта
-            if (selExpDestNode != null)
-            {
-                TreeNode prevNode = selExpDestNode.PrevNode;
-                TreeNode nextNode = selExpDestNode.NextNode;
-
-                int ind = selExpDestNode.Index;
-                config.ExportDestinations.RemoveAt(ind);
-                treeView.Nodes.RemoveAt(ind);
-
-                treeView.SelectedNode = nextNode == null ? prevNode : nextNode;
-                if (treeView.SelectedNode == null)
-                {
-                    selExpDest = null;
-                    selExpDestNode = null;
-                }
-
-                SetControlsEnabled();
-                Modified = true;
-            }
-        }
-
-        private void btnManualExport_Click(object sender, EventArgs e)
-        {
-            // отображение формы экспорта в ручном режиме
-            int curDataCtrlCnlNum = config.CurDataCtrlCnlNum;
-            int arcDataCtrlCnlNum = config.ArcDataCtrlCnlNum;
-            int eventsCtrlCnlNum = config.EventsCtrlCnlNum;
-            
-            if (FrmManualExport.ShowDialog(serverComm, config.ExportDestinations, selExpDest, 
-                ref curDataCtrlCnlNum, ref arcDataCtrlCnlNum, ref eventsCtrlCnlNum) &&
-                (config.CurDataCtrlCnlNum != curDataCtrlCnlNum || 
-                config.ArcDataCtrlCnlNum != arcDataCtrlCnlNum ||
-                config.EventsCtrlCnlNum != eventsCtrlCnlNum))
-            {
-                // установка изменившихся номеров каналов управления
-                config.CurDataCtrlCnlNum = curDataCtrlCnlNum;
-                config.ArcDataCtrlCnlNum = arcDataCtrlCnlNum;
-                config.EventsCtrlCnlNum = eventsCtrlCnlNum;
-                Modified = true;
-            }
-        }
-
-
-        private void txtServer_TextChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null && selExpDestNode != null)
-            {
-                selExpDest.DataSource.Server = txtServer.Text;
-                selExpDestNode.Text = selExpDest.DataSource.Name;
-                SetConnectionString();
-                Modified = true;
-            }
-        }
-
-        private void txtDatabase_TextChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.DataSource.Database = txtDatabase.Text;
-                SetConnectionString();
-                Modified = true;
-            }
-        }
-
-        private void txtUser_TextChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.DataSource.User = txtUser.Text;
-                SetConnectionString();
-                Modified = true;
-            }
-        }
-
-        private void txtPassword_TextChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.DataSource.Password = txtPassword.Text;
-                SetConnectionString();
-                Modified = true;
-            }
-        }
-
-        private void txtConnectionString_TextChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.DataSource.ConnectionString = txtConnectionString.Text;
-                SetConnControlsBackColor(KnownColor.Control, KnownColor.Window);
-                Modified = true;
-            }
-        }
-
-        private void ctrlExportCurDataQuery_PropChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.ExportParams.ExportCurData = ctrlExportCurDataQuery.Export;
-                selExpDest.ExportParams.ExportCurDataQuery = ctrlExportCurDataQuery.Query;
-                Modified = true;
-            }
-        }
-
-        private void ctrlExportArcDataQuery_PropChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.ExportParams.ExportArcData = ctrlExportArcDataQuery.Export;
-                selExpDest.ExportParams.ExportArcDataQuery = ctrlExportArcDataQuery.Query;
-                Modified = true;
-            }
-        }
-
-        private void ctrlExportEventQuery_PropChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.ExportParams.ExportEvents = ctrlExportEventQuery.Export;
-                selExpDest.ExportParams.ExportEventQuery = ctrlExportEventQuery.Query;
-                Modified = true;
-            }
-        }
-
-
-        private void numMaxQueueSize_ValueChanged(object sender, EventArgs e)
-        {
-            if (!changing && selExpDest != null)
-            {
-                selExpDest.ExportParams.MaxQueueSize = Convert.ToInt32(numMaxQueueSize.Value);
-                Modified = true;
-            }
-        }
-
-
-        private void btnSave_Click(object sender, EventArgs e)
-        {
-            // сохранение конфигурации модуля
-            SaveConfig();
-        }
-
-        private void btnCancel_Click(object sender, EventArgs e)
-        {
-            // отмена изменений конфигурации
-            config = configCopy;
-            configCopy = config.Clone();
-            ConfigToControls();
-            Modified = false;
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.resx b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.resx
deleted file mode 100644
index ea7a691fb..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmDBExportConfig.resx
+++ /dev/null
@@ -1,287 +0,0 @@
-
-
-  
-  
-    
-    
-      
-        
-          
-            
-              
-                
-              
-              
-              
-              
-              
-            
-          
-          
-            
-              
-              
-            
-          
-          
-            
-              
-                
-                
-              
-              
-              
-              
-              
-            
-          
-          
-            
-              
-                
-              
-              
-            
-          
-        
-      
-    
-  
-  
-    text/microsoft-resx
-  
-  
-    2.0
-  
-  
-    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-  
-  
-    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-  
-  
-    115, 17
-  
-  
-    
-        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
-        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
-        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADc
-        CwAAAk1TRnQBSQFMAgEBBQEAAXgBAAF4AQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
-        AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
-        AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
-        AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
-        AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
-        AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM
-        AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA
-        ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz
-        AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ
-        AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM
-        AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA
-        AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA
-        AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ
-        AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/
-        AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA
-        AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm
-        ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ
-        Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz
-        AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA
-        AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM
-        AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM
-        ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM
-        Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA
-        AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM
-        AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ
-        AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
-        AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
-        AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
-        AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/4QAAfQBmQJzA0sBHAH0
-        NwABHAF5AZoBoAF6AVkCMQFzNwABcwFZAqABegFZATIBMQFLNwABcwFZAZoBoAF6AVkBMgExAUs3AAF0
-        AVkBmgGgAXoBWQEyATEBSzcAAXQBWQGaAaABegFZATIBMQFLNwABdAFZAZoBoAF6AVkBMgExAUs3AAF0
-        AVkBmgGgAXoBWQEyATEBSzcAAXQBWQGaAaABegFZATIBMQFLNwABdAF6A6ABmgF6AVkBSzcAARwBmgXD
-        AZoBczcAAfMBmQF0ARwCcwF0AZkBG8UAD/EIAAG8AYsBrgHyBAAB8w6LAfMH0wEABzgBAA8gAfEHAAH/
-        AZECiwGRAfQDAAGRDmwBkQfTAQAHOAEAASAF+QkgAfEHAAH/AZEDiwH0AwABiwRsAbsBkQFsAa4GbAGL
-        B9MBAAc4AQABIAf5ByAB8QUAAf8C9AGRA4sB9AMAAYsDbAKRAbsBkQZsAbwBiwfTAQAHOAEAASAE+QUX
-        AfkEIAHxAgAB9AHwAfQB8QH3AQcBrgOLAfMB9AH/AQABiwNsAbUBiwH3AYsFbAH3AbUBiwfTAQAHOAEA
-        ASAC+QGUB/8BlAH5AiAB8QEAAfQBtQGLAbwB9AHyAfcBrgOLAQcBkgG8AfQEiwG1CIsB8AKLB9MBAAc4
-        AQABIAH5Ab0B/wG9BRYBvQH/Ab0CIAHxAf8B8AOLAbwB9wG7BIsB9wHzAgAEiwKRBosBtAG1AosH0wEA
-        BzgBAAEgARcB/wG9B/kBvQH/ARcBIAHxAfQBtQKLAbUCiwG7BIsCBwH/AQAFiwG7BosB8AOLEAABIAEW
-        Af8BFwf5ARcB/wEWASAB8QH0AZECiwG7AosBtAOLAZEBrgG1AfIBAASLAbsGiwG7AbUDiwdHAQAHNQEA
-        ASABFgH/ARcH+QEXAf8BFgEgAfEB8wOLAbUCiwGRA4sBuwGLAbQBkQH/A4sBkQG7BYsBtAEJBIsHRwEA
-        BzUBAAEgARcB/wG9B/kBvQH/ARcBIAHxAbwDiwG7AWwBkQG7A4sBuwGRAbUBiwH0AZACiwG7AZABiwG0
-        AosBtQEJBIsBkAdHAQAHNQEAASAB+QG9Af8BvQUWAb0B/wG9AfkBIAHxAe8DiwG1ArsBtAOLAbUCuwGL
-        AfABswGLAZEBuwOLAZEBCQG7BYsBswdHAQAHNQEAASAC+QGUB/8BlAL5ASAB8QG1A4sBkQGuBosCkQGL
-        AbsBswGLAQkBiwG0AwkBkQaLAbMHRwEABzUBAAEgBPkFFwT5ASAC8QSLAbsGiwG1AosBvAGzAYsDCQGQ
-        CYsBswdHAQAHNQEAASAN+QEgAfEB9AG1A4sC9wOLAZEBuwKLAbsB/wG0AZAMiwGQAbQHRwEABzUBAA8g
-        AgAB/wLzAfQC/wLzAvQCBwHzAf8BAAH0AbQMswG0AfQBQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEA
-        AQEGAAEBFgAD/wEAAv8GAAL/BgAB4AEPBgAB4AEPBgAB4AEPBgAB4AEPBgAB4AEPBgAB4AEPBgAB4AEP
-        BgAB4AEPBgAB4AEPBgAB4AEPBgAB4AEPBgAB4AEPBgAC/wYAAv8GAAL/AYABAAH/AQ8CAAIBAgAB/gEH
-        AgACAQIAAf4BBwIAAgECAAH4AQcCAAIBAgABwAEBAgACAQIAAYADAAIBAwABAwIAAgEDAAEBAgAC/wMA
-        AQECAAIBBgACAQYAAgEGAAIBBgACAQYAAgEGAAIBAQABAQGAAQECAAs=
-
-  
-  
-    17, 17
-  
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAGJJREFUOE/t
-        zLENgEAMQ1FPwkisxDK3BCxFSZkzltw51TUUWPpV9IJn36oL3HGhut77/+ATD9Y37mrj6kR1yUfouASd
-        fISOS9DJR+i4BJ18hI5L0MlH6LgEnXyEjkvQya8NmE2e5IPy3OAlAAAAAElFTkSuQmCC
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m
-        dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFFSURBVDhPnZJZTsNAEESt7OtHjpQD5CNHyklyFraw
-        YwirQBAQAiEQCAQiIJamnu2xHFtAYKQnW9Nd1TM97e0VCjYNuxE7YjvCYxG0ZvPPbIUGnaxBq2XWbmdh
-        P5G3mc+nDEjo9+3HRVx5H42G+RkD3w+TRiOzXi8L+yzlvcpgY8Kg242D6aPCJ1/2XRHlr00YUCEKpMUc
-        911QNS6k/NXfDKiK+E281Ov2LJIGK86At40D0RWSVccSPiFOXWHJGTAYQVUXnKKJ5+WyLToDJiowoMKU
-        z3hSKtkglwsNhjJI3jUw+maQTiU8FofFos07A0YyedeHWs3uqlW7EVeVil3ouGeCqkcSHgj6NucMGEk6
-        /CjhvbiV8FrCS8Fdk1X3JaRnQ2lmnQEjyVStC4aD51kWdJlGDcSCkjkyVQHxjAgMosXPP/A6X4CZKcoz
-        oWSPAAAAAElFTkSuQmCC
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAyBJREFUOE+N
-        U0lPk1EU/Vau3Jm4cuUPsLSlFUgM0UQlmpi4UYzR0BGIkahB3QgOpUjnr5PFCYMD2spQgWIdiqCtIDHi
-        FGMVJ1RIS+knpa2fVHq8baobF3qSu3n3nnPvO/c9JoeFhYXln6JxNvxpyvR1Jr4//SMjSX/nV0xMzTie
-        T0yavnBz9ZG5pOrqwFD42q0HkfdT0ePZbHZZnjyXSFaa3T6+pEYHsVyDUnkTbJf7Micvd8ek1c0QyjQo
-        UWqxx9wOx80QipUalKm1sHb4I3wmI2LuPw0/Kqk6BrGCzUd57Uk4+4cgqdJCrDRRGCFSUU5lweZ9elg7
-        70Aib4ZEpkNXIDTOOHsGIVLaqSBXqEe9qxuVDa1YJWuBVEECRBSrDBAqHRQmHGTbIWvpyIs7ugcnmTNd
-        AQjVLJFtKFJbwPYMw+a9h7P+IBra+lCkNFMDC4UBze7buHpvBK7+UQjlLHpCzwKMLzg2LpbnutsgUJnB
-        9gaxvvYoDrquw9EXQLHCSGHHGvLI1XsXVVobtO4AXaMFHyOxRubd1MwZqUJHZCuKaFxj5xBK1XqIFGYc
-        dnZirUoHIXlQqjgBuy+Iiv0mHGnvR63+fGoxm13BcPMp2a5j5/4I2L1BSGkTxQoDGs/fQBmNLiSPihVW
-        1J3yYPuhFlg9fgyPhz35NXLct0pTh5/ILHUyw0jjbdirw2pyutV3HwK5mQwzUN6JshoL3IMjuBUc45Np
-        XpQXALB07OXrx6XKZjKRxcY6PQZGn8U0Z92c0+uHhFYrzRtpJ58ssHh8+Pj5sytP/o1EMlXR1NbLiciY
-        K/7QUHwuUf5i4kPYcKUL2w61QkzbEVTTJJS/dnsEjeyFhHfgzsNILL65IMEw0fj8Tu/gWN9snNvy5NWb
-        x8Z2D98fHOV3NbTRmh1YVWMgI/WY+Br1fPv+c2tmcXFlgfo3Uum0KBbnqr9MT9ftPn4JArWdJjCgvIZF
-        lEs2Fsr+jTTPC2RNF8lAU15g04HTmE3MVxbS/wb9uCX1tkt87k3kXqtMcw7JVHpdIf1/8D96OlmxR48d
-        R04h9OJtV+G4AIb5BfNMGC+05AnKAAAAAElFTkSuQmCC
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAgZJREFUOE+V
-        0O1PUlEAx/HztxQrimbajAXaKk3qhb5oDZ2tdtvdLNu0LB600OCG+XAjcVDdlaaQEe4mPjCBjWHSVrCK
-        tVGvjLL14N/xi3M2zrirVr74bPf8zv2+OaTl7otmy0T2+wl/FttBG9qSFl9m87AnhgZXpOwZzDci/4U2
-        tCXH5TRMA0+QKn5D+uMPqPkSWm+rbPsX2pLmsSQOOWax9LaExuthiIE4Vt9/ZdTcBtrlGLv/E9qSY8Nx
-        HLRNo1NewONMkX03ucIwO2dgHX+OlcJnBBMFGO3T7K4abckRaRH1fQqjpApoleZwcigEd2Sd71I0i5V3
-        JZjsj/hG0ZY03lRR1xtkTnnnEIjn+bmabSqJ5TefNBttSUP5RWsv+bnoyw8w993TbBWB5RxG59f5mbbE
-        5Ayh5oLMtbmmoKzmNVtFbbcPrzd+wnR5kp1pS4zlxzCII9z5saewKUuardrgbAL+WJZ905bUX1GgFyRu
-        NJpG07VJzVZtn+hFvrSFA10joC2p6wli99khzqdmcLT3DqRwAm39Ac1dhTechDyfBm3J/u4J6DoHuIty
-        CD3+CGZSOTjuq5q7CsO5QawVv4C2pKZrHDutdm5XhxOLr4pwPVyAUXTjjPuB5p7/1+4AbYlBHN7UdfRj
-        x+mrf6Wz2n7fyg1tiV7wWPYI0tZe4Ra2gzZ6wWP5BaRQUOILyN2AAAAAAElFTkSuQmCC
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAYFJREFUOE9j
-        GFzg8pGO5FPbG67tWl32f/Pigv/r5+b8Xzc7+/+WRfn/ty8punlgbVk+VCl2cHRzw//X92b///vzKAZ+
-        dX/B/0UT0/5DlWIHB1Zm//91Jez/rzdz/v96v/r/j7fL/v94PuX/t5uF/1/utfk/vcYZvwF7FsX//37O
-        /f+Xx93/v71e+P/Ttbz/77bL/3+xnPH/rTnM/ycVGOI3YNe8uP8/L/gCDeiFGHA9H8WA/nwT/AZsnx0D
-        NMD//1eYATeL/r/bqQI3oDfXCL8BW2dG/v99EWjAkz6oCwpQDOjKNsBvwIap4f9/XfL7/+UJzAuoBnRk
-        6OM3YN3EEKABPv+/QQ34DDTgPZIBbak6+A1Y1R/8//913/+/Xk0AG/AFGH2f9iAMaEnWwm/ArHrXCxc3
-        BP5/cbUFbMD/J8X/P+9T+X9vPvP/fd0i/xvjtW9ClWIHO6a4ai9odV83qz38zbTm2P+9ZV7/e3JN/vdm
-        qn3oSFXb3JWqaA5VOmgAAwMAVhwzMyFCpNwAAAAASUVORK5CYII=
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGWSURBVDhPtZBLS1tRFIXzGxyoxFaR0lqfSRqjRpsqgmLw
-        lSKtGXXWuRQfUdGB2EEw15vEiOIblTZGrJpCC1WpYhAp/hgNXpOrF76eVCGOJLfggsXmHDjfPmsZHk3u
-        s3rcfxx0xWpxHdZwd525uk/fsKtFhDfo2KvWD+iK1RG92WRbW8H585V+gOuoht2bCFvaMs1Rs35A276N
-        qIgQ1uZo+mZ6GOAWed+fvObtsR3XbzsdBzY+nnWyo4WJCMCHIycNX4qpW31B1eIzbPOFVM4WpKHvYg6R
-        NSwefP1XWsqpc8pr19OsqAHWr4OsibmclFhK+LCE8tMA16GdJVVmVh1nJvn5dqpjhNRR4WECCQ9yoh+f
-        0ous9CFd9VIRyEsD2n5Zcf6w0CLKatwqo3GzhPb9KiRlAK/SQ+t3K6bQE8xTeZT7jZTLuZRKOQ/34lgt
-        wnfZjzf+CfP0vW2ZyrZQSEDxIMX7xHeN+gHWuXz88UHkCw8lk9n6AZbQU4LnI/jPh3g58R8AU9BIsSiq
-        1JfNc2+WfkBmMhj+Ar4W9nayuroPAAAAAElFTkSuQmCC
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAH1SURBVDhPrZM/aBNRHMefVqWXtvfnXZM20HpprEWjBpN7
-        LxcVTK3QwdZBQgeXDhkUF3F2d3KSDi7i6CJYuohgwV2Qam0QLAgiCNdJTOzgu/v9fO/yOqSxtKAfuOH9
-        vt/73fv9OfJfQG6dj31nFSruDBJyWIcPBi6QPvCd23BrDsPFqwI4vaFiWu4Ca+QIMisvPXd1qBMERhsx
-        py+hMYthoxTJ8/3dSbDm9asbhoszImb2Ex3uAOXhLFRoNUlSZwg3L2HMnRUojgwkenXMiGsTK2HdE9Lz
-        EAvpweTF3WCBHJNfvxfOekIlkuZnENhFmWxJJ11C37G0/e/IJh6CgJ6OynQtKWk++7t9rdiSTX6hbqJt
-        +4O+Ox3WcwKun0NRpl+galIt7Q8GVi7idH2LU9gu2dgqmSh857OW90btAJRsT/hWc6swGn0/M7QK3GWq
-        ueFZE4Hbd1SJ2t4L8vRoFGTW2ldy2JxMbb4e6ZtWk1BPzOjj954h1vMG0/Zu1JzjauZ568JA+9248fPt
-        caOuJb0D1Pw2ldps5vtfLTtkvKehULHntoMMfsgb+HEitbyzAzt0yktPvhk7+mvjpFHpWnk1fznjB19P
-        DeLGCeMT8OGpLoNGbeePovkUmMt7dLmN5Zg5j2SjLsNFd2ivZiX/g59N6eO/QsgfmHjRslRz8ZoAAAAA
-        SUVORK5CYII=
-
-  
-  
-    
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADDSURBVDhPY6ApcCu+ZAxlkg7U/eZIlc158d+j+EIEVIh4
-        ANM8b9/f/4Zhi/4bxqz3hUoRBsia8+f++O+Ud+S/VsAC4gxB1ty67t//yJ5P/z3KLv63z9r/X8NvLmFD
-        QJqLZz79D6JrV/z/Hzf5z3//+nv/NUNW/1f1nftfxXPaf6hS/ABkAMgFMAPU/RcRpxEGQAZM3v73f+68
-        v2ADVL1nkW4AKBwqlg6kAcsO/6bcAFAUgrCy+yTSDQBpQsZQqUEHGBgAfMqv+q0Q2acAAAAASUVORK5C
-        YII=
-
-  
-
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.Designer.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.Designer.cs
deleted file mode 100644
index 7ac132fd8..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.Designer.cs
+++ /dev/null
@@ -1,360 +0,0 @@
-namespace Scada.Server.Modules.DBExport
-{
-    partial class FrmManualExport
-    {
-        /// 
-        /// Required designer variable.
-        /// 
-        private System.ComponentModel.IContainer components = null;
-
-        /// 
-        /// Clean up any resources being used.
-        /// 
-        /// true if managed resources should be disposed; otherwise, false.
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Windows Form Designer generated code
-
-        /// 
-        /// Required method for Designer support - do not modify
-        /// the contents of this method with the code editor.
-        /// 
-        private void InitializeComponent()
-        {
-            this.cbDataSource = new System.Windows.Forms.ComboBox();
-            this.lblDataSource = new System.Windows.Forms.Label();
-            this.gbCurData = new System.Windows.Forms.GroupBox();
-            this.numCurDataCtrlCnlNum = new System.Windows.Forms.NumericUpDown();
-            this.lblCurDataCtrlCnlNum = new System.Windows.Forms.Label();
-            this.btnExportCurData = new System.Windows.Forms.Button();
-            this.gbArcData = new System.Windows.Forms.GroupBox();
-            this.lblArcDataDateTime = new System.Windows.Forms.Label();
-            this.dtpArcDataTime = new System.Windows.Forms.DateTimePicker();
-            this.dtpArcDataDate = new System.Windows.Forms.DateTimePicker();
-            this.numArcDataCtrlCnlNum = new System.Windows.Forms.NumericUpDown();
-            this.lblArcDataCtrlCnlNum = new System.Windows.Forms.Label();
-            this.btnExportArcData = new System.Windows.Forms.Button();
-            this.gbEvents = new System.Windows.Forms.GroupBox();
-            this.lblEventsDate = new System.Windows.Forms.Label();
-            this.dtpEventsDate = new System.Windows.Forms.DateTimePicker();
-            this.numEventsCtrlCnlNum = new System.Windows.Forms.NumericUpDown();
-            this.lblEventsCtrlCnlNum = new System.Windows.Forms.Label();
-            this.btnExportEvents = new System.Windows.Forms.Button();
-            this.btnCancel = new System.Windows.Forms.Button();
-            this.btnOK = new System.Windows.Forms.Button();
-            this.gbCurData.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numCurDataCtrlCnlNum)).BeginInit();
-            this.gbArcData.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numArcDataCtrlCnlNum)).BeginInit();
-            this.gbEvents.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numEventsCtrlCnlNum)).BeginInit();
-            this.SuspendLayout();
-            // 
-            // cbDataSource
-            // 
-            this.cbDataSource.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-            this.cbDataSource.FormattingEnabled = true;
-            this.cbDataSource.Location = new System.Drawing.Point(12, 25);
-            this.cbDataSource.Name = "cbDataSource";
-            this.cbDataSource.Size = new System.Drawing.Size(374, 21);
-            this.cbDataSource.TabIndex = 1;
-            // 
-            // lblDataSource
-            // 
-            this.lblDataSource.AutoSize = true;
-            this.lblDataSource.Location = new System.Drawing.Point(9, 9);
-            this.lblDataSource.Name = "lblDataSource";
-            this.lblDataSource.Size = new System.Drawing.Size(95, 13);
-            this.lblDataSource.TabIndex = 0;
-            this.lblDataSource.Text = "Источник данных";
-            // 
-            // gbCurData
-            // 
-            this.gbCurData.Controls.Add(this.numCurDataCtrlCnlNum);
-            this.gbCurData.Controls.Add(this.lblCurDataCtrlCnlNum);
-            this.gbCurData.Controls.Add(this.btnExportCurData);
-            this.gbCurData.Location = new System.Drawing.Point(12, 52);
-            this.gbCurData.Name = "gbCurData";
-            this.gbCurData.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
-            this.gbCurData.Size = new System.Drawing.Size(374, 67);
-            this.gbCurData.TabIndex = 2;
-            this.gbCurData.TabStop = false;
-            this.gbCurData.Text = "Текущие данные";
-            // 
-            // numCurDataCtrlCnlNum
-            // 
-            this.numCurDataCtrlCnlNum.Location = new System.Drawing.Point(13, 32);
-            this.numCurDataCtrlCnlNum.Maximum = new decimal(new int[] {
-            65535,
-            0,
-            0,
-            0});
-            this.numCurDataCtrlCnlNum.Name = "numCurDataCtrlCnlNum";
-            this.numCurDataCtrlCnlNum.Size = new System.Drawing.Size(70, 20);
-            this.numCurDataCtrlCnlNum.TabIndex = 1;
-            this.numCurDataCtrlCnlNum.Value = new decimal(new int[] {
-            1,
-            0,
-            0,
-            0});
-            this.numCurDataCtrlCnlNum.ValueChanged += new System.EventHandler(this.numCurDataCtrlCnlNum_ValueChanged);
-            // 
-            // lblCurDataCtrlCnlNum
-            // 
-            this.lblCurDataCtrlCnlNum.AutoSize = true;
-            this.lblCurDataCtrlCnlNum.Location = new System.Drawing.Point(10, 16);
-            this.lblCurDataCtrlCnlNum.Name = "lblCurDataCtrlCnlNum";
-            this.lblCurDataCtrlCnlNum.Size = new System.Drawing.Size(61, 13);
-            this.lblCurDataCtrlCnlNum.TabIndex = 0;
-            this.lblCurDataCtrlCnlNum.Text = "Канал упр.";
-            // 
-            // btnExportCurData
-            // 
-            this.btnExportCurData.Location = new System.Drawing.Point(89, 31);
-            this.btnExportCurData.Name = "btnExportCurData";
-            this.btnExportCurData.Size = new System.Drawing.Size(75, 23);
-            this.btnExportCurData.TabIndex = 2;
-            this.btnExportCurData.Text = "Экспорт";
-            this.btnExportCurData.UseVisualStyleBackColor = true;
-            this.btnExportCurData.Click += new System.EventHandler(this.btnExport_Click);
-            // 
-            // gbArcData
-            // 
-            this.gbArcData.Controls.Add(this.lblArcDataDateTime);
-            this.gbArcData.Controls.Add(this.dtpArcDataTime);
-            this.gbArcData.Controls.Add(this.dtpArcDataDate);
-            this.gbArcData.Controls.Add(this.numArcDataCtrlCnlNum);
-            this.gbArcData.Controls.Add(this.lblArcDataCtrlCnlNum);
-            this.gbArcData.Controls.Add(this.btnExportArcData);
-            this.gbArcData.Location = new System.Drawing.Point(12, 125);
-            this.gbArcData.Name = "gbArcData";
-            this.gbArcData.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
-            this.gbArcData.Size = new System.Drawing.Size(374, 67);
-            this.gbArcData.TabIndex = 3;
-            this.gbArcData.TabStop = false;
-            this.gbArcData.Text = "Архивные данные";
-            // 
-            // lblArcDataDateTime
-            // 
-            this.lblArcDataDateTime.AutoSize = true;
-            this.lblArcDataDateTime.Location = new System.Drawing.Point(86, 16);
-            this.lblArcDataDateTime.Name = "lblArcDataDateTime";
-            this.lblArcDataDateTime.Size = new System.Drawing.Size(77, 13);
-            this.lblArcDataDateTime.TabIndex = 2;
-            this.lblArcDataDateTime.Text = "Дата и время";
-            // 
-            // dtpArcDataTime
-            // 
-            this.dtpArcDataTime.CustomFormat = "";
-            this.dtpArcDataTime.Format = System.Windows.Forms.DateTimePickerFormat.Time;
-            this.dtpArcDataTime.Location = new System.Drawing.Point(195, 32);
-            this.dtpArcDataTime.Name = "dtpArcDataTime";
-            this.dtpArcDataTime.ShowUpDown = true;
-            this.dtpArcDataTime.Size = new System.Drawing.Size(85, 20);
-            this.dtpArcDataTime.TabIndex = 4;
-            // 
-            // dtpArcDataDate
-            // 
-            this.dtpArcDataDate.CustomFormat = "";
-            this.dtpArcDataDate.Format = System.Windows.Forms.DateTimePickerFormat.Short;
-            this.dtpArcDataDate.Location = new System.Drawing.Point(89, 32);
-            this.dtpArcDataDate.Name = "dtpArcDataDate";
-            this.dtpArcDataDate.Size = new System.Drawing.Size(100, 20);
-            this.dtpArcDataDate.TabIndex = 3;
-            // 
-            // numArcDataCtrlCnlNum
-            // 
-            this.numArcDataCtrlCnlNum.Location = new System.Drawing.Point(13, 32);
-            this.numArcDataCtrlCnlNum.Maximum = new decimal(new int[] {
-            65535,
-            0,
-            0,
-            0});
-            this.numArcDataCtrlCnlNum.Name = "numArcDataCtrlCnlNum";
-            this.numArcDataCtrlCnlNum.Size = new System.Drawing.Size(70, 20);
-            this.numArcDataCtrlCnlNum.TabIndex = 1;
-            this.numArcDataCtrlCnlNum.Value = new decimal(new int[] {
-            2,
-            0,
-            0,
-            0});
-            this.numArcDataCtrlCnlNum.ValueChanged += new System.EventHandler(this.numArcDataCtrlCnlNum_ValueChanged);
-            // 
-            // lblArcDataCtrlCnlNum
-            // 
-            this.lblArcDataCtrlCnlNum.AutoSize = true;
-            this.lblArcDataCtrlCnlNum.Location = new System.Drawing.Point(10, 16);
-            this.lblArcDataCtrlCnlNum.Name = "lblArcDataCtrlCnlNum";
-            this.lblArcDataCtrlCnlNum.Size = new System.Drawing.Size(61, 13);
-            this.lblArcDataCtrlCnlNum.TabIndex = 0;
-            this.lblArcDataCtrlCnlNum.Text = "Канал упр.";
-            // 
-            // btnExportArcData
-            // 
-            this.btnExportArcData.Location = new System.Drawing.Point(286, 31);
-            this.btnExportArcData.Name = "btnExportArcData";
-            this.btnExportArcData.Size = new System.Drawing.Size(75, 23);
-            this.btnExportArcData.TabIndex = 5;
-            this.btnExportArcData.Text = "Экспорт";
-            this.btnExportArcData.UseVisualStyleBackColor = true;
-            this.btnExportArcData.Click += new System.EventHandler(this.btnExport_Click);
-            // 
-            // gbEvents
-            // 
-            this.gbEvents.Controls.Add(this.lblEventsDate);
-            this.gbEvents.Controls.Add(this.dtpEventsDate);
-            this.gbEvents.Controls.Add(this.numEventsCtrlCnlNum);
-            this.gbEvents.Controls.Add(this.lblEventsCtrlCnlNum);
-            this.gbEvents.Controls.Add(this.btnExportEvents);
-            this.gbEvents.Location = new System.Drawing.Point(12, 198);
-            this.gbEvents.Name = "gbEvents";
-            this.gbEvents.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
-            this.gbEvents.Size = new System.Drawing.Size(374, 67);
-            this.gbEvents.TabIndex = 4;
-            this.gbEvents.TabStop = false;
-            this.gbEvents.Text = "События";
-            // 
-            // lblEventsDate
-            // 
-            this.lblEventsDate.AutoSize = true;
-            this.lblEventsDate.Location = new System.Drawing.Point(86, 16);
-            this.lblEventsDate.Name = "lblEventsDate";
-            this.lblEventsDate.Size = new System.Drawing.Size(33, 13);
-            this.lblEventsDate.TabIndex = 2;
-            this.lblEventsDate.Text = "Дата";
-            // 
-            // dtpEventsDate
-            // 
-            this.dtpEventsDate.CustomFormat = "";
-            this.dtpEventsDate.Format = System.Windows.Forms.DateTimePickerFormat.Short;
-            this.dtpEventsDate.Location = new System.Drawing.Point(89, 32);
-            this.dtpEventsDate.Name = "dtpEventsDate";
-            this.dtpEventsDate.Size = new System.Drawing.Size(100, 20);
-            this.dtpEventsDate.TabIndex = 3;
-            // 
-            // numEventsCtrlCnlNum
-            // 
-            this.numEventsCtrlCnlNum.Location = new System.Drawing.Point(13, 32);
-            this.numEventsCtrlCnlNum.Maximum = new decimal(new int[] {
-            65535,
-            0,
-            0,
-            0});
-            this.numEventsCtrlCnlNum.Name = "numEventsCtrlCnlNum";
-            this.numEventsCtrlCnlNum.Size = new System.Drawing.Size(70, 20);
-            this.numEventsCtrlCnlNum.TabIndex = 1;
-            this.numEventsCtrlCnlNum.Value = new decimal(new int[] {
-            3,
-            0,
-            0,
-            0});
-            this.numEventsCtrlCnlNum.ValueChanged += new System.EventHandler(this.numEventsCtrlCnlNum_ValueChanged);
-            // 
-            // lblEventsCtrlCnlNum
-            // 
-            this.lblEventsCtrlCnlNum.AutoSize = true;
-            this.lblEventsCtrlCnlNum.Location = new System.Drawing.Point(10, 16);
-            this.lblEventsCtrlCnlNum.Name = "lblEventsCtrlCnlNum";
-            this.lblEventsCtrlCnlNum.Size = new System.Drawing.Size(61, 13);
-            this.lblEventsCtrlCnlNum.TabIndex = 0;
-            this.lblEventsCtrlCnlNum.Text = "Канал упр.";
-            // 
-            // btnExportEvents
-            // 
-            this.btnExportEvents.Location = new System.Drawing.Point(195, 31);
-            this.btnExportEvents.Name = "btnExportEvents";
-            this.btnExportEvents.Size = new System.Drawing.Size(75, 23);
-            this.btnExportEvents.TabIndex = 4;
-            this.btnExportEvents.Text = "Экспорт";
-            this.btnExportEvents.UseVisualStyleBackColor = true;
-            this.btnExportEvents.Click += new System.EventHandler(this.btnExport_Click);
-            // 
-            // btnCancel
-            // 
-            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
-            this.btnCancel.Location = new System.Drawing.Point(311, 271);
-            this.btnCancel.Name = "btnCancel";
-            this.btnCancel.Size = new System.Drawing.Size(75, 23);
-            this.btnCancel.TabIndex = 6;
-            this.btnCancel.Text = "Отмена";
-            this.btnCancel.UseVisualStyleBackColor = true;
-            // 
-            // btnOK
-            // 
-            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
-            this.btnOK.Location = new System.Drawing.Point(230, 271);
-            this.btnOK.Name = "btnOK";
-            this.btnOK.Size = new System.Drawing.Size(75, 23);
-            this.btnOK.TabIndex = 5;
-            this.btnOK.Text = "OK";
-            this.btnOK.UseVisualStyleBackColor = true;
-            // 
-            // FrmManualExport
-            // 
-            this.AcceptButton = this.btnOK;
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.CancelButton = this.btnCancel;
-            this.ClientSize = new System.Drawing.Size(398, 306);
-            this.Controls.Add(this.btnOK);
-            this.Controls.Add(this.btnCancel);
-            this.Controls.Add(this.gbEvents);
-            this.Controls.Add(this.gbArcData);
-            this.Controls.Add(this.gbCurData);
-            this.Controls.Add(this.lblDataSource);
-            this.Controls.Add(this.cbDataSource);
-            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
-            this.MaximizeBox = false;
-            this.MinimizeBox = false;
-            this.Name = "FrmManualExport";
-            this.ShowIcon = false;
-            this.ShowInTaskbar = false;
-            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
-            this.Text = "Экспорт в ручном режиме";
-            this.Load += new System.EventHandler(this.FrmManualExport_Load);
-            this.gbCurData.ResumeLayout(false);
-            this.gbCurData.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numCurDataCtrlCnlNum)).EndInit();
-            this.gbArcData.ResumeLayout(false);
-            this.gbArcData.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numArcDataCtrlCnlNum)).EndInit();
-            this.gbEvents.ResumeLayout(false);
-            this.gbEvents.PerformLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.numEventsCtrlCnlNum)).EndInit();
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-
-        private System.Windows.Forms.ComboBox cbDataSource;
-        private System.Windows.Forms.Label lblDataSource;
-        private System.Windows.Forms.GroupBox gbCurData;
-        private System.Windows.Forms.Button btnExportCurData;
-        private System.Windows.Forms.NumericUpDown numCurDataCtrlCnlNum;
-        private System.Windows.Forms.Label lblCurDataCtrlCnlNum;
-        private System.Windows.Forms.GroupBox gbArcData;
-        private System.Windows.Forms.NumericUpDown numArcDataCtrlCnlNum;
-        private System.Windows.Forms.Label lblArcDataCtrlCnlNum;
-        private System.Windows.Forms.Button btnExportArcData;
-        private System.Windows.Forms.DateTimePicker dtpArcDataTime;
-        private System.Windows.Forms.DateTimePicker dtpArcDataDate;
-        private System.Windows.Forms.Label lblArcDataDateTime;
-        private System.Windows.Forms.GroupBox gbEvents;
-        private System.Windows.Forms.DateTimePicker dtpEventsDate;
-        private System.Windows.Forms.NumericUpDown numEventsCtrlCnlNum;
-        private System.Windows.Forms.Label lblEventsCtrlCnlNum;
-        private System.Windows.Forms.Button btnExportEvents;
-        private System.Windows.Forms.Label lblEventsDate;
-        private System.Windows.Forms.Button btnCancel;
-        private System.Windows.Forms.Button btnOK;
-    }
-}
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.cs b/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.cs
deleted file mode 100644
index e3d50612f..000000000
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.cs
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Manual export form
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
- */
-
-using Scada.Client;
-using Scada.UI;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Windows.Forms;
-
-namespace Scada.Server.Modules.DBExport
-{
-    /// 
-    /// Manual export form.
-    /// Форма экспорта в ручном режиме.
-    /// 
-    internal partial class FrmManualExport : Form
-    {
-        /// 
-        /// Конструктор, ограничивающий создание формы без параметров
-        /// 
-        private FrmManualExport()
-        {
-            InitializeComponent();
-        }
-
-
-        /// 
-        /// Отобразить форму модально
-        /// 
-        public static bool ShowDialog(ServerComm serverComm,
-            List expDests, ModConfig.ExportDestination selExpDest,
-            ref int curDataCtrlCnlNum, ref int arcDataCtrlCnlNum, ref int eventsCtrlCnlNum)
-        {
-            FrmManualExport frmManualExport = new FrmManualExport();
-            frmManualExport.ServerComm = serverComm;
-
-            // заполнение списка источников данных
-            foreach (ModConfig.ExportDestination expDest in expDests)
-            {
-                int ind = frmManualExport.cbDataSource.Items.Add(expDest.DataSource);
-                if (expDest == selExpDest)
-                    frmManualExport.cbDataSource.SelectedIndex = ind;
-            }
-
-            // установка каналов управления
-            frmManualExport.CurDataCtrlCnlNum = curDataCtrlCnlNum;
-            frmManualExport.ArcDataCtrlCnlNum = arcDataCtrlCnlNum;
-            frmManualExport.EventsCtrlCnlNum = eventsCtrlCnlNum;
-
-            if (frmManualExport.ShowDialog() == DialogResult.OK)
-            {
-                // возврат каналов управления
-                curDataCtrlCnlNum = frmManualExport.CurDataCtrlCnlNum;
-                arcDataCtrlCnlNum = frmManualExport.ArcDataCtrlCnlNum;
-                eventsCtrlCnlNum = frmManualExport.EventsCtrlCnlNum;
-                return true;
-            }
-            else
-            {
-                return false;
-            }
-        }
-
-
-        /// 
-        /// Получить или установить объект для обмена данными со SCADA-Сервером
-        /// 
-        private ServerComm ServerComm { get; set; }
-
-        /// 
-        /// Получить или установить номер канала управления для экспорта текущих данных
-        /// 
-        private int CurDataCtrlCnlNum
-        {
-            get
-            {
-                return Convert.ToInt32(numCurDataCtrlCnlNum.Value);
-            }
-            set
-            {
-                numCurDataCtrlCnlNum.SetValue(value);
-            }
-        }
-
-        /// 
-        /// Получить или установить номер канала управления для экспорта архивных данных
-        /// 
-        private int ArcDataCtrlCnlNum
-        {
-            get
-            {
-                return Convert.ToInt32(numArcDataCtrlCnlNum.Value);
-            }
-            set
-            {
-                numArcDataCtrlCnlNum.SetValue(value);
-            }
-        }
-
-        /// 
-        /// Получить или установить номер канала управления для экспорта событий
-        /// 
-        private int EventsCtrlCnlNum
-        {
-            get
-            {
-                return Convert.ToInt32(numEventsCtrlCnlNum.Value);
-            }
-            set
-            {
-                numEventsCtrlCnlNum.SetValue(value);
-            }
-        }
-
-
-        private void FrmManualExport_Load(object sender, EventArgs e)
-        {
-            // перевод формы
-            if (!Localization.UseRussian)
-                Translator.TranslateForm(this, "Scada.Server.Modules.DBExport.FrmManualExport");
-
-            // настройка элементов управления
-            if (cbDataSource.SelectedIndex < 0 && cbDataSource.Items.Count > 0)
-                cbDataSource.SelectedIndex = 0;
-            gbCurData.Enabled = gbArcData.Enabled = gbEvents.Enabled = 
-                cbDataSource.Items.Count > 0;
-            dtpArcDataDate.Value = dtpEventsDate.Value = dtpArcDataTime.Value = DateTime.Today;
-
-            if (ServerComm == null)
-            {
-                btnExportCurData.Enabled = false;
-                btnExportArcData.Enabled = false;
-                btnExportEvents.Enabled = false;
-            }
-        }
-
-        private void numCurDataCtrlCnlNum_ValueChanged(object sender, EventArgs e)
-        {
-            btnExportCurData.Enabled = numCurDataCtrlCnlNum.Value > 0;
-        }
-
-        private void numArcDataCtrlCnlNum_ValueChanged(object sender, EventArgs e)
-        {
-            dtpArcDataDate.Enabled = dtpArcDataTime.Enabled = btnExportArcData.Enabled =
-                numArcDataCtrlCnlNum.Value > 0;
-        }
-
-        private void numEventsCtrlCnlNum_ValueChanged(object sender, EventArgs e)
-        {
-            dtpEventsDate.Enabled = btnExportEvents.Enabled =
-                numEventsCtrlCnlNum.Value > 0;
-        }
-
-        private void btnExport_Click(object sender, EventArgs e)
-        {
-            // отправка команды экспорта
-            int ctrlCnlNum;
-            string cmdDataStr = cbDataSource.Text;
-
-            if (sender == btnExportArcData)
-            {
-                ctrlCnlNum = ArcDataCtrlCnlNum;
-                DateTime dateTime = dtpArcDataDate.Value.Date.Add(dtpArcDataTime.Value.TimeOfDay);
-                cmdDataStr += "\n" + ScadaUtils.XmlValToStr(dateTime);
-            }
-            else if (sender == btnExportEvents)
-            {
-                ctrlCnlNum = EventsCtrlCnlNum;
-                DateTime date = dtpEventsDate.Value.Date;
-                cmdDataStr += "\n" + ScadaUtils.XmlValToStr(date);
-            }
-            else
-            {
-                ctrlCnlNum = CurDataCtrlCnlNum;
-            }
-
-            byte[] cmdData = Encoding.Default.GetBytes(cmdDataStr);
-
-            if (ServerComm.SendBinaryCommand(0, ctrlCnlNum, cmdData, out bool result))
-                ScadaUiUtils.ShowInfo(ModPhrases.CmdSentSuccessfully);
-            else
-                ScadaUiUtils.ShowError(ServerComm.ErrMsg);
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/Lang/ModDBExport.en-GB.xml b/ScadaServer/OpenModules/ModDBExport/Lang/ModDBExport.en-GB.xml
deleted file mode 100644
index 5d47bcd43..000000000
--- a/ScadaServer/OpenModules/ModDBExport/Lang/ModDBExport.en-GB.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-  
-    Export to DB
-    Add data source
-    Delete data source
-    Manual export
-    Add data sources
-    Connection
-    Server
-    Database
-    User
-    Password
-    Connection string
-    Current Data
-    Archive Data
-    Events
-    Export
-    Misc
-    Max. queue size
-    Save
-    Cancel
-    Close
-  
-  
-    Manual Export
-    Data source
-    Current data
-    Out channel
-    Export
-    Archive data
-    Out channel
-    Date and time
-    Export
-    Events
-    Out channel
-    Date
-    Export
-    OK
-    Cancel
-  
-
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDBExport/ModDBExportLogic.cs b/ScadaServer/OpenModules/ModDBExport/ModDBExportLogic.cs
deleted file mode 100644
index 9db624b80..000000000
--- a/ScadaServer/OpenModules/ModDBExport/ModDBExportLogic.cs
+++ /dev/null
@@ -1,540 +0,0 @@
-/*
- * Copyright 2020 Mikhail Shiryaev
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * 
- * 
- * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Server module logic
- * 
- * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2010
- * 
- * Description
- * Server module for real time data export from Rapid SCADA to DB.
- */
-
-using Scada.Data.Configuration;
-using Scada.Data.Models;
-using Scada.Data.Tables;
-using Scada.Server.Modules.DBExport;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Threading;
-using Utils;
-
-namespace Scada.Server.Modules
-{
-    /// 
-    /// Server module logic
-    /// Логика работы серверного модуля
-    /// 
-    public class ModDBExportLogic : ModLogic
-    {
-        /// 
-        /// Имя файла журнала работы модуля
-        /// 
-        internal const string LogFileName = "ModDBExport.log";
-        /// 
-        /// Имя файла информации о работе модуля
-        /// 
-        private const string InfoFileName = "ModDBExport.txt";
-        /// 
-        /// Задержка потока обновления файла информации, мс
-        /// 
-        private const int InfoThreadDelay = 500;
-
-        private bool normalWork;          // признак нормальной работы модуля
-        private string workState;         // строковая запись состояния работы
-        private Log log;                  // журнал работы модуля
-        private string infoFileName;      // полное имя файла информации
-        private Thread infoThread;        // поток для обновления файла информации
-        private ModConfig config;         // конфигурация модуля
-        private List exporters; // экспортёры
-
-
-        /// 
-        /// Конструктор
-        /// 
-        public ModDBExportLogic()
-        {
-            normalWork = true;
-            workState = Localization.UseRussian ? "норма" : "normal";
-            log = null;
-            infoFileName = "";
-            infoThread = null;
-            config = null;
-            exporters = null;
-        }
-
-
-        /// 
-        /// Получить имя модуля
-        /// 
-        public override string Name
-        {
-            get
-            {
-                return "ModDBExport";
-            }
-        }
-
-
-        /// 
-        /// Получить параметры команды
-        /// 
-        private void GetCmdParams(Command cmd, out string dataSourceName, out DateTime dateTime)
-        {
-            string cmdDataStr = cmd.GetCmdDataStr();
-            string[] parts = cmdDataStr.Split('\n');
-
-            dataSourceName = parts[0];
-            try { dateTime = ScadaUtils.XmlParseDateTime(parts[1]); }
-            catch { dateTime = DateTime.MinValue; }
-        }
-
-        /// 
-        /// Найти экспортёр по наименованию источника данных
-        /// 
-        private Exporter FindExporter(string dataSourceName)
-        {
-            foreach (Exporter exporter in exporters)
-                if (exporter.DataSource.Name == dataSourceName)
-                    return exporter;
-            return null;
-        }
-
-        /// 
-        /// Экспортировать текущие данные, загрузив их из файла
-        /// 
-        private void ExportCurDataFromFile(Exporter exporter)
-        {
-            // загрузка текущего среза из файла
-            SrezTableLight srezTable = new SrezTableLight();
-            SrezAdapter srezAdapter = new SrezAdapter();
-            srezAdapter.FileName = ServerUtils.BuildCurFileName(Settings.ArcDir);
-
-            try
-            {
-                srezAdapter.Fill(srezTable);
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(string.Format(Localization.UseRussian ? 
-                    "Ошибка при загрузке текущего среза из файла {0}: {1}" :
-                    "Error loading current data from file {0}: {1}", srezAdapter.FileName, ex.Message));
-            }
-
-            // добавление среза в очередь экспорта
-            if (srezTable.SrezList.Count > 0)
-            {
-                SrezTableLight.Srez sourceSrez = srezTable.SrezList.Values[0];
-                SrezTableLight.Srez srez = new SrezTableLight.Srez(DateTime.Now, sourceSrez.CnlNums, sourceSrez);
-                exporter.EnqueueCurData(srez);
-                log.WriteAction(Localization.UseRussian ? "Текущие данные добавлены в очередь экспорта" :
-                    "Current data added to export queue");
-            }
-            else
-            {
-                log.WriteAction(Localization.UseRussian ? "Отсутствуют текущие данные для экспорта" :
-                    "No current data to export");
-            }
-        }
-
-        /// 
-        /// Экспортировать архивные данные, загрузив их из файла
-        /// 
-        private void ExportArcDataFromFile(Exporter exporter, DateTime dateTime)
-        {
-            // загрузка таблицы минутных срезов из файла
-            SrezTableLight srezTable = new SrezTableLight();
-            SrezAdapter srezAdapter = new SrezAdapter();
-            srezAdapter.FileName = ServerUtils.BuildMinFileName(Settings.ArcDir, dateTime);
-
-            try
-            {
-                srezAdapter.Fill(srezTable);
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(string.Format(Localization.UseRussian ?
-                    "Ошибка при загрузке таблицы минутных срезов из файла {0}: {1}" :
-                    "Error loading minute data table from file {0}: {1}", srezAdapter.FileName, ex.Message));
-            }
-
-            // поиск среза на заданное время
-            SrezTableLight.Srez srez = srezTable.GetSrez(dateTime);
-
-            // добавление среза в очередь экспорта
-            if (srez == null)
-            {
-                log.WriteAction(Localization.UseRussian ? "Отсутствуют архивные данные для экспорта" :
-                    "No archive data to export");
-            }
-            else
-            {
-                exporter.EnqueueArcData(srez);
-                log.WriteAction(Localization.UseRussian ? "Архивные данные добавлены в очередь экспорта" :
-                    "Archive data added to export queue");
-            }
-        }
-
-        /// 
-        /// Экспортировать события, загрузив их из файла
-        /// 
-        private void ExportEventsFromFile(Exporter exporter, DateTime date)
-        {
-            // загрузка таблицы событий из файла
-            EventTableLight eventTable = new EventTableLight();
-            EventAdapter eventAdapter = new EventAdapter();
-            eventAdapter.FileName = ServerUtils.BuildEvFileName(Settings.ArcDir, date);
-
-            try
-            {
-                eventAdapter.Fill(eventTable);
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(string.Format(Localization.UseRussian ?
-                    "Ошибка при загрузке таблицы событий из файла {0}: {1}" :
-                    "Error loading event table from file {0}: {1}", eventAdapter.FileName, ex.Message));
-            }
-
-            // добавление событий в очередь экспорта
-            if (eventTable.AllEvents.Count > 0)
-            {
-                foreach (EventTableLight.Event ev in eventTable.AllEvents)
-                    exporter.EnqueueEvent(ev);
-                log.WriteAction(Localization.UseRussian ? "События добавлены в очередь экспорта" :
-                    "Events added to export queue");
-            }
-            else
-            {
-                log.WriteAction(Localization.UseRussian ? "Отсутствуют события для экспорта" :
-                    "No events to export");
-            }
-        }
-
-        /// 
-        /// Записать в файл информацию о работе модуля
-        /// 
-        private void WriteInfo()
-        {
-            try
-            {
-                // формирование текста
-                StringBuilder sbInfo = new StringBuilder();
-
-                if (Localization.UseRussian)
-                {
-                    sbInfo
-                        .AppendLine("Модуль экспорта данных")
-                        .AppendLine("----------------------")
-                        .Append("Состояние: ").AppendLine(workState).AppendLine()
-                        .AppendLine("Источники данных")
-                        .AppendLine("----------------");
-                }
-                else
-                {
-                    sbInfo
-                        .AppendLine("Export Data Module")
-                        .AppendLine("------------------")
-                        .Append("State: ").AppendLine(workState).AppendLine()
-                        .AppendLine("Data Sources")
-                        .AppendLine("------------");
-                }
-
-                int cnt = exporters == null ? 0 : exporters.Count;
-                if (cnt > 0)
-                {
-                    for (int i = 0; i < cnt; i++)
-                    {
-                        sbInfo.Append((i + 1).ToString()).Append(". ").
-                            AppendLine(exporters[i].GetInfo());
-                    }
-                }
-                else
-                {
-                    sbInfo.AppendLine(Localization.UseRussian ? "Нет" : "No");
-                }
-
-                // вывод в файл
-                using (StreamWriter writer = new StreamWriter(infoFileName, false, Encoding.UTF8))
-                {
-                    writer.Write(sbInfo.ToString());
-                }
-            }
-            catch (ThreadAbortException)
-            {
-            }
-            catch (Exception ex)
-            {
-                log.WriteAction(ModPhrases.WriteInfoError + ": " + ex.Message, Log.ActTypes.Exception);
-            }
-        }
-
-
-        /// 
-        /// Выполнить действия при запуске работы сервера
-        /// 
-        public override void OnServerStart()
-        {
-            // вывод в журнал
-            log = new Log(Log.Formats.Simple)
-            {
-                Encoding = Encoding.UTF8,
-                FileName = AppDirs.LogDir + LogFileName
-            };
-            log.WriteBreak();
-            log.WriteAction(string.Format(ModPhrases.StartModule, Name));
-
-            // определение полного имени файла информации
-            infoFileName = AppDirs.LogDir + InfoFileName;
-
-            // загрука конфигурации
-            config = new ModConfig(AppDirs.ConfigDir);
-
-            if (config.Load(out string errMsg))
-            {
-                // создание и запуск экспортёров
-                exporters = new List();
-                foreach (ModConfig.ExportDestination expDest in config.ExportDestinations)
-                {
-                    Exporter exporter = new Exporter(expDest, log);
-                    exporters.Add(exporter);
-                    exporter.Start();
-                }
-
-                // создание и запуск потока для обновления файла информации
-                infoThread = new Thread(() => { while (true) { WriteInfo(); Thread.Sleep(InfoThreadDelay); } });
-                infoThread.Start();
-            }
-            else
-            {
-                normalWork = false;
-                workState = Localization.UseRussian ? "ошибка" : "error";
-                WriteInfo();
-                log.WriteAction(errMsg);
-                log.WriteAction(ModPhrases.NormalModExecImpossible);
-            }
-        }
-
-        /// 
-        /// Выполнить действия при остановке работы сервера
-        /// 
-        public override void OnServerStop()
-        {
-            // остановка экспортёров
-            foreach (Exporter exporter in exporters)
-                exporter.Terminate();
-
-            // ожидание завершения работы экспортёров
-            DateTime nowDT = DateTime.Now;
-            DateTime begDT = nowDT;
-            DateTime endDT = nowDT.AddMilliseconds(WaitForStop);
-            bool running;
-
-            do
-            {
-                running = false;
-                foreach (Exporter exporter in exporters)
-                {
-                    if (exporter.Running)
-                    {
-                        running = true;
-                        break;
-                    }
-                }
-                if (running)
-                    Thread.Sleep(ScadaUtils.ThreadDelay);
-                nowDT = DateTime.Now;
-            }
-            while (begDT <= nowDT && nowDT <= endDT && running);
-
-            // прерывание работы экспортёров
-            if (running)
-            {
-                foreach (Exporter exporter in exporters)
-                    if (exporter.Running)
-                        exporter.Abort();
-            }
-
-            // прерывание потока для обновления файла информации
-            if (infoThread != null)
-            {
-                infoThread.Abort();
-                infoThread = null;
-            }
-
-            // вывод информации
-            workState = Localization.UseRussian ? "остановлен" : "stopped";
-            WriteInfo();
-            log.WriteAction(string.Format(ModPhrases.StopModule, Name));
-            log.WriteBreak();
-        }
-
-        /// 
-        /// Выполнить действия после обработки новых текущих данных
-        /// 
-        public override void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez)
-        {
-            // экспорт текущих данных в БД
-            if (normalWork)
-            {
-                // создание экпортируемого среза
-                SrezTableLight.Srez srez = new SrezTableLight.Srez(DateTime.Now, cnlNums, curSrez);
-
-                // добавление среза в очередь экспорта
-                foreach (Exporter exporter in exporters)
-                    exporter.EnqueueCurData(srez);
-            }
-        }
-
-        /// 
-        /// Выполнить действия после обработки новых архивных данных
-        /// 
-        public override void OnArcDataProcessed(int[] cnlNums, SrezTableLight.Srez arcSrez)
-        {
-            // экспорт архивных данных в БД
-            if (normalWork)
-            {
-                // создание экпортируемого среза
-                SrezTableLight.Srez srez = new SrezTableLight.Srez(arcSrez.DateTime, cnlNums, arcSrez);
-
-                // добавление среза в очередь экспорта
-                foreach (Exporter exporter in exporters)
-                    exporter.EnqueueArcData(srez);
-            }
-        }
-
-        /// 
-        /// Выполнить действия после создания события и записи на диск
-        /// 
-        public override void OnEventCreated(EventTableLight.Event ev)
-        {
-            // экспорт события в БД
-            if (normalWork)
-            {
-                // добавление события в очередь экспорта
-                foreach (Exporter exporter in exporters)
-                {
-                    exporter.EnqueueEvent(ev);
-                }
-            }
-        }
-
-        /// 
-        /// Выполнить действия после приёма команды ТУ
-        /// 
-        public override void OnCommandReceived(int ctrlCnlNum, Command cmd, int userID, ref bool passToClients)
-        {
-            // экспорт в ручном режиме
-            if (normalWork)
-            {
-                bool exportCurData = ctrlCnlNum == config.CurDataCtrlCnlNum;
-                bool exportArcData = ctrlCnlNum == config.ArcDataCtrlCnlNum;
-                bool exportEvents = ctrlCnlNum == config.EventsCtrlCnlNum;
-                bool procCmd = true;
-
-                if (exportCurData)
-                    log.WriteAction(Localization.UseRussian ? 
-                        "Получена команда экспорта текущих данных" :
-                        "Export current data command received");
-                else if (exportArcData)
-                    log.WriteAction(Localization.UseRussian ? 
-                        "Получена команда экспорта архивных данных" :
-                        "Export archive data command received");
-                else if (exportEvents)
-                    log.WriteAction(Localization.UseRussian ? 
-                        "Получена команда экспорта событий" :
-                        "Export events command received");
-                else
-                    procCmd = false;
-
-                if (procCmd)
-                {
-                    passToClients = false;
-
-                    if (cmd.CmdTypeID == BaseValues.CmdTypes.Binary)
-                    {
-                        string dataSourceName;
-                        DateTime dateTime;
-                        GetCmdParams(cmd, out dataSourceName, out dateTime);
-
-                        if (dataSourceName == "")
-                        {
-                            log.WriteLine(string.Format(Localization.UseRussian ?
-                                "Источник данных не задан" : "Data source is not specified"));
-                        }
-                        else
-                        {
-                            Exporter exporter = FindExporter(dataSourceName);
-
-                            if (exporter == null)
-                            {
-                                log.WriteLine(string.Format(Localization.UseRussian ?
-                                    "Неизвестный источник данных {0}" : "Unknown data source {0}", dataSourceName));
-                            }
-                            else
-                            {
-                                log.WriteLine(string.Format(Localization.UseRussian ?
-                                    "Источник данных: {0}" : "Data source: {0}", dataSourceName));
-
-                                if (exportCurData)
-                                {
-                                    ExportCurDataFromFile(exporter);
-                                }
-                                else if (exportArcData)
-                                {
-                                    if (dateTime == DateTime.MinValue)
-                                    {
-                                        log.WriteLine(string.Format(Localization.UseRussian ?
-                                            "Некорректная дата и время" : "Incorrect date and time"));
-                                    }
-                                    else
-                                    {
-                                        log.WriteLine(string.Format(Localization.UseRussian ?
-                                            "Дата и время: {0:G}" : "Date and time: {0:G}", dateTime));
-                                        ExportArcDataFromFile(exporter, dateTime);
-                                    }
-                                }
-                                else // exportEvents
-                                {
-                                    if (dateTime == DateTime.MinValue)
-                                    {
-                                        log.WriteLine(string.Format(Localization.UseRussian ?
-                                            "Некорректная дата" : "Incorrect date"));
-                                    }
-                                    else
-                                    {
-                                        log.WriteLine(string.Format(Localization.UseRussian ?
-                                            "Дата: {0:d}" : "Date: {0:d}", dateTime));
-                                        ExportEventsFromFile(exporter, dateTime);
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    else
-                    {
-                        log.WriteAction(ModPhrases.IllegalCommand);
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/delete.png b/ScadaServer/OpenModules/ModDBExport/Res/delete.png
deleted file mode 100644
index 5d23b2b20..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/delete.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/export.png b/ScadaServer/OpenModules/ModDBExport/Res/export.png
deleted file mode 100644
index 895b9c6d3..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/export.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/mssql.png b/ScadaServer/OpenModules/ModDBExport/Res/mssql.png
deleted file mode 100644
index 21c1e8ce6..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/mssql.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/mysql.png b/ScadaServer/OpenModules/ModDBExport/Res/mysql.png
deleted file mode 100644
index 5d7b534b8..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/mysql.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/oledb.png b/ScadaServer/OpenModules/ModDBExport/Res/oledb.png
deleted file mode 100644
index 6676514f7..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/oledb.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/oracle.png b/ScadaServer/OpenModules/ModDBExport/Res/oracle.png
deleted file mode 100644
index 117623bc4..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/oracle.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/plus.png b/ScadaServer/OpenModules/ModDBExport/Res/plus.png
deleted file mode 100644
index 7f18d8595..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/plus.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDBExport/Res/postgresql.png b/ScadaServer/OpenModules/ModDBExport/Res/postgresql.png
deleted file mode 100644
index ba475f948..000000000
Binary files a/ScadaServer/OpenModules/ModDBExport/Res/postgresql.png and /dev/null differ
diff --git a/ScadaServer/OpenModules/ModDbExport/Config/ModDbExport.xml b/ScadaServer/OpenModules/ModDbExport/Config/ModDbExport.xml
new file mode 100644
index 000000000..a423a2f08
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/Config/ModDbExport.xml
@@ -0,0 +1,60 @@
+
+
+  
+    
+      true
+      1
+      Target 1
+      1000
+      3600
+      0
+    
+    
+      
+      PostgreSQL
+      localhost
+      rapid_scada
+      postgres
+      4D83D8AEB31C1B40335A78AF3539DD22
+      
+    
+    
+      
+      
+        101-105
+        
+        false
+        
+          INSERT INTO mod_db_export.cnldata (datetime, cnlnum, val, stat)
+          VALUES (@dateTime, @cnlNum, @val, @stat)
+        
+      
+      
+        
+        
+        false
+        
+          WITH upsert AS (UPDATE mod_db_export.cnldata SET val = @val, stat = @stat
+          WHERE datetime = @datetime AND cnlnum = @cnlNum RETURNING *)
+          INSERT INTO mod_db_export.cnldata (datetime, cnlnum, val, stat)
+          SELECT @dateTime, @cnlNum, @val, @stat
+          WHERE NOT EXISTS (SELECT * FROM upsert)
+        
+      
+      
+        
+        
+        
+          INSERT INTO mod_db_export.events (datetime, objnum, kpnum, paramid, cnlnum, oldcnlval, oldcnlstat, newcnlval, newcnlstat, checked, userid, descr, data)
+          VALUES (@dateTime, @objNum, @kpNum, @paramID, @cnlNum, @oldCnlVal, @oldCnlStat, @newCnlVal, @newCnlStat, @checked, @userID, @descr, @data)
+        
+      
+    
+    
+      
+      Min
+      10000
+      1
+    
+  
+
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/ArcUploadState.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/ArcUploadState.cs
new file mode 100644
index 000000000..0407a8e44
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/ArcUploadState.cs
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a state of snapshot upload process
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2020
+ * Modified : 2021
+ */
+
+using System;
+using System.Text;
+
+namespace Scada.Server.Modules.DbExport
+{
+    /// 
+    /// Represents a state of snapshot upload process.
+    /// Представляет состояние процесса загрузки срезов.
+    /// 
+    internal class ArcUploadState
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ArcUploadState()
+        {
+            IsReady = true;
+            SnapshotIndex = -1;
+            SnapshotDate = DateTime.MinValue;
+            MinSnapshotDT = DateTime.MinValue;
+            MaxSnapshotDT = DateTime.MaxValue;
+            QueuedSnapshotDT = DateTime.MinValue;
+            SentSnapshotDT = DateTime.MinValue;
+        }
+
+
+        /// 
+        /// Gets or sets a value indicating whether a gateway is ready to upload next snapshot.
+        /// 
+        public bool IsReady { get; set; }
+
+        /// 
+        /// Gets or sets the current index in a snapshot table.
+        /// 
+        public int SnapshotIndex { get; set; }
+
+        /// 
+        /// Gets or sets the date to select snapshots.
+        /// 
+        public DateTime SnapshotDate { get; set; }
+
+        /// 
+        /// Gets or sets the minimum snapshot timestamp.
+        /// 
+        public DateTime MinSnapshotDT { get; set; }
+
+        /// 
+        /// Gets or sets the maximum snapshot timestamp.
+        /// 
+        public DateTime MaxSnapshotDT { get; set; }
+
+        /// 
+        /// Gets or sets the timestamp of the queued snapshot.
+        /// 
+        public DateTime QueuedSnapshotDT { get; set; }
+
+        /// 
+        /// Gets or sets the timestamp of the last snapshot that was successfully sent.
+        /// 
+        public DateTime SentSnapshotDT { get; set; }
+
+
+        /// 
+        /// Initializes the snapshot date.
+        /// 
+        public void InitSnapshotDate(int maxAge)
+        {
+            SnapshotDate = SentSnapshotDT > DateTime.MinValue ?
+                SentSnapshotDT.Date :
+                DateTime.Today.AddDays(1 - Math.Max(maxAge, 1));
+        }
+
+        /// 
+        /// Confirms that a snapshot has been sent.
+        /// 
+        public bool ConfirmSending()
+        {
+            if (IsReady)
+            {
+                return false;
+            }
+            else
+            {
+                IsReady = true;
+                SentSnapshotDT = QueuedSnapshotDT;
+                QueuedSnapshotDT = DateTime.MinValue;
+                return true;
+            }
+        }
+
+        /// 
+        /// Appends information to the string builder.
+        /// 
+        public void AppendInfo(StringBuilder sbInfo)
+        {
+            if (Localization.UseRussian)
+            {
+                sbInfo
+                    .Append("Готовность     : ").Append(IsReady ? "да" : "нет").AppendLine()
+                    .Append("Индекс         : ").Append(SnapshotIndex).AppendLine()
+                    .Append("Дата           : ").Append(SnapshotDate.ToLocalizedDateString()).AppendLine()
+                    .Append("Мин. время     : ").Append(MinSnapshotDT > DateTime.MinValue ? MinSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .Append("Макс. время    : ").Append(MaxSnapshotDT < DateTime.MaxValue ? MaxSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .Append("В очереди      : ").Append(QueuedSnapshotDT > DateTime.MinValue? QueuedSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .Append("Отправлен      : ").Append(SentSnapshotDT > DateTime.MinValue ? SentSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .AppendLine();
+            }
+            else
+            {
+                sbInfo
+                    .Append("Ready      : ").Append(IsReady ? "Yes" : "No").AppendLine()
+                    .Append("Index      : ").Append(SnapshotIndex).AppendLine()
+                    .Append("Date       : ").Append(SnapshotDate.ToLocalizedDateString()).AppendLine()
+                    .Append("Min. time  : ").Append(MinSnapshotDT > DateTime.MinValue ? MinSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .Append("Max. time  : ").Append(MaxSnapshotDT < DateTime.MaxValue ? MaxSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .Append("Queued     : ").Append(QueuedSnapshotDT > DateTime.MinValue ? QueuedSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .Append("Sent       : ").Append(SentSnapshotDT > DateTime.MinValue ? SentSnapshotDT.ToLocalizedString() : "---").AppendLine()
+                    .AppendLine();
+            }
+        }
+
+        /// 
+        /// Appends information to the string builder.
+        /// 
+        public static void AppendInfo(ArcUploadState uploadState, StringBuilder sbInfo)
+        {
+            if (uploadState == null)
+            {
+                sbInfo
+                    .AppendLine(Localization.UseRussian ? "Отключена" : "Disabled")
+                    .AppendLine();
+            }
+            else
+            {
+                uploadState.AppendInfo(sbInfo);
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/DBTypes.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/CmdAction.cs
similarity index 54%
rename from ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/DBTypes.cs
rename to ScadaServer/OpenModules/ModDbExport/DbExport/CmdAction.cs
index 05a4321c2..e1185145f 100644
--- a/ScadaServer/OpenModules/ModDBExport/DBExport/DataSources/DBTypes.cs
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/CmdAction.cs
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 Mikhail Shiryaev
+ * Copyright 2021 Mikhail Shiryaev
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,27 +15,35 @@
  * 
  * 
  * Product  : Rapid SCADA
- * Module   : ModDBExport
- * Summary  : Database types
+ * Module   : ModDbExport
+ * Summary  : Specifies the command actions
  * 
  * Author   : Mikhail Shiryaev
- * Created  : 2015
- * Modified : 2020
+ * Created  : 2021
+ * Modified : 2021
  */
 
-namespace Scada.Server.Modules.DBExport
+namespace Scada.Server.Modules.DbExport
 {
     /// 
-    /// Database types.
-    /// Типы БД.
+    /// Specifies the command actions.
+    /// Задает действия команды.
     /// 
-    internal enum DBType
+    internal enum CmdAction
     {
-        Undefined,
-        MSSQL,
-        Oracle,
-        PostgreSQL,
-        MySQL,
-        OLEDB
+        /// 
+        /// No command.
+        /// 
+        None,
+
+        /// 
+        /// Upload data archive.
+        /// 
+        ArcUpload,
+
+        /// 
+        /// Upload events.
+        /// 
+        EvUpload
     }
 }
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/CmdParams.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/CmdParams.cs
new file mode 100644
index 000000000..265a942c6
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/CmdParams.cs
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents parameters of a module command
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Globalization;
+
+namespace Scada.Server.Modules.DbExport
+{
+    /// 
+    /// Represents parameters of a module command.
+    /// Представляет параметры команды модуля.
+    /// 
+    internal class CmdParams
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CmdParams()
+        {
+            Action = CmdAction.None;
+            MinDT = DateTime.MinValue;
+            MaxDT = DateTime.MinValue;
+        }
+
+
+        /// 
+        /// Gets or sets the command action.
+        /// 
+        public CmdAction Action { get; set; }
+
+        /// 
+        /// Gets or sets the beginning of the time range.
+        /// 
+        public DateTime MinDT { get; set; }
+
+        /// 
+        /// Gets or sets the end of the time range.
+        /// 
+        public DateTime MaxDT { get; set; }
+
+
+        /// 
+        /// Converts the string to command parameters.
+        /// 
+        public static bool Parse(string s, out CmdParams cmdParams, out string errMsg)
+        {
+            try
+            {
+                cmdParams = new CmdParams();
+                string[] lines = (s ?? "").Split('\n');
+
+                foreach (string line in lines)
+                {
+                    int idx = line.IndexOf('=');
+
+                    if (idx > 0)
+                    {
+                        string key = line.Substring(0, idx).Trim().ToLowerInvariant();
+                        string value = line.Substring(idx + 1).Trim();
+
+                        if (key == "cmd")
+                            cmdParams.Action = Enum.TryParse(value, true, out CmdAction action) ? action : CmdAction.None;
+                        else if (key == "mindt")
+                            cmdParams.MinDT = DateTime.Parse(value, DateTimeFormatInfo.InvariantInfo);
+                        else if (key == "maxdt")
+                            cmdParams.MaxDT = DateTime.Parse(value, DateTimeFormatInfo.InvariantInfo);
+                    }
+                }
+
+                if (cmdParams.Action != CmdAction.None && 
+                    cmdParams.MinDT > DateTime.MinValue && cmdParams.MaxDT > DateTime.MinValue)
+                {
+                    errMsg = "";
+                    return true;
+                }
+                else
+                {
+                    errMsg = Localization.UseRussian ?
+                        "Некорректная команда" :
+                        "Incorrect command";
+                    return false;
+                }
+            }
+            catch
+            {
+                cmdParams = null;
+                errMsg = Localization.UseRussian ?
+                    "Ошибка при разборе команды" :
+                    "Error parsing command";
+                return false;
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ArcDataTriggerOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ArcDataTriggerOptions.cs
new file mode 100644
index 000000000..9c2a1ce54
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ArcDataTriggerOptions.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents archive data trigger options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents archive data trigger options.
+    /// Представляет параметры триггера на архивные данные.
+    /// 
+    [Serializable]
+    internal class ArcDataTriggerOptions : DataTriggerOptions
+    {
+        /// 
+        /// Gets the trigger type name.
+        /// 
+        public override string TriggerType => "ArcDataTrigger";
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ArcUploadOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ArcUploadOptions.cs
new file mode 100644
index 000000000..2ff7190f3
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ArcUploadOptions.cs
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents archive upload options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents archive upload options.
+    /// Представляет параметры загрузки архивов.
+    /// 
+    [Serializable]
+    internal class ArcUploadOptions
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ArcUploadOptions()
+        {
+            Enabled = true;
+            SnapshotType = SnapshotType.Min;
+            Delay = 10000;
+            MaxAge = 1;
+        }
+
+
+        /// 
+        /// Gets or sets a value indicating whether to upload data.
+        /// 
+        public bool Enabled { get; set; }
+
+        /// 
+        /// Gets or sets the snapshot code.
+        /// 
+        public SnapshotType SnapshotType { get; set; }
+
+        /// 
+        /// Gets or sets the delay before sending archive in milliseconds.
+        /// 
+        public int Delay { get; set; }
+
+        /// 
+        /// Gets or sets the maximum age of archive in days.
+        /// 
+        public int MaxAge { get; set; }
+
+
+        /// 
+        /// Loads the options from the XML node.
+        /// 
+        public void LoadFromXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException(nameof(xmlElem));
+
+            Enabled = xmlElem.GetAttrAsBool("enabled");
+            SnapshotType = xmlElem.GetChildAsEnum("SnapshotType", SnapshotType.Min);
+            Delay = xmlElem.GetChildAsInt("Delay", Delay);
+            MaxAge = xmlElem.GetChildAsInt("MaxAge", MaxAge);
+        }
+
+        /// 
+        /// Saves the options into the XML node.
+        /// 
+        public void SaveToXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException(nameof(xmlElem));
+
+            xmlElem.SetAttribute("enabled", Enabled);
+            xmlElem.AppendElem("SnapshotType", SnapshotType);
+            xmlElem.AppendElem("Delay", Delay);
+            xmlElem.AppendElem("MaxAge", MaxAge);
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/CurDataTriggerOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/CurDataTriggerOptions.cs
new file mode 100644
index 000000000..8e53405d5
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/CurDataTriggerOptions.cs
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents current data trigger options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents current data trigger options.
+    /// Представляет параметры триггера на текущие данные.
+    /// 
+    [Serializable]
+    internal class CurDataTriggerOptions : DataTriggerOptions
+    {
+        /// 
+        /// Gets the trigger type name.
+        /// 
+        public override string TriggerType => "CurDataTrigger";
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/DataTriggerOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/DataTriggerOptions.cs
new file mode 100644
index 000000000..f5063b8b4
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/DataTriggerOptions.cs
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents data trigger options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents data trigger options.
+    /// Представляет параметры триггера на данные.
+    /// 
+    [Serializable]
+    internal abstract class DataTriggerOptions : TriggerOptions
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public DataTriggerOptions()
+            : base()
+        {
+            SingleQuery = false;
+        }
+
+
+        /// 
+        /// Gets or sets a value indicating whether to execute a single SQL query according to the trigger.
+        /// 
+        public bool SingleQuery { get; set; }
+
+
+        /// 
+        /// Loads the options from the XML node.
+        /// 
+        public override void LoadFromXml(XmlElement xmlElem)
+        {
+            base.LoadFromXml(xmlElem);
+            SingleQuery = xmlElem.GetChildAsBool("SingleQuery");
+        }
+
+        /// 
+        /// Saves the options into the XML node.
+        /// 
+        public override void SaveToXml(XmlElement xmlElem)
+        {
+            base.SaveToXml(xmlElem);
+            xmlElem.AppendElem("SingleQuery", SingleQuery);
+        }
+
+        /// 
+        /// Gets the names of the available query parameters.
+        /// 
+        public override List GetParamNames()
+        {
+            List paramNames = new List { "dateTime" };
+            paramNames.Add("kpNum");
+
+            if (SingleQuery)
+            {
+                foreach (int cnlNum in CnlNums)
+                {
+                    string cnlNumStr = cnlNum.ToString();
+                    paramNames.Add("val" + cnlNumStr);
+                    paramNames.Add("stat" + cnlNumStr);
+                }
+            }
+            else
+            {
+                paramNames.Add("cnlNum");
+                paramNames.Add("val");
+                paramNames.Add("stat");
+            }
+
+            return paramNames;
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/EventTriggerOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/EventTriggerOptions.cs
new file mode 100644
index 000000000..8b2c901e4
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/EventTriggerOptions.cs
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents event trigger options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents event trigger options.
+    /// Представляет параметры триггера на событие.
+    /// 
+    [Serializable]
+    internal class EventTriggerOptions : TriggerOptions
+    {
+        /// 
+        /// Gets the trigger type name.
+        /// 
+        public override string TriggerType => "EventTrigger";
+
+        /// 
+        /// Gets the names of the available query parameters.
+        /// 
+        public override List GetParamNames()
+        {
+            return new List
+            { 
+                "dateTime",
+                "objNum",
+                "kpNum",
+                "paramID",
+                "cnlNum",
+                "oldCnlVal",
+                "oldCnlStat",
+                "newCnlVal",
+                "newCnlStat",
+                "checked",
+                "userID",
+                "descr",
+                "data"
+            };
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ExportTargetConfig.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ExportTargetConfig.cs
new file mode 100644
index 000000000..183227e9e
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ExportTargetConfig.cs
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents an export target configuration
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Config;
+using System;
+using System.Collections;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents an export target configuration.
+    /// Представляет конфигурацию цели экспорта.
+    /// 
+    [Serializable]
+    internal class ExportTargetConfig : ITreeNode, IComparable
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ExportTargetConfig()
+        {
+            GeneralOptions = new GeneralOptions();
+            ConnectionOptions = new DbConnectionOptions();
+            Triggers = new TriggerOptionList { Parent = this };
+            ArcUploadOptions = new ArcUploadOptions();
+            Parent = null;
+        }
+
+
+        /// 
+        /// Gets the general options.
+        /// 
+        public GeneralOptions GeneralOptions { get; private set; }
+
+        /// 
+        /// Gets the database connection options.
+        /// 
+        public DbConnectionOptions ConnectionOptions { get; private set; }
+
+        /// 
+        /// Gets the configuration of the triggers.
+        /// 
+        public TriggerOptionList Triggers { get; }
+
+        /// 
+        /// Gets the archive upload options.
+        /// 
+        public ArcUploadOptions ArcUploadOptions { get; private set; }
+
+        /// 
+        /// Gets or sets the parent node.
+        /// 
+        public ITreeNode Parent { get; set; }
+
+        /// 
+        /// Get a list of child nodes.
+        /// 
+        public IList Children
+        {
+            get
+            {
+                return Triggers;
+            }
+        }
+
+
+        /// 
+        /// Loads the configuration from the XML node.
+        /// 
+        public void LoadFromXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException("xmlElem");
+
+            if (xmlElem.SelectSingleNode("GeneralOptions") is XmlNode generalOptionsNode)
+                GeneralOptions.LoadFromXml(generalOptionsNode);
+
+            if (xmlElem.SelectSingleNode("ConnectionOptions") is XmlNode connectionOptionsNode)
+                ConnectionOptions.LoadFromXml(connectionOptionsNode);
+
+            if (xmlElem.SelectSingleNode("Triggers") is XmlNode triggersNode)
+                Triggers.LoadFromXml(triggersNode);
+
+            if (xmlElem.SelectSingleNode("ArcUploadOptions") is XmlElement arcUploadOptionsElem)
+                ArcUploadOptions.LoadFromXml(arcUploadOptionsElem);
+        }
+
+        /// 
+        /// Saves the configuration into the XML node.
+        /// 
+        public void SaveToXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException("xmlElem");
+
+            GeneralOptions.SaveToXml(xmlElem.AppendElem("GeneralOptions"));
+            ConnectionOptions.SaveToXml(xmlElem.AppendElem("ConnectionOptions"));
+            Triggers.SaveToXml(xmlElem.AppendElem("Triggers"));
+            ArcUploadOptions.SaveToXml(xmlElem.AppendElem("ArcUploadOptions"));
+        }
+
+        /// 
+        /// Compares the current instance with another object of the same type.
+        /// 
+        /// Required for the ModConfig.Validate method.
+        public int CompareTo(ExportTargetConfig other)
+        {
+            return GeneralOptions.ID.CompareTo(other.GeneralOptions.ID);
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/GeneralOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/GeneralOptions.cs
new file mode 100644
index 000000000..fce7ba1a2
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/GeneralOptions.cs
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents general export target options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents general export target options.
+    /// Представляет основные параметры цели экспорта.
+    /// 
+    [Serializable]
+    internal class GeneralOptions
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public GeneralOptions()
+        {
+            Active = true;
+            ID = 0;
+            Name = "";
+            MaxQueueSize = 1000;
+            DataLifetime = 3600;
+            OutCnlNum = 0;
+        }
+
+
+        /// 
+        /// Gets or sets a value indicating whether the export target is active.
+        /// 
+        public bool Active { get; set; }
+
+        /// 
+        /// Gets or sets the export target ID.
+        /// 
+        public int ID { get; set; }
+
+        /// 
+        /// Gets or sets the export target name.
+        /// 
+        public string Name { get; set; }
+
+        /// 
+        /// Gets or sets the maximum queue size.
+        /// 
+        public int MaxQueueSize { get; set; }
+
+        /// 
+        /// Gets or sets the data lifetime in the queue, in seconds.
+        /// 
+        public int DataLifetime { get; set; }
+
+        /// 
+        /// Gets or sets the output channel number to control the export target.
+        /// 
+        public int OutCnlNum { get; set; }
+
+
+        /// 
+        /// Loads the options from the XML node.
+        /// 
+        public void LoadFromXml(XmlNode xmlNode)
+        {
+            if (xmlNode == null)
+                throw new ArgumentNullException("xmlNode");
+
+            Active = xmlNode.GetChildAsBool("Active");
+            ID = xmlNode.GetChildAsInt("ID");
+            Name = xmlNode.GetChildAsString("Name");
+            MaxQueueSize = xmlNode.GetChildAsInt("MaxQueueSize");
+            DataLifetime = xmlNode.GetChildAsInt("DataLifetime");
+            OutCnlNum = xmlNode.GetChildAsInt("OutCnlNum");
+        }
+
+        /// 
+        /// Saves the options into the XML node.
+        /// 
+        public void SaveToXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException("xmlElem");
+
+            xmlElem.AppendElem("Active", Active);
+            xmlElem.AppendElem("ID", ID);
+            xmlElem.AppendElem("Name", Name);
+            xmlElem.AppendElem("MaxQueueSize", MaxQueueSize);
+            xmlElem.AppendElem("DataLifetime", DataLifetime);
+            xmlElem.AppendElem("OutCnlNum", OutCnlNum);
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ModConfig.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ModConfig.cs
new file mode 100644
index 000000000..746d432a1
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/ModConfig.cs
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a module configuration
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2015
+ * Modified : 2021
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents a module configuration.
+    /// Представляет конфигурацию модуля.
+    /// 
+    [Serializable]
+    internal class ModConfig : ITreeNode
+    {
+        /// 
+        /// The configuration file name.
+        /// 
+        public const string ConfigFileName = "ModDbExport.xml";
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ModConfig()
+        {
+            SetToDefault();
+        }
+
+
+        /// 
+        /// Gets the configuration of the export targets.
+        /// 
+        public List ExportTargets { get; private set; }
+
+        /// 
+        /// Gets or sets the parent node.
+        /// 
+        ITreeNode ITreeNode.Parent
+        {
+            get
+            {
+                return null;
+            }
+            set
+            {
+                throw new InvalidOperationException();
+            }
+        }
+
+        /// 
+        /// Get a list of child nodes.
+        /// 
+        IList ITreeNode.Children
+        {
+            get
+            {
+                return ExportTargets;
+            }
+        }
+
+
+        /// 
+        /// Sets the default values.
+        /// 
+        private void SetToDefault()
+        {
+            ExportTargets = new List();
+        }
+
+        /// 
+        /// Loads the configuration from the specified file.
+        /// 
+        public bool Load(string fileName, out string errMsg)
+        {
+            try
+            {
+                SetToDefault();
+
+                if (!File.Exists(fileName))
+                    throw new FileNotFoundException(string.Format(CommonPhrases.NamedFileNotFound, fileName));
+
+                XmlDocument xmlDoc = new XmlDocument();
+                xmlDoc.Load(fileName);
+
+                foreach (XmlElement exportTargetElem in xmlDoc.DocumentElement.SelectNodes("ExportTarget"))
+                {
+                    ExportTargetConfig exportTargetConfig = new ExportTargetConfig() { Parent = this };
+                    exportTargetConfig.LoadFromXml(exportTargetElem);
+                    ExportTargets.Add(exportTargetConfig);
+                }
+
+                errMsg = "";
+                return true;
+            }
+            catch (Exception ex)
+            {
+                errMsg = ModPhrases.LoadModSettingsError + ": " + ex.Message;
+                return false;
+            }
+        }
+
+        /// 
+        /// Saves the configuration to the specified file.
+        /// 
+        public bool Save(string fileName, out string errMsg)
+        {
+            try
+            {
+                XmlDocument xmlDoc = new XmlDocument();
+                XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
+                xmlDoc.AppendChild(xmlDecl);
+
+                XmlElement rootElem = xmlDoc.CreateElement("ModDbExport");
+                xmlDoc.AppendChild(rootElem);
+
+                foreach (ExportTargetConfig exportTargetConfig in ExportTargets)
+                {
+                    exportTargetConfig.SaveToXml(rootElem.AppendElem("ExportTarget"));
+                }
+
+                xmlDoc.Save(fileName);
+                errMsg = "";
+                return true;
+            }
+            catch (Exception ex)
+            {
+                errMsg = ModPhrases.SaveModSettingsError + ": " + ex.Message;
+                return false;
+            }
+        }
+
+        /// 
+        /// Briefly validates the configuration.
+        /// 
+        public bool Validate(out List activeExportConfigs, out string errMsg)
+        {
+            activeExportConfigs = new List(ExportTargets.Where(x => x.GeneralOptions.Active));
+
+            if (activeExportConfigs.Count <= 0)
+            {
+                errMsg = Localization.UseRussian ?
+                    "Отсутствуют активные цели экспорта." :
+                    "No active export targets.";
+                return false;
+            }
+            else if (ExportTargets.Distinct().Count() < ExportTargets.Count)
+            {
+                errMsg = Localization.UseRussian ?
+                    "Дублируются идентификаторы целей экспорта." :
+                    "Export target IDs are duplicated.";
+                return false;
+            }
+            else
+            {
+                errMsg = "";
+                return true;
+            }
+        }
+
+        /// 
+        /// Clones the module configuration.
+        /// 
+        public ModConfig Clone()
+        {
+            return ScadaUtils.DeepClone(this, new SerializationBinder(Assembly.GetExecutingAssembly()));
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/TriggerOptionList.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/TriggerOptionList.cs
new file mode 100644
index 000000000..4bb396df0
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/TriggerOptionList.cs
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a list of trigger options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents a list of trigger options.
+    /// Представляет список параметров триггера.
+    /// 
+    [Serializable]
+    internal class TriggerOptionList : List, ITreeNode
+    {
+        /// 
+        /// Gets or sets the parent node.
+        /// 
+        public ITreeNode Parent { get; set; }
+
+        /// 
+        /// Get a list of child nodes.
+        /// 
+        public IList Children
+        {
+            get
+            {
+                return this;
+            }
+        }
+
+
+        /// 
+        /// Loads the options from the XML node.
+        /// 
+        public void LoadFromXml(XmlNode xmlNode)
+        {
+            if (xmlNode == null)
+                throw new ArgumentNullException(nameof(xmlNode));
+
+            foreach (XmlElement triggerElem in xmlNode.SelectNodes("Trigger"))
+            {
+                TriggerOptions triggerOptions = null;
+                string triggerType = triggerElem.GetAttrAsString("type").ToLowerInvariant();
+
+                if (triggerType == "curdatatrigger")
+                    triggerOptions = new CurDataTriggerOptions();
+                else if (triggerType == "arcdatatrigger")
+                    triggerOptions = new ArcDataTriggerOptions();
+                else if (triggerType == "eventtrigger")
+                    triggerOptions = new EventTriggerOptions();
+
+                if (triggerOptions != null)
+                {
+                    triggerOptions.Parent = this;
+                    triggerOptions.LoadFromXml(triggerElem);
+                    Add(triggerOptions);
+                }
+            }
+        }
+
+        /// 
+        /// Saves the options into the XML node.
+        /// 
+        public void SaveToXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException(nameof(xmlElem));
+
+            foreach (TriggerOptions triggerOptions in this)
+            {
+                triggerOptions.SaveToXml(xmlElem.AppendElem("Trigger"));
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Config/TriggerOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/TriggerOptions.cs
new file mode 100644
index 000000000..c4535871c
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Config/TriggerOptions.cs
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents trigger options
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Scada.Server.Modules.DbExport.Config
+{
+    /// 
+    /// Represents trigger options.
+    /// Представляет параметры триггера.
+    /// 
+    [Serializable]
+    internal abstract class TriggerOptions : ITreeNode
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public TriggerOptions()
+        {
+            Active = true;
+            Name = "";
+            CnlNums = new List();
+            DeviceNums = new List();
+            Query = "";
+            Parent = null;
+        }
+
+
+        /// 
+        /// Gets or sets a value indicating whether the trigger is active.
+        /// 
+        public bool Active { get; set; }
+
+        /// 
+        /// Gets or sets the trigger name.
+        /// 
+        public string Name { get; set; }
+
+        /// 
+        /// Gets the trigger type name.
+        /// 
+        public abstract string TriggerType { get; }
+
+        /// 
+        /// Gets the input channel numbers.
+        /// 
+        public List CnlNums { get; private set; }
+
+        /// 
+        /// Gets the device numbers.
+        /// 
+        public List DeviceNums { get; private set; }
+
+        /// 
+        /// Gets or sets the SQL query that is called when the trigger is fired.
+        /// 
+        public string Query { get; set; }
+
+        /// 
+        /// Gets or sets the parent node.
+        /// 
+        public ITreeNode Parent { get; set; }
+
+        /// 
+        /// Get a list of child nodes.
+        /// 
+        public IList Children
+        {
+            get
+            {
+                return null;
+            }
+        }
+
+
+        /// 
+        /// Loads the options from the XML node.
+        /// 
+        public virtual void LoadFromXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException(nameof(xmlElem));
+
+            Active = xmlElem.GetAttrAsBool("active", true);
+            Name = xmlElem.GetAttrAsString("name");
+            CnlNums.AddRange(RangeUtils.StrToRange(xmlElem.GetChildAsString("CnlNums"), true, true));
+            DeviceNums.AddRange(RangeUtils.StrToRange(xmlElem.GetChildAsString("DeviceNums"), true, true));
+            Query = xmlElem.GetChildAsString("Query");
+        }
+
+        /// 
+        /// Saves the options into the XML node.
+        /// 
+        public virtual void SaveToXml(XmlElement xmlElem)
+        {
+            if (xmlElem == null)
+                throw new ArgumentNullException(nameof(xmlElem));
+
+            xmlElem.SetAttribute("active", Active);
+            xmlElem.SetAttribute("name", Name);
+            xmlElem.SetAttribute("type", TriggerType);
+            xmlElem.AppendElem("CnlNums", RangeUtils.RangeToStr(CnlNums));
+            xmlElem.AppendElem("DeviceNums", RangeUtils.RangeToStr(DeviceNums));
+            xmlElem.AppendElem("Query", Query);
+        }
+
+        /// 
+        /// Gets the names of the available query parameters.
+        /// 
+        public virtual List GetParamNames()
+        {
+            return new List();
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/EntityMap.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/EntityMap.cs
new file mode 100644
index 000000000..cbda8c1c7
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/EntityMap.cs
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a map of channels and devices
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Data.Entities;
+using Scada.Data.Tables;
+using System.Collections.Generic;
+
+namespace Scada.Server.Modules.DbExport
+{
+    /// 
+    /// Represents a map of channels and devices.
+    /// Представляет карту каналов и устройств.
+    /// 
+    internal class EntityMap
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public EntityMap()
+        {
+            DeviceByCnlNum = new Dictionary();
+            CnlNumGroups = new List();
+        }
+
+
+        /// 
+        /// Gets the device numbers accessed by channel number.
+        /// 
+        public Dictionary DeviceByCnlNum { get; }
+
+        /// 
+        /// Gets the groups of input channel numbers split by device.
+        /// 
+        public List CnlNumGroups { get; }
+
+
+        /// 
+        /// Initializes the entity map.
+        /// 
+        public void Init(BaseTable inCnlTable)
+        {
+            SortedDictionary> cnlsByDevice = new SortedDictionary>();
+
+            foreach (InCnl inCnl in inCnlTable.EnumerateItems())
+            {
+                int deviceNum = inCnl.KPNum ?? 0;
+
+                if (deviceNum > 0)
+                    DeviceByCnlNum[inCnl.CnlNum] = deviceNum;
+
+                if (!cnlsByDevice.TryGetValue(deviceNum, out List cnlNums))
+                {
+                    cnlNums = new List();
+                    cnlsByDevice.Add(deviceNum, cnlNums);
+                }
+
+                cnlNums.Add(inCnl.CnlNum);
+            }
+
+            foreach (List cnlNums in cnlsByDevice.Values)
+            {
+                CnlNumGroups.Add(cnlNums.ToArray());
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Exporter.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Exporter.cs
new file mode 100644
index 000000000..63506e739
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Exporter.cs
@@ -0,0 +1,1206 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Exports data to a one target
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2015
+ * Modified : 2021
+ */
+
+using Scada.Data.Models;
+using Scada.Data.Tables;
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+using Scada.Server.Modules.DbExport.Triggers;
+using System;
+using System.Collections.Generic;
+using System.Data.Common;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using Utils;
+
+namespace Scada.Server.Modules.DbExport
+{
+    /// 
+    /// Exports data to a one target.
+    /// Экспортирует данные в одну базу данных.
+    /// 
+    internal class Exporter
+    {
+        /// 
+        /// Represents queue statistics.
+        /// 
+        private class QueueStats
+        {
+            public bool ErrorState { get; set; }
+            public int ExportedItems { get; set; }
+            public int SkippedItems { get; set; }
+        }
+
+        /// 
+        /// Specifies the connection statuses.
+        /// 
+        private enum ConnStatus { Undefined, Normal, Error }
+
+        /// 
+        /// The prefix of log files and state file.
+        /// 
+        private const string FilePrefix = "ModDbExport";
+        /// 
+        /// The minimum queue size.
+        /// 
+        private const int MinQueueSize = 100;
+        /// 
+        /// The number of queue items transferred in a single loop iteration.
+        /// 
+        private const int BundleSize = 100;
+        /// 
+        /// The delay in case of a database error, in milliseconds.
+        /// 
+        private const int ErrorDelay = 1000;
+        /// 
+        /// The period of writing information.
+        /// 
+        private static readonly TimeSpan WriteInfoPeriod = TimeSpan.FromMilliseconds(1000);
+        /// 
+        /// The period of checking the archive for changes.
+        /// 
+        private static readonly TimeSpan CheckArcPeriod = TimeSpan.FromSeconds(10);
+        /// 
+        /// The connection status names in English.
+        /// 
+        private static readonly string[] ConnStatusNamesEn = { "Undefined", "Normal", "Error" };
+        /// 
+        /// The connection status names in Russian.
+        /// 
+        private static readonly string[] ConnStatusNamesRu = { "не определено", "норма", "ошибка" };
+
+        private readonly ExportTargetConfig exporterConfig;   // the exporter configuration
+        private readonly EntityMap entityMap;                 // the map of channels and devices
+        private readonly IServerData serverData;              // provides access to server data
+        private readonly string arcDir;                       // the DAT archive directory
+        private readonly TimeSpan dataLifetime;               // the data lifetime in the queue
+        private readonly Log log;                             // the exporter log
+        private readonly string infoFileName;                 // the information file name
+        private readonly string stateFileName;                // the state file name
+        private readonly string exporterTitle;                // the exporter ID and name
+        private readonly DataSource dataSource;               // provides access to the DB
+        private readonly ClassifiedTriggers triggers;         // the triggers separated by classes
+
+        private Thread thread;            // the exporter thread
+        private volatile bool terminated; // it is required to stop the thread
+        private ConnStatus connStatus;    // the connection status
+
+        private int maxQueueSize;                                    // the maximum queue size
+        private Queue> curDataQueue;  // the queue of current data
+        private Queue> arcDataQueue;  // the queue of archive data
+        private Queue> eventQueue;  // the queue of events
+        private QueueStats curDataStats;        // the statistics of current data queue
+        private QueueStats arcDataStats;        // the statistics of archive data queue
+        private QueueStats eventStats;          // the statistics of event queue
+
+        private ArcUploadState arcUploadState;  // the state of uploading archives
+        private ArcUploadState taskUploadState; // the state of uploading archives according to the task
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public Exporter(ExportTargetConfig exporterConfig, EntityMap entityMap, 
+            IServerData serverData, AppDirs appDirs, string arcDir)
+        {
+            this.exporterConfig = exporterConfig ?? throw new ArgumentNullException(nameof(exporterConfig));
+            this.entityMap = entityMap ?? throw new ArgumentNullException(nameof(entityMap));
+            this.serverData = serverData ?? throw new ArgumentNullException(nameof(serverData));
+            this.arcDir = arcDir ?? throw new ArgumentNullException(nameof(arcDir));
+
+            GeneralOptions generalOptions = exporterConfig.GeneralOptions;
+            dataLifetime = TimeSpan.FromSeconds(generalOptions.DataLifetime);
+            string prefix = FilePrefix + "_" + generalOptions.ID.ToString("D3");
+            log = new Log(Log.Formats.Simple) { FileName = Path.Combine(appDirs.LogDir, prefix + ".log") };
+            infoFileName = Path.Combine(appDirs.LogDir, prefix + ".txt");
+            stateFileName = Path.Combine(appDirs.StorageDir, prefix + "_State.xml");
+            exporterTitle = string.Format("[{0}] {1}", generalOptions.ID, generalOptions.Name);
+            dataSource = DataSourceFactory.GetDataSource(exporterConfig.ConnectionOptions);
+            triggers = new ClassifiedTriggers(exporterConfig.Triggers, dataSource);
+
+            thread = null;
+            terminated = false;
+            connStatus = ConnStatus.Undefined;
+
+            CreateQueues();
+            InitArcUploading();
+        }
+
+
+        /// 
+        /// Creates the data queues.
+        /// 
+        private void CreateQueues()
+        {
+            maxQueueSize = Math.Max(exporterConfig.GeneralOptions.MaxQueueSize, MinQueueSize);
+
+            if (triggers.CurDataTriggers.Count > 0)
+            {
+                curDataQueue = new Queue>(maxQueueSize);
+                curDataStats = new QueueStats();
+            }
+            else
+            {
+                curDataQueue = null;
+                curDataStats = null;
+            }
+
+            if (triggers.ArcDataTriggers.Count > 0)
+            {
+                arcDataQueue = new Queue>(maxQueueSize);
+                arcDataStats = new QueueStats();
+            }
+            else
+            {
+                arcDataQueue = null;
+                arcDataStats = null;
+            }
+
+            if (triggers.EventTriggers.Count > 0)
+            {
+                eventQueue = new Queue>(maxQueueSize);
+                eventStats = new QueueStats();
+            }
+            else
+            {
+                eventQueue = null;
+                eventStats = null;
+            }
+        }
+
+        /// 
+        /// Initializes objects required for uploading archives.
+        /// 
+        private void InitArcUploading()
+        {
+            arcUploadState = exporterConfig.ArcUploadOptions.Enabled ? new ArcUploadState() : null;
+            taskUploadState = null;
+        }
+
+        /// 
+        /// Exporter cycle running in a separate thread.
+        /// 
+        private void Execute()
+        {
+            try
+            {
+                DateTime utcNowDT = DateTime.UtcNow;
+                DateTime arcCheckDT = DateTime.MinValue;
+                DateTime writeInfoDT = utcNowDT;
+                WriteInfo();
+                LoadState();
+
+                while (!terminated)
+                {
+                    // export data
+                    try
+                    {
+                        if (Connect())
+                        {
+                            ExportCurData();
+                            ExportArcData();
+                            ExportEvents();
+                        }
+                    }
+                    finally
+                    {
+                        Disconnect();
+                    }
+
+                    // upload archive
+                    if (exporterConfig.ArcUploadOptions.Enabled || taskUploadState != null)
+                    {
+                        utcNowDT = DateTime.UtcNow;
+                        if (utcNowDT - arcCheckDT > CheckArcPeriod)
+                        {
+                            arcCheckDT = utcNowDT;
+                            UploadArcData();
+                        }
+                    }
+
+                    // write information
+                    utcNowDT = DateTime.UtcNow;
+                    if (utcNowDT - writeInfoDT > WriteInfoPeriod)
+                    {
+                        writeInfoDT = utcNowDT;
+                        WriteInfo();
+                    }
+
+                    Thread.Sleep(ScadaUtils.ThreadDelay);
+                }
+            }
+            finally
+            {
+                WriteInfo();
+            }
+        }
+
+        /// 
+        /// Connects to the database.
+        /// 
+        private bool Connect()
+        {
+            try
+            {
+                dataSource.Connect();
+                connStatus = ConnStatus.Normal;
+                return true;
+            }
+            catch (Exception ex)
+            {
+                connStatus = ConnStatus.Error;
+                log.WriteException(ex, Localization.UseRussian ? 
+                    "Ошибка при соединении с БД" :
+                    "Error connecting to DB");
+                Thread.Sleep(ErrorDelay);
+                return false;
+            }
+        }
+
+        /// 
+        /// Disconnects from the database.
+        /// 
+        private void Disconnect()
+        {
+            try
+            {
+                dataSource.Disconnect();
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ? 
+                    "Ошибка при разъединении с БД" :
+                    "Error disconnecting from DB");
+            }
+        }
+
+        /// 
+        /// Exports current data.
+        /// 
+        private void ExportCurData()
+        {
+            if (curDataQueue == null)
+                return;
+
+            DbTransaction trans = null;
+
+            try
+            {
+                trans = dataSource.Connection.BeginTransaction();
+
+                for (int i = 0; i < BundleSize; i++)
+                {
+                    // retrieve a snapshot from the queue
+                    QueueItem queueItem;
+                    SrezTableLight.Srez snapshot;
+
+                    lock (curDataQueue)
+                    {
+                        if (curDataQueue.Count > 0)
+                        {
+                            queueItem = curDataQueue.Dequeue();
+                            snapshot = queueItem.Value;
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+
+                    // export the snapshot
+                    if (DateTime.UtcNow - queueItem.CreationTime > dataLifetime)
+                    {
+                        curDataStats.SkippedItems++;
+                        log.WriteError(string.Format(Localization.UseRussian ?
+                            "Устаревший текущий срез за {0} не экспортирован" :
+                            "The outdated current snapshot for {0} is not exported",
+                            snapshot.DateTime.ToLocalizedString()));
+                    }
+                    else if (ExportSnapshot(snapshot, trans, triggers.CurDataTriggers))
+                    {
+                        curDataStats.ExportedItems++;
+                        curDataStats.ErrorState = false;
+                    }
+                    else
+                    {
+                        // return the unsent snapshot to the queue
+                        lock (curDataQueue)
+                        {
+                            curDataQueue.Enqueue(queueItem);
+                        }
+
+                        curDataStats.ErrorState = true;
+                        Thread.Sleep(ErrorDelay);
+                        break;
+                    }
+                }
+
+                trans.Commit();
+            }
+            catch (Exception ex)
+            {
+                dataSource.SafeRollback(trans);
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при экспорте текущих данных" :
+                    "Error export current data");
+            }
+        }
+
+        /// 
+        /// Exports archive data.
+        /// 
+        private void ExportArcData()
+        {
+            if (arcDataQueue == null)
+                return;
+
+            DbTransaction trans = null;
+
+            try
+            {
+                trans = dataSource.Connection.BeginTransaction();
+
+                for (int i = 0; i < BundleSize; i++)
+                {
+                    // retrieve a snapshot from the queue
+                    QueueItem queueItem;
+                    SrezTableLight.Srez snapshot;
+
+                    lock (arcDataQueue)
+                    {
+                        if (arcDataQueue.Count > 0)
+                        {
+                            queueItem = arcDataQueue.Dequeue();
+                            snapshot = queueItem.Value;
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+
+                    // export the snapshot
+                    if (DateTime.UtcNow - queueItem.CreationTime > dataLifetime)
+                    {
+                        arcDataStats.SkippedItems++;
+                        log.WriteError(string.Format(Localization.UseRussian ?
+                            "Устаревший архивный срез за {0} не экспортирован" :
+                            "The outdated archive snapshot for {0} is not exported",
+                            snapshot.DateTime.ToLocalizedString()));
+                    }
+                    else if (ExportSnapshot(snapshot, trans, triggers.ArcDataTriggers))
+                    {
+                        arcDataStats.ExportedItems++;
+                        arcDataStats.ErrorState = false;
+
+                    }
+                    else
+                    {
+                        // return the unsent snapshot to the queue
+                        lock (arcDataQueue)
+                        {
+                            arcDataQueue.Enqueue(queueItem);
+                        }
+
+                        arcDataStats.ErrorState = true;
+                        Thread.Sleep(ErrorDelay);
+                        break;
+                    }
+
+                    // confirm sending to allow new data to be queued
+                    if (arcDataQueue.Count == 0)
+                    {
+                        if (arcUploadState != null && arcUploadState.ConfirmSending())
+                            SaveState();
+
+                        taskUploadState?.ConfirmSending();
+                    }
+                }
+
+                trans.Commit();
+            }
+            catch (Exception ex)
+            {
+                dataSource.SafeRollback(trans);
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при экспорте архивных данных" :
+                    "Error export archive data");
+            }
+        }
+
+        /// 
+        /// Exports events.
+        /// 
+        private void ExportEvents()
+        {
+            if (eventQueue == null)
+                return;
+
+            DbTransaction trans = null;
+
+            try
+            {
+                trans = dataSource.Connection.BeginTransaction();
+
+                for (int i = 0; i < BundleSize; i++)
+                {
+                    // retrieve an event from the queue
+                    QueueItem queueItem;
+                    EventTableLight.Event ev;
+
+                    lock (eventQueue)
+                    {
+                        if (eventQueue.Count > 0)
+                        {
+                            queueItem = eventQueue.Dequeue();
+                            ev = queueItem.Value;
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+
+                    // export the event
+                    if (DateTime.UtcNow - queueItem.CreationTime > dataLifetime)
+                    {
+                        eventStats.SkippedItems++;
+                        log.WriteError(string.Format(Localization.UseRussian ?
+                            "Устаревшее событие за {0} не экспортировано" :
+                            "The outdated event for {0} is not exported",
+                            ev.DateTime.ToLocalizedString()));
+                    }
+                    else if (ExportEvent(ev, trans))
+                    {
+                        eventStats.ExportedItems++;
+                        eventStats.ErrorState = false;
+                    }
+                    else
+                    {
+                        // return the unsent event to the queue
+                        lock (eventQueue)
+                        {
+                            eventQueue.Enqueue(queueItem);
+                        }
+
+                        eventStats.ErrorState = true;
+                        Thread.Sleep(ErrorDelay);
+                        break;
+                    }
+                }
+
+                trans.Commit();
+            }
+            catch (Exception ex)
+            {
+                dataSource.SafeRollback(trans);
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при экспорте событий" :
+                    "Error export events");
+            }
+        }
+
+        /// 
+        /// Exports the specified snapshot.
+        /// 
+        private bool ExportSnapshot(SrezTableLight.Srez snapshot, DbTransaction trans, 
+            IEnumerable dataTriggers)
+        {
+            Trigger currentTrigger = null;
+
+            try
+            {
+                int firstCnlNum = snapshot.CnlNums.Length > 0 ? snapshot.CnlNums[0] : 0;
+                entityMap.DeviceByCnlNum.TryGetValue(firstCnlNum, out int deviceNum);
+
+                foreach (DataTrigger trigger in dataTriggers)
+                {
+                    currentTrigger = trigger;
+
+                    if ((trigger.CnlNums.Count == 0 || trigger.CnlNums.Overlaps(snapshot.CnlNums)) &&
+                        (trigger.DeviceNums.Count == 0 || trigger.DeviceNums.Contains(deviceNum)))
+                    {
+                        DbCommand cmd = trigger.Command;
+                        cmd.Transaction = trans;
+                        trigger.DateTimeParam.Value = snapshot.DateTime;
+                        trigger.KpNumParam.Value = deviceNum;
+
+                        if (trigger.DataTriggerOptions.SingleQuery)
+                        {
+                            if (trigger.CnlNums.Count > 0)
+                            {
+                                foreach (int cnlNum in trigger.CnlNums)
+                                {
+                                    SrezTableLight.CnlData cnlData = snapshot.GetCnlData(cnlNum);
+                                    trigger.SetValParam(cnlNum, cnlData.Val);
+                                    trigger.SetStatParam(cnlNum, cnlData.Stat);
+                                }
+
+                                cmd.ExecuteNonQuery();
+                            }
+                        }
+                        else
+                        {
+                            void ExportDataPoint(int cnlNum)
+                            {
+                                SrezTableLight.CnlData cnlData = snapshot.GetCnlData(cnlNum);
+                                trigger.CnlNumParam.Value = cnlNum;
+                                trigger.ValParam.Value = cnlData.Val;
+                                trigger.StatParam.Value = cnlData.Stat;
+                                cmd.ExecuteNonQuery();
+                            }
+
+                            if (trigger.CnlNums.Count > 0)
+                            {
+                                foreach (int cnlNum in snapshot.CnlNums)
+                                {
+                                    if (trigger.CnlNums.Contains(cnlNum))
+                                        ExportDataPoint(cnlNum);
+                                }
+                            }
+                            else
+                            {
+                                foreach (int cnlNum in snapshot.CnlNums)
+                                {
+                                    ExportDataPoint(cnlNum);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при экспорте среза по триггеру \"{0}\"" :
+                    "Error export snapshot by the trigger \"{0}\"",
+                    currentTrigger?.Options?.Name ?? "");
+                return false;
+            }
+        }
+
+        /// 
+        /// Exports the specified event.
+        /// 
+        private bool ExportEvent(EventTableLight.Event ev, DbTransaction trans)
+        {
+            Trigger currentTrigger = null;
+
+            try
+            {
+                foreach (EventTrigger trigger in triggers.EventTriggers)
+                {
+                    currentTrigger = trigger;
+
+                    if ((trigger.CnlNums.Count == 0 || trigger.CnlNums.Contains(ev.CnlNum)) &&
+                        (trigger.DeviceNums.Count == 0 || trigger.DeviceNums.Contains(ev.KPNum)))
+                    {
+                        DbCommand cmd = trigger.Command;
+                        cmd.Transaction = trans;
+                        dataSource.SetParam(cmd, "dateTime", ev.DateTime);
+                        dataSource.SetParam(cmd, "objNum", ev.ObjNum);
+                        dataSource.SetParam(cmd, "kpNum", ev.KPNum);
+                        dataSource.SetParam(cmd, "paramID", ev.ParamID);
+                        dataSource.SetParam(cmd, "cnlNum", ev.CnlNum);
+                        dataSource.SetParam(cmd, "oldCnlVal", ev.OldCnlVal);
+                        dataSource.SetParam(cmd, "oldCnlStat", ev.OldCnlStat);
+                        dataSource.SetParam(cmd, "newCnlVal", ev.NewCnlVal);
+                        dataSource.SetParam(cmd, "newCnlStat", ev.NewCnlStat);
+                        dataSource.SetParam(cmd, "checked", ev.Checked);
+                        dataSource.SetParam(cmd, "userID", ev.UserID);
+                        dataSource.SetParam(cmd, "descr", ev.Descr);
+                        dataSource.SetParam(cmd, "data", ev.Data);
+                        cmd.ExecuteNonQuery();
+                    }
+                }
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при экспорте события по триггеру \"{0}\"" :
+                    "Error export event by the trigger \"{0}\"", 
+                    currentTrigger?.Options?.Name ?? "");
+                return false;
+            }
+        }
+
+        /// 
+        /// Makes and enqueues snapshots of archive data.
+        /// 
+        private void MakeArcSnapshots(DateTime dateTime)
+        {
+            foreach (int[] cnlNums in entityMap.CnlNumGroups)
+            {
+                EnqueueArcData(serverData.GetSnapshot(dateTime, exporterConfig.ArcUploadOptions.SnapshotType, cnlNums));
+            }
+        }
+
+        /// 
+        /// Uploads archive data if possible.
+        /// 
+        private void UploadArcData()
+        {
+            ArcUploadState uploadState = taskUploadState ?? arcUploadState;
+            bool maxTimeReached = false;
+
+            if (uploadState.IsReady &&
+                serverData.GetAvailableSnapshots(uploadState.SnapshotDate, exporterConfig.ArcUploadOptions.SnapshotType) is
+                DateTime[] availableSnapshots)
+            {
+                int snapshotIndex = uploadState.SnapshotIndex;
+                int snapshotCount = availableSnapshots.Length;
+
+                if (snapshotCount > 0)
+                {
+                    if (uploadState.SentSnapshotDT < uploadState.SnapshotDate)
+                    {
+                        if (uploadState.MinSnapshotDT.Date == uploadState.SnapshotDate)
+                        {
+                            // find a snapshot to upload
+                            int index = Array.BinarySearch(availableSnapshots, uploadState.MinSnapshotDT);
+                            snapshotIndex = index >= 0 ? index : ~index;
+                        }
+                        else
+                        {
+                            // upload the first snapshot
+                            snapshotIndex = 0;
+                        }
+                    }
+                    else if (0 <= snapshotIndex && snapshotIndex < snapshotCount &&
+                        availableSnapshots[snapshotIndex] == uploadState.SentSnapshotDT)
+                    {
+                        // upload the next snapshot
+                        snapshotIndex++;
+                    }
+                    else
+                    {
+                        // correct the index
+                        int index = Array.BinarySearch(availableSnapshots, uploadState.SentSnapshotDT);
+                        snapshotIndex = index >= 0 ? index + 1 : ~index;
+                    }
+                }
+
+                if (0 <= snapshotIndex && snapshotIndex < snapshotCount)
+                {
+                    DateTime snapshotDT = availableSnapshots[snapshotIndex];
+
+                    if (snapshotDT <= uploadState.MaxSnapshotDT)
+                    {
+                        if (snapshotDT.AddMilliseconds(exporterConfig.ArcUploadOptions.Delay) <= DateTime.Now)
+                        {
+                            // upload the snapshot
+                            uploadState.IsReady = false;
+                            uploadState.SnapshotIndex = snapshotIndex;
+                            uploadState.QueuedSnapshotDT = snapshotDT;
+                            MakeArcSnapshots(snapshotDT);
+                        }
+                    }
+                    else
+                    {
+                        maxTimeReached = true;
+                    }
+                }
+                else if (uploadState.SnapshotDate < DateTime.Today)
+                {
+                    // go to the next day
+                    uploadState.SnapshotIndex = -1;
+                    uploadState.SnapshotDate = uploadState.SnapshotDate.AddDays(1.0);
+
+                    if (uploadState.SnapshotDate > uploadState.MaxSnapshotDT)
+                        maxTimeReached = true;
+                }
+                else
+                {
+                    // date is today and no snapshots to upload
+                    maxTimeReached = true;
+                }
+
+                if (maxTimeReached && taskUploadState != null)
+                {
+                    // stop the task
+                    taskUploadState = null;
+                }
+            }
+        }
+
+        /// 
+        /// Loads events from file and adds to the queue.
+        /// 
+        private void ExportEventsFromFile(DateTime minDT, DateTime maxDT)
+        {
+            if (minDT.Date != maxDT.Date)
+            {
+                log.WriteError(Localization.UseRussian ?
+                    "Временной диапазон событий должен быть в пределах одних суток" :
+                    "The time range of events must be within one day");
+                return;
+            }
+
+            string fileName = ServerUtils.BuildEvFileName(arcDir, minDT.Date);
+
+            if (!File.Exists(fileName))
+            {
+                log.WriteError(string.Format(CommonPhrases.NamedFileNotFound, fileName));
+                return;
+            }
+
+            try
+            {
+                EventTableLight eventTable = new EventTableLight();
+                EventAdapter eventAdapter = new EventAdapter { FileName = fileName };
+                eventAdapter.Fill(eventTable);
+
+                foreach (EventTableLight.Event ev in eventTable.AllEvents)
+                {
+                    if (minDT <= ev.DateTime && ev.DateTime <= maxDT)
+                        EnqueueEvent(ev);
+                }
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при загрузке событий из файла {0}" :
+                    "Error loading events from file {0}", fileName);
+            }
+        }
+
+        /// 
+        /// Writes the exporter information to the file.
+        /// 
+        private void WriteInfo()
+        {
+            try
+            {
+                // build text
+                StringBuilder sbInfo = new StringBuilder();
+
+                if (Localization.UseRussian)
+                {
+                    sbInfo
+                        .AppendLine("Состояние экспортёра")
+                        .AppendLine("--------------------")
+                        .Append("Наименование   : ").AppendLine(exporterTitle)
+                        .Append("Сервер БД      : ").AppendLine(exporterConfig.ConnectionOptions.Server)
+                        .Append("Соединение     : ").AppendLine(ConnStatusNamesRu[(int)connStatus])
+                        .AppendLine();
+
+                    void AppendQueueStatsRu(QueueStats queueStats, int? queueSize)
+                    {
+                        if (queueStats == null)
+                        {
+                            sbInfo.AppendLine("Очередь не используется");
+                        }
+                        else
+                        {
+                            sbInfo
+                                .Append("Состояние      : ").AppendLine(queueStats.ErrorState ? "ошибка" : "норма")
+                                .Append("В очереди      : ").Append(queueSize).Append(" из ").Append(maxQueueSize).AppendLine()
+                                .Append("Экспортировано : ").Append(queueStats.ExportedItems).AppendLine()
+                                .Append("Пропущено      : ").Append(queueStats.SkippedItems).AppendLine();
+                        }
+
+                        sbInfo.AppendLine();
+                    }
+
+                    sbInfo.AppendLine("Текущие данные");
+                    sbInfo.AppendLine("--------------");
+                    AppendQueueStatsRu(curDataStats, curDataQueue?.Count);
+
+                    sbInfo.AppendLine("Архивные данные");
+                    sbInfo.AppendLine("---------------");
+                    AppendQueueStatsRu(arcDataStats, arcDataQueue?.Count);
+
+                    sbInfo.AppendLine("События");
+                    sbInfo.AppendLine("-------");
+                    AppendQueueStatsRu(eventStats, eventQueue?.Count);
+
+                    sbInfo.AppendLine("Передача архивов");
+                    sbInfo.AppendLine("----------------");
+                    ArcUploadState.AppendInfo(arcUploadState, sbInfo);
+
+                    if (taskUploadState != null)
+                    {
+                        sbInfo.AppendLine("Передача архивов по заданию");
+                        sbInfo.AppendLine("---------------------------");
+                        taskUploadState.AppendInfo(sbInfo);
+                    }
+                }
+                else
+                {
+                    sbInfo
+                        .AppendLine("Exporter State")
+                        .AppendLine("--------------")
+                        .Append("Name       : ").AppendLine(exporterTitle)
+                        .Append("DB server  : ").AppendLine(exporterConfig.ConnectionOptions.Server)
+                        .Append("Connection : ").AppendLine(ConnStatusNamesEn[(int)connStatus])
+                        .AppendLine();
+
+                    void AppendQueueStatsEn(QueueStats queueStats, int? queueSize)
+                    {
+                        if (queueStats == null)
+                        {
+                            sbInfo.AppendLine("Queue is not in use");
+                        }
+                        else
+                        {
+                            sbInfo
+                                .Append("Status     : ").AppendLine(queueStats.ErrorState ? "Error" : "Normal")
+                                .Append("In queue   : ").Append(queueSize).Append(" of ").Append(maxQueueSize).AppendLine()
+                                .Append("Exported   : ").Append(queueStats.ExportedItems).AppendLine()
+                                .Append("Skipped    : ").Append(queueStats.SkippedItems).AppendLine();
+                        }
+
+                        sbInfo.AppendLine();
+                    }
+
+                    sbInfo.AppendLine("Current Data");
+                    sbInfo.AppendLine("------------");
+                    AppendQueueStatsEn(curDataStats, curDataQueue?.Count);
+
+                    sbInfo.AppendLine("Archive Data");
+                    sbInfo.AppendLine("------------");
+                    AppendQueueStatsEn(arcDataStats, arcDataQueue?.Count);
+
+                    sbInfo.AppendLine("Events");
+                    sbInfo.AppendLine("------");
+                    AppendQueueStatsEn(eventStats, eventQueue?.Count);
+
+                    sbInfo.AppendLine("Archive Uploading");
+                    sbInfo.AppendLine("-----------------");
+                    ArcUploadState.AppendInfo(arcUploadState, sbInfo);
+
+                    if (taskUploadState != null)
+                    {
+                        sbInfo.AppendLine("Archive Uploading by Task");
+                        sbInfo.AppendLine("-------------------------");
+                        taskUploadState.AppendInfo(sbInfo);
+                    }
+                }
+
+                // write to file
+                using (StreamWriter writer = new StreamWriter(infoFileName, false, Encoding.UTF8))
+                {
+                    writer.Write(sbInfo.ToString());
+                }
+            }
+            catch (ThreadAbortException)
+            {
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, ModPhrases.WriteInfoError);
+            }
+        }
+
+        /// 
+        /// Loads the export state.
+        /// 
+        private void LoadState()
+        {
+            try
+            {
+                if (File.Exists(stateFileName))
+                {
+                    XmlDocument xmlDoc = new XmlDocument();
+                    xmlDoc.Load(stateFileName);
+
+                    if (arcUploadState != null)
+                        arcUploadState.SentSnapshotDT = xmlDoc.DocumentElement.GetChildAsDateTime("SentSnapshotDT");
+
+                    log.WriteAction(Localization.UseRussian ?
+                        "Состояние экспорта загружено из файла" :
+                        "Export state loaded from file");
+                }
+                else
+                {
+                    log.WriteAction(Localization.UseRussian ?
+                        "Файл состояния экспорта отсутствует" :
+                        "Export state file is missing");
+                }
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при загрузке состояния экспорта" :
+                    "Error loading export state");
+            }
+            finally
+            {
+                arcUploadState?.InitSnapshotDate(exporterConfig.ArcUploadOptions.MaxAge);
+            }
+        }
+
+        /// 
+        /// Saves the exporter state.
+        /// 
+        private void SaveState()
+        {
+            try
+            {
+                XmlDocument xmlDoc = new XmlDocument();
+                XmlDeclaration xmlDecl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
+                xmlDoc.AppendChild(xmlDecl);
+
+                XmlElement rootElem = xmlDoc.CreateElement("ModDbExport_State");
+                xmlDoc.AppendChild(rootElem);
+
+                if (arcUploadState != null)
+                    rootElem.AppendElem("SentSnapshotDT", arcUploadState.SentSnapshotDT);
+
+                xmlDoc.Save(stateFileName);
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при сохранении состояния экспорта" :
+                    "Error saving export state");
+            }
+        }
+
+
+        /// 
+        /// Starts the exporter.
+        /// 
+        public void Start()
+        {
+            try
+            {
+                if (thread == null)
+                {
+                    log.WriteBreak();
+                    log.WriteAction(string.Format(Localization.UseRussian ?
+                        "Запуск экспортёра \"{0}\"" :
+                        "Start exporter \"{0}\"", exporterTitle));
+
+                    terminated = false;
+                    thread = new Thread(Execute);
+                    thread.Start();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при запуске работы экспортёра" :
+                    "Error starting exporter");
+            }
+
+        }
+
+        /// 
+        /// Stops the exporter.
+        /// 
+        public void Stop()
+        {
+            try
+            {
+                if (thread != null)
+                {
+                    terminated = true;
+
+                    if (thread.Join(ModLogic.WaitForStop))
+                    {
+                        log.WriteAction(string.Format(Localization.UseRussian ?
+                            "Экспортёр \"{0}\" остановлен" :
+                            "Exporter \"{0}\" is stopped", exporterTitle));
+                    }
+                    else
+                    {
+                        thread.Abort();
+                        log.WriteError(Localization.UseRussian ?
+                            "Работа экспортёра прервана" :
+                            "Exporter is aborted");
+                    }
+
+                    thread = null;
+                    log.WriteBreak();
+                }
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при остановке работы экспортёра" :
+                    "Error stop exporter");
+            }
+        }
+
+        /// 
+        /// Enqueues the current data for export.
+        /// 
+        public void EnqueueCurData(SrezTableLight.Srez snapshot)
+        {
+            if (snapshot == null)
+                throw new ArgumentNullException(nameof(snapshot));
+
+            if (curDataQueue != null)
+            {
+                lock (curDataQueue)
+                {
+                    if (curDataQueue.Count < maxQueueSize)
+                    {
+                        curDataQueue.Enqueue(new QueueItem(DateTime.UtcNow, snapshot));
+                    }
+                    else
+                    {
+                        curDataStats.SkippedItems++;
+                        log.WriteError(string.Format(Localization.UseRussian ?
+                            "Невозможно добавить текущие данные в очередь. Максимальный размер очереди {0} превышен" :
+                            "Unable to enqueue current data. The maximum size of the queue {0} is exceeded",
+                            maxQueueSize));
+                    }
+                }
+            }
+        }
+
+        /// 
+        /// Enqueues the archive data for export.
+        /// 
+        public void EnqueueArcData(SrezTableLight.Srez snapshot)
+        {
+            if (snapshot == null)
+                throw new ArgumentNullException(nameof(snapshot));
+
+            if (arcDataQueue != null)
+            {
+                lock (arcDataQueue)
+                {
+                    if (arcDataQueue.Count < maxQueueSize)
+                    {
+                        arcDataQueue.Enqueue(new QueueItem(DateTime.UtcNow, snapshot));
+                    }
+                    else
+                    {
+                        arcDataStats.SkippedItems++;
+                        log.WriteError(string.Format(Localization.UseRussian ?
+                            "Невозможно добавить архивные данные в очередь. Максимальный размер очереди {0} превышен" :
+                            "Unable to enqueue archive data. The maximum size of the queue {0} is exceeded",
+                            maxQueueSize));
+                    }
+                }
+            }
+        }
+
+        /// 
+        /// Enqueues the event for export.
+        /// 
+        public void EnqueueEvent(EventTableLight.Event ev)
+        {
+            if (ev == null)
+                throw new ArgumentNullException(nameof(ev));
+
+            if (eventQueue != null)
+            {
+                lock (eventQueue)
+                {
+                    if (eventQueue.Count < maxQueueSize)
+                    {
+                        eventQueue.Enqueue(new QueueItem(DateTime.UtcNow, ev));
+                    }
+                    else
+                    {
+                        eventStats.SkippedItems++;
+                        log.WriteError(string.Format(Localization.UseRussian ?
+                            "Невозможно добавить событие в очередь. Максимальный размер очереди {0} превышен" :
+                            "Unable to enqueue an event. The maximum size of the queue {0} is exceeded",
+                            maxQueueSize));
+                    }
+                }
+            }
+        }
+
+        /// 
+        /// Enqueues the command for execution.
+        /// 
+        public void EnqueueCmd(int outCnlNum, Command cmd, ref bool passToClients)
+        {
+            if (cmd == null)
+                throw new ArgumentNullException(nameof(cmd));
+
+            if (outCnlNum == exporterConfig.GeneralOptions.OutCnlNum)
+            {
+                passToClients = false;
+
+                if (CmdParams.Parse(cmd.GetCmdDataStr(), out CmdParams cmdParams, out string errMsg))
+                {
+                    switch (cmdParams.Action)
+                    {
+                        case CmdAction.ArcUpload:
+                            if (arcDataQueue == null)
+                            {
+                                log.WriteError(Localization.UseRussian ?
+                                    "Невозможно выполнить команду, потому что экспорт архивов отключен" :
+                                    "Unable to execute a command because archive export is disabled");
+                            }
+                            else
+                            {
+                                log.WriteError(Localization.UseRussian ?
+                                    "Получена команда экспорта архивов" :
+                                    "Archive export command received");
+
+                                taskUploadState = new ArcUploadState()
+                                {
+                                    SnapshotDate = cmdParams.MinDT.Date,
+                                    MinSnapshotDT = cmdParams.MinDT,
+                                    MaxSnapshotDT = cmdParams.MaxDT
+                                };
+                            }
+                            break;
+
+                        case CmdAction.EvUpload:
+                            if (eventQueue == null)
+                            {
+                                log.WriteError(Localization.UseRussian ?
+                                    "Невозможно выполнить команду, потому что экспорт событий отключен" :
+                                    "Unable to execute a command because event export is disabled");
+                            }
+                            else
+                            {
+                                log.WriteError(Localization.UseRussian ?
+                                    "Получена команда экспорта событий" :
+                                    "Event export command received");
+                                ExportEventsFromFile(cmdParams.MinDT, cmdParams.MaxDT);
+                            }
+                            break;
+
+                        default:
+                            log.WriteError(Localization.UseRussian ?
+                                "Неизвестная команда" :
+                                "Unknown command");
+                            break;
+                    }
+                }
+                else
+                {
+                    log.WriteError(errMsg);
+                }
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/ArcDataTrigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/ArcDataTrigger.cs
new file mode 100644
index 000000000..fdcd1d2fe
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/ArcDataTrigger.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents an archive data trigger
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+
+namespace Scada.Server.Modules.DbExport.Triggers
+{
+    /// 
+    /// Represents an archive data trigger.
+    /// Представляет триггер на архивные данные.
+    /// 
+    internal class ArcDataTrigger : DataTrigger
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ArcDataTrigger(TriggerOptions triggerOptions, DataSource dataSource)
+            : base(triggerOptions, dataSource)
+        {
+            ArcDataTriggerOptions = (ArcDataTriggerOptions)triggerOptions;
+        }
+
+        /// 
+        /// Gets the trigger options.
+        /// 
+        public ArcDataTriggerOptions ArcDataTriggerOptions { get; }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/ClassifiedTriggers.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/ClassifiedTriggers.cs
new file mode 100644
index 000000000..f8e0fefe4
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/ClassifiedTriggers.cs
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Stores triggers separated by classes
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+using System;
+using System.Collections.Generic;
+
+namespace Scada.Server.Modules.DbExport.Triggers
+{
+    /// 
+    /// Stores triggers separated by classes.
+    /// Хранит триггеры, разделённые на классы.
+    /// 
+    internal class ClassifiedTriggers
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ClassifiedTriggers(List triggersOptionsList, DataSource dataSource)
+        {
+            if (triggersOptionsList == null)
+                throw new ArgumentNullException(nameof(triggersOptionsList));
+            if (dataSource == null)
+                throw new ArgumentNullException(nameof(dataSource));
+
+            CurDataTriggers = new List();
+            ArcDataTriggers = new List();
+            EventTriggers = new List();
+            CreateTriggers(triggersOptionsList, dataSource);
+        }
+
+
+        /// 
+        /// Gets the current data triggers.
+        /// 
+        public List CurDataTriggers { get; private set; }
+
+        /// 
+        /// Gets the archive data triggers.
+        /// 
+        public List ArcDataTriggers { get; private set; }
+
+        /// 
+        /// Gets the event triggers.
+        /// 
+        public List EventTriggers { get; private set; }
+
+
+        /// 
+        /// Creates the triggers according to the trigger options.
+        /// 
+        private void CreateTriggers(List triggersOptionsList, DataSource dataSource)
+        {
+            foreach (TriggerOptions triggerOptions in triggersOptionsList)
+            {
+                if (triggerOptions.Active)
+                {
+                    if (triggerOptions is CurDataTriggerOptions options1)
+                        CurDataTriggers.Add(new CurDataTrigger(options1, dataSource));
+                    else if (triggerOptions is ArcDataTriggerOptions options2)
+                        ArcDataTriggers.Add(new ArcDataTrigger(options2, dataSource));
+                    else if (triggerOptions is EventTriggerOptions options3)
+                        EventTriggers.Add(new EventTrigger(options3, dataSource));
+                }
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/CurDataTrigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/CurDataTrigger.cs
new file mode 100644
index 000000000..fb33363db
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/CurDataTrigger.cs
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a current data trigger
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+
+namespace Scada.Server.Modules.DbExport.Triggers
+{
+    /// 
+    /// Represents a current data trigger.
+    /// Представляет триггер на текущие данные.
+    /// 
+    internal class CurDataTrigger : DataTrigger
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CurDataTrigger(TriggerOptions triggerOptions, DataSource dataSource)
+            : base(triggerOptions, dataSource)
+        {
+            CurDataTriggerOptions = (CurDataTriggerOptions)triggerOptions;
+        }
+
+        /// 
+        /// Gets the trigger options.
+        /// 
+        public CurDataTriggerOptions CurDataTriggerOptions { get; }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/DataTrigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/DataTrigger.cs
new file mode 100644
index 000000000..b7a042b83
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/DataTrigger.cs
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a data trigger
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+using System;
+using System.Data.Common;
+
+namespace Scada.Server.Modules.DbExport.Triggers
+{
+    /// 
+    /// Represents a data trigger.
+    /// Представляет триггер на данные.
+    /// 
+    internal abstract class DataTrigger : Trigger
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public DataTrigger(TriggerOptions triggerOptions, DataSource dataSource)
+            : base(triggerOptions, dataSource)
+        {
+            DataTriggerOptions = (DataTriggerOptions)triggerOptions;
+        }
+
+
+        /// 
+        /// Gets the trigger options.
+        /// 
+        public DataTriggerOptions DataTriggerOptions { get; }
+
+        /// 
+        /// Gets the command parameter that represents date and time.
+        /// 
+        public DbParameter DateTimeParam { get; protected set; }
+
+        /// 
+        /// Gets the command parameter that represents a device number.
+        /// 
+        public DbParameter KpNumParam { get; protected set; }
+
+        /// 
+        /// Gets the command parameter that represents a channel number.
+        /// 
+        public DbParameter CnlNumParam { get; protected set; }
+
+        /// 
+        /// Gets the command parameter that represents a value.
+        /// 
+        public DbParameter ValParam { get; protected set; }
+
+        /// 
+        /// Gets the command parameter that represents a status.
+        /// 
+        public DbParameter StatParam { get; protected set; }
+
+
+        /// 
+        /// Initializes the command parameters.
+        /// 
+        protected override void InitParams()
+        {
+            DataTriggerOptions options = (DataTriggerOptions)Options;
+            DateTimeParam = DataSource.SetParam(Command, "dateTime", DateTime.MinValue);
+            KpNumParam = DataSource.SetParam(Command, "kpNum", 0);
+
+            if (options.SingleQuery)
+            {
+                foreach (int cnlNum in options.CnlNums)
+                {
+                    string cnlNumStr = cnlNum.ToString();
+                    DataSource.SetParam(Command, "val" + cnlNumStr, 0.0);
+                    DataSource.SetParam(Command, "stat" + cnlNumStr, 0);
+                }
+            }
+            else
+            {
+                CnlNumParam = DataSource.SetParam(Command, "cnlNum", 0);
+                ValParam = DataSource.SetParam(Command, "val", 0.0);
+                StatParam = DataSource.SetParam(Command, "stat", 0);
+            }
+        }
+
+        /// 
+        /// Sets the command parameter that represents a value of the specified channel number.
+        /// 
+        public void SetValParam(int cnlNum, double val)
+        {
+            DataSource.SetParam(Command, "val" + cnlNum, val);
+        }
+
+        /// 
+        /// Sets the command parameter that represents a status of the specified channel number.
+        /// 
+        public void SetStatParam(int cnlNum, int stat)
+        {
+            DataSource.SetParam(Command, "stat" + cnlNum, stat);
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/EventTrigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/EventTrigger.cs
new file mode 100644
index 000000000..8f73d2e3c
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/EventTrigger.cs
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents an event trigger
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+using System;
+
+namespace Scada.Server.Modules.DbExport.Triggers
+{
+    /// 
+    /// Represents an event trigger.
+    /// Представляет триггер на событие.
+    /// 
+    internal class EventTrigger : Trigger
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public EventTrigger(TriggerOptions triggerOptions, DataSource dataSource)
+            : base(triggerOptions, dataSource)
+        {
+            EventTriggerOptions = (EventTriggerOptions)triggerOptions;
+        }
+
+        /// 
+        /// Gets the trigger options.
+        /// 
+        public EventTriggerOptions EventTriggerOptions { get; }
+
+        /// 
+        /// Initializes the command parameters.
+        /// 
+        protected override void InitParams()
+        {
+            DataSource.SetParam(Command, "dateTime", DateTime.MinValue);
+            DataSource.SetParam(Command, "objNum", 0);
+            DataSource.SetParam(Command, "kpNum", 0);
+            DataSource.SetParam(Command, "paramID", 0);
+            DataSource.SetParam(Command, "cnlNum", 0);
+            DataSource.SetParam(Command, "oldCnlVal", 0.0);
+            DataSource.SetParam(Command, "oldCnlStat", 0);
+            DataSource.SetParam(Command, "newCnlVal", 0.0);
+            DataSource.SetParam(Command, "newCnlStat", 0);
+            DataSource.SetParam(Command, "checked", false);
+            DataSource.SetParam(Command, "userID", 0);
+            DataSource.SetParam(Command, "descr", "");
+            DataSource.SetParam(Command, "data", "");
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/Trigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/Trigger.cs
new file mode 100644
index 000000000..9f34dbc78
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/Triggers/Trigger.cs
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a trigger
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using Scada.Db;
+using Scada.Server.Modules.DbExport.Config;
+using System;
+using System.Collections.Generic;
+using System.Data.Common;
+
+namespace Scada.Server.Modules.DbExport.Triggers
+{
+    /// 
+    /// Represents a trigger.
+    /// Представляет триггер.
+    /// 
+    internal abstract class Trigger
+    {
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public Trigger(TriggerOptions triggerOptions, DataSource dataSource)
+        {
+            DataSource = dataSource ?? throw new ArgumentNullException(nameof(dataSource));
+            Options = triggerOptions ?? throw new ArgumentNullException(nameof(triggerOptions));
+            CnlNums = new HashSet(Options.CnlNums);
+            DeviceNums = new HashSet(Options.DeviceNums);
+            Command = dataSource.CreateCommand();
+            Command.CommandText = triggerOptions.Query;
+            InitParams();
+        }
+
+
+        /// 
+        /// Gets the data source.
+        /// 
+        protected DataSource DataSource { get; }
+
+        /// 
+        /// Gets the trigger options.
+        /// 
+        public TriggerOptions Options { get; }
+
+        /// 
+        /// Gets the input channel numbers as a set.
+        /// 
+        public HashSet CnlNums { get; }
+
+        /// 
+        /// Gets the device numbers as a set.
+        /// 
+        public HashSet DeviceNums { get; private set; }
+
+        /// 
+        /// Gets or sets the database command corresponding to the trigger query.
+        /// 
+        public DbCommand Command { get; set; }
+
+
+        /// 
+        /// Initializes the command parameters.
+        /// 
+        protected virtual void InitParams()
+        {
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.Designer.cs
new file mode 100644
index 000000000..7c69df696
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.Designer.cs
@@ -0,0 +1,177 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class CtrlArcUploadOptions
+    {
+        ///  
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        ///  
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        ///  
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            this.gbArcUploadOptions = new System.Windows.Forms.GroupBox();
+            this.lblDelay = new System.Windows.Forms.Label();
+            this.lblMaxAge = new System.Windows.Forms.Label();
+            this.chkEnabled = new System.Windows.Forms.CheckBox();
+            this.numMaxAge = new System.Windows.Forms.NumericUpDown();
+            this.numDelay = new System.Windows.Forms.NumericUpDown();
+            this.cbSnapshotType = new System.Windows.Forms.ComboBox();
+            this.lblSnapshotType = new System.Windows.Forms.Label();
+            this.gbArcUploadOptions.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numMaxAge)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numDelay)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // gbArcUploadOptions
+            // 
+            this.gbArcUploadOptions.Controls.Add(this.lblDelay);
+            this.gbArcUploadOptions.Controls.Add(this.lblMaxAge);
+            this.gbArcUploadOptions.Controls.Add(this.chkEnabled);
+            this.gbArcUploadOptions.Controls.Add(this.numMaxAge);
+            this.gbArcUploadOptions.Controls.Add(this.numDelay);
+            this.gbArcUploadOptions.Controls.Add(this.cbSnapshotType);
+            this.gbArcUploadOptions.Controls.Add(this.lblSnapshotType);
+            this.gbArcUploadOptions.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.gbArcUploadOptions.Location = new System.Drawing.Point(0, 0);
+            this.gbArcUploadOptions.Name = "gbArcUploadOptions";
+            this.gbArcUploadOptions.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
+            this.gbArcUploadOptions.Size = new System.Drawing.Size(414, 388);
+            this.gbArcUploadOptions.TabIndex = 0;
+            this.gbArcUploadOptions.TabStop = false;
+            this.gbArcUploadOptions.Text = "Archive Upload Options";
+            // 
+            // lblDelay
+            // 
+            this.lblDelay.AutoSize = true;
+            this.lblDelay.Location = new System.Drawing.Point(10, 99);
+            this.lblDelay.Name = "lblDelay";
+            this.lblDelay.Size = new System.Drawing.Size(168, 13);
+            this.lblDelay.TabIndex = 3;
+            this.lblDelay.Text = "Delay before sending archive, sec";
+            // 
+            // lblMaxAge
+            // 
+            this.lblMaxAge.AutoSize = true;
+            this.lblMaxAge.Location = new System.Drawing.Point(10, 148);
+            this.lblMaxAge.Name = "lblMaxAge";
+            this.lblMaxAge.Size = new System.Drawing.Size(150, 13);
+            this.lblMaxAge.TabIndex = 5;
+            this.lblMaxAge.Text = "Maximum age of archive, days";
+            // 
+            // chkEnabled
+            // 
+            this.chkEnabled.AutoSize = true;
+            this.chkEnabled.Location = new System.Drawing.Point(13, 19);
+            this.chkEnabled.Name = "chkEnabled";
+            this.chkEnabled.Size = new System.Drawing.Size(65, 17);
+            this.chkEnabled.TabIndex = 0;
+            this.chkEnabled.Text = "Enabled";
+            this.chkEnabled.UseVisualStyleBackColor = true;
+            this.chkEnabled.CheckedChanged += new System.EventHandler(this.chkEnabled_CheckedChanged);
+            // 
+            // numMaxAge
+            // 
+            this.numMaxAge.Location = new System.Drawing.Point(13, 164);
+            this.numMaxAge.Maximum = new decimal(new int[] {
+            30,
+            0,
+            0,
+            0});
+            this.numMaxAge.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numMaxAge.Name = "numMaxAge";
+            this.numMaxAge.Size = new System.Drawing.Size(120, 20);
+            this.numMaxAge.TabIndex = 6;
+            this.numMaxAge.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numMaxAge.ValueChanged += new System.EventHandler(this.numMaxAge_ValueChanged);
+            // 
+            // numDelay
+            // 
+            this.numDelay.Location = new System.Drawing.Point(13, 115);
+            this.numDelay.Maximum = new decimal(new int[] {
+            3600000,
+            0,
+            0,
+            0});
+            this.numDelay.Name = "numDelay";
+            this.numDelay.Size = new System.Drawing.Size(120, 20);
+            this.numDelay.TabIndex = 4;
+            this.numDelay.Value = new decimal(new int[] {
+            10,
+            0,
+            0,
+            0});
+            this.numDelay.ValueChanged += new System.EventHandler(this.numDelay_ValueChanged);
+            // 
+            // cbSnapshotType
+            // 
+            this.cbSnapshotType.FormattingEnabled = true;
+            this.cbSnapshotType.Location = new System.Drawing.Point(13, 65);
+            this.cbSnapshotType.Name = "cbSnapshotType";
+            this.cbSnapshotType.Size = new System.Drawing.Size(120, 21);
+            this.cbSnapshotType.TabIndex = 2;
+            this.cbSnapshotType.SelectedIndexChanged += new System.EventHandler(this.cbSnapshotType_SelectedIndexChanged);
+            // 
+            // lblSnapshotType
+            // 
+            this.lblSnapshotType.AutoSize = true;
+            this.lblSnapshotType.Location = new System.Drawing.Point(10, 49);
+            this.lblSnapshotType.Name = "lblSnapshotType";
+            this.lblSnapshotType.Size = new System.Drawing.Size(79, 13);
+            this.lblSnapshotType.TabIndex = 1;
+            this.lblSnapshotType.Text = "Snapshot code";
+            // 
+            // CtrlArcUploadOptions
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.gbArcUploadOptions);
+            this.Name = "CtrlArcUploadOptions";
+            this.Size = new System.Drawing.Size(414, 388);
+            this.gbArcUploadOptions.ResumeLayout(false);
+            this.gbArcUploadOptions.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numMaxAge)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numDelay)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbArcUploadOptions;
+        private System.Windows.Forms.Label lblDelay;
+        private System.Windows.Forms.Label lblMaxAge;
+        private System.Windows.Forms.CheckBox chkEnabled;
+        private System.Windows.Forms.NumericUpDown numMaxAge;
+        private System.Windows.Forms.NumericUpDown numDelay;
+        private System.Windows.Forms.ComboBox cbSnapshotType;
+        private System.Windows.Forms.Label lblSnapshotType;
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.cs
new file mode 100644
index 000000000..df71f1c76
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.cs
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a control for editing archive upload option
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using Scada.Server.Modules.DbExport.Config;
+using Scada.UI;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Represents a control for editing archive upload options.
+    /// Представляет элемент управления для редактирования параметров загрузки архивов.
+    /// 
+    public partial class CtrlArcUploadOptions : UserControl
+    {
+        private ArcUploadOptions arcUploadOptions;
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CtrlArcUploadOptions()
+        {
+            InitializeComponent();
+            cbSnapshotType.DropDownStyle = ComboBoxStyle.DropDownList;
+            cbSnapshotType.Items.Clear();
+            cbSnapshotType.Items.Add(SnapshotType.Cur);
+            cbSnapshotType.Items.Add(SnapshotType.Min);
+            cbSnapshotType.Items.Add(SnapshotType.Hour);
+            arcUploadOptions = null;
+        }
+
+
+        /// 
+        /// Gets or sets an editable archive upload options.
+        /// 
+        internal ArcUploadOptions ArcUploadOptions
+        {
+            get
+            {
+                return arcUploadOptions;
+            }
+            set
+            {
+                if (value != null)
+                {
+                    arcUploadOptions = null;
+
+                    if (value.SnapshotType == SnapshotType.Cur)
+                    {
+                        cbSnapshotType.SelectedIndex = 0;
+                    }
+                    else
+                    {
+                        if (value.SnapshotType == SnapshotType.Min)
+                            cbSnapshotType.SelectedIndex = 1;
+                        else
+                            cbSnapshotType.SelectedIndex = 2;
+                    }
+
+                    numDelay.Value = value.Delay;
+                    numMaxAge.Value = value.MaxAge;
+                    chkEnabled.Checked = value.Enabled;
+                }
+
+                arcUploadOptions = value;
+            }
+        }
+
+        /// 
+        /// Trigges an event ArcUploadOptionsChanged.
+        /// 
+        private void OnArcUploadOptionsChanged()
+        {
+            ArcUploadOptionsChanged?.Invoke(this, new ObjectChangedEventArgs(arcUploadOptions));
+        }
+
+        /// 
+        /// An event that occurs when the properties of an edited archive upload options.
+        /// 
+        [Category("Property Changed")]
+        public event ObjectChangedEventHandler ArcUploadOptionsChanged;
+
+
+        private void cbSnapshotType_SelectedIndexChanged(object sender, EventArgs e)
+        {
+            if (arcUploadOptions != null)
+            {
+                arcUploadOptions.SnapshotType = (SnapshotType)cbSnapshotType.SelectedIndex;
+                OnArcUploadOptionsChanged();
+            }
+        }
+
+        private void numDelay_ValueChanged(object sender, EventArgs e)
+        {
+            if (arcUploadOptions != null)
+            {
+                arcUploadOptions.Delay = Convert.ToInt32(numDelay.Value);
+                OnArcUploadOptionsChanged();
+            }
+        }
+
+        private void numMaxAge_ValueChanged(object sender, EventArgs e)
+        {
+            if (arcUploadOptions != null)
+            {
+                arcUploadOptions.MaxAge = Convert.ToInt32(numMaxAge.Value);
+                OnArcUploadOptionsChanged();
+            }
+        }
+
+        private void chkEnabled_CheckedChanged(object sender, EventArgs e)
+        {
+            if (arcUploadOptions != null)
+            {
+                arcUploadOptions.Enabled = chkEnabled.Checked;
+                OnArcUploadOptionsChanged();
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.resx
similarity index 100%
rename from ScadaServer/OpenModules/ModDBExport/DBExport/UI/CtrlExportQuery.resx
rename to ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlArcUploadOptions.resx
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.Designer.cs
new file mode 100644
index 000000000..8fddefff2
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.Designer.cs
@@ -0,0 +1,212 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class CtrlConnectionOptions
+    {
+        ///  
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        ///  
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        ///  
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            this.gbConnection = new System.Windows.Forms.GroupBox();
+            this.chkConnectionString = new System.Windows.Forms.CheckBox();
+            this.txtConnectionString = new System.Windows.Forms.TextBox();
+            this.lblDataBase = new System.Windows.Forms.Label();
+            this.txtDataBase = new System.Windows.Forms.TextBox();
+            this.lblDBMS = new System.Windows.Forms.Label();
+            this.txtDBMS = new System.Windows.Forms.TextBox();
+            this.lblServer = new System.Windows.Forms.Label();
+            this.txtServer = new System.Windows.Forms.TextBox();
+            this.lblServerPwd = new System.Windows.Forms.Label();
+            this.txtUserPwd = new System.Windows.Forms.TextBox();
+            this.txtUser = new System.Windows.Forms.TextBox();
+            this.lblServerUser = new System.Windows.Forms.Label();
+            this.gbConnection.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // gbConnection
+            // 
+            this.gbConnection.AutoSize = true;
+            this.gbConnection.Controls.Add(this.chkConnectionString);
+            this.gbConnection.Controls.Add(this.txtConnectionString);
+            this.gbConnection.Controls.Add(this.lblDataBase);
+            this.gbConnection.Controls.Add(this.txtDataBase);
+            this.gbConnection.Controls.Add(this.lblDBMS);
+            this.gbConnection.Controls.Add(this.txtDBMS);
+            this.gbConnection.Controls.Add(this.lblServer);
+            this.gbConnection.Controls.Add(this.txtServer);
+            this.gbConnection.Controls.Add(this.lblServerPwd);
+            this.gbConnection.Controls.Add(this.txtUserPwd);
+            this.gbConnection.Controls.Add(this.txtUser);
+            this.gbConnection.Controls.Add(this.lblServerUser);
+            this.gbConnection.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.gbConnection.Location = new System.Drawing.Point(0, 0);
+            this.gbConnection.Name = "gbConnection";
+            this.gbConnection.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
+            this.gbConnection.RightToLeft = System.Windows.Forms.RightToLeft.No;
+            this.gbConnection.Size = new System.Drawing.Size(414, 483);
+            this.gbConnection.TabIndex = 0;
+            this.gbConnection.TabStop = false;
+            this.gbConnection.Text = "Connection Options";
+            // 
+            // chkConnectionString
+            // 
+            this.chkConnectionString.AutoSize = true;
+            this.chkConnectionString.Location = new System.Drawing.Point(13, 257);
+            this.chkConnectionString.Name = "chkConnectionString";
+            this.chkConnectionString.Size = new System.Drawing.Size(108, 17);
+            this.chkConnectionString.TabIndex = 10;
+            this.chkConnectionString.Text = "Connection string";
+            this.chkConnectionString.UseVisualStyleBackColor = true;
+            this.chkConnectionString.CheckedChanged += new System.EventHandler(this.chkConnectionString_CheckedChanged);
+            // 
+            // txtConnectionString
+            // 
+            this.txtConnectionString.Location = new System.Drawing.Point(13, 280);
+            this.txtConnectionString.Multiline = true;
+            this.txtConnectionString.Name = "txtConnectionString";
+            this.txtConnectionString.Size = new System.Drawing.Size(386, 188);
+            this.txtConnectionString.TabIndex = 11;
+            this.txtConnectionString.TextChanged += new System.EventHandler(this.txtConnectionString_TextChanged);
+            // 
+            // lblDataBase
+            // 
+            this.lblDataBase.AutoSize = true;
+            this.lblDataBase.Location = new System.Drawing.Point(10, 69);
+            this.lblDataBase.Name = "lblDataBase";
+            this.lblDataBase.Size = new System.Drawing.Size(53, 13);
+            this.lblDataBase.TabIndex = 2;
+            this.lblDataBase.Text = "Database";
+            // 
+            // txtDataBase
+            // 
+            this.txtDataBase.Location = new System.Drawing.Point(13, 85);
+            this.txtDataBase.Name = "txtDataBase";
+            this.txtDataBase.Size = new System.Drawing.Size(386, 20);
+            this.txtDataBase.TabIndex = 3;
+            this.txtDataBase.Text = "rapid scada";
+            this.txtDataBase.TextChanged += new System.EventHandler(this.txtDataBase_TextChanged);
+            // 
+            // lblDBMS
+            // 
+            this.lblDBMS.AutoSize = true;
+            this.lblDBMS.Location = new System.Drawing.Point(10, 22);
+            this.lblDBMS.Name = "lblDBMS";
+            this.lblDBMS.Size = new System.Drawing.Size(38, 13);
+            this.lblDBMS.TabIndex = 0;
+            this.lblDBMS.Text = "DBMS";
+            // 
+            // txtDBMS
+            // 
+            this.txtDBMS.Location = new System.Drawing.Point(13, 38);
+            this.txtDBMS.Name = "txtDBMS";
+            this.txtDBMS.ReadOnly = true;
+            this.txtDBMS.Size = new System.Drawing.Size(386, 20);
+            this.txtDBMS.TabIndex = 1;
+            this.txtDBMS.TextChanged += new System.EventHandler(this.txtDBMS_TextChanged);
+            // 
+            // lblServer
+            // 
+            this.lblServer.AutoSize = true;
+            this.lblServer.Location = new System.Drawing.Point(10, 116);
+            this.lblServer.Name = "lblServer";
+            this.lblServer.Size = new System.Drawing.Size(38, 13);
+            this.lblServer.TabIndex = 4;
+            this.lblServer.Text = "Server";
+            // 
+            // txtServer
+            // 
+            this.txtServer.Location = new System.Drawing.Point(13, 132);
+            this.txtServer.Name = "txtServer";
+            this.txtServer.Size = new System.Drawing.Size(385, 20);
+            this.txtServer.TabIndex = 5;
+            this.txtServer.Text = "localhost";
+            this.txtServer.TextChanged += new System.EventHandler(this.txtServer_TextChanged);
+            // 
+            // lblServerPwd
+            // 
+            this.lblServerPwd.AutoSize = true;
+            this.lblServerPwd.Location = new System.Drawing.Point(10, 210);
+            this.lblServerPwd.Name = "lblServerPwd";
+            this.lblServerPwd.Size = new System.Drawing.Size(53, 13);
+            this.lblServerPwd.TabIndex = 8;
+            this.lblServerPwd.Text = "Password";
+            // 
+            // txtUserPwd
+            // 
+            this.txtUserPwd.Location = new System.Drawing.Point(13, 226);
+            this.txtUserPwd.Name = "txtUserPwd";
+            this.txtUserPwd.Size = new System.Drawing.Size(385, 20);
+            this.txtUserPwd.TabIndex = 9;
+            this.txtUserPwd.UseSystemPasswordChar = true;
+            this.txtUserPwd.TextChanged += new System.EventHandler(this.txtUserPwd_TextChanged);
+            // 
+            // txtUser
+            // 
+            this.txtUser.Location = new System.Drawing.Point(13, 179);
+            this.txtUser.Name = "txtUser";
+            this.txtUser.Size = new System.Drawing.Size(386, 20);
+            this.txtUser.TabIndex = 7;
+            this.txtUser.TextChanged += new System.EventHandler(this.txtUser_TextChanged);
+            // 
+            // lblServerUser
+            // 
+            this.lblServerUser.AutoSize = true;
+            this.lblServerUser.Location = new System.Drawing.Point(10, 163);
+            this.lblServerUser.Name = "lblServerUser";
+            this.lblServerUser.Size = new System.Drawing.Size(29, 13);
+            this.lblServerUser.TabIndex = 6;
+            this.lblServerUser.Text = "User";
+            // 
+            // CtrlConnectionOptions
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.gbConnection);
+            this.Name = "CtrlConnectionOptions";
+            this.Size = new System.Drawing.Size(414, 483);
+            this.gbConnection.ResumeLayout(false);
+            this.gbConnection.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbConnection;
+        private System.Windows.Forms.Label lblServerPwd;
+        private System.Windows.Forms.TextBox txtUserPwd;
+        private System.Windows.Forms.TextBox txtUser;
+        private System.Windows.Forms.Label lblServerUser;
+        private System.Windows.Forms.Label lblServer;
+        private System.Windows.Forms.TextBox txtServer;
+        private System.Windows.Forms.Label lblDBMS;
+        private System.Windows.Forms.TextBox txtDBMS;
+        private System.Windows.Forms.Label lblDataBase;
+        private System.Windows.Forms.TextBox txtDataBase;
+        private System.Windows.Forms.TextBox txtConnectionString;
+        private System.Windows.Forms.CheckBox chkConnectionString;
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.cs
new file mode 100644
index 000000000..cdc239804
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.cs
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a control for editing connection options
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using Scada.Config;
+using Scada.UI;
+using Scada.Db;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Represents a control for editing connection options.
+    /// Представляет элемент управления для редактирования настроек соединения.
+    /// 
+    public partial class CtrlConnectionOptions : UserControl
+    {
+        private DbConnectionOptions connectionOptions;
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CtrlConnectionOptions()
+        {
+            InitializeComponent();
+            connectionOptions = null;
+        }
+
+
+        /// 
+        /// Gets or sets an editable connection options.
+        /// 
+        public DbConnectionOptions ConnectionOptions
+        {
+            get
+            {
+                return connectionOptions;
+            }
+            set
+            {
+                if (value != null)
+                {
+                    connectionOptions = null;
+                    txtDBMS.Text = value.DBMS;
+                    txtDataBase.Text = value.Database;
+                    txtServer.Text = value.Server;
+                    txtUser.Text = value.Username;
+                    txtUserPwd.Text = value.Password;
+                    txtConnectionString.Text = value.ConnectionString;
+
+                    if (value.ConnectionString != "")
+                    {
+                        chkConnectionString.Checked = true;
+                        txtDataBase.Enabled = false;
+                        txtServer.Enabled = false;
+                        txtUser.Enabled = false;
+                        txtUserPwd.Enabled = false;
+                        txtConnectionString.Enabled = true;
+                    }
+                    else
+                    {
+                        chkConnectionString.Checked = false;
+                        txtDBMS.Enabled = true;
+                        txtDataBase.Enabled = true;
+                        txtServer.Enabled = true;
+                        txtUser.Enabled = true;
+                        txtUserPwd.Enabled = true;
+                        txtConnectionString.Enabled = false;
+
+                        SetConnectionString(value);
+                    }
+                }
+
+                connectionOptions = value;
+            }
+        }
+
+        /// 
+        /// Triggers an event ConnectChanged.
+        /// 
+        private void OnConnectChanged()
+        {
+            ConnectChanged?.Invoke(this, new ObjectChangedEventArgs(connectionOptions));
+        }
+
+        /// 
+        /// An event that occurs when the properties of an edited connect options change.
+        /// 
+        [Category("Property Changed")]
+        public event ObjectChangedEventHandler ConnectChanged;
+
+        /// 
+        /// Set input focus.
+        /// 
+        public void SetFocus()
+        {
+            txtDataBase.Select();
+        }
+
+        /// 
+        /// Set and show an auto-generated connection string. 
+        /// 
+        private void SetConnectionString(DbConnectionOptions dbConnectionOptions)
+        {
+            if (dbConnectionOptions != null)
+            {
+                if (dbConnectionOptions.KnownDBMS == KnownDBMS.Oracle)
+                    txtConnectionString.Text = OraDataSource.BuildOraConnectionString(dbConnectionOptions, true);
+                else if (dbConnectionOptions.KnownDBMS == KnownDBMS.PostgreSQL)
+                    txtConnectionString.Text = PgSqlDataSource.BuildPgSqlConnectionString(dbConnectionOptions, true);
+                else if (dbConnectionOptions.KnownDBMS == KnownDBMS.MySQL)
+                    txtConnectionString.Text = MySqlDataSource.BuildMySqlConnectionString(dbConnectionOptions, true);
+                else if (dbConnectionOptions.KnownDBMS == KnownDBMS.MSSQL)
+                    txtConnectionString.Text = SqlDataSource.BuildSqlConnectionString(dbConnectionOptions, true);
+                else
+                    txtConnectionString.Text = "";
+            }
+        }
+
+
+        private void txtDBMS_TextChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                connectionOptions.DBMS = txtDBMS.Text;
+                OnConnectChanged();
+            }
+        }
+
+        private void txtDataBase_TextChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                connectionOptions.Database = txtDataBase.Text;
+
+                if (txtDataBase.Text != "")
+                {
+                    SetConnectionString(connectionOptions);
+                    connectionOptions.ConnectionString = "";
+                }
+                OnConnectChanged();
+            }
+        }
+
+        private void txtServer_TextChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                connectionOptions.Server = txtServer.Text;
+
+                if (txtServer.Text != "")
+                {
+                    SetConnectionString(connectionOptions);
+                    connectionOptions.ConnectionString = "";
+                }
+                
+                OnConnectChanged();
+            }
+        }
+
+        private void txtUser_TextChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                connectionOptions.Username = txtUser.Text;
+
+                if (txtUser.Text != "")
+                {
+                    SetConnectionString(connectionOptions);
+                    connectionOptions.ConnectionString = "";
+                }
+                
+                OnConnectChanged();
+            }
+        }
+
+        private void txtUserPwd_TextChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                connectionOptions.Password = txtUserPwd.Text;
+
+                if (txtUserPwd.Text != "")
+                {
+                    SetConnectionString(connectionOptions);
+                    connectionOptions.ConnectionString = "";
+                }
+                
+                OnConnectChanged();
+            }
+        }
+
+        private void txtConnectionString_TextChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                connectionOptions.ConnectionString = txtConnectionString.Text;
+                OnConnectChanged();
+            }
+        }
+
+        private void chkConnectionString_CheckedChanged(object sender, EventArgs e)
+        {
+            if (connectionOptions != null)
+            {
+                txtDataBase.Enabled = !chkConnectionString.Checked;
+                txtServer.Enabled = !chkConnectionString.Checked;
+                txtUser.Enabled = !chkConnectionString.Checked;
+                txtUserPwd.Enabled = !chkConnectionString.Checked;
+                txtConnectionString.Enabled = chkConnectionString.Checked;
+
+                if (chkConnectionString.Checked)
+                {
+                    SetConnectionString(connectionOptions);
+                    connectionOptions.ConnectionString = txtConnectionString.Text;
+                    txtDataBase.Text = "";
+                    txtServer.Text = "";
+                    txtUser.Text = "";
+                    txtUserPwd.Text = "";
+                    txtConnectionString.Select();
+                }
+                else
+                {
+                    connectionOptions.ConnectionString = "";
+                }
+
+                OnConnectChanged();
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.resx
similarity index 100%
rename from ScadaServer/OpenModules/ModDBExport/DBExport/UI/FrmManualExport.resx
rename to ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlConnectionOptions.resx
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.Designer.cs
new file mode 100644
index 000000000..57dc37753
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.Designer.cs
@@ -0,0 +1,311 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class CtrlEventTrigger
+    {
+        ///  
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        ///  
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        ///  
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CtrlEventTrigger));
+            this.gbTrigger = new System.Windows.Forms.GroupBox();
+            this.lblTriggerType = new System.Windows.Forms.Label();
+            this.txtTriggerType = new System.Windows.Forms.TextBox();
+            this.btnEditDeviceNum = new System.Windows.Forms.Button();
+            this.btnEditCnlNum = new System.Windows.Forms.Button();
+            this.lblSeparatorQuery = new System.Windows.Forms.Label();
+            this.txtDeviceNum = new System.Windows.Forms.TextBox();
+            this.lblDeviceNum = new System.Windows.Forms.Label();
+            this.lblSeparatorFilter = new System.Windows.Forms.Label();
+            this.lvParametrs = new System.Windows.Forms.ListView();
+            this.lblParametrs = new System.Windows.Forms.Label();
+            this.txtCnlNum = new System.Windows.Forms.TextBox();
+            this.txtName = new System.Windows.Forms.TextBox();
+            this.txtSql = new System.Windows.Forms.TextBox();
+            this.lblSql = new System.Windows.Forms.Label();
+            this.lblCnlNum = new System.Windows.Forms.Label();
+            this.lblTriggerName = new System.Windows.Forms.Label();
+            this.chkActive = new System.Windows.Forms.CheckBox();
+            this.lblSeparator = new System.Windows.Forms.Label();
+            this.lblSeparator1 = new System.Windows.Forms.Label();
+            this.gbTrigger.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // gbTrigger
+            // 
+            this.gbTrigger.Controls.Add(this.lblTriggerType);
+            this.gbTrigger.Controls.Add(this.txtTriggerType);
+            this.gbTrigger.Controls.Add(this.btnEditDeviceNum);
+            this.gbTrigger.Controls.Add(this.btnEditCnlNum);
+            this.gbTrigger.Controls.Add(this.lblSeparatorQuery);
+            this.gbTrigger.Controls.Add(this.txtDeviceNum);
+            this.gbTrigger.Controls.Add(this.lblDeviceNum);
+            this.gbTrigger.Controls.Add(this.lblSeparatorFilter);
+            this.gbTrigger.Controls.Add(this.lvParametrs);
+            this.gbTrigger.Controls.Add(this.lblParametrs);
+            this.gbTrigger.Controls.Add(this.txtCnlNum);
+            this.gbTrigger.Controls.Add(this.txtName);
+            this.gbTrigger.Controls.Add(this.txtSql);
+            this.gbTrigger.Controls.Add(this.lblSql);
+            this.gbTrigger.Controls.Add(this.lblCnlNum);
+            this.gbTrigger.Controls.Add(this.lblTriggerName);
+            this.gbTrigger.Controls.Add(this.chkActive);
+            this.gbTrigger.Controls.Add(this.lblSeparator);
+            this.gbTrigger.Controls.Add(this.lblSeparator1);
+            this.gbTrigger.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.gbTrigger.Location = new System.Drawing.Point(0, 0);
+            this.gbTrigger.Name = "gbTrigger";
+            this.gbTrigger.Size = new System.Drawing.Size(414, 480);
+            this.gbTrigger.TabIndex = 0;
+            this.gbTrigger.TabStop = false;
+            this.gbTrigger.Text = "Triggers";
+            // 
+            // lblTriggerType
+            // 
+            this.lblTriggerType.AutoSize = true;
+            this.lblTriggerType.Location = new System.Drawing.Point(217, 38);
+            this.lblTriggerType.Name = "lblTriggerType";
+            this.lblTriggerType.Size = new System.Drawing.Size(63, 13);
+            this.lblTriggerType.TabIndex = 3;
+            this.lblTriggerType.Text = "Trigger type";
+            // 
+            // txtTriggerType
+            // 
+            this.txtTriggerType.Location = new System.Drawing.Point(220, 54);
+            this.txtTriggerType.Name = "txtTriggerType";
+            this.txtTriggerType.ReadOnly = true;
+            this.txtTriggerType.Size = new System.Drawing.Size(177, 20);
+            this.txtTriggerType.TabIndex = 4;
+            this.txtTriggerType.TabStop = false;
+            // 
+            // btnEditDeviceNum
+            // 
+            this.btnEditDeviceNum.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnEditDeviceNum.Image = ((System.Drawing.Image)(resources.GetObject("btnEditDeviceNum.Image")));
+            this.btnEditDeviceNum.Location = new System.Drawing.Point(377, 171);
+            this.btnEditDeviceNum.Name = "btnEditDeviceNum";
+            this.btnEditDeviceNum.Size = new System.Drawing.Size(20, 20);
+            this.btnEditDeviceNum.TabIndex = 12;
+            this.btnEditDeviceNum.UseVisualStyleBackColor = true;
+            this.btnEditDeviceNum.Click += new System.EventHandler(this.btnEditDeviceNum_Click);
+            // 
+            // btnEditCnlNum
+            // 
+            this.btnEditCnlNum.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnEditCnlNum.Image = ((System.Drawing.Image)(resources.GetObject("btnEditCnlNum.Image")));
+            this.btnEditCnlNum.Location = new System.Drawing.Point(377, 129);
+            this.btnEditCnlNum.Name = "btnEditCnlNum";
+            this.btnEditCnlNum.Size = new System.Drawing.Size(20, 20);
+            this.btnEditCnlNum.TabIndex = 9;
+            this.btnEditCnlNum.UseVisualStyleBackColor = true;
+            this.btnEditCnlNum.Click += new System.EventHandler(this.btnEditCnlNum_Click);
+            // 
+            // lblSeparatorQuery
+            // 
+            this.lblSeparatorQuery.AutoSize = true;
+            this.lblSeparatorQuery.ForeColor = System.Drawing.SystemColors.WindowText;
+            this.lblSeparatorQuery.Location = new System.Drawing.Point(10, 208);
+            this.lblSeparatorQuery.Name = "lblSeparatorQuery";
+            this.lblSeparatorQuery.Size = new System.Drawing.Size(35, 13);
+            this.lblSeparatorQuery.TabIndex = 13;
+            this.lblSeparatorQuery.Text = "Query";
+            // 
+            // txtDeviceNum
+            // 
+            this.txtDeviceNum.Location = new System.Drawing.Point(13, 171);
+            this.txtDeviceNum.Name = "txtDeviceNum";
+            this.txtDeviceNum.Size = new System.Drawing.Size(358, 20);
+            this.txtDeviceNum.TabIndex = 11;
+            this.txtDeviceNum.TextChanged += new System.EventHandler(this.txtDeviceNum_TextChanged);
+            this.txtDeviceNum.Enter += new System.EventHandler(this.txtDeviceNum_Enter);
+            this.txtDeviceNum.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtDeviceNum_KeyDown);
+            this.txtDeviceNum.Validating += new System.ComponentModel.CancelEventHandler(this.txtDeviceNum_Validating);
+            // 
+            // lblDeviceNum
+            // 
+            this.lblDeviceNum.AutoSize = true;
+            this.lblDeviceNum.Location = new System.Drawing.Point(10, 155);
+            this.lblDeviceNum.Name = "lblDeviceNum";
+            this.lblDeviceNum.Size = new System.Drawing.Size(84, 13);
+            this.lblDeviceNum.TabIndex = 10;
+            this.lblDeviceNum.Text = "Device numbers";
+            // 
+            // lblSeparatorFilter
+            // 
+            this.lblSeparatorFilter.AutoSize = true;
+            this.lblSeparatorFilter.ForeColor = System.Drawing.SystemColors.WindowText;
+            this.lblSeparatorFilter.Location = new System.Drawing.Point(10, 91);
+            this.lblSeparatorFilter.Name = "lblSeparatorFilter";
+            this.lblSeparatorFilter.Size = new System.Drawing.Size(34, 13);
+            this.lblSeparatorFilter.TabIndex = 5;
+            this.lblSeparatorFilter.Text = "Filtres";
+            // 
+            // lvParametrs
+            // 
+            this.lvParametrs.BackColor = System.Drawing.SystemColors.MenuBar;
+            this.lvParametrs.HideSelection = false;
+            this.lvParametrs.Location = new System.Drawing.Point(13, 388);
+            this.lvParametrs.MultiSelect = false;
+            this.lvParametrs.Name = "lvParametrs";
+            this.lvParametrs.Size = new System.Drawing.Size(384, 75);
+            this.lvParametrs.TabIndex = 17;
+            this.lvParametrs.UseCompatibleStateImageBehavior = false;
+            this.lvParametrs.View = System.Windows.Forms.View.List;
+            // 
+            // lblParametrs
+            // 
+            this.lblParametrs.AutoSize = true;
+            this.lblParametrs.Location = new System.Drawing.Point(10, 372);
+            this.lblParametrs.Name = "lblParametrs";
+            this.lblParametrs.Size = new System.Drawing.Size(99, 13);
+            this.lblParametrs.TabIndex = 16;
+            this.lblParametrs.Text = "Available parametrs";
+            // 
+            // txtCnlNum
+            // 
+            this.txtCnlNum.Location = new System.Drawing.Point(13, 129);
+            this.txtCnlNum.Name = "txtCnlNum";
+            this.txtCnlNum.Size = new System.Drawing.Size(358, 20);
+            this.txtCnlNum.TabIndex = 8;
+            this.txtCnlNum.TextChanged += new System.EventHandler(this.txtCnlNum_TextChanged);
+            this.txtCnlNum.Enter += new System.EventHandler(this.txtCnlNum_Enter);
+            this.txtCnlNum.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtCnlNum_KeyDown);
+            this.txtCnlNum.Validating += new System.ComponentModel.CancelEventHandler(this.txtCnlNum_Validating);
+            // 
+            // txtName
+            // 
+            this.txtName.Location = new System.Drawing.Point(13, 54);
+            this.txtName.Name = "txtName";
+            this.txtName.Size = new System.Drawing.Size(202, 20);
+            this.txtName.TabIndex = 2;
+            this.txtName.TextChanged += new System.EventHandler(this.txtName_TextChanged);
+            // 
+            // txtSql
+            // 
+            this.txtSql.Location = new System.Drawing.Point(13, 246);
+            this.txtSql.Multiline = true;
+            this.txtSql.Name = "txtSql";
+            this.txtSql.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtSql.Size = new System.Drawing.Size(384, 118);
+            this.txtSql.TabIndex = 15;
+            this.txtSql.TextChanged += new System.EventHandler(this.txtSql_TextChanged);
+            // 
+            // lblSql
+            // 
+            this.lblSql.AutoSize = true;
+            this.lblSql.Location = new System.Drawing.Point(10, 230);
+            this.lblSql.Name = "lblSql";
+            this.lblSql.Size = new System.Drawing.Size(28, 13);
+            this.lblSql.TabIndex = 14;
+            this.lblSql.Text = "SQL";
+            // 
+            // lblCnlNum
+            // 
+            this.lblCnlNum.AutoSize = true;
+            this.lblCnlNum.Location = new System.Drawing.Point(10, 113);
+            this.lblCnlNum.Name = "lblCnlNum";
+            this.lblCnlNum.Size = new System.Drawing.Size(77, 13);
+            this.lblCnlNum.TabIndex = 7;
+            this.lblCnlNum.Text = "Input channels";
+            // 
+            // lblTriggerName
+            // 
+            this.lblTriggerName.AutoSize = true;
+            this.lblTriggerName.Location = new System.Drawing.Point(10, 38);
+            this.lblTriggerName.Name = "lblTriggerName";
+            this.lblTriggerName.Size = new System.Drawing.Size(69, 13);
+            this.lblTriggerName.TabIndex = 1;
+            this.lblTriggerName.Text = "Trigger name";
+            // 
+            // chkActive
+            // 
+            this.chkActive.AutoSize = true;
+            this.chkActive.Location = new System.Drawing.Point(13, 19);
+            this.chkActive.Name = "chkActive";
+            this.chkActive.Size = new System.Drawing.Size(56, 17);
+            this.chkActive.TabIndex = 0;
+            this.chkActive.Text = "Active";
+            this.chkActive.UseVisualStyleBackColor = true;
+            this.chkActive.CheckedChanged += new System.EventHandler(this.chkActive_CheckedChanged);
+            // 
+            // lblSeparator
+            // 
+            this.lblSeparator.BackColor = System.Drawing.SystemColors.Control;
+            this.lblSeparator.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.lblSeparator.ForeColor = System.Drawing.SystemColors.Desktop;
+            this.lblSeparator.Location = new System.Drawing.Point(13, 98);
+            this.lblSeparator.Name = "lblSeparator";
+            this.lblSeparator.RightToLeft = System.Windows.Forms.RightToLeft.No;
+            this.lblSeparator.Size = new System.Drawing.Size(385, 2);
+            this.lblSeparator.TabIndex = 6;
+            this.lblSeparator.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // lblSeparator1
+            // 
+            this.lblSeparator1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.lblSeparator1.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.lblSeparator1.Location = new System.Drawing.Point(13, 215);
+            this.lblSeparator1.Name = "lblSeparator1";
+            this.lblSeparator1.Size = new System.Drawing.Size(385, 2);
+            this.lblSeparator1.TabIndex = 15;
+            this.lblSeparator1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // CtrlEventTrigger
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.gbTrigger);
+            this.Name = "CtrlEventTrigger";
+            this.Size = new System.Drawing.Size(414, 480);
+            this.gbTrigger.ResumeLayout(false);
+            this.gbTrigger.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbTrigger;
+        private System.Windows.Forms.Label lblParametrs;
+        private System.Windows.Forms.TextBox txtSql;
+        private System.Windows.Forms.Label lblSql;
+        private System.Windows.Forms.TextBox txtName;
+        private System.Windows.Forms.Label lblTriggerName;
+        private System.Windows.Forms.TextBox txtCnlNum;
+        private System.Windows.Forms.Label lblCnlNum;
+        private System.Windows.Forms.CheckBox chkActive;
+        private System.Windows.Forms.ListView lvParametrs;
+        private System.Windows.Forms.Label lblSeparatorFilter;
+        private System.Windows.Forms.TextBox txtDeviceNum;
+        private System.Windows.Forms.Label lblDeviceNum;
+        private System.Windows.Forms.Label lblSeparatorQuery;
+        private System.Windows.Forms.Button btnEditCnlNum;
+        private System.Windows.Forms.Button btnEditDeviceNum;
+        private System.Windows.Forms.Label lblTriggerType;
+        private System.Windows.Forms.TextBox txtTriggerType;
+        private System.Windows.Forms.Label lblSeparator1;
+        private System.Windows.Forms.Label lblSeparator;
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.cs
new file mode 100644
index 000000000..7de67e660
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.cs
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a control for editing event triggers option
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using Scada.Server.Modules.DbExport.Config;
+using System.Collections.Generic;
+using Scada.UI;
+using Scada.Config;
+using System.Drawing;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Represents a control for editing trigger event options.
+    /// Представляет элемент управления для редактирования параметров триггеров событий.
+    /// 
+    public partial class CtrlEventTrigger : UserControl
+    {
+        private EventTriggerOptions eventTiggerOptions;
+        private ICollection resultRange;           // range after editing
+        private bool cnlNumChanged;
+        private bool deviceNumChanged;
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CtrlEventTrigger()
+        {
+            InitializeComponent();
+            cnlNumChanged = false;
+            deviceNumChanged = false;
+        }
+
+
+        /// 
+        /// Gets or sets an editable trigger options.
+        /// 
+        internal EventTriggerOptions EventTriggerOptions
+        {
+            get
+            {
+                return eventTiggerOptions;
+            }
+            set
+            {
+                if (value != null)
+                {
+                    eventTiggerOptions = null;
+                    chkActive.Checked = value.Active;
+                    txtName.Text = value.Name;
+
+                    txtSql.AppendText(value.Query.Trim());
+                    txtCnlNum.Text = RangeUtils.RangeToStr(value.CnlNums);
+                    txtDeviceNum.Text = RangeUtils.RangeToStr(value.DeviceNums);
+
+                    List names = value.GetParamNames();
+
+                    string s;
+                    if (DbmsType == KnownDBMS.Oracle)  // oralce db
+                        s = ":";
+                    else
+                        s = "@";
+
+                    foreach (string val in names)
+                        lvParametrs.Items.Add(s + val);
+
+                    txtTriggerType.Text = LibPhrases.EventType;
+                }
+
+                eventTiggerOptions = value;
+            }
+        }
+
+        /// 
+        ///Gets editable target DbType.
+        /// 
+        internal KnownDBMS DbmsType { get; set; }
+
+        /// 
+        /// Triggers an event TriggerOptionsChanged.
+        /// 
+        private void OnEventTriggerOptionsChanged()
+        {
+            TriggerEventOptionsChanged?.Invoke(this, new ObjectChangedEventArgs(eventTiggerOptions));
+        }
+
+        /// 
+        /// An event that occurs when the properties of an edited trigger event options.
+        /// 
+        [Category("Property Changed")]
+        public event ObjectChangedEventHandler TriggerEventOptionsChanged;
+
+        /// 
+        /// Sets input focus.
+        /// 
+        public void SetFocus()
+        {
+            txtName.Select();
+        }
+
+        /// 
+        /// Clears the fields.
+        /// 
+        public void Clear()
+        {
+            eventTiggerOptions = null;
+            chkActive.Checked = false;
+            txtSql.Text = "";
+            txtCnlNum.Text = "";
+            txtDeviceNum.Text = "";
+            txtName.Text = "";
+            lvParametrs.Items.Clear();
+        }
+
+        private void txtSql_TextChanged(object sender, EventArgs e)
+        {
+            if (eventTiggerOptions != null)
+            {
+                eventTiggerOptions.Query = txtSql.Text;
+                OnEventTriggerOptionsChanged();
+            }
+        }
+
+        private void txtName_TextChanged(object sender, EventArgs e)
+        {
+            if (eventTiggerOptions != null)
+            {
+                eventTiggerOptions.Name = txtName.Text;
+                OnEventTriggerOptionsChanged();
+            }
+        }
+
+        private void chkActive_CheckedChanged(object sender, EventArgs e)
+        {
+            if (eventTiggerOptions != null)
+            {
+                eventTiggerOptions.Active = chkActive.Checked;
+                OnEventTriggerOptionsChanged();
+            }
+        }
+
+        private void btnEditCnlNum_Click(object sender, EventArgs e)
+        {
+            if (eventTiggerOptions != null)
+            {
+                if (FrmRangeEdit.EditRange(eventTiggerOptions.CnlNums))
+                {
+                    txtCnlNum.Text = RangeUtils.RangeToStr(eventTiggerOptions.CnlNums);
+                    txtCnlNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    OnEventTriggerOptionsChanged();
+                }
+            }
+
+            txtCnlNum.Select();
+            txtCnlNum.DeselectAll();
+        }
+
+        private void txtCnlNum_Validating(object sender, CancelEventArgs e)
+        {
+            if (eventTiggerOptions != null && cnlNumChanged)
+            {
+                if (RangeUtils.StrToRange(txtCnlNum.Text, true, true, out resultRange))
+                {
+                    // update the list of trigger input channels
+                    eventTiggerOptions.CnlNums.Clear();
+
+                    foreach (int val in resultRange)
+                    {
+                        eventTiggerOptions.CnlNums.Add(val);
+                    }
+
+                    txtCnlNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    OnEventTriggerOptionsChanged();
+                }
+                else
+                {
+                    // show a message
+                    txtCnlNum.ForeColor = Color.Red;
+                    ScadaUiUtils.ShowError(LibPhrases.RangeNotValid);
+                }
+            }
+        }
+
+        private void txtCnlNum_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Enter)
+                txtCnlNum_Validating(null, null);
+        }
+
+        private void txtCnlNum_TextChanged(object sender, EventArgs e)
+        {
+            cnlNumChanged = true;
+        }
+
+        private void txtCnlNum_Enter(object sender, EventArgs e)
+        {
+            cnlNumChanged = false;
+        }
+
+
+
+        private void btnEditDeviceNum_Click(object sender, EventArgs e)
+        {
+            if (eventTiggerOptions != null)
+            {
+                if (FrmRangeEdit.EditRange(eventTiggerOptions.DeviceNums))
+                {
+                    txtDeviceNum.Text = RangeUtils.RangeToStr(eventTiggerOptions.DeviceNums);
+                    txtDeviceNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    OnEventTriggerOptionsChanged();
+                }
+            }
+
+            txtDeviceNum.Select();
+            txtDeviceNum.DeselectAll();
+        }
+
+
+        private void txtDeviceNum_Validating(object sender, CancelEventArgs e)
+        {
+            if (eventTiggerOptions != null && deviceNumChanged)
+            {
+                if (RangeUtils.StrToRange(txtDeviceNum.Text, true, true, out resultRange))
+                {
+                    // update the list of trigger device nums
+                    eventTiggerOptions.DeviceNums.Clear();
+
+                    foreach (int val in resultRange)
+                    {
+                        eventTiggerOptions.DeviceNums.Add(val);
+                    }
+
+                    txtDeviceNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    OnEventTriggerOptionsChanged();
+                }
+                else
+                {
+                    // show a message
+                    txtDeviceNum.ForeColor = Color.Red;
+                    ScadaUiUtils.ShowError(LibPhrases.RangeNotValid);
+                }
+            }
+        }
+
+        private void txtDeviceNum_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Enter)
+                txtDeviceNum_Validating(null, null);
+        }
+
+        private void txtDeviceNum_TextChanged(object sender, EventArgs e)
+        {
+            deviceNumChanged = true;
+        }
+
+        private void txtDeviceNum_Enter(object sender, EventArgs e)
+        {
+            deviceNumChanged = false;
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.resx
new file mode 100644
index 000000000..27b582342
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlEventTrigger.resx
@@ -0,0 +1,143 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
+        dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAESSURBVDhPY/j//z9FGKsgNnyoLsNzbU7cfxDeU5lq
+        ABPHUIgNr59X4QTS+Hp+4/8LZRBDYHIYitExSPPuDbX/1+w49f9iazFY8wRTU6AURB5DAzIGad65pvj/
+        uwc9/28eyfnf1lYL1txsqe8HU4OhCYZBmrcvSwVrvr4/6f+mWZ7/xYT4/qeFasD9D8IommAY2WZkzaVJ
+        utboalE4IIzLZmyaQRiFA9K8dUE4Ns2ayOqQMZwB0rx5ji9JmkEYzpgxd/H/49s7/j86VwLXHOSiqoGs
+        GBsGE0DNZSAD/v37+3/l5ECibIZhCMHAUJZXWPo/MCQcxCHKZhiGEAwMD0CGAA3IQFdACGMVJAVjFSQe
+        /2cAAKIjwdj3D0MKAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
+        dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAESSURBVDhPY/j//z9FGKsgNnyoLsNzbU7cfxDeU5lq
+        ABPHUIgNr59X4QTS+Hp+4/8LZRBDYHIYitExSPPuDbX/1+w49f9iazFY8wRTU6AURB5DAzIGad65pvj/
+        uwc9/28eyfnf1lYL1txsqe8HU4OhCYZBmrcvSwVrvr4/6f+mWZ7/xYT4/qeFasD9D8IommAY2WZkzaVJ
+        utboalE4IIzLZmyaQRiFA9K8dUE4Ns2ayOqQMZwB0rx5ji9JmkEYzpgxd/H/49s7/j86VwLXHOSiqoGs
+        GBsGE0DNZSAD/v37+3/l5ECibIZhCMHAUJZXWPo/MCQcxCHKZhiGEAwMD0CGAA3IQFdACGMVJAVjFSQe
+        /2cAAKIjwdj3D0MKAAAAAElFTkSuQmCC
+
+  
+
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.Designer.cs
new file mode 100644
index 000000000..8c5572cc4
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.Designer.cs
@@ -0,0 +1,242 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class CtrlGeneralOptions
+    {
+        ///  
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        ///  
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        ///  
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            this.gbGeneral = new System.Windows.Forms.GroupBox();
+            this.numOutCnlNum = new System.Windows.Forms.NumericUpDown();
+            this.lblOutCnlNum = new System.Windows.Forms.Label();
+            this.numDataLifetime = new System.Windows.Forms.NumericUpDown();
+            this.lblDataLifetime = new System.Windows.Forms.Label();
+            this.numMaxQueueSize = new System.Windows.Forms.NumericUpDown();
+            this.lblMaxQueueSize = new System.Windows.Forms.Label();
+            this.lblName = new System.Windows.Forms.Label();
+            this.lblID = new System.Windows.Forms.Label();
+            this.chkActive = new System.Windows.Forms.CheckBox();
+            this.txtName = new System.Windows.Forms.TextBox();
+            this.txtTargetID = new System.Windows.Forms.TextBox();
+            this.gbGeneral.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numOutCnlNum)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numDataLifetime)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numMaxQueueSize)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // gbGeneral
+            // 
+            this.gbGeneral.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.gbGeneral.Controls.Add(this.numOutCnlNum);
+            this.gbGeneral.Controls.Add(this.lblOutCnlNum);
+            this.gbGeneral.Controls.Add(this.numDataLifetime);
+            this.gbGeneral.Controls.Add(this.lblDataLifetime);
+            this.gbGeneral.Controls.Add(this.numMaxQueueSize);
+            this.gbGeneral.Controls.Add(this.lblMaxQueueSize);
+            this.gbGeneral.Controls.Add(this.lblName);
+            this.gbGeneral.Controls.Add(this.lblID);
+            this.gbGeneral.Controls.Add(this.chkActive);
+            this.gbGeneral.Controls.Add(this.txtName);
+            this.gbGeneral.Controls.Add(this.txtTargetID);
+            this.gbGeneral.Location = new System.Drawing.Point(0, 0);
+            this.gbGeneral.Name = "gbGeneral";
+            this.gbGeneral.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
+            this.gbGeneral.Size = new System.Drawing.Size(414, 388);
+            this.gbGeneral.TabIndex = 0;
+            this.gbGeneral.TabStop = false;
+            this.gbGeneral.Text = "General";
+            // 
+            // numOutCnlNum
+            // 
+            this.numOutCnlNum.Location = new System.Drawing.Point(13, 211);
+            this.numOutCnlNum.Maximum = new decimal(new int[] {
+            65635,
+            0,
+            0,
+            0});
+            this.numOutCnlNum.Name = "numOutCnlNum";
+            this.numOutCnlNum.Size = new System.Drawing.Size(120, 20);
+            this.numOutCnlNum.TabIndex = 10;
+            this.numOutCnlNum.Value = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numOutCnlNum.ValueChanged += new System.EventHandler(this.numOutCnlNum_ValueChanged);
+            // 
+            // lblOutCnlNum
+            // 
+            this.lblOutCnlNum.AutoSize = true;
+            this.lblOutCnlNum.Location = new System.Drawing.Point(10, 195);
+            this.lblOutCnlNum.Name = "lblOutCnlNum";
+            this.lblOutCnlNum.Size = new System.Drawing.Size(118, 13);
+            this.lblOutCnlNum.TabIndex = 9;
+            this.lblOutCnlNum.Text = "Output channel number";
+            // 
+            // numDataLifetime
+            // 
+            this.numDataLifetime.Location = new System.Drawing.Point(13, 163);
+            this.numDataLifetime.Maximum = new decimal(new int[] {
+            3600,
+            0,
+            0,
+            0});
+            this.numDataLifetime.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numDataLifetime.Name = "numDataLifetime";
+            this.numDataLifetime.Size = new System.Drawing.Size(120, 20);
+            this.numDataLifetime.TabIndex = 8;
+            this.numDataLifetime.Value = new decimal(new int[] {
+            30,
+            0,
+            0,
+            0});
+            this.numDataLifetime.ValueChanged += new System.EventHandler(this.numDataLifetime_ValueChanged);
+            // 
+            // lblDataLifetime
+            // 
+            this.lblDataLifetime.AutoSize = true;
+            this.lblDataLifetime.Location = new System.Drawing.Point(10, 147);
+            this.lblDataLifetime.Name = "lblDataLifetime";
+            this.lblDataLifetime.Size = new System.Drawing.Size(91, 13);
+            this.lblDataLifetime.TabIndex = 7;
+            this.lblDataLifetime.Text = "Data life time, sec";
+            // 
+            // numMaxQueueSize
+            // 
+            this.numMaxQueueSize.Location = new System.Drawing.Point(13, 110);
+            this.numMaxQueueSize.Maximum = new decimal(new int[] {
+            86400,
+            0,
+            0,
+            0});
+            this.numMaxQueueSize.Minimum = new decimal(new int[] {
+            1,
+            0,
+            0,
+            0});
+            this.numMaxQueueSize.Name = "numMaxQueueSize";
+            this.numMaxQueueSize.Size = new System.Drawing.Size(120, 20);
+            this.numMaxQueueSize.TabIndex = 6;
+            this.numMaxQueueSize.Value = new decimal(new int[] {
+            3600,
+            0,
+            0,
+            0});
+            this.numMaxQueueSize.ValueChanged += new System.EventHandler(this.numMaxQueueSize_ValueChanged);
+            // 
+            // lblMaxQueueSize
+            // 
+            this.lblMaxQueueSize.AutoSize = true;
+            this.lblMaxQueueSize.Location = new System.Drawing.Point(10, 94);
+            this.lblMaxQueueSize.Name = "lblMaxQueueSize";
+            this.lblMaxQueueSize.Size = new System.Drawing.Size(105, 13);
+            this.lblMaxQueueSize.TabIndex = 5;
+            this.lblMaxQueueSize.Text = "Maximum queue size";
+            // 
+            // lblName
+            // 
+            this.lblName.AutoSize = true;
+            this.lblName.Location = new System.Drawing.Point(74, 43);
+            this.lblName.Name = "lblName";
+            this.lblName.Size = new System.Drawing.Size(35, 13);
+            this.lblName.TabIndex = 3;
+            this.lblName.Text = "Name";
+            // 
+            // lblID
+            // 
+            this.lblID.AutoSize = true;
+            this.lblID.Location = new System.Drawing.Point(10, 43);
+            this.lblID.Name = "lblID";
+            this.lblID.Size = new System.Drawing.Size(52, 13);
+            this.lblID.TabIndex = 1;
+            this.lblID.Text = "Target ID";
+            // 
+            // chkActive
+            // 
+            this.chkActive.AutoSize = true;
+            this.chkActive.Location = new System.Drawing.Point(13, 19);
+            this.chkActive.Name = "chkActive";
+            this.chkActive.Size = new System.Drawing.Size(56, 17);
+            this.chkActive.TabIndex = 0;
+            this.chkActive.Text = "Active";
+            this.chkActive.UseVisualStyleBackColor = true;
+            this.chkActive.CheckedChanged += new System.EventHandler(this.chkActive_CheckedChanged);
+            // 
+            // txtName
+            // 
+            this.txtName.Location = new System.Drawing.Point(77, 59);
+            this.txtName.Name = "txtName";
+            this.txtName.Size = new System.Drawing.Size(324, 20);
+            this.txtName.TabIndex = 4;
+            this.txtName.TextChanged += new System.EventHandler(this.txtName_TextChanged);
+            // 
+            // txtTargetID
+            // 
+            this.txtTargetID.Location = new System.Drawing.Point(13, 59);
+            this.txtTargetID.Name = "txtTargetID";
+            this.txtTargetID.ReadOnly = true;
+            this.txtTargetID.Size = new System.Drawing.Size(58, 20);
+            this.txtTargetID.TabIndex = 2;
+            this.txtTargetID.TabStop = false;
+            // 
+            // CtrlGeneralOptions
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.gbGeneral);
+            this.Name = "CtrlGeneralOptions";
+            this.Size = new System.Drawing.Size(414, 388);
+            this.gbGeneral.ResumeLayout(false);
+            this.gbGeneral.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.numOutCnlNum)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numDataLifetime)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.numMaxQueueSize)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbGeneral;
+        private System.Windows.Forms.CheckBox chkActive;
+        private System.Windows.Forms.TextBox txtName;
+        private System.Windows.Forms.TextBox txtTargetID;
+        private System.Windows.Forms.Label lblName;
+        private System.Windows.Forms.Label lblID;
+        private System.Windows.Forms.NumericUpDown numOutCnlNum;
+        private System.Windows.Forms.Label lblOutCnlNum;
+        private System.Windows.Forms.NumericUpDown numDataLifetime;
+        private System.Windows.Forms.Label lblDataLifetime;
+        private System.Windows.Forms.NumericUpDown numMaxQueueSize;
+        private System.Windows.Forms.Label lblMaxQueueSize;
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.cs
new file mode 100644
index 000000000..2176c0c0d
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.cs
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a control for editing general options
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using Scada.Server.Modules.DbExport.Config;
+using Scada.UI;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Represents a control for editing general options.
+    /// Представляет элемент управления для редактирования общих настроек.
+    /// 
+    public partial class CtrlGeneralOptions : UserControl
+    {
+        private GeneralOptions generalOptions;
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CtrlGeneralOptions()
+        {
+            InitializeComponent();
+            generalOptions = null;
+        }
+
+
+        /// 
+        /// Gets or sest an editable general options.
+        /// 
+        internal GeneralOptions GeneralOptions
+        {
+            get
+            {
+                return generalOptions;
+            }
+            set
+            {
+                if (value != null)
+                {
+                    generalOptions = null;
+                    txtTargetID.Text = value.ID.ToString();
+                    txtName.Text = value.Name;
+                    chkActive.Checked = value.Active;
+                    numMaxQueueSize.Value = value.MaxQueueSize;
+                    numDataLifetime.Value = value.DataLifetime;
+                    numOutCnlNum.Value = value.OutCnlNum;
+                }
+
+                generalOptions = value;
+            }
+        }
+
+        /// 
+        /// Trigger an event GeneralOptionsChanged.
+        /// 
+        private void OnGeneralOptionsChanged()
+        {
+            GeneralOptionsChanged?.Invoke(this, new ObjectChangedEventArgs(generalOptions));
+        }
+
+        /// 
+        /// An event that occurs when the properties of an edited gerenal options change.
+        /// 
+        [Category("Property Changed")]
+        public event ObjectChangedEventHandler GeneralOptionsChanged;
+
+        /// 
+        /// Set input focus.
+        /// 
+        public void SetFocus()
+        {
+            txtName.Select();
+        }
+
+
+        private void txtName_TextChanged(object sender, EventArgs e)
+        {
+            if (generalOptions != null)
+            {
+                generalOptions.Name = txtName.Text;
+                OnGeneralOptionsChanged();
+            }
+        }
+
+        private void chkActive_CheckedChanged(object sender, EventArgs e)
+        {
+            if (generalOptions != null)
+            {
+                generalOptions.Active = chkActive.Checked;            
+                OnGeneralOptionsChanged();
+            }
+        }
+
+        private void numMaxQueueSize_ValueChanged(object sender, EventArgs e)
+        {
+            if (generalOptions != null)
+            {
+                generalOptions.MaxQueueSize = Convert.ToInt32(numMaxQueueSize.Value);
+                OnGeneralOptionsChanged();
+            }
+        }
+
+        private void numDataLifetime_ValueChanged(object sender, EventArgs e)
+        {
+            if (generalOptions != null)
+            {
+                generalOptions.DataLifetime = Convert.ToInt32(numDataLifetime.Value);
+                OnGeneralOptionsChanged();
+            }
+        }
+
+        private void numOutCnlNum_ValueChanged(object sender, EventArgs e)
+        {
+            if (generalOptions != null)
+            {
+                generalOptions.OutCnlNum = Convert.ToInt32(numOutCnlNum.Value);
+                OnGeneralOptionsChanged();
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDBExport/Properties/Resources.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.resx
similarity index 100%
rename from ScadaServer/OpenModules/ModDBExport/Properties/Resources.resx
rename to ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlGeneralOptions.resx
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.Designer.cs
new file mode 100644
index 000000000..5a24742a8
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.Designer.cs
@@ -0,0 +1,321 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class CtrlTrigger
+    {
+        ///  
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        ///  
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Component Designer generated code
+
+        ///  
+        /// Required method for Designer support - do not modify 
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CtrlTrigger));
+            this.gbTrigger = new System.Windows.Forms.GroupBox();
+            this.lblTriggerType = new System.Windows.Forms.Label();
+            this.txtTriggerType = new System.Windows.Forms.TextBox();
+            this.btnEditDeviceNum = new System.Windows.Forms.Button();
+            this.btnEditCnlNum = new System.Windows.Forms.Button();
+            this.lblSeparatorQuery = new System.Windows.Forms.Label();
+            this.lblSeparatorFilter = new System.Windows.Forms.Label();
+            this.txtDeviceNum = new System.Windows.Forms.TextBox();
+            this.lblDeviceNum = new System.Windows.Forms.Label();
+            this.lvParametrs = new System.Windows.Forms.ListView();
+            this.txtName = new System.Windows.Forms.TextBox();
+            this.lblParametrs = new System.Windows.Forms.Label();
+            this.txtSql = new System.Windows.Forms.TextBox();
+            this.lblTriggerName = new System.Windows.Forms.Label();
+            this.lblSql = new System.Windows.Forms.Label();
+            this.txtCnlNum = new System.Windows.Forms.TextBox();
+            this.chkSingleQuery = new System.Windows.Forms.CheckBox();
+            this.chkActive = new System.Windows.Forms.CheckBox();
+            this.lblCnlNum = new System.Windows.Forms.Label();
+            this.lblSeparator1 = new System.Windows.Forms.Label();
+            this.lblSeparator = new System.Windows.Forms.Label();
+            this.gbTrigger.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // gbTrigger
+            // 
+            this.gbTrigger.Controls.Add(this.lblTriggerType);
+            this.gbTrigger.Controls.Add(this.txtTriggerType);
+            this.gbTrigger.Controls.Add(this.btnEditDeviceNum);
+            this.gbTrigger.Controls.Add(this.btnEditCnlNum);
+            this.gbTrigger.Controls.Add(this.lblSeparatorQuery);
+            this.gbTrigger.Controls.Add(this.lblSeparatorFilter);
+            this.gbTrigger.Controls.Add(this.txtDeviceNum);
+            this.gbTrigger.Controls.Add(this.lblDeviceNum);
+            this.gbTrigger.Controls.Add(this.lvParametrs);
+            this.gbTrigger.Controls.Add(this.txtName);
+            this.gbTrigger.Controls.Add(this.lblParametrs);
+            this.gbTrigger.Controls.Add(this.txtSql);
+            this.gbTrigger.Controls.Add(this.lblTriggerName);
+            this.gbTrigger.Controls.Add(this.lblSql);
+            this.gbTrigger.Controls.Add(this.txtCnlNum);
+            this.gbTrigger.Controls.Add(this.chkSingleQuery);
+            this.gbTrigger.Controls.Add(this.chkActive);
+            this.gbTrigger.Controls.Add(this.lblCnlNum);
+            this.gbTrigger.Controls.Add(this.lblSeparator1);
+            this.gbTrigger.Controls.Add(this.lblSeparator);
+            this.gbTrigger.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.gbTrigger.Location = new System.Drawing.Point(0, 0);
+            this.gbTrigger.Name = "gbTrigger";
+            this.gbTrigger.Size = new System.Drawing.Size(414, 480);
+            this.gbTrigger.TabIndex = 0;
+            this.gbTrigger.TabStop = false;
+            this.gbTrigger.Text = "Triggers";
+            // 
+            // lblTriggerType
+            // 
+            this.lblTriggerType.AutoSize = true;
+            this.lblTriggerType.Location = new System.Drawing.Point(217, 38);
+            this.lblTriggerType.Name = "lblTriggerType";
+            this.lblTriggerType.Size = new System.Drawing.Size(63, 13);
+            this.lblTriggerType.TabIndex = 3;
+            this.lblTriggerType.Text = "Trigger type";
+            // 
+            // txtTriggerType
+            // 
+            this.txtTriggerType.Location = new System.Drawing.Point(220, 54);
+            this.txtTriggerType.Name = "txtTriggerType";
+            this.txtTriggerType.ReadOnly = true;
+            this.txtTriggerType.Size = new System.Drawing.Size(177, 20);
+            this.txtTriggerType.TabIndex = 4;
+            this.txtTriggerType.TabStop = false;
+            // 
+            // btnEditDeviceNum
+            // 
+            this.btnEditDeviceNum.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnEditDeviceNum.Image = ((System.Drawing.Image)(resources.GetObject("btnEditDeviceNum.Image")));
+            this.btnEditDeviceNum.Location = new System.Drawing.Point(377, 171);
+            this.btnEditDeviceNum.Name = "btnEditDeviceNum";
+            this.btnEditDeviceNum.Size = new System.Drawing.Size(20, 20);
+            this.btnEditDeviceNum.TabIndex = 12;
+            this.btnEditDeviceNum.UseVisualStyleBackColor = true;
+            this.btnEditDeviceNum.Click += new System.EventHandler(this.btnEditDeviceNum_Click);
+            // 
+            // btnEditCnlNum
+            // 
+            this.btnEditCnlNum.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.btnEditCnlNum.Image = ((System.Drawing.Image)(resources.GetObject("btnEditCnlNum.Image")));
+            this.btnEditCnlNum.Location = new System.Drawing.Point(377, 129);
+            this.btnEditCnlNum.Name = "btnEditCnlNum";
+            this.btnEditCnlNum.Size = new System.Drawing.Size(20, 20);
+            this.btnEditCnlNum.TabIndex = 9;
+            this.btnEditCnlNum.UseVisualStyleBackColor = true;
+            this.btnEditCnlNum.Click += new System.EventHandler(this.btnEditCnlNum_Click);
+            // 
+            // lblSeparatorQuery
+            // 
+            this.lblSeparatorQuery.AutoSize = true;
+            this.lblSeparatorQuery.ForeColor = System.Drawing.SystemColors.WindowText;
+            this.lblSeparatorQuery.Location = new System.Drawing.Point(10, 208);
+            this.lblSeparatorQuery.Name = "lblSeparatorQuery";
+            this.lblSeparatorQuery.Size = new System.Drawing.Size(35, 13);
+            this.lblSeparatorQuery.TabIndex = 13;
+            this.lblSeparatorQuery.Text = "Query";
+            // 
+            // lblSeparatorFilter
+            // 
+            this.lblSeparatorFilter.AutoSize = true;
+            this.lblSeparatorFilter.ForeColor = System.Drawing.SystemColors.WindowText;
+            this.lblSeparatorFilter.Location = new System.Drawing.Point(10, 91);
+            this.lblSeparatorFilter.Name = "lblSeparatorFilter";
+            this.lblSeparatorFilter.Size = new System.Drawing.Size(34, 13);
+            this.lblSeparatorFilter.TabIndex = 5;
+            this.lblSeparatorFilter.Text = "Filtres";
+            // 
+            // txtDeviceNum
+            // 
+            this.txtDeviceNum.Location = new System.Drawing.Point(13, 171);
+            this.txtDeviceNum.Name = "txtDeviceNum";
+            this.txtDeviceNum.Size = new System.Drawing.Size(358, 20);
+            this.txtDeviceNum.TabIndex = 11;
+            this.txtDeviceNum.TextChanged += new System.EventHandler(this.txtDeviceNum_TextChanged);
+            this.txtDeviceNum.Enter += new System.EventHandler(this.txtDeviceNum_Enter);
+            this.txtDeviceNum.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtDeviceNum_KeyDown);
+            this.txtDeviceNum.Validating += new System.ComponentModel.CancelEventHandler(this.txtDeviceNum_Validating);
+            // 
+            // lblDeviceNum
+            // 
+            this.lblDeviceNum.AutoSize = true;
+            this.lblDeviceNum.Location = new System.Drawing.Point(10, 155);
+            this.lblDeviceNum.Name = "lblDeviceNum";
+            this.lblDeviceNum.Size = new System.Drawing.Size(84, 13);
+            this.lblDeviceNum.TabIndex = 10;
+            this.lblDeviceNum.Text = "Device numbers";
+            // 
+            // lvParametrs
+            // 
+            this.lvParametrs.BackColor = System.Drawing.SystemColors.MenuBar;
+            this.lvParametrs.HideSelection = false;
+            this.lvParametrs.Location = new System.Drawing.Point(13, 388);
+            this.lvParametrs.MultiSelect = false;
+            this.lvParametrs.Name = "lvParametrs";
+            this.lvParametrs.Size = new System.Drawing.Size(384, 75);
+            this.lvParametrs.TabIndex = 19;
+            this.lvParametrs.UseCompatibleStateImageBehavior = false;
+            this.lvParametrs.View = System.Windows.Forms.View.List;
+            // 
+            // txtName
+            // 
+            this.txtName.Location = new System.Drawing.Point(13, 54);
+            this.txtName.Name = "txtName";
+            this.txtName.Size = new System.Drawing.Size(202, 20);
+            this.txtName.TabIndex = 2;
+            this.txtName.TextChanged += new System.EventHandler(this.txtName_TextChanged);
+            // 
+            // lblParametrs
+            // 
+            this.lblParametrs.AutoSize = true;
+            this.lblParametrs.Location = new System.Drawing.Point(10, 372);
+            this.lblParametrs.Name = "lblParametrs";
+            this.lblParametrs.Size = new System.Drawing.Size(99, 13);
+            this.lblParametrs.TabIndex = 18;
+            this.lblParametrs.Text = "Available parametrs";
+            // 
+            // txtSql
+            // 
+            this.txtSql.Location = new System.Drawing.Point(13, 266);
+            this.txtSql.Multiline = true;
+            this.txtSql.Name = "txtSql";
+            this.txtSql.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtSql.Size = new System.Drawing.Size(384, 98);
+            this.txtSql.TabIndex = 17;
+            this.txtSql.TextChanged += new System.EventHandler(this.txtSql_TextChanged);
+            // 
+            // lblTriggerName
+            // 
+            this.lblTriggerName.AutoSize = true;
+            this.lblTriggerName.Location = new System.Drawing.Point(10, 38);
+            this.lblTriggerName.Name = "lblTriggerName";
+            this.lblTriggerName.Size = new System.Drawing.Size(69, 13);
+            this.lblTriggerName.TabIndex = 1;
+            this.lblTriggerName.Text = "Trigger name";
+            // 
+            // lblSql
+            // 
+            this.lblSql.AutoSize = true;
+            this.lblSql.Location = new System.Drawing.Point(10, 250);
+            this.lblSql.Name = "lblSql";
+            this.lblSql.Size = new System.Drawing.Size(28, 13);
+            this.lblSql.TabIndex = 16;
+            this.lblSql.Text = "SQL";
+            // 
+            // txtCnlNum
+            // 
+            this.txtCnlNum.Location = new System.Drawing.Point(13, 129);
+            this.txtCnlNum.Name = "txtCnlNum";
+            this.txtCnlNum.Size = new System.Drawing.Size(358, 20);
+            this.txtCnlNum.TabIndex = 8;
+            this.txtCnlNum.TextChanged += new System.EventHandler(this.txtCnlNum_TextChanged);
+            this.txtCnlNum.Enter += new System.EventHandler(this.txtCnlNum_Enter);
+            this.txtCnlNum.KeyDown += new System.Windows.Forms.KeyEventHandler(this.txtCnlNum_KeyDown);
+            this.txtCnlNum.Validating += new System.ComponentModel.CancelEventHandler(this.txtCnlNum_Validating);
+            // 
+            // chkSingleQuery
+            // 
+            this.chkSingleQuery.AutoSize = true;
+            this.chkSingleQuery.Location = new System.Drawing.Point(13, 230);
+            this.chkSingleQuery.Name = "chkSingleQuery";
+            this.chkSingleQuery.Size = new System.Drawing.Size(203, 17);
+            this.chkSingleQuery.TabIndex = 15;
+            this.chkSingleQuery.Text = "Single query (input channels required)";
+            this.chkSingleQuery.UseVisualStyleBackColor = true;
+            this.chkSingleQuery.CheckedChanged += new System.EventHandler(this.chkSingleQuery_CheckedChanged);
+            // 
+            // chkActive
+            // 
+            this.chkActive.AutoSize = true;
+            this.chkActive.Location = new System.Drawing.Point(13, 19);
+            this.chkActive.Name = "chkActive";
+            this.chkActive.Size = new System.Drawing.Size(56, 17);
+            this.chkActive.TabIndex = 0;
+            this.chkActive.Text = "Active";
+            this.chkActive.UseVisualStyleBackColor = true;
+            this.chkActive.CheckedChanged += new System.EventHandler(this.chkActive_CheckedChanged);
+            // 
+            // lblCnlNum
+            // 
+            this.lblCnlNum.AutoSize = true;
+            this.lblCnlNum.Location = new System.Drawing.Point(10, 113);
+            this.lblCnlNum.Name = "lblCnlNum";
+            this.lblCnlNum.Size = new System.Drawing.Size(77, 13);
+            this.lblCnlNum.TabIndex = 7;
+            this.lblCnlNum.Text = "Input channels";
+            // 
+            // lblSeparator1
+            // 
+            this.lblSeparator1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.lblSeparator1.Location = new System.Drawing.Point(13, 215);
+            this.lblSeparator1.Name = "lblSeparator1";
+            this.lblSeparator1.Size = new System.Drawing.Size(385, 2);
+            this.lblSeparator1.TabIndex = 14;
+            // 
+            // lblSeparator
+            // 
+            this.lblSeparator.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.lblSeparator.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.lblSeparator.ForeColor = System.Drawing.SystemColors.ControlText;
+            this.lblSeparator.Location = new System.Drawing.Point(13, 98);
+            this.lblSeparator.Name = "lblSeparator";
+            this.lblSeparator.Size = new System.Drawing.Size(385, 2);
+            this.lblSeparator.TabIndex = 6;
+            // 
+            // CtrlTrigger
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.gbTrigger);
+            this.Name = "CtrlTrigger";
+            this.Size = new System.Drawing.Size(414, 480);
+            this.gbTrigger.ResumeLayout(false);
+            this.gbTrigger.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.GroupBox gbTrigger;
+        private System.Windows.Forms.CheckBox chkActive;
+        private System.Windows.Forms.Label lblCnlNum;
+        private System.Windows.Forms.TextBox txtCnlNum;
+        private System.Windows.Forms.TextBox txtName;
+        private System.Windows.Forms.Label lblTriggerName;
+        private System.Windows.Forms.ListView lvParametrs;
+        private System.Windows.Forms.Label lblParametrs;
+        private System.Windows.Forms.TextBox txtSql;
+        private System.Windows.Forms.Label lblSql;
+        private System.Windows.Forms.CheckBox chkSingleQuery;
+        private System.Windows.Forms.TextBox txtDeviceNum;
+        private System.Windows.Forms.Label lblDeviceNum;
+        private System.Windows.Forms.Label lblSeparatorQuery;
+        private System.Windows.Forms.Label lblSeparatorFilter;
+        private System.Windows.Forms.Button btnEditCnlNum;
+        private System.Windows.Forms.Button btnEditDeviceNum;
+        private System.Windows.Forms.Label lblTriggerType;
+        private System.Windows.Forms.TextBox txtTriggerType;
+        private System.Windows.Forms.Label lblSeparator1;
+        private System.Windows.Forms.Label lblSeparator;
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.cs
new file mode 100644
index 000000000..ecc175b20
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.cs
@@ -0,0 +1,335 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Represents a control for editing triggers option
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using Scada.Server.Modules.DbExport.Config;
+using System.Collections.Generic;
+using Scada.UI;
+using Scada.Config;
+using System.Drawing;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Represents a control for editing trigger options.
+    /// Представляет элемент управления для редактирования параметров триггеров.
+    /// 
+    public partial class CtrlTrigger : UserControl
+    {
+        private DataTriggerOptions triggerOptions;
+        private ICollection resultRange;   // range after editing
+        private bool cnlNumChanged;
+        private bool deviceNumChanged;
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public CtrlTrigger()
+        {
+            InitializeComponent();
+            triggerOptions = null;
+            cnlNumChanged = false;
+            deviceNumChanged = false;
+        }
+
+
+        /// 
+        /// Gets or sets an editable trigger options.
+        /// 
+        internal DataTriggerOptions DataTriggerOptions
+        {
+            get
+            {
+                return triggerOptions;
+            }
+            set
+            {
+                if (value != null)
+                {
+                    triggerOptions = null;
+                    chkActive.Checked = value.Active;
+                    chkSingleQuery.Checked = value.SingleQuery;
+                    chkSingleQuery.Enabled = true;
+                    txtName.Text = value.Name;
+
+                    txtSql.AppendText(value.Query.Trim());
+                    txtCnlNum.Text = RangeUtils.RangeToStr(value.CnlNums);
+                    txtDeviceNum.Text = RangeUtils.RangeToStr(value.DeviceNums);
+
+                    List names = value.GetParamNames();
+
+                    string s;
+                    if (DbmsType == KnownDBMS.Oracle)  // oralce db
+                        s = ":";
+                    else
+                        s = "@";
+
+                    foreach (string val in names)
+                        lvParametrs.Items.Add(s+val);
+
+                    if (value.TriggerType == "CurDataTrigger")
+                        txtTriggerType.Text = LibPhrases.CurDataType;
+                    if (value.TriggerType == "ArcDataTrigger")
+                        txtTriggerType.Text = LibPhrases.ArcDataType;
+
+                    if (txtCnlNum.Text == "")
+                    {
+                        chkSingleQuery.Checked = false;
+                        chkSingleQuery.Enabled = false;
+                    }
+                    else
+                    {
+                        chkSingleQuery.Enabled = true;
+                    }
+                }
+
+                triggerOptions = value;
+            }
+        }
+
+        /// 
+        ///Gets editable target DbType.
+        /// 
+        internal KnownDBMS DbmsType { get; set; }
+       
+
+        /// 
+        /// Trigges an event TriggerOptionsChanged.
+        /// 
+        private void OnTriggerOptionsChanged()
+        {
+            TriggerOptionsChanged?.Invoke(this, new ObjectChangedEventArgs(triggerOptions));
+        }
+
+        /// 
+        /// An event that occurs when the properties of an edited trigger options.
+        /// 
+        [Category("Property Changed")]
+        public event ObjectChangedEventHandler TriggerOptionsChanged;
+
+        /// 
+        /// Set input focus.
+        /// 
+        public void SetFocus()
+        {
+            txtName.Select();
+        }
+
+        /// 
+        /// Clears the fields.
+        /// 
+        public void Clear()
+        {
+            triggerOptions = null;
+            chkActive.Checked = false;
+            txtSql.Text = "";
+            txtCnlNum.Text = "";
+            txtName.Text = "";
+            chkSingleQuery.Checked = false;
+            lvParametrs.Items.Clear();
+        }
+
+        private void txtSql_TextChanged(object sender, EventArgs e)
+        {
+            if (triggerOptions != null)
+            {
+                triggerOptions.Query = txtSql.Text;
+                OnTriggerOptionsChanged();
+            }
+        }
+
+        private void chkActive_CheckedChanged(object sender, EventArgs e)
+        {
+            if (triggerOptions != null)
+            {
+                triggerOptions.Active = chkActive.Checked;
+                OnTriggerOptionsChanged();
+            }
+        }
+
+        private void chkSingleQuery_CheckedChanged(object sender, EventArgs e)
+        {
+            if (triggerOptions != null)
+            {
+                triggerOptions.SingleQuery = chkSingleQuery.Checked;
+                OnTriggerOptionsChanged();
+
+                lvParametrs.Items.Clear();
+                List names = triggerOptions.GetParamNames();
+
+                string s;
+                if (DbmsType == KnownDBMS.Oracle)  // oralce db
+                    s = ":";
+                else
+                    s = "@";
+
+                foreach (string val in names)
+                    lvParametrs.Items.Add(s + val);
+            }
+        }
+
+        private void txtName_TextChanged(object sender, EventArgs e)
+        {
+            if (triggerOptions != null)
+            {
+                triggerOptions.Name = txtName.Text;
+                OnTriggerOptionsChanged();
+            }
+        }
+
+
+        private void btnEditCnlNum_Click(object sender, EventArgs e)
+        {
+            if (triggerOptions != null)
+            {
+                if (FrmRangeEdit.EditRange(triggerOptions.CnlNums))
+                {
+                    txtCnlNum.Text = RangeUtils.RangeToStr(triggerOptions.CnlNums);
+                    txtCnlNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    if (txtCnlNum.Text == "")
+                    {
+                        chkSingleQuery.Checked = false;
+                        chkSingleQuery.Enabled = false;
+                    }
+                    else
+                    {
+                        chkSingleQuery.Enabled = true;
+                    }
+
+                    OnTriggerOptionsChanged();
+                }
+            }
+
+            txtCnlNum.Select();
+            txtCnlNum.DeselectAll();
+        }
+
+        private void txtCnlNum_Validating(object sender, CancelEventArgs e)
+        {
+            if (triggerOptions != null && cnlNumChanged)
+            {
+                if (RangeUtils.StrToRange(txtCnlNum.Text, true, true, out resultRange))
+                {
+                    // update the list of trigger input channels
+                    triggerOptions.CnlNums.Clear();
+
+                    foreach (int val in resultRange)
+                    {
+                        triggerOptions.CnlNums.Add(val);
+                    }
+
+                    txtCnlNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    if (txtCnlNum.Text == "")
+                    {
+                        chkSingleQuery.Checked = false;
+                        chkSingleQuery.Enabled = false;
+                    }
+                    else
+                    {
+                        chkSingleQuery.Enabled = true;
+                    }
+
+                    OnTriggerOptionsChanged();
+                }
+                else
+                {
+                    // show a message
+                    txtCnlNum.ForeColor = Color.Red;
+                    ScadaUiUtils.ShowError(LibPhrases.RangeNotValid);
+                }
+            }
+        }
+
+        private void txtCnlNum_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Enter)
+                txtCnlNum_Validating(null, null);
+        }
+
+        private void txtCnlNum_TextChanged(object sender, EventArgs e)
+        {
+            cnlNumChanged = true;    
+        }
+
+        private void txtCnlNum_Enter(object sender, EventArgs e)
+        {
+            cnlNumChanged = false;
+        }
+
+        private void btnEditDeviceNum_Click(object sender, EventArgs e)
+        {
+            if (triggerOptions != null)
+            {
+                if (FrmRangeEdit.EditRange(triggerOptions.DeviceNums))
+                {
+                    txtDeviceNum.Text = RangeUtils.RangeToStr(triggerOptions.DeviceNums);
+                    txtDeviceNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+               
+                    OnTriggerOptionsChanged();
+                }
+            }
+
+            txtDeviceNum.Select();
+            txtDeviceNum.DeselectAll();
+        }
+
+
+        private void txtDeviceNum_Validating(object sender, CancelEventArgs e)
+        {
+            if (triggerOptions != null && deviceNumChanged)
+            {
+                if (RangeUtils.StrToRange(txtDeviceNum.Text, true, true, out resultRange))
+                {
+                    // update the list of trigger device nums
+                    triggerOptions.DeviceNums.Clear();
+
+                    foreach (int val in resultRange)
+                    {
+                        triggerOptions.DeviceNums.Add(val);
+                    }
+
+                    txtDeviceNum.ForeColor = Color.FromKnownColor(KnownColor.WindowText);
+
+                    OnTriggerOptionsChanged();
+                }
+                else
+                {
+                    // show a message
+                    txtDeviceNum.ForeColor = Color.Red;
+                    ScadaUiUtils.ShowError(LibPhrases.RangeNotValid);
+                }
+            }
+        }
+
+        private void txtDeviceNum_KeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.KeyCode == Keys.Enter)
+                txtDeviceNum_Validating(null, null);
+        }
+
+        private void txtDeviceNum_TextChanged(object sender, EventArgs e)
+        {
+            deviceNumChanged = true;
+        }
+
+        private void txtDeviceNum_Enter(object sender, EventArgs e)
+        {
+            deviceNumChanged = false;
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.resx
new file mode 100644
index 000000000..27b582342
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/CtrlTrigger.resx
@@ -0,0 +1,143 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
+        dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAESSURBVDhPY/j//z9FGKsgNnyoLsNzbU7cfxDeU5lq
+        ABPHUIgNr59X4QTS+Hp+4/8LZRBDYHIYitExSPPuDbX/1+w49f9iazFY8wRTU6AURB5DAzIGad65pvj/
+        uwc9/28eyfnf1lYL1txsqe8HU4OhCYZBmrcvSwVrvr4/6f+mWZ7/xYT4/qeFasD9D8IommAY2WZkzaVJ
+        utboalE4IIzLZmyaQRiFA9K8dUE4Ns2ayOqQMZwB0rx5ji9JmkEYzpgxd/H/49s7/j86VwLXHOSiqoGs
+        GBsGE0DNZSAD/v37+3/l5ECibIZhCMHAUJZXWPo/MCQcxCHKZhiGEAwMD0CGAA3IQFdACGMVJAVjFSQe
+        /2cAAKIjwdj3D0MKAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m
+        dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAESSURBVDhPY/j//z9FGKsgNnyoLsNzbU7cfxDeU5lq
+        ABPHUIgNr59X4QTS+Hp+4/8LZRBDYHIYitExSPPuDbX/1+w49f9iazFY8wRTU6AURB5DAzIGad65pvj/
+        uwc9/28eyfnf1lYL1txsqe8HU4OhCYZBmrcvSwVrvr4/6f+mWZ7/xYT4/qeFasD9D8IommAY2WZkzaVJ
+        utboalE4IIzLZmyaQRiFA9K8dUE4Ns2ayOqQMZwB0rx5ji9JmkEYzpgxd/H/49s7/j86VwLXHOSiqoGs
+        GBsGE0DNZSAD/v37+3/l5ECibIZhCMHAUJZXWPo/MCQcxCHKZhiGEAwMD0CGAA3IQFdACGMVJAVjFSQe
+        /2cAAKIjwdj3D0MKAAAAAElFTkSuQmCC
+
+  
+
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.Designer.cs
new file mode 100644
index 000000000..d6acfbadc
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.Designer.cs
@@ -0,0 +1,455 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class FrmDbExportConfig
+    {
+        /// 
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        /// 
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// 
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FrmDbExportConfig));
+            System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Element groups");
+            System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Triggers");
+            this.pnlBottom = new System.Windows.Forms.Panel();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.btnSave = new System.Windows.Forms.Button();
+            this.btnClose = new System.Windows.Forms.Button();
+            this.tlStBottom = new System.Windows.Forms.ToolStrip();
+            this.ddbAdd = new System.Windows.Forms.ToolStripDropDownButton();
+            this.btnSqlServer = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnOracle = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnPostgreSql = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnMySql = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnOleDb = new System.Windows.Forms.ToolStripMenuItem();
+            this.btnAddCurTrigger = new System.Windows.Forms.ToolStripButton();
+            this.btnAddArcTrigger = new System.Windows.Forms.ToolStripButton();
+            this.btnAddEventTrigger = new System.Windows.Forms.ToolStripButton();
+            this.btnDelete = new System.Windows.Forms.ToolStripButton();
+            this.btnMoveUp = new System.Windows.Forms.ToolStripButton();
+            this.btnMoveDown = new System.Windows.Forms.ToolStripButton();
+            this.pnlGeneral = new System.Windows.Forms.Panel();
+            this.ctrlConnectionOptions = new Scada.Server.Modules.DbExport.UI.CtrlConnectionOptions();
+            this.ctrlGeneralOptions = new Scada.Server.Modules.DbExport.UI.CtrlGeneralOptions();
+            this.gbTarget = new System.Windows.Forms.GroupBox();
+            this.tvTargets = new System.Windows.Forms.TreeView();
+            this.cmsTree = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.miExpandAll = new System.Windows.Forms.ToolStripMenuItem();
+            this.miCollapseAll = new System.Windows.Forms.ToolStripMenuItem();
+            this.ilTree = new System.Windows.Forms.ImageList(this.components);
+            this.ctrlEventTrigger = new Scada.Server.Modules.DbExport.UI.CtrlEventTrigger();
+            this.ctrlTrigger = new Scada.Server.Modules.DbExport.UI.CtrlTrigger();
+            this.ctrlArcUploadOptions = new Scada.Server.Modules.DbExport.UI.CtrlArcUploadOptions();
+            this.pnlBottom.SuspendLayout();
+            this.tlStBottom.SuspendLayout();
+            this.pnlGeneral.SuspendLayout();
+            this.gbTarget.SuspendLayout();
+            this.cmsTree.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // pnlBottom
+            // 
+            this.pnlBottom.Controls.Add(this.btnCancel);
+            this.pnlBottom.Controls.Add(this.btnSave);
+            this.pnlBottom.Controls.Add(this.btnClose);
+            this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
+            this.pnlBottom.Location = new System.Drawing.Point(0, 518);
+            this.pnlBottom.Name = "pnlBottom";
+            this.pnlBottom.Size = new System.Drawing.Size(714, 41);
+            this.pnlBottom.TabIndex = 2;
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnCancel.Enabled = false;
+            this.btnCancel.Location = new System.Drawing.Point(546, 6);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 23);
+            this.btnCancel.TabIndex = 1;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // btnSave
+            // 
+            this.btnSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnSave.Location = new System.Drawing.Point(465, 6);
+            this.btnSave.Name = "btnSave";
+            this.btnSave.Size = new System.Drawing.Size(75, 23);
+            this.btnSave.TabIndex = 0;
+            this.btnSave.Text = "Save";
+            this.btnSave.UseVisualStyleBackColor = true;
+            this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
+            // 
+            // btnClose
+            // 
+            this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.btnClose.Location = new System.Drawing.Point(627, 6);
+            this.btnClose.Name = "btnClose";
+            this.btnClose.Size = new System.Drawing.Size(75, 23);
+            this.btnClose.TabIndex = 2;
+            this.btnClose.Text = "Close";
+            this.btnClose.UseVisualStyleBackColor = true;
+            // 
+            // tlStBottom
+            // 
+            this.tlStBottom.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.ddbAdd,
+            this.btnAddCurTrigger,
+            this.btnAddArcTrigger,
+            this.btnAddEventTrigger,
+            this.btnDelete,
+            this.btnMoveUp,
+            this.btnMoveDown});
+            this.tlStBottom.Location = new System.Drawing.Point(0, 0);
+            this.tlStBottom.Name = "tlStBottom";
+            this.tlStBottom.Size = new System.Drawing.Size(714, 25);
+            this.tlStBottom.TabIndex = 0;
+            this.tlStBottom.Text = " ";
+            // 
+            // ddbAdd
+            // 
+            this.ddbAdd.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.ddbAdd.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.btnSqlServer,
+            this.btnOracle,
+            this.btnPostgreSql,
+            this.btnMySql,
+            this.btnOleDb});
+            this.ddbAdd.Image = ((System.Drawing.Image)(resources.GetObject("ddbAdd.Image")));
+            this.ddbAdd.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.ddbAdd.Name = "ddbAdd";
+            this.ddbAdd.Size = new System.Drawing.Size(29, 22);
+            this.ddbAdd.Text = "Add";
+            this.ddbAdd.ToolTipText = "Add export target";
+            // 
+            // btnSqlServer
+            // 
+            this.btnSqlServer.Image = ((System.Drawing.Image)(resources.GetObject("btnSqlServer.Image")));
+            this.btnSqlServer.Name = "btnSqlServer";
+            this.btnSqlServer.Size = new System.Drawing.Size(184, 22);
+            this.btnSqlServer.Text = "Microsoft SQL Server";
+            this.btnSqlServer.Click += new System.EventHandler(this.btnAddTagret_Click);
+            // 
+            // btnOracle
+            // 
+            this.btnOracle.Image = ((System.Drawing.Image)(resources.GetObject("btnOracle.Image")));
+            this.btnOracle.Name = "btnOracle";
+            this.btnOracle.Size = new System.Drawing.Size(184, 22);
+            this.btnOracle.Text = "Oracle";
+            this.btnOracle.Click += new System.EventHandler(this.btnAddTagret_Click);
+            // 
+            // btnPostgreSql
+            // 
+            this.btnPostgreSql.Image = ((System.Drawing.Image)(resources.GetObject("btnPostgreSql.Image")));
+            this.btnPostgreSql.Name = "btnPostgreSql";
+            this.btnPostgreSql.Size = new System.Drawing.Size(184, 22);
+            this.btnPostgreSql.Text = "PostgreSQL";
+            this.btnPostgreSql.Click += new System.EventHandler(this.btnAddTagret_Click);
+            // 
+            // btnMySql
+            // 
+            this.btnMySql.Image = ((System.Drawing.Image)(resources.GetObject("btnMySql.Image")));
+            this.btnMySql.Name = "btnMySql";
+            this.btnMySql.Size = new System.Drawing.Size(184, 22);
+            this.btnMySql.Text = "MySQL";
+            this.btnMySql.Click += new System.EventHandler(this.btnAddTagret_Click);
+            // 
+            // btnOleDb
+            // 
+            this.btnOleDb.Image = ((System.Drawing.Image)(resources.GetObject("btnOleDb.Image")));
+            this.btnOleDb.Name = "btnOleDb";
+            this.btnOleDb.Size = new System.Drawing.Size(184, 22);
+            this.btnOleDb.Text = "OLE DB";
+            this.btnOleDb.Click += new System.EventHandler(this.btnAddTagret_Click);
+            // 
+            // btnAddCurTrigger
+            // 
+            this.btnAddCurTrigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnAddCurTrigger.Image = ((System.Drawing.Image)(resources.GetObject("btnAddCurTrigger.Image")));
+            this.btnAddCurTrigger.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnAddCurTrigger.Name = "btnAddCurTrigger";
+            this.btnAddCurTrigger.Size = new System.Drawing.Size(23, 22);
+            this.btnAddCurTrigger.Text = "Add current data trigger";
+            this.btnAddCurTrigger.ToolTipText = "Add current data trigger";
+            this.btnAddCurTrigger.Click += new System.EventHandler(this.btnAddTrigger_Click);
+            // 
+            // btnAddArcTrigger
+            // 
+            this.btnAddArcTrigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnAddArcTrigger.Image = ((System.Drawing.Image)(resources.GetObject("btnAddArcTrigger.Image")));
+            this.btnAddArcTrigger.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnAddArcTrigger.Name = "btnAddArcTrigger";
+            this.btnAddArcTrigger.Size = new System.Drawing.Size(23, 22);
+            this.btnAddArcTrigger.Text = "tlStBtnAddArcTrigger";
+            this.btnAddArcTrigger.ToolTipText = "Add archive data trigger";
+            this.btnAddArcTrigger.Click += new System.EventHandler(this.btnAddTrigger_Click);
+            // 
+            // btnAddEventTrigger
+            // 
+            this.btnAddEventTrigger.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnAddEventTrigger.Image = ((System.Drawing.Image)(resources.GetObject("btnAddEventTrigger.Image")));
+            this.btnAddEventTrigger.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnAddEventTrigger.Name = "btnAddEventTrigger";
+            this.btnAddEventTrigger.Size = new System.Drawing.Size(23, 22);
+            this.btnAddEventTrigger.Text = "tlStBtnAddEventTrigger";
+            this.btnAddEventTrigger.ToolTipText = "Add event trigger";
+            this.btnAddEventTrigger.Click += new System.EventHandler(this.btnAddTrigger_Click);
+            // 
+            // btnDelete
+            // 
+            this.btnDelete.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnDelete.Image = ((System.Drawing.Image)(resources.GetObject("btnDelete.Image")));
+            this.btnDelete.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnDelete.Name = "btnDelete";
+            this.btnDelete.Size = new System.Drawing.Size(23, 22);
+            this.btnDelete.Text = "Delete";
+            this.btnDelete.ToolTipText = "Delete";
+            this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
+            // 
+            // btnMoveUp
+            // 
+            this.btnMoveUp.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnMoveUp.Image = ((System.Drawing.Image)(resources.GetObject("btnMoveUp.Image")));
+            this.btnMoveUp.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnMoveUp.Name = "btnMoveUp";
+            this.btnMoveUp.Size = new System.Drawing.Size(23, 22);
+            this.btnMoveUp.Text = "Move up";
+            this.btnMoveUp.ToolTipText = "Move up";
+            this.btnMoveUp.Click += new System.EventHandler(this.btnMoveUpDown_Click);
+            // 
+            // btnMoveDown
+            // 
+            this.btnMoveDown.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this.btnMoveDown.Image = ((System.Drawing.Image)(resources.GetObject("btnMoveDown.Image")));
+            this.btnMoveDown.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.btnMoveDown.Name = "btnMoveDown";
+            this.btnMoveDown.Size = new System.Drawing.Size(23, 22);
+            this.btnMoveDown.Text = "Move down";
+            this.btnMoveDown.ToolTipText = "Move down";
+            this.btnMoveDown.Click += new System.EventHandler(this.btnMoveUpDown_Click);
+            // 
+            // pnlGeneral
+            // 
+            this.pnlGeneral.Controls.Add(this.ctrlConnectionOptions);
+            this.pnlGeneral.Controls.Add(this.ctrlGeneralOptions);
+            this.pnlGeneral.Controls.Add(this.gbTarget);
+            this.pnlGeneral.Controls.Add(this.ctrlEventTrigger);
+            this.pnlGeneral.Controls.Add(this.ctrlTrigger);
+            this.pnlGeneral.Controls.Add(this.ctrlArcUploadOptions);
+            this.pnlGeneral.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.pnlGeneral.Location = new System.Drawing.Point(0, 25);
+            this.pnlGeneral.Name = "pnlGeneral";
+            this.pnlGeneral.Size = new System.Drawing.Size(714, 493);
+            this.pnlGeneral.TabIndex = 1;
+            // 
+            // ctrlConnectionOptions
+            // 
+            this.ctrlConnectionOptions.ConnectionOptions = null;
+            this.ctrlConnectionOptions.Location = new System.Drawing.Point(288, 5);
+            this.ctrlConnectionOptions.Name = "ctrlConnectionOptions";
+            this.ctrlConnectionOptions.Size = new System.Drawing.Size(412, 481);
+            this.ctrlConnectionOptions.TabIndex = 1;
+            this.ctrlConnectionOptions.ConnectChanged += new Scada.UI.ObjectChangedEventHandler(this.ctrlConnectionOptions_ConnectChanged);
+            // 
+            // ctrlGeneralOptions
+            // 
+            this.ctrlGeneralOptions.Location = new System.Drawing.Point(288, 5);
+            this.ctrlGeneralOptions.Name = "ctrlGeneralOptions";
+            this.ctrlGeneralOptions.Size = new System.Drawing.Size(412, 481);
+            this.ctrlGeneralOptions.TabIndex = 6;
+            this.ctrlGeneralOptions.GeneralOptionsChanged += new Scada.UI.ObjectChangedEventHandler(this.ctrlGeneralOptions_GeneralOptionsChanged);
+            // 
+            // gbTarget
+            // 
+            this.gbTarget.Anchor = System.Windows.Forms.AnchorStyles.Left;
+            this.gbTarget.Controls.Add(this.tvTargets);
+            this.gbTarget.Location = new System.Drawing.Point(6, 5);
+            this.gbTarget.Name = "gbTarget";
+            this.gbTarget.Padding = new System.Windows.Forms.Padding(10, 3, 10, 10);
+            this.gbTarget.Size = new System.Drawing.Size(276, 481);
+            this.gbTarget.TabIndex = 0;
+            this.gbTarget.TabStop = false;
+            this.gbTarget.Text = "Export Targets";
+            // 
+            // tvTargets
+            // 
+            this.tvTargets.ContextMenuStrip = this.cmsTree;
+            this.tvTargets.HideSelection = false;
+            this.tvTargets.ImageIndex = 0;
+            this.tvTargets.ImageList = this.ilTree;
+            this.tvTargets.Location = new System.Drawing.Point(13, 19);
+            this.tvTargets.Name = "tvTargets";
+            treeNode1.ImageKey = "group.png";
+            treeNode1.Name = "grsNode";
+            treeNode1.SelectedImageKey = "group.png";
+            treeNode1.Text = "Element groups";
+            treeNode2.ImageIndex = 2;
+            treeNode2.Name = "triggersNode";
+            treeNode2.SelectedImageKey = "cmds.png";
+            treeNode2.Text = "Triggers";
+            this.tvTargets.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
+            treeNode1,
+            treeNode2});
+            this.tvTargets.SelectedImageIndex = 0;
+            this.tvTargets.Size = new System.Drawing.Size(250, 449);
+            this.tvTargets.TabIndex = 0;
+            this.tvTargets.AfterCollapse += new System.Windows.Forms.TreeViewEventHandler(this.tvTargets_AfterCollapse);
+            this.tvTargets.AfterExpand += new System.Windows.Forms.TreeViewEventHandler(this.tvTargets_AfterExpand);
+            this.tvTargets.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.tvTargets_AfterSelect);
+            // 
+            // cmsTree
+            // 
+            this.cmsTree.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.miExpandAll,
+            this.miCollapseAll});
+            this.cmsTree.Name = "cmsTree";
+            this.cmsTree.Size = new System.Drawing.Size(137, 48);
+            // 
+            // miExpandAll
+            // 
+            this.miExpandAll.Name = "miExpandAll";
+            this.miExpandAll.Size = new System.Drawing.Size(136, 22);
+            this.miExpandAll.Text = "Expand All";
+            this.miExpandAll.Click += new System.EventHandler(this.miExpandAll_Click);
+            // 
+            // miCollapseAll
+            // 
+            this.miCollapseAll.Name = "miCollapseAll";
+            this.miCollapseAll.Size = new System.Drawing.Size(136, 22);
+            this.miCollapseAll.Text = "Collapse All";
+            this.miCollapseAll.Click += new System.EventHandler(this.miCollapseAll_Click);
+            // 
+            // ilTree
+            // 
+            this.ilTree.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("ilTree.ImageStream")));
+            this.ilTree.TransparentColor = System.Drawing.Color.Transparent;
+            this.ilTree.Images.SetKeyName(0, "arc_upload.png");
+            this.ilTree.Images.SetKeyName(1, "connect.png");
+            this.ilTree.Images.SetKeyName(2, "db_mssql.png");
+            this.ilTree.Images.SetKeyName(3, "db_mysql.png");
+            this.ilTree.Images.SetKeyName(4, "db_oledb.png");
+            this.ilTree.Images.SetKeyName(5, "db_oracle.png");
+            this.ilTree.Images.SetKeyName(6, "db_postgresql.png");
+            this.ilTree.Images.SetKeyName(7, "tr_arc_data.png");
+            this.ilTree.Images.SetKeyName(8, "tr_cur_data.png");
+            this.ilTree.Images.SetKeyName(9, "tr_data_inactive.png");
+            this.ilTree.Images.SetKeyName(10, "tr_event.png");
+            this.ilTree.Images.SetKeyName(11, "tr_event_inactive.png");
+            this.ilTree.Images.SetKeyName(12, "db_mssql_inactive.png");
+            this.ilTree.Images.SetKeyName(13, "db_mysql_inactive.png");
+            this.ilTree.Images.SetKeyName(14, "db_oledb_inactive.png");
+            this.ilTree.Images.SetKeyName(15, "db_oracle_inactive.png");
+            this.ilTree.Images.SetKeyName(16, "db_postgresql_inactive.png");
+            this.ilTree.Images.SetKeyName(17, "folder_closed.png");
+            this.ilTree.Images.SetKeyName(18, "folder_open.png");
+            // 
+            // ctrlEventTrigger
+            // 
+            this.ctrlEventTrigger.Location = new System.Drawing.Point(288, 5);
+            this.ctrlEventTrigger.Name = "ctrlEventTrigger";
+            this.ctrlEventTrigger.Size = new System.Drawing.Size(412, 481);
+            this.ctrlEventTrigger.TabIndex = 24;
+            this.ctrlEventTrigger.TriggerEventOptionsChanged += new Scada.UI.ObjectChangedEventHandler(this.ctrlEventTriggers_TriggerEventOptionsChanged);
+            // 
+            // ctrlTrigger
+            // 
+            this.ctrlTrigger.Location = new System.Drawing.Point(288, 5);
+            this.ctrlTrigger.Name = "ctrlTrigger";
+            this.ctrlTrigger.Size = new System.Drawing.Size(412, 481);
+            this.ctrlTrigger.TabIndex = 23;
+            this.ctrlTrigger.TriggerOptionsChanged += new Scada.UI.ObjectChangedEventHandler(this.ctrlTriggers_TriggerOptionsChanged);
+            // 
+            // ctrlArcUploadOptions
+            // 
+            this.ctrlArcUploadOptions.Location = new System.Drawing.Point(288, 5);
+            this.ctrlArcUploadOptions.Name = "ctrlArcUploadOptions";
+            this.ctrlArcUploadOptions.Size = new System.Drawing.Size(412, 481);
+            this.ctrlArcUploadOptions.TabIndex = 5;
+            this.ctrlArcUploadOptions.ArcUploadOptionsChanged += new Scada.UI.ObjectChangedEventHandler(this.ctrlArcUploadOptions_ArcUploadOptionsChanged);
+            // 
+            // FrmDbExportConfig
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this.btnClose;
+            this.ClientSize = new System.Drawing.Size(714, 559);
+            this.Controls.Add(this.pnlGeneral);
+            this.Controls.Add(this.tlStBottom);
+            this.Controls.Add(this.pnlBottom);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "FrmDbExportConfig";
+            this.ShowInTaskbar = false;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+            this.Text = "Export to DB";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FrmConfig_FormClosing);
+            this.Load += new System.EventHandler(this.FrmConfig_Load);
+            this.pnlBottom.ResumeLayout(false);
+            this.tlStBottom.ResumeLayout(false);
+            this.tlStBottom.PerformLayout();
+            this.pnlGeneral.ResumeLayout(false);
+            this.gbTarget.ResumeLayout(false);
+            this.cmsTree.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel pnlBottom;
+        private System.Windows.Forms.Button btnCancel;
+        private System.Windows.Forms.Button btnSave;
+        private System.Windows.Forms.Button btnClose;
+        private System.Windows.Forms.ToolStrip tlStBottom;
+        private System.Windows.Forms.ToolStripButton btnDelete;
+        private System.Windows.Forms.ToolStripButton btnMoveUp;
+        private System.Windows.Forms.ToolStripButton btnMoveDown;
+        private System.Windows.Forms.Panel pnlGeneral;
+        private System.Windows.Forms.GroupBox gbTarget;
+        private System.Windows.Forms.TreeView tvTargets;
+        private CtrlGeneralOptions ctrlGeneralOptions;
+        private CtrlConnectionOptions ctrlConnectionOptions;
+        private CtrlTrigger ctrlTrigger;
+        private CtrlArcUploadOptions ctrlArcUploadOptions;
+        private System.Windows.Forms.ContextMenuStrip cmsTree;
+        private System.Windows.Forms.ToolStripMenuItem miExpandAll;
+        private System.Windows.Forms.ToolStripMenuItem miCollapseAll;
+        private CtrlEventTrigger ctrlEventTrigger;
+        private System.Windows.Forms.ToolStripButton btnAddCurTrigger;
+        private System.Windows.Forms.ToolStripButton btnAddArcTrigger;
+        private System.Windows.Forms.ToolStripButton btnAddEventTrigger;
+        private System.Windows.Forms.ImageList ilTree;
+        private System.Windows.Forms.ToolStripDropDownButton ddbAdd;
+        private System.Windows.Forms.ToolStripMenuItem btnSqlServer;
+        private System.Windows.Forms.ToolStripMenuItem btnOracle;
+        private System.Windows.Forms.ToolStripMenuItem btnPostgreSql;
+        private System.Windows.Forms.ToolStripMenuItem btnMySql;
+        private System.Windows.Forms.ToolStripMenuItem btnOleDb;
+    }
+}
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.cs
new file mode 100644
index 000000000..adb5f083a
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.cs
@@ -0,0 +1,716 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Module configuration form
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+using System;
+using Scada.Server.Modules.DbExport.Config;
+using Scada.UI;
+using Scada.Config;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq; 
+using System.Windows.Forms;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Module configuration form.
+    /// Форма конфигурации модуля.
+    /// 
+    public partial class FrmDbExportConfig : Form
+    {
+        private readonly AppDirs appDirs; // application directories
+        private bool modified;            // sign of configuration change
+        private TreeNode selTargetNode;   // tree node of the selected target
+        private TreeNode selTriggerNode;  // tree node of the selected trigger
+        private ModConfig config;         // configuration
+        private ModConfig configCopy;     // copy of configuration to implement rollback    
+        private string configFileName;    // configuration file name
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        private FrmDbExportConfig()
+        {
+            InitializeComponent();
+        }
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public FrmDbExportConfig(AppDirs appDirs)
+            : this()
+        {
+            this.appDirs = appDirs ?? throw new ArgumentNullException("appDirs");
+            modified = false;
+            selTargetNode = null;
+            selTriggerNode = null;
+            config = null;
+            configCopy = null;
+            configFileName = "";
+        }
+
+
+        /// 
+        /// Gets or sets a sign of a configuration change.
+        /// 
+        private bool Modified
+        {
+            get
+            {
+                return modified;
+            }
+            set
+            {
+                modified = value;
+                btnSave.Enabled = modified;
+                btnCancel.Enabled = modified;
+            }
+        }
+
+
+        /// 
+        /// Returns an icon, depending on the selected node. 
+        /// 
+        private string SelectDbIcon(ExportTargetConfig exportTargetConfig)
+        {
+            string suffix = exportTargetConfig.GeneralOptions.Active ? "" : "_inactive";
+
+            switch (exportTargetConfig.ConnectionOptions.KnownDBMS)
+            {
+                case KnownDBMS.Oracle: 
+                    return $"db_oracle{suffix}.png";
+
+                case KnownDBMS.PostgreSQL:
+                    return $"db_postgresql{suffix}.png";
+
+                case KnownDBMS.MySQL:
+                    return $"db_mysql{suffix}.png";
+
+                case KnownDBMS.MSSQL:
+                    return $"db_mssql{suffix}.png";
+
+                case KnownDBMS.OLEDB:
+                    return $"db_oledb{suffix}.png";
+
+                default:
+                    return "db_oledb.png";
+            }
+        }
+
+        /// 
+        /// Selects an object image key.
+        /// 
+        private string ChooseImageKey(object obj, bool expanded = false)
+        {
+            if (obj is ExportTargetConfig config)
+                return SelectDbIcon(config);       
+            else if (obj is TriggerOptionList)
+                return (expanded ? "folder_open.png" : "folder_closed.png");
+            else if (obj is DbConnectionOptions)
+                return "connect.png";
+            else if (obj is CurDataTriggerOptions options1)
+                return options1.Active ? "tr_cur_data.png" : "tr_data_inactive.png";
+            else if (obj is ArcDataTriggerOptions options2)
+                return options2.Active ? "tr_arc_data.png" : "tr_data_inactive.png";
+            else if (obj is EventTriggerOptions options3)
+                return options3.Active ? "tr_event.png" : "tr_event_inactive.png";
+            else if (obj is ArcUploadOptions)
+                return "arc_upload.png";
+            else
+                return "options.png";
+        }
+
+        /// 
+        /// Creates a tree node corresponding to the target.
+        /// 
+        private TreeNode CreateTargetNode(ExportTargetConfig exportTargetConfig)
+        {
+            return TreeViewUtils.CreateNode(exportTargetConfig, ChooseImageKey(exportTargetConfig));
+        }
+
+        /// 
+        /// Creates a tree node corresponding to the trigger.
+        /// 
+        private TreeNode CreateTriggerNode(TriggerOptions triggerOptions)
+        {
+            return TreeViewUtils.CreateNode(triggerOptions, ChooseImageKey(triggerOptions));
+        }
+
+        /// 
+        /// Downloads information from the configuration file.
+        /// 
+        private void LoadConfig()
+        {
+            // initialize common data
+            configFileName = appDirs.ConfigDir + ModConfig.ConfigFileName;
+            ctrlGeneralOptions.Visible = true;
+            ctrlConnectionOptions.Visible = false;
+            ctrlArcUploadOptions.Visible = false;
+            ctrlTrigger.Visible = false;
+            ctrlEventTrigger.Visible = false;
+
+            config = new ModConfig();
+            if (File.Exists(configFileName) && !config.Load(configFileName, out string errMsg))
+                ScadaUiUtils.ShowError(errMsg);
+
+            FillTree();
+
+            // creating a copy of the configuration
+            configCopy = config.Clone();
+        }
+
+        /// 
+        /// Gets target ID.
+        /// 
+        private int GetTagetID()
+        {
+            return config.ExportTargets.Count > 0 ? config.ExportTargets.Max(x => x.GeneralOptions.ID) + 1 : 1;
+        }
+
+        /// 
+        /// Adds a branch to the tree.
+        /// 
+        private void AddBranch(ExportTargetConfig exportTargetConfig, bool insertNewTarget)
+        {
+            TreeNode targetNode = CreateTargetNode(exportTargetConfig);
+            targetNode.Text = exportTargetConfig.GeneralOptions.Name;
+
+            if (!insertNewTarget)
+                tvTargets.Nodes.Add(targetNode);
+            else
+                tvTargets.Insert(null, targetNode, config.ExportTargets, exportTargetConfig);
+
+            TreeNode connectionNode = TreeViewUtils.CreateNode(exportTargetConfig.ConnectionOptions,
+                ChooseImageKey(exportTargetConfig.ConnectionOptions));
+            connectionNode.Text = LibPhrases.ConnectionOptionsNode;
+            targetNode.Nodes.Add(connectionNode);
+
+            TreeNode triggerGroupNode = TreeViewUtils.CreateNode(exportTargetConfig.Triggers,
+                ChooseImageKey(exportTargetConfig.Triggers));
+            triggerGroupNode.Text = LibPhrases.TriggerGrNode;
+            targetNode.Nodes.Add(triggerGroupNode);
+
+            foreach (TriggerOptions triggerOptions in exportTargetConfig.Triggers)
+            {
+                TreeNode triggerNode = TreeViewUtils.CreateNode(triggerOptions,
+                    ChooseImageKey(triggerOptions));
+                triggerNode.Text = triggerOptions.Name;
+                triggerGroupNode.Nodes.Add(triggerNode);
+            }
+      
+            TreeNode arcUploadNode = TreeViewUtils.CreateNode(exportTargetConfig.ArcUploadOptions,
+                ChooseImageKey(exportTargetConfig.ArcUploadOptions));
+            arcUploadNode.Text = LibPhrases.ArcUploadOptionsNode;
+            targetNode.Nodes.Add(arcUploadNode);
+
+            if (insertNewTarget)
+                tvTargets.SelectedNode.Expand();
+        }
+
+        /// 
+        /// Fills the tree according to the configuration file.
+        /// 
+        private void FillTree()
+        {
+            selTargetNode = null;
+            selTriggerNode = null;
+
+            // tree cleaning and filling
+            tvTargets.BeginUpdate();
+            tvTargets.Nodes.Clear();
+
+            foreach (ExportTargetConfig exportTargetConfig in config.ExportTargets)
+            {
+                AddBranch(exportTargetConfig, false);
+            }
+
+            tvTargets.ExpandAll();
+            tvTargets.EndUpdate();
+
+            // first target selection
+            if (tvTargets.Nodes.Count > 0)
+                tvTargets.SelectedNode = tvTargets.Nodes[0];
+            
+             SetActionButtonsEnabled();
+        }
+
+        /// 
+        /// Hides properties of objects.
+        /// 
+        private void HideProps()
+        {
+            ctrlGeneralOptions.Visible = false;
+            ctrlConnectionOptions.Visible = false;
+            ctrlTrigger.Visible = false;
+            ctrlEventTrigger.Visible = false;
+            ctrlArcUploadOptions.Visible = false;
+        }
+
+        /// 
+        /// Set the input focus of the trigger edit control. 
+        /// 
+        public void SetTriggerFocus()
+        {
+            if (ctrlTrigger.Visible)
+                ctrlTrigger.SetFocus();
+            else if (ctrlEventTrigger.Visible)
+                ctrlEventTrigger.SetFocus();
+        }
+
+        /// 
+        /// Sets availability move and delete elements buttons.
+        /// 
+        private void SetActionButtonsEnabled()
+        {
+            btnMoveUp.Enabled = tvTargets.MoveUpSelectedNodeIsEnabled(
+                TreeViewUtils.MoveBehavior.ThroughSimilarParents) && tvTargets.SelectedNode.Parent == null;
+            btnMoveDown.Enabled = tvTargets.MoveDownSelectedNodeIsEnabled(
+                TreeViewUtils.MoveBehavior.ThroughSimilarParents) && tvTargets.SelectedNode.Parent == null;
+            btnDelete.Enabled = (tvTargets.SelectedNode != null && tvTargets.SelectedNode.Parent == null) ||
+                (selTriggerNode != null && ((tvTargets.SelectedNode?.Tag as DataTriggerOptions) != null ||
+                (tvTargets.SelectedNode?.Tag as EventTriggerOptions) != null));
+            btnAddArcTrigger.Enabled = selTargetNode != null;
+            btnAddCurTrigger.Enabled = selTargetNode != null;
+            btnAddEventTrigger.Enabled = selTargetNode != null;
+        }
+
+        /// 
+        /// Saves module configuration.
+        /// 
+        private bool SaveConfig()
+        {
+            if (Modified)
+            {
+                if (ValidateConfig())
+                {
+                    if (config.Save(configFileName, out string errMsg))
+                    {
+                        configCopy = config.Clone();
+                        Modified = false;
+                        return true;
+                    }
+                    else
+                    {
+                        ScadaUiUtils.ShowError(errMsg);
+                        return false;
+                    }
+                }
+                else
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                return true;
+            }
+        }
+
+        /// 
+        /// Applies localization to the form.
+        /// 
+        private void LocalizeForm()
+        {
+            if (Localization.LoadDictionaries(appDirs.LangDir, "ModDbExport", out string errMsg))
+                Translator.TranslateForm(this, GetType().FullName, null, cmsTree);
+            else
+                ScadaUiUtils.ShowError(errMsg);
+
+            LibPhrases.Init();
+        }
+
+        /// 
+        /// Checks target name for uniqueness.
+        /// 
+        private bool CheckGateNamesUniqueness()
+        {
+            HashSet targetNames = new HashSet(
+                from ExportTargetConfig exportTargetConfig in config.ExportTargets
+                select exportTargetConfig.GeneralOptions.Name.ToLowerInvariant());
+
+            return targetNames.Count >= config.ExportTargets.Count;
+        }
+
+        /// 
+        /// Checks names for empty value.
+        /// 
+        private bool CheckNamesNull()
+        {
+            bool checkNamesNull = true;
+            HashSet names = new HashSet(
+                from ExportTargetConfig exportTargetConfig in config.ExportTargets
+                select exportTargetConfig.GeneralOptions.Name);
+
+            if (names.Contains(string.Empty))
+                checkNamesNull = false;
+
+            return checkNamesNull;
+        }
+
+        /// 
+        /// Checks the correctness of the target.
+        /// 
+        private bool ValidateConfig()
+        {
+            if (!CheckNamesNull())
+            {
+                ScadaUiUtils.ShowError(LibPhrases.NameEmpty);
+                return false;
+            }
+            else if (!CheckGateNamesUniqueness())
+            {
+                ScadaUiUtils.ShowError(LibPhrases.TargetNameNotUnique);
+                return false;
+            }
+
+            return true;
+        }
+
+        /// 
+        /// Shows target properties.
+        /// 
+        private void ShowGeneralOptions(ExportTargetConfig exportTargetConfig)
+        {
+            if (exportTargetConfig == null)
+            {
+                ctrlGeneralOptions.Visible = false;
+            }
+            else
+            {
+                ctrlGeneralOptions.Visible = true;
+                ctrlGeneralOptions.GeneralOptions = exportTargetConfig.GeneralOptions;
+                ctrlTrigger.Visible = false;
+                ctrlConnectionOptions.Visible = false;
+                ctrlArcUploadOptions.Visible = false;
+                ctrlEventTrigger.Visible = false;
+            }
+        }
+
+        /// 
+        /// Shows connect properties.
+        /// 
+        private void ShowConnectionOptions(DbConnectionOptions connectionOptions)
+        {
+            if (connectionOptions == null)
+            {
+                ctrlConnectionOptions.Visible = false;
+            }
+            else
+            {
+                ctrlConnectionOptions.Visible = true;
+                ctrlConnectionOptions.ConnectionOptions = connectionOptions;
+                ctrlTrigger.Visible = false;
+                ctrlGeneralOptions.Visible = false;
+                ctrlArcUploadOptions.Visible = false;
+                ctrlEventTrigger.Visible = false;
+            }
+        }
+
+        /// 
+        /// Shows data cur triggers.
+        /// 
+        private void ShowTriggersProps(DataTriggerOptions triggerOptions, ExportTargetConfig exportTargetConfig)
+        {
+            if (triggerOptions == null)
+            {
+                ctrlTrigger.Visible = false;
+            }
+            else
+            {
+                ctrlTrigger.DbmsType = exportTargetConfig.ConnectionOptions.KnownDBMS;
+                ctrlTrigger.Visible = true;
+                ctrlTrigger.Clear();
+                ctrlTrigger.DataTriggerOptions = triggerOptions;
+                ctrlConnectionOptions.Visible = false;
+                ctrlGeneralOptions.Visible = false;
+                ctrlArcUploadOptions.Visible = false;
+                ctrlEventTrigger.Visible = false;
+            }
+        }
+
+        /// 
+        /// Shows data event triggers options.
+        /// 
+        private void ShowEventTriggersProps(EventTriggerOptions eventTriggerOptions, ExportTargetConfig exportTargetConfig)
+        {
+            if (eventTriggerOptions == null)
+            {
+                ctrlEventTrigger.Visible = false;
+            }
+            else
+            {
+                ctrlEventTrigger.DbmsType = exportTargetConfig.ConnectionOptions.KnownDBMS;
+                ctrlEventTrigger.Visible = true;
+                ctrlEventTrigger.Clear();
+                ctrlEventTrigger.EventTriggerOptions = eventTriggerOptions;
+                ctrlConnectionOptions.Visible = false;
+                ctrlGeneralOptions.Visible = false;
+                ctrlArcUploadOptions.Visible = false;
+                ctrlTrigger.Visible = false;
+            }
+        }
+
+        /// 
+        /// Shows archive upload options.
+        /// 
+        private void ShowArcUploadOptionsProps(ArcUploadOptions arcUploadOptions)
+        {
+            if (arcUploadOptions == null)
+            {
+                ctrlArcUploadOptions.Visible = false;
+            }
+            else
+            {
+                ctrlArcUploadOptions.Visible = true;
+                ctrlArcUploadOptions.ArcUploadOptions = arcUploadOptions;
+                ctrlTrigger.Visible = false;
+                ctrlEventTrigger.Visible = false;
+                ctrlGeneralOptions.Visible = false;
+                ctrlConnectionOptions.Visible = false;
+            }
+        }
+
+
+        private void FrmConfig_Load(object sender, EventArgs e)
+        {
+            LocalizeForm();
+            LoadConfig();
+            btnSave.Enabled = false;
+            btnCancel.Enabled = false;
+            Modified = false;
+        }
+
+        private void FrmConfig_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            if (Modified)
+            {
+                DialogResult result = MessageBox.Show(CommonPhrases.SaveSettingsConfirm,
+                    CommonPhrases.QuestionCaption, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
+
+                switch (result)
+                {
+                    case DialogResult.Yes:
+                        if (!SaveConfig())
+                            e.Cancel = true;
+                        break;
+                    case DialogResult.No:
+                        break;
+                    default:
+                        e.Cancel = true;
+                        break;
+                }
+            }
+        }
+
+        private void tvTargets_AfterSelect(object sender, TreeViewEventArgs e)
+        {
+            // definition of a chain of selected nodes and objects
+            TreeNode selNode = tvTargets.SelectedNode;
+            selTargetNode = selNode.FindClosest(typeof(ExportTargetConfig));
+            selTriggerNode = selNode.FindClosest(typeof(TriggerOptionList));
+
+            // display properties of the selected object
+            object selObj = selNode?.Tag;
+            object selTarget = selTargetNode?.Tag;
+
+            if (selObj is ExportTargetConfig exportTargetConfig)
+                ShowGeneralOptions(exportTargetConfig);
+            else if (selObj is DbConnectionOptions dbConnectionOptions)
+                ShowConnectionOptions(dbConnectionOptions);
+            else if (selObj is DataTriggerOptions dataTriggerOptions)
+                ShowTriggersProps(dataTriggerOptions, selTarget as ExportTargetConfig);
+            else if (selObj is EventTriggerOptions eventTriggerOptions)
+                ShowEventTriggersProps(eventTriggerOptions, selTarget as ExportTargetConfig);
+            else if (selObj is ArcUploadOptions arcUploadOptions)
+                ShowArcUploadOptionsProps(arcUploadOptions);
+            else
+                HideProps();
+
+            // setting available of buttons for moving and deleting elements
+            SetActionButtonsEnabled();
+        }
+
+        private void tvTargets_AfterExpand(object sender, TreeViewEventArgs e)
+        {
+            // set the icon if the group was expanded 
+            if (e.Node.Tag is TriggerOptionList)
+                e.Node.SetImageKey(ChooseImageKey(e.Node.Tag, true));
+        }
+
+        private void tvTargets_AfterCollapse(object sender, TreeViewEventArgs e)
+        {
+            // set the icon if the group was collaosed
+            if (e.Node.Tag is TriggerOptionList)
+                e.Node.SetImageKey(ChooseImageKey(e.Node.Tag, false));
+        }
+
+        private void btnAddTagret_Click(object sender, EventArgs e)
+        {
+            // add target
+            ExportTargetConfig target = new ExportTargetConfig { Parent = config };
+            target.GeneralOptions.ID = GetTagetID();
+            target.GeneralOptions.Name = LibPhrases.TargetName + " " + target.GeneralOptions.ID;
+
+            // add dbconnection setting
+            if (sender == btnSqlServer)
+                target.ConnectionOptions.KnownDBMS = KnownDBMS.MSSQL;
+            else if (sender == btnOracle)
+                target.ConnectionOptions.KnownDBMS = KnownDBMS.Oracle;
+            else if (sender == btnPostgreSql)
+                target.ConnectionOptions.KnownDBMS = KnownDBMS.PostgreSQL;
+            else if (sender == btnMySql)
+                target.ConnectionOptions.KnownDBMS = KnownDBMS.MySQL;
+            else if (sender == btnOleDb)
+                target.ConnectionOptions.KnownDBMS = KnownDBMS.OLEDB;
+            else
+                throw new ScadaException("Unknown DBMS.");
+
+            AddBranch(target, true);
+            Modified = true;
+            ctrlGeneralOptions.SetFocus();
+        }
+
+        private void btnAddTrigger_Click(object sender, EventArgs e)
+        {
+            // add trigger
+            if (selTargetNode != null)
+            {
+                TriggerOptions trigger;
+
+                if (sender == btnAddCurTrigger)
+                    trigger = new CurDataTriggerOptions { Name = LibPhrases.CurDataTrigger };
+                else if (sender == btnAddArcTrigger)
+                    trigger = new ArcDataTriggerOptions { Name = LibPhrases.ArcDataTrigger };
+                else if (sender == btnAddEventTrigger)
+                    trigger = new EventTriggerOptions { Name = LibPhrases.EventTrigger };
+                else
+                    trigger = null;
+
+                if (trigger != null)
+                {
+                    TreeNode triggerNode = CreateTriggerNode(trigger);
+                    triggerNode.Text = trigger.Name;
+
+                    if (selTriggerNode != null)
+                        tvTargets.Insert(selTriggerNode, triggerNode);
+                    else if (selTargetNode.FindFirst(typeof(TriggerOptionList)) is TreeNode treeNodeInsertTriggers)
+                        tvTargets.Add(treeNodeInsertTriggers, triggerNode);
+
+                    SetTriggerFocus();
+                    Modified = true;
+                }
+            }
+        }
+
+        private void btnDelete_Click(object sender, EventArgs e)
+        {
+            // delete selected item
+            if (selTargetNode != null)
+            {
+                tvTargets.RemoveSelectedNode();
+
+                tvTargets.Select();
+                Modified = true;
+
+                if (tvTargets.Nodes.Count == 0)
+                    HideProps();
+
+                // setting available  of buttons for moving and deleting elements
+                SetActionButtonsEnabled();
+            }
+        }
+
+        private void btnMoveUpDown_Click(object sender, EventArgs e)
+        {
+            // move the selected item up or down
+            if (sender == btnMoveUp)
+                tvTargets.MoveUpSelectedNode(TreeViewUtils.MoveBehavior.ThroughSimilarParents);
+            else
+                tvTargets.MoveDownSelectedNode(TreeViewUtils.MoveBehavior.ThroughSimilarParents);
+
+            Modified = true;
+            tvTargets.Select();
+        }
+
+        private void btnSave_Click(object sender, EventArgs e)
+        {
+            // save module configuration
+            SaveConfig();
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e)
+        {
+            // cancel configuration changes
+            config = configCopy;
+            configCopy = config.Clone();
+            LoadConfig();
+            Modified = false;
+        }
+
+        private void miExpandAll_Click(object sender, EventArgs e)
+        {
+            tvTargets.ExpandAll();
+        }
+
+        private void miCollapseAll_Click(object sender, EventArgs e)
+        {
+            tvTargets.CollapseAll();
+        }
+
+        private void ctrlGeneralOptions_GeneralOptionsChanged(object sender, ObjectChangedEventArgs e)
+        {
+            Modified = true;
+
+            if (selTargetNode != null)
+            {
+                selTargetNode.Text = (selTargetNode?.Tag as ExportTargetConfig).GeneralOptions.Name;
+                selTargetNode.SetImageKey(ChooseImageKey(selTargetNode?.Tag as ExportTargetConfig));
+            }
+        }
+
+        private void ctrlConnectionOptions_ConnectChanged(object sender, ObjectChangedEventArgs e)
+        {
+            Modified = true;
+        }
+
+        private void ctrlArcUploadOptions_ArcUploadOptionsChanged(object sender, ObjectChangedEventArgs e)
+        {
+            Modified = true;
+        }
+
+        private void ctrlTriggers_TriggerOptionsChanged(object sender, ObjectChangedEventArgs e)
+        {
+            Modified = true;
+
+            // updating the trigger name in the tree
+            if (selTriggerNode != null)
+            {
+                tvTargets.SelectedNode.Text = (tvTargets.SelectedNode?.Tag as DataTriggerOptions).Name;
+                tvTargets.SelectedNode.SetImageKey(ChooseImageKey(e.ChangedObject));
+            }
+        }
+
+        private void ctrlEventTriggers_TriggerEventOptionsChanged(object sender, ObjectChangedEventArgs e)
+        {
+            Modified = true;
+
+            // updating the trigger name in the tree  
+            if (selTriggerNode != null)
+            {
+                tvTargets.SelectedNode.Text = (tvTargets.SelectedNode?.Tag as TriggerOptions).Name;
+                tvTargets.SelectedNode.SetImageKey(ChooseImageKey(e.ChangedObject));
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.resx
new file mode 100644
index 000000000..8e60caaea
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmDbExportConfig.resx
@@ -0,0 +1,575 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    17, 17
+  
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAGJJREFUOE/t
+        zLENgEAMQ1FPwkisxDK3BCxFSZkzltw51TUUWPpV9IJn36oL3HGhut77/+ATD9Y37mrj6kR1yUfouASd
+        fISOS9DJR+i4BJ18hI5L0MlH6LgEnXyEjkvQya8NmE2e5IPy3OAlAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29m
+        dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAFFSURBVDhPnZJZTsNAEESt7OtHjpQD5CNHyklyFraw
+        YwirQBAQAiEQCAQiIJamnu2xHFtAYKQnW9Nd1TM97e0VCjYNuxE7YjvCYxG0ZvPPbIUGnaxBq2XWbmdh
+        P5G3mc+nDEjo9+3HRVx5H42G+RkD3w+TRiOzXi8L+yzlvcpgY8Kg242D6aPCJ1/2XRHlr00YUCEKpMUc
+        911QNS6k/NXfDKiK+E281Ov2LJIGK86At40D0RWSVccSPiFOXWHJGTAYQVUXnKKJ5+WyLToDJiowoMKU
+        z3hSKtkglwsNhjJI3jUw+maQTiU8FofFos07A0YyedeHWs3uqlW7EVeVil3ouGeCqkcSHgj6NucMGEk6
+        /CjhvbiV8FrCS8Fdk1X3JaRnQ2lmnQEjyVStC4aD51kWdJlGDcSCkjkyVQHxjAgMosXPP/A6X4CZKcoz
+        oWSPAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAyBJREFUOE+N
+        U0lPk1EU/Vau3Jm4cuUPsLSlFUgM0UQlmpi4UYzR0BGIkahB3QgOpUjnr5PFCYMD2spQgWIdiqCtIDHi
+        FGMVJ1RIS+knpa2fVHq8baobF3qSu3n3nnPvO/c9JoeFhYXln6JxNvxpyvR1Jr4//SMjSX/nV0xMzTie
+        T0yavnBz9ZG5pOrqwFD42q0HkfdT0ePZbHZZnjyXSFaa3T6+pEYHsVyDUnkTbJf7Micvd8ek1c0QyjQo
+        UWqxx9wOx80QipUalKm1sHb4I3wmI2LuPw0/Kqk6BrGCzUd57Uk4+4cgqdJCrDRRGCFSUU5lweZ9elg7
+        70Aib4ZEpkNXIDTOOHsGIVLaqSBXqEe9qxuVDa1YJWuBVEECRBSrDBAqHRQmHGTbIWvpyIs7ugcnmTNd
+        AQjVLJFtKFJbwPYMw+a9h7P+IBra+lCkNFMDC4UBze7buHpvBK7+UQjlLHpCzwKMLzg2LpbnutsgUJnB
+        9gaxvvYoDrquw9EXQLHCSGHHGvLI1XsXVVobtO4AXaMFHyOxRubd1MwZqUJHZCuKaFxj5xBK1XqIFGYc
+        dnZirUoHIXlQqjgBuy+Iiv0mHGnvR63+fGoxm13BcPMp2a5j5/4I2L1BSGkTxQoDGs/fQBmNLiSPihVW
+        1J3yYPuhFlg9fgyPhz35NXLct0pTh5/ILHUyw0jjbdirw2pyutV3HwK5mQwzUN6JshoL3IMjuBUc45Np
+        XpQXALB07OXrx6XKZjKRxcY6PQZGn8U0Z92c0+uHhFYrzRtpJ58ssHh8+Pj5sytP/o1EMlXR1NbLiciY
+        K/7QUHwuUf5i4kPYcKUL2w61QkzbEVTTJJS/dnsEjeyFhHfgzsNILL65IMEw0fj8Tu/gWN9snNvy5NWb
+        x8Z2D98fHOV3NbTRmh1YVWMgI/WY+Br1fPv+c2tmcXFlgfo3Uum0KBbnqr9MT9ftPn4JArWdJjCgvIZF
+        lEs2Fsr+jTTPC2RNF8lAU15g04HTmE3MVxbS/wb9uCX1tkt87k3kXqtMcw7JVHpdIf1/8D96OlmxR48d
+        R04h9OJtV+G4AIb5BfNMGC+05AnKAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAgZJREFUOE+V
+        0O1PUlEAx/HztxQrimbajAXaKk3qhb5oDZ2tdtvdLNu0LB600OCG+XAjcVDdlaaQEe4mPjCBjWHSVrCK
+        tVGvjLL14N/xi3M2zrirVr74bPf8zv2+OaTl7otmy0T2+wl/FttBG9qSFl9m87AnhgZXpOwZzDci/4U2
+        tCXH5TRMA0+QKn5D+uMPqPkSWm+rbPsX2pLmsSQOOWax9LaExuthiIE4Vt9/ZdTcBtrlGLv/E9qSY8Nx
+        HLRNo1NewONMkX03ucIwO2dgHX+OlcJnBBMFGO3T7K4abckRaRH1fQqjpApoleZwcigEd2Sd71I0i5V3
+        JZjsj/hG0ZY03lRR1xtkTnnnEIjn+bmabSqJ5TefNBttSUP5RWsv+bnoyw8w993TbBWB5RxG59f5mbbE
+        5Ayh5oLMtbmmoKzmNVtFbbcPrzd+wnR5kp1pS4zlxzCII9z5saewKUuardrgbAL+WJZ905bUX1GgFyRu
+        NJpG07VJzVZtn+hFvrSFA10joC2p6wli99khzqdmcLT3DqRwAm39Ac1dhTechDyfBm3J/u4J6DoHuIty
+        CD3+CGZSOTjuq5q7CsO5QawVv4C2pKZrHDutdm5XhxOLr4pwPVyAUXTjjPuB5p7/1+4AbYlBHN7UdfRj
+        x+mrf6Wz2n7fyg1tiV7wWPYI0tZe4Ra2gzZ6wWP5BaRQUOILyN2AAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAYFJREFUOE9j
+        GFzg8pGO5FPbG67tWl32f/Pigv/r5+b8Xzc7+/+WRfn/ty8punlgbVk+VCl2cHRzw//X92b///vzKAZ+
+        dX/B/0UT0/5DlWIHB1Zm//91Jez/rzdz/v96v/r/j7fL/v94PuX/t5uF/1/utfk/vcYZvwF7FsX//37O
+        /f+Xx93/v71e+P/Ttbz/77bL/3+xnPH/rTnM/ycVGOI3YNe8uP8/L/gCDeiFGHA9H8WA/nwT/AZsnx0D
+        NMD//1eYATeL/r/bqQI3oDfXCL8BW2dG/v99EWjAkz6oCwpQDOjKNsBvwIap4f9/XfL7/+UJzAuoBnRk
+        6OM3YN3EEKABPv+/QQ34DDTgPZIBbak6+A1Y1R/8//913/+/Xk0AG/AFGH2f9iAMaEnWwm/ArHrXCxc3
+        BP5/cbUFbMD/J8X/P+9T+X9vPvP/fd0i/xvjtW9ClWIHO6a4ai9odV83qz38zbTm2P+9ZV7/e3JN/vdm
+        qn3oSFXb3JWqaA5VOmgAAwMAVhwzMyFCpNwAAAAASUVORK5CYII=
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGLSURBVDhPtZBtK4NxFMb3GbxAHqaliJShYdi89spXkdiT
+        yNPytJnZlrUNI2OzoaymPGTLkuQTbJ6KISFmt7lZXc7Wal6t3cpVV6f/6fx/1+nw/k1n3nacbkkQdLfA
+        72xGup27TrakSDDrSMRc2Ftp4g4IelrxHXMj8WzHjr2eOyDgaiYAbfCyiG2bkDtg3yGi9ZMACzbNtdkB
+        J5tSHHvacOQW49ApxsGKCGe+TgI4kXiyIODpwKquCsvaCsxPlsM6JoB5pCwDDXokdDAafl9LHS3l5Jv8
+        9WQC+6jH18Ms2Hs9Pu+0iEc0MA7xMwC/S0xDOrCRURpQpyp7Owz2ZgDsdR/ilwqyDMxFD5hwLz6o6geK
+        M4DdpQb4FuqwbRFiY64GbkM19h2NYK7kYM674LU2UGIJDPRppr8IOlUhtMqC7HdZ1lQiRqnRcDdMg7/S
+        cpVtXEDpCkRDvdBTarqduyxqPqUr8RZSYFqVzx1gHCzFa7gfryEVppR/AMzS2tq+Amjk+ZiQ5XEH5CYe
+        7wfoOxP7rAzZtQAAAABJRU5ErkJggg==
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACcSURBVDhPY6A5iJh1VRvKJB2ANEfPvvGfLENgmmee/f+f
+        ZEOQNYNw3/HfxBuCqfnP/7q93/5nb37/37n4JH5D0DX3A22u2/ftfw5Qc+SKF/895j/+z2A8E7shmDaD
+        NH+Fa/YkXTPU5pUENMMASNI0eStE896vYD8TrRkGYIaANa94CdT8iHjNMAAzhCSb0QFYE7maYYAizXQE
+        DAwA4kzYfjmoEkIAAAAASUVORK5CYII=
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY6A5+Nz3WRvKJB2ANF9KvfyfLENgmn/v/P2f
+        ZEOQNYPw9w0/iDcEU/P3/58Wf/r/euprwoZg1bwEqHnKm/9P2p7+v1/54H+Pbi92QzA1//j/EaQZaDNR
+        mm/k3ETRDHH2m/9PW5/+v4dPMwzADAHbDNI8BWgzUDNem9EBzBCwZrCz7xOvGQZAijfZbAY6mwzNMADS
+        RLZmGKBIMx0BAwMAmFz+IUIItz8AAAAASUVORK5CYII=
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFISURBVDhPYxic4MnZRsu7Z/r+P7/Q+f/Z+c7/d482/T+x
+        qeL/mulZ/yeX6BRBleEGz09E/v/36eb//0/q/7871Pn/xdKa/w/bm/5HBHv/Dw2154Eqww4eX6h3Ahnw
+        +/6G/78ulv1/uaoOrDkryeN/dIijOlQZbgCzHaT51YZ6sOaOKi/iND85Xx0KMuDXrWX/vx7IA2uur3f9
+        FxtpZxkaGsoMVYYbgDSD/A3Cn85M+f9+74T/Lxc0gg2Kczf4XxZrrglVih2smhT4ZVKt95eiSLuvnVkR
+        P0HeAGnO9tf8X5tibgxVhh+smpLFs2t902OY5p4Mpf+l0Ua2UGnCYMvisq0wzVPz5f/nRRjqQaUIg2m5
+        8oYfjk0Ca55fIfs/L1SXOGfDwJrFrYdBAbe2SeF/mo+OBlSYeAByQU2C8Jo4DxVlqNCgBwwMAKdOxp1Z
+        VlKBAAAAAElFTkSuQmCC
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAH3SURBVDhPrZNPTBNBFMZHUMIW2D+ztNAEXKhItGpDuzPd
+        qglFTDgIHkzDgQuHHjRejGfvnjwZDl6MRy8mEC6ERBLvGoNiGxNJbIyRxBuhlYO7+x4z7fRQKsEEfske
+        5r1v37753ltyKiA3JkLX2oCsPY2EdKjw/4HzpBNc6wHcn8XK4m0fOL0nYyrdAubJWWRGQmgeqVAjCIwW
+        Q07XoDiDpWIyEOcnh4tg3umWHVYWp/2QmS9VuAFk+uOQpbl6kQJDWLiJIbdWITXQU8/nhrQwP7paKTi+
+        0DzDZLS3/uJhMEm6xNcfV2YcXxYS4tfgmSlRbEkVXULXMpT83wgTz4BHLwcZuimv9Gsu/rd2J1UVJi/L
+        TpTseNC1p2TLcPca+hn6HXI6VanjQc8YCTjd+sAp7KdNrKZ19F3rm0ofjdwBSJuO7xrlUnIw2LnStwHc
+        ZtLc31d1BG4+lFdU8naQRwcDL7ZZuzWC5bHI9tuBzik5CfmEjL745Gj+VkJjSt6KnHOYi72pXu+pfRzW
+        9t6f1woqpXaA6j/HI9vlRPf6ikWG2wyFrDm778Xwc0LDL6ORleYONGlcLzr2bujcn9JFLduy8nL+YsZP
+        f1zqxdIF7Svw/vEWgUJu525KfwXM5m15sY2ZkFnPhVGTcMPuO8qs+v/gxiPqeFIIOQBCBNEq+uGsJwAA
+        AABJRU5ErkJggg==
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAC8SURBVDhPY6ApuPXm238ok3Tw8uPX/2WHXvw/cO896YbA
+        NM+7+/e/YfWi/wdvPyfeEGTN+ad//HeaeeS/VvkC4gxB1tx67d//yP2f/nssufjffsr+/xqlcwkbAtJc
+        vP8p2JDay///x534899//b3/mvWr/6sCDVDJn0acV0AGgFwAM0C9YhFpAQkyYPKtv/9zz/0FG6BaNIt0
+        A0DhUHFxIA1Ydv835QaAohCElXMmkW4ASBMyhkoNOsDAAAC0v82EM6R6QQAAAABJRU5ErkJggg==
+
+  
+  
+    
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAENSURBVDhPYxicoOzQi/9F+578z9lx73/qxuv/Y1ee/w+V
+        Ig4U7Hn0f9n93/+n3/rzv/Pa3//KOZNIMyBjy63/8+7+/V9x8e//mCPf/6sWzSLNgPjVF//PuvP3f/G5
+        3//Ddr35r16xiHQDptz69z/n9E/yDei78e9/6tFv5BvQfu3f/7hDX0gzABR9xfuf/s/aevt/49X//yP3
+        f/rvv/7ef8361f9VS+f+V8mfht+gF59+/Pebe/R/9snv//NP//gfvPXpf48lF//bT9n/XwNowOXHrwi7
+        5P7bz/+1W9b9D9zy9L/Pqhv/nWYe+a9VvoA4zTDw8O0XsCGOs479N6xeRJpmGIAZQpZmOgIGBgANscic
+        Mivf1gAAAABJRU5ErkJggg==
+
+  
+  
+    127, 17
+  
+  
+    230, 17
+  
+  
+    
+        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
+        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABE
+        RQAAAk1TRnQBSQFMAgEBEwEAASABAQEgAQEBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
+        AwABUAMAAQEBAAEgBgABUDIAA8wB/wNCAf8DUwH/A+MB/1wAAdcB7QH1Af8BuAHeAe0B/wGTAcwB4gH/
+        AWoBugHYAf8BQgGlAcsB/wHHAdcB3QH/eAAE/wOWAf8DOwH/A0IB/wOGAf8D8QH/DAABOgGjAcoB/wE6
+        AaMBygH/AToBowHKAf8BOgGjAcoB/wE6AaMBygH/AToBowHKAf8BOgGjAcoB/wE6AaMBygH/AToBowHK
+        Af8BOgGjAcoB/wE6AaMBygH/AWEBnwHEAf8BdgGsAcwB/wG7AdMB5AH/EAABZAG+Ad8B/wFhAb4B3AH/
+        AV0BvQHZAf8BXAG9AdgB/wFcAb8B2AH/ATsBowHKAf8BNgGQAbIB/wE5AZMBtQH/AT0BpQHLAf8BPAGk
+        AcsB/wE7AaQBygH/AVUBsAHRAf8BqgHWAecB/2AABP8DhgH/A0IB/wNCAf8DQgH/A/EB/wwAAT4BpgHM
+        Af8BkAHnAfYB/wGHAeQB9AH/AYAB4QHzAf8BdgHfAfIB/wFyAd0B8QH/AW8B2wHwAf8BbgHaAfAB/wFw
+        AdsB8AH/AXMB3AHwAf8BPgGmAcwB/wFPAcwB6gH/AVIBxgHlAf8BdgGsAcwB/xAAAWgBwAHhAf8BgAHU
+        AeQB/wF0AdEB4gH/AW8BzQHgAf8BagHKAd4B/wE8AaQBywH/ATwBogG9Af8BQAGlAcEB/wFIAcEB3gH/
+        AUgBwQHeAf8BSAHBAd4B/wFGAb0B2wH/AVUBsAHRAf9YAAT/A/EB/wPqAf8DhgH/A0IB/wNCAf8DQgH/
+        A/EB/wwAAUMBqQHOAf8BjwHoAfYB/wGGAeUB9QH/AXkB4QHzAf8BcwHeAfIB/wFvAdwB8QH/AWwB3AHw
+        Af8BawHaAfAB/wFsAdoB8AH/AXEB2wHwAf8BQwGpAc4B/wFVAc8B6wH/AdMBpQFDAf8BYAGfAcQB/xAA
+        AWsBwgHiAf8BhgHZAecB/wGBAdUB5QH/AXYB0gHiAf8BcQHOAeAB/wE/AaYBzAH/AT4BowG+Af8BQAGl
+        AcEB/wFIAcEB3gH/AUgBwQHeAf8BSAHBAd4B/wHTAaUBQwH/ATwBpAHLAf9MAAPxAf8D1wH/A/EB/wPd
+        Af8BpAKgAf8DwAH/A4YB/wNCAf8DQgH/AzsB/wPqAf8D8QX/BAABSAGsAdEB/wGQAekB9gH/AYcB5QH1
+        Af8BeQHiAfQB/wFzAeAB8gH/AW8B3gHyAf8BbQHcAfEB/wFrAdsB8QH/AW0B2gHwAf8BcAHcAfEB/wFI
+        AawB0QH/AV0B0gHsAf8B3QG5AVcB/wFgAaEBxQH/EAABbgHEAeQB/wGNAd0B6gH/AYgB2gHoAf8BggHW
+        AeUB/wF3AdMB4wH/AUEBpwHNAf8BRAGmAb8B/wFFAagBwgH/AUwBwwHfAf8BSAHBAd4B/wFIAcEB3gH/
+        Ad0BuQFXAf8BPgGlAcwB/0gAA/EB/wGkAqAB/wM7Af8DzAH/A/EB/wPdAf8BpAKgAf8DUwH/A0IB/wNC
+        Af8DOwH/A7IB/wOWAf8DzAH/A/EB/wFNAa8B0wH/AZMB6wH4Af8BigHoAfcB/wGCAeUB9QH/AXYB4gH0
+        Af8BcwHgAfMB/wFvAd4B8gH/AW0B3QHxAf8BbwHcAfEB/wFzAd0B8QH/AU0BrwHTAf8BZQHVAe4B/wPs
+        Af8BYAGiAcYB/xAAAXIBxgHlAf8BlAHiAe0B/wGOAd4B6wH/AYkB2wHoAf8BhAHXAeYB/wFEAakBzwH/
+        AUwBqgHBAf8BTAGrAcQB/wFVAccB4QH/AVABxQHgAf8BTAHDAd8B/wPsAf8BPwGmAc0B/0QABP8D3QH/
+        AzsB/wNCAf8DQgH/A8wB/wGkAqAB/wOyAf8DOwH/A0IB/wNCAf8DQgH/AaQCoAH/A+oB/wgAAVMBswHW
+        Af8BlwHuAfkB/wGPAeoB+AH/AYcB6AH2Af8BgQHlAfUB/wF4AeMB9AH/AXQB4QHzAf8BcgHgAfIB/wF0
+        Ad8B8gH/AXcB4AHyAf8BUwGzAdYB/wFuAdkB7wH/A+wB/wFfAaMBxgH/EAABdQHIAecB/wGaAeYB8AH/
+        AZUB4wHtAf8BkAHfAesB/wGKAdsB6QH/AUcBqwHQAf8BVAGuAcQB/wFUAa8BxgH/AWABzQHkAf8BWgHK
+        AeMB/wFVAccB4QH/A+wB/wFCAagBzgH/RAAD8QH/AaQCoAH/A0IB/wNCAf8BpAKgAf8DQgH/AzsB/wOy
+        Af8DOwH/AzsB/wNCAf8DQgH/A8AB/wPABf8EAAFZAbcB2QH/AZwB8AH6Af8BlAHtAfgB/wGMAeoB9wH/
+        AYcB6AH2Af8BgwHmAfUB/wF5AeQB9QH/AXgB4wH0Af8BeAHiAfQB/wGBAeIB9AH/AVkBtwHZAf8BeAHd
+        AfEB/wPsAf8BXwGlAccB/xAAAXcBygHoAf8BoAHqAfIB/wGbAecB8AH/AZYB4wHuAf8BkQHgAewB/wFK
+        Aa0B0gH/AV4BsgHGAf8BXQG0AckB/wFtAdMB6AH/AWcB0AHmAf8BYAHNAeQB/wPsAf8BRAGpAc8B/0QA
+        A/EB/wOGAf8DQgH/A0IB/wOyAf8DOwH/AzsB/wOZAf8DQgH/A0IB/wM7Af8DlgH/A1MB/wGkAqAB/wPd
+        Af8EAAFfAboB3AH/AaAB8gH7Af8BmAHvAfkB/wGRAe0B+QH/AYwB6wH4Af8BiAHpAfcB/wGEAecB9gH/
+        AYIB5QH1Af8BggHlAfUB/wGFAeUB9AH/AV8BugHcAf8BiAHhAfMB/wGGAeEB8gH/AV4BpwHIAf8QAAGA
+        AcsB6QH/AaYB7gH1Af8BoQHrAfMB/wGdAegB8QH/AZgB5AHvAf8BTQGvAdQB/wFnAbgByQH/AWcBuAHL
+        Af8BggHaAewB/wF0AdcB6gH/AW0B0wHoAf8BZwHQAeYB/wFGAasB0AH/RAAD6gH/AzsB/wNCAf8DQgH/
+        AaQCoAH/A0IB/wM7Af8DlgH/A0IB/wNCAf8DOwH/A7IB/wNCAf8DmQH/A4YF/wFlAb4B3wH/AaQB9QH8
+        Af8BnAHyAfsB/wGWAe8B+gH/AZEB7QH5Af8BjQHrAfgB/wGKAekB9wH/AYcB5wH2Af8BhwHmAfYB/wGI
+        AeUB9AH/AWYBvwHgAf8BhAHVAegB/wFlAbMB0AH/AaQBzAHfAf8QAAGCAc0B6wH/AasB8QH3Af8BpwHv
+        AfUB/wGjAewB8wH/AZ4B6AHxAf8BUQGyAdUB/wFwAbwBywH/AXABvQHOAf8BkAHiAfAB/wGJAd4B7gH/
+        AYIB2gHsAf8BWQG8AdoB/wGXAc4B5AH/RAAD1wH/AzsB/wNCAf8DQgH/A7IB/wNCAf8DlgH/A7IB/wM7
+        Af8DOwH/A0IB/wOyAf8DhgH/AaQCoAH/AzsB/wPqAf8BagHCAeIB/wGoAfYB/AH/AaEB9AH8Af8BmwHy
+        AfsB/wGVAfAB+gH/AZIB7gH5Af8BjwHsAfgB/wGMAeoB9wH/AYoB6QH3Af8BjQHoAfcB/wF3AdIB6wH/
+        AWkBwQHhAf8B0QHnAfAB/xQAAYQBzgHsAf8BrwH0AfkB/wGsAfIB9wH/AagB7wH2Af8BpAHsAfQB/wFV
+        AbQB1wH/AYABwAHOAf8BeQHBAdAB/wGeAekB8wH/AZcB5QHyAf8BkAHiAfAB/wFOAa8B1AH/SAADsgH/
+        A0IB/wNCAf8DQgH/A7IB/wOyAf8DsgH/A5kB/wM7Af8DOwH/AzsB/wGkAqAB/wPAAf8DsgH/AzsB/wPX
+        Af8BcAHFAeQB/wGrAfgB/QH/AaUB9gH9Af8BnwH0AfwB/wGaAfIB+wH/AZcB8QH6Af8BkwHvAfoB/wGR
+        Ae0B+QH/AY8B7AH4Af8BkQHrAfgB/wGUAesB9wH/AXABxQHkAf8YAAGGAc8B7QH/AbMB9wH6Af8BsAH1
+        AfkB/wGtAfMB+AH/AakB8AH2Af8BWAG2AdkB/wGHAcQB0AH/AYcBxQHSAf8BrAHvAfcB/wGlAewB9QH/
+        AZ4B6QHzAf8BUAGxAdUB/0gAA7IB/wNCAf8DQgH/A0IB/wOWAf8DhgH/AzsB/wM7Af8DQgH/A0IB/wNC
+        Af8DOwH/A4YB/wOGAf8DOwH/A8AB/wF1AcgB5wH/Aa8B+gH+Af8BqQH4Af4B/wGkAfYB/QH/AaAB9QH8
+        Af8BnQHzAfsB/wGaAfEB+wH/AZcB8AH6Af8BlQHvAfkB/wGXAe4B+QH/AZkB7gH4Af8BdQHIAecB/xgA
+        AYcB0AHtAf8BtAH3AfsB/wG0AfcB+wH/AbEB9QH6Af8BrgHzAfgB/wFcAbkB2wH/AYwBxwHRAf8BjgHJ
+        AdQB/wG3AfQB+gH/AbEB8gH5Af8BrAHvAfcB/wFTAbMB1wH/SAAD3QH/AzsB/wM7Af8DOwH/A0IB/wOy
+        Af8DOwH/AzsB/wM7Af8DQgH/A0IB/wNCAf8BpAKgAf8DOwH/AzsB/wPMAf8BgAHLAekB/wG0AfsC/wGu
+        AfoB/gH/AaoB+QH+Af8BpwH4Af0B/wGkAfYB/AH/AaEB9QH8Af8BngHzAfsB/wGdAfEB+gH/AZ4B8AH6
+        Af8BoAHxAfoB/wGAAcsB6QH/GAABhwHQAe0B/wG0AfcB+wH/AbQB9wH7Af8BqgHvAfcB/wGQAdsB7QH/
+        AWABuwHdAf8BkgHMAdUB/wGzAesB8QH/Ab8B+QH8Af8BuwH3AfsB/wG3AfQB+gH/AVYBtQHYAf9IAAPx
+        Af8BpAKgAf8DQgH/AzsB/wM7Af8BpAKgAf8DsgH/A0IB/wM7Af8DOwH/A4YB/wOyAf8DOwH/A0IB/wOy
+        Bf8BhAHOAesB/wG4AfwC/wG1AfsC/wGxAfoB/gH/Aa4B+QH+Af8BrAH4Af0B/wGpAfcB/QH/AacB9gH8
+        Af8BpgH1AfwB/wGmAfQB/AH/AZMB3QHyAf8BhAHOAesB/xgAAYcB0AHtAf8BnQHjAfQB/wGJAdMB7QH/
+        AYcB0AHrAf8BmgHfAfAB/wGWAdMB3gH/Ab4B9gH6Af8BwgH6Af0B/wHCAfoB/QH/AcIB+gH9Af8BswHx
+        AfgB/wFuAcAB3wH/TAAE/wPqAf8D6gH/A/EJ/wPqAf8D6gH/A/EB/wPxAf8DwAH/A8AB/wPqBf8EAAGH
+        AdAB7QH/AYcB0AHtAf8BhwHQAe0B/wGHAdAB7QH/AYcB0AHtAf8BhwHQAe0B/wGHAdAB7QH/AYcB0AHt
+        Af8BhwHQAe0B/wGHAdAB7QH/AYcB0AHtAf8BtgHfAeoB/xgAAZIB1AHvAf8BkAHTAe4B/wGCAc0B6gH/
+        AXkBywHpAf8BdgHJAegB/wFzAccB5gH/AW8BxQHkAf8BawHCAeIB/wFoAcAB4QH/AWQBvQHfAf8BdAHE
+        AeEB/wG3Ad8B7gH/iAAD6gH/A1MB/wM7Af8DOwH/AzsB/wM7Af8DOwH/AzsB/wM7Af8DOwH/AzsB/wM7
+        Af8DOwH/AzsB/wNTAf8D6gH/RAAD3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/
+        A90B/wPdAf8D3QH/A90B/wPdAf8DmQH/A5kB/wOZAf8DmQH/A5kB/wOZAf8DmQH/BAADwAH/A8AB/wPA
+        Af8DwAH/A8AB/wPAAf8DwAH/BAADhgH/AzEB/wMpAf8DKQH/AykB/wMpAf8DKQH/AykB/wMpAf8DMQH/
+        AykB/wMpAf8DKQH/AykB/wMxAf8DhgH/QAADQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wNC
+        Af8DQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8D3QH/A5kB/wOZAf8DmQH/A5kB/wOZAf8DmQH/A5kB/wQA
+        A8AB/wPAAf8DwAH/A8AB/wPAAf8DwAH/A8AB/wQAAzsB/wMxAf8DMQH/AzEB/wMxAf8DwAH/A5YB/wM7
+        Af8DhgH/AzEB/wMxAf8DMQH/AzEB/wMxAf8DMQH/AzsB/wwAA/EB/wPAAf8DlgH/A4YB/wOGAf8DUwH/
+        A4YB/wOyAf8D8QH/EAADQgH/A4YB/wOGAf8DhgH/A4YB/wNTAf8DUwH/A1MB/wNTAf8DUwH/A0IB/wNC
+        Af8DQgH/A0IB/wNCAf8D3QH/A5kB/wOZAf8DmQH/A5kB/wOZAf8DmQH/A5kB/wQAA8AB/wPAAf8DwAH/
+        A8AB/wPAAf8DwAH/A8AB/wQAA0IB/wMxAf8DMQH/AzEB/wOGAf8DhgH/A7IB/wOWAf8DMQH/AzEB/wMx
+        Af8DMQH/AzEB/wMxAf8DzAH/A0IB/wwAAaQCoAH/A7IB/wPXAf8D6gH/A+MB/wPAAf8DsgH/A5YB/wOG
+        Af8QAANCAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DUwH/A1MB/wNTAf8DUwH/A0IB/wNCAf8DQgH/
+        A0IB/wPdAf8DmQH/A5kB/wOZAf8DmQH/A5kB/wOZAf8DmQH/BAADwAH/A8AB/wPAAf8DwAH/A8AB/wPA
+        Af8DwAH/BAADQgH/AzEB/wMxAf8DMQH/AaQCoAH/A0IB/wOZAf8DUwH/AzEB/wMxAf8DMQH/AzEB/wMx
+        Af8DmQH/AaQCoAH/A0IB/wwAA5YB/wPdAf8D6gH/A+oB/wPdAf8DwAH/A7IB/wOyAf8DQgH/EAADQgH/
+        A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wNTAf8DUwH/A0IB/wNCAf8D3QH/
+        A5kB/wOZAf8DmQH/A5kB/wOZAf8DmQH/A5kB/wQAA8AB/wPAAf8DwAH/A8AB/wPAAf8DwAH/A8AB/wQA
+        A0IB/wM7Af8DOwH/AzsB/wGkAqAB/wNCAf8DOwH/AzsB/wM7Af8DOwH/AzsB/wM7Af8DOwH/A9cB/wM7
+        Af8DQgH/DAADlgH/A9cB/wPjAf8D6gH/A90B/wPAAf8DsgH/A7IB/wNCAf8QAANCAf8DhgH/A4YB/wPA
+        Hf8DwAH/A4YB/wNTAf8DQgH/A90B/wOZAf8DmQH/A5kB/wOZAf8DmQH/A5kB/wOZAf8EAAPAAf8DwAH/
+        A8AB/wPAAf8DwAH/A8AB/wPAAf8EAANCAf8DOwH/AzsB/wM7Af8DhgH/A5YB/wM7Af8DOwH/AzsB/wM7
+        Af8DOwH/AzsB/wOZAf8DsgH/AzsB/wNCAf8MAAOZAf8D1wH/A+MB/wPqAf8D3QH/A8AB/wOyAf8DsgH/
+        A0IB/xAAA0IB/wOGAf8D3QX/A+MB/wOyAf8DsgH/A7IB/wOyAf8DsgH/A+MF/wPdAf8DUwH/A0IB/wPd
+        Af8DmQH/A5kB/wOZAf8DmQH/A5kB/wOZAf8DmQH/BAADwAH/A8AB/wPAAf8DwAH/A8AB/wPAAf8DwAH/
+        BAADQgH/A0IB/wNCAf8DQgH/A1MB/wOyAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8D1wH/A0IB/wNC
+        Af8DQgH/DAADmQH/A9cB/wPjAf8D6gH/A90B/wPAAf8DsgH/A7IB/wNTAf8QAANCAf8DlgX/A90B/wOG
+        Af8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8D3QX/A5YB/wNCAf8D3QH/QAADUwH/A0IB/wNCAf8DQgH/
+        A8AB/wNCAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wOyAf8BpAKgAf8DQgH/A0IB/wNTAf8MAAOZAf8D1wH/
+        A+MB/wPqAf8D3QH/A8AB/wOyAf8DsgH/A1MB/xAAA0IB/wOyBf8DlgH/A4YB/wOGAf8DhgH/A4YB/wOG
+        Af8DhgH/A4YB/wOWBf8DsgH/A0IB/wPdAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/BAADsgH/
+        A7IB/wOyAf8DsgH/A7IB/wOyAf8DsgH/BAADUwH/A0IB/wNCAf8DhgH/A7IB/wNCAf8DQgH/A0IB/wNC
+        Af8DQgH/A5YB/wPAAf8DQgH/A0IB/wNCAf8DUwH/DAABpAKgAf8D1wH/A+MB/wPqAf8D3QH/A8AB/wOy
+        Af8DsgH/A1MB/xAAA0IB/wOyBf8DlgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOWBf8DsgH/
+        A0IB/wPdAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/BAADsgH/A7IB/wOyAf8DsgH/A7IB/wOy
+        Af8DsgH/BAADhgH/A0IB/wNCAf8DsgH/A4YB/wNTAf8DmQH/A0IB/wNCAf8BpAKgAf8DwAH/A0IB/wNC
+        Af8DQgH/A0IB/wOGAf8MAAGkAqAB/wPXAf8D4wH/A+oB/wPdAf8DwAH/A7IB/wOyAf8DUwH/EAADQgH/
+        A5YF/wPdAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A90F/wOWAf8DQgH/A90B/wOGAf8DhgH/
+        A4YB/wOGAf8DhgH/A4YB/wOGAf8EAAOyAf8DsgH/A7IB/wOyAf8DsgH/A7IB/wOyAf8EAAOGAf8DQgH/
+        A4YB/wOyAf8DQgH/A1MB/wNCAf8DhgH/A8AB/wOyAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wOGAf8MAAOy
+        Af8D3QH/A+oB/wPqAf8D6gH/A+MB/wPdAf8DwAH/A4YB/xAAA0IB/wOGAf8D3QX/A+MB/wOyAf8DsgH/
+        A7IB/wOyAf8DsgH/A+MF/wPdAf8DhgH/A0IB/wPdAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/
+        BAADsgH/A7IB/wOyAf8DsgH/A7IB/wOyAf8DsgH/BAADhgH/A0IB/wPAAf8DUwH/A4YB/wPMAf8DzAH/
+        A8AB/wOGAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8DhgH/DAADsgH/A90B/wPxAf8D8QH/A/EB/wPx
+        Af8D8QH/A90B/wOWAf8QAANCAf8DhgH/A4YB/wPAHf8DwAH/A4YB/wOGAf8DQgH/A90B/wOGAf8DhgH/
+        A4YB/wOGAf8DhgH/A4YB/wOGAf8EAAOyAf8DsgH/A7IB/wOyAf8DsgH/A7IB/wOyAf8EAAOGAf8DUwH/
+        A8wB/wPMAf8DwAH/A4YB/wNTAf8DUwH/A1MB/wNTAf8DUwH/A1MB/wNTAf8DUwH/A1MB/wOGAf8MAAPq
+        Af8DzAH/A7IB/wGkAqAB/wOZAf8DmQH/AaQCoAH/A8AB/wPjAf8QAANCAf8DhgH/A4YB/wOGAf8DhgH/
+        A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A0IB/wPdAf8DhgH/A4YB/wOGAf8DhgH/
+        A4YB/wOGAf8DhgH/BAADsgH/A7IB/wOyAf8DsgH/A7IB/wOyAf8DsgH/BAADmQH/A4YB/wNTAf8DUwH/
+        A1MB/wNTAf8DUwH/A1MB/wNTAf8DUwH/A1MB/wNTAf8DUwH/A1MB/wOGAf8DmQH/QAADQgH/A4YB/wOG
+        Af8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wNCAf8D3QH/A4YB/wOG
+        Af8DhgH/A4YB/wOGAf8DhgH/A4YB/wQAA7IB/wOyAf8DsgH/A7IB/wOyAf8DsgH/A7IB/wQAA+oB/wOZ
+        Af8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DhgH/A4YB/wOGAf8DmQH/A+oB/0AA
+        A0IB/wNCAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8DQgH/A0IB/wNCAf8DQgH/
+        /wD/AB4ABP88AAPxAf8wAAPxAf8BkAGpAa0B/wPxAf80AAPxAf8BpAKgAf8D8QH/PAAE/wGZAQ8BAAX/
+        NAAD8QH/AwUB/wPxAf8sAAPAAf8BmQHMAv8BDwKZAf8D8QH/MAADsgH/A8AB/wNTAf8D8QH/NAAE/wHM
+        AUIBDwH/AcwBmQEPAf8BmQEPAQAF/ywAA/EB/wMpAf8DhgH/AwUB/wPxAf8oAAPxAf8BmQHMAv8BgAFY
+        Av8BDwFCAZkB/wPxAf8sAAPxAf8DwAH/A4YB/wNCAf8D8QH/LAAE/wHMAUIBDwL/AcwBQgL/AZkBQgH/
+        AcwBmQEPAf8BmQEPAQAF/yQAA/EB/wMpAf8DmQH/A4YB/wOGAf8DBQH/A/EB/ygAA8wB/wFCAcwC/wGA
+        AVgC/wEPAUIBmQH/A/EB/ywAA8AB/wPMAf8DhgH/A0IB/wPxAf8kAAT/AcwBQgEPAv8BzAGZAv8BzAFC
+        Av8BzAFCAv8BmQFCAf8BzAGZAQ8B/wGZAQ8BAAX/HAAD8QH/AykB/wOyAf8BpAKgAf8DmQH/A4YB/wOG
+        Af8DBQH/A/EB/yQABP8BmQLMAf8BQgHMAv8BgAFYAv8BDwFCAZkB/wPqAf8oAAT/A7IB/wPMAf8DhgH/
+        AzsB/wPqAf8cAAT/AcwBmQFCAv8BzAGZAv8BzAGZAv8BzAGZAv8BzAFCAv8BzAFCAv8BmQFCAf8BzAGZ
+        AQ8B/wGZAQ8BAAX/FAAD8QH/A4YB/wPAAf8DwAH/A7IB/wGkAqAB/wOZAf8DhgH/A4YB/wMFAf8D8QH/
+        HAABQgGZAcwB/wFCApkB/wEPAkIB/wFCApkB/wFCAcwC/wGAAVgC/wIPAUIB/wPxAf8gAAOGAf8DUwH/
+        AzsB/wNCAf8DzAH/A4YB/wMeAf8D8QH/HAAE/wHMAZkBQgL/AcwBmQL/AcwBmQL/AcwBmQL/AcwBQgL/
+        AcwBQgL/AZkBQgH/AcwBmQEPAf8BmQEPAQAF/xQAA/EB/wOGAf8DwAH/A8AB/wOyAf8BpAKgAf8DmQH/
+        A4YB/wOGAf8DBQH/A/EB/xgAAUICzAH/AUIBzAL/AUIBzAL/AZkBzAL/AZkBzAL/ApkC/wGAAVgC/wIP
+        AUIB/wPxAf8cAAPAAf8D3QH/A90B/wPAAf8DwAH/AaQCoAH/A4YB/wMVAf8D8QH/HAAE/wHMAZkBQgL/
+        AcwBmQL/AcwBmQL/AcwBmQL/AcwBQgL/AcwBQgL/AZkBQgH/AcwBmQEPAf8BmQEPAQAF/xQAA/EB/wOG
+        Af8DwAH/A8AB/wOyAf8BpAKgAf8DmQH/A4YB/wOGAf8DBQH/A/EB/xQAA/EB/wFCAswB/wGZAcwC/wFC
+        AcwC/wGAAVgC/wEPApkB/wPqBf8gAAPqAf8DwAH/A9cB/wPAAf8DhgH/A4YB/wPqBf8kAAT/AcwBmQFC
+        Av8BzAGZAv8BzAGZAv8BzAGZAv8BzAFCAv8BzAFCAf8BzAFCAQ8F/xwAA/EB/wOGAf8DwAH/A8AB/wOy
+        Af8BpAKgAf8DmQH/AzsB/wPxAf8cAAFCAswB/wHMA/8BQgHMAv8BQgHMAv8BgAFYAv8BDwFCAZkB/wPx
+        Af8kAAPAAf8D8QH/A8wB/wOyAf8DhgH/A0IB/wPxAf8oAAT/AcwBmQFCAv8BzAGZAv8BzAGZAv8BzAGZ
+        Af8BzAGZAUIF/yQAA/EB/wOGAf8DwAH/A8AB/wOyAf8DhgH/A/EB/yAAA/EB/wFCAswB/wHGAdYB7wH/
+        AUIBzAL/AUIBmQL/AYABWAL/AzsB/wPxAf8gAAPxAf8DwAH/A90B/wPMAf8BpAKgAf8DhgH/AykB/wPx
+        Af8oAAT/AcwBmQFCAv8BzAGZAf8BzAGZAUIF/ywAA/EB/wOGAf8DwAH/A4YB/wPxAf8oAAFCAswB/wHM
+        A/8BQgHMAv8BmQHMAv8BQgGZAv8BgAFYAv8DMQX/IAADwAH/A+oB/wPdAf8DwAH/AaQCoAH/A4YB/wMV
+        Bf8oAAT/AcwBmQFCBf80AAPxAf8DhgH/A/EB/ywAA/EB/wGZAswB/wGZAswB/wGZAswB/wGZAswB/wFC
+        AswB/wFCApkB/wPXAf8gAAPxAf8DwAH/A8AB/wPAAf8DwAH/AaQCoAH/A4YB/wPXAf8sAAT/PAAD8QH/
+        /wDhAAPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/A90B/wPdAf8D3QH/
+        A90B/yAAA8wB/wGZAUIBDwH/AZkCQgH/A+MB/5IAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIA
+        AcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wPd
+        Af8cAAT/ApkBQgH/AZkBQgEPAf8BmQFCAQ8B/wKZAUIB/wPxAf9YAAPxAf8BmQLMAf8BQgKZAf8BQgKZ
+        Af8BDwFCAZkB/wEPAUIBmQH/AQ8BQgGZAf8BkAGpAa0B/wPxAf8SAAHMAf8CAAL/AgAC/wIAAv8CAAL/
+        AgAC/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wPd
+        Af8cAAT/ApkBQgH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/A/EB/yQABP8wAAGQAakBrQH/AUICzAH/
+        AZkBzAL/AZkD/wFCAcwC/wEPAcwC/wEAAZkBzAH/AQABmQHMAf8BQgKZAf8SAAHMAf8CAAL/AgAC/wIA
+        Av8CAAL/AgAC/wIAAv8CAAL/AgABzAH/AgABzAH/AgABzAH/AgABzAH/AgABzAH/AgABzAH/AgABzAH/
+        A90B/xQABP8D8QH/A/EB/wKZAUIB/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wPxAf8gAAT/AZkBDwGZ
+        Bf8sAAFCApkB/wEPAcwC/wGZA/8BmQP/AUIBzAL/AQ8BzAL/AQABmQL/AQABmQHMAf8BDwFCAZkB/xIA
+        AcwB/wIAAv8CAAL/AgAC/wIAAv8CLAL/AiwC/wIsAv8CLAL/AiwC/wIAAv8CAAHMAf8CAAHMAf8CAAHM
+        Af8CAAHMAf8D3QH/CAAD8QH/A9cB/wPxAf8D3QH/AaQCoAH/A8AB/wGZAkIB/wGZAUIBDwH/AZkBQgEP
+        Af8BmQFCAQ8B/wPqAf8D8QX/FAAE/wHMAQ8BzAH/AcwBQgHMAf8BmQEPAZkF/ygAAUICmQH/AQ8BzAL/
+        AZkBzAL/AZkD/wFCAcwC/wEPAcwC/wEAAZkC/wEAAZkBzAH/AQ8BQgGZAf8SAAHMAf8CAAL/AgAC/wKZ
+        Hv8CmQL/AgAC/wIAAcwB/wIAAcwB/wPdAf8EAAPxAf8BzAKZAf8BmQFCAQ8B/wPMAf8D8QH/A+MB/wGk
+        AqAB/wGZAkIB/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wPAAf8DmQH/A8wB/wPxAf8MAAT/AcwBQgHM
+        Av8BmQL/AcwBmQHMAf8BzAFCAcwB/wGZAQ8BmQX/JAABQgGZAcwB/wEPAcwC/wGZAcwC/wGZA/8BQgHM
+        Av8BDwHMAv8BAAGZAv8BAAGZAcwB/wEPAUIBmQH/EgABzAH/AgAC/wLMBv8CzAL/AYABWAL/AYABWAL/
+        AYABWAL/AYABWAL/AYABWAL/AswG/wLMAv8CAAHMAf8CAAHMAf8D3QX/A9cB/wGZAUIBDwH/AZkBQgEP
+        Af8BmQFCAQ8B/wPMAf8BpAKgAf8CzAGZAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGk
+        AqAB/wPqAf8QAAT/AcwBQgHMAv8BzAP/AZkD/wGZAv8BzAGZAcwB/wHMAUIBzAH/AZkBDwGZBf8gAAFC
+        AZkBzAH/AQ8BzAL/AZkBzAL/AZkD/wFCAcwC/wEPAcwC/wEAAZkC/wEAAZkBzAH/AQ8BQgGZAf8SAAHM
+        Af8CLAb/AswC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CzAb/AiwC/wIAAcwB/wPdAf8D8QH/
+        AcwCmQH/AZkBQgEPAf8BmQFCAQ8B/wHMApkB/wGZAUIBDwH/AZkBQgEPAf8CzAGZAf8BmQFCAQ8B/wGZ
+        AUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wPAAf8DwAX/CAAE/wHMAUIBzAL/AcwD/wHMA/8BzAP/AZkD/wGZ
+        Av8BzAGZAcwB/wHMAUIBzAH/AZkBDwGZBf8cAAFCAZkBzAH/AQ8BzAL/AZkBzAL/AZkD/wFCAcwC/wEP
+        AcwC/wEAAZkC/wEAAZkBzAH/AQ8BQgGZAf8SAAHMAf8BgAFYBv8CLAL/AgAC/wIAAv8CAAL/AgAC/wIA
+        Av8CAAL/AgAC/wIsBv8BgAFYAv8CAAHMAf8D3QH/A/EB/wKZAUIB/wGZAUIBDwH/AZkBQgEPAf8CzAGZ
+        Af8BmQFCAQ8B/wGZAUIBDwH/AcwBmQFCAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8CmQFCAf8BmQJC
+        Af8BzAKZAf8D4wH/DAAE/wHMAUIBzAL/AcwD/wHMA/8BzAP/AZkD/wGZAv8BzAGZAcwB/wHMAUIBzAH/
+        AZkBDwGZBf8YAAFCAZkBzAH/AQ8BzAL/AZkBzAL/AZkD/wFCAcwC/wEPAcwC/wEAAZkC/wEAAZkBzAH/
+        AQ8BQgGZAf8SAAHMAf8BgAFYBv8CLAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIsBv8BgAFY
+        Av8CAAHMAf8D3QH/A+oB/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wHMApkB/wGZAUIBDwH/AZkBQgEP
+        Af8CmQFCAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8CzAGZAf8BmQFCAQ8B/wHMAZkBQgH/ApkBQgX/
+        DAAE/wHMAUIBzAL/AcwD/wHMA/8BzAP/AZkD/wGZAv8BzAGZAcwB/wHMAUIBzAH/AZkBDwGZBf8UAAFC
+        AZkBzAH/AQ8BzAL/AZkBzAL/AZkD/wFCAcwC/wEPAcwC/wEAAZkC/wEAAZkBzAH/AQ8BQgGZAf8SAAHM
+        Af8CLAb/AswC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CzAb/AiwC/wIAAcwB/wPdAf8DzAH/
+        AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AswBmQH/AkIBDwH/ApkBQgH/AswBmQH/AZkBQgEPAf8BmQFC
+        AQ8B/wGZAUIBDwH/AswBmQH/ApkBQgH/AcwCmQH/AZkBQgEPAf8D8QH/EAAE/wHMAUIBzAL/AcwD/wHM
+        A/8BzAP/AZkD/wGZAv8BzAFCAcwF/xgAAUIBmQHMAf8BQgHMAv8BmQP/AZkD/wGZA/8BmQHMAv8BQgHM
+        Av8BDwHMAv8BDwFCAZkB/xIAAcwB/wIAAv8CzAb/AswC/wGAAVgC/wGAAVgC/wGAAVgC/wGAAVgC/wGA
+        AVgC/wLMBv8CzAL/AgAC/wIAAcwB/wPdAf8DsgH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AcwCmQH/
+        AswBmQH/AswBmQH/AcwBmQFCAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BzAKZAf8CzAGZAf8CzAGZ
+        Af8BmQFCAQ8B/wPXAf8UAAT/AcwBQgHMAv8BzAP/AcwD/wHMAv8BzAFCAcwF/xwAAZABqQGtAf8BmQHM
+        Av8BzAP/AcwD/wHMA/8BzAP/AcwD/wGZAcwC/wFCApkB/xIAAcwB/wIAAv8CAAL/Apke/wKZAv8CAAL/
+        AgAC/wIAAcwB/wPdAf8BzAKZAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8CmQFCAf8BmQJCAf8BmQFC
+        AQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8CmQFCAf8CmQFCAf8BmQFC
+        AQ8B/wLMAZkB/xgABP8BzAFCAcwC/wHMAv8BzAFCAcwF/yAAA+oB/wGZAswB/wFCAZkBzAH/AZABqQGt
+        Af8BQgKZAf8BQgKZAf8BQgGZAcwB/wGZAswB/wHWAucB/xIAAcwB/wIAAv8CAAL/AgAC/wIAAv8CLAL/
+        AiwC/wIsAv8CLAL/AiwC/wIAAv8CAAL/AgAC/wIAAv8CAAHMAf8D3QH/A90B/wGZAUIBDwH/AZkBQgEP
+        Af8BmQFCAQ8B/wGZAUIBDwH/AswBmQH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFC
+        AQ8B/wGZAUIBDwH/AcwCmQH/AZkBQgEPAf8BmQFCAQ8B/wPMAf8cAAT/AcwBQgHMBf9aAAHMAf8CAAL/
+        AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgAC/wIAAv8CAAL/AgABzAH/A90B/wPx
+        Af8BzAKZAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BpAKgAf8BpAKgAf8BmQFCAQ8B/wGZAUIBDwH/
+        AZkBQgEPAf8CmQFCAf8CzAGZAf8BmQFCAQ8B/wGZAUIBDwH/AswBmQX/IAAE/14AAcwB/wIAAcwB/wIA
+        AcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIAAcwB/wIA
+        AcwB/wIAAcwB/wIAAcwB/wgABP8D6gH/A+oB/wPxCf8D6gH/A+oB/wPxAf8D8QH/A8AB/wPAAf8D6gX/
+        nAAD8QH/A/EB/wPxAf8D8QH/WAAD6gH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFC
+        AQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/
+        AZkBQgEPAf8BmQFCAQ8B/wPqAf9YAAPxAf8BQgGZAUIB/wFCAZkBQgH/A/EB/xgAAf8BmQEAAv8BmQEA
+        Av8BmQEAAv8BmQEAAv8BmQEAAv8BmQEAAv8BmQEAAf8FAAHMAv8BAAHMAv8BAAHMAv8BAAHMAv8BAAHM
+        Av8BAAHMAv8BAAHMAv8EAAKZAUIB/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJC
+        AQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wKZAUIB/xQAAUIBzAGZ
+        Af8BQgHMAZkB/wFCAZkBQgH/AQ8BmQFCAf8BDwFCAQ8B/zAAA/EB/wFCAZkBQgH/AUIBmQFCAf8D8QH/
+        GAAB/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAB/wUAAcwC/wEAAcwC/wEA
+        AcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wQAAZkBQgEPAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEP
+        Af8CzAGZAf8CmQFCAf8CQgEPAf8BmQJCAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEP
+        Af8BmQFCAQ8B/xQAA+oB/wPxAf8D6gH/A+oB/wPjAf8sAAPxAf8D8QH/AUIBmQFCAf8BQgGZAUIB/wPx
+        Af8D8QH/FAAB/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAB/wUAAcwC/wEA
+        AcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wQAAZkBQgEPAf8CQgEPAf8CQgEPAf8CQgEP
+        Af8CmQFCAf8CmQFCAf8CzAGZAf8CmQFCAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEPAf8CQgEP
+        Af8DzAH/AZkBQgEPAf8UAAFCAcwBmQH/AZkBzAGZAf8BQgHMAZkB/wEPAcwBQgH/AQ8BQgEPAf8oAAPx
+        Af8D1wH/AUIBmQFCAf8BDwGZAQ8B/wEPAZkBDwH/AUIBmQFCAf8D1wH/A/EB/xAAAf8BmQEAAv8BmQEA
+        Av8BmQEAAv8BmQEAAv8BmQEAAv8BmQEAAv8BmQEAAf8FAAHMAv8BAAHMAv8BAAHMAv8BAAHMAv8BAAHM
+        Av8BAAHMAv8BAAHMAv8EAAGZAUIBDwH/AkIBDwH/AkIBDwH/AkIBDwH/AcwCmQH/AZkBQgEPAf8BpAKg
+        Af8BmQFCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wJCAQ8B/wGkAqAB/wHMApkB/wGZAUIBDwH/
+        FAABwAHcAcAB/wHAAdwBwAH/AcAB3AHAAf8BwAHcAcAB/wOyAf8kAAPxAf8D1wH/AQ8BmQEPAf8BmQHM
+        AZkB/wPdAf8D3QH/AZkBzAGZAf8BDwGZAQ8B/wPXAf8D8QH/DAAB/wGZAQAC/wGZAQAC/wGZAQAC/wGZ
+        AQAC/wGZAQAC/wGZAQAC/wGZAQAB/wUAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEA
+        AcwC/wQAAZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BzAKZAf8BmQFCAQ8B/wGZAUIBDwH/
+        AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/A9cB/wGZAUIBDwH/
+        AZkBQgEPAf8UAAFCAcwBmQH/AZkBzAGZAf8BQgHMAZkB/wEPAcwBQgH/AQ8BQgEPAf8kAAPxAf8BQgGZ
+        AUIB/wGZAcwBmQH/A/EB/wPxAf8D8QH/A/EB/wGZAcwBmQH/AUIBmQFCAf8D8QH/DAAB/wGZAQAC/wGZ
+        AQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAC/wGZAQAB/wUAAcwC/wEAAcwC/wEAAcwC/wEAAcwC/wEA
+        AcwC/wEAAcwC/wEAAcwC/wQAAZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8CmQFCAf8CmQFC
+        Af8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BzAGZAUIB/wHM
+        ApkB/wGZAUIBDwH/AZkBQgEPAf8UAAGZAcwBmQH/AcAB3AHAAf8BmQHMAZkB/wGZAcwBmQH/AUICmQH/
+        JAAD8QH/AQ8BmQEPAf8D3QH/A/EB/wPxAf8D8QH/A/EB/wPdAf8BDwGZAQ8B/wPxAf8MAAH/AZkBAAL/
+        AZkBAAL/AZkBAAL/AZkBAAL/AZkBAAL/AZkBAAL/AZkBAAH/BQABzAL/AQABzAL/AQABzAL/AQABzAL/
+        AQABzAL/AQABzAL/AQABzAL/BAABmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/
+        AswBmQH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/A9cB/wGZ
+        AUIBDwH/AZkBQgEPAf8BmQFCAQ8B/xQAAUIBzAGZAf8BmQHMAZkB/wFCAcwBmQH/AQ8BzAFCAf8BDwFC
+        AQ8B/yQAA/EB/wEPAZkBDwH/A/EB/wPxAf8D8QH/A/EB/wPxAf8D8QH/AQ8BmQEPAf8D8QH/TAABmQFC
+        AQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wLMAZkB/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZ
+        AUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wLMAZkB/wHMApkB/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wwA
+        AUIBzAGZAf8BQgHMAZkB/wFCAcwBmQH/AUIBzAGZAf8BQgHMAZkB/wEPAcwBQgH/AQ8BQgEPAf8BDwFC
+        AQ8B/wEPAUIBDwH/HAAD8QH/AQ8BmQEPAf8D8QH/A/EB/wPxAf8D8QH/A/EB/wPxAf8BDwGZAQ8B/wPx
+        Af8MAAIPAv8CDwL/Ag8C/wIPAv8CDwL/Ag8C/wIPAv8FAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8BAAHM
+        AUIB/wEAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wQAAZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/ApkBQgH/
+        AswBmQH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wHMAZkBQgH/AfABygGm
+        Af8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wwABP8BQgHMAZkB/wGZAcwBmQH/AZkBzAGZ
+        Af8BQgHMAZkB/wFCAcwBQgH/AUIBmQFCAf8BDwFCAQ8B/wPqAf8cAAPxAf8BDwGZAQ8B/wPxAf8D8QH/
+        A/EB/wPxAf8D8QH/A/EB/wEPAZkBDwH/A/EB/wwAAg8C/wIPAv8CDwL/Ag8C/wIPAv8CDwL/Ag8C/wUA
+        AcwBQgH/AQABzAFCAf8BAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wEAAcwBQgH/BAACmQEP
+        Af8BmQFCAQ8B/wGZAUIBDwH/AswBmQH/ApkBDwH/AZkBQgEPAf8BzAGZAUIB/wGZAUIBDwH/AZkBQgEP
+        Af8BzAKZAf8B8AHKAaYB/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/ApkBDwH/EAAE/wFC
+        AcwBmQH/AZkBzAGZAf8BQgHMAZkB/wFCAZkBQgH/AQ8BQgEPAf8D6gH/IAAD8QH/AQ8BmQEPAf8BDwGZ
+        AQ8B/wEPAZkBDwH/AQ8BmQEPAf8BDwGZAQ8B/wEPAZkBDwH/AQ8BmQEPAf8BDwGZAQ8B/wPxAf8MAAIP
+        Av8CDwL/Ag8C/wIPAv8CDwL/Ag8C/wIPAv8FAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wEA
+        AcwBQgH/AQABzAFCAf8BAAHMAUIB/wQAAcwBmQEPAf8BmQFCAQ8B/wKZAUIB/wLMAZkB/wGZAUIBDwH/
+        AZkBQgEPAf8BmQFCAQ8B/wKZAUIB/wHwAcoBpgH/AswBmQH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/
+        AZkBQgEPAf8BmQFCAQ8B/wHMAZkBDwH/FAAE/wFCAcwBmQH/AZkBzAGZAf8BDwFCAQ8B/wPqAf8kAAPx
+        Af8D8QH/A/EB/wEPAZkBDwH/A/EB/wPxAf8BDwGZAQ8B/wPxAf8D8QH/A/EB/wwAAg8C/wIPAv8CDwL/
+        Ag8C/wIPAv8CDwL/Ag8C/wUAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8BAAHM
+        AUIB/wEAAcwBQgH/BAABzAGZAQ8B/wGZAUIBDwH/AfABygGmAf8BmQFCAQ8B/wHMAZkBQgH/AfABygGm
+        Af8B8AHKAaYB/wHwAcoBpgH/ApkBQgH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFC
+        AQ8B/wGZAUIBDwH/AcwBmQEPAf8YAAT/AUIBzAGZAf8B1gLnAf8wAAPxAf8BDwGZAQ8B/wPxAf8D8QH/
+        AQ8BmQEPAf8D8QH/FAACDwL/Ag8C/wIPAv8CDwL/Ag8C/wIPAv8CDwL/BQABzAFCAf8BAAHMAUIB/wEA
+        AcwBQgH/AQABzAFCAf8BAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8EAAHMAZkBDwH/AZkBQgEPAf8B8AHK
+        AaYB/wHwAcoBpgH/AfABygGmAf8CmQEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZ
+        AUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BzAGZAQ8B/xwAA/EB/zQAA/EB/wEP
+        AZkBDwH/A/EB/wPxAf8BDwGZAQ8B/wPxAf8UAAIPAv8CDwL/Ag8C/wIPAv8CDwL/Ag8C/wIPAv8FAAHM
+        AUIB/wEAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wQAAcwBmQFC
+        Af8CmQEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFC
+        AQ8B/wGZAUIBDwH/AZkBQgEPAf8BmQFCAQ8B/wGZAUIBDwH/AZkBQgEPAf8CmQEPAf8BzAGZAUIB/1QA
+        A/EB/wPxAf8D8QH/A/EB/wPxAf8D8QH/FAACDwL/Ag8C/wIPAv8CDwL/Ag8C/wIPAv8CDwL/BQABzAFC
+        Af8BAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8BAAHMAUIB/wEAAcwBQgH/AQABzAFCAf8EAAPxAf8BzAGZ
+        AUIB/wHMAZkBDwH/AcwBmQEPAf8BzAGZAQ8B/wHMAZkBDwH/AcwBmQEPAf8BzAGZAQ8B/wHMAZkBDwH/
+        AcwBmQEPAf8BzAGZAQ8B/wHMAZkBDwH/AcwBmQEPAf8BzAGZAQ8B/wHMAZkBQgH/A/EB/wFCAU0BPgcA
+        AT4DAAEoAwABQAMAAVADAAEBAQABAQUAAYABAhYAA/8BAAH/AQ8C/wHgAX8CAAH+AQcBAAEDAcABAQIA
+        Af4BBwEAAQMBwAEBAgAB+AEHAQABAwHAAQECAAHAAQEBAAEDAcABAQIAAYACAAEDAcABAQMAAQMBAAED
+        AcABAQMAAQEBAAEDAcABAQMAAQEBAAEDAcABAQUAAQMBwAEBBQABBwHAAQMFAAEPAcABAwUAAQ8BwAED
+        BQABDwHAAQMFAAEPAcABAwIAAYABAQEAAQ8BwAEDAgAC/wIAAv8BgAEAAgECAAL/AgACAQIAAeABDwIA
+        AgECAAHgAQ8CAAIBAgAB4AEPAgACAQIAAeABDwIAAgECAAHgAQ8CAAIBAgAB4AEPAgAC/wIAAeABDwIA
+        AgECAAHgAQ8CAAIBAgAB4AEPAgACAQIAAeABDwIAAgECAAHgAQ8CAAIBAgAB4AEPAgACAQIAAv8CAAIB
+        AgAC/wEAAQEQ/wH9Af8B/QH/AeMB/wHjAf8B+AH/AfgB/wHhAf8B4QH/AfABfwHwAX8B4AH/AeAB/wHg
+        AT8B4AE/AfABfwHwAX8BwAEfAcABHwHwAT8B8AE/AYABDwGAAQ8B4AEfAeABHwHAAQcBwAEHAeABDwHg
+        AQ8B4AEDAeABAwHgAR8B4AEfAfABBwHwAQcB8AEfAfABHwH4AQ8B+AEPAfABDwHwAQ8B/AEfAfwBHwH4
+        AQcB+AEHAf4BPwH+AT8B+AEHAfgBBwH/AX8B/wF/Dv8BgAEAAf8BDwT/AgAB/gEHAv8B4AEPAgAB/gEH
+        Af0B/wHgAQ8CAAH4AQcB+AH/AeABDwIAAcABAQHwAX8B4AEPAgABgAEAAeABPwHgAQ8DAAEDAcABHwHg
+        AQ8DAAEBAYABDwHgAQ8DAAEBAcABBwHgAQ8EAAHgAQMB4AEPBAAB8AEHAeABDwQAAfgBDwHgAQ8EAAH8
+        AR8B4AEPBAAB/gE/Av8EAAH/AX8C/wEAAQEBgAEBBP8B/AE/Av8CAAL/AfwBPwIBAgAB+AE/AfwBPwIB
+        AgAB+AE/AfgBHwIBAgAB+AE/AfABDwIBAgAB+AE/AeABBwIBAgAB+AE/AeABBwIBAgAB+AE/AeABBwIB
+        AgAB+AE/AeABBwL/AgAB4AEPAeABBwIBAgAB4AEPAeABBwIBAgAB8AEfAeABBwIBAgAB+AE/AeABBwIB
+        AgAB/AF/AfgBHwIBAgAB/gH/AfgBHwIBAgAC/wH4AR8CAQIACw==
+
+  
+
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.Designer.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.Designer.cs
new file mode 100644
index 000000000..77f567cc6
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.Designer.cs
@@ -0,0 +1,127 @@
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    partial class FrmRangeEdit
+    {
+        /// 
+        /// Required designer variable.
+        /// 
+        private System.ComponentModel.IContainer components = null;
+
+        /// 
+        /// Clean up any resources being used.
+        /// 
+        /// true if managed resources should be disposed; otherwise, false.
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// 
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// 
+        private void InitializeComponent()
+        {
+            this.lblExample = new System.Windows.Forms.Label();
+            this.txtRange = new System.Windows.Forms.TextBox();
+            this.lblRange = new System.Windows.Forms.Label();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.btnOK = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // lblExample
+            // 
+            this.lblExample.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+            this.lblExample.AutoSize = true;
+            this.lblExample.ForeColor = System.Drawing.SystemColors.GrayText;
+            this.lblExample.Location = new System.Drawing.Point(11, 161);
+            this.lblExample.Name = "lblExample";
+            this.lblExample.Size = new System.Drawing.Size(109, 13);
+            this.lblExample.TabIndex = 2;
+            this.lblExample.Text = "For example: 1 - 5, 10";
+            // 
+            // txtRange
+            // 
+            this.txtRange.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+            this.txtRange.Location = new System.Drawing.Point(14, 26);
+            this.txtRange.Multiline = true;
+            this.txtRange.Name = "txtRange";
+            this.txtRange.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this.txtRange.Size = new System.Drawing.Size(310, 132);
+            this.txtRange.TabIndex = 1;
+            // 
+            // lblRange
+            // 
+            this.lblRange.AutoSize = true;
+            this.lblRange.Location = new System.Drawing.Point(11, 10);
+            this.lblRange.Name = "lblRange";
+            this.lblRange.Size = new System.Drawing.Size(129, 13);
+            this.lblRange.TabIndex = 0;
+            this.lblRange.Text = "Range of integer numbers";
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.btnCancel.Location = new System.Drawing.Point(249, 177);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(75, 23);
+            this.btnCancel.TabIndex = 4;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            // 
+            // btnOK
+            // 
+            this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnOK.Location = new System.Drawing.Point(168, 177);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(75, 23);
+            this.btnOK.TabIndex = 3;
+            this.btnOK.Text = "OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // FrmRangeEdit
+            // 
+            this.AcceptButton = this.btnOK;
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this.btnCancel;
+            this.ClientSize = new System.Drawing.Size(334, 211);
+            this.Controls.Add(this.lblExample);
+            this.Controls.Add(this.txtRange);
+            this.Controls.Add(this.lblRange);
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnOK);
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.MinimumSize = new System.Drawing.Size(300, 200);
+            this.Name = "FrmRangeEdit";
+            this.ShowIcon = false;
+            this.ShowInTaskbar = false;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+            this.Text = "Edit Range";
+            this.Load += new System.EventHandler(this.FrmRangeEdit_Load);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label lblExample;
+        private System.Windows.Forms.TextBox txtRange;
+        private System.Windows.Forms.Label lblRange;
+        private System.Windows.Forms.Button btnCancel;
+        private System.Windows.Forms.Button btnOK;
+    }
+}
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.cs
new file mode 100644
index 000000000..932ed0fee
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.cs
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Range edit or add form
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2020
+ * Modified : 2021
+ */
+
+using Scada.UI;
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// Range edit or add form
+    /// Форма редактирования или добавления диапазонов
+    /// 
+    public partial class FrmRangeEdit : Form
+    {
+        private ICollection resultRange; // range after editing
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public FrmRangeEdit()
+        {
+            InitializeComponent();
+            resultRange = null;
+        }
+
+        /// 
+        /// Edits Range or Adds Range.
+        /// 
+        public static bool EditRange(ICollection range)
+        {
+            if (range == null)
+                throw new ArgumentNullException(nameof(range));
+
+            FrmRangeEdit frmRange = new FrmRangeEdit();
+            frmRange.txtRange.Text = RangeUtils.RangeToStr(range);
+
+            if (frmRange.ShowDialog() == DialogResult.OK)
+            {
+                range.Clear();
+
+                foreach (int val in frmRange.resultRange)
+                {
+                    range.Add(val);
+                }
+
+                return true;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        private void FrmRangeEdit_Load(object sender, EventArgs e)
+        {
+            Translator.TranslateForm(this, GetType().FullName);
+            LibPhrases.Init();
+        }
+
+        private void btnOK_Click(object sender, EventArgs e)
+        {
+            if (RangeUtils.StrToRange(txtRange.Text, true, true, out resultRange))
+                DialogResult = DialogResult.OK;
+            else
+                ScadaUiUtils.ShowError(LibPhrases.RangeNotValid);
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.resx b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.resx
new file mode 100644
index 000000000..1af7de150
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/FrmRangeEdit.resx
@@ -0,0 +1,120 @@
+
+
+  
+  
+    
+    
+      
+        
+          
+            
+              
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+              
+            
+          
+          
+            
+              
+                
+                
+              
+              
+              
+              
+              
+            
+          
+          
+            
+              
+                
+              
+              
+            
+          
+        
+      
+    
+  
+  
+    text/microsoft-resx
+  
+  
+    2.0
+  
+  
+    System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+  
+    System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+  
+
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/DbExport/UI/LibPhrases.cs b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/LibPhrases.cs
new file mode 100644
index 000000000..27d78c0b4
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/DbExport/UI/LibPhrases.cs
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2021 Elena Shiryaeva
+ * All rights reserved
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : The phrases used by the module
+ * 
+ * Author   : Elena Shiryaeva
+ * Created  : 2021
+ * Modified : 2021
+ */
+
+namespace Scada.Server.Modules.DbExport.UI
+{
+    /// 
+    /// The phrases used by the module.
+    /// Фразы, используемые модулем.
+    /// 
+    internal static class LibPhrases
+    {
+        // Scada.Server.Modules.DbExport.UI.FrmDbExportConfig
+        public static string ConnectionOptionsNode { get; private set; }
+        public static string ArcUploadOptionsNode { get; private set; }
+        public static string TriggerGrNode { get; private set; }
+        public static string CurDataTrigger { get; private set; }
+        public static string ArcDataTrigger { get; private set; }
+        public static string EventTrigger { get; private set; }
+        public static string CurDataType { get; private set; }
+        public static string ArcDataType { get; private set; }
+        public static string EventType { get; private set; }
+        public static string TargetName{ get; private set; }
+        public static string TargetNameNotUnique { get; private set; }
+        public static string NameEmpty { get; private set; }
+
+        // Scada.Server.Modules.DbExport.UI.FrmRangeEdit
+        public static string RangeNotValid { get; private set; }
+
+        public static void Init()
+        {
+            Localization.Dict dict = Localization.GetDictionary("Scada.Server.Modules.DbExport.UI.FrmDbExportConfig");
+           
+            ConnectionOptionsNode = dict.GetPhrase("ConnectionOptionsNode");
+            ArcUploadOptionsNode = dict.GetPhrase("ArcUploadOptionsNode");
+            TriggerGrNode = dict.GetPhrase("TriggerGrNode");
+
+            CurDataType = dict.GetPhrase("CurDataType");
+            ArcDataType = dict.GetPhrase("ArcDataType");
+            EventType = dict.GetPhrase("EventType");
+
+            CurDataTrigger = dict.GetPhrase("CurDataTrigger");
+            ArcDataTrigger = dict.GetPhrase("ArcDataTrigger");
+            EventTrigger = dict.GetPhrase("EventTrigger");
+            TargetName = dict.GetPhrase("TargetName");
+
+            NameEmpty = dict.GetPhrase("NameEmpty");
+            TargetNameNotUnique = dict.GetPhrase("TargetNameNotUnique");
+
+            dict = Localization.GetDictionary("Scada.Server.Modules.DbExport.UI.FrmRangeEdit");
+            RangeNotValid = dict.GetPhrase("RangeNotValid");
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDbExport/Lang/ModDbExport.en-GB.xml b/ScadaServer/OpenModules/ModDbExport/Lang/ModDbExport.en-GB.xml
new file mode 100644
index 000000000..9379ba0b7
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/Lang/ModDbExport.en-GB.xml
@@ -0,0 +1,70 @@
+
+
+	
+		Export to DB
+		Export Targets
+		Add export target
+		Add current data trigger
+		Add archive data trigger
+		Add event trigger
+		Delete
+		Move up
+		Move down
+		Save
+		Cancel
+		Close
+		General
+		Active
+		Target ID
+		Name
+		Maximum queue size
+		Data life time, sec
+		Output channel number
+		Connection Options
+		DBMS
+		Database
+		Server
+		User
+		Password
+		Connection string
+		Trigger
+		Trigger name
+		Trigger type
+		Filters
+		Input channels
+		Device numbers
+		Query
+		Single query (input channels required)
+		SQL
+		Available parametrs
+		Archive Upload Options
+		Enabled
+		Snapshot code
+		Cur
+		Min
+		Hour
+		Delay before sending archive, ms
+		Maximum age of archive, days
+		Connection Options
+		Archive Upload Options
+		Triggers
+		Target
+		Current data trigger
+		Archive data trigger
+		Event trigger
+		Current data trigger
+		Archive data trigger
+		Event trigger
+		Target names must be unique.
+		The name of the gate cannot be empty.
+	
+	
+		Edit Range
+		Range of integer numbers
+		For example: 1 - 5, 10
+		OK
+		Cancel
+		The range is not valid.
+		The range of integer number cannot be empty.
+	
+
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/Lang/ModDbExport.ru-RU.xml b/ScadaServer/OpenModules/ModDbExport/Lang/ModDbExport.ru-RU.xml
new file mode 100644
index 000000000..68dbee727
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/Lang/ModDbExport.ru-RU.xml
@@ -0,0 +1,70 @@
+
+
+	
+		Экспорт в БД
+		Цель
+		Добавить цель экспорта
+		Добавить триггер на текущие данные
+		Добавить триггер на архивные данные
+		Добавить триггер на событие
+		Удалить
+		Переместить вверх
+		Переместить вниз
+		Сохранить
+		Отменить
+		Закрыть
+		Общие настройки
+		Активен
+		Идент.
+		Наименование
+		Максимальный размер очереди
+		Время ожидания в очереди, с
+		Номер канала управления для управления экспортом
+		Параметры соединения
+		СУБД
+		База данных
+		Сервер
+		Пользователь
+		Пароль
+		Строка соединения
+		Триггер
+		Имя триггера
+		Тип триггера
+		Фильтры
+		Входные каналы
+		Номера КП
+		Запрос
+		Одним запросом (требуются входные каналы)
+		SQL
+		Доступные параметры
+		Параметры загрузки архива
+		Включено
+		Срез
+		Текущий
+		Минутный
+		Часовой
+		Задержка перед отправкой архива, мс
+		Максимальный срок архива, дней
+		Параметры соединения
+		Параметры загрузки архива
+		Триггеры
+		Цель
+		Tриггер на текущие данные
+		Триггер на архивные данные
+		Триггер на событие
+		Tриггер на текущие данные
+		Триггер на архивные данные
+		Триггер на событие
+		Имя цели должны быть уникальным.
+		Имя цели не должно быть пустым.
+	
+	
+		Редактирование диапазона
+		Диапазон целых чисел
+		Например: 1 - 5, 10
+		OK
+		Отмена
+		Диапазон целых чисел некорректен.
+		Диапазон целых чисел не может быть пустым.
+	
+
diff --git a/ScadaServer/OpenModules/ModDBExport/ModDBExport.csproj b/ScadaServer/OpenModules/ModDbExport/ModDbExport.csproj
similarity index 50%
rename from ScadaServer/OpenModules/ModDBExport/ModDBExport.csproj
rename to ScadaServer/OpenModules/ModDbExport/ModDbExport.csproj
index 9a3e3c7bb..9182d2905 100644
--- a/ScadaServer/OpenModules/ModDBExport/ModDBExport.csproj
+++ b/ScadaServer/OpenModules/ModDbExport/ModDbExport.csproj
@@ -1,16 +1,17 @@
 
-
+
   
   
     Debug
     AnyCPU
-    {CD5B2061-B57F-4FEB-9596-779DDCFAC2C7}
+    {1943BB06-1D1E-45A6-ADF0-B6437512138B}
     Library
     Properties
     Scada.Server.Modules
-    ModDBExport
+    ModDbExport
     v4.7.2
     512
+    true
     
   
   
@@ -21,7 +22,6 @@
     DEBUG;TRACE
     prompt
     4
-    false
   
   
     pdbonly
@@ -30,12 +30,10 @@
     TRACE
     prompt
     4
-    false
   
   
-    
-      False
-      ..\..\..\Log\Log\bin\Release\Log.dll
+    
+      ..\..\..\..\scada\Log\Log\bin\Release\Log.dll
     
     
       ..\packages\MySql.Data.6.9.12\lib\net45\MySql.Data.dll
@@ -43,13 +41,14 @@
     
       ..\packages\Npgsql.4.0.11\lib\net451\Npgsql.dll
     
-    
-      False
-      ..\..\..\ScadaData\ScadaData\bin\Release\ScadaData.dll
+    
+      ..\..\..\..\scada\ScadaData\ScadaData\bin\Release\ScadaData.dll
     
-    
-      False
-      ..\..\ScadaServer\ScadaServerCommon\bin\Release\ScadaServerCommon.dll
+    
+      ..\..\..\..\scada\ScadaData\ScadaData.Db\bin\Release\ScadaData.Db.dll
+    
+    
+      ..\..\..\..\scada\ScadaServer\ScadaServer\ScadaServerCommon\bin\Release\ScadaServerCommon.dll
     
     
     
@@ -79,35 +78,72 @@
     
   
   
-    
-    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+      UserControl
+    
+    
+      CtrlArcUploadOptions.cs
+    
+    
+      UserControl
+    
+    
+      CtrlConnectionOptions.cs
+    
+    
       UserControl
     
-    
-      CtrlExportQuery.cs
+    
+      CtrlEventTrigger.cs
     
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    
+      UserControl
+    
+    
+      CtrlGeneralOptions.cs
+    
+    
+      UserControl
+    
+    
+      CtrlTrigger.cs
+    
+    
       Form
     
-    
-      FrmDBExportConfig.cs
+    
+      FrmDbExportConfig.cs
     
-    
+    
       Form
     
-    
-      FrmManualExport.cs
+    
+      FrmRangeEdit.cs
     
-    
-    
+    
+    
     
     
       True
@@ -116,44 +152,44 @@
     
   
   
-    
-    
+    
+    
+      PreserveNewest
+    
+    
+      PreserveNewest
+    
   
   
-    
-      CtrlExportQuery.cs
+    
+      CtrlArcUploadOptions.cs
+    
+    
+      CtrlConnectionOptions.cs
+    
+    
+      CtrlEventTrigger.cs
     
-    
-      FrmDBExportConfig.cs
+    
+      CtrlGeneralOptions.cs
     
-    
-      FrmManualExport.cs
+    
+      CtrlTrigger.cs
+    
+    
+      FrmDbExportConfig.cs
+    
+    
+      FrmRangeEdit.cs
     
     
       ResXFileCodeGenerator
       Resources.Designer.cs
     
   
-  
   
-    
-      PreserveNewest
-    
-    
-    
-    
-    
-    
-    
-    
-    
+    
+    
   
   
-  
 
\ No newline at end of file
diff --git a/ScadaServer/OpenModules/ModDbExport/ModDbExportLogic.cs b/ScadaServer/OpenModules/ModDbExport/ModDbExportLogic.cs
new file mode 100644
index 000000000..afaa4265f
--- /dev/null
+++ b/ScadaServer/OpenModules/ModDbExport/ModDbExportLogic.cs
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2021 Mikhail Shiryaev
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * 
+ * Product  : Rapid SCADA
+ * Module   : ModDbExport
+ * Summary  : Server module logic
+ * 
+ * Author   : Mikhail Shiryaev
+ * Created  : 2015
+ * Modified : 2021
+ */
+
+using Scada.Data.Entities;
+using Scada.Data.Models;
+using Scada.Data.Tables;
+using Scada.Server.Modules.DbExport;
+using Scada.Server.Modules.DbExport.Config;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Utils;
+
+namespace Scada.Server.Modules
+{
+    /// 
+    /// Server module logic.
+    /// Логика работы серверного модуля.
+    /// 
+    public class ModDbExportLogic : ModLogic
+    {
+        /// 
+        /// The log file name.
+        /// 
+        private const string LogFileName = "ModDbExport.log";
+
+        private Log log;                  // the module log
+        private List exporters; // the active exporters
+
+
+        /// 
+        /// Initializes a new instance of the class.
+        /// 
+        public ModDbExportLogic()
+        {
+            log = null;
+            exporters = null;
+        }
+
+
+        /// 
+        /// Gets the module name.
+        /// 
+        public override string Name
+        {
+            get
+            {
+                return "ModDbExport";
+            }
+        }
+
+
+        /// 
+        /// Loads a map of channels and devices.
+        /// 
+        private bool LoadEntityMap(out EntityMap entityMap)
+        {
+            try
+            {
+                BaseTable inCnlTable = new BaseTable("InCnl", "CnlNum", CommonPhrases.InCnlTable);
+
+                BaseAdapter adapter = new BaseAdapter()
+                {
+                    Directory = Settings.BaseDATDir,
+                    TableName = "incnl.dat"
+                };
+
+                adapter.Fill(inCnlTable, false);
+                entityMap = new EntityMap();
+                entityMap.Init(inCnlTable);
+
+                log.WriteAction(Localization.UseRussian ?
+                    "Карта каналов и КП загружена" :
+                    "Map of channels and devices loaded");
+                return true;
+            }
+            catch (Exception ex)
+            {
+                log.WriteException(ex, Localization.UseRussian ?
+                    "Ошибка при загрузке карты каналов и КП" :
+                    "Error loading map of channels and devices");
+                entityMap = null;
+                return false;
+            }
+        }
+
+        /// 
+        /// Performs actions when starting Server.
+        /// 
+        public override void OnServerStart()
+        {
+#if DEBUG
+            System.Diagnostics.Debugger.Launch();
+#endif
+
+            // write to log
+            log = new Log(Log.Formats.Simple) { FileName = Path.Combine(AppDirs.LogDir, LogFileName) };
+            log.WriteBreak();
+            log.WriteAction(string.Format(ModPhrases.StartModule, Name));
+
+            // load configuration
+            exporters = new List();
+            ModConfig config = new ModConfig();
+            string errMsg = "";
+
+            if (LoadEntityMap(out EntityMap entityMap) &&
+                config.Load(Path.Combine(AppDirs.ConfigDir, ModConfig.ConfigFileName), out errMsg) &&
+                config.Validate(out List activeExportConfigs, out errMsg))
+            {
+                // create and start exporters
+                log.WriteAction(Localization.UseRussian ?
+                    "Запуск экспорта" :
+                    "Start export");
+
+                foreach (ExportTargetConfig exporterConfig in activeExportConfigs)
+                {
+                    try
+                    {
+                        Exporter exporter = new Exporter(exporterConfig, entityMap, ServerData, AppDirs, Settings.ArcDir);
+                        exporters.Add(exporter);
+                        exporter.Start();
+                    }
+                    catch (Exception ex)
+                    {
+                        log.WriteException(ex, Localization.UseRussian ?
+                            "Ошибка при создании экспортёра" :
+                            "Error creating exporter");
+                    }
+                }
+            }
+            else
+            {
+                if (errMsg != "")
+                    log.WriteError(errMsg);
+
+                log.WriteError(ModPhrases.NormalModExecImpossible);
+            }
+        }
+
+        /// 
+        /// Performs actions when Server stops.
+        /// 
+        public override void OnServerStop()
+        {
+            // stop exporters
+            log.WriteAction(Localization.UseRussian ?
+                "Остановка экспорта" :
+                "Stop export");
+
+            foreach (Exporter exporter in exporters)
+            {
+                exporter.Stop();
+            }
+
+            // write to log
+            log.WriteAction(string.Format(ModPhrases.StopModule, Name));
+            log.WriteBreak();
+        }
+
+        /// 
+        /// Performs actions after receiving and processing new current data.
+        /// 
+        public override void OnCurDataProcessed(int[] cnlNums, SrezTableLight.Srez curSrez)
+        {
+            if (exporters.Count > 0)
+            {
+                SrezTableLight.Srez snapshot = new SrezTableLight.Srez(DateTime.Now, cnlNums, curSrez);
+
+                foreach (Exporter exporter in exporters)
+                {
+                    exporter.EnqueueCurData(snapshot);
+                }
+            }
+        }
+
+        /// 
+        /// Performs actions after receiving and processing new archive data.
+        /// 
+        public override void OnArcDataProcessed(int[] cnlNums, SrezTableLight.Srez arcSrez)
+        {
+            if (exporters.Count > 0 && arcSrez != null)
+            {
+                SrezTableLight.Srez snapshot = new SrezTableLight.Srez(arcSrez.DateTime, cnlNums, arcSrez);
+
+                foreach (Exporter exporter in exporters)
+                {
+                    exporter.EnqueueArcData(snapshot);
+                }
+            }
+        }
+
+        /// 
+        /// Performs actions after creating an event.
+        /// 
+        public override void OnEventCreated(EventTableLight.Event ev)
+        {
+            foreach (Exporter exporter in exporters)
+            {
+                exporter.EnqueueEvent(ev);
+            }
+        }
+
+        /// 
+        /// Performs actions after receiving the telecontrol command.
+        /// 
+        public override void OnCommandReceived(int ctrlCnlNum, Command cmd, int userID, ref bool passToClients)
+        {
+            foreach (Exporter exporter in exporters)
+            {
+                exporter.EnqueueCmd(ctrlCnlNum, cmd, ref passToClients);
+            }
+        }
+    }
+}
diff --git a/ScadaServer/OpenModules/ModDBExport/ModDBExportView.cs b/ScadaServer/OpenModules/ModDbExport/ModDbExportView.cs
similarity index 73%
rename from ScadaServer/OpenModules/ModDBExport/ModDBExportView.cs
rename to ScadaServer/OpenModules/ModDbExport/ModDbExportView.cs
index c2fd2d252..ba7243f1b 100644
--- a/ScadaServer/OpenModules/ModDBExport/ModDBExportView.cs
+++ b/ScadaServer/OpenModules/ModDbExport/ModDbExportView.cs
@@ -15,7 +15,7 @@
  * 
  * 
  * Product  : Rapid SCADA
- * Module   : ModDBExport
+ * Module   : ModDbExport
  * Summary  : Server module user interface
  * 
  * Author   : Mikhail Shiryaev
@@ -23,7 +23,7 @@
  * Modified : 2021
  */
 
-using Scada.Server.Modules.DBExport;
+using Scada.Server.Modules.DbExport.UI;
 
 namespace Scada.Server.Modules
 {
@@ -31,37 +31,37 @@ namespace Scada.Server.Modules
     /// Server module user interface.
     /// Пользовательский интерфейс серверного модуля.
     /// 
- public class ModDBExportView : ModView + public class ModDbExportView : ModView { /// - /// Версия модуля. + /// The module version. /// - internal const string ModVersion = "5.0.1.3"; + internal const string ModVersion = "5.1.0.1"; /// - /// Конструктор. + /// Initializes a new instance of the class. /// - public ModDBExportView() + public ModDbExportView() { CanShowProps = true; } /// - /// Получить описание модуля. + /// Gets the module description. /// public override string Descr { get { - return Localization.UseRussian ? - "Экспорт данных в БД в реальном времени." : + return Localization.UseRussian ? + "Экспорт данных в БД в реальном времени." : "Real time data export to DB."; } } /// - /// Получить версию модуля. + /// Gets the module version. /// public override string Version { @@ -71,13 +71,12 @@ public override string Version } } - /// - /// Отобразить свойства модуля. + /// Shows module properties. /// public override void ShowProps() { - FrmDBExportConfig.ShowDialog(AppDirs, ServerComm); + new FrmDbExportConfig(AppDirs).ShowDialog(); } } } diff --git a/ScadaServer/OpenModules/ModDBExport/Properties/AssemblyInfo.cs b/ScadaServer/OpenModules/ModDbExport/Properties/AssemblyInfo.cs similarity index 79% rename from ScadaServer/OpenModules/ModDBExport/Properties/AssemblyInfo.cs rename to ScadaServer/OpenModules/ModDbExport/Properties/AssemblyInfo.cs index aeb3aeddc..92fc57110 100644 --- a/ScadaServer/OpenModules/ModDBExport/Properties/AssemblyInfo.cs +++ b/ScadaServer/OpenModules/ModDbExport/Properties/AssemblyInfo.cs @@ -2,10 +2,10 @@ using System.Reflection; using System.Runtime.InteropServices; -// General Information about an assembly is controlled through the following +// General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("ModDBExport")] +[assembly: AssemblyTitle("ModDbExport")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] @@ -14,23 +14,23 @@ [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("fc784fae-ca3b-451d-b328-a2e7924aaa75")] +[assembly: Guid("1943bb06-1d1e-45a6-adf0-b6437512138b")] // Version information for an assembly consists of the following four values: // // Major Version -// Minor Version +// Minor Version // Build Number // Revision // -// You can specify all the values or you can default the Build and Revision Numbers +// You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion(ModDBExportView.ModVersion)] -[assembly: AssemblyFileVersion(ModDBExportView.ModVersion)] \ No newline at end of file +[assembly: AssemblyVersion(ModDbExportView.ModVersion)] +[assembly: AssemblyFileVersion(ModDbExportView.ModVersion)] diff --git a/ScadaServer/OpenModules/ModDBExport/Properties/Resources.Designer.cs b/ScadaServer/OpenModules/ModDbExport/Properties/Resources.Designer.cs similarity index 100% rename from ScadaServer/OpenModules/ModDBExport/Properties/Resources.Designer.cs rename to ScadaServer/OpenModules/ModDbExport/Properties/Resources.Designer.cs diff --git a/ScadaServer/OpenModules/ModDbExport/Properties/Resources.resx b/ScadaServer/OpenModules/ModDbExport/Properties/Resources.resx new file mode 100644 index 000000000..1af7de150 --- /dev/null +++ b/ScadaServer/OpenModules/ModDbExport/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ScadaServer/OpenModules/ModDBExport/app.config b/ScadaServer/OpenModules/ModDbExport/app.config similarity index 52% rename from ScadaServer/OpenModules/ModDBExport/app.config rename to ScadaServer/OpenModules/ModDbExport/app.config index fc5fbe838..b071f1605 100644 --- a/ScadaServer/OpenModules/ModDBExport/app.config +++ b/ScadaServer/OpenModules/ModDbExport/app.config @@ -1,9 +1,16 @@  - - + + + + + + + + + - + \ No newline at end of file diff --git a/ScadaServer/OpenModules/ModDBExport/packages.config b/ScadaServer/OpenModules/ModDbExport/packages.config similarity index 100% rename from ScadaServer/OpenModules/ModDBExport/packages.config rename to ScadaServer/OpenModules/ModDbExport/packages.config diff --git a/ScadaServer/OpenModules/OpenModules.sln b/ScadaServer/OpenModules/OpenModules.sln index 8c11be132..03c28d8f0 100644 --- a/ScadaServer/OpenModules/OpenModules.sln +++ b/ScadaServer/OpenModules/OpenModules.sln @@ -1,14 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28010.2036 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31729.503 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModTest", "ModTest\ModTest.csproj", "{1D0EF7CF-B70B-4544-A11B-EAE4F6DCFF7F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModDBExport", "ModDBExport\ModDBExport.csproj", "{CD5B2061-B57F-4FEB-9596-779DDCFAC2C7}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModActiveDirectory", "ModActiveDirectory\ModActiveDirectory.csproj", "{2D224EFD-95FC-4039-AE99-72D383464FF5}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModDbExport", "ModDbExport\ModDbExport.csproj", "{1943BB06-1D1E-45A6-ADF0-B6437512138B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -19,14 +19,14 @@ Global {1D0EF7CF-B70B-4544-A11B-EAE4F6DCFF7F}.Debug|Any CPU.Build.0 = Debug|Any CPU {1D0EF7CF-B70B-4544-A11B-EAE4F6DCFF7F}.Release|Any CPU.ActiveCfg = Release|Any CPU {1D0EF7CF-B70B-4544-A11B-EAE4F6DCFF7F}.Release|Any CPU.Build.0 = Release|Any CPU - {CD5B2061-B57F-4FEB-9596-779DDCFAC2C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CD5B2061-B57F-4FEB-9596-779DDCFAC2C7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CD5B2061-B57F-4FEB-9596-779DDCFAC2C7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CD5B2061-B57F-4FEB-9596-779DDCFAC2C7}.Release|Any CPU.Build.0 = Release|Any CPU {2D224EFD-95FC-4039-AE99-72D383464FF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2D224EFD-95FC-4039-AE99-72D383464FF5}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D224EFD-95FC-4039-AE99-72D383464FF5}.Release|Any CPU.ActiveCfg = Release|Any CPU {2D224EFD-95FC-4039-AE99-72D383464FF5}.Release|Any CPU.Build.0 = Release|Any CPU + {1943BB06-1D1E-45A6-ADF0-B6437512138B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1943BB06-1D1E-45A6-ADF0-B6437512138B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1943BB06-1D1E-45A6-ADF0-B6437512138B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1943BB06-1D1E-45A6-ADF0-B6437512138B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE