美好的一天!,我仍然是VBA的新人,任何帮助将不胜感激。 :)
我的问题是,我正在VBA中生成一个生成的报告,现在我正处于需要在特定列中获取相同数据的部分,并在最后添加另一列以根据给定标准对其进行标记..
这是标准:
注意:相同的数据在列(服务号)中,也在第4号标准中
例如:
Completed-date | Installed-date | Service# | Status | Tag |
03/03/2016 | 03/03/2016 | 1111 | repaired | |
04/04/2016 | 04/04/2016 | 1111 | defective | |
05/05/2016 | 05/06/2016 | 1111 | defective | |
06/06/2016 | 06/07/2016 | 2222 | repaired | |
07/07/2016 | 07/07/2016 | 3333 | defective | |
08/08/2016 | 08/08/2016 | 4444 | change modem | |
08/09/2016 | 08/09/2016 | 4444 | change modem | |
列标记仍然是空的因为我们没有选择标准, 现在样本输出是这样的..
输出:
Completed-date | Installed-date | Service# | Status | Tag |
03/03/2016 | 03/03/2016 | 1111 | repaired | |
04/04/2016 | 04/04/2016 | 1111 | defective | |
05/05/2016 | 05/06/2016 | 1111 | defective | 1 |
06/06/2016 | 06/07/2016 | 2222 | repaired | |
07/07/2016 | 07/07/2016 | 3333 | defective | |
08/08/2016 | 08/08/2016 | 4444 | change modem | |
08/09/2016 | 08/09/2016 | 4444 | change modem | 4 |
现在,正如您在标签(列)中看到的那样,我们根据标准选择了它 我只在最近完成的日期标记每个重复的一个数据。
这是我的代码,我的代码只确定行中的副本我不知道如何开始编码标准..请帮帮我!...
Public Sub sample1()
Dim varCOMDate As Variant
Dim varServiceID As Variant
Dim varInstallationDate As Variant
Dim serviceIDRng As Range
Dim lastRow As Long
Dim matchFoundIndex As Long
Dim iCntr As Long
Set Sheet1 = Workbooks.Open(TextBox1.Text).Sheets(1)
lngLastRow = Sheet1.Range("A" & wksht.Rows.Count).End(xlUp).Row
Set serviceIDRng = wksht.Range("C1:C" & lngLastRow)
For iCntr = 1 To lastRow
If Cells(iCntr, 1) <> "" Then
matchFoundIndex = WorksheetFunction.Match(Cells(iCntr, 1), Range("A1:A" & lastRow), 0)
If iCntr <> matchFoundIndex Then
Cells(iCntr, 2) = "Duplicate" (I want to start the loop of dates here)
End If
End If
Next
End Sub
答案 0 :(得分:0)
这是一个帮助你的片段。它不完整,几乎没有说明异常数据。您还没有充分指定标准,例如,如果有多个行满足条件,应该发生什么,例如5次出现&#34; 1111&#34;在3个月内。
您必须根据所需的具体标准更改代码(或将其用作启发其他内容的灵感)。
Sub duplicateTaggerExample()
Dim startRng As Range, currRng As Range
Dim first1Var As Date, second1Var As Date, third1Var As Date
Set startRng = Range("C2")
Set currRng = startRng
Do While (Not currRng Is Nothing And currRng.Value <> "")
Select Case currRng.Value
Case "1111"
' Test if we're beyond the criteria - if so, reset vars and skip
If (CDate(currRng.Value) - firstVar) > 90 Then
first1Var = ""
second1Var = ""
third1Var = ""
GoTo SkipIteration
End If
' If we haven't skipped the iteration, it means the criteria is still viable, so we need to proceed with the comparison
If first1Var <> "" And second1Var <> "" Then
' If both first and second vars are filled, we fill the third.
' We can do this without further comparison, because we already checked if we're inside the window for the criteria or not.
third1Var = CDate(currRng.Value)
ElseIf firstVar <> "" Then
' If only the first var is filled, fill the 2nd var.
second1Var = CDate(currRng.Value)
Else
' Should never happen, but...
Debug.Print "Some error"
End If
' If the third var is filled, criteria is matched and we need to mark the occurrence and reset vars
If third1Var <> "" Then
currRng.Offset(0, 2).Value = "1"
first1Var = ""
second1Var = ""
third1Var = ""
End If
Case "2222"
' Fill these as well, but the criteria are different so you will have to use different code than the above
Case "3333"
Case "4444"
Case Else
' something
End Select
SkipIteration:
Loop
End Sub
答案 1 :(得分:0)
@Vegard,我希望你不介意我在你之后发布一个答案,但我一直在看这篇文章的扩展,我觉得有很多内容可供其他人学习。
@&amp; A65726F,我的一些答案可能看起来有点,我们可以说是健壮的,所以通过橄榄枝我已经发布了一些代码,这将为你解决这个问题。
好的,所以......
Collection
内按ServiceNumber对其进行分组。如果我花时间完成这项任务,我可能也会把它放到日期的子组中。以下是一些将开始攻击您的问题的代码。我已将其分解为小的模块化块,以便您可以看到每个部分的作用,并且可以随意扩展它们,例如,有一个单独的数据验证例程。我不打算为你写你的项目,所以请花一些时间自己完成。我们的想法是,在您优化标准并扩展数据验证时,您自己添加它。将此代码粘贴到Module
:
Option Explicit
'Worksheet constants
Private Const SHEET_NAME As String = "Sheet1"
Private Const COMPLETED_DATE_COL As Long = 1
Private Const INSTALLED_DATE_COL As Long = 2
Private Const SERVICE_NUM_COL As Long = 3
Private Const STATUS_COL As Long = 4
Private Const TAG_COL As Long = 5
Private Const START_ROW As Long = 2
'Status constants
Private Const REPAIRED_ID As Integer = 0
Private Const DEFECTIVE_ID As Integer = 1
Private Const CHANGE_MODEM_ID As Integer = 2
'Tag test constants for variant array
Private Const T1_HIT_ID As Integer = 0
Private Const T2_HIT_ID As Integer = 1
Private Const T3_HIT_ID As Integer = 2
Private Const T4_HIT_ID As Integer = 3
Private Const ROW_ID As Integer = 4
Private Const COMPLETED_DATE_ID As Integer = 5
Private Const INSTALLED_DATE_ID As Integer = 6
Private Const SERVICE_COUNT_ID As Integer = 7
Private Const MODEM_COUNT_ID As Integer = 8
Private mStatusList As Collection
Public Sub RunMe()
'Run this once
Initialise
Dim data As Variant
Dim result As Variant
'Run each time you set the tags
data = ReadData
result = GetTagTests(data)
WriteData result
End Sub
Private Sub Initialise()
'Set the allowable list of status definitions
Set mStatusList = New Collection
mStatusList.Add REPAIRED_ID, "repaired"
mStatusList.Add DEFECTIVE_ID, "defective"
mStatusList.Add CHANGE_MODEM_ID, "change modem"
End Sub
Private Function ReadData() As Variant
Dim endRow As Long
Dim data As Variant
'Read the data to variant
With ThisWorkbook.Worksheets(SHEET_NAME)
endRow = .Cells(.Rows.Count, SERVICE_NUM_COL).End(xlUp).Row
data = .Range(.Cells(START_ROW, COMPLETED_DATE_COL), .Cells(endRow, STATUS_COL)).Value2
End With
ReadData = data
End Function
Private Sub WriteData(data As Variant)
'Size the range and pass in the array
With ThisWorkbook.Worksheets(SHEET_NAME)
.Cells(START_ROW, TAG_COL).Resize(UBound(data, 1), UBound(data, 2)).value = data
End With
End Sub
Private Function GetTagTests(data As Variant) As Variant
Dim serviceItems As Collection
Dim rowData As Variant
Dim tagResults() As Variant
Dim tagTests As Variant
Dim tagParams(0 To 8) As Variant
Dim refDate As Date
Dim r As Long
'Dimension the output array
ReDim tagResults(1 To UBound(data, 1), 1 To 1)
'Loop through the data to assess for the tag criteria
Set serviceItems = New Collection
For r = 1 To UBound(data, 1)
'Validate the data
rowData = ValidatedRow(data, r)
If Not IsEmpty(rowData) Then
'Acquire tag params for this service number
tagTests = Empty
On Error Resume Next
tagTests = serviceItems(rowData(SERVICE_NUM_COL))
On Error GoTo 0
If IsEmpty(tagTests) Then 'it's a new service number
tagParams(T1_HIT_ID) = False
tagParams(T2_HIT_ID) = False
tagParams(T3_HIT_ID) = False
tagParams(T4_HIT_ID) = False
tagParams(ROW_ID) = r
tagParams(COMPLETED_DATE_ID) = rowData(COMPLETED_DATE_COL)
tagParams(INSTALLED_DATE_ID) = rowData(INSTALLED_DATE_COL)
tagParams(SERVICE_COUNT_ID) = 1
tagParams(MODEM_COUNT_ID) = IIf(rowData(STATUS_COL) = CHANGE_MODEM_ID, 1, 0)
serviceItems.Add tagParams, rowData(SERVICE_NUM_COL)
Else
'Run the first test
refDate = DateAdd("m", 3, tagTests(COMPLETED_DATE_ID))
If rowData(COMPLETED_DATE_COL) < refDate Then
tagTests(T1_HIT_ID) = True
Else
If tagTests(T1_HIT_ID) Then
tagResults(tagTests(ROW_ID), 1) = 1
End If
tagTests(T1_HIT_ID) = False
End If
'Run the second test
refDate = DateAdd("d", 15, tagTests(INSTALLED_DATE_ID))
If rowData(COMPLETED_DATE_COL) < refDate Then
tagTests(T2_HIT_ID) = True
Else
If tagTests(T2_HIT_ID) Then
tagResults(tagTests(ROW_ID), 1) = 2
End If
tagTests(T2_HIT_ID) = False
End If
'Run the third test
refDate = DateAdd("d", 30, tagTests(COMPLETED_DATE_ID))
If rowData(COMPLETED_DATE_COL) < refDate Then
If tagTests(SERVICE_COUNT_ID) >= 3 Then
tagTests(T3_HIT_ID) = True
Else
tagTests(T3_HIT_ID) = False
End If
Else
tagTests(SERVICE_COUNT_ID) = 0
End If
'Run the fourth test
If rowData(COMPLETED_DATE_COL) < refDate Then
If tagTests(MODEM_COUNT_ID) >= 1 Then
tagTests(T4_HIT_ID) = True
Else
tagTests(T4_HIT_ID) = False
End If
Else
tagTests(MODEM_COUNT_ID) = 0
End If
'Update the values
tagTests(COMPLETED_DATE_ID) = rowData(COMPLETED_DATE_COL)
tagTests(ROW_ID) = r
tagTests(INSTALLED_DATE_ID) = rowData(INSTALLED_DATE_COL)
tagTests(SERVICE_COUNT_ID) = tagTests(SERVICE_COUNT_ID) + 1
tagTests(MODEM_COUNT_ID) = tagTests(MODEM_COUNT_ID) + IIf(rowData(STATUS_COL) = CHANGE_MODEM_ID, 1, 0)
'Update the collection with the new tag test params
serviceItems.Remove rowData(SERVICE_NUM_COL)
serviceItems.Add tagTests, rowData(SERVICE_NUM_COL)
End If
End If
Next
'Catch all the outstanding hits
For Each tagTests In serviceItems
If tagTests(T1_HIT_ID) Then
tagResults(tagTests(ROW_ID), 1) = 1
End If
If tagTests(T2_HIT_ID) Then
tagResults(tagTests(ROW_ID), 1) = 2
End If
If tagTests(T3_HIT_ID) Then
tagResults(tagTests(ROW_ID), 1) = 3
End If
If tagTests(T4_HIT_ID) Then
tagResults(tagTests(ROW_ID), 1) = 4
End If
Next
GetTagTests = tagResults
End Function
Private Function ValidatedRow(data As Variant, r As Long) As Variant
Dim d As Date
Dim str As String
Dim i As Integer
Dim result(1 To 4) As Variant
'Test each of the values for correct types
On Error Resume Next
d = CDate(data(r, COMPLETED_DATE_COL))
result(COMPLETED_DATE_COL) = d
d = CDate(data(r, INSTALLED_DATE_COL))
result(INSTALLED_DATE_COL) = d
str = CStr(data(r, SERVICE_NUM_COL))
result(SERVICE_NUM_COL) = str
i = mStatusList(CStr(data(r, STATUS_COL)))
result(STATUS_COL) = i
'But there's a lot more validating that ought to be done, eg
'dates in sequence, completed before installed, etc.
If Err.Number = 0 Then
ValidatedRow = result
Else
ValidatedRow = Empty
End If
On Error GoTo 0
End Function