Киби.ru

Живой сайт об актуальных проектах

User Tools

Site Tools


science_and_life:isxodniki

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
Last revisionBoth sides next revision
science_and_life:isxodniki [2008/12/11 13:01] – внешнее изменение 127.0.0.1science_and_life:isxodniki [2017/03/13 17:14] 84.180.171.72
Line 1: Line 1:
-====== исходники ====== +Парник «Подснежник» предназначен для укрытия и защиты рассады от неблагоприятных условий, сильных ветров и ночных заморозков до -5 градусов, а так же обеспечит защиту от насекомых, вредителей и птиц.  
- +Каркас парника представляет из себя набор пластиковых дуг диаметром 20 мм. Все дуги вшиты в укрывной материал "СУФ-42", что обеспечивает надежное крепление материала к дугам и удобство использования парника.  
-<code delphi> +Самовывоз из более 100 пунктов выдачи и доставка по всей стране. Артикул 146853744
-{excel2djvu - конвертор xls файлов с содержанием журнала в HTML формат для создания DJVU архива. +
- +
-Copyright (C) 2006 by Alexander Sorkin aka Kibi +
- +
-This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. +
- +
-This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +
- +
-You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. +
- +
-                              11.11.2006 +
-                              Alexander Sorkin aka Kibi +
-                              kibizoid@gmail.com +
-                              http://kibi.ru +
- +
-****************************************************************************************} +
- +
-// Исходный код основан на примере работы с Excel человека по имени Злой и опубликованного  +
-//для свободного использования на сайте Королевство Дельфи. +
- +
-unit Unit1; +
- +
-interface +
- +
-uses +
-  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, +
-  ComObj, ActiveX, shellapi, FileCtrl, +
-{$IFDEF VER120} +
-  OleCtrls, // Почем-то так написано у меня - по-моему для D5 это лишнее. +
-            // Это склероз или диабет, не помню! +
-{$ENDIF} +
-  Excel8TLB, StdCtrls, ExtCtrls, ComCtrls, SHDocVw; +
- +
- +
-type +
-  TForm1 = class(TForm) +
-    StatusBar1: TStatusBar; +
-    OpenDialog1: TOpenDialog; +
-    PageControl2: TPageControl; +
-    TabSheet1: TTabSheet; +
-    Panel1: TPanel; +
-    html_preview: TWebBrowser; +
-    TabSheet2: TTabSheet; +
-    tree_preview: TTreeView; +
-    SaveDialog1: TSaveDialog; +
-    Panel2: TPanel; +
-    PageControl1: TPageControl; +
-    simple_tab: TTabSheet; +
-    grp_simple_volume: TGroupBox; +
-    btn_simple_volume: TButton; +
-    complex_tab: TTabSheet; +
-    btn_Initiate_Data: TButton; +
-    chk_debug_mode: TCheckBox; +
-    btn_Collect_Data: TButton; +
-    GroupBox1: TGroupBox; +
-    Button1: TButton; +
-    Button2: TButton; +
-    ErrorLog: TListView; +
-    TabSheet3: TTabSheet; +
-    single_volume_tree: TTreeView; +
-    local_progress: TProgressBar; +
-    global_progress: TProgressBar; +
-    edt_volumes: TComboBox; +
-    btn_Create_Global_Content: TButton; +
-    Label1: TLabel; +
-    Bevel1: TBevel; +
-    chk_make_bookmarks: TCheckBox; +
-    chk_make_authors: TCheckBox; +
-    chk_make_rubriks: TCheckBox; +
-    chk_make_content: TCheckBox; +
-    procedure FormDestroy(Sender: TObject); +
-    procedure Initiate_Data(Sender: TObject); +
-    procedure Local_Content_Create(Sender: TObject); +
-    procedure FormCreate(Sender: TObject); +
-    procedure Global_Content_Create(Sender: TObject); +
-    procedure btn_simple_volumeClick(Sender: TObject); +
-    procedure btn_Collect_DataClick(Sender: TObject); +
-    procedure Button1Click(Sender: TObject); +
-    procedure Button2Click(Sender: TObject); +
-  private +
-    { Private declarations } +
-    FIXLSApp: Excel8TLB._Application; +
-    FIWorkbook,FIWorkbook2: Excel8TLB._Workbook; +
-    AllContent, fileDJVU_Bookmarks, file_Global_Volumes_Content, file_All_Authors_Index, file_All_Rubriks_Index:TStream; +
-    // Все ОНО тут! +
-    // Оформлено отдельными процедурами из противности. +
-    // Впрочем, отсюда проще взять для последующей утилизации. +
-    procedure CreateExcel (NewInstance: boolean); +
-    procedure ShowExcel; +
-    //procedure HideExcel; +
-    procedure ReleaseExcel; +
-    procedure ShowTree; +
-    procedure MakeContent; +
-    procedure ExportHTML(all:boolean); +
-    procedure CreateBook; +
-    procedure CreateTOC; +
-    procedure Load_complex_rubriks; +
-    procedure Load_rubriks_groups; +
-    procedure CreateBatches; +
-    function compare_rubriks(rubriki, test_string:string; var other_rubriks:string; var pos_found:integer):boolean; +
-    procedure sort_articles; +
-    procedure ShowMessageInLog(year, volume, page, msg:string); +
-  public +
-    { Public declarations } +
-    // Свойство, спросите Вы? Так это же ООП+
-    property IXLSApp: Excel8TLB._Application read FIXLSApp; +
-    property IWorkbook: Excel8TLB._Workbook read FIWorkbook; +
-    property IWorkbook2: Excel8TLB._Workbook read FIWorkbook2; +
-  end; +
-Const Make_Single = false; +
-      Make_Global = true; +
-      min_year = 1990; +
-      max_year = 2005; +
-      max_toc_triplet = 7; +
-      max_complex_rubriks = 5; +
- +
-Type ContentElement = class +
-     public +
-        year_vol_str : string; +
-        str_vol : string; +
-        rubrika : string; +
-        author : string; +
-        title : string; +
-        page : string; +
-        link : string; +
-        volume : string; +
-        year : string; +
-        function ColoredResult:string; +
-        constructor Create(rubrika, author, title, page, link, volume, year: string); +
-     end; +
- +
-Type TMyContent = record +
-        rubrika : string; +
-        author : string; +
-        title : string; +
-        page : string; +
-        link : string; +
-        volume : string; +
-        year : string; +
-        used_as_slave: boolean; +
-        used_as_article: array [1..max_complex_rubriks] of boolean; +
-     end; +
-     index_element = record +
-        name : string; +
-        index : integer; +
-     end; +
-     rubr_index_element = record +
-        name : string; +
-        index : integer; +
-        other_rubrik : string; +
-     end; +
-     authors_element = record +
-        name:string; +
-        index: integer; +
-        count: integer; +
-        triplet: string; +
-        surname: string; +
-     end; +
-     rubriks_element = record +
-        name:string; +
-        index: integer; +
-        count: integer; +
-        sinonim: string; +
-        common: integer; +
-        group_number: integer; +
-        number : integer; +
-     end; +
-     triplets_element = record +
-        triplet:string; +
-        index: integer; +
-        count: integer; +
-        letter: string; +
-        toc_triplets_index: integer;// связь с массивом toc_triplets - к какому диапазону принадлежит. +
-     end; +
-     sinonims_element = record +
-        rubrika: string; +
-        sinonim: string; +
-     end; +
-     rubriks_type_element = record +
-        rubrika:string; +
-        is_table_rubrik:integer; // 1 - если рубрика табличная, 0 - списочная +
-     end; +
-     rubriks_group_element = record +
-        group: string;          // название группы +
-        rubriks: TStringList;   // перечень рубрик в группе +
-     end; +
-  type TRubr_Info = class(TObject) +
-       public +
-          info : rubriks_element; +
-          constructor Create(init_info: rubriks_element); +
-       end; +
-var +
-  Form1: TForm1; +
-  VolumeContent: array of TMyContent; +
-  Rubriki:TStringList; +
-  Rubriks_groups:array of rubriks_group_element; +
-  prog_path: string; +
-  simple_mode: boolean; +
-implementation +
- +
-{$R *.DFM} +
-constructor TRubr_Info.Create(init_info: rubriks_element); +
-begin +
-   self.info := init_info; +
-end; +
-function ContentElement.ColoredResult:string; +
-begin +
-// +
-end; +
- +
-constructor ContentElement.Create(rubrika, author, title, page, link, volume, year: string); +
-begin +
-        self.rubrika := rubrika; +
-        self.author := author; +
-        self.title := title; +
-        self.page := page; +
-        self.link := link; +
-        self.volume := volume; +
-        self.year := year; +
-        if ((year = '1992') and (volume = '05')) then begin +
-           year_vol_str := '1992_05_06'; +
-           str_vol := '05-06'; +
-        end else begin +
-           year_vol_str := format('%s_%s',[self.year, self.volume]); +
-           str_vol := self.volume; +
-        end; +
-end; +
- +
- +
-procedure TForm1.CreateExcel(NewInstance: boolean); +
-var IU: IUnknown; +
-    isCreate: boolean; +
-begin +
-  // Tricks: +
-  //        в случает вызова Excel-а, как сервера автоматизации: +
-  //          - все автозагружаемые книги не загружаются (и слава богу!); +
-  //          - создается процесс, но Excel в случае создания нового процесса, +
-  //            естественно, невидим. +
-  if not Assigned(IXLSApp) then begin // а зачем его создавать, если уже есть? +
-    isCreate := NewInstance or +
-      (not SUCCEEDED( GetActiveObject(Excel8TLB.CLASS_Application_, nil, IU) ) ); +
-    if isCreate then +
-      FIXLSApp := CreateComObject(Excel8TLB.CLASS_Application_) as Excel8TLB._Application +
-    else +
-      FIXLSApp := IU as Excel8TLB._Application; +
-  end; +
-end; +
-procedure TForm1.ShowMessageInLog(year, volume, page, msg:string); +
-var newItem:TListItem; +
-begin +
-   newItem := ErrorLog.Items.Add; +
-   newItem.Caption := (inttostr(ErrorLog.Items.Count)); +
-   newItem.SubItems.Add (format('%s, №%s',[year,volume])); +
-   newItem.SubItems.Add (page); +
-   newItem.SubItems.Add (msg); +
-end; +
-procedure TForm1.ShowExcel; +
-begin +
-  // Tricks: +
-  //        Приведение к TOLEEnum сделано только для того, чтобы не видеть +
-  //        warning-ов типа "Constant expression violates subrange bounds" и т.п. +
-  // +
-  //        lcid - что такое? Что-то насчет локализации, уже не помню. Надо уточнить! +
-  //        Но вы всегда можете спокойно передать 0 вместо lcid. +
-  // +
-  //        Так насчет показать Excel... Показать просто. Главное корректно показать. +
-  //        Вроде бы, достаточно просто Visible := true. Черта с два! +
-  //        Комментируем строки с условием на минимизацию и ScreenUpdating. +
-  //        Делаем CreateExcel, ShowExcel, минимизируем его (мышью - чем еще?), +
-  //        возвращаемся в приложение и делаем еще раз ShowExcel! И что? +
-  //        Насколько я понял его поведение, Visible в таком случае сфокусирует туда, +
-  //        но окно-то не раскроется. Поэтому проверка на xlMinimize. +
-  // +
-  //        Что здесь делает ScreenUpdating? Многие спросят. Делаем: +
-  //        - раскомментим строки с условием на минимайз; +
-  //        - CreateExcel; +
-  //        - ShowExcel; +
-  //        - закрываем (мышью) Excel (можно через Файл\Закрыть); +
-  //        - смотрим в процессы - Excel не выгрузился (так оно и понятно - интерфейс не освободили); +
-  //        - Главное! Делаем ShowExcel - имеем право. +
-  //        При последнем действии Excel у меня активизируется, но не перерисовывается. +
-  //        Эту проблему последняя строка и решает. Этот баг я называю "прозрачный Excel"+
-  //        А мы тут полупрозрачные окна рисуем. Наверняка, MS скоро в WinAPI это положит! +
-  if Assigned(IXLSApp) then begin +
-    IXLSApp.Visible[0] := true; +
-    //IXLSApp.Visible[0] := false; +
-    if IXLSApp.WindowState[0] = TOLEEnum(Excel8TLB.xlMinimized) then +
-      IXLSApp.WindowState[0] := TOLEEnum(Excel8TLB.xlNormal); +
-    IXLSApp.ScreenUpdating[0] := true; +
-    IXLSApp.DisplayAlerts[0] := true; +
-  end; +
-end; +
- +
-(*procedure TForm1.HideExcel; +
-begin +
-  if Assigned(IXLSApp) then begin +
-    IXLSApp.Visible[0] := false; +
-  end; +
-end;*) +
- +
-procedure TForm1.ReleaseExcel; +
-begin +
-  // Tricks: +
-  //        Верни пользователю его Excel!!! +
-  //        Считаем, что если остается хотя бы одна открытая книга, значит пользователь ее хотел +
-  //        бы потом увидеть. А то ж можно сделать Excel-у Hide и Release. И что? +
-  //        Если там осталась книга, которая правилась - процесс останется, но в списке приложений +
-  //        его не увидишь - только в списке процессов. +
-  //        Так решим эту проблему следующим образом: +
-  if Assigned(IXLSApp) then begin +
-    // если есть книга и мы невидимы +
-    if (IXLSApp.Workbooks.Count > 0) and (not IXLSApp.Visible[0]) then begin +
-      // положим аккуратненько (правильно написал это слово?) его вниз, +
-      IXLSApp.WindowState[0] := TOLEEnum(xlMinimized); +
-      // а потом покажем, +
-      IXLSApp.Visible[0] := true; +
-      // ну, и после вернем фокус форме и приложению, а то после Visible - у эксела SetFocus +
-      // происходит. +
-      // Собственно говоря, набор свойств Visible, ScreenUpdating, Activate (еще остановимся) и +
-      // WindowState меня периодически пугает своей неоднозначностью. +
-      // Дельфийная альтернатива Visible, SetFocus, WindowState работает четко. +
-      if not(csDestroying in ComponentState) then Self.SetFocus; // а это объяснять необходимо? +
-      // Объясню вопросом. Какой SetFocus, если приложение (форма) закрывается? +
-      Application.BringToFront; +
-    end; +
-  end; +
-  // Tricks: +
-  // Главное мое правило: поюзал интерфейс - сам его и освободи. +
-  // Эта привычка выработана давно. Освобождаю даже локально объявленные переменные-интерфейсы. +
-  // То есть блок finally всегда присутствует с такими присваиваниями. +
-  // Совет начинающим от начинающего: если чего-то не выгружается - проверь, освобождаются ли +
-  // все использованные интерфейсы, особенно те, которые в полях классов и глобальных переменных. +
-  // Кстати, последнее - дурной стиль. +
-  // Максималист, я знаю. По мне, дурной стиль всякая лишняя глобальная переменная, будь то +
-  // экземпляр класса, целое число или интерфейс. Я даже сношу описания типа var Form1: TForm1. +
-  // Для использования Excel у меня существует несколько классов. +
-  // Это классы XL Report - низкоуровневый набор компонентов, обеспечивающий +
-  // создание одного отчета по нескольким TDataSet. А вся подсистема отчетов описана еще одним +
-  // классом, который умеет создать эти самые наборы данных под конкретный отчет, хранить +
-  // описания этих запросов (Это запросы. Параметризованные, конечно). К тому же, все это +
-  // завязано на COM и ActiveX Scripting. Это не оттого, что я такой крутой. Просто пора +
-  // давно понять, что начинать строить настоящие приложения надо с создания интерфейса +
-  // МоеПриложение.Application. Это не мода, это, по-моему, уже необходимость. +
-  FIXLSApp := nil; +
-end; +
- +
-procedure TForm1.FormCreate(Sender: TObject); +
-begin +
-  prog_path:=ExtractFilePath(ParamStr(0)); +
-  if not DirectoryExists(prog_path+'bookmarks/') then ForceDirectories(prog_path+'bookmarks/'); +
-  CreateExcel(false); +
-  ShowExcel; +
-  Application.BringToFront; +
-  if fileexists(prog_path+'!simple_mode.txt') then simple_mode := true else simple_mode := false; +
-  if not simple_mode then CreateBook; +
-  if simple_mode then begin +
-     Simple_tab.TabVisible:=true; +
-     complex_tab.TabVisible:=false; +
-     pagecontrol1.ActivePage:=Simple_tab; +
-  end else begin +
-     Simple_tab.TabVisible:=false; +
-     complex_tab.TabVisible:=true; +
-     pagecontrol1.ActivePage:=complex_tab; +
-  end; +
-  Rubriki:=TStringList.Create; +
-//  Rubriki.LoadFromFile(prog_path+'rubriki.txt'); +
-end; +
- +
-procedure TForm1.FormDestroy(Sender: TObject); +
-begin +
-  FIWorkbook.Close(EmptyParam, EmptyParam, EmptyParam,0); +
-  FIWorkbook:= nil; +
-  FIWorkbook2:= nil; +
-  ReleaseExcel; // святое дело +
-  Rubriki.Free; +
-end; +
- +
-procedure TForm1.CreateBook; +
-var FullFileName: string; +
-    x:integer; +
-    Value: OLEVariant; +
-begin +
-  if simple_mode then begin +
-     OpenDialog1.InitialDir:=prog_path; +
-     if OpenDialog1.Execute then begin +
-       FullFileName:=OpenDialog1.FileName; +
-     end; +
-  end else FullFileName := prog_path + 'content.xls'; +
-  if Assigned(IXLSApp) and (not Assigned(IWorkbook) ) then +
-    try +
-      try +
-        FIWorkbook := IXLSApp.Workbooks.Open(FullFileName, +
-             EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, +
-             EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, false, 0); +
-        edt_volumes.Items.Clear; +
-        edt_volumes.Sorted:=false; +
-        for x:=1 to IWorkbook.Names.Count do begin // прочесть из экселя список уже существующих именованных диапазонов +
-           Value:=IWorkbook.Names.Item(x,EmptyParam,EmptyParam).Name; +
-           edt_volumes.Items.Add(Copy(VarToStr(Value), length('vol_')+1, length(VarToStr(Value))-length('vol_'))); +
-           // префикс к номеру в списке нам не нужен - чтобы оставались чистые yyyy_mm (имя в экселе не может начинаться с цифры) +
-        end; +
-        edt_volumes.Sorted:=true; +
-        if edt_volumes.Items.Count>0 then edt_volumes.ItemIndex:=0; +
-      finally +
-        ShowExcel; +
-        Application.BringToFront; +
-      end; +
-    except +
-      raise Exception.Create('Не могу открыть книгу!'); +
-    end; +
-end; +
- +
-procedure TForm1.Initiate_Data(Sender: TObject); +
-+
-  Простановка именованных диапазонов +
-  Исходные данные - уже открытый XLS файллист "Содержание" +
-  Конечный результат - именованные диапазоны в XLS файле +
-  Происходит сброс всех именных диапазонов и сохранение обработанного файла +
- +
-  Именно тут надо сделать разбор списка авторов и построение списка "Автор - ссылки на статьи", +
-  а так же списка "Рубрика - ссылки на статьи" +
- +
-  Сам процесс разбора - поэтапный +
-     - построение неупорядоченного списка 1 автор - 1 ссылка на статью +
-     - сортировка созданного списка по авторам / статьям +
-     + экспорт в текстовый файл статистики - автор/количество статей - для проверки и построения списка исключений +
-     + статистика, сколько ссылок у одной рубрики - нужна при составлении дерева рубрик +
-     + регалии хранить не требуется - автор имеет только фамилию, имя и отчество +
- +
-  Запользование этого списка идёт уже на этапе построения авторского указателя и рубрикатора соответственно +
-  потому как в одной строке не получается хранить больше 1000 символов и 500 ссылок в одну строку на укладываются :( +
- +
-  Оглавление по авторам - также три уровня +
-     - первый уровень - таблица на одну страницу - алфавит с уточнением - диапазонами из трёх букв +
-       Количество диапазонов фиксированное - для равномерного заполнения первой страницы +
-     - второй уровень - полный перечень авторов для каждого диапазона +
-     - третий - перечень статей для каждого автора (возможно с фоткой и краткой биографией) +
- +
- +
-+
-var vYear, vMonth, vAuthor, vRubrika, Values, prevValue, outValues: OLEVariant; +
-    ISheet, ISheet_auth_index, ISheet_rubr_index, ISheet_authors, ISheet_rubriks, +
-    ISheet_triplet, ISheet_sinonims, ISheet_rubriks_type: Excel8TLB._Worksheet; +
-    IRange: Excel8TLB.Range; +
-    //IR1, IR2: IxlRange; +
-    articles: array of TMyContent; +
-    auth_index:array of index_element; +
-    authors: array of authors_element; +
-    triplets: array of triplets_element; +
-    rubr_index: array of rubr_index_element; +
-    rubriks: array of rubriks_element; +
-    sinonims: array of sinonims_element; +
-    rubriks_type: array of rubriks_type_element; +
-    x, first,last:integer; +
-    stroka,prevStroka,prevVolume:string; +
-    auth_index_counter, // счётчик авторских статей +
-    authors_counter, // счётчик уникальных авторов +
-    triplet_counter:integer; // счётчик триплетов +
-    rubr_index_counter, // счётчик статей с рубриками +
-    rubriks_counter: integer; // счётчик уникальных рубрик +
- +
-  function get_sinonim(rubrika:string):string; +
-  // вычисляем синоним рубрики (по предварительно составленному вручную списку) +
-  // список синонимов находится в массиве sinonims +
-  var x:integer; +
-  begin +
-     for x:=0 to length(sinonims)-1 do begin +
-        if sinonims[x].rubrika=rubrika then begin +
-           result:=sinonims[x].sinonim; +
-           exit; +
-        end; +
-     end; +
-     result:=rubrika; +
-  end; +
-  function get_rubrik_type(calculated_type:integer; rubrika:string):integer; +
-  // получаем тип рубрики (по вычисленному типу и предварительно составленному вручную списку) +
-  // список типов рубрик от пользователя находится в массиве rubriks_type +
-  var x:integer; +
-  begin +
-     for x:=0 to length(rubriks_type)-1 do begin +
-        if rubriks_type[x].rubrika = rubrika then begin +
-           result := rubriks_type[x].is_table_rubrik; +
-           exit; +
-        end; +
-     end; +
-     result := calculated_type; +
-  end; +
-procedure process_rubriks(rubriki:string; link:integer); +
-  function other_rubriks(rubriks:TStringList; i: integer):string; +
-  var x: integer; +
-      temp_str:string; +
-  begin +
-     temp_str := ''; +
-     for x:=0 to rubriks.Count-1 do begin +
-        if x<i then begin // запомнить все рубрики до i - "материнские" рубрики - рубрики более высокого уровня +
-           if temp_str = '' +
-              then temp_str := rubriks[x] +
-              else temp_str := temp_str + ' | ' + rubriks[x]; +
-        end; +
-     end; +
-     result := temp_str; +
-  end; +
-  var x:integer; +
-      temp:string; +
-      mas:TStringList; +
-  begin +
-     if rubriki='' then exit; // пропускаем статьи без рубрик +
- +
-     rubriki:=StringReplace(rubriki, ' | ', '@', [rfReplaceAll]); // получено в вычищенном виде при сборке +
- +
-     mas:=TStringList.Create; +
-     temp:=''; +
-     for x:=1 to length(rubriki) do begin // разбиваем строку на подстроки, разделитель "@" +
-       if rubriki[x]='@' then begin +
-          mas.Add(temp); +
-          temp:=''; +
-       end else temp:=temp+rubriki[x]; +
-     end; +
-     mas.Add(temp); // добавить последний найденный элемент +
-     for x := 0 to mas.Count-1 do begin +
-        setlength(rubr_index,rubr_index_counter+1); // завести место под новый элемент +
-        rubr_index[rubr_index_counter].name:= get_sinonim(mas[x]); +
-        rubr_index[rubr_index_counter].index:= link; +
-        rubr_index[rubr_index_counter].other_rubrik := other_rubriks(mas,x); // сопутствующие рубрики +
-        inc(rubr_index_counter); +
-     end; +
-     mas.Free; +
-  end; +
-function extract_surname(name:string):string; +
-  {фамилия вычленяется следующим образом - берётся конец строки до пробела "М. Иванов", "Михаил Иванов"+
-  Итого, алгоритм критичен к отсутствию пробела после точки - это можно исправить, но тогда не будут появляться разные авторы +
-  "М.Иванов" и "М. Иванов"+
-  var temp:string; +
-      x:integer; +
-  begin +
-     temp:=''; +
-     for x:=length(name) downto 1 do begin +
-        if name[x]=' ' then break; +
-        temp := name[x] + temp; +
-     end; +
-     extract_surname:=temp; +
-  end; +
-function check_name(name:string):boolean; +
-// проверка качества имени - имя должно быть только из русских букв +
-var x:integer; +
-    test_str:string; +
-begin +
-   for x:=1 to length(name) do begin +
-      if not (name[x] in ['а'..'я','А'..'Я','ё','Ё','.',' ','''','-']) then begin +
-         result := false; +
-         exit; +
-      end; +
-   end; +
-   test_str := extract_surname(name); +
-   if length(test_str)<3 then begin // триплет должен иметь три символа +
-      result := false; +
-      exit; +
-   end; +
-   for x:=1 to length(test_str) do begin +
-      if not (test_str[x] in ['А'..'Я','Ё','''','-']) then begin // ограничения на символы в фамилии +
-         result := false; +
-         exit; +
-      end; +
-   end; +
- +
-   result := true; +
-end; +
-function process_authors(rubrika, authors:string; link:integer):boolean; +
-//link - номер статьи в основном списке (на листе "Содержание"+
-  var x:integer; +
-      temp:string; +
-      mas:TStringList; +
-      ok: boolean; +
-  begin +
-     ok := true; +
-     if authors='' then begin result := ok; exit end; // пропускаем статьи без авторов +
-     if pos('Рефераты',rubrika)>0 then begin result := ok; exit end; // пропускаем авторов рефератов +
-     if pos('Вкладк',rubrika)>0 then begin result := ok; exit end; // пропускаем вкладки +
-     if pos('Обложк',rubrika)>0 then begin result := ok; exit end; // пропускаем обложки +
-     temp := copy (authors,1,5); +
- +
-     authors := StringReplace(authors,' и ','@',[rfReplaceAll, rfIgnoreCase]); +
-     authors := StringReplace(authors,', ','@',[rfReplaceAll, rfIgnoreCase]); +
- +
-     mas:=TStringList.Create; +
-     temp:=''; +
-     for x:=1 to length(authors) do begin // разбиваем строку на подстроки, разделитель "@" +
-       if authors[x]='@' then begin +
- +
-          if (length(temp)>0) and (temp[1]=AnsiUpperCase(temp[1])) and  // добавлять только имена (начинаются с заглавной буквы) +
-             (pos('кадемии',temp)=0) and // никаких "кадемии" в имени нет +
-             (pos('осударствен',temp)=0) and // никаких "осударствен" в имени нет +
-             (pos('Украины',temp)=0) // никаких "Украины" в имени нет +
-             then mas.Add(temp); +
-          temp:=''; +
-       end else temp:=temp+authors[x]; +
-     end; +
-     if (temp<>'') and (temp[1]=AnsiUpperCase(temp[1])) and  // добавлять только имена (начинаются с заглавной буквы) +
-        (pos('кадемии',temp)=0) and // никаких "кадемии" в имени нет +
-        (pos('осударствен',temp)=0) and // никаких "осударствен" в имени нет +
-        (pos('Украины',temp)=0) // никаких "Украины" в имени нет +
-        then mas.Add(temp); +
-     for x := 0 to mas.Count-1 do begin +
-        setlength(auth_index,auth_index_counter+1); // завести место под новый элемент +
-        if not check_name(mas[x]) then ok := false; +
-        auth_index[auth_index_counter].name:= mas[x]; +
-        auth_index[auth_index_counter].index:= link; +
-        inc(auth_index_counter); +
-     end; +
-     mas.Free; +
-     result := ok; +
-  end; +
-  function detect_rubriks_group(rubrik_name:string):integer; +
-  var x:integer; +
-      n: integer; +
-      results: integer; +
-  begin +
-     results:=0; +
-     for x:=1 to length(Rubriks_Groups)-1 do begin +
-        if Rubriks_Groups[x].rubriks.Find(rubrik_name, n) then begin +
-           results := x; +
-           break; +
-        end +
-     end; +
-     detect_rubriks_group := results; +
-  end; +
-  function detect_common_rubriks(i:integer; rubrik_name:string):integer; +
-     Const min_vol = 1; +
-           max_vol = 12; +
-           test_vol = max_vol + 1; +
-           magic_number = 6; // количество номеров с рубрикой в году, +
-                             // при котором рубрика считается регулярной +
-     var x:integer; +
-         user_year, user_vol:integer; +
-         all_volumes:array[min_year..max_year, min_vol..max_vol+1] of integer; +
-  begin +
-    // Заполнить таблицу ссылок (all_volumes) для рубрики +
-    FillChar(all_volumes,sizeof(all_volumes),0); // инициализировать таблицу номеров +
-    for x := rubriks[i].index to rubriks[i].index+rubriks[i].count-1 do begin // прочесать все статьи для рубрики x +
-       try +
-          user_year := strtoint(articles[rubr_index[x].index].year); // заполучить год, в котором статья +
-          user_vol := strtoint(articles[rubr_index[x].index].volume); // заполучить номер, в котором статья +
-       except +
-          user_year := 0; +
-          user_vol := 0; +
-       end; +
-       if (user_year >= min_year) and (user_year <= max_year) and +
-       (user_vol >= min_vol) and (user_vol <= max_vol) +
-       then begin +
-          if all_volumes[user_year, user_vol] = 0 then begin +
-             all_volumes[user_year, user_vol] := 1; // в этом номере есть статьи нужной рубрики +
-             inc(all_volumes[user_year, test_vol]); // увеличить годовой счётчик +
-          end; +
-       end; +
-    end; +
-    for x:=min_year to max_year do begin +
-       if all_volumes[x, test_vol] >= magic_number then begin +
- +
-          detect_common_rubriks:=get_rubrik_type(1,rubrik_name); exit; +
- +
-       end; +
-    end; +
-    detect_common_rubriks:=get_rubrik_type(0,rubrik_name); +
-  end; +
-begin +
-  sort_articles; // отсортировать статьи +
-  Load_rubriks_groups; // загрузить список групп рубрик +
-  // загрузить полный список статей +
- +
-  auth_index_counter := 1; +
-  rubr_index_counter := 1; +
-  global_progress.Min:=0; +
-  global_progress.max:=15; // основные этапы +
-  global_progress.Position:=local_progress.Min; +
-  global_progress.Step:=1; +
-  if Assigned(IWorkbook) then +
-    try +
-      ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-      if not simple_mode then begin +
-         ISheet_auth_index := IWorkbook.Worksheets.Item['Авторы'] as Excel8TLB._Worksheet; +
-         ISheet_auth_index.Cells.Clear; // очистить лист "Авторы" +
-         ISheet_rubr_index := IWorkbook.Worksheets.Item['Рубрики'] as Excel8TLB._Worksheet; +
-         ISheet_rubr_index.Cells.Clear; // очистить лист "Рубрики" +
-         ISheet_authors := IWorkbook.Worksheets.Item['Авторы (свод)'] as Excel8TLB._Worksheet; +
-         ISheet_authors.Cells.Clear; // очистить лист "Авторы (свод)" +
-         ISheet_rubriks := IWorkbook.Worksheets.Item['Рубрики (свод)'] as Excel8TLB._Worksheet; +
-         ISheet_rubriks.Cells.Clear; // очистить лист "Рубрики (свод)" +
-         ISheet_triplet := IWorkbook.Worksheets.Item['Триплеты'] as Excel8TLB._Worksheet; +
-         ISheet_triplet.Cells.Clear; // очистить лист "Триплеты" +
-         // загрузить список типов рубрик (табличная/списочная) +
-         ISheet_rubriks_type := IWorkbook.Worksheets.Item['Типы рубрик'] as Excel8TLB._Worksheet; +
-         IRange := ISheet_rubriks_type.UsedRange[0]; +
-         Values := IRange.Value; +
-         SetLength(Rubriks_type,IRange.Rows.Count+1); +
-         global_progress.StepIt; +
-         local_progress.Min:=0; +
-         local_progress.max:=IRange.Rows.Count; +
-         local_progress.Position:=local_progress.Min; +
-         local_progress.Step:=1; +
-         statusbar1.simpletext:='Загрузка листа "Типы рубрик"...'; +
-         for x := 1 to IRange.Rows.Count do begin +
-            local_progress.stepit; +
-            with Rubriks_type[x] do begin +
-               rubrika := Values[x, 1]; +
-               if (Values[x, 2] = 'таблица') then is_table_rubrik := 1 else is_table_rubrik := 0; +
-            end; +
-         end; +
-         ISheet_rubriks_type := nil; +
- +
-         // загрузить список синонимов рубрик +
-         ISheet_sinonims := IWorkbook.Worksheets.Item['Синонимы'] as Excel8TLB._Worksheet; +
-         IRange := ISheet_sinonims.UsedRange[0]; +
-         Values := IRange.Value; +
-         SetLength(Sinonims,IRange.Rows.Count+1); +
-         global_progress.StepIt; +
-         local_progress.Min:=0; +
-         local_progress.max:=IRange.Rows.Count; +
-         local_progress.Position:=local_progress.Min; +
-         local_progress.Step:=1; +
-         statusbar1.simpletext:='Загрузка листа "Синонимы"...'; +
-         for x := 1 to IRange.Rows.Count do begin +
-            local_progress.stepit; +
-            with Sinonims[x] do begin +
-               rubrika := Values[x, 1]; +
-               sinonim := Values[x, 2]; +
-            end; +
-         end; +
-         ISheet_sinonims := nil; +
-      end; +
-      try +
-        for x:=1 to IWorkbook.Names.Count do begin +
-           IWorkbook.Names.Item(1,EmptyParam,EmptyParam).delete; {удалить все именованные диапазоны} +
-        end; +
-        edt_volumes.Items.Clear; +
-        edt_volumes.Sorted:=false; +
- +
- +
-        // загрузить лист "Содержание" +
-        IRange := ISheet.UsedRange[0];  // прочесть весь лист +
-        Values := IRange.Value; +
-        SetLength(Articles,IRange.Rows.Count+1); // установить длину массива статей +
-        // загрузить массив статей +
-        global_progress.StepIt; +
-        local_progress.Min:=1; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка массива статей...'; +
-        for x:=1 to IRange.Rows.Count do begin +
-          local_progress.StepIt; +
-          with Articles[x] do begin +
-             rubrika := Values[x, 1]; +
-             author := Values[x, 2]; +
-             title := Values[x, 3]; +
-             page := Values[x, 4]; +
-             link := Values[x, 5]; +
-             volume := Values[x, 6]; +
-             year := Values[x, 7]; +
-          end; +
-        end; +
-        with Articles[2] do begin +
-           stroka := year + '_' + volume; first:=2; +
-           if not simple_mode then begin +
-              if not process_authors(rubrika,author,2) then // вычленить авторов из описания и положить в список авторов +
-                 ShowMessageInLog(year,volume,page,format('Некорректное имя автора - "%s"',[author])); +
-              process_rubriks(rubrika,2); // вычленить рубрики из описания и положить в список рубрик +
-           end; +
-        end; +
- +
-        global_progress.StepIt; +
-        local_progress.Min:=3; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Построение списка номеров...'; +
-        for x:=3 to IRange.Rows.Count do begin +
-           local_progress.StepIt; +
-           statusbar1.simpletext:='Построение списка номеров (строка '+inttostr(x)+')...'; +
-           with Articles[x] do begin +
-              prevVolume := articles[x-1].volume; +
-              prevStroka := stroka; +
-              if not simple_mode then begin +
-                 if not process_authors(rubrika,author,x) then // вычленить авторов из описания и положить в список авторов +
-                    ShowMessageInLog(year, volume, page, format('Некорректное имя автора - "%s"',[author])); +
-                 process_rubriks(Rubrika,x); // вычленить рубрики из описания и положить в список рубрик +
-              end; +
-              stroka := Year + '_' + volume; +
-              if (stroka <> prevStroka) then begin // сменился блок без разделителя +
-                 statusbar1.simpletext:='Построение списка номеров... ('+prevStroka+')'; +
-                 last:=x-1; +
-                 IWorkbook.Names.Add('vol_'+prevStroka, +
-                                     EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam, +
-                                     '=Содержание!R'+IntToStr(first)+'C1:R'+IntToStr(last)+'C7',EmptyParam); +
-                 edt_volumes.Items.Add(prevStroka); +
-                 first:=x; +
-              end; +
-              if (prevVolume = '') and (volume = '') then break; +
-           end; +
-        end; +
-        last:=IRange.Rows.Count; +
-        if prevStroka<>'_' then begin IWorkbook.Names.Add('vol_'+prevStroka, +
-                                  EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam, +
-                                  '=Содержание!R'+IntToStr(first)+'C1:R'+IntToStr(last)+'C7',EmptyParam); +
-           edt_volumes.Items.Add(prevStroka); +
-        end; +
-        if not simple_mode then begin +
- +
-        // выгрузить инфу на лист ISheet_auth_index +
-        outValues := VarArrayCreate([1, length(auth_index), 1, 2], varVariant); +
-        for x:=1 to length(auth_index)-1 do begin +
-           outValues[x, 1] := auth_index[x].name; +
-           outValues[x, 2] := auth_index[x].index; +
-        end; +
-        IRange:= ISheet_auth_index.Range['A1','B'+inttostr(length(auth_index)-1)]; +
-        IRange.Value := outValues; +
-        VarClear(outValues); +
- +
-        global_progress.StepIt; +
-        sort_articles; +
- +
-        // выгрузить инфу на лист ISheet_rubr_index +
-        outValues := VarArrayCreate([1, length(rubr_index), 1, 3], varVariant); +
-        for x:=1 to length(rubr_index)-1 do begin +
-           outValues[x, 1] := rubr_index[x].name; +
-           outValues[x, 2] := rubr_index[x].index; +
-           outValues[x, 3] := rubr_index[x].other_rubrik; +
-        end; +
-        IRange:= ISheet_rubr_index.Range['A1','C'+inttostr(length(rubr_index)-1)]; +
-        IRange.Value := outValues; +
-        VarClear(outValues); +
- +
-        global_progress.StepIt; +
-        sort_articles; +
- +
-        // построение списка уникальных авторов +
-        IRange := ISheet_auth_index.UsedRange[0];  // прочесть весь лист +
-        Values := IRange.Value; +
- +
-        // то самое место, где жутко тормозит +
-        vAuthor := Values[1, 1]; first:=1; //last:=0; +
-        statusbar1.simpletext:='Построение списка авторов...'; +
-        authors_counter := 1; +
- +
-        global_progress.StepIt; +
-        local_progress.Min:=2; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        for x:=2 to IRange.Rows.Count do begin // построить список авторов +
-            local_progress.StepIt; +
-            prevValue := vAuthor; +
-            vAuthor := Values[x, 1]; +
-            if (vartostr(vAuthor) <> vartostr(prevValue)) then begin // сменился блок +
-               last := x-1; +
-               stroka:=extract_surname(VarToStr(prevValue)); +
- +
-               setlength(authors,authors_counter+1); // завести место под новый элемент +
-               with authors[authors_counter] do begin +
-                  name := vartostr(prevValue); +
-                  index := first; +
-                  count := last-first+1; +
-                  triplet:= copy(stroka,1,3); +
-                  surname:= stroka; +
-               end; +
-               inc(authors_counter); +
-               first := x; +
-            end; +
-        end; +
-        last := IRange.Rows.Count; +
-        stroka:=extract_surname(VarToStr(vAuthor)); +
- +
-        setlength(authors,authors_counter+1); // завести место под новый элемент +
-        with authors[authors_counter] do begin +
-           name := vartostr(vAuthor); +
-           index := first; +
-           count := last-first+1; +
-           triplet:= copy(stroka,1,3); +
-           surname:= stroka; +
-        end; +
-        //inc(authors_counter); +
- +
-        // выгрузить инфу на лист ISheet_authors +
-        outValues := VarArrayCreate([1, length(authors), 1, 5], varVariant); +
-        for x:=1 to length(authors)-1 do begin +
-           outValues[x, 1] := authors[x].name; +
-           outValues[x, 2] := authors[x].index; +
-           outValues[x, 3] := authors[x].count; +
-           outValues[x, 4] := authors[x].triplet; +
-           outValues[x, 5] := authors[x].surname; +
-        end; +
-        IRange:= ISheet_authors.Range['A1','E'+inttostr(length(authors)-1)]; +
-        IRange.Value := outValues; +
-        VarClear(outValues); +
- +
-        sort_articles; +
-        global_progress.StepIt; +
- +
-        // построение списка уникальных рубрик +
-        IRange := ISheet_rubr_index.UsedRange[0];  // прочесть весь лист +
-        Values := IRange.Value; +
- +
-        // загрузить индекс рубрик назад +
-        global_progress.StepIt; +
-        local_progress.Min:=2; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        Setlength(Rubr_index,IRange.Rows.Count+1); +
-        for x := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with Rubr_index[x] do begin +
-             name := Values[x, 1]; +
-             index := Values[x, 2]; +
-          end; +
-        end; +
- +
-        vRubrika := Values[1, 1]; first:=1; //last:=0; +
-        statusbar1.simpletext:='Построение списка рубрик...'; +
-        rubriks_counter := 1; +
- +
-        global_progress.StepIt; +
-        local_progress.Min:=2; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        for x:=2 to IRange.Rows.Count do begin // построить список рубрик +
-            local_progress.StepIt; +
-            prevValue := vRubrika; +
-            vRubrika := Values[x, 1]; +
-            if (vartostr(vRubrika) <> vartostr(prevValue)) then begin // сменился блок +
-               last := x-1; +
-               stroka:=get_sinonim(VarToStr(prevValue)); +
-               setlength(rubriks,rubriks_counter+1); // завести место под новый элемент +
-               with rubriks[rubriks_counter] do begin +
-                  name := vartostr(prevValue); +
-                  index := first; +
-                  count := last-first+1; +
-                  common := detect_common_rubriks(rubriks_counter, stroka); // определить, регулярная ли рубрика +
-                  group_number := detect_rubriks_group(stroka); // определить группу рубрики +
-               end; +
-               inc(rubriks_counter); +
-               first := x; +
-            end; +
-        end; +
-        last := IRange.Rows.Count; +
-        stroka:=get_sinonim(VarToStr(vRubrika)); +
-        // обработать последний элемент +
-        setlength(rubriks,rubriks_counter+1); // завести место под новый элемент +
-        with rubriks[rubriks_counter] do begin +
-           name := vartostr(vRubrika); +
-           index := first; +
-           count := last-first+1; +
-           common := detect_common_rubriks(rubriks_counter, stroka); // определить, регулярная ли рубрика +
-           group_number := detect_rubriks_group(stroka); // определить группу рубрики +
-        end; +
-        //inc(rubriks_counter); +
- +
-        // выгрузить инфу на лист ISheet_rubriks +
-        outValues := VarArrayCreate([1, length(rubriks), 1, 5], varVariant); +
-        for x:=1 to length(rubriks)-1 do begin +
-           outValues[x, 1] := rubriks[x].name; +
-           outValues[x, 2] := rubriks[x].index; +
-           outValues[x, 3] := rubriks[x].count; +
-           outValues[x, 4] := rubriks[x].common; +
-           outValues[x, 5] := rubriks[x].group_number; +
- +
-        end; +
-        IRange:= ISheet_rubriks.Range['A1','E'+inttostr(length(rubriks)-1)]; +
-        IRange.Value := outValues; +
-        VarClear(outValues); +
- +
-        sort_articles; +
-        global_progress.StepIt; +
- +
-        // построение списка триплетов (трёхбуквенных комбинаций) +
-        IRange := ISheet_authors.UsedRange[0];  // прочесть весь лист +
-        Values := IRange.Value; +
- +
-        vAuthor := Values[1, 4]; first:=1; //last:=0; +
-        statusbar1.simpletext:='Построение списка триплетов...'; +
-        triplet_counter:=1; +
- +
-        global_progress.StepIt; +
-        local_progress.Min:=2; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        for x:=2 to IRange.Rows.Count do begin // построить список триплетов +
-            local_progress.StepIt; +
-            prevValue := vAuthor; +
-            vAuthor := Values[x, 4]; +
-            if vartostr(vAuthor) <> vartostr(prevValue) then begin // сменился блок +
-               last := x-1; +
-               stroka:=extract_surname(VarToStr(prevValue)); +
- +
-               setlength(triplets,triplet_counter+1); // завести место под новый элемент +
-               with triplets[triplet_counter] do begin +
-                  triplet := vartostr(prevValue); +
-                  index := first; +
-                  count := last-first+1; +
-                  letter:= copy(stroka,1,1); +
-               end; +
-               inc(triplet_counter); +
-               first := x; +
-            end; +
-        end; +
-        last := IRange.Rows.Count; +
-        stroka:=extract_surname(VarToStr(vAuthor)); +
- +
-        setlength(triplets,triplet_counter+1); // завести место под новый элемент +
-        with triplets[triplet_counter] do begin +
-           triplet := vartostr(vAuthor); +
-           index := first; +
-           count := last-first+1; +
-           letter:= copy(stroka,1,1); +
-        end; +
-        //inc(triplet_counter); +
- +
-        // выгрузить инфу на лист ISheet_triplet +
-        outValues := VarArrayCreate([1, length(triplets), 1, 4], varVariant); +
-        for x:=1 to length(triplets)-1 do begin +
-           outValues[x, 1] := triplets[x].triplet; +
-           outValues[x, 2] := triplets[x].index; +
-           outValues[x, 3] := triplets[x].count; +
-           outValues[x, 4] := triplets[x].letter; +
-        end; +
-        IRange:= ISheet_triplet.Range['A1','D'+inttostr(length(triplets)-1)]; +
-        IRange.Value := outValues; +
-        VarClear(outValues); +
- +
-        sort_articles; +
-        end; // simple_mode +
-        global_progress.StepIt; +
-        statusbar1.simpletext:='Сохранение файла...'; +
- +
-        local_progress.Position := local_progress.max; +
-        edt_volumes.Sorted:=true; +
-        if edt_volumes.Items.Count>0 then edt_volumes.ItemIndex:=0; +
-          //0: Value := ISheet.Cells.Item[2, 1].Value; +
-          //1: Value := ISheet.Range['A2', EmptyParam].Value; +
-          //2: Value := ISheet.Range['TestCell', EmptyParam].Value; +
-          //3: Value := IWorkbook.Names.Item('TestCell', EmptyParam, EmptyParam).RefersToRange.Value; +
-          //ShowMessageInLog(Value); +
-      finally +
-        IRange := nil; +
-        ISheet := nil; +
-        ISheet_auth_index := nil; +
-        ISheet_rubr_index := nil; +
-        ISheet_authors := nil; +
-        ISheet_rubriks := nil; +
-        ISheet_triplet := nil; +
-        IWorkBook.Save(0); +
-        setlength(auth_index,0); +
-        setlength(rubr_index,0); +
-        setlength(authors,0); +
-        setlength(rubriks,0); +
-        setlength(triplets,0); +
-        setlength(sinonims,0); +
-        statusbar1.simpletext:='Готово'; +
-        global_progress.StepIt; +
-      end; +
-    except +
-      raise Exception.Create('Не могу прочитать данные!'); +
-    end; +
-    local_progress.Position := local_progress.Max; +
-    global_progress.Position := global_progress.Max; +
-end; +
- +
-Procedure TForm1.sort_articles; +
-var ISheet: Excel8TLB._Worksheet; +
-begin +
-  if Assigned(IWorkbook) then begin +
-     ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-     try +
-       try +
-         ISheet.Columns.Sort(ISheet.Range['G1',emptyparam],xlAscending,ISheet.Range['F1',emptyparam],EmptyParam, +
-         xlAscending,ISheet.Range['D1',emptyparam],xlAscending, +
-         xlYes, EmptyParam, EmptyParam, +
-         xlTopToBottom, xlStroke, +
-         true, true, +
-         true); +
-      finally +
-         ISheet := nil; +
-       end; +
-     except +
-       raise Exception.Create('Не могу отсортировать статьи!'); +
-     end; +
- +
-     if not simple_mode then begin +
-     ISheet := IWorkbook.Worksheets.Item['Авторы'] as Excel8TLB._Worksheet; +
-     try +
-       try +
-         ISheet.Columns.Sort(ISheet.Range['A1',emptyparam],xlAscending,ISheet.Range['B1',emptyparam],EmptyParam, +
-         xlAscending,ISheet.Range['C1',emptyparam],xlAscending, +
-         xlNo, EmptyParam, EmptyParam, +
-         xlTopToBottom, xlStroke, +
-         true, true, +
-         true); +
-       finally +
-         ISheet := nil; +
-       end; +
-     except +
-       raise Exception.Create('Не могу отсортировать авторов!'); +
-     end; +
- +
-     ISheet := IWorkbook.Worksheets.Item['Рубрики'] as Excel8TLB._Worksheet; +
-     try +
-       try +
-         ISheet.Columns.Sort(ISheet.Range['A1',emptyparam],xlAscending,ISheet.Range['B1',emptyparam],EmptyParam, +
-         xlAscending,ISheet.Range['C1',emptyparam],xlAscending, +
-         xlNo, EmptyParam, EmptyParam, +
-         xlTopToBottom, xlStroke, +
-         true, true, +
-         true); +
-       finally +
-         ISheet := nil; +
-       end; +
-     except +
-       raise Exception.Create('Не могу отсортировать рубрики!'); +
-     end; +
- +
- +
-     ISheet := IWorkbook.Worksheets.Item['Авторы (свод)'] as Excel8TLB._Worksheet; +
-     try +
-       try +
-         ISheet.Columns.Sort(ISheet.Range['D1',emptyparam],xlAscending,ISheet.Range['E1',emptyparam],EmptyParam, +
-         xlAscending,ISheet.Range['F1',emptyparam],xlAscending, +
-         xlNo, EmptyParam, EmptyParam, +
-         xlTopToBottom, xlStroke, +
-         true, true, +
-         true); +
-       finally +
-         ISheet := nil; +
-       end; +
-     except +
-       raise Exception.Create('Не могу отсортировать свод авторов!'); +
-     end; +
- +
-     ISheet := IWorkbook.Worksheets.Item['Рубрики (свод)'] as Excel8TLB._Worksheet; +
-     try +
-       try +
-         ISheet.Columns.Sort(ISheet.Range['E1',emptyparam],xlAscending,ISheet.Range['A1',emptyparam],EmptyParam, +
-         xlAscending,ISheet.Range['F1',emptyparam],xlAscending, +
-         xlNo, EmptyParam, EmptyParam, +
-         xlTopToBottom, xlStroke, +
-         true, true, +
-         true); +
-       finally +
-         ISheet := nil; +
-       end; +
-     except +
-       raise Exception.Create('Не могу отсортировать свод рубрик!'); +
-     end; +
- +
- +
-     end; // simple_mode +
-  end; +
-end; +
- +
-procedure TForm1.Load_complex_rubriks; +
-var Values: OLEVariant; +
-    ISheet: Excel8TLB._Worksheet; +
-    IRange: Excel8TLB.Range; +
-    i: integer; +
-begin +
-   // загрузить список сборных рубрик +
-   ISheet := IWorkbook.Worksheets.Item['Сборные рубрики'] as Excel8TLB._Worksheet; +
-   IRange := ISheet.UsedRange[0]; +
-   local_progress.Min:=0; +
-   local_progress.max:=IRange.Rows.Count; +
-   local_progress.Position:=local_progress.Min; +
-   local_progress.Step:=1; +
-   statusbar1.simpletext:='Загрузка списка сборных рубрик...'; +
-   Values := IRange.Value; +
-   //global_progress.StepIt; +
-   Rubriki.Clear; +
-   for i := 1 to IRange.Rows.Count do begin +
-      local_progress.stepit; +
-      Rubriki.Add(Values[i,1]); +
-   end; +
-   ISheet := nil; +
-   statusbar1.simpletext:=''; +
-end; +
- +
- +
-{заполняет структуру Rubriks_groups на основе информации с листа "Группы рубрик"+
-procedure TForm1.Load_rubriks_groups; +
-var Values: OLEVariant; +
-    ISheet: Excel8TLB._Worksheet; +
-    IRange: Excel8TLB.Range; +
-    i,j: integer; +
-    temp_str: string; +
-begin +
-   ISheet := IWorkbook.Worksheets.Item['Группы рубрик'] as Excel8TLB._Worksheet; +
-   IRange := ISheet.UsedRange[0]; +
-   local_progress.Min:=0; +
-   local_progress.max:=IRange.Columns.Count; +
-   local_progress.Position:=local_progress.Min; +
-   local_progress.Step:=1; +
-   statusbar1.simpletext:='Загрузка списка типов рубрик...'; +
-   Values := IRange.Value; +
-   setlength(Rubriks_groups,IRange.Columns.Count+1); +
-   Rubriks_groups[0].group := 'Другие рубрики'; +
-   Rubriks_groups[0].rubriks := TStringList.Create; // создать контейнер для рубрик +
-   for i := 1 to IRange.Columns.Count do begin +
-      local_progress.stepit; +
-      with Rubriks_groups[i] do begin +
-         group := Values[1,i]; // получить название группы +
-         rubriks := TStringList.Create; // создать контейнер для рубрик +
-         rubriks.Sorted := true; +
-         for j:=2 to IRange.Rows.Count do begin // загрузить рубрики +
-            temp_str := Values[j,i]; +
-            if (temp_str <> '') then rubriks.Add(temp_str) else break; +
-         end; +
-      end; +
-   end; +
-   ISheet := nil; +
-   statusbar1.simpletext:=''; +
-end; +
- +
-procedure TForm1.Local_Content_Create(Sender: TObject); +
-var year_vol:string; +
-    x:integer; +
-    year, load_year_vol:string; +
-   procedure LoadContent(year_vol:string); +
-   var Values: OLEVariant; +
-       ISheet: Excel8TLB._Worksheet; +
-       IRange: Excel8TLB.Range; +
-       i,j: integer; +
-       stroka: string; +
-   begin +
-      try +
-         ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-         IRange := ISheet.Range['vol_'+year_vol, EmptyParam]; +
-         Values := IRange.Value; +
-         SetLength(VolumeContent,IRange.Rows.Count); +
-         for i := 1 to IRange.Rows.Count do begin +
-            with VolumeContent[i-1] do begin +
-              rubrika := Values[i, 1]; +
-              author := Values[i, 2]; +
-              title := Values[i, 3]; +
-              page := Values[i, 4]; +
-              link := Values[i, 5]; +
-              volume := Values[i, 6]; +
-              year := Values[i, 7]; +
-              used_as_slave := false; +
-              for j:=1 to max_complex_rubriks do used_as_article[j] := false; +
-              stroka:= format('%s * %s * %s * %s * %s * %s * %s', [rubrika, author, title, page, link, volume, year]); +
-           end; +
-         end; +
-      finally +
-         IRange := nil; +
-         ISheet := nil; +
-      end; +
-   end; +
-begin +
-  if Assigned(IWorkbook) then begin +
-     Load_complex_rubriks; // загрузить список сборных рубрик +
-     local_progress.Min:=0; +
-     local_progress.max:=edt_volumes.Items.Count; +
-     local_progress.Position:=local_progress.Min; +
-     local_progress.Step:=1; +
-     for x:=0 to edt_volumes.Items.Count-1 do begin +
-        AllContent:=TMemoryStream.Create; +
-        local_progress.StepIt; +
-        load_year_vol:=edt_volumes.Items[x]; +
-        year_vol:=load_year_vol; +
-        year := copy(year_vol, 1, 4); +
-        if (year_vol = '1992_05') then year_vol := '1992_05_06'; +
-        statusbar1.simpletext:=format('Создание закладок для %s.djvu...',[year_vol]); +
-        fileDJVU_Bookmarks:=TFileStream.Create(prog_path+'bookmarks\'+year_vol+'.htm', fmCreate); +
-        LoadContent(load_year_vol); +
-        MakeContent; +
-        ExportHTML(make_single); +
-        fileDJVU_Bookmarks.CopyFrom(AllContent,0); // скопировать всё оглавление в файл с оглавлением +
-        fileDJVU_Bookmarks.Free; +
-        AllContent.Free; +
-     end; +
-  end; +
-  statusbar1.simpletext:='Готово'; +
-end; +
- +
-procedure TForm1.CreateBatches; +
-var bat_file: TStringList; +
-    sed_path: string; +
-    x:integer; +
-    year, year_vol: string; +
-function test_path:boolean; +
-var x:integer; +
-    results:boolean; +
-begin +
-  results := true; +
-  for x:=1 to length(prog_path) do begin +
-     if (prog_path[x] in ['А'..'Я', 'а'..'я', 'Ё', 'ё', ' ']) then +
-     begin +
-        results := false; +
-        break; +
-     end; +
-  end; +
-  test_path := results; +
-end; +
-begin +
-  if not test_path then begin +
-  Application.MessageBox( +
-    'Путь к рабочей папке содержит нежелательные символы - автоматическая конвертация в DJVU будет невозможна.'+#13#10+#13#10+ +
-    'Имена папок должны быть набраны латиницей и не содержать пробелов', +
-    'Предупреждение о проблемах', +
-    MB_OK); +
-  end; +
-  bat_file:=TStringList.Create; +
- +
-  // !insert_bookmarks.bat +
- +
-  for x:=0 to edt_volumes.Items.Count-1 do begin +
-     year_vol:=edt_volumes.Items[x]; +
-     year := copy(year_vol, 1, 4); +
-     if (year_vol = '1992_05') then year_vol := '1992_05_06'; +
-     bat_file.Add(format('@call !insert_one.bat %s %s',[year, year_vol])); +
-  end; +
-  bat_file.SaveToFile(prog_path+'!insert_bookmarks.bat'); +
- +
-  // !insert_one.bat +
- +
-  bat_file.Clear; +
-  bat_file.Add('@echo off'); +
-  bat_file.Add('echo Inserting bookmarks into %1\%2.djvu'); +
-  bat_file.Add('bookmark.exe "bookmarks\%2.htm" "%1\%2.djvu"'); +
-  bat_file.Add('del "%1\%2.djvu"'); +
-  bat_file.Add('ren "%1\%2.new.djvu" "%2.djvu"'); +
-  bat_file.SaveToFile(prog_path+'!insert_one.bat'); +
- +
-  // !do_all.bat +
- +
-  bat_file.Clear; +
-  bat_file.Add('@call !process_one.bat all_authors'); +
-  bat_file.Add('@call !process_one.bat all_rubriks'); +
-  bat_file.Add('@call !process_one.bat all_content'); +
-  bat_file.Add('@call !insert_bookmarks.bat'); +
-  bat_file.SaveToFile(prog_path+'!do_all.bat'); +
- +
-  // !Process_one.bat +
- +
-  bat_file.Clear; +
-  bat_file.Add('@ECHO OFF'); +
-  bat_file.Add('echo Converting PDF to DJVU...'); +
-  bat_file.Add('"pdftodjvu.exe" --dpi=300 --threshold-level=80 --fg-quality=quasilossless --bg-subsample=3 '+ +
-  '--quality=75 --words --convert-links --fgbg-sep --fg-colors=256 --fg-image-colors=40 --pages-per-dict=20 '+ +
-  '--force --profile=clean300 --ignore-color-profiles "' + prog_path + '%1.pdf" "' + prog_path + '%1.djvu"'); +
-  bat_file.Add('echo Extracting links from DJVU...'); +
-  bat_file.Add('djvused.exe "%1.djvu" -e output-ant > "%1.txt"'); +
-  bat_file.Add('echo Correcting links...'); +
- +
-  // вычислить строку для коррекции ссылок внутри DJVU - коррекция бага Acrobat'+
-  sed_path := prog_path;                                        // G:\NiZh\read_excel\ +
-  sed_path:=StringReplace(sed_path, ':', '|', [rfReplaceAll]);  // G|\NiZh\read_excel\ +
-  sed_path:=StringReplace(sed_path, '\', '/', [rfReplaceAll]);  // G|/NiZh/read_excel/ +
-  sed_path:='../file:///' + sed_path;                           // ../file:///G|/NiZh/read_excel/ +
-  sed_path:=StringReplace(sed_path, '/', '\/', [rfReplaceAll]); // ..\/file:\/\/\/G|\/NiZh\/read_excel\/ +
- +
-  bat_file.Add('sed -e "s/' + sed_path + '//" "%1.txt" > "%1.temp.txt"'); +
-  bat_file.Add('echo Inserting links into DJVU...'); +
-  bat_file.Add('djvused.exe "%1.djvu" -f "%1.temp.txt" -s'); +
-  bat_file.Add('echo Inserting bookmarks into DJVU...'); +
-  bat_file.Add('bookmark.exe all_bookmarks.htm %1.djvu'); +
-  bat_file.Add('del "%1.djvu"'); +
-  bat_file.Add('ren "%1.new.djvu" "%1.djvu"'); +
-  bat_file.Add('echo Deleting temporary files...'); +
-  bat_file.Add('del "%1.txt"'); +
-  bat_file.Add('del "%1.temp.txt"'); +
-  bat_file.Add('echo %1.djvu is ready.'); +
-  bat_file.SaveToFile(prog_path+'!process_one.bat'); +
-  bat_file.Free; +
-end; +
- +
-procedure TForm1.ShowTree; +
-var i: integer; +
-    srcNode:TTreeNode; +
-    stroka:string; +
-begin +
-        tree_preview.Items.Clear; +
-        tree_preview.Items:=single_volume_tree.Items; // перенести из дерева оглавления структуру +
-        srcNode:=tree_preview.TopItem; +
-        while srcNode <> nil do begin +
-           if pos('_',srcNode.Text)=0 then +
-              i:=StrToInt(srcNode.text) +
-           else +
-              i := strToInt(copy(SrcNode.Text,1,pos('_',SrcNode.Text)-1)); +
-           stroka := ''; +
-           if (VolumeContent[i].rubrika <> '') then stroka := '[' + VolumeContent[i].rubrika + '] '; +
-           if (VolumeContent[i].author <> '') then stroka := stroka + '(' + VolumeContent[i].author + ') — '; +
-           if (VolumeContent[i].title <> '') then stroka := stroka + VolumeContent[i].title; +
-           if length(stroka)>255 then stroka:=copy(stroka,1,250)+'...'; +
-           srcNode.text:=stroka;    // и подменить цифры на осмысленный текст +
-           srcNode:=srcNode.GetNext; +
-        end; +
-end; +
- +
-procedure TForm1.MakeContent; +
-var i,y: integer; +
-    Node, lastNode:TTreeNode; +
-    stroka, stroka_spec:string; +
-    special_rubrika, slave, master:boolean; +
-    other_rubriks:string; +
-    pos_found:integer; +
- +
-   procedure connect_slaves(Node:TTreeNode; master_link: string); +
-   // собирает все подчинённые статьи (подвёрстки) для данной мастер-статьи +
-   // на входе - узел мастер-статьи и мастер-ссылка +
-   var x:integer; +
-       stroka : string; +
-       master_flag : boolean; +
-       counter : integer; +
-       article_number:integer; +
-   begin +
-      master_flag:=true; +
-      stroka:=master_link; +
-      counter:=0; +
-      Delete(stroka,1,1); // получить соответствующий слэйв-линк +
-      stroka:= 'д' + stroka; +
-      for x:=0 to length(VolumeContent)-1 do begin +
-         with VolumeContent[x] do begin +
-            if link = master_link then inc(counter); // подсчитать кол-во мастер-линков (должен быть один) +
-            if link = stroka then begin  // найден соответсвующий слэйв +
-               single_volume_tree.Items.AddChild(Node, IntToStr(x)); +
-               used_as_slave:=true; +
-               master_flag:=false; +
-            end; +
-         end; +
-      end; +
-      // получить номер статьи для вывода сообщения +
-      if pos('_',Node.Text)=0 then begin +
-         article_number := StrToInt(Node.Text); +
-      end else begin +
-         article_number := strToInt(copy(Node.Text,1,pos('_',Node.Text)-1)); +
-      end; +
- +
-      if master_flag then begin // проверка на "orphan master"одинокие мастер-статьи +
-         with VolumeContent[article_number] do begin +
-            ShowMessageInLog(year, volume, page, format('Не найдено ни одной подвёрстки (%s) для [%s %s %s] (%s)',[stroka, rubrika, author, title, link])); +
-         end; +
-      end; +
-      if counter<>1 then begin +
-         with VolumeContent[article_number] do begin +
-            ShowMessageInLog(year, volume, page, format('Главная статья имеет уже использованный номер связи %s [%s %s %s] (%s)',[master_link, rubrika, author, title, link])); +
-         end; +
-      end; +
-   end; +
- +
-   procedure connect_subrubriks(Node:TTreeNode; root_rubrika: string); +
-   // собирает все статьи из сборной рубрики +
-   // на входе - узел главной статьи и имя сборной рубрики +
-   var x:integer; +
-       stroka:string; +
-       lastNode:TTreeNode; +
-       master:boolean; +
-       other_rubriks:string; +
-       rubr_position:integer; +
-   begin +
-      rubr_position := 0; +
-      for x:=0 to length(VolumeContent)-1 do begin +
-         with VolumeContent[x] do begin +
-            if compare_rubriks(rubrika,root_rubrika,other_rubriks,rubr_position) then begin // найдена статья для спецрубрики +
-               lastNode:=single_volume_tree.Items.AddChild(Node, IntToStr(x)+'_'+root_rubrika); +
-               used_as_article[rubr_position] := true; +
-               if (link='') then begin // определить мастер/слэйв +
-                  master:=false; +
-               end else begin +
-                  stroka:=Copy(link,1,1); +
-                  master:=stroka='а'; +
-               end; +
-               if master then connect_slaves(lastNode,link); +
-            end; +
-         end; +
-      end; +
-   end; +
-    { +
-    Нужно модифицировать алгоритм сборки оглавления: +
-    статья, у которой две сборные рубрики, появляется в оглавлении дважды. +
-    => признак used_as_article недостаточен для решения. +
-    нужен массив флагов для всех сборных рубрик "used_as_article #x" +
- +
-    Для того, чтобы не делать массив флагов зависимым от списка сборных рубрик, +
-    надо использовать принцип - "использовано как сборная рубрика для первой рубрики" и +
-    ограничить количество контролируемых сборных рубрик, например пятью. +
- +
-    used_as_article: array [0..5] of boolean; +
-    for i:=0 to 5 do used_as_slave[i]:=false; +
-    used_as_article[0] - использована как обычная статья (не из сборных рубрик) +
-    used_as_article[1] - использована как статья первой спецрубрики и т.д+
- +
-    } +
-begin +
-        single_volume_tree.Items.Clear; +
-        Node:=single_volume_tree.TopItem; +
-        for i:=0 to length(VolumeContent)-1 do begin +
-           with VolumeContent[i] do begin +
-              // определить мастер/слэйв +
-              if (link='') then begin +
-                 slave:=false; +
-                 master:=false; +
-              end else begin +
-                 stroka:=Copy(link,1,1); +
-                 master:=stroka='а'; +
-                 slave:=stroka='д'; +
-              end; +
-              // Узнать, относится ли рубрика к списку специальных +
-              special_rubrika:=false; +
-              for y:=0 to Rubriki.Count-1 do begin +
-                 if compare_rubriks(rubrika,Rubriki.Strings[y],other_rubriks, pos_found) then begin +
-                    special_rubrika:=true; +
-                    // проверить, что найдена сборная рубрикапо которой статья ещё не собиралась +
-                    if not used_as_article[pos_found] then begin +
-                       stroka_spec:=Rubriki.Strings[y]; // запомнить название спецрубрики, т.к. рубрика может быть сложносочинённой +
-                       break; +
-                    end else begin pos_found:=0; stroka_spec:=''; end; +
-                 end; +
-              end; +
-              // на выходе - признак, что есть спецрубрика+
-              // stroka_spec - только для случая, когда найдена неиспользованная рубрика +
-              // pos_found - тоже только тогда, когда найдена неиспользованная рубрика +
-              if special_rubrika then begin +
-                 // если найдена спецрубрика и она неиспользованная - подключить спецрубрики +
-                 if pos_found > 0 then begin +
-                    if not used_as_article[pos_found] then begin // спецрубрики строятся даже по слэйвам (обложки, вкладки) +
-                       lastNode:=single_volume_tree.Items.Add(Node, IntToStr(i)+'_'+stroka_spec); // добавить спецрубрику +
-                       connect_subrubriks(lastNode,stroka_spec); +
-                    end; +
-                 end; +
-              end else begin +
-                 if not (used_as_article[1]) and not (used_as_slave) and not slave then begin +
-                    lastNode:=single_volume_tree.Items.Add(Node, IntToStr(i)); // добавить статью +
-                    used_as_article[1]:=true; +
-                    if master then connect_slaves(lastNode,link); +
-                 end; +
-              end; +
-           end; +
-        end; +
-        // проверка на "orphan slaves" - одинокие подвёрстки +
-        for i:=0 to length(VolumeContent)-1 do begin +
-           with VolumeContent[i] do begin +
-              if (link='') then begin // определить мастер/слэйв +
-                 slave:=false; +
-              end else begin +
-                 stroka:=Copy(link,1,1); +
-                 slave:=stroka='д'; +
-              end; +
-              if not (used_as_slave) and slave then begin +
-                 stroka:=link; +
-                 Delete(stroka,1,1); // получить соответствующий мастер-линк +
-                 stroka:= 'а' + stroka; +
-                 ShowMessageInLog(year, volume, page, format('Нет главной статьи (%s) для подвёрстки [%s %s %s] (%s)',[stroka, rubrika, author, title, link])); +
-              end; +
-           end; +
-        end; +
-end; +
- +
-function TForm1.compare_rubriks(rubriki, test_string:string; var other_rubriks:string; var pos_found:integer):boolean; +
-//сравнение рубрик - rubriki - набор рубрик для статьи (разделён " | ") +
-//                   test_string - искомая рубрика +
-//        возвращает other_rubriks - набор рубрик без искомой рубрики (разделитель " | ") +
-//        возвращает pos_found - порядковый номер найденной рубрики в наборе рубрик +
-var temp:string; +
-    position:integer; +
-    counter:integer; +
-begin +
-   other_rubriks:=''; +
-   pos_found := 0; +
-   counter := 0; +
-   if rubriki=test_string then begin result:=true; pos_found := 1; exit end; +
-   if Pos('|',rubriki)=0 then begin result:=false; exit end; +
- +
-   rubriki:=StringReplace(rubriki, ' | ', '|', [rfReplaceAll]); // получено в вычищенном виде при сборке +
- +
-   result:=false; +
-   repeat +
-      position:=Pos('|',rubriki); +
-      if position>0 then begin +
-         temp:=Copy(rubriki,1,position-1); // скопировать кусок от начала до найденного "|" +
-         Delete(Rubriki,1,position); // удалить в рубриках всё, до найденного "|", включая разделитель +
-         inc(counter); +
-         if temp=test_string +
-            then begin // рубрика обнаружена +
-               pos_found := counter; +
-               result:=true; +
-            end else begin // записать найденную рубрику в список "другие рубрики" +
-               if other_rubriks='' +
-                  then other_rubriks:=temp +
-                  else other_rubriks:=format('%s | %s',[other_rubriks, temp]); +
-            end; +
-      end; +
-   until position=0; +
-   temp:=rubriki; // проверить оставшийся кусок +
-   inc(counter); +
-   if temp=test_string +
-      then begin  // рубрика обнаружена +
-         pos_found := counter; +
-         result:=true +
-      end else begin // записать найденную рубрику в список "другие рубрики" +
-         if other_rubriks='' +
-            then other_rubriks:=temp +
-            else other_rubriks:=format('%s | %s',[other_rubriks, temp]); +
-      end; +
-end; +
- +
-procedure TForm1.ExportHTML(all:boolean); +
-var oldLevel:integer; +
-    curNode:TTreeNode; +
-    x, y: integer; +
-    pos_found:integer; +
-    file_content_name: string; +
-    special_rubrika:boolean; +
-    stroka,stroka_spec,other_rubriks:string; +
-    Flags: OLEVariant; +
-    One_Volume_Content: TStringList; +
-    article_number: integer; +
-    rubrika_name: string; +
-    year_vol_str, str_vol : string; +
-    CurElement : ContentElement; +
-begin +
-    curNode:=single_volume_tree.TopItem; +
-    oldLevel:=-1; +
-    One_Volume_Content := TStringList.Create; +
-    if all then begin +
-       with VolumeContent[1] do begin +
-          if (year = '1992') and  (volume = '05') then begin +
-             year_vol_str := '1992_05_06'; +
-             str_vol := '05-06'; +
-          end else begin +
-             year_vol_str := year + '_' + volume; +
-             str_vol := volume; +
-          end; +
-          One_Volume_Content.Add(format('<ul><h1 STYLE="{clear: left; PAGE-BREAK-BEFORE: always}"><a href="%1:s/%2:s.djvu" name="nomer_%2:s">Наука и Жизнь №%0:s, %1:s</a></h1></ul>',[str_vol,year,year_vol_str])); +
-          if FileExists(prog_path+format('face/%0:s.jpg',[year_vol_str])) +
-             then One_Volume_Content.Add(format('<a href="%0:s/%1:s.djvu"><img src="face/%1:s.jpg" align=right hspace=10 border=0></a>',[year, year_vol_str])) +
-             else One_Volume_Content.Add(format('<a href="%0:s/%1:s.djvu"><img src="face/unknown.jpg" align=right hspace=10 border=0></a>',[year, year_vol_str])); +
-       end; +
-    end else begin +
-       One_Volume_Content.Add('<LINK REL="stylesheet" TYPE="text/css" HREF="all_content.css" TITLE="style">'); +
-    end; +
-    while curNode <> nil do begin +
-       if oldLevel<curNode.Level then begin // проставить <ul> +
-          for x:=1 to curNode.Level-oldLevel do begin +
-             One_Volume_Content.Add('<ul>'); +
-          end; +
-       end; +
-       if oldLevel>curNode.Level then begin // проставить </ul> +
-          for x:=1 to oldLevel-curNode.Level do begin +
-             One_Volume_Content.Add('</ul>'); +
-          end; +
-       end; +
-       // тут будет передаваться инфа о том, какая рубрика в данной статье является сборной. +
-       // передаваться в виде s1 (s2, s3, s4, s5 и т.д.) +
-       if pos('_',curNode.Text)=0 then begin +
-          article_number := StrToInt(curNode.Text); +
-          rubrika_name :=''; +
-       end else begin +
-          article_number := strToInt(copy(CurNode.Text,1,pos('_',curNode.Text)-1)); +
-          rubrika_name := copy(CurNode.Text,pos('_',curNode.Text)+1,length(curnode.text)-pos('_',curNode.Text)+1); +
-       end; +
-       with VolumeContent[article_number] do begin +
-          CurElement := ContentElement.Create(rubrika, author, title, page, link, volume, year); +
-          if (year = '1992') and  (volume = '05') then begin +
-             year_vol_str := '1992_05_06'; +
-             str_vol := '05-06'; +
-          end else begin +
-             year_vol_str := year + '_' + volume; +
-             str_vol := volume; +
-          end; +
-          if rubrika_name <> '' then begin +
-             special_rubrika:=true; // рубрика относится к списку специальных +
-             compare_rubriks(rubrika,rubrika_name,other_rubriks,pos_found); +
-             stroka_spec:=rubrika_name; // запомнить название спецрубрики, т.к. рубрика может быть сложносочинённой +
-          end else begin +
-             special_rubrika:=false; +
-          end; +
-          if chk_debug_mode.Checked then begin // режим вывода отладочного оглавления +
-             if special_rubrika and (curNode.Level=0) then begin +
-                stroka:=format('[%s] <font color=red> - сборная рубрика</font>',[stroka_spec]) +
-             end else begin; // вывести всю инфу по ссылке +
-                stroka:=''; +
-                if (rubrika <> '') then stroka := '[<font color=blue>' + rubrika + '</font>] '; +
-                if (author <> '') then stroka := stroka + '(<font color=green>' + author + '</font>) — '; +
-                if (title <> '') then stroka := stroka + title + ' '; +
-                if stroka = '' then stroka := '<font color=blue><i>нет информации</i></font> '; +
-                if (link <> ''+
-                   then stroka := stroka + '(стр. '+ page + ', связь "<font color=red>' + link + '</font>")' +
-                   else stroka := stroka + '(стр. '+ page + ')'; +
-             end; +
-          end else begin // обычный режим вывода оглавления +
-             if all then begin // вывод сборного оглавления +
-                if special_rubrika then begin // спецрубрика +
-                   if (curNode.Level=0) then // спецрубрика в корне +
-                      stroka:=format('[<font color=blue>%s</font>]',[stroka_spec]) +
-                   else begin // статья в спецрубрике +
-                      if stroka_spec <> rubrika then begin // статья со сложносочинённой рубрикой +
-                         if (author='') then begin // other_rubriks +
-                            if (title=''+
-                               then stroka:=format('[<font color=blue>%s</font>]',[other_rubriks]) +
-                               else stroka:=format('[<font color=blue>%s</font>] — %s',[other_rubriks, title]); +
-                         end else begin +
-                            if (title=''+
-                               then stroka:=format('[<font color=blue>%s</font>] (<font color=green>%s</font>)',[other_rubriks, author]) +
-                               else stroka:=format('[<font color=blue>%s</font>] (<font color=green>%s</font>) — %s',[other_rubriks, author, title]); +
-                         end; +
-                      end else begin +
-                         if (author='') then begin +
-                            if (title=''+
-                               then stroka:=stroka_spec +
-                               else stroka:=title; +
-                         end else begin +
-                            if (title=''+
-                               then stroka:=format('(<font color=green>%s</font>)',[author]) +
-                               else stroka:=format('(<font color=green>%s</font>) — %s',[author, title]); +
-                         end; +
-                      end; +
-                   end; +
-                end else begin // обычная рубрика +
-                   if (rubrika='') then begin +
-                      if (author='') then begin +
-                         if (title='') then stroka:='-=*=-' // заменитель для пустой ссылки +
-                         else stroka:=title; +
-                      end else begin +
-                         if (title='') then stroka:=format('(<font color=green>%s</font>)',[author]) +
-                         else stroka:=format('(<font color=green>%s</font>) — %s',[author, title]); +
-                      end; +
-                   end else begin // есть название рубрики +
-                      if (author='') then begin // но нет автора +
-                         if (title='') then stroka:=format('[<font color=blue>%s</font>]',[rubrika]) +
-                         else stroka:=format('[<font color=blue>%s</font>] — %s',[rubrika,title]); +
-                      end else begin +
-                         if (title='') then stroka:=format('(<font color=green>%s</font>)',[author]) +
-                         else stroka:=format('(<font color=green>%s</font>) — %s',[author, title]); +
-                      end; +
-                   end; +
-                end; +
-             end else begin // вывод оглавления для одного номера +
-                if special_rubrika then begin // спецрубрика +
-                   if (curNode.Level=0) then // спецрубрика в корне +
-                      stroka:=format('[%s]',[stroka_spec]) +
-                   else begin // статья в спецрубрике +
-                      if stroka_spec <> rubrika then begin // статья со сложносочинённой рубрикой +
-                         if (author='') then begin // other_rubriks +
-                            if (title=''+
-                               then stroka:=format('[%s]',[other_rubriks]) +
-                               else stroka:=format('[%s] — %s',[other_rubriks, title]); +
-                         end else begin +
-                            if (title=''+
-                               then stroka:=format('[%s] — %s',[other_rubriks, author]) +
-                               else stroka:=format('[%s] — %s — %s',[other_rubriks, author, title]); +
-                         end; +
-                      end else begin +
-                         if (author='') then begin +
-                            if (title=''+
-                               then stroka:=stroka_spec +
-                               else stroka:=title; +
-                         end else begin +
-                            if (title=''+
-                               then stroka:=author +
-                               else stroka:=format('%s — %s',[author, title]); +
-                         end; +
-                      end; +
-                   end; +
-                end else begin // обычная рубрика +
-                   if (rubrika='') then begin +
-                      if (author='') then begin +
-                         if (title='') then stroka:='-=*=-' // заменитель для пустой ссылки +
-                         else stroka:=title; +
-                      end else begin +
-                         if (title='') then stroka:=author +
-                         else stroka:=format('%s — %s',[author, title]); +
-                      end; +
-                   end else begin // есть название рубрики +
-                      if (author='') then begin // но нет автора +
-                         if (title='') then stroka:=format('[%s]',[rubrika]) +
-                         else stroka:=format('[%s] — %s',[rubrika,title]); +
-                      end else begin +
-                         if (title='') then stroka:=author +
-                         else stroka:=format('%s — %s',[author, title]); +
-                      end; +
-                   end; +
-                end; +
-             end; +
-          end; +
-          if all +
-             then stroka:=format('<li><a href="%0:s/%1:s.djvu#%2:s">%3:s</a></li>',[year,year_vol_str,page,stroka]) +
-             else stroka:=format('<li><a href="#%s">%s</a></li>',[page,stroka]); +
-          One_Volume_Content.Add(stroka); +
-          CurElement.Free; +
-       end; +
-       oldLevel:=curNode.Level; +
-       curNode:=curNode.GetNext; +
-    end; +
-    for x:=1 to oldLevel+1 do begin // проставить завершающие </ul> +
-       One_Volume_Content.Add('</ul>'); +
-    end; +
-    //if all then begin +
-       One_Volume_Content.SaveToStream(AllContent); +
-    {end else begin +
-       file_content_name:=prog_path+edt_volumes.Items[edt_volumes.ItemIndex]+'.htm'; +
-       One_Volume_Content.SaveToFile(file_content_name); +
-       // открыть созданный Html во встроенном редакторе +
-       Flags := 0; +
-       html_preview.Navigate(WideString(file_content_name), Flags, Flags, Flags, Flags); +
-       if chk_embed_bookmarks.Checked then begin +
-          ShellExecute(GetDesktopWindow(), 'open', PChar(prog_path + 'make.bat'), +
-          PChar(file_content_name + ' ' + edt_volumes.Items[edt_volumes.ItemIndex] + '.djvu ' + edt_volumes.Items[edt_volumes.ItemIndex] + '.new.djvu'), +
-          nil, SW_HIDE); +
-       end; +
-    end;  } +
-    One_Volume_Content.Free; +
-end; +
- +
-procedure TForm1.CreateTOC; // создание содержания для глобального оглавления по номерам +
-                            // используется инфа из edt_volumes +
-                            // результат записывается в file_Global_Volumes_Content +
-Const min_vol = 1; +
-      max_vol = 12; +
-      test_vol = max_vol + 1; +
-var MyContentTOC:TStringList; +
-    x,y,year_count:integer; +
-    user_year, user_vol:integer; +
-    str_vol, img_vol: string; +
-    style:string; +
-    all_volumes:array[min_year..max_year, min_vol..max_vol+1] of boolean; +
-    djvu_name:string; +
-    year_vol_str:string; +
-begin +
-    MyContentTOC:=TStringList.Create; +
-    FillChar(all_volumes,sizeof(all_volumes),0); // инициализировать таблицу номеров +
-    for x := 0 to edt_volumes.Items.Count-1 do begin // загрузить инфу по номерам и годам +
-       try +
-          user_year := StrToInt(copy(edt_volumes.Items[x],1,4)); +
-          user_vol := StrToInt(copy(edt_volumes.Items[x],6,2)); +
-       except +
-          ShowMessageInLog('----', '--', '---', format('Год или номер журнала являются некорректными (%s)',[edt_volumes.Items[x]])); +
-       end; +
-       if (user_year >= min_year) and (user_year <= max_year) and +
-       (user_vol >= min_vol) and (user_vol <= max_vol) +
-       then begin +
-          all_volumes[user_year, user_vol] := true; // есть конкретный номер +
-          all_volumes[user_year, test_vol] := true; // есть хоть один номер за определённый год +
-       end; +
-    end; +
-    // Создать заголовок +
-    MyContentTOC.Add('<LINK REL="stylesheet" TYPE="text/css" HREF="all_content.css" TITLE="style">'); +
-    MyContentTOC.Add(format('<ul><H1>Наука и Жизнь %d - %d</H1>',[min_year, max_year])); +
-    if chk_debug_mode.Checked then begin +
-       MyContentTOC.Add('<div align=right><font size=-1><i>Оглавление создано в режиме проверки, формат статей:'); +
-       MyContentTOC.Add('<br><b>[<font color=blue>Рубрика 1 | Рубрика 2</font>] - (<font color=green>Автор</font>) - Название статьи (страница, <font color=red>связь</font>)</b></i></font></div>'); +
-    end; +
-    // создать оглавление первого уровня (таблица номеров) +
-    MyContentTOC.Add('<table class="toc" style="font-size=-2" width=100% height=80% cellspacing=0 cellpadding=0>'); +
-    MyContentTOC.Add('<tr align=center><td class="hd">&nbsp;</td>'); +
-    for y := min_vol to max_vol do begin +
-       if y<10 +
-          then MyContentTOC.Add(format('<td class="hd">№0%d</td>',[y])) +
-          else MyContentTOC.Add(format('<td class="hd">№%d</td>',[y])); +
-    end; +
-    MyContentTOC.Add('</tr>'); +
-    for x := max_year downto min_year do begin +
-       if (x mod 2) = 0 then style := 'odd' else style := 'even'; +
-       if all_volumes[x,test_vol] +
-          then MyContentTOC.Add(format('<tr align=center class="%0:s"><td class="toc"><a href="#year_%1:d">%1:d год</a></td>',[style,x])) +
-          else MyContentTOC.Add(format('<tr align=center class="%0:s"><td class="toc">%1:d год</td>',[style,x])); +
-       for y := min_vol to max_vol do begin +
-          if y<10 +
-             then year_vol_str := format('%d_0%d',[x,y]) +
-             else year_vol_str := format('%d_%d',[x,y]); +
-          if (year_vol_str = '1992_05') and (all_volumes[x,y]) then begin // сдвоенный номер 1992 05-06 +
-             year_vol_str := '1992_05_06'; +
-             MyContentTOC.Add(format('<td class="toc" colspan=2><a href="#nomer_%s">-=&gt;&lt;=-</a></td>',[year_vol_str])); +
-             continue; // перейти к следующему номеру +
-          end; +
- +
-          if (x = 1992) and (y = 6) and (all_volumes[x,y-1]) then continue; // пропустить номер 1992 6 +
- +
-          if all_volumes[x,y] then begin +
-             MyContentTOC.Add(format('<td class="toc"><a href="#nomer_%s">-=&gt;&lt;=-</a></td>',[year_vol_str])) +
-          end else begin +
-             djvu_name := format('%s%d/%s.djvu',[prog_path,x,year_vol_str]); +
-             if (chk_debug_mode.checked) and (fileexists(djvu_name)) // в режиме проверки для имеющихся в DJVU номеров создавать ссылки в таблице номеров +
-                then MyContentTOC.Add(format('<td class="toc"><a href="%s">djvu</a></td>',[djvu_name])) +
-                else MyContentTOC.Add('<td class="toc">&nbsp;</td>'); +
-          end; +
-       end; +
-       MyContentTOC.Add('</tr>'); +
-    end; +
-    MyContentTOC.Add('</table></ul>'); +
- +
-    // создать оглавление второго уровня (годовые подшивки) +
-    MyContentTOC.Add('<ul>'); +
-    year_count:=0; +
-    for x:=max_year downto min_year do begin +
-       if all_volumes[x, test_vol] then begin // если есть номера для данного года +
-          inc(year_count); +
-          if (year_count mod 2) = 1 +
-             then MyContentTOC.Add(format('<H2 STYLE="{clear: left; PAGE-BREAK-BEFORE: always;}">Наука и Жизнь, %0:d год</H2><A NAME="year_%0:d"></A>',[x])) +
-             else MyContentTOC.Add(format('<H2 STYLE="{clear: left;}">Наука и Жизнь, %0:d год</H2><A NAME="year_%0:d"></A>',[x])); +
-          for y:=min_vol to max_vol do begin +
-             if y=7 then MyContentTOC.Add('<br STYLE="{clear: left;}">'); +
-             if (x = 1992) and (y = 6) and (all_volumes[x,y-1]) then continue; // пропустить номер 1992 6 +
-             if all_volumes[x,y] then begin // если есть конкретный номер, вывести для него ссылку +
-                if y<10 +
-                   then year_vol_str := format('%d_0%d',[x,y]) +
-                   else year_vol_str := format('%d_%d',[x,y]); +
- +
-                if y < 10 then str_vol := format('0%d',[y]) else str_vol := format('%d',[y]); +
- +
-                if (year_vol_str = '1992_05') then begin +
-                   str_vol := '05-06'; +
-                   year_vol_str := '1992_05_06'; +
-                end; +
- +
-                if FileExists(format('%sface/%s_mini.jpg',[prog_path,year_vol_str])) +
-                   then img_vol := format('%s_mini.jpg',[year_vol_str]) +
-                   else img_vol:='unknown_mini.jpg'; +
-                MyContentTOC.Add(format( +
-                   '<table border=0 align=left><tr align=center><td><a href="#nomer_%3:s">'+
-                   '<img src="face/%2:s" border=0></a></td></tr><tr align=center><td>'+
-                   '<a href="#nomer_%3:s">№%1:s, %0:d</a></td></tr></table>', +
-                   [x,str_vol,img_vol,year_vol_str])); +
-             end else begin // номера нет - вывести затычку +
-                if y < 10 then str_vol := format('0%d',[y]) else str_vol := format('%d',[y]); +
-                img_vol := 'absent_mini.gif'; +
-                MyContentTOC.Add(format( +
-                   '<table border=0 align=left><tr align=center><td>'+
-                   '<img src="face/%2:s" border=0></td></tr><tr align=center><td>'+
-                   '&nbsp;</td></tr></table>', +
-                   [x,str_vol,img_vol])); +
-             end; +
-          end; +
-       end; +
-    end; +
-    MyContentTOC.Add('</ul>'); +
-    MyContentTOC.SaveToStream(file_Global_Volumes_Content); +
-    MyContentTOC.Free; +
-end; +
- +
-procedure TForm1.Global_Content_Create(Sender: TObject); +
-  Procedure per_volumes; // создание глобального оглавления по номерам (all_content.htm) +
-  var Values: OLEVariant; +
-    ISheet: Excel8TLB._Worksheet; +
-    IRange: Excel8TLB.Range; +
-    i,z,j: integer; +
-    Flags: OLEVariant; +
-  begin +
-  if Assigned(IWorkbook) then +
-    //try +
-      ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-      file_Global_Volumes_Content:=TFileStream.Create(prog_path+'all_content.htm', fmCreate); +
-      AllContent:=TMemoryStream.Create; +
-      tree_preview.items.Clear; +
-      try +
-        local_progress.Min:=0; +
-        local_progress.max:=edt_volumes.Items.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        for z:=edt_volumes.Items.Count-1 downto 0 do begin // пройтись по всем выпускам +
-           local_progress.StepIt; +
-           IRange := ISheet.Range['vol_'+edt_volumes.Items[z], EmptyParam]; +
-           Values := IRange.Value; +
-           SetLength(VolumeContent,IRange.Rows.Count); +
-           for i := 1 to IRange.Rows.Count do begin +
-             with VolumeContent[i-1] do begin +
-                rubrika := Values[i, 1]; +
-                author := Values[i, 2]; +
-                title := Values[i, 3]; +
-                page := Values[i, 4]; +
-                link := Values[i, 5]; +
-                volume := Values[i, 6]; +
-                year := Values[i, 7]; +
-                used_as_slave := false; +
-                for j :=1 to max_complex_rubriks do used_as_article[j] := false; +
-                //stroka:= format('%s | %s | %s | %s | %s | %s | %s', [rubrika, author, title, page, link, volume, year]); +
-             end; +
-           end; +
-           MakeContent; +
-           ExportHTML(make_global); +
-        end; +
-        local_progress.StepIt; +
-        CreateTOC; +
-        local_progress.Position:=local_progress.Min; +
-        file_Global_Volumes_Content.CopyFrom(AllContent,0); // скопировать всё оглавление в файл с оглавлением +
-      finally +
-        IRange := nil; +
-        ISheet := nil; +
-        AllContent.Free; +
-        file_Global_Volumes_Content.Free; +
-        tree_preview.Items.Clear; +
-        single_volume_tree.Items.Clear; +
-        // открыть созданный Html во встроенном редакторе +
-        Flags := 0; +
-        html_preview.Navigate(WideString(prog_path+'all_content.htm'), Flags, Flags, Flags, Flags); +
-      end; +
-    //except +
-      //raise Exception.Create('Не могу прочитать данные в массив!'); +
-    //end; +
-  end; +
-  Procedure per_authors; // создание глобального авторского указателя (all_authors.htm) +
-//  type all_triplets_element: +
-  var Values: OLEVariant; +
-    ISheet, ISheet_auth_index, ISheet_authors, ISheet_triplet: Excel8TLB._Worksheet; +
-    articles: array of TMyContent; +
-    auth_index:array of index_element; +
-    authors: array of authors_element; +
-    triplets: array of triplets_element; +
-    odd_even:boolean; +
-    min_tripl, max_tripl: integer; // индексы для простановки диапазонов триплетов +
-    toc_triplets:array [ord('А')..ord('Я'), 0..max_toc_triplet] of string; // столбец '0' - признак, что столбец заполнен +
-    prevIndex, page_counter, rows_counter : integer; +
- +
-    vYear, vMonth, vAuthor, prevValue, vRubrika: OLEVariant; +
-    x,first,last:integer; +
-    stroka, prevStroka:string; +
-    auth_index_counter, // счётчик авторских статей +
-    authors_counter, // счётчик уникальных авторов +
-    triplet_counter:integer; // счётчик триплетов +
-    Authors_TOC:TStringList; // место для создания главной таблицы (верхний уровень) +
-    Authors_Names:TStringList; // место для создания списка фамилий (средний уровень) +
-    Authors_Articles:TStringList;// место для создания блоков ссылок на статьи (нижний уровень) +
-    IRange: Excel8TLB.Range; +
-    i,j,z: integer; +
-    Flags: OLEVariant; +
-    year_vol_str, str_vol: string; +
- +
-  begin +
-  if Assigned(IWorkbook) then +
-    try +
-      ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-      ISheet_auth_index := IWorkbook.Worksheets.Item['Авторы'] as Excel8TLB._Worksheet; +
-      ISheet_authors := IWorkbook.Worksheets.Item['Авторы (свод)'] as Excel8TLB._Worksheet; +
-      ISheet_triplet := IWorkbook.Worksheets.Item['Триплеты'] as Excel8TLB._Worksheet; +
- +
-      Authors_TOC := TStringList.Create; // место для создания главной таблицы (верхний уровень) +
-      Authors_Names := TStringList.Create; // место для создания списка фамилий (средний уровень) +
-      Authors_Articles := TStringList.Create; // место для создания блоков ссылок на статьи (нижний уровень) +
- +
-      file_All_Authors_Index:=TFileStream.Create(prog_path+'all_authors.htm', fmCreate); +
-      try +
-        // создать конечный перечень - имя автора (заголовок, ссылка вида #author_), перечень статей этого автора. +
- +
-        // загрузить лист одержание" +
-        IRange := ISheet.UsedRange[0]; +
-        Values := IRange.Value; +
-        SetLength(Articles,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Содержание"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with Articles[i] do begin +
-             rubrika := Values[i, 1]; +
-             author := Values[i, 2]; +
-             title := Values[i, 3]; +
-             page := Values[i, 4]; +
-             link := Values[i, 5]; +
-             volume := Values[i, 6]; +
-             year := Values[i, 7]; +
-          end; +
-        end; +
- +
-        // загрузить лист "Авторы" +
-        IRange := ISheet_auth_index.UsedRange[0]; +
-        Values := IRange.Value; +
-        Setlength(auth_index,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Авторы"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with auth_index[i] do begin +
-             name := Values[i, 1]; +
-             index := Values[i, 2]; +
-          end; +
-        end; +
- +
-        // загрузить лист "Авторы (свод)" +
-        IRange := ISheet_authors.UsedRange[0]; +
-        Values := IRange.Value; +
-        Setlength(authors,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Авторы (свод)"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with authors[i] do begin +
-             name := Values[i, 1]; +
-             index := Values[i, 2]; +
-             count:= Values[i, 3]; +
-             triplet:= Values[i, 4]; +
-             surname:= Values[i, 5]; +
-          end; +
-        end; +
- +
-        // загрузить лист "Триплеты" +
-        IRange := ISheet_triplet.UsedRange[0]; +
-        Values := IRange.Value; +
-        Setlength(triplets,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Триплеты"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with triplets[i] do begin +
-             triplet := Values[i, 1]; +
-             index := Values[i, 2]; +
-             count:= Values[i, 3]; +
-             letter:= Values[i, 4]; +
-             if not (letter[1] in ['А'..'Я']) then letter:='Ъ'; // подменить ошибочные триплеты на Ъ +
-          end; +
-        end; +
- +
-        Authors_TOC.add('<LINK REL="stylesheet" TYPE="text/css" HREF="all_content.css" TITLE="style">'); +
-        Authors_TOC.add('<ul>'); // ведущий UL +
-         // построить список всех триплетов +
-        local_progress.Min:=0; +
-        local_progress.max:=length(triplets)-1; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Построение списка триплетов...'; +
-        x:=0; +
-        //odd_even:=true; +
-        // загрузить массив триплетов +
-        for i:= ord('А') to ord('Я') do begin +
-           for x:=0 to max_toc_triplet do begin +
-              toc_triplets[i,x] := ''; // обнулить массив. +
-           end; +
-        end; +
-        { найти диапазон для очередной буквы +
-          по найденному диапазону триплетов построить 8 интервалов +
-          если кол-во триплетов меньше или равно max_toc_triplet - "тупой" алгоритм +
-          если кол-во триплетов больше max_toc_triplet - "хитрый" алгоритм +
-          приписать триплетам соостветствующие индексы интервалов +
-        } +
-        first:=1; prevStroka:=triplets[1].letter; +
-        for i := 1 to length(triplets)-1 do begin +
-           if (prevStroka <> triplets[i].letter) then begin // пошла новая буква +
-              last:=i-1; // конец диапазона - предыдущий триплет +
-              toc_triplets[ord(prevStroka[1]),0] := '*'; // проставить признак, что такая буква есть. +
-              if (last-first+1)<=max_toc_triplet then begin // кол-во триплетов меньше или равно max_toc_triplet - "тупой" алгоритм +
-                 for x:=1 to last-first+1 do begin +
-                    toc_triplets[ord(prevStroka[1]),x]:=triplets[first+x-1].triplet; +
-                    triplets[first+x-1].toc_triplets_index:=x; // приписать триплетам соостветствующие индексы интервалов +
-                 end; +
-              end else begin // хитрый алгоритм +
-                 for x:=1 to max_toc_triplet do begin +
-                    min_tripl:=first+round((last-first+1)/max_toc_triplet*(x-1)); +
-                    max_tripl:=first+round((last-first+1)/max_toc_triplet*(x))-1; +
-                    for z:=min_tripl to max_tripl do begin +
-                       triplets[z].toc_triplets_index:=x; // приписать триплетам соостветствующие индексы интервалов +
-                    end; +
-                    if min_tripl = max_tripl +
-                       then toc_triplets[ord(prevStroka[1]),x] := triplets[min_tripl].triplet +
-                       else toc_triplets[ord(prevStroka[1]),x] := triplets[min_tripl].triplet + ' - ' + triplets[max_tripl].triplet; +
-                 end; +
-              end; +
-              first:=i; // запомнить начало нового диапазона +
-           end; +
-           prevStroka := triplets[i].letter; +
-        end; +
-        i:=length(triplets); +
-        last:=i-1; // конец диапазона - последний элемент +
-        toc_triplets[ord(prevStroka[1]),0] := '*'; // проставить признак, что такая буква есть. +
-        if (last-first+1)<=max_toc_triplet then begin // кол-во триплетов меньше или равно max_toc_triplet - "тупой" алгоритм +
-           for x:=1 to last-first+1 do begin +
-              toc_triplets[ord(prevStroka[1]),x]:=triplets[first+x-1].triplet; +
-              triplets[first+x-1].toc_triplets_index:=x; // приписать триплетам соостветствующие индексы интервалов +
-           end; +
-        end else begin // хитрый алгоритм +
-           for x:=1 to max_toc_triplet do begin +
-              min_tripl:=first+round((last-first+1)/max_toc_triplet*(x-1)); +
-              max_tripl:=first+round((last-first+1)/max_toc_triplet*(x))-1; +
-              for z:=min_tripl to max_tripl do begin +
-                 triplets[z].toc_triplets_index:=x; // приписать триплетам соостветствующие индексы интервалов +
-              end; +
-              if min_tripl = max_tripl +
-                 then toc_triplets[ord(prevStroka[1]),x] := triplets[min_tripl].triplet +
-                 else toc_triplets[ord(prevStroka[1]),x] := triplets[min_tripl].triplet + ' - ' + triplets[max_tripl].triplet; +
-           end; +
-        end; +
-        odd_even := true; +
-        Authors_TOC.add('<h1>Авторский указатель</h1>'); +
-        Authors_TOC.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5>'); +
-        for i:= ord('А') to ord('Я') do begin +
-           if toc_triplets[i,0] = '' then continue; // пропустить пустые буквы +
-           odd_even := not odd_even; +
-           if odd_even +
-              then Authors_TOC.Add('<tr class="even"><td class="hd">' + chr(i) + '</td>'+
-              else Authors_TOC.Add('<tr class="odd"><td class="hd">' + chr(i) + '</td>'); +
-           for x:=1 to max_toc_triplet do begin +
-              if (toc_triplets[i,x] <> ''+
-                 then Authors_TOC.Add(format('<td class="toc"><a href="#triplet_%1:d_%2:d">%0:s</a></td>',[toc_triplets[i,x],i,x])) +
-                 else Authors_TOC.Add('<td class="toc">&nbsp;</td>'); +
-           end; +
-           Authors_TOC.Add('</tr>'); +
-           local_progress.StepIt; +
-        end; +
-        Authors_TOC.Add('</table>'); +
- +
-        // построить список всех фамилий +
-        Authors_Names.add('<div STYLE="{PAGE-BREAK-BEFORE: always}"></div>'); +
-        local_progress.Min:=0; +
-        local_progress.max:=length(triplets)-1; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step := 1; +
-        statusbar1.simpletext := 'Построение списка фамилий...'; +
-        z := 0; +
-        page_counter := 0; +
-        odd_even := false; +
-        i := 1; prevStroka := triplets[i].letter + '_' + IntToStr(triplets[i].toc_triplets_index); +
-        Authors_Names.Add(format('<h2><a name="triplet_%1:d_%2:d">%0:s</a></h2>',[toc_triplets[ord(triplets[i].letter[1]),triplets[i].toc_triplets_index],ord(triplets[i].letter[1]),triplets[i].toc_triplets_index])); +
-        inc(page_counter,27); // высота заголовка - 27 пунктов +
-        Authors_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-        for i:= 1 to length(triplets)-1 do begin +
-           if (prevStroka <> triplets[i].letter + '_' + IntToStr(triplets[i].toc_triplets_index)) then begin // пошёл новый интервал +
-              for x:=z to 2 do begin +
-                 Authors_Names.Add('<td class="toc">&nbsp;</td>'); // дописать пустые ячейки до трёх +
-              end; +
-              Authors_Names.Add('</tr></table>'); +
-              if (page_counter>220-27) then begin // высота страницы - 290 пунктов +
-                 z := 0; +
-                 page_counter := 0; +
-                 odd_even:=false; +
-                 Authors_Names.Add(format('<h2 style="{page-break-before: always}"><a name="triplet_%1:d_%2:d">%0:s</a></h2>',[toc_triplets[ord(triplets[i].letter[1]),triplets[i].toc_triplets_index],ord(triplets[i].letter[1]),triplets[i].toc_triplets_index])); +
-              end else +
-                 Authors_Names.Add(format('<h2><a name="triplet_%1:d_%2:d">%0:s</a></h2>',[toc_triplets[ord(triplets[i].letter[1]),triplets[i].toc_triplets_index],ord(triplets[i].letter[1]),triplets[i].toc_triplets_index])); +
-              inc(page_counter,27); // высота заголовка - 27 пунктов +
-              rows_counter := 0; +
-              Authors_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-              z := 0; +
-              odd_even:=false; +
-           end; +
-           for x := triplets[i].index to (triplets[i].index + triplets[i].count - 1) do begin // вывести все фамилии для триплета +
-              if z = 3 then begin // запустить новую строку +
-                 inc(page_counter,9);  // высота строки - 9 пунктов +
-                 inc(rows_counter); +
-                 z := 0; +
-                 if odd_even +
-                    then Authors_Names.Add('</tr><tr class="odd">'+
-                    else Authors_Names.Add('</tr><tr class="even">'); +
-                 odd_even:=not odd_even; +
-              end; +
-              if (page_counter>220) and (rows_counter>1) then begin // высота страницы - 290 пунктов +
-                 Authors_Names.Add('</tr></table>'); +
-                 z := 0; +
-                 page_counter := 0; +
-                 odd_even:=false; +
-                 Authors_Names.Add(format('<h2 style="{page-break-before: always}">%0:s</h2>',[toc_triplets[ord(triplets[i].letter[1]),triplets[i].toc_triplets_index]])); +
-                 inc(page_counter,27); // высота заголовка - 27 пунктов +
-                 Authors_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-              end; +
-              inc(z); +
-              Authors_Names.Add(format('<td class="toc" width="33%%"><a href="#author_%1:d">%0:s</a></td>',[authors[x].name, x])); +
-           end; +
-           local_progress.StepIt; +
-           prevStroka := triplets[i].letter + '_' + IntToStr(triplets[i].toc_triplets_index); +
-        end; +
-        Authors_Names.Add('</tr></table>'); +
- +
-        // построить список нижнего уровня +
-        local_progress.Min:=0; +
-        local_progress.max:=length(authors)-1; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Построение поавторского списка статей...'; +
-        Authors_Articles.add('<div STYLE="{PAGE-BREAK-BEFORE: always}"></div>'); +
-        for i := 1 to length(authors)-1 do begin +
-           stroka := format('<h2><a name="author_%0:d">%1:s</a></h2>',[i, authors[i].name]);; +
-           Authors_Articles.add(stroka); +
-           local_progress.StepIt; +
-           Authors_Articles.add('<ul>'); +
-           for x:=authors[i].index + authors[i].Count - 1 downto authors[i].index do begin // пройтись по всем записям индекса автора +
-              with articles[auth_index[x].index] do begin +
- +
-                 if (year = '1992') and  (volume = '05') then begin +
-                    year_vol_str := '1992_05_06'; +
-                    str_vol := '05-06'; +
-                 end else begin +
-                    year_vol_str := year + '_' + volume; +
-                    str_vol := volume; +
-                 end; +
- +
-                 stroka:=format('<li><a href="%0:s/%1:s.djvu#%2:s">%0:s №%3:s — ',[year, year_vol_str, page, str_vol]); +
-                 if (rubrika <> '') then stroka := stroka + '[<font color=blue>' + rubrika + '</font>] '; +
-                 if (author <> '') then stroka := stroka + '(<font color=green>' + author + '</font>) — '; +
-                 if (title <> '') then stroka := stroka + title + ' '; +
-                 stroka := stroka + '</a>'; +
- +
-                 Authors_Articles.Add(stroka); +
-              end; +
-           end; +
-           Authors_Articles.add('</ul>'); +
-        end; +
-        Authors_Articles.add('</ul>'); // конечный /UL +
-        statusbar1.simpletext:='Готово'; +
- +
-        Authors_TOC.SaveToStream(file_All_Authors_Index); +
-        Authors_Names.SaveToStream(file_All_Authors_Index); +
-        Authors_Articles.SaveToStream(file_All_Authors_Index); +
-      finally +
-        IRange := nil; +
-        ISheet := nil; +
-        ISheet_auth_index := nil; +
-        ISheet_authors := nil; +
-        ISheet_triplet := nil; +
-        setlength(articles,0); +
-        setlength(auth_index,0); +
-        setlength(authors,0); +
-        setlength(triplets,0); +
-        file_All_Authors_Index.Free; +
-        Authors_TOC.Free; // освободить место для создания главной таблицы (верхний уровень) +
-        Authors_Names.Free; // освободить место для создания списка фамилий (средний уровень) +
-        Authors_Articles.Free; // освободить место для создания блоков ссылок на статьи (нижний уровень) +
-        { +
-        // открыть созданный Html во встроенном редакторе +
-        Flags := 0; +
-        html_preview.Navigate(WideString(prog_path+'all_content.htm'), Flags, Flags, Flags, Flags); +
-        } +
-      end; +
-    except +
-      raise Exception.Create('Не могу прочитать данные в массив!'); +
-    end; +
-  end; +
-  Procedure per_rubrics; // создание глобального рубрикатора (all_rubrics.htm) +
-  var Values: OLEVariant; +
-    ISheet, ISheet_rubr_index, ISheet_rubriks: Excel8TLB._Worksheet; +
-    articles: array of TMyContent; +
-    rubr_index: array of rubr_index_element; +
-    rubriks: array of rubriks_element; +
- +
-    Sorted_rubriks:TStringList; +
-    Rubrik_Object:TRubr_Info; +
- +
-    odd_even:boolean; // хрень для полосатых таблиц +
-    page_counter, rows_counter : integer; +
-    x:integer; +
-    user_max_year, user_min_year : integer; // пределы для отображения таблиц ссылок +
-    stroka:string; +
-    Rubriks_TOC:TStringList; // место для создания главной таблицы (верхний уровень) +
-    Rubriks_Names:TStringList; // место для создания списка фамилий (средний уровень) +
-    Rubriks_Articles:TStringList;// место для создания блоков ссылок на статьи (нижний уровень) +
-    IRange: Excel8TLB.Range; +
-    i,z: integer; +
-    year_vol_str, str_vol:string; +
-    prev_group: integer; +
-    procedure show_table_rubrik(i:integer); // вывод таблицы со ссылками для регулярных рубрик +
-       Const min_vol = 1; +
-             max_vol = 12; +
-             test_vol = max_vol + 1; +
-       var x,y:integer; +
-           user_year, user_vol:integer; +
-           style:string; +
-           all_volumes:array[min_year..max_year, min_vol..max_vol+1] of integer; +
-              // если рубрики в номере нет, то значение равно нулю, +
-              // в противном случае - это номер страницы +
-              // последний столбец - количество номеров с рубриками в определённом году. +
-    begin +
-    // определить min_year, max_year для конкретной рубрики +
-    // +
- +
-    // Заполнить таблицу ссылок (all_volumes) для рубрики +
-    FillChar(all_volumes,sizeof(all_volumes),0); // инициализировать таблицу номеров +
-    for x := rubriks[i].index to rubriks[i].index+rubriks[i].count-1 do begin // прочесать все статьи для рубрики x +
-       user_year := strtoint(articles[rubr_index[x].index].year); // заполучить год, в котором статья +
-       user_vol := strtoint(articles[rubr_index[x].index].volume); // заполучить номер, в котором статья +
-       if (user_year >= min_year) and (user_year <= max_year) and +
-       (user_vol >= min_vol) and (user_vol <= max_vol) +
-       then begin +
-          if all_volumes[user_year, user_vol] = 0 then // если это первая статья данной рубрики в номере +
-             all_volumes[user_year, user_vol] := strtoint(articles[rubr_index[x].index].page); // запомнить номер страницы +
-          inc(all_volumes[user_year, test_vol]); // увеличить счётчик количества номеров в этом году +
-       end; +
-    end; +
- +
-    // Создать заголовок таблицы ссылок для рубрики +
-    //Rubriks_Articles.Add(format('<H1 STYLE="{PAGE-BREAK-BEFORE: always}">%s %d - %d</H1>',[rubriks[i].name, min_year, max_year])); +
-    Rubriks_Articles.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=0>'); +
-    Rubriks_Articles.Add('<tr align=center><td class="hd">&nbsp;</td>'); +
-    for y := min_vol to max_vol do begin +
-       if y<10 +
-          then Rubriks_Articles.Add(format('<td class="hd">№0%d</td>',[y])) +
-          else Rubriks_Articles.Add(format('<td class="hd">№%d</td>',[y])); +
-    end; +
-    Rubriks_Articles.Add('</tr>'); +
-    // просчитать пределы годов отображения +
-    for x := max_year downto min_year do begin +
-       user_max_year := x; +
-       if (all_volumes[x, test_vol] >0) then break; +
-    end; +
-    for x := min_year to max_year do begin +
-       user_min_year := x; +
-       if (all_volumes[x, test_vol] >0) then break; +
-    end; +
-    // вывести основную часть таблицы +
-    for x := user_max_year downto user_min_year do begin +
-       if (x mod 2) = 0 then style := 'odd' else style := 'even'; // полосатая таблица +
-       Rubriks_Articles.Add(format('<tr align=center class="%0:s"><td class="toc">%1:d год</td>',[style,x])); +
-       for y := min_vol to max_vol do begin +
-          if y < 10 +
-             then year_vol_str := format('%d_0%d',[x,y]) +
-             else year_vol_str := format('%d_%d',[x,y]); +
-          if (year_vol_str = '1992_05') then begin // сдвоенный номер 1992 05-06 +
-             year_vol_str := '1992_05_06'; +
-             if (all_volumes[x,y]>0) +
-                then Rubriks_Articles.Add(format('<td class="toc" colspan=2><a href="%0:d/%1:s.djvu#%2:d">-=&gt;&lt;=-</a></td>',[x, year_vol_str, all_volumes[x,y]])) +
-                else Rubriks_Articles.Add('<td class="toc" colspan=2>&nbsp;</td>'); +
-             continue; // перейти к следующему номеру +
-          end; +
-          if (x = 1992) and (y = 6) then continue; // пропустить номер 1992 6 +
-          if (all_volumes[x,y]>0) +
-             then Rubriks_Articles.Add(format('<td class="toc"><a href="%0:d/%1:s.djvu#%2:d">-=&gt;&lt;=-</a></td>',[x, year_vol_str, all_volumes[x,y]])) +
-             else Rubriks_Articles.Add('<td class="toc">&nbsp;</td>'); +
-       end; +
-       Rubriks_Articles.Add('</tr>'); +
-    end; +
-    Rubriks_Articles.Add('</table>'); +
- +
-    end; +
-  begin // собственно начало процедуры per_rubriks +
-  if Assigned(IWorkbook) then +
-    try +
-      ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-      ISheet_Rubr_index := IWorkbook.Worksheets.Item['Рубрики'] as Excel8TLB._Worksheet; +
-      ISheet_Rubriks := IWorkbook.Worksheets.Item['Рубрики (свод)'] as Excel8TLB._Worksheet; +
- +
-      Rubriks_TOC := TStringList.Create; // место для создания главной таблицы (верхний уровень) +
-      Rubriks_Names := TStringList.Create; // место для создания списка рубрик (средний уровень) +
-      Rubriks_Articles := TStringList.Create; // место для создания блоков ссылок на статьи (нижний уровень) +
- +
-      file_All_Rubriks_Index:=TFileStream.Create(prog_path+'all_rubriks.htm', fmCreate); +
-      try +
-        // создать конечный перечень - имя автора (заголовок, ссылка вида #Rubrika_), перечень статей в этой рубрике. +
- +
-        // загрузить лист "Содержание" +
-        IRange := ISheet.UsedRange[0]; +
-        Values := IRange.Value; +
-        SetLength(Articles,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Содержание"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with Articles[i] do begin +
-             rubrika := Values[i, 1]; +
-             author := Values[i, 2]; +
-             title := Values[i, 3]; +
-             page := Values[i, 4]; +
-             link := Values[i, 5]; +
-             volume := Values[i, 6]; +
-             year := Values[i, 7]; +
-          end; +
-        end; +
- +
-        // загрузить лист "Рубрики" +
-        IRange := ISheet_Rubr_index.UsedRange[0]; +
-        Values := IRange.Value; +
-        Setlength(Rubr_index,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Рубрики"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with Rubr_index[i] do begin +
-             name := Values[i, 1]; +
-             index := Values[i, 2]; +
-          end; +
-        end; +
- +
-        // загрузить лист "Рубрики (свод)" +
-        IRange := ISheet_Rubriks.UsedRange[0]; +
-        Values := IRange.Value; +
-        Setlength(Rubriks,IRange.Rows.Count+1); +
-        local_progress.Min:=0; +
-        local_progress.max:=IRange.Rows.Count; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Загрузка листа "Рубрики (свод)"...'; +
-        for i := 1 to IRange.Rows.Count do begin +
-          local_progress.stepit; +
-          with Rubriks[i] do begin +
-             name := Values[i, 1]; +
-             index := Values[i, 2]; +
-             count := Values[i, 3]; +
-             common := Values[i, 4]; +
-             group_number := Values[i, 5]; +
-             number := i; +
-          end; +
-        end; +
- +
-        // создать список рубрик, упорядоченный по алфавиту  "название рубрики" | "Исходный номер рубрики" +
-        Sorted_rubriks := TStringList.Create; +
-        for i := 1 to length(rubriks)-1 do begin +
-           Rubrik_Object := TRubr_Info.Create(rubriks[i]); +
-           sorted_rubriks.AddObject(Rubrik_Object.info.name, Rubrik_Object); +
-        end; +
-        sorted_rubriks.Sort; +
- +
-        // построить первую страницу (перечень групп рубрик и ссылка на алфавитный список рубрик) +
- +
-        Rubriks_TOC.add('<LINK REL="stylesheet" TYPE="text/css" HREF="all_content.css" TITLE="style">'); +
- +
-        Rubriks_TOC.add('<ul>'); // ведущий UL +
-        odd_even := true; +
-        //Rubriks_TOC.add('<h1>Рубрикатор</h2>'); +
-        Rubriks_TOC.add('<h2><a href="#Group_1">Группы рубрик</a></h2>'); +
-        Rubriks_TOC.add('<table class="stealth" style="font-size=-2" width=100% cellspacing=0 cellpadding=5>'); +
-        x := 1; +
-        repeat +
-           Rubriks_TOC.add('<tr align="center" valign="bottom" class="even">'); +
-           for i:=0 to 2 do begin +
-              if (x+i > length(Rubriks_Groups)-1) then continue; +
-              Rubriks_TOC.add(format('<td><a href="#Group_%0:d"><img src="face/group_%0:d.png" border=0></a></td>', [x+i])); +
-           end; +
-           Rubriks_TOC.add('</tr><tr align="center" valign="top" class="even">'); +
-           for i:=0 to 2 do begin +
-              if (x+i > length(Rubriks_Groups)-1) then continue; +
-              Rubriks_TOC.add(format('<td><a href="#Group_%0:d">%1:s</a>', [x+i, Rubriks_Groups[x+i].group])); +
-           end; +
-           Rubriks_TOC.add('</tr>'); +
-           inc(x,3); +
-        until (x > length(Rubriks_Groups)-1); +
-        Rubriks_TOC.add('</table>'); +
-        Rubriks_TOC.add('<h2><a href="#alphabet">Алфавитный список рубрик</a></h2>'); +
-        Rubriks_TOC.add('<table class="stealth" style="font-size=-2" width=100% cellspacing=0 cellpadding=5>'); +
-        Rubriks_TOC.add('<tr class="even"><td>'); +
- +
-        // построить список всех рубрик (группированный по темам) +
-        Rubriks_Names.add('<div STYLE="{PAGE-BREAK-BEFORE: always}"></div>'); +
-        local_progress.Min:=0; +
-        local_progress.max:=length(rubriks)-1; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step := 1; +
-        statusbar1.simpletext := 'Построение списка рубрик по группам...'; +
-        z := 0; +
-        page_counter := 0; +
-        odd_even := false; +
-        (*// на странице уже есть заголовок и список групп - надо учесть. +
-        inc(page_counter, 27); // высота заголовка - 27 пунктов +
-        inc(page_counter, 5 * (length(Rubriks_Groups)-1) ); // строки в списке - 5 пунктов +
-        *) +
-        prev_group:=0; // первая группа +
- +
-        Rubriks_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-        for i:= 1 to length(rubriks)-1 do begin +
-           if (Rubriks[i].group_number<>prev_group) then begin // сменилась группа рубрик +
-              if (rows_counter>0) then // игнорируем пустые таблицы +
-                 for x:=z to 2 do begin // закончить последнюю строку в таблице +
-                    Rubriks_Names.Add('<td class="toc">&nbsp;</td>'); // дописать пустые ячейки до трёх +
-                 end; +
-              Rubriks_Names.Add('</tr></table>'); // закрыть предыдущую таблицу +
-              z := 0; // снова инициализировать счётчик столбцов +
-              rows_counter := 0; +
-              //page_counter := 0; // снова инициализировать счётчик высоты +
-              odd_even := false; // снова инициализировать полосатость +
-              prev_group := Rubriks[i].group_number; // сменить текущую группу +
-              Rubriks_Names.add(format('<h2 style="{page-break-before: always}"><a name="Group_%d">%s</a></h2>',[prev_group, Rubriks_Groups[prev_group].group])); +
-              //inc(page_counter,27); // высота заголовка - 27 пунктов +
-              page_counter := 27; +
-              Rubriks_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); // открыть новую таблицу +
-           end; +
- +
-           if z = 3 then begin // запустить новую строку +
-              inc(page_counter,9);  // высота строки - 9 пунктов +
-              inc(rows_counter); +
-              z := 0; +
-              if odd_even +
-                 then Rubriks_Names.Add('</tr><tr class="odd">'+
-                 else Rubriks_Names.Add('</tr><tr class="even">'); +
-              odd_even:=not odd_even; +
-           end; +
-           if (page_counter>210) and (rows_counter>1) then begin // высота страницы - 210 пунктов +
-              Rubriks_Names.Add('</tr></table>'); +
-              z := 0; +
-              rows_counter := 0; +
-              page_counter := 0; +
-              odd_even:=false; +
-              Rubriks_Names.add(format('<h2 style="{page-break-before: always}">%s</h2>',[Rubriks_Groups[prev_group].group])); // повторить заголовок +
-              inc(page_counter,27); // высота заголовка - 27 пунктов +
-              Rubriks_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-           end; +
-           inc(z); +
-           Rubriks_Names.Add(format('<td class="toc" width="33%%"><a href="#Rubrika_%1:d">%0:s</a></td>',[Rubriks[i].name, i])); +
-           local_progress.StepIt; +
-        end; +
-        for x:=z to 2 do begin // закончить последнюю строку в таблице +
-           Rubriks_Names.Add('<td class="toc">&nbsp;</td>'); // дописать пустые ячейки до трёх +
-        end; +
-        Rubriks_Names.Add('</tr></table>'); +
- +
-        // построить список всех рубрик, без разбивки по группам рубрик (просто по алфавиту) +
- +
-        local_progress.Min:=0; +
-        local_progress.max:=sorted_rubriks.Count-1; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step := 1; +
-        statusbar1.simpletext := 'Построение алфавитного списка рубрик...'; +
-        z := 0; +
-        page_counter := 0; +
-        odd_even := false; +
-        prev_group :=ord(upcase(sorted_rubriks.Strings[0][1])); +
-        Rubriks_Names.add('<h2 style="{page-break-before: always}"><a name="alphabet">Алфавитный список рубрик</a></h2>'); +
-        inc(page_counter,27); // высота заголовка - 27 пунктов +
-        Rubriks_Names.add(format('<h2><a name="abc_%d">%s</a></h2>',[prev_group, upcase(sorted_rubriks.Strings[0][1])])); +
-        inc(page_counter,27); // высота заголовка - 27 пунктов +
-        Rubriks_TOC.add(format('Рубрики на: <a href="#abc_%d">%s</a>',[ord(upcase(sorted_rubriks.Strings[0][1])),upcase(sorted_rubriks.Strings[0][1])])); +
-        Rubriks_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-        for i:= 0 to sorted_rubriks.Count-1 do begin +
-           if (ord(upcase(sorted_rubriks.Strings[i][1]))<>prev_group) then begin // сменилась группа рубрик +
-              Rubriks_TOC.add(format(', <a href="#abc_%d">%s</a>',[ord(upcase(sorted_rubriks.Strings[i][1])),upcase(sorted_rubriks.Strings[i][1])])); +
-              for x:=z to 2 do begin // закончить последнюю строку в таблице +
-                 Rubriks_Names.Add('<td class="toc">&nbsp;</td>'); // дописать пустые ячейки до трёх +
-              end; +
-              Rubriks_Names.Add('</tr></table>'); // закрыть предыдущую таблицу +
-              //inc(page_counter,9);  // высота строки - 9 пунктов +
-              z := 0; // снова инициализировать счётчик столбцов +
-              rows_counter := 0; +
-              odd_even := false; // снова инициализировать полосатость +
-              prev_group := ord(upcase(sorted_rubriks.Strings[i][1])); // сменить текущую группу +
-              if (page_counter>220) then begin +
-                 page_counter := 0; +
-                 Rubriks_Names.add(format('<h2 STYLE="{PAGE-BREAK-BEFORE: always}"><a name="abc_%d">%s</a></h2>',[prev_group, upcase(sorted_rubriks.Strings[i][1])])); +
-              end else Rubriks_Names.add(format('<h2><a name="abc_%d">%s</a></h2>',[prev_group, upcase(sorted_rubriks.Strings[i][1])])); +
-              inc(page_counter,30); // высота заголовка - 27 пунктов +
-              Rubriks_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); // открыть новую таблицу +
-           end; +
- +
-           if z = 3 then begin // запустить новую строку +
-              inc(page_counter,10);  // высота строки - 9 пунктов +
-              inc(rows_counter); +
-              z := 0; +
-              if odd_even +
-                 then Rubriks_Names.Add('</tr><tr class="odd">'+
-                 else Rubriks_Names.Add('</tr><tr class="even">'); +
-              odd_even:=not odd_even; +
-           end; +
-           if (page_counter>220) and (rows_counter>1) then begin // высота страницы - 210 пунктов +
-              Rubriks_Names.Add('</tr></table>'); +
-              z := 0; +
-              rows_counter := 0; +
-              page_counter := 0; +
-              odd_even:=false; +
-              //Rubriks_Names.add('<div STYLE="{PAGE-BREAK-BEFORE: always}"></div>'); +
-              Rubriks_Names.add(format('<h2 STYLE="{PAGE-BREAK-BEFORE: always}">%s</h2>',[upcase(sorted_rubriks.Strings[i][1])])); +
-              Rubriks_Names.Add('<table class="toc" style="font-size=-2" width=100% cellspacing=0 cellpadding=5><tr class="odd">'); +
-              inc(page_counter,30); // высота заголовка - 27 пунктов +
-           end; +
-           inc(z); +
- +
-           Rubriks_Names.Add(format('<td class="toc" width="33%%"><a href="#Rubrika_%1:d">%0:s</a></td>',[sorted_rubriks.Strings[i], TRubr_Info(sorted_rubriks.Objects[i]).info.number])); +
-           local_progress.StepIt; +
-        end; +
-        for x:=z to 2 do begin // закончить последнюю строку в таблице +
-           Rubriks_Names.Add('<td class="toc">&nbsp;</td>'); // дописать пустые ячейки до трёх +
-        end; +
-        Rubriks_Names.Add('</tr></table>'); +
-        Rubriks_TOC.add('</td></tr></table>'); +
- +
-        // построить список нижнего уровня +
-        local_progress.Min:=0; +
-        local_progress.max:=length(Rubriks)-1; +
-        local_progress.Position:=local_progress.Min; +
-        local_progress.Step:=1; +
-        statusbar1.simpletext:='Построение поавторского списка статей...'; +
-        Rubriks_Articles.add('<div STYLE="{PAGE-BREAK-BEFORE: always}"></div>'); +
-        prev_group := 0; +
-        for i := 1 to length(Rubriks)-1 do begin +
-           local_progress.StepIt; +
-           if (Rubriks[i].group_number<>prev_group) then begin // сменилась группа рубрик +
-              prev_group := Rubriks[i].group_number; // сменить текущую группу +
-              Rubriks_Articles.add(format('<h1 style="{page-break-before: always}">%s</h1>',[Rubriks_Groups[prev_group].group])); +
-           end; +
-           if rubriks[i].common=1 then begin // регулярная рубрика +
-              // style="{page-break-before: always}" +
-              stroka := format('<h2><a name="Rubrika_%0:d">%1:s</a></h2>',[i, Rubriks[i].name]);; +
-              Rubriks_Articles.add(stroka); +
-              show_table_rubrik(i); +
-           end else begin // обычная рубрика +
-              stroka := format('<h2><a name="Rubrika_%0:d">%1:s</a></h2>',[i, Rubriks[i].name]);; +
-              Rubriks_Articles.add(stroka); +
-              Rubriks_Articles.add('<ul>'); +
-              for x:=Rubriks[i].index + Rubriks[i].Count - 1 downto Rubriks[i].index do begin // пройтись по всем записям индекса автора +
-                 with articles[Rubr_index[x].index] do begin +
- +
-                    if (year = '1992') and  (volume = '05') then begin +
-                       year_vol_str := '1992_05_06'; +
-                       str_vol := '05-06'; +
-                    end else begin +
-                       year_vol_str := year + '_' + volume; +
-                       str_vol := volume; +
-                    end; +
- +
-                    stroka:=format('<li><a href="%0:s/%1:s.djvu#%2:s">%0:s №%3:s — ',[year, year_vol_str, page, str_vol]); +
-                    if (rubrika <> '') then stroka := stroka + '[<font color=blue>' + rubrika + '</font>] '; +
-                    if (author <> '') then stroka := stroka + '(<font color=green>' + author + '</font>) — '; +
-                    if (title <> '') then stroka := stroka + title + ' '; +
-                    stroka := stroka + '</a>'; +
-                    Rubriks_Articles.Add(stroka); +
-                 end; +
-              end; +
-              Rubriks_Articles.add('</ul>'); +
-           end; +
-        end; +
-        Rubriks_Articles.add('</ul>'); // конечный /UL +
-        statusbar1.simpletext:='Готово'; +
- +
-        Rubriks_TOC.SaveToStream(file_All_Rubriks_Index); +
-        Rubriks_Names.SaveToStream(file_All_Rubriks_Index); +
-        Rubriks_Articles.SaveToStream(file_All_Rubriks_Index); +
-      finally +
-        IRange := nil; +
-        ISheet := nil; +
-        ISheet_Rubr_index := nil; +
-        ISheet_Rubriks := nil; +
-        setlength(articles,0); +
-        setlength(Rubr_index,0); +
-        setlength(Rubriks,0); +
-        file_All_Rubriks_Index.Free; +
-        Rubriks_TOC.Free; // освободить метсто для создания главной таблицы (верхний уровень) +
-        Rubriks_Names.Free; // освободить мнсто для создания списка фамилий (средний уровень) +
-        Rubriks_Articles.Free; // освободить место для создания блоков ссылок на статьи (нижний уровень) +
-        { +
-        // открыть созданный Html во встроенном редакторе +
-        Flags := 0; +
-        html_preview.Navigate(WideString(prog_path+'all_content.htm'), Flags, Flags, Flags, Flags); +
-        } +
-      end; +
-    except +
-      raise Exception.Create('Не могу прочитать данные в массив!'); +
-    end; +
-    end; +
-procedure make_bookmarks; +
-    var Bookmarks_Content: TStringList; +
-    x, y: integer; +
-    year_vol_str, str_vol: string; +
-Const min_vol = 1; +
-      max_vol = 12; +
-begin +
-    Bookmarks_Content := TStringList.Create; +
-    Bookmarks_Content.Add('<ul>'); +
-    Bookmarks_Content.Add('<li><a href="all_content.djvu">Сквозное оглавление</a></li>'); +
-    Bookmarks_Content.Add('<li><a href="all_authors.djvu">Авторский указатель</a></li>'); +
-    Bookmarks_Content.Add('<li><a href="all_rubriks.djvu">Рубрикатор</a></li>'); +
-    Bookmarks_Content.Add('<li><a href="#">Архив</a></li>'); +
-    Bookmarks_Content.Add('<ul>'); +
-    for x := max_year downto min_year do begin +
-       Bookmarks_Content.Add(format('<li><a href="#">%d год</a></li>',[x])); +
-       Bookmarks_Content.Add('<ul>'); +
-       for y := min_vol to max_vol do begin +
-          if y<10 +
-             then begin +
-                year_vol_str := format('%d_0%d',[x,y]); +
-                str_vol := format('0%d',[y]) +
-             end else begin +
-                year_vol_str := format('%d_%d',[x,y]); +
-                str_vol := format('%d',[y]) +
-             end; +
-          if (year_vol_str = '1992_05') then begin // сдвоенный номер 1992 05-06 +
-             year_vol_str := '1992_05_06'; +
-             str_vol := '05-06'; +
-          end; +
-          if (x = 1992) and (y = 6) then continue; // пропустить номер 1992 6 +
-          Bookmarks_Content.Add(format('<li><a href="%0:d/%1:s.djvu">%0:d №%2:s</a></li>',[x, year_vol_str, str_vol])); +
-       end; +
-       Bookmarks_Content.Add('</ul>'); +
-    end; +
-    Bookmarks_Content.Add('</ul>'); +
-    Bookmarks_Content.Add('<li><a href="search.exe">Сквозной поиск</a></li>'); +
-    Bookmarks_Content.Add('</ul>'); +
-    Bookmarks_Content.SaveToFile('all_bookmarks.htm'); +
-end; +
-begin +
-  global_progress.Min:=0; +
-  global_progress.max:=6; +
-  global_progress.Position:=global_progress.Min; +
-  global_progress.Step:=1; +
-  statusbar1.simpletext:='Создание BAT файлов...'; +
-  CreateBatches; // создать BAT файлы для конвертирования PDF в DJVU +
-  Load_complex_rubriks; // загрузить список сборных рубрик +
-  Load_rubriks_groups; // загрузить список групп рубрик +
-  global_progress.StepIt; +
- +
-  if chk_make_bookmarks.Checked then begin +
-     statusbar1.simpletext:='Создание закладок для DJVU...'; +
-     Local_Content_Create(self); +
-  end; +
-  global_progress.StepIt; +
- +
-  if chk_make_content.Checked then begin +
-     statusbar1.simpletext:='Создание глобального оглавления по номерам...'; +
-     per_volumes; // создать глобальное оглавление по номерам (all_content.htm) +
-  end; +
-  global_progress.StepIt; +
- +
-  if chk_make_authors.Checked then begin +
-     statusbar1.simpletext:='Создание авторского указателя...'; +
-     per_authors; // создать глобальный авторский указатель (all_authors.htm) +
-  end; +
-  global_progress.StepIt; +
- +
-  if chk_make_rubriks.Checked then begin +
-     statusbar1.simpletext:='Создание рубрикатора...'; +
-     per_rubrics; // создать глобальный рубрикатор (all_rubrics.htm) +
-  end; +
-  global_progress.StepIt; +
- +
-  statusbar1.simpletext:='Создание закладок для файлов all_?????.htm...'; +
-  make_bookmarks; // создать закладки для all_   .htm +
-  global_progress.StepIt; +
-  statusbar1.simpletext:='Готово'; +
-  local_progress.Position := local_progress.Max; +
-  global_progress.Position := global_progress.Max; +
-end; +
- +
-procedure TForm1.btn_simple_volumeClick(Sender: TObject); +
-begin +
-   btn_simple_volume.OnClick := Local_Content_Create; +
-   CreateBook; +
-   btn_simple_volume.Caption := 'Построить оглавление заново'; +
-   form1.Refresh; +
-   chk_debug_mode.Checked := true; +
-   Initiate_Data(Sender); +
-   grp_simple_volume.Caption := edt_volumes.Items[0]; +
-   Local_Content_Create(Sender); +
-end; +
- +
-procedure TForm1.btn_Collect_DataClick(Sender: TObject); +
-type temp_content_element = record +
-        rubrika : string; +
-        author : string; +
-        title : string; +
-        page : string; +
-        link : string; +
-        volume : string; +
-        year : string; +
-        responsible : string; +
-     end; +
-var FullFileName: string; +
-    x, n, position:integer; +
-    Values: OLEVariant; +
-    IRange: Excel8TLB.Range; +
-    ISheet: Excel8TLB._Worksheet; +
-    Content: array of temp_content_element; +
-    x_volume : string; +
-    x_year : string; +
-    x_responsible : string; +
-    use_interpolation: boolean; +
-procedure check_content(FullFileName:string; x:integer; var rubrika,author,title,page,link,volume,year,responsible:string); +
-   var test:integer; +
-   begin +
-      if use_interpolation then begin +
-         if trim(rubrika+author+title+page+link)='' then exit; // пропустить пустые вызовы +
-      end else begin +
-         if trim(rubrika+author+title+page+link+volume+year+responsible)='' then exit; // пропустить пустые вызовы +
-      end; +
-      if (trim(page)='') or (trim(volume)='') or (trim(year)='') or (trim(responsible)=''+
-         then ShowMessageInLog(year, volume, page, format('Отсутствует одно или несколько обязательных полей (страница, год, номер, ответственный), см. файл %s, строку %d',[FullFileName,x])); +
-      if (trim(rubrika + author + title) = ''+
-         then ShowMessageInLog(year, volume, page, format('Не указано ни рубрики, ни автора, ни названия статьи, см. файл %s, строку %d',[FullFileName,x])); +
-      try +
-         test:=strtoint(year); +
-      except +
-         ShowMessageInLog(year, volume, page, format('Ошибка в формате года журнала %s, см. файл %s, строку %d',[year,FullFileName,x])); +
-         test:=min_year; // чтобы не сработало следующее сообщение об ошибке +
-      end; +
-      if (test>max_year) or (test<min_year) +
-         then ShowMessageInLog(year, volume, page, format('Год журнала %d, находится вне диапазона %d-%d, см. файл %s, строку %d',[test,min_year,max_year,FullFileName,x])); +
-      try +
-         test:=strtoint(volume); +
-      except +
-         ShowMessageInLog(year, volume, page, format('Ошибка в формате номера журнала %s, см. файл %s, строку %d',[volume,FullFileName,x])); +
-         test:=1; // чтобы не сработало следующее сообщение об ошибке +
-      end; +
-      if (test>12) or (test<1) +
-         then ShowMessageInLog(year, volume, page, format('Номер журнала %d, находится вне диапазона 01-12, см. файл %s, строку %d',[test,FullFileName,x])); +
-      try +
-         test:=strtoint(page); +
-      except +
-         ShowMessageInLog(year, volume, page, format('Ошибка в формате номера страницы %s, см. файл %s, строку %d',[page,FullFileName,x])); +
-         test:=1; // чтобы не сработало следующее сообщение об ошибке +
-      end; +
-      if (test<1) or (test>200) +
-         then ShowMessageInLog(year, volume, page, format('Номер страницы %d, находится вне диапазона 1-200, см. файл %s, строку %d',[test,FullFileName,x])); +
-      if rubrika = 'Рефераты. Садоводу — на заметку' +
-         then rubrika := 'Рефераты | Садоводу — на заметку'; +
-      if rubrika = 'Вкладка' +
-         then rubrika := 'Вкладки'; +
-      if rubrika = 'Обложки' +
-         then rubrika := 'Обложка'; +
-      if rubrika = 'Рефераты. Садоводу — на заметку' +
-         then rubrika := 'Рефераты | Садоводу — на заметку'; +
-      if title = 'Маленькие хитрости' then begin +
-         title := ''; +
-         if rubrika = '' +
-            then rubrika := 'Маленькие хитрости' +
-            else rubrika := rubrika + ' | Маленькие хитрости'; +
-         end; +
-   end; +
-function cure_volume(stroka:string):string; +
-   begin +
-      if length(stroka)=1 +
-        then result := '0' + stroka +
-        else result := stroka; +
-   end; +
-function cure_page(stroka:string):string; +
-   begin +
-      try +
-         stroka:=inttostr(strtoint(stroka)); +
-      except +
-      end; +
-      result:=stroka; +
-   end; +
-function cure(stroka:string):string; +
-   var temp: string; +
-   begin +
-      temp:=StringReplace(stroka, ', ' ', [rfReplaceAll]); +
-      temp:=StringReplace(temp, '...', '…', [rfReplaceAll]); +
-      temp:=StringReplace(temp, '|', ' | ', [rfReplaceAll]); +
-      temp:=StringReplace(temp, ' ,', ',', [rfReplaceAll]); +
-      temp:=StringReplace(temp, ' .', '.', [rfReplaceAll]); +
-      temp:=StringReplace(temp, ',', ', ', [rfReplaceAll]); +
-      temp:=StringReplace(temp, '.', '. ', [rfReplaceAll]); +
-      temp:=StringReplace(temp, '. -', '.-', [rfReplaceAll]); +
-      temp:=StringReplace(temp, '––', '—', [rfReplaceAll]); +
-      temp:=StringReplace(temp, ', ' ', [rfReplaceAll]); +
-      temp:=StringReplace(temp, ', ,', ',', [rfReplaceAll]); +
-      temp:=StringReplace(temp, '. .', '.', [rfReplaceAll]); +
-      result:=trim(temp); +
-   end; +
-begin +
-  OpenDialog1.InitialDir:=prog_path; +
-  OpenDialog1.Options:=OpenDialog1.Options + [ofAllowMultiSelect]; +
-  if not OpenDialog1.Execute then exit; // свалить, коли не открыли ничего +
- +
-  if Application.MessageBox( +
-    'Использовать интерполяцию года-номера-ответственного по первой статье в файлах?', +
-    'Выбор способа обработки XLS файлов', +
-    MB_YESNO) = IDYES then use_interpolation:=true else use_interpolation:=false; +
-  statusbar1.simpletext:='Объединение файлов...'; +
-  local_progress.Min:=0; +
-  local_progress.max:=OpenDialog1.Files.Count; +
-  local_progress.Position:=local_progress.Min; +
-  local_progress.Step:=1; +
-  global_progress.Min:=0; +
-  global_progress.max:=3; +
-  global_progress.Position:=global_progress.Min; +
-  global_progress.Step:=1; +
-  for n:=0 to OpenDialog1.Files.Count-1 do begin +
-     FullFileName := OpenDialog1.Files[n]; +
-     local_progress.StepIt; +
-     statusbar1.simpletext:='Чтение файла '+extractfilename(fullfilename)+'...'; +
-     if Assigned(IXLSApp) and (not Assigned(IWorkbook2))then +
-       try +
-         try +
-           FIWorkbook2 := IXLSApp.Workbooks.Open(FullFileName, +
-                EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, +
-                EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, false, 0); +
-           ISheet := IWorkbook2.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-           IRange := ISheet.UsedRange[0];  // прочесть весь лист +
-           Values := IRange.Value; +
-           position := length(Content); +
-           setlength(Content, position + IRange.Rows.Count-1); +
- +
-           // взять значение номера, года и ответственного их первой строки +
-           if use_interpolation then begin +
-              x_volume := Values[2,6]; +
-              x_volume := cure(x_volume); +
-              x_volume := cure_volume(x_volume); +
-              x_year := Values[2,7]; +
-              x_year := cure(x_year); +
-              x_responsible := Values[2,8]; +
-              x_responsible := cure(x_responsible); +
-           end; +
-           for x:=2 to IRange.Rows.Count do begin +
-              with Content[position + x - 2] do begin +
-                 rubrika := Values[x,1]; +
-                 rubrika := cure(rubrika); +
-                 author := Values[x,2]; +
-                 author := cure(author); +
-                 title := Values[x,3]; +
-                 title := cure(title); +
-                 page := Values[x,4]; +
-                 page := cure(page); +
-                 page := cure_page(page); +
-                 link := Values[x,5]; +
-                 link := cure(link); +
-                 if use_interpolation then begin +
-                    volume := x_volume; +
-                    year := x_year; +
-                    responsible := x_responsible; +
-                 end else begin +
-                    volume := Values[x,6]; +
-                    volume := cure(volume); +
-                    volume := cure_volume(volume); +
-                    year := Values[x,7]; +
-                    year := cure(year); +
-                    responsible := Values[x,8]; +
-                    responsible := cure(responsible); +
-                 end; +
-                 check_content(FullFileName,x,rubrika,author,title,page,link,volume,year,responsible); +
-              end; +
-           end; +
-         finally +
-           IWorkBook2.Close(EmptyParam,EmptyParam,EmptyParam,0); +
-           FIWorkbook2 := nil; +
-           ISheet := nil; +
-         end; +
-       except +
-         raise Exception.Create('Не могу открыть книгу!'); +
-       end; +
-     end; +
-  try +
-     statusbar1.simpletext:='Выгрузка в файл "content.xls"...'; +
-     ISheet := IWorkbook.Worksheets.Item['Содержание'] as Excel8TLB._Worksheet; +
-     IDispatch(IRange) := ISheet.UsedRange[0].Rows.Item[1, EmptyParam]; // первая строка области +
-     Values := IRange.Value; // сохранить первую строку +
-     ISheet.Cells.ClearContents; // очистить лист "Содержание" +
-     IRange.Value := Values; // записать назад первую строку +
-     //IRange := nil; +
-     //VarClear(Values); +
- +
-     // выгрузить инфу на лист ISheet_auth_index +
-     global_progress.StepIt; +
-     Values := VarArrayCreate([1, length(Content)+1, 1, 8], varVariant); +
-     local_progress.Min:=0; +
-     local_progress.max:=length(Content); +
-     local_progress.Position:=local_progress.Min; +
-     local_progress.Step:=1; +
-     for x:=0 to length(Content)-1 do begin +
-        local_progress.StepIt; +
-        with Content[x] do begin +
-           if page = '' then continue; +
-           Values[x+1,1] := rubrika; +
-           Values[x+1,2] := author; +
-           Values[x+1,3] := title; +
-           Values[x+1,4] := page; +
-           Values[x+1,5] := link; +
-           Values[x+1,6] := volume; +
-           Values[x+1,7] := year; +
-           Values[x+1,8] := responsible; +
-        end; +
-     end; +
-     IRange:= ISheet.Range['A2','H'+inttostr(length(Content)+1)]; +
-     IRange.Value := Values; +
-     VarClear(Values); +
-  finally +
-     setlength(Content,0); +
-     IRange := nil; +
-     ISheet := nil; +
-     ShowExcel; +
-     Application.BringToFront; +
-     sort_articles; // отсортировать статьи +
-  end; +
-  global_progress.stepit; +
-  statusbar1.simpletext:='Сохранение "content.xls"...'; +
-  IWorkbook.Save(0); +
- +
-  local_progress.Position := local_progress.Max; +
-  global_progress.Position := global_progress.Max; +
-  statusbar1.simpletext:='Ok'; +
-end; +
- +
-procedure TForm1.Button1Click(Sender: TObject); +
-begin +
-errorlog.Items.Clear; +
-end; +
- +
-procedure TForm1.Button2Click(Sender: TObject); +
-var otchet : TStringList; +
-    x: integer; +
-begin +
-   otchet := TStringList.Create; +
-   SaveDialog1.InitialDir := prog_path; +
-   if SaveDialog1.Execute then begin +
-      for x:=0 to ErrorLog.Items.Count-1 do begin +
-         with ErrorLog.Items.Item[x] do +
-            otchet.Add(format('%s: %s, %s, %s',[Caption, SubItems.Strings[0], SubItems.Strings[1], SubItems.Strings[2]])); +
-      end; +
-      otchet.SaveToFile(SaveDialog1.FileName); +
-   end; +
-   otchet.Free; +
-end; +
- +
-end. +
- +
-// Особая позиция! Только для служебного "пользования"+
-// +
-// Я люблю Microsoft. Всей своей мелкой душонкой, всем своим бренным телом и еще, чем только могу. +
-// Я люблю эту фирму за то, что периодически веселит меня изменениями в логике методов интерфейсов +
-// ее приложений. За то, что мне не скучно жить от все увеличивающихся сервис-паков и сервис-релизов. +
-// За редактор VBA я тоже ее люблю, а особенно за ToolTips в нем и F5/F8/F9 в отладчике. И за язык +
-// этот самый я ее люблю. И за "правильные" коллекции в ExcelTLB с прекрасным механизмом поиска в них. +
-// И за обработку исключений, и за их периодическую генерацию. А еще люблю за то, что один и тот +
-// же код может работать, а может и не работать. Все ж зависит от влажности воздуха и атмосферного +
-// давления, от фазы луны и расположения звезд. Именно от этого перестает выгружаться Outlook с +
-// парами десятков потоков. Он, ведь, практически не использует ресурсов? От этого также валится +
-// Word, забыв сохранить последний мой файл. А Excel от этого только устойчивей. Он под натиском +
-// обработчиков событий просто вешает своих клиентов, потом отрубает их и говорит, что его нельзя +
-// закрывать, потому что просто нельзя! +
-// Так я люблю Microsoft, такой сильною любовью, что если б была она женщиной... +
-// Но видно не выжила б эта женщина в наших широтах с нашим климатом и под НАШИМИ звездами. +
-// +
-// А еще мне нравится справка по VBA. Особенно, в Excel 2000. И на кого ее рассчитывали? +
-// Или они думали, что я буду набирать что-то, типа "Покажи мне, пожалуйста, как использовать +
-// свойство SubTotals у объекта PivotField?" +
-// +
-//                                                                                Злой. +
- +
- +
-</code> +
- +
- +
science_and_life/isxodniki.txt · Last modified: 2017/03/13 18:20 by kibi

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki