列内容匹配时,将值从一个工作表复制到另一个工作表

时间:2012-02-28 15:44:05

标签: excel

我正在寻找类似的公式,如下所示: How to copy data from sheet1 to sheet2 with a condition in Excel

我正在使用:

= IF(EXACT(Sheet 1中!B4,Sheet 2中!A7),工作表Sheet!A4)

只是我想添加条件,如果sheet1的B列没有我要查找的值,它将查看B列中的下一行。如果匹配那么A列中该行的值将是复制的值。

由于

2 个答案:

答案 0 :(得分:1)

很明显,没有人会为您提供配方解决方案。当然我不知道如何用公式解决你的问题。

您尚未定义来源或目标表格的格式。但是,我有一些代码可以解决,以匹配可能的格式。

下图中左侧是我的源表。请注意,列C包含一个我已格式化为“ddd dd”的日期,因为我发现这种类型的列表是一种方便的格式。右侧是输出的打印图像。列宽,边框和单元格合并由宏设置。

站名称序列由宏中的数组设置。我有三个站,但这是任意的。输出表中的开始日期,开始时间,结束时间和结束日期由源表中的最早和最新值设置。

宏中的原始验证与您的要求不符,因此我删除了它。您需要添加自己的。

宏观并未注意到安吉拉周二中午12点有两个电台。它确实注意到源行13和18与先前的条目重叠并报告这些错误。

enter image description here

下面的代码包含解释它正在做什么但不解释为什么或如何做的评论。我希望这会给你一些想法。如有必要,请回答问题。

Option Explicit

  Type typStationBooking
    NamePerson As String
    NameStation As String
    BookDate As Date
    BookTimeStart As Long       ' Time in minutes  540 = 9:00
    BookTimeEnd As Long         ' Time in minutes  900 = 15:00
  End Type
