Help

Автор Рязанцев, 8 июля 2024, 10:26

0 Пользователи и 1 гость просматривают эту тему.

aequit

Здравствуйте! Ниже код, как это (перенос предлогов) реализовано на VBA в Word.
Неразрывный пробел ставится, только если необходимое слово (предлог) из перечисленных в массиве стоит в конце строки.
Попытался разобраться, как найти конец строки в Basic LO - запутался ???
Почему oViewCursor.gotoEndOfLine(False) Перемещает видимый курсор не в конец, а в начало следующей строки?
При этом Print oViewCursor.isAtEndOfLine() и Print oViewCursor.isAtStartOfLine(), соответственно True?
Если переместить курсор в конец строки клавишей End, то курсор перемещается перед последним пробелом в строке и isAtEndOfLine()=False ???
Напротив, в Word нажатие клавиши End переносит курсор после последнего пробела в строке, как, имхо, и должно быть, так как Selection.IPAtEndOfLine при этом True :roll:
Или я неправильно понимаю логику работы gotoEndOfLine?

Sub PerenosPredlogov()
'Предварительно выделить требуемый диапазон текста.
ActiveDocument.ActiveWindow.View.Type = wdPrintView
'ActiveDocument.Range(0, 0).Select
SimpleReplaceAtEndOfLine3 Selection.Range, "", "\1^s"
End Sub

Sub SimpleReplaceAtEndOfLine3(FindRange As Range, What As String, ForWhat As String)
Dim mark
If FindRange.Duplicate = "" Then
MsgBox "Выделите текст!", vbInformation, "Обработка невозможна!"
Exit Sub
End If
Dim r As Word.Range
Dim EOL As Boolean
Dim n As Long
Dim arrWhat
arrWhat = Array("(<[Нн]а)", "(<[Ии]ли)", "(<[Вв]о)", "(<[Вв]иду)", "(<[Вв]опреки)", "(<[Вв]след)", _
"(<[Вв]следствие)", "(<[Дд]ля)", "(<[Дд]о)", "(<[Ии]з)", "(<[Ии]з-за)", "(<[Зз]а)", "(<[Ии]сключая)", _
"(<[Кк]о)", "(<[Кк]роме)", "(<[Нн]а)", "(<[Мм]ежду)", "(<[Нн]ад)", "(<[Нн]е)", "(<[Оо]б)", "(<[Оо]бо)", _
"(<[Оо]коло)", "(<[Оо]т)", "(<[Пп]еред)", "(<[Пп]о)", "(<[Пп]од)", "(<[Пп]ред)", "(<[Пп]ри)", "(<[Пп]ро)", _
"(<[Пп]ротив)", "(<[Пп]ри)", "(<[а-яА-Яa-zA-Z]{1})")
Dim i As Integer
i = 1
For i = 1 To 3
    For Each mark In arrWhat
    Set r = FindRange.Duplicate
    r.Collapse Direction:=wdCollapseStart
    With r.Find
        .ClearFormatting
        .Replacement.ClearFormatting
        .Forward = True
        .Wrap = wdFindStop
        .MatchWildcards = True
        .Text = mark & "([ ]@)"
        .Replacement.Text = ForWhat
    End With
    Do While r.End < r.StoryLength - 1
        r.Collapse Direction:=wdCollapseEnd
        r.Find.Execute Replace:=wdReplaceNone
        If r.Find.Found <> True Then Exit Do
        If FindRange.Start < FindRange.End Then
            If r.InRange(FindRange) <> True Then Exit Do
        End If
        ' обработка
        r.Select
        n = Selection.EndOf(Unit:=Word.wdLine, Extend:=Word.wdMove)
        EOL = Selection.IPAtEndOfLine
        If (n = 1) And EOL Then
            r.Collapse Direction:=wdCollapseStart
            r.Find.Execute Replace:=wdReplaceOne
        End If
    Loop
    Next
i = i + 1
Next
End Sub

mikekaganski

Во-первых, давайте заметим, что то, что Вы описываете, относится только к разрывам строк, но не к концу абзаца.

Обратите внимание, что любое количество пробелов в конце строки не переносится на следующую сторону (это стандарт, определённый, например, в Unicode Line Breaking Algorithm). Это значит, что конец данной строки - это позиция после всех пробелов непосредственно перед следующим непробельным символом (который будет начинать следующую строку).

Теперь посмотрите, что значит поставить курсор после последнего пробела. Это позиция перед первым символом следующей строки. И Word здесь позволяет двусмысленность. Рассмотрим место разрыва "разорванный текст" между словом "разорванный" и словом "текст". Если Вы двигаете курсор по строке клавишей стрелки (вправо), то после позиции ещё на первой строке после буквы "й" перед пробелом, следующее нажатие стрелки перенесёт курсор в начало следующей строки после пробела перед буквой "т". Нажатие, скажем, клавиши "к" добавит букву "к" в начале слова "текст" на второй строке, получится "ктекст". Но если вместо стрелок Вы в первой строке нажмёте клавишу End, то Вы попадёте в конец первой строки после пробела, перед буквой "т". Вы можете проверить, что это другое место, где сейчас мигает курсор - то же самое, что и вначале следующей строки: нажмите клавишу "к", и она добавится в начало слова на следующей строке.

В LibreOffice нет такой двусмысленности. Позиция курсора после всех пробелов перед буквой на следующей строке всегда отображается на следующей строке. Правда, при этом оказывается, что клавиша End переносит курсор не в настоящий конец строки, а перед пробелом.

Вопрос: чем это мешает при программировании?
С уважением,
Михаил Каганский

aequit

Цитата: mikekaganski от 15 июля 2024, 12:13Но если вместо стрелок Вы в первой строке нажмёте клавишу End, то Вы попадёте в конец первой строки после пробела
Проверил. Только в Word я попадаю в конец строки после пробела. В Writer при нажатии клавиши END я попадаю перед пробелом в конце строки, а не в настоящий конец строки.
А мешает это тем, что после gotoEndOfLine  oViewCursor.isAtEndOfLine()  и  oViewCursor.isAtStartOfLine()  одновременно выдают True. Не могу понять, как одновременно конец строки может быть равным началу строки ???

McAaron

Периодически делаю отчеты, выровненные по ширине и в котором переносы по требованию нормоконтроля заказчика запрещены. Соответственно, по тексту возникают большие пробелы между словами, что заказчику тоже не нравится.
Когда столкнулся с этим первый раз, спросил нормоконтролера, как решить проблему. Он ответил, что просто нужно изложить материал немного по другому, чтобы чтобы пробелы сжались. Собственно, так и поступаю -- набираю и контролирую разметку. Причем, не только для этого заказчика, а для всех документов, где переносы не допускаются.