Excel宏循环遍历所有行

时间:2018-03-16 04:50:06

标签: excel vba excel-vba

我在Excel行中接收数据如下:

INVOICE NO. 1000001
Plan AAAAA 17371 22.00
Plan BBBBB 31782 0.00
Plan CCCCC 13918 44.00
Total for 1000001 66.00
INVOICE NO. 1000002
Plan AAAAA 31385 0.00
Plan CCCCC 15981 44.00
Total for 1000002 44.00
INVOICE NO. 1000003
Plan BBBBB 13181 0.00
Plan CCCCC 01828 16.00
GARBAGE TEXT
Total for 1000003 16.00

我需要将这些数据显示在单独的工作表上(甚至替换当前工作表),如下所示:

Invoice No | Plan AAAAA | Plan AAAAA Cost | Plan BBBBB | Plan BBBBB Cost | Plan CCCCC | Plan CCCCC Cost | Total
1000001 | Plan AAAAA 17371 | 22.00 | Plan BBBBB 31782 | 0.00 | Plan CCCCC 13918 | 44.00 | 66.00
1000002 | Plan AAAAA 31385 | 0.00 | | | Plan CCCCC 15981 | 44.00 | 44.00
1000003 | | | Plan BBBBB 13181 | 0.00 | Plan CCCCC 01828 | 16.00 | 16.00

需要注意的一些事项是:

  1. 我无法改变收到这些数据的方式。我希望我能。
  2. 每套发票均以INVOICE NO. XXXXXXX开头,以Total for XXXXXXX结尾,后跟其总费用。
  3. 只有3个可能的计划AAAAA / BBBBB / CCCCC,但并非所有3个都可能出现在发票中。
  4. 有时在输出中间有垃圾文本需要忽略。
  5. 我正在考虑创建一个Excel宏,它将遍历Excel工作表的每一行,伪代码

    1. 创建包含所需标题的新表格
    2. 查找INVOICE NO的第一个实例,并将以下编号添加到表格
    3. 检查下一行,而行不包含Total for,请检查是否包含Plan AAAAA,如果是,请在将最后一部分拆分为成本时添加行,如果不是留下黑色,请保持在线并检查对于计划BBBBB,重复BBBBB和CCCCC
    4. 如何循环执行上述操作的每一行(或者有更好的方法来完成此操作)?

3 个答案:

答案 0 :(得分:2)

正如代码中的注释所写,我假设您的数据存储在以A1单元格开头的A列中。然后,它将被所需的输出所取代(你说是允许的)。

试试这段代码:

Sub ParseInvoices()
Dim lsatRow As Long, i As Long, invoiceData As Variant, currentRow As Long, currentData As String
currentRow = 2
'get last row of A column - I assumed that there you store your data
lastrow = Cells(Rows.Count, 1).End(xlUp).Row
'read data
invoiceData = Range("A1:A" & lastrow).Value
'clear data from sheet
Columns(1).Clear
'set up table headers
Cells(1, 1) = "Invoice No"
Cells(1, 2) = "Plan AAAAA"
Cells(1, 3) = "Plan AAAAA Cost"
Cells(1, 4) = "Plan BBBBB"
Cells(1, 5) = "Plan BBBBB Cost"
Cells(1, 6) = "Plan CCCCC"
Cells(1, 7) = "Plan CCCCC Cost"
Cells(1, 8) = "Total"

For i = 1 To lastrow
    currentData = RTrim(LTrim(invoiceData(i, 1)))
    Select Case UCase(Left(currentData, 10))
        Case "INVOICE NO"
            Cells(currentRow, 1).Value = Mid(currentData, InStrRev(currentData, " "))
        Case "PLAN AAAAA"
            Cells(currentRow, 2).Value = Left(currentData, InStrRev(currentData, " ") - 1)
            Cells(currentRow, 3).Value = Mid(currentData, InStrRev(currentData, " "))
        Case "PLAN BBBBB"
            Cells(currentRow, 4).Value = Left(currentData, InStrRev(currentData, " ") - 1)
            Cells(currentRow, 5).Value = Mid(currentData, InStrRev(currentData, " "))
        Case "PLAN CCCCC"
            Cells(currentRow, 6).Value = Left(currentData, InStrRev(currentData, " ") - 1)
            Cells(currentRow, 7).Value = Mid(currentData, InStrRev(currentData, " "))
        Case "TOTAL FOR "
            Cells(currentRow, 8).Value = Mid(currentData, InStrRev(currentData, " "))
            currentRow = currentRow + 1
    End Select
Next
End Sub

答案 1 :(得分:1)

代码不是那么灵活,但它的工作原理基于以上标准:

Sub test()


Sheets.Add After:=ActiveSheet

Sheets(2).Range("a1").Value = "Invoice No"
Sheets(2).Range("b1").Value = "Plan AAAAA"
Sheets(2).Range("c1").Value = "Plan AAAAA Cost"
Sheets(2).Range("d1").Value = "Plan BBBBB"
Sheets(2).Range("e1").Value = "Plan BBBBB Cost"
Sheets(2).Range("f1").Value = "Plan CCCCC"
Sheets(2).Range("g1").Value = "Plan CCCCC Cost"
Sheets(2).Range("h1").Value = "Total"

sheet2y = 1

For y = 1 To 10000
    If Len(Sheets(1).Cells(y, 1).Value) > 0 Then
            If LCase(Sheets(1).Cells(y, 1).Value) Like "*invoice*" Then
                If sheet2y > 1 Then
                    Sheets(2).Cells(sheet2y, 8).Value = Sheets(2).Cells(sheet2y, 3).Value + Sheets(2).Cells(sheet2y, 5).Value + Sheets(2).Cells(sheet2y, 7).Value
                End If
                sheet2y = sheet2y + 1
                Sheets(2).Cells(sheet2y, 1).Value = Trim(Split(LCase(Sheets(1).Cells(y, 1).Value), "no.")(1))

            End If


        If LCase(Sheets(1).Cells(y, 1).Value) Like "*plan*" Then
            For sheet2x = 2 To 6 Step 2
                If LCase(Sheets(1).Cells(y, 1).Value) Like "*" & LCase(Sheets(2).Cells(1, sheet2x).Value) & "*" Then
                    Sheets(2).Cells(sheet2y, sheet2x).Value = Sheets(2).Cells(1, sheet2x).Value & " " & Split(Sheets(1).Cells(y, 1).Value, " ")(2)
                    Sheets(2).Cells(sheet2y, sheet2x + 1).Value = Trim(Split(Sheets(1).Cells(y, 1).Value, " ")(3))
                End If
            Next sheet2x
        End If

    Else
        Sheets(2).Cells(sheet2y, 8).Value = Sheets(2).Cells(sheet2y, 3).Value + Sheets(2).Cells(sheet2y, 5).Value + Sheets(2).Cells(sheet2y, 7).Value
        Exit For
    End If
Next y

End Sub

答案 2 :(得分:0)

您可以在此处使用For-Each循环。它已经过去了。像这样:

 function getCookie(name)
  {
    var re = new RegExp(name + "=([^;]+)");
    var value = re.exec(document.cookie);
    return (value != null) ? unescape(value[1]) : null;
  }

如果您按照自己的伪代码中的说明执行此操作,我认为没有理由不应该这样做。但是,这种看起来像是上班的问题;)