我糾正了代碼中最明顯的錯誤,但對我來說沒有意義,所以我不知道它是否按照您的要求進行了操作。
' Option Explicit ensures that misspelt names are
' not taken as an implicit declaration
Option Explicit
Sub Macro1()
' This is legal syntax but I find it confusing. I only have two or more
' variables in a Dim if they are closely related.
Dim LastRow1 As Long, RowG As Range, RowCheck As Long, Rowtosave As Long, LastCol1 As Long
Dim EGCheck As Long, ColEG As Range, firstEG As Long, IGCheck As Long, ColIG As Range
Dim findtemp As Range, tempRow As Long, tempRow1 As Long, lastEG As Long
Dim totalvalue As Long, valuestoadd As Long, tempCheck As Long
Dim emptycol As Long, empty1 As Range, Colempty As Long, tempcol As Long
' You can nest Withs.
' You only use one worksheet so let us declare that at the top.
With Worksheets("Sheet1")
' These statements will have to be replaced when the number of rows and
' columns exceed 50.
'LastRow1 = 50
'LastCol1 = 50
LastRow1 = .Cells.SpecialCells(xlCellTypeLastCell).Row
LastCol1 = .Cells.SpecialCells(xlCellTypeLastCell).Column
Rowtosave = 0 ' Initialise in case not found
For RowCheck = 1 To LastRow1
' I use: With .Cells(R, C)
' .Value = 5
' .NumberFormat = "0.00"
' .Font.Bold = True
' End With
' because I want to refer to .Cells(R, C) in several ways.
' I do not see the benefit of:
' With .Cells(R, C)
' .Value = 5
' End With
If .Cells(RowCheck, 1).Value = "Name" Then
Rowtosave = RowCheck
firstEG = 0 ' Initialise so you can test for
lastEG = 0 ' EG and IG not being found.
For EGCheck = 1 To LastCol1
If .Cells(Rowtosave, EGCheck).Value = "EG" Then
firstEG = EGCheck
' Without the Exit For, the search will continue and
' firstEG will identify the last EG not the first.
Exit For
End If
Next EGCheck
For IGCheck = 1 To LastCol1
If .Cells(Rowtosave, IGCheck).Value = "IG" Then
' I find the name lastEG confusing
lastEG = IGCheck - 1
End If
Next IGCheck
' If you really want the last IG on the row
' better to search backwards.
For IGCheck = LastCol1 To 1 Step -1
If .Cells(Rowtosave, IGCheck).Value = "IG" Then
lastEG = IGCheck - 1
Exit For
End If
Next IGCheck
End If
' I assume there is only one row with Name in column A
' so there is no point in searching further.
Exit For
Next RowCheck
If Rowtosave = 0 Then
Call MsgBox("Name row not found", vbOKOnly)
Exit Sub
End If
If lastEG = 0 Then
Call MsgBox("EG not found on Name row", vbOKOnly)
Exit Sub
End If
'Look for temp
totalvalue = 0
tempRow1 = 0 ' Initialise in case not found
tempcol = 0
For RowCheck = 1 To LastRow1
If .Cells(RowCheck, 1).Value = "temp" Then
For tempCheck = 1 To lastEG
tempRow1 = RowCheck
' I assume .Cells(tempRow1, tempCheck).Value is numeric.
' If so "0" has to be converted to numeric for every test.
' Better: If .Cells(tempRow1, tempCheck).Value = 0 Then
' I might use "With .Cells(tempRow1, tempCheck)" because you
' test its value then use the value. However, this code
' makes no sense to me.
If .Cells(tempRow1, tempCheck).Value = "0" Then
' Why are you saving tempcol?
tempcol = tempCheck
' Why are you selecting valuestoadd?
' You have not activated the sheet. You cannot select a
' a cell except within the active worksheet.
'valuestoadd = .Cells(tempRow1, tempcol).Select
' Why are you totalling all the cells with a value of zero.
totalvalue = totalvalue + .Cells(tempRow1, tempcol).Value
End If
Next tempCheck
' I assume there is only one temp row
Exit For
End If
Next RowCheck
' This loop appears to be searching for a empty cell
' in which to place totalvalue.
'Look for empty column
emptycol = 1
Do
' Why are you selecting the cell?
Set empty1 = .Cells(tempRow1, emptycol)
If empty1 = "" Then
' Why are you place the value in the cell after the empty one?
emptycol = emptycol + 1
' How will you use Colempty?
Colempty = emptycol
' You cannot set a range to a numeric.
'empty1 = totalvalue
' "empty1.Value = totalvalue" would be OK
.Cells(tempRow1, emptycol).Value = totalvalue
' I have moved the Exit Do to inside the If.
' Before "emptycol = emptycol + 1" could not be reached
Exit Do
End If
emptycol = emptycol + 1
Loop
End With
End Sub
響應user1204868的問題和新的闡釋新科
我開始回答你的問題,但我無法調和你給的所有信息。代碼,解釋和問題不一致。以下是我嘗試創建一致的描述。
- 在列A中有一個名爲「Name」的行。調用這個Name行。
- 在名稱行中,存在包含「EG」的單元格。包含「EG」的細胞之後的幾個細胞是包含「IG」的細胞。從包含「EG」的單元格開始調用範圍,並繼續(但不包括)包含「IG」(EG範圍)的下一個單元格。在這個例子中,EG範圍是B:D和H:J。
- A列中有一行帶有「temp」,將此稱爲Temp行。在這個例子中,Temp行緊接在Name行的下面,但顯然這不是必需的。 「名稱」和「臨時」行可以出現在工作表內的任何位置,並可以按任意順序顯示
- 列A中有一行「test1」。調用此Test1行。
- 在此示例中,Test1行立即位於Temp行下。該代碼不訪問Test1行。該解釋說,Temp行下的行是Test1行,但不會被檢查。
- 在Temp行內的每個EG範圍內,都有一個包含零的單元格。零以下的單元格將爲空或包含數字。所有EG範圍的這些數字的值將被合計。在Temp行中的第一個空單元格覆蓋任何現有值後,此總數將被保存在單元格中。在該示例中,Temp行中的第一個空單元格在N列中,因此總數將被保存在O列中,覆蓋現有的零。
我懷疑這個解釋是完全正確的。你應該把這個解釋複製到你的問題中並糾正它,這樣Tim或我或其他人就可以理解你真正想要的東西。
有關名稱行不是第1行的問題表明您擔心在開發工作表時名稱行可能會向下移動。您需要決定該工作表的修正情況以及可能發生的變化。例如,Test1行是否必須立即在Temp行之下?
A列中的「test2」和「test3」是什麼行?它們是否與Test1行相關?
在代碼中的註釋從testing1.xlsm
1期
您已刪除我的Option Explicit
讓您有未聲明的變量。
地址:
Dim totalvalue1 As Long
Dim totalvalue2 As Long
第2期
.Cells(LastRow1, 1).Select
只能選擇活動工作表中的單元格。我們正在使用With
訪問工作表Sheet1,因此它不必處於活動狀態。
沒有必要選擇這個單元格,所以刪除這條語句。
3個
End If
' I assume there is only one row with Name in column A
' so there is no point in searching further.
Exit For
Next RowCheck
正如我在評論解釋,這個塊必須被替換爲:
Exit For
End If
Next RowCheck
第4期
For IGCheck = 1 To LastCol1
If .Cells(Rowtosave, IGCheck).Value = "IG" Then
lastEG = IGCheck - 1
Exit For
ElseIf .Cells(Rowtosave, IGCheck).Value = "EG" Then
lastEG = IGCheck - 1
'Exit For
ElseIf .Cells(Rowtosave, IGCheck).Value = "CG" Then
lastEG = IGCheck - 1
'Exit For
End If
Next IGCheck
我從這個猜想代碼和你前您正在搜索的名稱列的部分列planations其中包含「EG」細胞開始和結束一個欄前:
- 含有「CG」細胞或
- 接下來的下一列包含「EG」或
- 含「IG」
我也想你已經註釋掉Exit For
語句,因爲這個代碼不起作用細胞下一列的單元格的列。您的問題是For IGCheck = 1 To LastCol1
。您在第1列開始搜索,因此您再次找到第一個「EG」。
替換的代碼塊有:
If firstEG = 0 Then
Call MsgBox("EG not found on Name row", vbOKOnly)
Exit Sub
End If
For IGCheck = firstEG + 1 To LastCol1
If .Cells(Rowtosave, IGCheck).Value = "IG" Or _
.Cells(Rowtosave, IGCheck).Value = "EG" Or _
.Cells(Rowtosave, IGCheck).Value = "CG" Then
lastEG = IGCheck - 1
Exit For
End If
Next IGCheck
5期
If lastEG = 0 Then
Call MsgBox("EG not found on Name row", vbOKOnly)
Exit Sub
End If
前面的問題下討論的代碼表明,EG的範圍可以由下一EG結束。這表明最終的EG範圍可以在使用範圍的末尾結束。
替換的代碼塊具有:
If lastEG = 0 Then
lastEG = LastCol1 - 1
End If
問題6
For n = 1 To LastRow1
:
Next
整個代碼的第二塊是由這個For Loop
包圍。用您的示例數據,這相當於For n = 1 to 5
。在此代碼塊中,查找包含值「temp」的列A(RowCheck = 3)。然後您可以從RowCheck + n行訪問數據。也就是說,你訪問了第4到第8行。這真的是你想要做的嗎?
問題7
For tempCheck = 1 To lastEG
我認爲這應該是:
For tempCheck = firstEG To lastEG
第8
的第二個代碼塊是一個混亂。我可以看到代碼的作用,但我沒有理解爲什麼我很難評論。但是我會努力的。
環路尋找臨時行需要在外面所以像:
For RowCheck = 1 To LastRow1
If .Cells(RowCheck, 1).Value = "temp" Then
' Set up new headers on Name row
' Process all the test rows
Exit For
End If
Next
代碼上的Temp行上方的行放置一個「EG」。這假定Temp行上面的行是Name行。或者:
- 臨時行始終將成爲名稱排在這種情況下,你不需要搜索的臨時行或
- 你應該放在排Rowtosave的「EG」下面的一行。
無論哪個,你只需要做一次。
您不應該嘗試使用For n = 1 To LastRow1
處理列A中帶有「testN」的行。選項包括:
- 您已經使LastRow1比最後一行少了兩個。從初始化LastRow1的語句中刪除
- 2
。將For n = 1 To LastRow1
替換爲For n = 1 To LastRow1 - tempRow1
- 替換
For n = 1 To LastRow1
... Next
帶Do循環一直持續到A列爲空或不包含「testN」或無論如何終止此表。
如果您正在循環查找值,那麼您可能希望在找到要查找的內容時使用「退出」。我試圖按照你的要求,但他們可以更清楚一點... – 2012-03-06 06:24:32
@TimWilliams,我試過了,退出了,我不太確定哪個是它?你建議它應該在哪裏? – user1204868 2012-03-06 06:58:13
要做的第一件事就是更新您的問題,並詳細解釋您希望代碼執行的操作。 – 2012-03-06 17:48:10