Sub ListByNameToListByStation()

  Dim ColDataCrnt As Long
  Dim DateCrnt As Date
  Dim DateLatest As Date
  Dim DateEarliest As Date
  Dim Found As Boolean
  Dim InxBookCrnt As Long
  Dim InxBookMax As Long
  Dim InxStatCrnt As Long
  Dim NumRowsPerDay As Long
  Dim NumStations As Long
  Dim NumTimeSlots As Long
  Dim Occupied As Boolean
  Dim RowDataCrnt As Long
  Dim RowDataDayFirst As Long
  Dim RowDataLast As Long
  Dim RowDataTimeSlot As Long
  Dim StationBooking() As typStationBooking
  Dim StationName() As Variant
  Dim SheetDest As String
  Dim SheetSrc As String
  Dim TimeCrnt As Long
  Dim TimeEarliest As Long
  Dim TimeLatest As Long
  Dim TimeInterval As Long

  ' Names of stations in desired column sequence.  Names must match
  ' those used in worksheet Source.  LBound = 0
  StationName = Array("Station2", "Station3", "Station1")

  SheetDest = "Dest"      ' ) Change to your
  SheetSrc = "Source"     ' ) sheet names

  DateEarliest = -1
  DateLatest = -1

  TimeInterval = 30       ' ) Values in minutes.  Change as necessary
  TimeEarliest = -1
  TimeLatest = -1

  With Sheets(SheetSrc)

    ' First Last used row
    RowDataLast = .Cells(Rows.Count, "A").End(xlUp).Row

    ' Reserve space for rows 2 to RowLast
    ReDim StationBooking(1 To RowDataLast - 1)

    InxBookMax = 0     ' No current entries

    ' Load data from Sheet1 table into array
    For RowDataCrnt = 2 To RowDataLast
      ' ### The source data should be checked:
      ' *  Person name non-blank
      ' *  Station name matches value in StationName()
      ' *  Day is date in range DateFirst to DateLast
      ' *  Start and End times are times in range TimeFirst to
      '    TimeLast+TimeInteval with Start time before End time
      '    and both are of the form TimeStart + N*TimeInterval
      '    where is a positive integer

      InxBookMax = InxBookMax + 1
      StationBooking(InxBookMax).NamePerson = .Cells(RowDataCrnt, 1).Value
      StationBooking(InxBookMax).NameStation = .Cells(RowDataCrnt, 2).Value
      StationBooking(InxBookMax).BookDate = .Cells(RowDataCrnt, 3).Value
      StationBooking(InxBookMax).BookTimeStart = _
            Hour(.Cells(RowDataCrnt, 4).Value) * 60 + _
                                     Minute(.Cells(RowDataCrnt, 4).Value)
      StationBooking(InxBookMax).BookTimeEnd = _
            Hour(.Cells(RowDataCrnt, 5).Value) * 60 + _
                                     Minute(.Cells(RowDataCrnt, 5).Value)
      If DateEarliest = -1 Then
        DateEarliest = StationBooking(InxBookMax).BookDate
        DateLatest = StationBooking(InxBookMax).BookDate
      Else
        If DateEarliest > StationBooking(InxBookMax).BookDate Then
          DateEarliest = StationBooking(InxBookMax).BookDate
        End If
        If DateLatest < StationBooking(InxBookMax).BookDate Then
          DateLatest = StationBooking(InxBookMax).BookDate
        End If
      End If
      If TimeEarliest = -1 Then
        TimeEarliest = StationBooking(InxBookMax).BookTimeStart
        TimeLatest = StationBooking(InxBookMax).BookTimeEnd
      Else
        If TimeEarliest > StationBooking(InxBookMax).BookTimeStart Then
          TimeEarliest = StationBooking(InxBookMax).BookTimeStart
        End If
        If TimeLatest < StationBooking(InxBookMax).BookTimeEnd Then
          TimeLatest = StationBooking(InxBookMax).BookTimeEnd
        End If
      End If
    Next

  End With

  With Sheets(SheetDest)

    ' Lay out destination sheet
    ' Format per day
    ' Row 1 : Date
    ' Row 2 : Station names
    ' Row 3+: One row per time interval from TimeEarliest to
    '                                       TimeLatest + TimeInteval
    ' Row N : Blank row
    ' Col 1 : Time
    ' Col 2+: Station name

    ' Delete current contents
    .Cells.EntireRow.Delete

    NumRowsPerDay = (TimeLatest - TimeEarliest) / TimeInterval + 3
    NumStations = UBound(StationName) + 1

    ' Set column widths
    .Columns(1).ColumnWidth = 6
    For ColDataCrnt = 2 To NumStations + 1
      .Columns(ColDataCrnt).ColumnWidth = 14
    Next

    RowDataCrnt = 1
    DateCrnt = DateEarliest
    Do While DateCrnt <= DateLatest
      RowDataDayFirst = RowDataCrnt
      .Range(.Cells(RowDataCrnt, 1), .Cells(RowDataCrnt, 1 + NumStations)).Merge
      With .Cells(RowDataCrnt, 1)
        .HorizontalAlignment = xlCenter
        .NumberFormat = "dddd d mmmm"
        .Value = DateCrnt
      End With
      RowDataCrnt = RowDataCrnt + 1
      InxStatCrnt = 0
      For ColDataCrnt = 2 To NumStations + 1
        .Cells(RowDataCrnt, ColDataCrnt).Value = StationName(InxStatCrnt)
        InxStatCrnt = InxStatCrnt + 1
      Next
      RowDataCrnt = RowDataCrnt + 1
      TimeCrnt = TimeEarliest
      Do While TimeCrnt < TimeLatest
        With .Cells(RowDataCrnt, 1)
          .NumberFormat = "hh:mm"
          .Value = DateCrnt + TimeSerial(TimeCrnt \ 60, TimeCrnt Mod 60, 0)
        End With
        RowDataCrnt = RowDataCrnt + 1
        TimeCrnt = TimeCrnt + TimeInterval
      Loop
      With .Range(.Cells(RowDataDayFirst, 1), _
                  .Cells(RowDataCrnt - 1, NumStations + 1))
        With .Borders(xlEdgeLeft)
          .LineStyle = xlContinuous
          .Weight = xlThin
          .Color = RGB(192, 192, 192)
        End With
        With .Borders(xlEdgeTop)
          .LineStyle = xlContinuous
          .Weight = xlThin
          .Color = RGB(192, 192, 192)
        End With
        With .Borders(xlEdgeBottom)
          .LineStyle = xlContinuous
          .Weight = xlThin
          .Color = RGB(192, 192, 192)
        End With
        With .Borders(xlEdgeRight)
          .LineStyle = xlContinuous
          .Weight = xlThin
          .Color = RGB(192, 192, 192)
        End With
        With .Borders(xlInsideVertical)
          .LineStyle = xlContinuous
          .Weight = xlThin
          .Color = RGB(192, 192, 192)
        End With
        With .Borders(xlInsideHorizontal)
          .LineStyle = xlContinuous
          .Weight = xlThin
          .Color = RGB(192, 192, 192)
        End With
      End With
      RowDataCrnt = RowDataCrnt + 1
      DateCrnt = DateSerial(Year(DateCrnt), Month(DateCrnt), Day(DateCrnt) + 1)
    Loop

    ' Now place each entry in StationBooking  in the appropriate cell(s)

    For InxBookCrnt = 1 To InxBookMax
      'Debug.Assert InxBookCrnt <> 17
      DateCrnt = StationBooking(InxBookCrnt).BookDate
      RowDataDayFirst = (DateCrnt - DateEarliest) * NumRowsPerDay + 1
      TimeCrnt = StationBooking(InxBookCrnt).BookTimeStart
      RowDataTimeSlot = RowDataDayFirst + 2 + _
                                      (TimeCrnt - TimeEarliest) / TimeInterval
      NumTimeSlots = (StationBooking(InxBookCrnt).BookTimeEnd - TimeCrnt) _
                                                                 / TimeInterval
      Found = False
      For InxStatCrnt = 0 To UBound(StationName)
        If StationBooking(InxBookCrnt).NameStation = _
                                                   StationName(InxStatCrnt) Then
          Found = True
          Exit For
        End If
      Next
      If Not Found Then
        MsgBox ("Row " & InxBookCrnt + 1 & " of worksheet " & SheetSrc & _
                "contains an unknown station name")
      Else
        ColDataCrnt = InxStatCrnt + 2
        ' Check space for this entry is not already occupied
        Occupied = False
        For RowDataCrnt = RowDataTimeSlot To RowDataTimeSlot + NumTimeSlots - 1
          If .Cells(RowDataCrnt, ColDataCrnt) <> "" Then
            Occupied = True
            Exit For
          End If
        Next
        If Not Occupied Then
          If Range(.Cells(RowDataTimeSlot, ColDataCrnt), _
                   .Cells(RowDataTimeSlot + NumTimeSlots - 1, _
                                        ColDataCrnt)).MergeCells Then
            Occupied = True
          End If
        End If
        If Occupied Then
          MsgBox ("Row " & InxBookCrnt + 1 & " of worksheet " & SheetSrc & _
                   " overlaps a previous entry")
        Else
          ' Entire slot is free
          .Cells(RowDataTimeSlot, ColDataCrnt).Value = _
                                     StationBooking(InxBookCrnt).NamePerson
          If NumTimeSlots > 1 Then
            With .Range(.Cells(RowDataTimeSlot, ColDataCrnt), _
                        .Cells(RowDataTimeSlot + NumTimeSlots - 1, ColDataCrnt))
              .Merge
              .WrapText = True
              .VerticalAlignment = xlCenter
             End With
          End If
        End If
      End If
    Next

  End With

End Sub

答案 1 :(得分:0)

以下示例可帮助您根据“来自工作表”中的匹配列,将值(行方式)从一个工作表复制到另一个工作表。

Sub TodaysActions()

Dim listSheetRange As Range
'Sheet to copy data From
Dim listSheet As Worksheet
'Sheet to copy data To
Dim actionSheet As Worksheet

Set listSheetRange = Worksheets("List").UsedRange
Set listSheet = Worksheets("List")
Set actionSheet = Worksheets("Action")

'Clear the To Sheet
actionSheet.UsedRange.Clear

'Row 1 of From Sheet contains the data to match
'Copy Header Row i.e Row 2 of From Sheet
listSheet.Rows(2).Copy Destination:=actionSheet.Rows(1)

currentActionRow = 2

For i = 3 To listSheetRange.Rows.Count
    'Comparision Condition
    If InStr(listSheetRange.Cells(i, 1), listSheetRange.Cells(1, 3)) Then
        listSheet.Rows(i).Copy Destination:=actionSheet.Rows(currentActionRow)
        currentActionRow = currentActionRow + 1
    End If
Next i

'hide any unwanted columns
actionSheet.Columns(1).Hidden = 1
actionSheet.Activate

End Sub