bool CreateAppeal(Appeal newAppeal)
        {
            OracleConnection conn = DB.GetConnection();
            OracleCommand cmd = new OracleCommand();
            cmd.Connection = conn;
            OracleDataReader dr = null;
            string NewAppealID = "";
            //

            cmd.CommandText = "select CONCAT('1" + newAppeal.subjcode.PadLeft(2, '0') + "', LPAD(AKRIKO.seq_appeal.NEXTVAL,7,'0')) from dual";
            try {
                dr = cmd.ExecuteReader();
            } catch (Oracle.DataAccess.Client.OracleException e) {
                _t(e.Message.ToString());
                cmd.Dispose();
                //DB.CloseConnection();
                return false;
            }
            dr.Read();
            if (dr.IsDBNull(0)) {
                //DB.CloseConnection();
                return false;
            } else {
                NewAppealID = dr.GetString(0);
            }
            // Сохраняем реальные id родительских обращений
            if (newAppeal.id != null) {
                this.ParentIDs.Add(new string[] { newAppeal.id, NewAppealID });
            }
            //
            dr.Dispose();
            cmd.Dispose();
            String query = "insert into AKRIKO.APPEAL " +
                "(id, numb, f_date, hod_ispoln, is_control, is_repeat, podtv, subjcode, parent_id, is_sud, is_collective, replicate_need, created, unread, meri_cik, links, sud_tematika, content_cik, ispolnitel_cik_id, del)" +
                " VALUES (:newappealid, :numb, TO_DATE(:f_date, 'DD.MM.YYYY'), :hod_ispoln, :is_control, :is_repeat, :podtv, :subjcode, :parent_id, :is_sud, :is_collective, :replicate_need, :created, :unread, :meri_cik, :links, :sud_tematika, :content_cik, :ispolnitel_cik_id, :del)";

            OracleCommand command = new OracleCommand(query, conn);
            command.Parameters.Add(":newappealid", NewAppealID);
            command.Parameters.Add(":numb", newAppeal.numb);
            command.Parameters.Add(":f_date", newAppeal.f_date);
            command.Parameters.Add(":hod_ispoln", "0");
            command.Parameters.Add(":is_control", "0");
            command.Parameters.Add(":is_repeat", "0");
            command.Parameters.Add(":podtv", newAppeal.confirmation);
            command.Parameters.Add(":subjcode", Int32.Parse(newAppeal.subjcode));
            command.Parameters.Add(":parent_id", newAppeal.parent_id);
            command.Parameters.Add(":is_sud", "0");
            command.Parameters.Add(":is_collective", "0");
            command.Parameters.Add(":replicate_need", "0");
            command.Parameters.Add(":created", this.ConvertDate);
            command.Parameters.Add(":unread", "0");
            command.Parameters.Add(":meri_cik", newAppeal.measures);
            command.Parameters.Add(":links", "0");
            command.Parameters.Add(":sud_tematika", "0");
            command.Parameters.Add(":content_cik", newAppeal.content);
            command.Parameters.Add(":ispolnitel_cik_id", newAppeal.executor_id);
            command.Parameters.Add(":del", "0");

            command.ExecuteNonQuery();
            this.Log("appeal", NewAppealID);

            foreach (string[] str in newAppeal.multi) {
                command.CommandText = "insert into akriko.appeal_multi (appeal_id,col_name,content,key) values(" + NewAppealID + ",'" + str[0] + "','" + str[1] + "', '" + str[2] + "')";
                command.ExecuteNonQuery();
            }
            // Добавляем ещё строки, которые доавляет АКРИКО.
            command.CommandText = "insert into akriko.appeal_multi (appeal_id,col_name,key) values(" + NewAppealID + ",'sud_declarant',0)";
            command.ExecuteNonQuery();
            command.CommandText = "insert into akriko.appeal_multi (appeal_id,col_name,key) values(" + NewAppealID + ",'sud_member',0)";
            command.ExecuteNonQuery();
            command.CommandText = "insert into akriko.appeal_multi (appeal_id,col_name,key) values(" + NewAppealID + ",'election_ik',0)";
            command.ExecuteNonQuery();
            // Добавляем запись в журнал корректировок.
            command.CommandText = "insert into akriko.log_appeal (time, action, appeal_id, user_subjcode, user_l_name) values(TO_TIMESTAMP('" + this.ConvertDate.ToString("dd.MM.yyyy HH-mm-ss") + "', 'DD.MM.YYYY HH24-MI-SS'), '1', " + NewAppealID + ", '0', 'Converter')";
            command.ExecuteNonQuery();
            command.Dispose();

            return true;
        }
        /// <summary>
        /// <para>Проверяет данные заявки</para>
        /// <para>Возвращает true если данные разобраны без ошибок и false в противном случае.</para>
        /// </summary>
        /// <param name="row">Строка таблицы.</param>
        /// <param name="parsedData">out ArayList с данными либо с ошибками, если разбор завершился неудаче.</param>
        bool CheckAppeal(Row row, ArrayList appeals, out ArrayList errors)
        {
            errors = new ArrayList();
            bool result = true;
            string cellText = "";
            string tmp;
            string DeclarantType = "";
            string DeclarantParty = "";
            ArrayList cellParsedValues;
            ArrayList Subjects = new ArrayList();
            ArrayList NumbersAndDates = new ArrayList();
            // ФИО и info заявителей из колонки "Кем заявлено".
            ArrayList AppealDeclarants = new ArrayList();
            // Объект для хранения общих данных обращения/обращений
            Appeal NewAppeal = new Appeal();
            NewAppeal.init();
            // Пропускаем первую и последнюю колонку.
            for (int colIndex = 1; colIndex < row.Cells.Count - 1; colIndex++) {
                Cell c = row.Cells[colIndex];
                cellText = "";
                tmp = "";
                // Собираем текст ячейки из всех параграфов в одну переменную.
                for (int i = 0; i < c.Paragraphs.Count; i++) {
                    if (c.Paragraphs[i].Text.Trim() != "") {
                        cellText += c.Paragraphs[i].Text + " ";
                    }
                }
                // Запускаем разбор текста из ячейки.
                switch (colIndex) {
                    // Субъект РФ+
                    case 1:
                        if (ParseSubject(cellText, out cellParsedValues)) {
                            // Проверка завершилась успешно - заполняем массив субъектов
                            foreach (string str in cellParsedValues) {
                                Subjects.Add(str);
                            }
                        } else {
                            // Проверка завершилась с ошибкой.
                            result = false;
                            errors.Add(new ErrorMessage("Субъект Российской Федерации: ", MessageType.Header, colIndex));
                            // Добавляем все сообщения об ошибках в errors.
                            foreach (string str in cellParsedValues) {
                                errors.Add(new ErrorMessage(str, MessageType.Text));
                            }
                        }
                        break;
                    // Содержание+
                    case 2:
                        if (ParseContent(cellText, out tmp)) {
                            NewAppeal.content = tmp;
                        } else {
                            result = false;
                            errors.Add(new ErrorMessage("Содержание: ", MessageType.Header, colIndex));
                            errors.Add(new ErrorMessage(tmp, MessageType.Text));
                        }
                        break;
                    // Заявитель+
                    case 3:
                        if (ParseDeclarant(cellText, out cellParsedValues)) {
                            // Проверка завершилась успешно - заполняем массив заявителей
                            foreach (string[] str in cellParsedValues) {
                                AppealDeclarants.Add(str);
                            }

                        } else {
                            // Проверка завершилась с ошибкой.
                            result = false;
                            errors.Add(new ErrorMessage("Кем заявлено: ", MessageType.Header, colIndex));

                            // Добавляем все сообщения об ошибках в errors.
                            foreach (string[] str in cellParsedValues) {
                                errors.Add(new ErrorMessage(str[0],MessageType.Text));
                            }
                        }
                        break;
                    // Сведения о подтверждении
                    case 4:
                        if (ParseConfirmation(cellText, out tmp)) {
                            NewAppeal.confirmation = tmp;
                        } else {
                            result = false;
                            errors.Add(new ErrorMessage("Сведения о подтверждении: ", MessageType.Header, colIndex));
                            errors.Add(new ErrorMessage(tmp, MessageType.Text));
                        }
                        break;
                    // Приянтые меры
                    case 5:
                        if (ParseMeasures(cellText, out tmp)) {
                            NewAppeal.measures = tmp;
                        } else {
                            result = false;
                            errors.Add(new ErrorMessage("Приянтые меры: ", MessageType.Header, colIndex));
                            errors.Add(new ErrorMessage(tmp, MessageType.Text));
                        }
                        break;
                    // Номер и дата
                    case 6:
                        if (ParseNumberAndDate(cellText, out cellParsedValues)) {
                            // Проверка завершилась успешно - заполняем массив субъектов
                            foreach (Tuple<string, string> NumDate in cellParsedValues) {
                                NumbersAndDates.Add(NumDate);
                            }
                        } else {
                            // Проверка завершилась с ошибкой.
                            result = false;
                            errors.Add(new ErrorMessage("Рег. номер и дата: ", MessageType.Header, colIndex));
                            // Добавляем все сообщения об ошибках в errors.
                            foreach (string str in cellParsedValues) {
                                errors.Add(new ErrorMessage(str, MessageType.Text));
                            }
                        }
                        break;
                    // 7 - Уровень выборов
                    // Партия
                    case 8:
                        if (ParseParty(cellText, out tmp)) {
                            DeclarantParty = tmp;
                            //NewAppeal.multi.Add(new string[] { "tematika", tmp });
                        } else {
                            // Проверка завершилась с ошибкой.
                            result = false;
                            errors.Add(new ErrorMessage("Партия: ", MessageType.Header, colIndex));
                            // Добавляем все сообщения об ошибках в errors.
                            errors.Add(new ErrorMessage(tmp, MessageType.Text));
                        }

                        break;
                    // Тип заявителя
                    case 9:
                        if (ParseDeclarantType(cellText, out tmp)) {
                            //NewAppeal.declarant_type = tmp;
                            DeclarantType = tmp;
                        } else {
                            result = false;
                            errors.Add(new ErrorMessage("Тип заявителя: ", MessageType.Header, colIndex));
                            errors.Add(new ErrorMessage(tmp, MessageType.Text));
                        }

                        break;
                    // Тематика
                    case 10:
                        if (ParseTheme(cellText, out cellParsedValues)) {
                            int ThemeIndex = 0;
                            foreach(string str in cellParsedValues) {
                                NewAppeal.multi.Add(new string[] { "tematika", str, ThemeIndex.ToString() });
                                ThemeIndex++;
                            }
                        } else {
                            // Проверка завершилась с ошибкой.
                            result = false;
                            errors.Add(new ErrorMessage("Тематика: ", MessageType.Header, colIndex));

                            // Добавляем все сообщения об ошибках в errors.
                            foreach (string str in cellParsedValues) {
                                errors.Add(new ErrorMessage(str, MessageType.Text));
                            }
                        }
                        break;
                    // 11 - +
                    // Исполнитель
                    case 12:
                        if (ParseExecutor(cellText, out tmp)) {
                            NewAppeal.executor_id = tmp;
                        } else {
                            result = false;
                            errors.Add(new ErrorMessage("Исполнитель: ", MessageType.Header, colIndex));
                            errors.Add(new ErrorMessage(tmp, MessageType.Text));
                        }
                        break;
                }
            }

            // Проверяем заявителей
            bool NewDeclarant;
            string DeclarantID = "";
            int DeclarantIndex = 0;
            foreach (string[] fio_info in AppealDeclarants) {
                NewDeclarant = true;
                Declarant d = new Declarant(DeclarantType, DeclarantParty, fio_info[1]);
                d.SetFIO(fio_info[0]);
                // Ищем в справочнике.
                foreach (Declarant dd in Declarants) {
                    if (d.Equals(dd)) {
                        NewDeclarant = false;
                        DeclarantID = dd.GetID();
                        break;
                    }
                }
                if (NewDeclarant) {
                    // Добавляем в справочник заявителя с фиктивным ID.
                    DeclarantID = "fake-" + this.DeclarantFakeID++;
                    if (d.SetID(DeclarantID)) {
                        Declarants.Add(d);
                    }
                }
                // Проверяем, что такого заявителя ещё нет в данной заявке.
                NewDeclarant = true;
                foreach (string[] str in NewAppeal.multi) {
                    if (str[0] == "declarant" && str[1] == DeclarantID) {
                        NewDeclarant = false;
                        break;
                    }
                }

                if (NewDeclarant) {
                    // Добавляем заявителя к обращению.
                    NewAppeal.multi.Add(new string[] { "declarant", DeclarantID, DeclarantIndex.ToString() });
                    DeclarantIndex++;
                }
            }
            // Добавляем субъекты
            int SubjCodeIndex = 0;
            foreach (string sc in Subjects) {
                NewAppeal.multi.Add(new string[] { "ik_subjcode", sc, SubjCodeIndex.ToString() });
                SubjCodeIndex++;
            }

            // Создаём "простые" обращения
            foreach (Tuple<string, string> NumDate in NumbersAndDates) {
                string ParentID = null;
                if(Subjects.Count > 1) {
                    // Указано несколько субъектов - создаём родительской обращение
                    ParentID = this.AppealFakeID.ToString();
                    this.AppealFakeID++;
                    ParentID = "999" + ParentID.PadLeft(5, '0');
                    NewAppeal.Prepare(ParentID, null, "0", NumDate.Item1, NumDate.Item2);
                    appeals.Add(NewAppeal);
                } else {
                    ParentID = null;
                }
                foreach (string SubjCode in Subjects) {
                    NewAppeal.Prepare(null, ParentID, SubjCode, NumDate.Item1, NumDate.Item2);
                    appeals.Add(NewAppeal);
                }
            }
            return result;
        }