0

我正在尝试提出一个可以在不同工作表中运行并引用以下数据的公式。

基本上对于 D 中的每个单元格,我想向上检查,当我找到字符串“发票”时,我选择上面的下一行和 B 列。基本上我每次都会找到公司名称。如您所见,每家公司的记录行数可能会有所不同。

更简单地说,该公式可以只对 B 列起作用,并直接返回字符串“Status”第一次出现的上方的字符串。

我不喜欢这有多复杂,但我无法控制我收到的数据格式,而且来源拒绝更改它。

原始数据

    A               B               C               D
1                   ABC Widgets, Inc.
2   Account         Status          Date            Invoice
3   1423            Open            4/25/2011       123748
4   1423            Closed          5/1/2011        432741
5   1423            Open            5/2/2011        522211
6 
7                   XYZ Sprockets, Inc.
8   Account         Status          Date            Invoice
9   3222            Open            5/3/2011        529999
10

完成数据

    A               B               C               D            E
2   Account         Status          Date            Invoice      Client
3   1423            Open            4/25/2011       123748       ABC Widgets, Inc.
4   1423            Closed          5/1/2011        432741       ABC Widgets, Inc.
5   1423            Open            5/2/2011        522211       ABC Widgets, Inc.
9   3222            Open            5/3/2011        529999       XYZ Sprockets, Inc.

纳奇,

虽然我无法让您的 VBA 代码正常工作(见评论),但它确实让我想出了这个代码,它找到了第一次出现的“状态”,然后偏移了上面的 1 个单元格。这本质上是我正在尝试的,但采用公式格式。

Sub findFirstStringAbove()
'
Cells.Find(What:="Status", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
    :=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase _
    :=False).Offset(-1, 0).Select
End Sub
4

4 回答 4

2

试试这个公式,作为数组公式输入,即用++ Ctrl,然后复制下来。ShiftEnter

=INDEX(B:B,IF(ROW()>COUNTIF(B:B,"Status"),"",SMALL(IF($B:$B="Status",ROW($B:$B),2000000000),ROW()))-1)

要从另一张纸上运行它,请从原始纸上剪切并粘贴它,它会自动调整参考。

于 2012-09-28T20:27:34.230 回答
1

VBA 将为您提供比公式更快的答案,尽管不是动态的。运行过滤、偏移和复制结果的附加代码:

Dim lLastRow As Long, rgResult As Range


lLastRow = Cells(Rows.Count, 2).End(xlUp).Row


With Range("B1:B" & lLastRow)
    .AutoFilter field:=1, Criteria1:="Status"
    Set rgResult = .Offset(1).Resize(.Rows.Count - 1).SpecialCells(xlCellTypeVisible)
    .AutoFilter
End With

Sheets.Add

rgResult.Offset(-1).Copy ActiveSheet.Cells(1, 1)
于 2012-09-28T20:35:47.987 回答
0

我讨厌拼图。至少,我是这么告诉人们的。

行。我将第一列作为您的标题。

A1 =    Account
B1 =    Status
C1 =    Date
D1 =    Invoice
E1 =    Client
F1 =    Index
G1 =    Client Index
H1 =    Client Cnt

第 2 行将是您的数据的开始。

A2 =    =INDEX(Sheet1!A$1:A$1000,$F2)
B2 =    =INDEX(Sheet1!B$1:B$1000,$F2)
C2 =    =INDEX(Sheet1!C$1:C$1000,$F2)
D2 =    =INDEX(Sheet1!D$1:D$1000,$F2)
E2 =    =INDEX(Sheet1!B$1:B$1000,$G2)
F2 =    =IF(ISNUMBER(F1),IF(INDEX(Sheet1!B$1:B$1000,$F1+1)="",G2+2,F1+1),G2+2)
G2 =    {=IF(H2=H1,G1,SMALL(IF(Sheet1!$B$1:$B$1000="Status",ROW(Sheet1!$B$1:$B$1000),2000),H2)-1)}
H2 =    =IF(ISNUMBER(H1),IF(INDEX(Sheet1!B$1:B$1000,$F1+1)="",H1+1,H1),1)

向下粘贴,直到出现#REF 错误。

Excel 对 $B:$B 语法产生了恶臭。它想要一个真实的范围。此外,您可能想要一个大于 1000 美元的数字。

毕竟,宏更直接且更适合此要求,但其中的乐趣是什么。

享受!

于 2012-09-29T16:37:28.047 回答
0

好的。这是VBA。

Public Sub test()
Dim rngStCol As Range
Dim rngSt As Range
Dim lastRow As Integer
Dim rngDB As Range
Dim currRow As Integer

Set rngStCol = Sheet1.UsedRange.Columns(2)
Set rngSt = rngStCol.Find("Status")
Do While rngSt.Row > lastRow
    Set rngDB = rngSt.CurrentRegion
    Set rngDB = rngDB.Offset(2, 0).Resize(rngDB.Rows.Count - 2)

    If currRow = 0 Then
        Sheet3.Range(Sheet3.Cells(1, 1), Sheet3.Cells(1, rngDB.Columns.Count)).Value = rngDB.Offset(-1, 0).Resize(1).Value
        Sheet3.Cells(1, rngDB.Columns.Count + 1).Value = "Client"
        currRow = 2
    End If

    Sheet3.Range(Sheet3.Cells(currRow, 1), Sheet3.Cells(currRow + rngDB.Rows.Count - 1, rngDB.Columns.Count)).Value = rngDB.Value
    Sheet3.Range(Sheet3.Cells(currRow, rngDB.Columns.Count + 1), Sheet3.Cells(currRow + rngDB.Rows.Count - 1, rngDB.Columns.Count + 1)).Value = rngDB.Cells(-1, 2)

    currRow = currRow + rngDB.Rows.Count

    lastRow = rngSt.Row
    Set rngSt = rngStCol.FindNext(rngSt)
Loop


End Sub
于 2012-09-29T17:13:13.910 回答