1

Тема: Определить начало абзаца

Доброго времени суток. В Word, как известно, нет спецсимвола для определения начала абзаца. Есть такой способ - "^p^?", используя конец предыдущего абзаца. Но такое не прокатит внутри таблицы и, как ни странно, в случае, если абзац расположен сразу после таблицы. То есть:

[какая-то_таблица]
Текст1
Текст2
...

Здесь я не смогу найти пробел перед "Текст1", чтобы удалить его.
Стояла задача, удалить все начальные и конечные пробелы и tab'ы. Такой код Delphi работает слишком медленно.

Par := WordApp.ActiveDocument.Paragraphs.Item(1);
  while Assigned(Par) do
  begin
    Application.ProcessMessages;
    while True do
    begin
      CH := WordApp.ActiveDocument.Range(Par.Range.Start, Par.Range.Start);
      if not CharInSet(PAnsiChar(AnsiString(CH.Text))^, ChSet) then
        Break;
      CH.Delete(wdCharacter, 1);
    end;
    if Par.Range.End_ > 2 then
    while True do
    begin
      CH := WordApp.ActiveDocument.Range(Par.Range.End_ - 2, Par.Range.End_ - 1);
      if not CharInSet(PAnsiChar(AnsiString(CH.Text))^, ChSet) then
        Break;
      CH := WordApp.ActiveDocument.Range(Par.Range.End_ - 2, Par.Range.End_ - 2);
      CH.Delete(wdCharacter, 1);
    end;
    Par := Par.Next(1);
    if BreakProc then
      goto Ex;
  end;

Поиск конечных пробелов определил так (вместо вышеописанного кода):

while True do
  begin
    Application.ProcessMessages;
    WordApp.Selection.SetRange(0, 0);
    if not WordApp.Selection.Find.Execute(' ^p', EP, EP, False, EP, EP, EP, EP, EP, EP, EP, EP, EP, EP, EP) then
      Break;
    WordApp.Selection.MoveLeft(wdCharacter, 1, EP);
    WordApp.Selection.Delete(wdCharacter, 1);
    if BreakProc then
      goto Ex;
  end;

Как найти начальные?

2

Re: Определить начало абзаца

janxp пишет:

Стояла задача, удалить все начальные и конечные пробелы и tab'ы. Такой код Delphi работает слишком медленно.
Как найти начальные?

Возможно, медленная работа обусловлена тем, что вы обрабатываете объект Word (абзац) в цикле, причем каждый раз формируете его заново. Попробуйте присвоение переменной CH вынести из цикла и, как вариант, использовать метод MoveEndUntil (это поиск символов, не совпадающими с заданными) - а задать в атрибуте Cset можно строку из пробела и знака табуляции.

3

Re: Определить начало абзаца

если задача просто удалить начальные и конечные пробелы, у абзацев, то можно воспользоваться стандартным инструментом замены. Например, заменить абзац+пробел на просто абзац. (^p_  →   ^p).

Этот процесс можно записать макрорекордером и посмотреть код. Потом доработать под задачу.

4

Re: Определить начало абзаца

yshindin пишет:

Попробуйте присвоение переменной CH вынести из цикла и, как вариант, использовать метод MoveEndUntil (это поиск символов, не совпадающими с заданными) - а задать в атрибуте Cset можно строку из пробела и знака табуляции.

Видимо, я ошибся: нужен метод MoveEndWhile. Общий смысл - выделить последовательность символов, состоящую только из символов, входящих в заданную строку. Далее, если выделена непустая последовательность (что можно узнать, пhоанализировав Selection), то выполнить Selection.Delete.

5

Re: Определить начало абзаца

если задача просто удалить начальные и конечные пробелы, у абзацев, то можно воспользоваться стандартным инструментом замены. Например, заменить абзац+пробел на просто абзац. (^p_  →   ^p).

