Tornar as linhas obrigatórias se a primeira célula for preenchida

1

Eu tenho um arquivo do Excel onde quero que as pessoas preencham itens específicos. Eu quero fazer um intervalo de células em uma linha obrigatória se a primeira célula da linha estiver preenchida. Por exemplo. se a célula A7 estiver preenchida, as células B7-O7 precisam ser preenchidas. E isso se repete até que haja uma célula na coluna A que não esteja preenchida.

Eu tentei algumas codificações de VBA não muito boas aqui

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    If Sheets("Sheet1").Range("A7").Value <> "" And Sheets("Sheet1").Range("B7").Value = "" Or Range("C7").Value = "" Or Range("D7").Value = "" Or Range("E7").Value = "" Or Range("F7").Value = "" Or Range("G7").Value = "" Or Range("H7").Value = "" Or Range("I7").Value = "" Or Range("J7").Value = "" Or Range("K7").Value = "" Or Range("L7").Value = "" Or Range("M7").Value = "" Or Range("N7").Value = "" Or Range("O7").Value = "" Then
        MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
        Cancel = True

    ElseIf Sheets("Sheet1").Range("A8").Value <> "" And Sheets("Sheet1").Range("B8").Value = "" Or Range("C8").Value = "" Or Range("D8").Value = "" Or Range("E8").Value = "" Or Range("F8").Value = "" Or Range("G8").Value = "" Or Range("H8").Value = "" Or Range("I8").Value = "" Or Range("J8").Value = "" Or Range("K8").Value = "" Or Range("L8").Value = "" Or Range("M8").Value = "" Or Range("N8").Value = "" Or Range("O8").Value = "" Then
        MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
        Cancel = True

    ElseIf Sheets("Sheet1").Range("A9").Value <> "" And Sheets("Sheet1").Range("B9").Value = "" Or Range("C9").Value = "" Or Range("D9").Value = "" Or Range("E9").Value = "" Or Range("F9").Value = "" Or Range("G9").Value = "" Or Range("H9").Value = "" Or Range("I9").Value = "" Or Range("J9").Value = "" Or Range("K9").Value = "" Or Range("L9").Value = "" Or Range("M9").Value = "" Or Range("N9").Value = "" Or Range("O9").Value = "" Then
        MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
        Cancel = True

    End If

End Sub

Funciona até eu chegar:

ElseIf Sheets("Sheet1").Range("A9").Value <> "" And Sheets("Sheet1").Range("B9").Value = "" Or Range("C9").Value = "" Or Range("D9").Value = "" Or Range("E9").Value = "" Or Range("F9").Value = "" Or Range("G9").Value = "" Or Range("H9").Value = "" Or Range("I9").Value = "" Or Range("J9").Value = "" Or Range("K9").Value = "" Or Range("L9").Value = "" Or Range("M9").Value = "" Or Range("N9").Value = "" Or Range("O9").Value = "" Then
    MsgBox "Alla celler i en rad måste vara ifyllda för att du skall kunna spara. Kontrollera detta och spara igen."
    Cancel = True
End If

Em seguida, o MsgBox aparece mesmo que o A9 não esteja preenchido.

Eu sei que esta não é a melhor maneira de conseguir o que eu quero, mas foi o que eu criei. Alguma sugestão para um código melhor?

    
por Stax82 13.09.2018 / 08:42

1 resposta

2

Você tem um erro na sua cadeia de condições:

cond1 And cond2 Or cond3 Or cond4 será sempre avaliado como True se um (ou ambos) de cond3 ou cond4 for True . Isso ocorre porque And será avaliado antes de Or . Consulte a documentação para obter mais informações.

Você pode usar parênteses para ajustar a ordem de avaliação:

cond1 And (cond2 Or cond3 Or cond4)

Esta expressão só avaliará True se cond1 e qualquer cond2, cond3, cond4 forem True .

