Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/22: Рейтинг темы: голосов - 22, средняя оценка - 4.73
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
1

Удаление комментариев в коде

26.10.2015, 17:16. Показов 4371. Ответов 16
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый вечер! Может кто знает как быстро из кода VBA удалить все комментарии, а то у меня комментарии размером почти как сам код, очень утяжеляет рабочий код.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.10.2015, 17:16
Ответы с готовыми решениями:

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

Удаление комментариев в программном коде Си
Удаление комментариев В языке Си комментарии к исходному коду начинаются с двух символов /* и...

Поиск комментариев в коде C#
Нужно в массиве строк( код C#) найти (большие) комментарии типа /* Бла бла бла бла бла бла бал...

Использование русских комментариев в коде
как сделать так чтобы в Паскале можно было писать русскими буквами???у мя пишет чисто английскими...

16
15145 / 6418 / 1731
Регистрация: 24.09.2011
Сообщений: 9,999
26.10.2015, 18:18 2
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

aleks_des, http://www.vbaexpress.com/kb/g... ?kb_id=266
Вообще, много комментариев - это замечательно!
А на работу кода наличие комментариев не влияет, только на размер файла.
1
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
26.10.2015, 18:33  [ТС] 3
Ок спасибо, у меня просто простой вордовский файл почти мегабайт весит, нужно объем уменьшить
0
Модератор
Эксперт MS Access
11960 / 4828 / 779
Регистрация: 07.08.2010
Сообщений: 14,138
Записей в блоге: 4
26.10.2015, 19:15 4
вряд ли это код ---скорей туда супер-рисунок закинули или очень много формул/рисунков
0
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
26.10.2015, 19:27  [ТС] 5
Он действительно не работает,
Во-первых написан для Excel, мне нужно для Word (моя вина, не уточнил) попытался переписать для word, не нашел фразу аналог в word
Visual Basic
1
 If Quotes = Application.WorksheetFunction.Odd(Quotes) Then
Во-вторых этот код даже в Excel не работает
0
4134 / 2238 / 940
Регистрация: 01.12.2010
Сообщений: 4,624
26.10.2015, 20:44 6
VBA Code Cleaner

P.S. Обратите внимание на то, что здесь также не удаляются комментарии, созданные с помощью инструкции REM
0
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
26.10.2015, 20:48  [ТС] 7
это вы про что?
0
4134 / 2238 / 940
Регистрация: 01.12.2010
Сообщений: 4,624
26.10.2015, 21:10 8
Пардон, полное название утилиты Excel VBA Code Cleaner, так что можете не обращать внимание на мой пост
0
6081 / 1325 / 195
Регистрация: 12.12.2012
Сообщений: 1,023
26.10.2015, 23:25 9
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

Здравствуйте, aleks_des,
Весьма любопытная задача. Набросал свой дилетантский (наверное), зато кроссплатформенный (в том смысле, что он работает в любых приложениях, использующих VBA) вариант макроса удаления комментариев... Может быть, он вас заинтересует.

Программа удаления комментариев из кода VBA
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Type CursorPos
    Ln As Long
    Col As Long
End Type
 
Sub DeleteRemarks()
    Dim quot As String, apos As String, remPattern As String
    Dim env As Object, prj As Object, com As Object, cmd As Object
    Dim docName As String, lineCount As Long, lastLineCharCount As Long
    Dim cursorStart As CursorPos, cursorEnd As CursorPos
    Dim remFound As Boolean, remLine As String, beforeRem As String
    Dim i As Long, n As Long, quotCount As Long, ch As String * 1
    quot = Chr(34): apos = Chr(39): remPattern = apos & Chr(42)
    Set env = Application.VBE
    docName = env.MainWindow.Caption
    On Error Resume Next
    docName = Split(docName, "-")(1)
    On Error GoTo 0
    docName = Trim(Replace(docName, "[running]", ""))
    Set prj = env.ActiveVBProject
    If MsgBox("Сейчас будут удалены все комментарии в программных модулях проекта " & prj.Name & " (документ " & docName & "). Вы уверены?", vbYesNo + vbDefaultButton2, "Необратимая операция (предупреждение)") = vbYes Then
    For Each com In prj.VBComponents
        Set cmd = com.CodeModule
        lineCount = cmd.CountOfLines
        lastLineCharCount = Len(cmd.Lines(lineCount, 1))
        cursorStart.Ln = 1
        cursorStart.Col = 1
        cursorEnd.Ln = lineCount
        cursorEnd.Col = lastLineCharCount + 1
        remFound = cmd.Find(remPattern, cursorStart.Ln, cursorStart.Col, cursorEnd.Ln, cursorEnd.Col, , , True)
        While remFound
            remLine = cmd.Lines(cursorStart.Ln, 1)
            n = Len(remLine)
            beforeRem = Space(n)
            quotCount = 0
            For i = 1 To n
                ch = Mid(remLine, i, 1)
                If ch = apos Then
                    If quotCount Mod 2 = 0 Then Exit For Else Mid(beforeRem, i, 1) = apos
                ElseIf ch = quot Then
                    Mid(beforeRem, i, 1) = quot
                    quotCount = quotCount + 1
                Else
                    Mid(beforeRem, i, 1) = ch
                End If
            Next i
            If i <= n Then
                If Len(Trim(beforeRem)) = 0 Then
                    cmd.DeleteLines cursorStart.Ln, 1
                    cursorStart.Ln = cursorStart.Ln - 1
                Else
                    cmd.ReplaceLine cursorStart.Ln, RTrim(beforeRem)
                End If
            End If
            cursorStart.Ln = cursorStart.Ln + 1
            cursorStart.Col = 1
            cursorEnd.Ln = lineCount
            cursorEnd.Col = lastLineCharCount + 1
            remFound = cmd.Find(remPattern, cursorStart.Ln, cursorStart.Col, cursorEnd.Ln, cursorEnd.Col, , , True)
        Wend
    Next com
    End If
End Sub

С уважением,
Аксима
1
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
27.10.2015, 10:23  [ТС] 10
Все четко! Спасибо. На работу дилетанта не похоже, как минимум нужно знание структуры VBA.

А комментариев нет, удалились УдаляторомКомментариев?
0
6081 / 1325 / 195
Регистрация: 12.12.2012
Сообщений: 1,023
27.10.2015, 12:19 11
Лучший ответ Сообщение было отмечено aleks_des как решение

Решение

Здравствуйте, aleks_des,
Если я правильно понял, что вас интересуют также пояснения к программе, то предлагаю вашему вниманию...

Комментарии к коду программы "УдаляторКомментариев".

Введение

Назначение программы "УдаляторКомментариев" - удаление комментариев из кода VBA. Для ускорения работы и повышения надежности (неизвестно, как поведет себя программа при модификации самой себя) она не содержит комментариев. Этот пробел восполняется далее.

Комментарии
  1. Visual Basic
    1
    2
    3
    4
    
    Type CursorPos
        Ln As Long
        Col As Long
    End Type
    Тип CursorPos разработан для описания позиции курсора в IDE. Приняты те же сокращения, что в самой IDE: Ln - сокращение от Line и означает номер строки программного кода, Col - сокращение от Column и означает номер столбца (вертикальной линии, разделяющей символы). Самая первая линия находится перед самым первым символом и имеет номер 1.
  2. Visual Basic
    1
    2
    3
    4
    5
    6
    
    Dim quot As String, apos As String, remPattern As String
    Dim env As Object, prj As Object, com As Object, cmd As Object
    Dim docName As String, lineCount As Long, lastLineCharCount As Long
    Dim cursorStart As CursorPos, cursorEnd As CursorPos
    Dim remFound As Boolean, remLine As String, beforeRem As String
    Dim i As Long, n As Long, quotCount As Long, ch As String * 1
    quot - Переменная для хранения символа "Двойная кавычка" (").
    apos - Переменная для хранения символа "Апостроф" (').
    remPattern - Переменная, хранящая шаблон для первичного поиска комментариев.
    env, prj, com, cmd - Переменные, относящиеся к объектной модели IDE.
    docName - Переменная для хранения имени документа, программный проект которого подлежит очистке.
    lineCount - Переменная для хранения количества строк кода в программном модуле.
    lastLineCharCount - Переменная для хранения количества символов в последней строке кода.
    cursorStart, cursorEnd - Переменные для хранения границ выделения, в котором осуществляется поиск комментария.
    remFound - Флаг, указывающий на то, что была найдена строка, похожая на комментарий.
    remLine - Текст строки, похожей на комментарий.
    beforeRem - Текст части строки, находящейся перед комментарием.
    i, n - Переменные цикла.
    quotCount - Счётчик количества двойных кавычек. Необходим для того, чтобы определить, находится ли символ апострофа внутри строки или является началом комментария.
    ch - Переменная для хранения отдельного символа анализируемой строки.
  3. Visual Basic
    1
    
    Set env = Application.VBE
    Получаем ссылку на объект, предоставляющий доступ к среде разработчика.
  4. Visual Basic
    1
    2
    3
    4
    5
    
    docName = env.MainWindow.Caption
    On Error Resume Next
    docName = Split(docName, "-")(1)
    On Error GoTo 0
    docName = Trim(Replace(docName, "[running]", ""))
    Получаем заголовок основного окна среды разработчика, который обычно имеет вид "Microsoft Visual Basic for Applications - <имя документа> [<статус выполнения макроса>] [ - <имя активного модуля>]".
    Из заголовка выделяем имя книги ввместе со статусом и удаляем статус выполнения макроса (пользователя он не интересует).
  5. Visual Basic
    1
    
    Set prj = env.ActiveVBProject
    Получаем ссылку на активный проект.
  6. Visual Basic
    1
    
    If MsgBox("Сейчас будут удалены все комментарии в программных модулях проекта " & prj.Name & " (документ " & docName & "). Вы уверены?", vbYesNo + vbDefaultButton2, "Необратимая операция (предупреждение)") = vbYes Then
    Запрашиваем подтверждение операции по удалению макросов. Комментарии перед удалением не запоминаются, поэтому восстановить их будет невозможно.
  7. Visual Basic
    1
    2
    
    For Each com In prj.VBComponents
    Set cmd = com.CodeModule
    Обрабатываем все программные модули проекта.
  8. Visual Basic
    1
    2
    3
    4
    5
    6
    
    lineCount = cmd.CountOfLines
    lastLineCharCount = Len(cmd.Lines(lineCount, 1))
    cursorStart.Ln = 1
    cursorStart.Col = 1
    cursorEnd.Ln = lineCount
    cursorEnd.Col = lastLineCharCount + 1
    Получаем максимально раннюю и максимально позднюю позиции курсора. Сформированное с их помощью выделение - это выделение всего кода в программном модуле.
  9. Visual Basic
    1
    
    remFound = cmd.Find(remPattern, cursorStart.Ln, cursorStart.Col, cursorEnd.Ln, cursorEnd.Col, , , True)
    Ищем строку, похожую на комментарий. Используем шаблон "'*", а не "'", чтобы каждая строка находилась только один раз (например, с шаблоном "'" строка MsgBox("'Hello'") будет обработана дважды (т.к. будут найден сначала первый, а потом второй апостроф). С шаблоном "'*" будет найдена подстрока 'Hello'"), а затем поиск продолжится уже в других строках.
  10. Visual Basic
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    While remFound
        remLine = cmd.Lines(cursorStart.Ln, 1)
        n = Len(remLine)
        beforeRem = Space(n)
        quotCount = 0
        For i = 1 To n
            ch = Mid(remLine, i, 1)
            If ch = apos Then
                    If quotCount Mod 2 = 0 Then Exit For Else Mid(beforeRem, i, 1) = apos
            ElseIf ch = quot Then
                Mid(beforeRem, i, 1) = quot
                quotCount = quotCount + 1
            Else
                Mid(beforeRem, i, 1) = ch
            End If
        Next i
    Если найдена строка, похожая на комментарий, то есть строка, содержащая апостроф или апострофы, то анализируем ее на предмет того, что она действительно содержит комментарий. Для этого проходим по ней посимвольно, параллельно подсчитывая количество двойных кавычек. Если находим апостроф, а количество найденных перед ним двойных кавычек четно, то апостроф действительно предваряет комментарий, и мы переходим к удалению комментария. Если же количество двойных кавычек перед апострофом нечетно, то апостроф является частью строкового литерала, а не признаком начала комментария.
    В ходе прохода по строке в переменной beforeRem сохраняем часть текста, найденную перед комментарием.
  11. Visual Basic
    1
    2
    3
    4
    5
    6
    7
    8
    
                If i <= n Then
                    If Len(Trim(beforeRem)) = 0 Then
                        cmd.DeleteLines cursorStart.Ln, 1
                        cursorStart.Ln = cursorStart.Ln - 1
                    Else
                        cmd.ReplaceLine cursorStart.Ln, RTrim(beforeRem)
                    End If
                End If
    Если комментарий найден, и перед ним ничего нет, кроме пробельных символов, то удаляем содержащую его строку. Иначе, заменяем эту строку текстом без комментария, а также без пробельных символов, которые были перед этим комментарием.
  12. Visual Basic
    1
    2
    3
    4
    5
    
    cursorStart.Ln = cursorStart.Ln + 1
    cursorStart.Col = 1
    cursorEnd.Ln = lineCount
    cursorEnd.Col = lastLineCharCount + 1
    remFound = cmd.Find(remPattern, cursorStart.Ln, cursorStart.Col, cursorEnd.Ln, cursorEnd.Col, , , True)
    Выделяем код со следующей строки и до конца модуля и повторяем поиск строк, похожих на комментарии, до тех пор, пока таковые находятся.
  13. Visual Basic
    1
    
    Next com
    После очистки всех комментариев в программном модуле переходим к следующему модулю (если есть).

Резюме

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

С уважением,
Аксима
4
Заблокирован
27.10.2015, 12:36 12
Visual Basic
1
2
3
'комментарий _
это тоже комментарий(но данная строка не удалена Удалятором, в полученном коде будет ошибка)
Rem И этот комментарий не удалён
2
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
27.10.2015, 23:24  [ТС] 13
Аксима благодарю за подробнейший комментарий. На этом примере попробую немного изучить структуру VBA
0
5562 / 1368 / 150
Регистрация: 08.02.2009
Сообщений: 4,109
Записей в блоге: 30
28.10.2015, 04:15 14
Припомнив тему dimonser’а Подсветка синтаксиса в word 2007 — попробовал использовать зелёный цвет этих самых комментариев.

Но так глубоко не забурился, однако нашёл шаблон поиска* прямо в коде:
_________________
* не считая упомянутых Апострофф’ом многострочных комментов
Миниатюры
Удаление комментариев в коде   Удаление комментариев в коде  
0
6081 / 1325 / 195
Регистрация: 12.12.2012
Сообщений: 1,023
19.11.2015, 17:33 15
После многих проб и ошибок сумел реализовать вариант программы, учитывающий ценные замечания от Апостроффа. В этом мне очень помогла теория конечных автоматов.

Программа удаления комментариев из кода VBA (улучшенная версия)
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
Enum Status 'Состояния детерминированного конечного автомата, осуществляющего поиск комментариев в тексте.
    INITIAL 'Начальное.
    SPACE_FOUND 'Обнаружены хвостовые пробелы в начале линии.
    QUOT_FOUND 'Обнаружена открывающая кавычка строкового литерала. Поиск комментария в литерале не производится.
    REMARK_FOUND 'Обнаружен комментарий.
    R_FOUND 'Подозрение на 1-ю букву ключевого слова Rem.
    RE_FOUND 'Подозрение на 2 буквы ключевого слова Rem.
    REM_FOUND 'Подозрение на 3 буквы ключевого слова Rem.
    AFTERSPACE 'Текст после хвостовых пробелов (не строковой литерал и не комментарий).
    CR_FOUND 'Найден перевод строки.
    REMSPACE_FOUND 'Найден пробел внутри комментария (если за пробелом следует знак подчеркивания - это признак многострочного комментария).
    UNDERLINE_FOUND 'Найден знак подчеркивания после пробела (перевод строки больше не означает конец комментария).
End Enum
Rem Процедура удаления комментариев из кода VBA.
Sub DeleteRemarks()
    Dim env As Object, prj As Object, com As Object, cm As Object
    Dim i As Long, j As Long, k As Long, lc As Long, sc As Long, n As Long
    Dim doc As String, code() As Byte, clean() As Byte
    Dim s As Status, skipLine As Boolean
    Set env = Application.VBE
    Set prj = env.ActiveVBProject
    doc = "несохраненный"
    On Error Resume Next
    doc = prj.Filename
    On Error GoTo 0
    'Уточняем у пользователя, действительно ли он хочет удалить все комментарии.
    If MsgBox("Сейчас будут удалены все комментарии в программных модулях проекта " & prj.Name & " (документ " & doc & "). Вы уверены?", vbYesNo + vbDefaultButton2, "Необратимая операция (предупреждение)") = vbYes Then
        For Each com In prj.VBComponents
            Set cm = com.CodeModule
            lc = cm.CountOfLines
            If lc Then 'Если есть строки для анализа...
                code = cm.Lines(1, lc)
                n = UBound(code)
                ReDim clean(0 To n) As Byte
                s = INITIAL 'Устанавливаем автомат в начальное состояние.
                sc = 0
                k = 0
                skipLine = False
                For i = 0 To n Step 2
                    Select Case s
                        Case INITIAL
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 32
                                        s = SPACE_FOUND
                                        sc = 1
                                    Case 34
                                        s = QUOT_FOUND
                                    Case 39
                                        s = REMARK_FOUND
                                        skipLine = True
                                    Case 82
                                        s = R_FOUND
                                    Case Else
                                        s = AFTERSPACE
                                End Select
                            End If
                        Case SPACE_FOUND
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 32
                                        sc = sc + 1
                                    Case 39
                                        s = REMARK_FOUND
                                        skipLine = True
                                    Case 82
                                        s = R_FOUND
                                    Case Else
                                        For j = 1 To sc
                                            clean(k) = 32
                                            clean(k + 1) = 0
                                            k = k + 2
                                        Next j
                                        If code(i) = 34 Then s = QUOT_FOUND Else s = AFTERSPACE
                                End Select
                            End If
                        Case R_FOUND
                            If code(i) = 101 And code(i + 1) = 0 Then
                                s = RE_FOUND
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    clean(k + 1) = 0
                                    k = k + 2
                                Next j
                                clean(k) = 82
                                clean(k + 1) = 0
                                k = k + 2
                                If code(i) = 13 And code(i + 1) = 0 Then s = CR_FOUND Else s = AFTERSPACE
                            End If
                        Case RE_FOUND
                            If code(i) = 109 And code(i + 1) = 0 Then
                                s = REM_FOUND
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    clean(k + 1) = 0
                                    k = k + 2
                                Next j
                                clean(k) = 82
                                clean(k + 1) = 0
                                k = k + 2
                                clean(k) = 101
                                clean(k + 1) = 0
                                k = k + 2
                                If code(i) = 13 And code(i + 1) = 0 Then s = CR_FOUND Else s = AFTERSPACE
                            End If
                        Case REM_FOUND
                            If code(i + 1) = 0 And (code(i) = 13 Or code(i) = 32) Then
                                skipLine = True
                                If code(i) = 13 Then s = CR_FOUND Else s = REMARK_FOUND
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    clean(k + 1) = 0
                                    k = k + 2
                                Next j
                                clean(k) = 82
                                clean(k + 1) = 0
                                k = k + 2
                                clean(k) = 101
                                clean(k + 1) = 0
                                k = k + 2
                                clean(k) = 109
                                clean(k + 1) = 0
                                k = k + 2
                                s = AFTERSPACE
                            End If
                        Case AFTERSPACE
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 34
                                        s = QUOT_FOUND
                                    Case 39
                                        s = REMARK_FOUND
                                End Select
                            End If
                        Case REMARK_FOUND
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 32
                                        s = REMSPACE_FOUND
                                End Select
                            End If
                        Case QUOT_FOUND
                            If code(i) = 34 And code(i + 1) = 0 Then s = AFTERSPACE
                        Case CR_FOUND
                            'Если в абзаце(ах) исходника нет ничего, кроме комментария (о чем сигнализирует _
                            булева переменная skipLine), то в выходной текст абзац не добавляем.
                            If skipLine Then
                                skipLine = False
                            Else
                                clean(k) = 13
                                k = k + 2
                                clean(k) = 10
                                k = k + 2
                            End If
                            s = INITIAL
                        Case REMSPACE_FOUND
                            If code(i) = 95 And code(i + 1) = 0 Then s = UNDERLINE_FOUND Else s = REMARK_FOUND
                        Case UNDERLINE_FOUND
                            s = REMARK_FOUND
                    End Select
                    If s = QUOT_FOUND Or s = AFTERSPACE Then
                        clean(k) = code(i)
                        clean(k + 1) = code(i + 1)
                        k = k + 2
                    End If
                Next i
                If k < n Then
                    cm.DeleteLines 1, lc
                    cm.AddFromString CStr(clean)
                End If
            End If
        Next com
        MsgBox "Все комментарии удалены", vbInformation, "Результат"
    Else
        MsgBox "Удаление комментариев отменено.", vbInformation, "Результат"
    End If
End Sub

Была также мысль реализовать поиск комментариев через регулярные выражения, но производительность недетерминированных конечных автоматов (на которые отображаются регулярные выражения) ниже, чем производительность детерминированных конечных автоматов, что для больших объемов текста весьма существенно. Текущий вариант сочетает надежность с высокой производительностью.

Если будут какие-то замечания или пожелания, буду рад выслушать.

С уважением,
Аксима
2
194 / 13 / 3
Регистрация: 20.01.2015
Сообщений: 174
19.11.2015, 20:24  [ТС] 16
Не корректно работает. Попробуйте на примере:
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Private Function Ячейки(Optional n As Integer)
    If txt_Ячейки.Value <> "" Then
        If txt_Ячейки.Value Like "* *" Or txt_Ячейки.Value Like "*,*" Then
            Ячейки = IIf(n = 1, " (", "") & IIf(n = 2, ", ", "") & "ячейки " & txt_Ячейки.Value & IIf(n = 1, ")", "")
        Else
            Ячейки = IIf(n = 1, " (", "") & IIf(n = 2, ", ", "") & "ячейка " & txt_Ячейки.Value & IIf(n = 1, ")", "")
        End If
    End If
End Function
 
Private Sub cmd_Печать_Click()
On Error GoTo Ошибка
    Dim sPrinter As String ' переменная имени активного принтера
    sPrinter = ActivePrinter ' присваиваем имя активный принтера
    ' Принтер по умолчанию на время работы приложения
    ActivePrinter = Work_Form.txt_Принтер.Value ' Присваивает имя принтера из поля "Принтер по умолчанию" в настройках
    ' Печать по параметрам: Количество копий, Сортирова по копиям (False)
    ActiveDocument.PrintOut Copies:=txt_Копии.Value, Collate:=ch_Сортировка.Value
    Application.ActivePrinter = sPrinter ' возвращает активный принтер на момент открытия документа
    Exit Sub
Ошибка:
    Dim mBox As VbMsgBoxResult
    mBox = MsgBox("      Заданный принтер" & vbCrLf & _
           Work_Form.txt_Принтер.Value & vbCrLf & _
           "не найден. Задать принтер?", vbYesNo + vbExclamation, "Ошибка принтера")
    If mBox = vbYes Then cmd_Принтер_Click
End Sub
Добавлено через 21 минуту
Кстати, это удаление комментариев можно вернуть кнопкой отмена
0
6081 / 1325 / 195
Регистрация: 12.12.2012
Сообщений: 1,023
19.11.2015, 21:30 17
aleks_des, действительно, упустил ряд переходов в автомате... С этими автоматами надо быть очень аккуратным и внимательным.

Прилагаю исправленный код, и выражаю вам огромную благодарность за тестирование.

Программа удаления комментариев из кода VBA (улучшенная и скорректированная версия)
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
Enum Status 'Состояния детерминированного конечного автомата, осуществляющего поиск комментариев в тексте.
    INITIAL 'Начальное.
    SPACE_FOUND 'Обнаружены хвостовые пробелы в начале линии.
    QUOT_FOUND 'Обнаружена открывающая кавычка строкового литерала. Поиск комментария в литерале не производится.
    REMARK_FOUND 'Обнаружен комментарий.
    R_FOUND 'Подозрение на 1-ю букву ключевого слова Rem.
    RE_FOUND 'Подозрение на 2 буквы ключевого слова Rem.
    REM_FOUND 'Подозрение на 3 буквы ключевого слова Rem.
    AFTERSPACE 'Текст после хвостовых пробелов (не строковой литерал и не комментарий).
    CR_FOUND 'Найден перевод строки.
    REMSPACE_FOUND 'Найден пробел внутри комментария (если за пробелом следует знак подчеркивания - это признак многострочного комментария).
    UNDERLINE_FOUND 'Найден знак подчеркивания после пробела (перевод строки больше не означает конец комментария).
End Enum
Rem Процедура удаления комментариев из кода VBA.
Sub DeleteRemarks()
    Dim env As Object, prj As Object, com As Object, cm As Object
    Dim i As Long, j As Long, k As Long, lc As Long, sc As Long, n As Long
    Dim doc As String, code() As Byte, clean() As Byte
    Dim s As Status, skipLine As Boolean
    Set env = Application.VBE
    Set prj = env.ActiveVBProject
    doc = "несохраненный"
    On Error Resume Next
    doc = prj.Filename
    On Error GoTo 0
    'Уточняем у пользователя, действительно ли он хочет удалить все комментарии.
    If MsgBox("Сейчас будут удалены все комментарии в программных модулях проекта " & prj.Name & " (документ " & doc & "). Вы уверены?", vbYesNo + vbDefaultButton2, "Необратимая операция (предупреждение)") = vbYes Then
        For Each com In prj.VBComponents
            Set cm = com.CodeModule
            lc = cm.CountOfLines
            If lc Then 'Если есть строки для анализа...
                code = cm.Lines(1, lc)
                n = UBound(code)
                ReDim clean(0 To n) As Byte
                s = INITIAL 'Устанавливаем автомат в начальное состояние.
                sc = 0
                k = 0
                skipLine = False
                For i = 0 To n Step 2
                    Select Case s
                        Case INITIAL
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 32
                                        s = SPACE_FOUND
                                        sc = 1
                                    Case 34
                                        s = QUOT_FOUND
                                    Case 39
                                        s = REMARK_FOUND
                                        skipLine = True
                                    Case 82
                                        s = R_FOUND
                                    Case Else
                                        s = AFTERSPACE
                                End Select
                            Else
                                s = AFTERSPACE
                            End If
                        Case SPACE_FOUND
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 32
                                        sc = sc + 1
                                    Case 39
                                        s = REMARK_FOUND
                                        skipLine = True
                                    Case 82
                                        s = R_FOUND
                                    Case Else
                                        For j = 1 To sc
                                            clean(k) = 32
                                            k = k + 2
                                        Next j
                                        If code(i) = 34 Then s = QUOT_FOUND Else s = AFTERSPACE
                                End Select
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    k = k + 2
                                Next j
                                s = AFTERSPACE
                            End If
                        Case R_FOUND
                            If code(i) = 101 And code(i + 1) = 0 Then
                                s = RE_FOUND
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    k = k + 2
                                Next j
                                clean(k) = 82
                                k = k + 2
                                If code(i) = 13 And code(i + 1) = 0 Then s = CR_FOUND Else s = AFTERSPACE
                            End If
                        Case RE_FOUND
                            If code(i) = 109 And code(i + 1) = 0 Then
                                s = REM_FOUND
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    k = k + 2
                                Next j
                                clean(k) = 82
                                k = k + 2
                                clean(k) = 101
                                k = k + 2
                                If code(i) = 13 And code(i + 1) = 0 Then s = CR_FOUND Else s = AFTERSPACE
                            End If
                        Case REM_FOUND
                            If code(i + 1) = 0 And (code(i) = 13 Or code(i) = 32) Then
                                skipLine = True
                                If code(i) = 13 Then s = CR_FOUND Else s = REMARK_FOUND
                            Else
                                For j = 1 To sc
                                    clean(k) = 32
                                    k = k + 2
                                Next j
                                clean(k) = 82
                                k = k + 2
                                clean(k) = 101
                                k = k + 2
                                clean(k) = 109
                                k = k + 2
                                s = AFTERSPACE
                            End If
                        Case AFTERSPACE
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 34
                                        s = QUOT_FOUND
                                    Case 39
                                        s = REMARK_FOUND
                                End Select
                            End If
                        Case REMARK_FOUND
                            If code(i + 1) = 0 Then
                                Select Case code(i)
                                    Case 13
                                        s = CR_FOUND
                                    Case 32
                                        s = REMSPACE_FOUND
                                End Select
                            End If
                        Case QUOT_FOUND
                            If code(i) = 34 And code(i + 1) = 0 Then s = AFTERSPACE
                        Case CR_FOUND
                            'Если в абзаце(ах) исходника нет ничего, кроме комментария (о чем сигнализирует _
                            булева переменная skipLine), то в выходной текст абзац не добавляем.
                            If skipLine Then
                                skipLine = False
                            Else
                                clean(k) = 13
                                k = k + 2
                                clean(k) = 10
                                k = k + 2
                            End If
                            s = INITIAL
                        Case REMSPACE_FOUND
                            If code(i) = 95 And code(i + 1) = 0 Then s = UNDERLINE_FOUND Else s = REMARK_FOUND
                        Case UNDERLINE_FOUND
                            s = REMARK_FOUND
                    End Select
                    If s = QUOT_FOUND Or s = AFTERSPACE Then
                        clean(k) = code(i)
                        clean(k + 1) = code(i + 1)
                        k = k + 2
                    End If
                Next i
                If k < n Then
                    cm.DeleteLines 1, lc
                    cm.AddFromString CStr(clean)
                End If
            End If
        Next com
        MsgBox "Все комментарии удалены", vbInformation, "Результат"
    Else
        MsgBox "Удаление комментариев отменено.", vbInformation, "Результат"
    End If
End Sub

С уважением,
Аксима
2
19.11.2015, 21:30
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.11.2015, 21:30
Помогаю со студенческими работами здесь

Регулярное выражение: поиск комментариев в коде
Стоит задача вывести в консоль все комментарии с кода ( &quot;//&quot; и &quot;/* */&quot;) с помощью регулярного...

Сниппет Emmet для комментариев в коде
Подскажите, как в Emmet получить такое комментирование div&gt;.block1+.block2 &lt;div&gt; &lt;!-- BLOCKS...

Удаление комментариев
Здравствуйте! Пишу программу для удаления комментариев из программ. Вот кусочек кода. Проблема...

Удаление комментариев
Всем привет ) Нужна Ваша помощь! Дан код на паскале в мемо, нужно при нажатии удалить коментарии с...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru