Список форумов Форум Libreoffice

Форум Libreoffice

Добро пожаловать на Форум Libreoffice!
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 

English French German Italian Portuguese Russian Spanish
Найти и заменить: "пустой абзац" на ""-?

 
Начать новую тему   Ответить на тему    Список форумов Форум Libreoffice -> Writer
Предыдущая тема :: Следующая тема  
Автор Сообщение
vanya



Репутация: 0    

Зарегистрирован: 02.08.2011
Сообщения: 17

СообщениеДобавлено: Ср Сен 21, 2011 7:25 am    Заголовок сообщения: Найти и заменить: "пустой абзац" на ""-? Ответить с цитатой

При попытке удалить пустые абзацы с помощью "Найти и заменить" (Ctrl-F) и использованием регулярных выражений в документе, содержащем Таблицы, офис намертво зависает. В поле поиска задано "^$", а в поле Замены "" (пустое значение). Опция "Регулярные выражения" включена. При попытке "Заменить все" офис наглухо зависает.

То же самое происходит при использовании макроса:
Код:
Sub Main()
   Dim oDoc
   Dim oReplace

   oDoc = ThisComponent
   oReplace = oDoc.createReplaceDescriptor

   With oReplace
      .SearchRegularExpression = True
      .SearchString = "^$"
      .ReplaceString = ""
   End With
   oDoc.ReplaceAll(oReplace)
End Sub

Файл с примером http://ifolder.ru/25864756
Как можно обойти эту трудность?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
RFJ



Репутация: +1    

Зарегистрирован: 02.08.2011
Сообщения: 59

СообщениеДобавлено: Ср Сен 21, 2011 7:50 am    Заголовок сообщения: Ответить с цитатой