No seu caso, eu recomendaria as seguintes melhorias no seu código:

  • Primeiramente, leia sobre loops no VBA. For ... Next e Do ... Loop são os dois tipos que você precisa conhecer.
  • Então, para fazer as coisas pouco mais claro (isto é, deixe suas intenções visíveis no código), coloque esse código validação em sua própria sub-rotina / função.
  • E finalmente, para tornar ainda mais óbvio o que está acontecendo, você pode dividir estas longas cadeias de condições.

Se nós olharmos agora para o procedimento Workbook_BeforeSave , não é imediatamente óbvio o que ele está fazendo lá (pode ser para você, porque você acabou de colocar o código lá e está fresco em sua mente - mas volte a este folha em 3/6/12 meses e primeiro você precisa entender o que está fazendo). Vamos remediar isso:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

    Cancel = IsUserInputMissing

End Sub

Private Function IsUserInputMissing() as Boolean

    ' Validation code goes in here

End Function

Agora, todos que estão vendo o código podem ver rapidamente o que acontecerá quando a pasta de trabalho for salva.

Esta linha

If Sheets("Sheet1").Range("A7").Value <> "" And Sheets("Sheet1").Range("B7").Value = "" Or Range("C7").Value = "" Or Range("D7").Value = "" Or Range("E7").Value = "" Or Range("F7").Value = "" Or Range("G7").Value = "" Or Range("H7").Value = "" Or Range("I7").Value = "" Or Range("J7").Value = "" Or Range("K7").Value = "" Or Range("L7").Value = "" Or Range("M7").Value = "" Or Range("N7").Value = "" Or Range("O7").Value = "" Then

não é muito amigável aos olhos. Verbatim diz If FirstCellIsNotEmpty And AnyFollowingCellIsEmpty Then . Vamos codificar dessa maneira.

Dim FirstCellIsEmpty as Boolean
FirstCellIsEmpty = Sheets("Sheet1").Range("A7").Value = ""

Dim AnyFollowingCellIsEmpty as Boolean
AnyFollowingCellIsEmpty = WorksheetFunction.CountBlank(Sheets("Sheet1").Range("B7:O7")) > 0

If Not FirstCellIsEmpty And AnyFollowingCellIsEmpty Then
    MsgBox "I don't know any Swedish. But please fill out the necessary cells."
End If

Observe o uso de WorksheetFunction.CountBlank para evitar a necessidade de digitar todas as células a serem verificadas.

No final, darei um exemplo de como sua função IsUserInputMissing poderia se parecer. (Ainda há muito espaço para melhorias, no entanto.)

Private Function IsUserInputMissing() As Boolean

    ' Easy way to set the beginning of the range
    Const FirstRowToBeChecked As Long = 7
    ' Set a reference to the sheet that needs checking
    Dim Ws As Worksheet
    Set Ws = ThisWorkbook.Worksheets("Sheet1")

    Dim iRow As Long
    iRow = FirstRowToBeChecked

    Do

        Dim FirstCellIsEmpty As Boolean
        FirstCellIsEmpty = Ws.Cells(iRow, 1).Value = vbNullString ' vbNullString is a clearer way of saying ""
        ' Exit loop at the first empty row
        If FirstCellIsEmpty Then Exit Do

        Dim AnyFollowingCellIsEmpty As Boolean
        AnyFollowingCellIsEmpty = WorksheetFunction.CountBlank(Ws.Range(Ws.Cells(iRow, 2), Ws.Cells(iRow, 15))) > 0

        If AnyFollowingCellIsEmpty Then
            ' Any time the requirements are not met, notify user and abort checking and saving
            ' This is not as elegant as checking the whole range and collecting info about all missing inputs
            ' But it's way easier to code :)
            MsgBox "I don't know any Swedish. But please fill out the necessary cells. Tack!"
            IsUserInputMissing = True
            Exit Function
        End If
        ' Don't forget to increment the counter, otherwise you've got yourself an endless loop
        iRow = iRow + 1

    Loop

    ' If execution reaches this line, all rows fulfil the requirement
    ' IsUserInputMissing will have its Default value: False
End Function

Tome seu tempo e trabalhe com isso. Eu tentei deixar as coisas o mais claras possível. Mas se algo não está claro. Não hesite em perguntar. :)

    
por 13.09.2018 / 09:07