Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Microsoft Office и VBA программирование > Microsoft Office Word
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.04.2009, 20:48   #1
Lisi4ka
Пользователь
 
Регистрация: 28.09.2008
Сообщений: 31
По умолчанию получение текстового диапазона программым путем

Есть док.в Ворде следующей структуры:
Текст вопроса № 1 <Enter>
-ответ № 1 <Enter>
-ответ № 2 <Enter>
-ответ № 3 <Enter>
<Enter>
Текст вопроса № 2 <Enter>
-ответ № 1 <Enter>
-ответ № 2 <Enter>
-ответ № 3 <Enter>
<Enter> и т.д.
Необходимо считать с дин.массив текст вопроса с ответами. Поступаю след. образом: считываем число строк до позиции дока, когда подряд идут два <Enter>, затем выделяю память под это кол-во строк, после чего хочу циклом считать каждую из строк, привожу код:
Код:
procedure TForm1.FormActivate(Sender: TObject);
begin
Memo1.Clear;
KolZapisei:=0;
i:=0;
j:=1;
j_count:=j;
m:=i;
If OpenDialog1.Execute then
  begin
   try
    Filename:=OpenDialog1.FileName;
    WordApplication1.Connect;
    WordApplication1.Documents.Open(FileName,
     emptyparam,emptyparam,emptyparam,
     emptyparam,emptyparam,emptyparam,
     emptyparam,emptyparam,emptyparam,
     emptyparam,emptyparam);
    worddocument1.connectto(wordapplication1.activedocument);
    wordApplication1.Visible:=false;
     while j<=WordDocument1.Range.End_ do
      begin
       While (WordDocument1.Range(i,j).Text <>#13) do
        begin
         i:=i+1;
         j:=j+1;
        end;
       KolZapisei:=KolZapisei+1;
       n:=j-1;
       i:=j+1;
       j:=i+1;
       s:='';
       if (WordDocument1.Range(m,n).Text[1]=#13) then
        begin
         if(KolVoprosov=0) then
          begin
           Memo1.Lines.Add('KolStrok '+IntToStr(KolZapisei-1));
           SetLength(MassivVoprosov,KolZapisei-1);
           Memo1.Lines.Add('Vopros '+IntToStr(KolVoprosov+1));
           Memo1.Lines.Add('pervaya poz '+IntToStr(j_count)+' posl poz '+IntToStr(j));
           While (j_count<j) do
            begin
             //While (WordDocument1.Range(10,20).Text <>#13) do
             // ТУТ ВЫЛЕТАЕТ ОШИБКА "THERE IS NO OVERLOADED VOERSION OF 'RANGE' THAT CAN BE CALLED WITH THESE ARGUMENTS"
             // begin
            //  end;
             j_count:=j_count+1;
            end;
           j_count:=j;
           KolVoprosov:=KolVoprosov+1;
          end
         else
          begin
           KolVoprosov:=KolVoprosov+1;
           Memo1.Lines.Add('KolStrok '+IntToStr(KolZapisei));
           SetLength(MassivVoprosov,KolZapisei);
           Memo1.Lines.Add('Vopros '+IntToStr(KolVoprosov));
           Memo1.Lines.Add('pervaya poz '+IntToStr(j_count)+' posl poz '+IntToStr(j));
           j_count:=j;
          end;
         KolZapisei:=0;
       end;
       if (j=WordDocument1.Range.End_ ) then
           begin
            SetLength(MassivVoprosov,KolZapisei);
            Memo1.Lines.Add('KolStrok '+IntToStr(KolZapisei));
            Memo1.Lines.Add('pervaya poz '+IntToStr(j_count)+' posl poz '+IntToStr(j));
            j_count:=j;
            break;
           end;
       s:=s+Trim(WordDocument1.Range(m,n).Text);
       Memo1.Lines.Add(s);
       m:=n+1;
      end;
   finally
    Worddocument1.Free;
    WordApplication1.Disconnect;
   end;
  end;

end;
Подскажите, почему может выходить такая ошибка, ведь диапазоны индексов заданы статически, несколькими строками ранее использован подобный принцип прохождения цикла????
Lisi4ka вне форума Ответить с цитированием
Старый 09.04.2009, 22:08   #2
viter.alex
Балуюсь кодами
Участник клуба
 
Аватар для viter.alex
 
Регистрация: 09.01.2009
Сообщений: 1,837
По умолчанию

Как-то странно вы, Lisi4ka, рассуждаете.
У вас каждая строка — это абзац, вернее и текст вопроса и ответы занимают один абзац. Поэтому, да, можно читать абзацы, пока не наткнемся на пустой. Но это не продуктивно.
Гораздо выгоднее, с точки зрения производительности, пользоваться поиском. Искать нужно 2 абзаца подряд. К сожалению, в Delphi я не силен, а на VBA это выглядит так:
Код:
Sub FindTwoParagraphs()
  Dim iStart&, oRng As Range, bFound As Boolean
  Do
    With ActiveDocument.Range(iStart, ActiveDocument.Range.End).Find
      .ClearFormatting: .Text = "^0013^0013"
      .MatchWildcards = True
      .Execute
      'Когда поиск что-то находит, то Parent объекта Find содержит Range найденного объекта. _
      В нашем случае там оказались два абзаца. Вернее, последний символ одного абзаца и _
      первый символ второго (пустого) абзаца. В переменную oRng мы записываем диапазон от _
      точки старта поиска и до конца первого из найденных абзацев. Дальше с этим диапазоном _
      можно делать, что угодно. Можете его сразу записать в массив или взять свойство oRng.Text _
      и записать в массив только строку, или разбить эту строку на массив строк по разделителю #13, _
      или читать абзацы из него и т.д.
      If .Found Then
        Set oRng = ActiveDocument.Range(iStart, .Parent.Paragraphs(1).Range.End)
        'Переносим точку старта для следующего поиска в конец найденного диапазона
        iStart = .Parent.End
        bFound = True 'Флаг для цикла Do…Loop
      Else: bFound = False
      End If
    End With
  Loop While bFound
End Sub
Думаю общий смысл вам ясен. А реализовать на конкретном языке, — это уже мелочи.
Еще одна мелочь. Такой поиск нам даст всё, кроме последнего вопроса если в конце документа не стоит, я надеюсь, два абзаца подряд. Получить этот последний вопрос просто: нужно взять диапазон от iStart конца документа. Надеюсь, что это сделаете сами.
Спрашивайте, всегда рад помочь.
Лучше день потерять — потом за пять минут долететь!©

Последний раз редактировалось viter.alex; 09.04.2009 в 22:21.
viter.alex вне форума Ответить с цитированием
Старый 10.04.2009, 10:06   #3
viter.alex
Балуюсь кодами
Участник клуба
 
Аватар для viter.alex
 
Регистрация: 09.01.2009
Сообщений: 1,837
По умолчанию

Посмотрел я ваш код еще раз. Сама строка, где вылетает ошибка, мне непонятна.
Код:
While (WordDocument1.Range(10,20).Text <>#13) do
Другими словами мы берем текст с 10 по 20 символ документа и сравниваем его с одним символом. Зачем? Как можно 10 символов сравнить с одним? Вот и вылетает ошибка о том, что перегруженного метода Text, который бы из диапазона символов возвращал код символа (какого?), для Range не существует.
Лучше день потерять — потом за пять минут долететь!©
viter.alex вне форума Ответить с цитированием
Старый 10.04.2009, 16:17   #4
Lisi4ka
Пользователь
 
Регистрация: 28.09.2008
Сообщений: 31
По умолчанию

Спасибо за науку и ответ!
Действительно, такой способ гораздо проще и рациональнее, чем мой! Однако Дельфя не дает проверить, как он работает (а через VBA все хорошо!), ругается аналогично на Range
Код:
Repeat
      With worddocument1.Range(iStart, worddocument1.Range.End_).Find do
Lisi4ka вне форума Ответить с цитированием
Старый 10.04.2009, 16:22   #5
viter.alex
Балуюсь кодами
Участник клуба
 
Аватар для viter.alex
 
Регистрация: 09.01.2009
Сообщений: 1,837
По умолчанию

А как объявлена переменная WordDocument1? Список объектов и методов доступен для нее? Кстати, насколько я помню, Delphi чувствителен к регистру в именах переменных.
Лучше день потерять — потом за пять минут долететь!©

Последний раз редактировалось viter.alex; 10.04.2009 в 16:25.
viter.alex вне форума Ответить с цитированием
Старый 10.04.2009, 16:29   #6
Lisi4ka
Пользователь
 
Регистрация: 28.09.2008
Сообщений: 31
По умолчанию

viter.alex, я в Range(1,2); Range(0,1) и т.д. ставила, оно все равно не работало, изначально на позициях нач. и кон. диапазона стояло что-то вроде К и К+1...
Теперь вот ваш переделанный код тоже е работает, ругается аналогичным образом, проверю, мож. где-то типы д. не те указала..
Lisi4ka вне форума Ответить с цитированием
Старый 10.04.2009, 16:32   #7
Lisi4ka
Пользователь
 
Регистрация: 28.09.2008
Сообщений: 31
По умолчанию

ВордДокумент как надо объявлен, для него Range доступно, а для Range доступно Find, но в самом Range при указании нижнего индекса диапазона (WordDocument.Range.End_) все недоступно, что-то дельфям не нравится)
Lisi4ka вне форума Ответить с цитированием
Старый 10.04.2009, 16:50   #8
Lisi4ka
Пользователь
 
Регистрация: 28.09.2008
Сообщений: 31
По умолчанию

Проблему решила путем присвоения переменной типа OleVariant значения worddocument1.Range.End_, теперь с синтаксисом разбираюсь, ведь свойства Paragraphs у ActiveDocument.Range(iStart, ActiveDocument.Range.End).Find.Pare nt нет(((
Lisi4ka вне форума Ответить с цитированием
Старый 10.04.2009, 17:31   #9
viter.alex
Балуюсь кодами
Участник клуба
 
Аватар для viter.alex
 
Регистрация: 09.01.2009
Сообщений: 1,837
По умолчанию

Цитата:
Сообщение от Lisi4ka Посмотреть сообщение
Проблему решила путем присвоения переменной типа OleVariant значения worddocument1.Range.End_, теперь с синтаксисом разбираюсь, ведь свойства Paragraphs у ActiveDocument.Range(iStart, ActiveDocument.Range.End).Find.Pare nt нет(((
Объект Parent не доступен через список, но существует. В VBA его тоже не видно, но я же знаю, что это Range, поэтому и пишу, как будто он есть. Может в Delphi такой вариант и не пройдет.
Лучше день потерять — потом за пять минут долететь!©
viter.alex вне форума Ответить с цитированием
Старый 10.04.2009, 18:29   #10
Lisi4ka
Пользователь
 
Регистрация: 28.09.2008
Сообщений: 31
По умолчанию

Вот что получилось:
Код:
If OpenDialog1.Execute then
  begin
   try
    Filename:=OpenDialog1.FileName;
    WordApplication1.Connect;
    WordApplication1.Documents.Open(FileName,
     emptyparam,emptyparam,emptyparam,
     emptyparam,emptyparam,emptyparam,
     emptyparam,emptyparam,emptyparam,
     emptyparam,emptyparam);
    worddocument1.connectto(wordapplication1.activedocument);
    wordApplication1.Visible:=false;
    iStart:=0;
    Count_end:=WordDocument1.Range.End_;
    Repeat
     Fnd:= worddocument1.Range(iStart, Count_end).Find;
     Fnd.ClearFormatting;
     fnd.Execute('^0013^0013', EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam, EmptyParam, EmptyParam,
                     EmptyParam, EmptyParam);
     if fnd.Found=True then
      begin
       bFound:=true;
       rang:=fnd.Parent;
       RangeFin:=rang.End;
       oRng:=WordDocument1.Range(iStart,RangeFin);
       Showmessage(' eto vopros! '+oRng.Text);
       iStart:=RangeFin;
      end
     Else
      begin
       bFound:= False;
      end;
     Until(not(bFound));
Lisi4ka вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Создание билетов путем импорта из таблицы mistx Microsoft Office Excel 2 25.02.2009 09:02
Эллипс путем перемещения точки вокруг отрезка Dublin Мультимедиа в Delphi 4 22.10.2008 21:30
Как вставить имя файла с путем в combobox Andreych74 Win Api 0 08.10.2008 10:30
Имя диапазона CAMyM Microsoft Office Excel 8 09.11.2007 10:16
Как ввести пароль для БД Paradox программным путем ? zetrix БД в Delphi 2 07.04.2007 21:50