检查行和列后获取值总和的麻烦

时间:2012-03-06 05:16:13

标签: vba excel-vba excel

我在尝试使用EG获取第一列的值时遇到一些麻烦,0将在H,EG和0列中找到的值相加。总和将放在第O列第3行。

我试图写出代码,找到名称,EG和temp,0。不幸的是,代码查找在O列看到的最后0个。如果你有任何想法,请分享你的,将会感谢您的帮助!谢谢!

enter image description here

  Sub Macro1()

   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

    LastRow1 = 50
    LastCol1 = 50

      For RowCheck = 1 To LastRow1

          With Worksheets("Sheet1").Cells(RowCheck, 1)
              If .Value = "Name" Then

                   Rowtosave = RowCheck

                 For EGCheck = 1 To LastCol1

                    With Worksheets("Sheet1").Cells(Rowtosave, EGCheck)

                    If .Value = "EG" Then

                     firstEG = EGCheck

                    End If
                    End With

                Next EGCheck

               For IGCheck = 1 To LastCol1

                    With Worksheets("Sheet1").Cells(Rowtosave, IGCheck)

                    If .Value = "IG" Then

                    lastEG = IGCheck - 1

                    End If
                    End With

              Next IGCheck

         End If

       End With

    Next RowCheck

   'Look for temp

   totalvalue = 0

    For RowCheck = 1 To LastRow1

       With Worksheets("Sheet1").Cells(RowCheck, 1)
         If .Value = "temp" Then

          tempRow1 = RowCheck

              For tempCheck = 1 To lastEG

              With Worksheets("Sheet1").Cells(tempRow1, tempCheck)

               If .Value = "0" Then

                  tempcol = tempCheck

                valuestoadd = Worksheets("Sheet1").Cells(tempRow1, tempcol).Select

                totalvalue = totalvalue + valuestoadd

              End If
             End With

              Next tempCheck

          End If
          End With

      Next RowCheck

   'Look for empty column
      emptycol = 1

      Do

     Set empty1 = Worksheets("Sheet1").Cells(tempRow1, emptycol)

       If empty1 = "" Then

        emptycol = emptycol + 1

        Colempty = emptycol

       empty1 = totalvalue

      End If
     Exit Do

    emptycol = emptycol + 1

    Loop

  End Sub

跟进:

我的代码需要做的事情如下:

  1. 选中“名称”行。
  2. 找到“姓名”后会查找“EG”并将其设置为第一个“EG”
  3. 然后它将尝试寻找第一个“IG”,以便我们可以拥有第一个“EG”的最后一个(注意:“EG”组BD列,IG组E列到G,第2个EG组HJ等等上。
  4. 之后,寻找临时。
  5. 然后找到0或100或整体将在列中,例如“EG”的类别,“First EG”到“Last of the first EG”。
  6. 然后将1添加到Row,以便我们可以将test1的总和制成表格。
  7. 从“First EG(B列)”和“Second EG(H列)”中得到0的总和,并将其放在空列,如列O.对于此示例,结果将为2 + 0 = 2
  8. 我意识到当我使用lastEG时引起的混乱。我对lastEG的意思是第一次EG的最后一次

    我希望这清除了疑虑。

    与Tony讨论并跟进改进问题

    • A列中有一行“Name”。将其命名为Name行。它可能没有必要在第一行。
    • 在“名称”行中,有一些单元格包含“EG”。含有“EG”的细胞后的一些细胞是含有“IG”的细胞。从包含“EG”的单元格开始调用范围,并继续(但不包括)包含“IG”(EG范围)的下一个单元格。在该示例中,EG范围是B:D和H:J。
    • A列中有一行“temp”。将此行称为Temp行。在该示例中,Temp行紧跟在Name行下,但显然这不是必需的。名称和临时行可以出现在工作表中的任何位置,名称将始终高于临时,但这并不意味着它们已配对在一起,有时我们可以有名称,月份,临时。
    • A列中有一行“test1”。将其称为Test1行。
    • 在该示例中,Test1 Row紧邻Temp行。代码不访问Test1行。解释说Temp行下面的行是Test1行,但是没有检查。
    • 在Temp行的每个EG范围内,有一个包含'0','100'和'Overall'的单元格。零下方的单元格将为空或包含数字。所有EG范围的这些数字的值将被合计。此总数将保存在临时行下方的第一个空单元格之后的单元格中,例如,O3 - Q3,其中将放置值。

    我希望这会变得更好,Tony,我已经使用了你的一些观点并进行了编辑。

1 个答案:

答案 0 :(得分:1)

我已经纠正了代码中最明显的错误,但这对我来说没什么意义,所以我无法判断它是否符合您的要求。

' 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

回应用户1204868的问题和新解释的新部分

我开始回答您的问题,但我无法调和您提供的所有信息。代码,解释和问题不一致。以下是我尝试创建一致的描述。

  • 有一行"名称"在A列中。将其命名为Name行。
  • 在名称行中,有一些单元格包含" EG"。细胞接种后的几个细胞" EG"是一个包含" IG"的细胞。从包含" EG"的单元格开始调用范围。并继续(但不包括)包含" IG",EG范围的下一个单元格。在该示例中,EG范围是B:D和H:J。
  • 有一行" temp"在A列中。将其称为Temp行。在该示例中,Temp行紧跟在Name行下,但显然这不是必需的。 Name和Temp行可以出现在Sheet中的任何位置,也可以按任意顺序出现。
  • 有一行" test1"在A列中。将其称为Test1行。
  • 在该示例中,Test1 Row紧邻Temp行。代码不访问Test1行。解释说Temp行下面的行是Test1行,但是没有检查。
  • 在Temp行中的每个EG范围内,有一个包含零的单元格。零下方的单元格将为空或包含数字。所有EG范围的这些数字的值将被合计。在Temp行中的第一个空单元格覆盖任何现有值之后,此总数将保存在单元格中。在该示例中,Temp行中的第一个空单元格位于N列中,因此总计将保存在O列中,覆盖现有零。

我怀疑这种解释是完全正确的。您应该将此解释复制到您的问题并进行更正,以便Tim或我或其他人能够理解您真正想要的内容。

关于名称行不是第1行的问题表明您担心在开发工作表时,“名称”行可能会向下移动。您需要确定工作表的修复内容以及可能发生的变化。例如,Test1行必须紧接在Temp行吗?

" test2"的行是什么?和" test3"在A列中。它们与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

我想从这段代码和你的解释中,你正在搜索名称行中的一系列列,这些列以包含" 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。在这段代码中,您将查找行(RowCheck = 3),其中A列包含值" temp"。然后,您可以从行RowCheck + n访问数据。也就是说,您可以访问第4到第8行。这真的是您想要做的吗?

第7期

For tempCheck = 1 To lastEG

我认为这应该是:

For tempCheck = firstEG To lastEG

第8期

第二段代码是混乱。我可以看到代码的作用,但我没有说明为什么这样我很难发表评论。但我会尝试。

寻找Temp行的循环需要在外面,如下所示:

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

代码放置" EG"在Temp行上方的行上。这假设Temp行上方的行是Name行。之一:

  • Temp行始终是Name行下面的行,在这种情况下,您不需要搜索Temp行或
  • 你应该放置" EG"在行Rowtosave。

无论哪一种,你只需要做一次。

您不应尝试使用" testN"处理行。在A列中For n = 1 To LastRow1。选择包括:

  • 你使LastRow1比真正的最后一行少两个。从初始化LastRow1的语句中删除- 2。将For n = 1 To LastRow1替换为For n = 1 To LastRow1 - tempRow1
  • For n = 1 To LastRow1 ... Next替换为Do循环,直到A列为空或不包含" testN"或任何终止此表。
相关问题