Это первое, что пришло в голову. Но данный способ, как я уже написал выше, не работает, если абзац расположен сразу после таблицы. Попробовал так - "^007 " (^007 - код "конца" ячейки) с подстановочными знаками, но Word'у такой вариант не нравится.
Насчет MoveEndWhile, - попробую.

6

Re: Определить начало абзаца

yshindin пишет:

Возможно, медленная работа обусловлена тем, что вы обрабатываете объект Word (абзац) в цикле, причем каждый раз формируете его заново.

Здравая мысль.

yshindin пишет:

Общий смысл - выделить последовательность символов, состоящую только из символов, входящих в заданную строку. Далее, если выделена непустая последовательность (что можно узнать, пhоанализировав Selection), то выполнить Selection.Delete.

Можно поподробней, например, на VBA.

7

Re: Определить начало абзаца

janxp пишет:

Можно поподробней, например, на VBA.

Вот, напр., для удаления символов в начале строки это может выглядеть так (перед исполнением кода надо поместить курсор в начало целевого абзаца):

Sub tsel()
Dim sr_end1 As Long
Dim sr_end2 As Long
Dim cs As String

cs = vbTab & " "
sr_end1 = Selection.Range.End
Selection.MoveEndWhile cset:=cs, Count:=wdForward
sr_end2 = Selection.Range.End
If sr_end2 > sr_end1 Then 'выделена непустая последовательность ппробелов и табов
    Selection.Delete
End If
End Sub

8

Re: Определить начало абзаца

Вот, напр., для удаления символов в начале строки это может выглядеть так (перед исполнением кода надо поместить курсор в начало целевого абзаца):

Удалить пробелы не проблема. Именно, как установить курсор на абзаце с пробелом в начале? Кстати, пробел возможен только один, т.к. я произвожу замену множественных пробелов и tab'ов заменой ^w на " ".

9

Re: Определить начало абзаца

janxp пишет:

Удалить пробелы не проблема. Именно, как установить курсор на абзаце с пробелом в начале?

Чтобы поместить курсор в начало абзаца, можно выделить весь абзац, затем выполнить метод Collapse (к началу абзаца), либо можно сформировать диапазон, начинающийся и заканчивающийся в точке начала абзаца, а потом выделить этот диапазон, как в примере ниже (в этом примере выполняется цикл по всем абзацам документа с перемещением каждый раз перед обработкой курсора в начало очередного абзаца):

Sub tpar()
Dim pstart As Range
Dim para As Paragraph
Set pstart = ActiveDocument.Paragraphs(1).Range 'форм. нач. знач. рабочего диапазона
For Each para In ActiveDocument.Paragraphs 'цикл по абзацам
    pstart.SetRange Start:=para.Range.Start, End:=para.Range.Start 'диап.начала абзаца
    pstart.Select 'выделяем этот диапазон (т.е., перемещаем курсор в начало абзаца
    'теперь можно выполнить MoveEndWhile
    '...
Next
End Sub

10

Re: Определить начало абзаца

Сделал все проще. Спереди и сзади таблиц добавил по новому пустому абзацу и выполнил стандартную замену "^p " и " ^p" на "^p". Все передние и задние пробелы удалились. Затем удаляю добавленные абзацы. Скорость выполнения относительно большая.
Спасибо за советы.

11

Re: Определить начало абзаца

janxp пишет:

Стояла задача, удалить все начальные и конечные пробелы и tab'ы. Такой код Delphi работает слишком медленно.

Если задача состоит в том, чтобы убрать пробелы в абзацах перед и после, разве для этого не функция Trim обычно используется? roll

Ищу соратников по программированию

12

Re: Определить начало абзаца

Nataliya пишет:

Если задача состоит в том, чтобы убрать пробелы в абзацах перед и после, разве для этого не функция Trim обычно используется? roll

В Word2000 функция Trim отсутствует. Нужен был универсальный способ.
А копирование-применение_Trim-вставка исключается из-за крайней тормознутости.