Проще всего в 2 этапа.
Сначала использовать Поиск и замену на некую "уникальную строку" (аналогично http://libreoffice.3nx.ru/viewtopic.php?t=14),
А затем Поиск и замену этой "уникальной строки" на "пустое значение".

То есть, так:
1. Найти : ^$
Заменить: @#$% ("уникальная" строка)
2. Найти : @#$%
Заменить: (оставить пустым)

Для макроса аналогично:
Код:

Sub Main()
   Dim oDoc
   Dim oReplace

   oDoc = ThisComponent
   oReplace = oDoc.createReplaceDescriptor

   With oReplace
      .SearchRegularExpression = True
      .SearchString = "^$"
      .ReplaceString = "@#$%"
   End With
   oDoc.ReplaceAll(oReplace)

   With oReplace
      .SearchRegularExpression = True
      .SearchString = "@#$%"
      .ReplaceString = ""
   End With
   oDoc.ReplaceAll(oReplace)

End Sub
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vanya



Репутация: 0    

Зарегистрирован: 02.08.2011
Сообщения: 17

СообщениеДобавлено: Ср Сен 21, 2011 8:02 am    Заголовок сообщения: Ответить с цитатой

Да, это работает, спасибо.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
JohnSUN



Репутация: 0    

Зарегистрирован: 29.08.2011
Сообщения: 39
Откуда: Киев, Украина

СообщениеДобавлено: Ср Сен 21, 2011 5:26 pm    Заголовок сообщения: Ответить с цитатой

Другой способ - не "заменять пустые строки на пустые строки", а только найти их все (выделить) и удалить обычным Delet'ом
_________________
Владислав Орлов aka JohnSUN
LibreOffice 3.4.0 OOO340m1 (Build:12) WinXP SP2
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
vanya



Репутация: 0    

Зарегистрирован: 02.08.2011
Сообщения: 17

СообщениеДобавлено: Ср Сен 21, 2011 7:34 pm    Заголовок сообщения: Ответить с цитатой

JohnSUN писал(а):
Другой способ - не "заменять пустые строки на пустые строки", а только найти их все (выделить) и удалить обычным Delet'ом

Очень хороший способ.
Как его использовать в макросе?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
RFJ



Репутация: +1    

Зарегистрирован: 02.08.2011
Сообщения: 59

СообщениеДобавлено: Ср Сен 21, 2011 8:14 pm    Заголовок сообщения: Ответить с цитатой

vanya писал(а):
Как его использовать в макросе?

Можно так:
Код:
Sub Main()
   Dim oDoc
   Dim oReplace

   oDoc = ThisComponent
   oReplace = oDoc.createSearchDescriptor

   With oReplace
      .SearchRegularExpression = True
      .SearchString = "^$"
   End With

   Res=oDoc.findAll(oReplace)
   
   N=Res.Count
   
   For i=0 to N-1
     Res(i).String=""
   Next
   
End Sub
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
mathnew



Репутация: 0    

Зарегистрирован: 20.08.2011
Сообщения: 24

СообщениеДобавлено: Чт Сен 22, 2011 9:29 am    Заголовок сообщения: Ответить с цитатой

Ну, а проще всего использовать расширение AltSearch
http://extensions.services.openoffice.org/project/AltSearch
И результат лучше:
ДО

ПОСЛЕ
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vanya



Репутация: 0    

Зарегистрирован: 02.08.2011
Сообщения: 17

СообщениеДобавлено: Пт Сен 23, 2011 11:21 am    Заголовок сообщения: Ответить с цитатой

Макрос не работает, если я вставляю регулярное выражение, такое как в AltSearch.
.SearchString = "\p"
Shocked Rolling Eyes
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
RFJ



Репутация: +1    

Зарегистрирован: 02.08.2011
Сообщения: 59

СообщениеДобавлено: Сб Сен 24, 2011 8:40 am    Заголовок сообщения: Ответить с цитатой

vanya писал(а):
Макрос не работает, если я вставляю регулярное выражение, такое как в AltSearch.

.SearchString = "\p"


И не будет работать.

Судя по СПРАВКЕ (F1), "\p" не является регулярным выражением для LibreOffice/OpenOffice.

В расширении AltSearch использовано это обозначение, но реализован этот механизм по-другому.

Каким образом? Это надо смотреть код AltSearch.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
JohnSUN



Репутация: 0    

Зарегистрирован: 29.08.2011
Сообщения: 39
Откуда: Киев, Украина

СообщениеДобавлено: Вт Сен 27, 2011 10:13 am    Заголовок сообщения: Ответить с цитатой

Питоньяк предлагает еще несколько способов. Например, в "7.3.7. Удаление пустых абзацев, еще один пример" он для начала напоминает, что удаление пустых строк уже встроено в штатные средства Writer, в "Автоформат" (или в "Автозамена", зависит от локализации)... Это в Формат-Автозамена-Параметры автозамены. Хотя в справке и написано, что это в Сервис - Параметры автозамены. Там во вкладке Параметры есть отдельная птичка для "Удалять пустые абзацы".
Ну, а дальше идет текст макроса, который удаляет пустые абзацы или в выделенном тексте, или во всем документе, если выделения нет:
Код:
Listing 7.20: Remove empty paragraphs.
Sub RemoveEmptyParsWorker(oLCurs As Object, oRCurs As Object)
  Dim sParText As String, i As Integer
  Dim oText

  oText = oLCurs
  If IsNull(oLCurs) Or IsNull(oRCurs) Or IsNull(oText) Then Exit Sub
  If oText.compareRegionEnds(oLCurs, oRCurs) <= 0 Then Exit Sub
  oLCurs.goRight(0, False)
  Do While oLCurs.gotoNextParagraph(TRUE) AND _
           oText.compareRegionEnds(oLCurs, oRCurs) > 0
    'Yes, I know, limited to 64K here
    'If we have one  paragraph that is over 64K
    'Then I am in trouble!
    sParText = oLCurs.getString()
    i = Len(sParText)
    'We do not have short circuit logical. Drat!
    Do While i > 0
      If (Mid(sParText,i,1) = Chr(10)) OR (Mid(sParText,i,1) = Chr(13)) Then
        i = i - 1
      Else
        i = -1
      End If
    Loop
    If i = 0 Then
      oLCurs.setString("")
    Else
      oLCurs.goLeft(0,FALSE)
    End If
  loop
End Sub

С первым IF'ом там, по-моему, не все гладко - зачем проверять на null и oText, и oLCurs, если строчкой выше мы их сделали одинаковыми? Достаточно было бы проверить одного из них...
_________________
Владислав Орлов aka JohnSUN
LibreOffice 3.4.0 OOO340m1 (Build:12) WinXP SP2
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
RFJ



Репутация: +1    

Зарегистрирован: 02.08.2011
Сообщения: 59

СообщениеДобавлено: Вт Сен 27, 2011 12:31 pm    Заголовок сообщения: Ответить с цитатой

Питоньяк, конечно, "великий макрописатель".
Но этот макрос нельзя просто так использовать для проверки на тестовом файле, т.к. параметры, передаваемые макросу (oLCurs As Object, oRCurs As Object) не определены.
А хотелось бы что-нибудь "готовое к применению".
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vanya



Репутация: 0    

Зарегистрирован: 02.08.2011
Сообщения: 17

СообщениеДобавлено: Вт Сен 27, 2011 1:05 pm    Заголовок сообщения: Ответить с цитатой

Ни фига у этого Питоньяка не работает!
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
mathnew



Репутация: 0    

Зарегистрирован: 20.08.2011
Сообщения: 24

СообщениеДобавлено: Ср Сен 28, 2011 7:32 am    Заголовок сообщения: Ответить с цитатой

RFJ писал(а):
Это надо смотреть код AltSearch.


Не "ковыряя дотошно" код AltSearch, можно воспользоваться готовыми подпрограммами (Sub) и функциями (Function) из AltSearch для собственных макросов.

Так, как сделано тут: http://libreoffice.3nx.ru/viewtopic.php?t=24 для CyrillicTools.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
JohnSUN



Репутация: 0    

Зарегистрирован: 29.08.2011
Сообщения: 39
Откуда: Киев, Украина

СообщениеДобавлено: Ср Сен 28, 2011 10:12 am    Заголовок сообщения: Ответить с цитатой

RFJ писал(а):
этот макрос нельзя просто так использовать для проверки на тестовом файле

Разумеется. Для запуска макроса нужно использовать слегка переработанный макрос из листинга 7.14: A cumbersome selected text framework that works, немного выше по тексту.
Этот макрос проверяет не выделено ли чего в документе на момент запуска. Если ничего не выделено, переспрашивает у пользователя нужно ли обрабатывать весь текущий документ и в случае согласия вызывает указанную процедуру с параметрами oLCurs = "самое начало документа" и oRCurs ="самый конец документа". Если же выделение есть, то для КАЖДОГО из них (выделение-то может быть множественным, например, с зажатым Ctrl) запускается та же процедура.
А для работы самого макроса нужны еще три функции: IsAnythingSelected чтобы определить выделено ли сейчас в документе хоть что-нибудь (это в листинге 7.11: Is text selected?), GetLeftMostCursor и GetRightMostCursor для получения левой и правой границы выделения (это в листинге 7.13: Determine if the start or end comes first).
Ну, и нужно исправить четвертую строку в тексте самой процедуры RemoveEmptyParsWorker. Там должно быть
Код:
oText = oLCurs.getText()
(не зря это место меня насторожило).
Со всеми этими правками и дополнениями полный текст кода около 120 строк. Поэтому обычно и цитируется только действующая часть алгоритма (30 строк) - остальное не трудно найти в той же книге.

vanya писал(а):
Ни фига у этого Питоньяка не работает!

Ожидаешь бурной реакции? Не дождёшься
_________________
Владислав Орлов aka JohnSUN
LibreOffice 3.4.0 OOO340m1 (Build:12) WinXP SP2
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
vanya



Репутация: 0    

Зарегистрирован: 02.08.2011
Сообщения: 17

СообщениеДобавлено: Ср Сен 28, 2011 12:05 pm    Заголовок сообщения: Ответить с цитатой

Специально выписал из Питоньяка все функции для полного комплекта. (В 4-й строке oText = oLCurs.getText() !!!)
Вот весь код:
Код:
Sub RemoveEmptyPars
  Dim oCurs(), i%
  If Not CreateSelectedTextIterator(ThisComponent, "ALL empty paragraph will be removed from the ENTIRE document?", oCurs()) Then Exit Sub
  For i% = LBOUND(oCurs()) To UBOUND(oCurs())
    RemoveEmptyParsWorker(oCurs(i%, 0), oCurs(i%, 1))
  Next i%
End Sub
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub RemoveEmptyParsWorker(oLCurs As Object, oRCurs As Object)
  Dim sParText As String, i As Integer
  Dim oText

  oText = oLCurs.getText()
  If IsNull(oLCurs) Or IsNull(oRCurs) Or IsNull(oText) Then Exit Sub
  If oText.compareRegionEnds(oLCurs, oRCurs) <= 0 Then Exit Sub
  oLCurs.goRight(0, False)
  Do While oLCurs.gotoNextParagraph(TRUE) AND _
           oText.compareRegionEnds(oLCurs, oRCurs) > 0
    'Yes, I know, limited to 64K here
    'If we have one  paragraph that is over 64K
    'Then I am in trouble!
    sParText = oLCurs.getString()
    i = Len(sParText)
    'We do not have short circuit logical. Drat!
    Do While i > 0
      If (Mid(sParText,i,1) = Chr(10)) OR (Mid(sParText,i,1) = Chr(13)) Then
        i = i - 1
      Else
        i = -1
      End If
    Loop
    If i = 0 Then
      oLCurs.setString("")
    Else
      oLCurs.goLeft(0,FALSE)
    End If
  loop
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function CreateSelectedTextIterator(oDoc, sPrompt$, oCurs()) As Boolean
Dim lSelCount As Long 'Number of selected sections.
Dim lWhichSelection As Long 'Current selection item.
Dim oSels 'All of the selections
Dim oSel 'A single selection.
Dim oLCurs 'Cursor to the left of the current selection.
Dim oRCurs 'Cursor to the right of the current selection.
CreateSelectedTextIterator = True
If Not IsAnythingSelected(ThisComponent) Then
Dim i%
i% = MsgBox("No text selected!" + Chr(13) + sPrompt, _
1 OR 32 OR 256, "Warning")
If i% = 1 Then
oLCurs = oDoc.getText().createTextCursor()
oLCurs.gotoStart(False)
oRCurs = oDoc.getText().createTextCursor()
oRCurs.gotoEnd(False)
oCurs = DimArray(0, 1)
oCurs(0, 0) = oLCurs
oCurs(0, 1) = oRCurs
Else
oCurs = DimArray()
CreateSelectedTextIterator = False
End If
Else
oSels = ThisComponent.getCurrentSelection()
lSelCount = oSels.getCount()
oCurs = DimArray(lSelCount - 1, 1)
For lWhichSelection = 0 To lSelCount - 1
oSel = oSels.getByIndex(lWhichSelection)
REM If I want to know if NO text is selected, I could
REM do the following:
REM oLCurs = oSel.getText().CreateTextCursorByRange(oSel)
REM If oLCurs.isCollapsed() Then ...
oLCurs = GetLeftMostCursor(oSel)
oRCurs = GetRightMostCursor(oSel)
oCurs(lWhichSelection, 0) = oLCurs
oCurs(lWhichSelection, 1) = oRCurs
Next
End If
End Function
'******************************************************************
Function IsAnythingSelected(oDoc) As Boolean
Dim oSels 'All of the selections
Dim oSel 'A single selection
Dim oCursor 'A temporary cursor
IsAnythingSelected = False
If IsNull(oDoc) Then Exit Function
oSels = oDoc.getCurrentSelection()
If IsNull(oSels) Then Exit Function
If oSels.getCount() = 0 Then Exit Function
REM If there are multiple selections, then certainly something is selected
If oSels.getCount() > 1 Then
IsAnythingSelected = True
Else
oSel = oSels.getByIndex(0)
oCursor = oSel.getText().CreateTextCursorByRange(oSel)
If Not oCursor.IsCollapsed() Then IsAnythingSelected = True
End If
End Function
Sub GetLeftRightCursors(oSel, oLeft, oRight)
Dim oCursor
If oSel.getText().compareRegionStarts(oSel.getEnd(), oSel) >= 0 Then
oLeft = oSel.getText().CreateTextCursorByRange(oSel.getEnd())
oRight = oSel.getText().CreateTextCursorByRange(oSel.getStart())
Else
oLeft = oSel.getText().CreateTextCursorByRange(oSel.getStart())
oRight = oSel.getText().CreateTextCursorByRange(oSel.getEnd())
End If
oLeft.goRight(0, False)
oRight.goLeft(0, False)
End Sub
'******************************************************************
Function RankChar(iPrevChar, iCurChar) As Integer
If Not IsWhiteSpace(iCurChar) Then 'Char is not WS, ignore it
RankChar = 0
ElseIf iPrevChar = 0 Then 'Line start and char is WS
RankChar = 1 ' so delete the character.
ElseIf Not IsWhiteSpace(iPrevChar) Then 'Char is WS but previous was not
RankChar = 0 ' so ignore the current character.
ElseIf iPrevChar = 13 Then 'Previous char is highest ranked WS
RankChar = 1 ' so delete the current character.
ElseIf iCurChar = 13 Then 'Character is highest ranked WS
RankChar = -1 ' so delete the previous character.
ElseIf iPrevChar = 10 Then 'No new Paragraph. Check prev for new line
RankChar = 1 'so delete the current character.
ElseIf iCurChar = 10 Then 'No new Pars. Check current for new line.
RankChar = -1 ' so delete the previous character.
ElseIf iPrevChar = 9 Then 'No new Line! Check previous for tab
RankChar = 1 ' so delete the current character.
ElseIf iCurChar = 9 Then 'No new Line. Check current char for tab
RankChar = -1 ' so delete the previous character.
ElseIf iPrevChar = 160 Then 'No Tabs! Check previous char for hard space
RankChar = 1 ' so delete the current character.
ElseIf iCurChar = 160 Then 'No Tabs. Check current char for hard space
RankChar = -1 'so delete the previous character.
ElseIf iPrevChar = 32 Then 'No hard space, check previous for a space
RankChar = 1 'so delete the current character.
ElseIf iCurChar = 32 Then 'No hard spaces so check current for a space
RankChar = -1 'so delete the previous character.
Else 'Should probably not get here
RankChar = 0 'so simply ignore it!
End If
End Function
'******************************************************************
Function IsWhiteSpace(iChar As Integer) As Boolean
Select Case iChar
Case 9, 10, 13, 32, 160
IsWhiteSpace = True
Case Else
IsWhiteSpace = False
End Select
End Function
'******************************************************************
Function GetLeftMostCursor(oSel As Object) As Object
Dim oRange 'Left most range.
Dim oCursor 'Cursor at the left most range.
If oSel.getText().compareRegionStarts(oSel.getEnd(), oSel) >= 0 Then
oRange = oSel.getEnd()
Else
oRange = oSel.getStart()
End If
oCursor = oSel.getText().CreateTextCursorByRange(oRange)
oCursor.goRight(0, False)
GetLeftMostCursor = oCursor
End Function
'******************************************************************
Function GetRightMostCursor(oSel As Object) As Object
Dim oRange 'Right most range.
Dim oCursor 'Cursor at the right most range.
If oSel.getText().compareRegionStarts(oSel.getEnd(), oSel) >= 0 Then
oRange = oSel.getStart()
Else
oRange = oSel.getEnd()
End If
oCursor = oSel.getText().CreateTextCursorByRange(oRange)
oCursor.goLeft(0, False)
GetRightMostCursor = oCursor
End Function


Тестовый файл с этим кодом http://ifolder.ru/26017937

На картинках результат работы этого кода.

Оригинал


Результат



Самый худший вариант из предложенных!

Таблицу вообще не обработал.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Начать новую тему   Ответить на тему    Список форумов Форум Libreoffice -> Writer Часовой пояс: GMT
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2005 phpBB Group
Вы можете бесплатно создать форум на MyBB2.ru, RSS