Есть ли способ упростить этот цикл

У меня есть цикл, который идет от -55 до -1, затем от 1 до 55, прежде чем снова вернуться к -55. Я хочу сделать цикл, идущий от произвольной точки в этом цикле к другой произвольной точке, но никогда не доходя до полного цикла.

Поскольку конечное значение счетчика может быть больше или меньше начального значения, я изначально сделал условие выхода для цикла, которое fra равно til.

Однако я также хочу что-нибудь сделать, когда fra = til, так что в итоге мой цикл выглядел так, как вы можете видеть ниже, с вспомогательной переменной, запускающей выход.

Я не очень доволен тем, как это в итоге выглядело, мне кажется, что логика немного неуклюжая. Есть ли способ улучшить приведенный ниже код?

Option Explicit

Dim første_økt_anodeskift(1 To 10, 1 To 2) As Long

Const farge_anodeskift_1 As Long = 14395790 ' RGB(142, 169, 219)

Sub main()
    Dim syklus As Long
    
    syklus = 1
    
    Call legg_inn_verdier
    Call fargelegg(første_økt_anodeskift(syklus, 1), første_økt_anodeskift(syklus, 2), farge_anodeskift_1)
End Sub

Private Sub fargelegg(fra, til, farge)
    Dim exit_on_next As Boolean
    
    exit_on_next = False
    
    Do
        ' Do stuff
        
        If exit_on_next Then Exit Do
        
        fra = fra + 1
        
        If fra = 0 Then
            fra = 1
        ElseIf fra = 56 Then
            fra = -55
        End If
        
        If fra = til Then exit_on_next = True
    Loop While True
End Sub

Private Sub legg_inn_verdier()
    første_økt_anodeskift(1, 1) = -11: første_økt_anodeskift(1, 2) = 6
End Sub
```

2 ответа
2

Может, тебе так кажется лучше. Инкапсуляция логики цикла в специализированные одноцелевые процедуры обычно упрощает чтение и понимание цикла (IMO). В этом случае условия цикла, требующие повторного выполнения кода «в последний раз», также становятся немного более ясными.

    Option Explicit

    Dim første_økt_anodeskift(1 To 10, 1 To 2) As Long

    Const farge_anodeskift_1 As Long = 14395790 ' RGB(142, 169, 219)

    Sub main()
        Dim syklus As Long
        
        syklus = 1
        
        Call legg_inn_verdier
        Call fargelegg(første_økt_anodeskift(syklus, 1), første_økt_anodeskift(syklus, 2), farge_anodeskift_1)
    End Sub

    Private Sub fargelegg(fra, til, farge)
        Do
            DoStuff fra, til, farge
            
            fra = GetNextFra(fra)
            
            If fra = til Then
                DoStuff fra, til, farge
                Exit Do
            End If
            
        Loop While True
    End Sub

    Private Sub legg_inn_verdier()
        første_økt_anodeskift(1, 1) = -11: første_økt_anodeskift(1, 2) = 6
    End Sub

    Private Sub DoStuff(fra, til, farge)
        ' Do stuff
    End Sub

    Private Function GetNextFra(fra) As Variant
        fra = fra + 1
        
        If fra = 0 Then
            fra = 1
        ElseIf fra = 56 Then
            fra = -55
        End If
        
        GetNextFra = fra
    End Function

  • 1

    Нет необходимости в Call

    — FreeMan

  • Да, мне нравится такой подход, спасибо за вклад 🙂

    — Эйрикдауде

Если можно, я дам вам дополнительный совет. Я заметил, что ваши идентификаторы написаны на норвежском языке (?). Обычно рекомендуется использовать простой ASCII и даже имена на английском языке.

Проблема с идентификаторами: некоторые компиляторы или интерпретаторы могут иметь проблемы с нестандартными символами. Поведение не всегда четко документируется и может быть непредсказуемым. Норвежский (или датский …) должен быть в порядке, но я не уверен, что VBA по-прежнему поддерживает полный диапазон Unicode. В контексте VBA и Windows ссылкой, вероятно, является набор символов Windows-1252, который должен охватывать большинство латинских алфавитов.

Но если вы использовали имена переменных арабским или японским шрифтом, я не уверен, как программа отреагирует.

Проблема с использованием имен переменных на вашем родном языке заключается в том, что иностранцам будет труднее понять логику вашего кода, потому что имена для них не интуитивно понятны.

Все больше и больше проектов командная работа, они также могут развиваться в проекты с открытым исходным кодом и публиковаться на Github. Если вы не используете английский язык, вы ограничиваете аудиторию возможных последователей и участников.

Кроме того, переменные с суффиксами типа _1 или _2 — плохие имена. Это верный признак того, что соглашения об именах нуждаются в улучшении.

Второе, что я заметил, это отсутствие Комментарии. Это типичный спагетти-код VB, за которым нелегко следить за потоком выполнения из-за:

  • структура, плюс процедуры вызова, которые имеют циклы
  • язык (выбор идентификаторов)
  • отсутствие комментариев

Все эти факторы в совокупности приводят к тому, что код становится трудным для понимания посторонними, такими как мы.

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

Проще говоря, Комментарии делает цель вашего кода более ясной.

Кроме того, вам следует избегать таких многострочных операторов:

første_økt_anodeskift(1, 1) = -11: første_økt_anodeskift(1, 2) = 6

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

Private Sub legg_inn_verdier()
    første_økt_anodeskift(1, 1) = -11
    første_økt_anodeskift(1, 2) = 6
End Sub

Но обратите внимание, как аккуратно выстроены утверждения.

С точки зрения спектакль и ясность: выберите правильный тип данных для переменных и возвращаемых значений. Это означает, что не используйте тип данных Long для коротких чисел. См. Этот пост для более подробного обсуждения типов данных VBA.

Функция GetNextFra возвращает целочисленное значение, поэтому не объявляйте функцию как вариант. Всегда. Целое число (или длинное, как указано в вышеупомянутом сообщении) должно подойти.

Эта функция может быть упрощена (и должна). Если у вас есть цикл, который вы хотите сбросить на 55, вам нужен модуль. Реализация будет такой (непроверенной):

Private Function GetNextFra(fra) As Integer
    GetNextFra = (fra mod 55) +1
End Function

Что делает эта функция: возвращает fra + 1, если fra = 55, тогда мы сбрасываем счетчик на 1. Если это не совсем то, что вам нужно, вы можете внести соответствующие изменения. Вуаля.

Но поскольку эта функция теперь однострочная, вы также можете отказаться от нее. Скопируйте однострочный текст в тело вашей программы. Выполнено. Вы уже упростили код.

Честно говоря, я не совсем понимаю, что на самом деле делает ваш код. Если бы я это сделал, то, возможно, мог бы предложить еще несколько идей.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *