2017-04-06 27 views
1

完全福利局:爲什麼是我在Sub throughCols第一迭代是意動一行,每次跳4行了嗎?VBA迭代錯誤跳四步預計1個

SO想讓我談談更多 - 但實際上它只是第一個迭代是胸部和越野車。

Option Explicit 

Dim txt As String 
Dim i As Long 
Dim strTest As String 
Dim strArray() As String 
Dim lCaseOn As Boolean 
Dim firstRow As Long, startIt As Long 
Dim thisCell As Range 
Dim lastRow As Long 
Dim resetAddress As Range 


Sub throughCols() 

' Dim thisCell As Range 

' get start and end of column data 
' NB sheet name is hard coded twice 
Call dataRange 
startIt = firstRow + 1 

For i = 1 To 8 Step 1 
    ' after testing use startIt To lastRow Step 1 
    ' by using activeCell I dont have to pass range through to the sub 
    Sheets("test").Range("B" & i).Select 
    MsgBox "this is itteration " & i & " which will output to " & ActiveCell.Offset(0, 2).Address 
    Call arrayManip 

    Call cleanTxt(txt) 
Next i 

End Sub 


Sub arrayManip() 

' clear out all data 
Erase strArray 
txt = "" 

'set default case 
lCaseOn = False 

' string into an array using a " " separator 
strTest = WorksheetFunction.Proper(ActiveCell.Value) 
strTest = Replace(strTest, "-", " - ") 
strTest = Replace(strTest, "‘", " ‘ ") 
strArray = Split(strTest, " ") 

' itterate through array looking to make text formats 

For i = LBound(strArray) To UBound(strArray) 
    If strArray(i) = "-" Then 
     lCaseOn = True 
     GoTo NextIteration 
    End If 

    If strArray(i) = "‘" Then 
     lCaseOn = True 

     GoTo NextIteration 
    End If 
    If lCaseOn Then 
     strArray(i) = LCase(strArray(i)) 
     lCaseOn = False 
NextIteration: 
    End If 

    Next 
End Sub 

Function cleanTxt(txt) 

' loop through the array to build up a text string 
For i = LBound(strArray) To UBound(strArray) 
    txt = txt & strArray(i) & " " 
Next i 

' remove the space 
txt = Trim(Replace(txt, " - ", "-")) 
txt = Trim(Replace(txt, " ‘ ", "‘")) 

' MsgBox "active cell is " & activeCell.Address 
ActiveCell.Offset(0, 2).Select: ActiveCell.Value = txt 

' MsgBox "final output would be " & txt & " to " & activeCell.Address 
' this is a thumb suck to attempt to reset the active cell to the itteration address that started it 
ActiveCell.Offset(0, -2).Select 
MsgBox "next itteration should start with active cell set as " & ActiveCell.Address 

End Function 
Sub dataRange() 

With Sheets("test").Columns("B") 

    If WorksheetFunction.CountA(.Cells) = 0 Then '<--| if no data whatever 
     MsgBox "Sorry: no data" 
    Else 
    With .SpecialCells(xlCellTypeConstants) '<--| reference its cells with constant (i.e, not derived from formulas) values) 
     firstRow = .Areas(1).Row 
     lastRow = .Areas(.Areas.Count).Cells(.Areas(.Areas.Count).Rows.Count).Row 
    End With 
     ' MsgBox "the first row is " & firstRow 
     ' MsgBox "last row is " & lastRow 
    End If 
End With 

End Sub 
+1

你'我'是一個全局變量,它的值由你在循環中調用的一些子變化。不要沒有很好的理由使用全局變量,在這裏似乎並不是這種情況。 –

+0

你是一個高度發展的天才 - 現在,當你做出評論而不是回答時,我該如何向你致意? – m4sterbunny

+0

@JohnColeman'我'不是全球性的,它是一個*私人領域*。但問題仍然存在:它的範圍太廣泛,有多個程序正在訪問它。 –

回答

2

你聲明你i變量在模塊範圍,這使得它的模塊中訪問無處不在;當您撥打arrayManip並且值發生變化時,它會被修改。

如果聲明這個程序就不會發生,因爲變量只會是它在聲明的範圍訪問內部本地ind變量試試下面的代碼:

Sub throughCols() 

' Dim thisCell As Range 
Dim ind As Long '<-- DECLARE local variable 
' get start and end of column data 
' NB sheet name is hard coded twice 
Call dataRange 
startIt = firstRow + 1 

' ===== loop on ind and not i (changes when you call arrayManip) ==== 
For ind = 1 To 8 ' Step 1 <-- actually not needed, that's the default increment value 
    ' after testing use startIt To lastRow Step 1 
    ' by using activeCell I dont have to pass range through to the sub 
    Sheets("test").Range("B" & ind).Select 
    MsgBox "this is itteration " & ind & " which will output to " & ActiveCell.Offset(0, 2).Address 
    Call arrayManip 

    Call cleanTxt(txt) 
Next ind 

End Sub 
+0

在模塊級別使用'Dim'使'Private'字段成爲'Private'字段; 「這個模塊中的全局」混淆了措辭,尤其是考慮到存在(不推薦使用)'Global'關鍵字,這意味着'Public'範圍。該變量是一個*私人領域*(*領域*表示一個模塊範圍變量),而不是「全球」。 –

+0

@ Mat'sMug我的解釋不如你的墊子,你知道我的意思。如果你可以編輯我的解釋會很棒(我不適合RubberDuck項目) –

+0

沒問題! =)... re「我不爲Rubberduck項目工作」 - 爲什麼不呢? ;-) –