Example #1
0
        /// <summary>
        /// Создание дерева списка копий для всех режимов сравнения
        /// </summary
        /// <param name="bw">Экземплар фонового обработчика класса BackgroundWorker</param>
        /// <param name="e">Экземпляр класса DoWorkEventArgs</param>
        /// <param name="ht">Заполненная хеш-таблица списками книг</param>
        /// <returns>Признак непрерывности обработки файлов</returns>
        public bool makeTreeOfBookCopies(BackgroundWorker bw, DoWorkEventArgs e,
                                         Label StatusLabel, ProgressBar ProgressBar, ListView listViewFB2Files,
                                         ref StatusView sv, HashtableClass ht)
        {
            StatusLabel.Text   += "Создание списка (псевдодерево) одинаковых fb2-файлов...\r";
            ProgressBar.Maximum = ht.Values.Count;
            ProgressBar.Value   = 0;
            // сортировка ключей (групп)
            List <string> keyList = makeSortedKeysForGroups(ht);
            int           i       = 0;

            foreach (string key in keyList)
            {
                ++sv.Group; // число групп одинаковых книг
                            // формирование представления Групп с их книгами
                makeBookCopiesView((FB2FilesDataInGroup)ht[key], listViewFB2Files, ref sv);
                bw.ReportProgress(++i);

                if (bw.CancellationPending)
                {
                    e.Cancel = true;
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Заполнение хеш таблицы данными о fb2-книгах в контексте Авторов
        /// </summary>
        /// <param name="fb2">объект класса FictionBook</param>
        /// <param name="ZipPath">путь к zip-архиву. Если книга - не запакована в zip, то ZipPath = null</param>
        /// <param name="SrcPath">путь к fb2-файлу</param>
        /// <param name="Encoding">кодировка текщего файла в fb2</param>
        /// <param name="sAuthor">Фамилия и 1-я буква Имени текущего автора</param>
        /// <param name="htFB2ForAuthorFIO">Хеш Таблица с книгами одинаковых Авторов</param>
        private void FB2AuthorFIOSetHashTable(FictionBook fb2, string ZipPath, string SrcPath, string Encoding,
                                              string sAuthor, ref HashtableClass htFB2ForAuthorFIO)
        {
            // данные о книге
            BookData fb2BookData = new BookData(
                fb2.TIBookTitle, fb2.TIAuthors, fb2.TIGenres, fb2.TILang, fb2.DIID, fb2.DIVersion, fb2.DIAuthors, SrcPath, Encoding
                );

            if (ZipPath != null)
            {
                fb2BookData.Path = ZipPath;
            }

            if (!htFB2ForAuthorFIO.ContainsKey(sAuthor))
            {
                // этого Автора sAuthor в Группе еще нет
                FB2FilesDataInGroup fb2f = new FB2FilesDataInGroup(fb2BookData, sAuthor);
                fb2f.Group = sAuthor;
                htFB2ForAuthorFIO.Add(sAuthor, fb2f);
            }
            else
            {
                // этот Автор sAuthor в Группе уже есть
                FB2FilesDataInGroup fb2f = (FB2FilesDataInGroup)htFB2ForAuthorFIO[sAuthor];
                fb2f.Add(fb2BookData);
                //htFB2ForBT[sAuthor] = fb2f; //ИЗБЫТОЧНЫЙ КОД
            }
        }
        /// <summary>
        /// Заполнение хеш таблицы данными о fb2-книгах в контексте Авторов с одинаковой Фамилией и инициалами
        /// </summary>
        /// <param name="ZipPath">путь к zip-архиву. Если книга - не запакована в zip, то ZipPath = null</param>
        /// <param name="SrcPath">путь к fb2-файлу</param>
        /// <param name="htFB2ForAuthorFIO">Хеш Таблица с книгами одинаковых Авторов</param>
        /// <param name="WithMiddleName">Учитывать ли отчество Авторов (true) или нет (false) при поиске</param>
        private void MakeFB2AuthorFIOHashTable(string ZipPath, string SrcPath, ref HashtableClass htFB2ForAuthorFIO, bool WithMiddleName)
        {
            FictionBook fb2 = null;

            try {
                fb2 = new FictionBook(SrcPath);
            } catch (Exception ex) {
                Debug.DebugMessage(
                    SrcPath, ex, "Дубликатор.CompareForm.MakeFB2AuthorFIOHashTable(): Заполнение хеш таблицы данными о fb2-книгах в контексте Авторов с одинаковой Фамилией и инициалами."
                    );
                _nonOpenedFileList = _compComm.collectBadFB2(!string.IsNullOrEmpty(ZipPath) ? ZipPath : SrcPath);
                return;
            }

            string Encoding = fb2.getEncoding();

            if (string.IsNullOrWhiteSpace(Encoding))
            {
                Encoding = "?";
            }

            IList <Author> AuthorsList = fb2.TIAuthors;
            string         sAuthor     = "<Автор книги отсутствует>";

            if (AuthorsList != null)
            {
                foreach (Author a in AuthorsList)
                {
                    if (a.LastName != null && !string.IsNullOrEmpty(a.LastName.Value))
                    {
                        sAuthor = a.LastName.Value;
                    }
                    if (a.FirstName != null && !string.IsNullOrEmpty(a.FirstName.Value))
                    {
                        sAuthor += " " + a.FirstName.Value.Substring(0, 1);
                    }
                    if (WithMiddleName)
                    {
                        if (a.MiddleName != null && !string.IsNullOrEmpty(a.MiddleName.Value))
                        {
                            sAuthor += " " + a.MiddleName.Value.Substring(0, 1);
                        }
                    }
                    if (a.NickName != null && !string.IsNullOrWhiteSpace(a.NickName.Value))
                    {
                        sAuthor += a.NickName.Value;
                    }
                    sAuthor = sAuthor.Trim();
                    // Заполнение хеш таблицы данными о fb2-книгах в контексте Авторов
                    FB2AuthorFIOSetHashTable(fb2, ZipPath, SrcPath, Encoding, sAuthor, ref htFB2ForAuthorFIO);
                }
            }
            else
            {
                // Заполнение хеш таблицы данными о fb2-книгах в контексте Авторов
                FB2AuthorFIOSetHashTable(fb2, ZipPath, SrcPath, Encoding, sAuthor, ref htFB2ForAuthorFIO);
            }
        }
Example #4
0
        /// <summary>
        /// Заполнение хеш таблицы данными о fb2-книгах в контексте их md5
        /// </summary>
        /// <param name="ZipPath">путь к zip-архиву. Если книга - не запакована в zip, то ZipPath = null</param>
        /// <param name="SrcPath">путь к fb2-файлу;</param>
        /// <param name="htFB2ForMd5">Хеш Таблица с книгами с одинаковыми значениями Md5</param>
        private void MakeFB2Md5HashTable(string ZipPath, string SrcPath, ref HashtableClass htFB2ForMd5)
        {
            string md5 = ComputeMD5Checksum(SrcPath);

            FictionBook fb2 = null;

            try {
                fb2 = new FictionBook(SrcPath);
            } catch (Exception ex) {
                Debug.DebugMessage(
                    SrcPath, ex, "Дубликатор.CompareForm.MakeFB2Md5HashTable(): Заполнение хеш таблицы данными о fb2-книгах в контексте их md5."
                    );
                _nonOpenedFileList = _compComm.collectBadFB2(!string.IsNullOrEmpty(ZipPath) ? ZipPath : SrcPath);
                return;
            }

            string Encoding = fb2.getEncoding();

            if (string.IsNullOrWhiteSpace(Encoding))
            {
                Encoding = "?";
            }
            string ID = fb2.DIID;

            if (ID == null)
            {
                return;
            }

            if (ID.Trim().Length == 0)
            {
                ID = "Тег <id> в этих книгах \"пустой\"";
            }

            // данные о книге
            BookData fb2BookData = new BookData(
                fb2.TIBookTitle, fb2.TIAuthors, fb2.TIGenres, fb2.TILang, ID, fb2.DIVersion, fb2.DIAuthors, SrcPath, Encoding
                );

            if (ZipPath != null)
            {
                fb2BookData.Path = ZipPath;
            }

            if (!htFB2ForMd5.ContainsKey(md5))
            {
                // такой книги в числе дублей еще нет
                FB2FilesDataInGroup fb2f = new FB2FilesDataInGroup(fb2BookData, md5);
                htFB2ForMd5.Add(md5, fb2f);
            }
            else
            {
                // такая книга в числе дублей уже есть
                FB2FilesDataInGroup fb2f = (FB2FilesDataInGroup)htFB2ForMd5[md5];
                fb2f.Add(fb2BookData);
                //htFB2ForMd5[md5] = fb2f; //ИЗБЫТОЧНЫЙ КОД
            }
        }
        /// <summary>
        /// Заполнение хеш таблицы данными о fb2-книгах в контексте их Названия
        /// </summary>
        /// <param name="ZipPath">путь к zip-архиву. Если книга - не запакована в zip, то ZipPath = null</param>
        /// <param name="SrcPath">путь к fb2-файлу;</param>
        /// <param name="htFB2ForBT">Хеш Таблица с книгами с одинаковыми Названиями</param>
        private void MakeFB2BTHashTable(string ZipPath, string SrcPath, HashtableClass htFB2ForBT)
        {
            FictionBook fb2 = null;

            try {
                fb2 = new FictionBook(SrcPath);
            }
            catch (Exception ex) {
                Debug.DebugMessage(
                    SrcPath, ex, "Дубликатор.CompareForm.MakeFB2BTHashTable(): Заполнение хеш таблицы данными о fb2-книгах в контексте их Названия."
                    );
                _nonOpenedFileList = _compComm.collectBadFB2(!string.IsNullOrEmpty(ZipPath) ? ZipPath : SrcPath);
                return;
            }

            string Encoding = fb2.getEncoding();

            if (string.IsNullOrWhiteSpace(Encoding))
            {
                Encoding = "?";
            }

            BookTitle bookTitle = fb2.TIBookTitle;
            string    BT        = "<Название книги отсутствует>";

            if (bookTitle != null && !string.IsNullOrWhiteSpace(bookTitle.Value))
            {
                BT = bookTitle.Value.Trim();
            }

            // данные о книге
            BookData fb2BookData = new BookData(
                bookTitle, fb2.TIAuthors, fb2.TIGenres, fb2.TILang, fb2.DIID, fb2.DIVersion, fb2.DIAuthors, SrcPath, Encoding
                );

            if (ZipPath != null)
            {
                fb2BookData.Path = ZipPath;
            }

            if (!htFB2ForBT.ContainsKey(BT))
            {
                // такой книги в числе дублей еще нет
                FB2FilesDataInGroup fb2f = new FB2FilesDataInGroup(fb2BookData, BT);
                htFB2ForBT.Add(BT, fb2f);
            }
            else
            {
                // такая книга в числе дублей уже есть
                FB2FilesDataInGroup fb2f = (FB2FilesDataInGroup)htFB2ForBT[BT];
                fb2f.Add(fb2BookData);
                //htFB2ForBT[sBT] = fb2f; //ИЗБЫТОЧНЫЙ КОД
            }
        }
Example #6
0
        /// <summary>
        /// Сортировка ключей (групп)
        /// </summary>
        /// <param name="htBookGroups">Хэш-таблица Групп</param>
        /// <returns>Список List объектов типа string значений отсортированных ключей хэш-таблицы</returns>
        public List <string> makeSortedKeysForGroups(HashtableClass htBookGroups)
        {
            List <string> keyList = new List <string>();

            foreach (string key in htBookGroups.Keys)
            {
                keyList.Add(key);
            }
            keyList.Sort();
            return(keyList);
        }
Example #7
0
        /// <summary>
        /// Заполнение хеш таблицы данными о fb2-книгах в контексте их ID
        /// </summary>
        /// <param name="ZipPath">путь к zip-архиву. Если книга - не запакована в zip, то ZipPath = null</param>
        /// <param name="SrcPath">путь к fb2-файлу;</param>
        /// <param name="htFB2ForID">Хеш Таблица с книгами с одинаковыми ID</param>
        private void MakeFB2IDHashTable(string ZipPath, string SrcPath, ref HashtableClass htFB2ForID)
        {
            FictionBook fb2 = null;

            try {
                fb2 = new FictionBook(SrcPath);
            }
            catch (Exception ex) {
                Debug.DebugMessage(
                    SrcPath, ex, "Дубликатор.CompareForm.MakeFB2IDHashTable(): Заполнение хеш таблицы данными о fb2-книгах в контексте их ID."
                    );
                _nonOpenedFileList = _compComm.collectBadFB2(!string.IsNullOrEmpty(ZipPath) ? ZipPath : SrcPath);
                return;
            }

            string Encoding = fb2.getEncoding();

            if (string.IsNullOrWhiteSpace(Encoding))
            {
                Encoding = "?";
            }
            string ID = fb2.DIID;

            if (string.IsNullOrEmpty(ID) || string.IsNullOrWhiteSpace(ID))
            {
                ID = _compComm.NoOrEmptyBookIDString;
            }

            // данные о книге
            BookData fb2BookData = new BookData(
                fb2.TIBookTitle, fb2.TIAuthors, fb2.TIGenres, fb2.TILang, ID, fb2.DIVersion, fb2.DIAuthors, SrcPath, Encoding
                );

            if (ZipPath != null)
            {
                fb2BookData.Path = ZipPath;
            }

            if (!htFB2ForID.ContainsKey(ID))
            {
                // такой книги в числе дублей еще нет
                FB2FilesDataInGroup fb2f = new FB2FilesDataInGroup(fb2BookData, ID);
                htFB2ForID.Add(ID, fb2f);
            }
            else
            {
                // такая книга в числе дублей уже есть
                FB2FilesDataInGroup fb2f = (FB2FilesDataInGroup)htFB2ForID[ID];
                fb2f.Add(fb2BookData);
                //htFB2ForID[sID] = fb2f; //ИЗБЫТОЧНЫЙ КОД
            }
        }
Example #8
0
        /// <summary>
        /// Удаление элементов таблицы, value (списки) которых состоят из 1-го элемента (это не копии)
        /// </summary>
        /// <param name="ht">Хеш Таблица, в которой производится удаление элементов по заданному алгоритму</param>
        public void removeNotCopiesEntryInHashTable(HashtableClass ht)
        {
            List <DictionaryEntry> notCopies = new List <DictionaryEntry>();

            foreach (DictionaryEntry entry in ht)
            {
                FB2FilesDataInGroup fb2f = (FB2FilesDataInGroup)entry.Value;
                if (fb2f.Count == 1)
                {
                    notCopies.Add(entry);
                }
            }
            foreach (var ent in notCopies)
            {
                ht.Remove(ent.Key);
            }
        }
Example #9
0
        /// <summary>
        /// Хэширование по одинаковым Авторам в пределах сгенерированных групп книг по одинаковым названиям
        /// </summary
        /// <param name="bw">Экземплар фонового обработчика класса BackgroundWorker</param>
        /// <param name="e">Экземпляр класса DoWorkEventArgs</param>
        /// <param name="htFB2ForBT">Заполненная хеш-таблица списками книг по критерию одинакового Названия книг</param>
        /// <param name="htBookTitleAuthors">Заполняемая хеш-таблица списками книг по критерию ( Название книги (Авторы) )</param>
        /// <param name="WithMiddleName">Учитывать ли отчество Авторов (true) или нет (false) при поиске</param>
        /// <returns>Признак непрерывности обработки файлов</returns>
        public bool FilesHashForAuthorsParser(BackgroundWorker bw, DoWorkEventArgs e,
                                              Label StatusLabel, ProgressBar ProgressBar,
                                              HashtableClass htFB2ForBT, HashtableClass htBookTitleAuthors,
                                              bool WithMiddleName)
        {
            StatusLabel.Text   += "Хеширование по Авторам книг...\r";
            ProgressBar.Maximum = htFB2ForBT.Values.Count;
            ProgressBar.Value   = 0;
            // генерация списка ключей хеш-таблицы (для удаления обработанного элемента таблицы)
            List <string> keyList = _compComm.makeSortedKeysForGroups(htFB2ForBT);
            // группировка книг по одинаковым Авторам в пределах сгенерированных Групп книг по одинаковым Названиям
            int i = 0;

            foreach (string key in keyList)
            {
                // разбивка на группы для одинакового Названия по Авторам
                Hashtable htGroupAuthors = FindDupForAuthors((FB2FilesDataInGroup)htFB2ForBT[key], WithMiddleName);
                foreach (FB2FilesDataInGroup fb2List in htGroupAuthors.Values)
                {
                    if (!htBookTitleAuthors.ContainsKey(fb2List.Group))
                    {
                        htBookTitleAuthors.Add(fb2List.Group, fb2List);
                    }
                    else
                    {
                        FB2FilesDataInGroup fb2ListInGroup = (FB2FilesDataInGroup)htBookTitleAuthors[fb2List.Group];
                        fb2ListInGroup.AddRange(fb2List);
                    }
                }

                // удаление обработанной группы книг, сгруппированных по одинаковому названию
                htFB2ForBT.Remove(key);
                bw.ReportProgress(++i);

                if (bw.CancellationPending)
                {
                    e.Cancel = true;
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Хэширование fb2-файлов по ID книги в пределах одинаковых Авторов Книги
        /// 10. Автор(ы), Одинаковый Id Книги
        /// </summary
        /// <param name="bw">Экземплар фонового обработчика класса BackgroundWorker</param>
        /// <param name="e">Экземпляр класса DoWorkEventArgs</param>
        /// <param name="htAuthors">Хэш Таблица с книгами по критерию одинаковости их Авторов</param>
        /// <param name="htWorkingBook">Хэш Таблица с книгами по критерию одинаковости их ID</param>
        /// <returns>Признак непрерывности обработки файлов</returns>
        public bool FilesHashForAuthorsBookIDParser(ref BackgroundWorker bw, ref DoWorkEventArgs e,
                                                    Label StatusLabel, ProgressBar ProgressBar,
                                                    ref HashtableClass htBookTitleAuthors, ref HashtableClass htWorkingBook)
        {
            StatusLabel.Text   += "Хэширование по ID книги в пределах одинаковых Авторов...\r";
            ProgressBar.Maximum = htBookTitleAuthors.Count;
            ProgressBar.Value   = 0;
            // генерация списка ключей хеш-таблицы (для удаления обработанного элемента таблицы)
            List <string> keyList = _compComm.makeSortedKeysForGroups(htBookTitleAuthors);
            // группировка книг по одинаковым Id Книги в пределах сгенерированных Групп книг одинаковых Авторов
            int i = 0;

            foreach (string key in keyList)
            {
                // разбивка на группы для одинакового Id книги по Названию и по Авторам
                Hashtable AuthorsTitleBookID = FindDupForAuthorsID((FB2FilesDataInGroup)htBookTitleAuthors[key]);
                foreach (FB2FilesDataInGroup fb2List in AuthorsTitleBookID.Values)
                {
                    if (!htBookTitleAuthors.ContainsKey(fb2List.Group))
                    {
                        htWorkingBook.Add(fb2List.Group, fb2List);
                    }
                    else
                    {
                        FB2FilesDataInGroup fb2ListInGroup = (FB2FilesDataInGroup)htBookTitleAuthors[fb2List.Group];
                        fb2ListInGroup.AddRange(fb2List);
                    }
                }
                // удаление обработанной группы книг, сгруппированных по одинаковому Автору
                htBookTitleAuthors.Remove(key);
                bw.ReportProgress(++i);

                if (bw.CancellationPending)
                {
                    e.Cancel = true;
                    return(false);
                }
            }
            return(true);
        }
Example #11
0
        /// <summary>
        /// Хеширование файлов в контексте Id книг:
        /// Одинаковый Id Книги (копии и/или разные версии правки одной и той же книги)
        /// </summary>
        /// <param name="FilesList">Список файлов для сканированияl</param>
        /// <param name="htFB2ForID">Хеш Таблица с книгами с одинаковыми ID</param>
        /// <returns>Признак непрерывности обработки файлов</returns>
        public bool FilesHashForIDParser(BackgroundWorker bw, DoWorkEventArgs e,
                                         Label StatusLabel, ProgressBar ProgressBar, string TempDir,
                                         List <string> FilesList, HashtableClass htFB2ForID)
        {
            StatusLabel.Text   += "Хэширование по Id книг...\r";
            ProgressBar.Maximum = FilesList.Count;
            ProgressBar.Value   = 0;

            List <string> FinishedFilesList = new List <string>();

            for (int i = 0; i != FilesList.Count; ++i)
            {
                if (FilesWorker.isFB2File(FilesList[i]))
                {
                    // заполнение хеш таблицы данными о fb2-книгах в контексте их ID
                    MakeFB2IDHashTable(null, FilesList[i], ref htFB2ForID);
                    // обработанные файлы
                    FinishedFilesList.Add(FilesList[i]);
                }
                else
                {
                    if (FilesWorker.isFB2Archive(FilesList[i]))
                    {
                        try {
                            if (_sharpZipLib.UnZipFB2Files(FilesList[i], TempDir) != -1)
                            {
                                string[] files = Directory.GetFiles(TempDir);
                                if (files.Length > 0)
                                {
                                    if (FilesWorker.isFB2File(files[0]))
                                    {
                                        // заполнение хеш таблицы данными о fb2-книгах в контексте их ID
                                        MakeFB2IDHashTable(FilesList[i], files[0], ref htFB2ForID);
                                        // обработанные файлы
                                        FinishedFilesList.Add(FilesList[i]);
                                    }
                                }
                            }
                        }
                        catch (Exception ex) {
                            Debug.DebugMessage(
                                FilesList[i], ex, "Дубликатор.CompareForm.FilesHashForIDParser(): Хеширование файлов в контексте Id книг."
                                );
                        }
                        FilesWorker.RemoveDir(TempDir);
                    }
                }
                bw.ReportProgress(i); // отобразим данные в контролах

                if (bw.CancellationPending)
                {
                    // удаление из списка всех файлов обработанных книг
                    WorksWithBooks.removeFinishedFilesInFilesList(ref FilesList, ref FinishedFilesList);
                    e.Cancel = true;
                    return(false);
                }
            }
            // удаление элементов таблицы, value (списки) которых состоят из 1-го элемента (это не копии)
            _compComm.removeNotCopiesEntryInHashTable(htFB2ForID);
            // удаление из списка всех файлов обработанных книг
            WorksWithBooks.removeFinishedFilesInFilesList(ref FilesList, ref FinishedFilesList);

            return(true);
        }
Example #12
0
        // =============================================================================================
        //                          СОХРАНЕНИЕ РЕЗУЛЬТАТА ПОИСКА КОПИЙ В XML-ФАЙЛЫ
        // =============================================================================================
        #region Сохранение результата поиска копий в xml-файлы
        /// <summary>
        /// Сохранение результата сразу в xml-файлы без построения визуального списка
        /// </summary>
        /// <param name="bw">Ссылка на объект класса BackgroundWorker</param>
        /// <param name="e">Ссылка на объект класса DoWorkEventArgs</param>
        /// <param name="GroupCountForList">Число Групп в Списке Групп</param>
        /// <param name="CompareMode">Вид сравнения при поиске копий</param>
        /// <param name="CompareModeName">Название вида сравнения при поиске копий</param>
        /// <param name="ht">Хэш-таблица данных на Группы (копии fb2 книг по Группам)</param>
        /// <returns>Признак непрерывности обработки файлов</returns>
        public bool saveCopiesListToXml(BackgroundWorker bw, DoWorkEventArgs e, int GroupCountForList,
                                        int CompareMode, string CompareModeName, Label StatusLabel, ProgressBar ProgressBar,
                                        ref StatusView sv, string SourceDir, bool ScanSubDirs,
                                        int GroupCountForListIndex, bool IsSaveGroupToXMLWithoutTree, HashtableClass ht)

        {
            // блокировка отмены сохранения результата в файлы
            StatusLabel.Text   += "Сохранение результата поиска в xml-файлы (папка '_Copies') без построения дерева копий...\r";
            ProgressBar.Maximum = ht.Values.Count;
            ProgressBar.Value   = 0;

            const string ToDirName = "_Copies";

            if (!Directory.Exists(ToDirName))
            {
                Directory.CreateDirectory(ToDirName);
            }

            // "сквозной" счетчик числа групп для каждого создаваемого xml файла копий
            int ThroughGroupCounterForXML = 0;
            // счетчик (в границых CompareModeName) числа групп для каждого создаваемого xml файла копий
            int GroupCounterForXML = 0;
            // номер файла - для формирования имени создаваемого xml файла копий
            int XmlFileNumber = 0;

            // копии fb2 книг по группам
            if (ht.Values.Count > 0)
            {
                XDocument doc = createXMLStructure(CompareMode, CompareModeName, SourceDir, ScanSubDirs,
                                                   GroupCountForListIndex, IsSaveGroupToXMLWithoutTree);

                int  BookInGroups       = 0; // число книг (books) в Группах (Groups)
                int  GroupCountInGroups = 0; // число Групп (Group count) в Группах (Groups)
                int  i   = 0;                // прогресс
                bool one = false;
                // сортировка ключей (групп)
                List <string> keyList = makeSortedKeysForGroups(ht);
                foreach (string key in keyList)
                {
                    ++sv.Group; // число групп одинаковых книг
                    // формирование представления Групп с их книгами
                    addAllBookInGroup(bw, e, doc, (FB2FilesDataInGroup)ht[key], ref BookInGroups, ref GroupCountInGroups, ref sv);

                    ++GroupCounterForXML;
                    ++ThroughGroupCounterForXML;
                    doc.Root.Element("SelectedItem").SetValue("0");
                    if (GroupCountForList <= ht.Values.Count)
                    {
                        if (GroupCounterForXML >= GroupCountForList)
                        {
                            string FileNumber = StringProcessing.makeNNNStringOfNumber(++XmlFileNumber) + ".dup_lbc";
                            setDataForNode(doc, GroupCountInGroups, BookInGroups);
                            doc.Save(Path.Combine(ToDirName, FileNumber));
                            StatusLabel.Text += "Файл: '_Copies\\" + FileNumber + "' создан...\r";
                            doc.Root.Element("Groups").Elements().Remove();
                            GroupCountInGroups = 0;
                            GroupCounterForXML = 0;
                            BookInGroups       = 0;
                        }
                        else
                        {
                            // последний диаппазон Групп
                            if (ThroughGroupCounterForXML == ht.Values.Count)
                            {
                                string FileNumber = StringProcessing.makeNNNStringOfNumber(++XmlFileNumber) + ".dup_lbc";
                                setDataForNode(doc, GroupCountInGroups, BookInGroups);
                                doc.Save(Path.Combine(ToDirName, FileNumber));
                                StatusLabel.Text += "Файл: '_Copies\\" + FileNumber + "' создан...\r";
                            }
                        }
                    }
                    else
                    {
                        setDataForNode(doc, GroupCountInGroups, BookInGroups);
                        one = true;
                    }
                    bw.ReportProgress(i++);

                    if (bw.CancellationPending)
                    {
                        e.Cancel = true;
                        return(false);
                    }
                } // по всем Группам
                if (one)
                {
                    StatusLabel.Text += @"Файл: '_Copies\001.dup_lbc' ...\r";
                    doc.Save(Path.Combine(ToDirName, "001.dup_lbc"));
                }
            }
            return(true);
        }