【问题标题】:Multidimensional Data Input多维数据输入
【发布时间】:2020-06-24 03:57:43
【问题描述】:

我目前被困在如何实现在 VBA 中获取和存储信息的过程。

目标:

  • 获取要分配任务的代理列表。
  • 获取每个代理的任务列表(票号)
  • 将信息格式化为已定义的电子邮件回复结构

目前,我有一个函数可以获取代理名称 (isagent(sAgent)) 并对其进行验证,获取票号 (Incident()) 并对其进行验证,以及使用要格式化的字符串回复消息的功能消息(sBody)。

问题:

输入数据的存储容器是我的保留。我不认为数组是一个正确的选择,因为代理的数量和每个代理的票数每天都会波动。

例如: 昨天的请求:将 123 票重新分配给第 1 个人

今天的请求 - 将工单 123、456 和 789 重新分配给第 1 个人。将 012 重新分配给第 2 个人,将 345、678、901、234 和 567 重新分配给第 3 个人

格式:

存储数据的格式需要这样返回:

示例 - 昨天的请求:123 已重新分配给 person1。 今天的请求: 123、456 和 789 已重新分配给人员 1。 012 已重新分配给第 2 个人。 345、678、901、234 和 567 已重新分配给第 3 个人

代码:

此部分为Message body格式,可以组合成一个字符串(sBody)。变量当前设置为 sIncs 代表票号,sXferAgent 代表代理,sTense 代表句子时态。

'Set Body Reply
    Dim sOpen, sBody, sAddendum, sClose As String 'Message Reply Format
    sOpen = "<span style=""font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;mso-bidi-font-family:" & vbCrLf & _
            "Arial"">Team, <o:p></o:p></span>" & vbCrLf

    sBody = "<p><span style=""font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;mso-bidi-font-family:" & vbCrLf & _
            "Arial"">" & sINCs & " " & sTense & " been created and assigned to " & sXferAgent & "<o:p></o:p></span></p>" & vbCrLf

    sClose = "<p><span style=""font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;mso-bidi-font-family:" & vbCrLf & _
            "Arial"">Thanks &amp; Regards,<o:p></o:p></span></p>" & vbCrLf & _
            "<p><br/></p>"

    olMsgReplyAll.HTMLBody = sOpen & sBody & sClose & sSig & olMsgReplyAll.HTMLBody

要获得票证和代理格式,我是这样称呼它们的:

Dim sInc As String
'Receive Incident Number as AlphaNumeric
sInc = Incident()
If sInc = "" Then
    Exit Sub
End If


'Receive Agent Name
sAgent = ValidateAgent
If sAgent = "" Then
    Exit Sub
End If

目前,我的半傻想法如下:

Sub Handoff()
    'Get reassigned tickets in loop
    'Asks for how many agents, ticket count per agent, gathers agent name and tickets for agent
    'Functions in place for get agent name, and ticket number preformatted
    'storage container issues for above process
    'Formats data into separate lines with verbiage
    Dim colReassignments As New Collection       'container for all reassignments
    Dim colAgents As New Collection              'container for agents
    Dim colTickets As New Collection             'container for tickets
    Dim ReassignCount As Integer                 '# of tickets for the agent
    Dim ReassignAgent As Integer                 'Agents to reassign to
    Dim Reassignments() As String

    'Start inquiry
    ReassignAgent = InputBox("Input number of Agents tickets being reassigned to:", "Agent Counter")
    If ReassignAgent = vbNullString Then
        Exit Sub
    End If


    While ReassignAgent > 0
        colAgents.Add = ValidateAgent
        ReassignCount = InputBox("Input number of ticket being reassigned to agent:", "Ticket Counter")
        If ReassignCount = vbNullString Then
            Exit Sub
        End If


        For Each agent In colAgents
            For Each ticket In colTickets
                agent(x).ticket(y) = Incident()
                If agent(x).ticket(y) = "" Then
                    Exit Sub
                End If
                agent(x) = ValidateAgent
                If agent(x) = "" Then
                    Exit Sub
                End If
                ReassignCount = ReassignCount - 1
            Next ticket
        Next agent
    Wend

    'Sentence Formatting

    'Get Tense of reassignment
    If ReassignCount > 1 Then
        tense = "have"
    Else
        tense = "has"
    End If

    'Compile stored info
    'Format: "(Ticket#(s)) (tense) been reassigned to (Agent)" repeat lines as necessary

    'Process email
    'In another module
End Sub

非常感谢任何建议或意见。我可能把问题复杂化了。

更新以反映其他模块:

    'Function to get ticket number
Public Function Incident()
    Dim strPattern As String: strPattern = "^(?:INC|NC|C)?([0-9]{1,8}$)"
    Dim strReplaceINC As String: strReplaceINC = "$1"
    Dim regEx As New RegExp
    Dim strInput As String
    Dim IncResult As Boolean

    Do
        If strPattern <> "" Then

            strInput = InputBox("Input Incident Number", "Ticket Number")

            If strInput = vbNullString Then
                Exit Function
            End If

            IncResult = False

            With regEx
                .Global = True
                .MultiLine = True
                .IgnoreCase = True
                .Pattern = strPattern
            End With

            If regEx.Test(strInput) Then
                sInc = regEx.Replace(strInput, strReplaceINC)
                sInc = "INC" & Format(sInc, "00000000")
                IncResult = True
            Else
                MsgBox ("Please input a valid ticket number format")
                IncResult = False
            End If
        End If

    Loop While IncResult = False
    Incident = sInc
End Function

'Function to select Agent
Public Function IsAgent(stxt As String) As Boolean
        Dim aAgent As Variant, oItem As Variant, bans As Boolean
        aAgent = Array("Bob", "Chuck", "David", "Fred", "John", "Kirk", "Paul", "Sean")
        bans = False
        For Each oItem In aAgent
            If LCase(oItem) = LCase(Trim(stxt)) Then
                bans = True
                Exit For
            End If
        Next
        IsAgent = bans
    End Function

'Function to Validate Agent
Public Function ValidateAgent()

    'Dim sAgent As String 'Assigned Agent
    Do
        sAgent = InputBox("Please enter a the assigned agent's name:", "Pick an Assignee's Name")
        If sAgent = vbNullString Then
            Exit Function
        End If
        If sAgent <> "" Then
            If GlobalVars.IsAgent(sAgent) = True Then
                sAgent = sAgent
            Else
                MsgBox ("Incorrect Name, pick a new one!")
            End If
        End If

    Loop While GlobalVars.IsAgent(sAgent) = False
    ValidateAgent = sAgent
End Function

【问题讨论】:

  • 如果您担心尺寸变化,数组可以是动态的。不过,您只能重新调整最后一个维度。在某些情况下,您可以通过转置暂时/永久地交换最后一个维度来解决这个问题。
  • 这是在乞求面向对象的解决方案。
  • 注意Dim sOpen, sBody, sAddendum, sClose As String 中只有 sClose 是一个字符串。其余的将是变体。在这样的列表中,您需要在每个变量名之后使用As String
  • agent(x).ticket(y) = Incident() 是做什么的? agentticket 似乎是简单的变体。我想不出任何方式可以将它们像这样组合在一起。
  • sInc = Incident()sAgent = ValidateAgent 如何工作?

标签: arrays vba collections outlook


【解决方案1】:

请不要在评论中发布这么多代码,因为它很难(不可能?)阅读。它应该添加到问题中。

我忘记了像ValidateAgent 这样的例程有一个粗鲁的名字。该名称隐藏了例程的作用,即输入经过验证的代理。像GetValidatedAgent 这样的名字会更好

InputBox 是一种非常笨拙的输入多个值的方法。如果我理解正确,用户输入代理,然后计数,然后计数票。有一个循环允许多个代理进入,每个代理都有自己的一组票。

假设我输入了 3,然后发现有 4 张票?我将如何解决我的错误?假设我已经输入 Bob 作为代理并在意识到我输入 Alice 的票之前开始输入票。我将如何解决我的错误?

我会使用表格。

如果代理的最大数量和每个代理的票数很少,我可能会选择一个文本框网格。例如,用户将在第 1 列中输入代理,在第 2 到第 5 列中输入票证。我可能会有 10 行。当用户移动到新的文本框时,我会验证代理和票证。在用户单击提交按钮之前,我不会检查一致性(例如,没有代理的票和没有票的代理)。在数据一致或用户单击取消按钮之前,我不会允许退出。通过这种布局,用户可以在屏幕上看到他们的全部输入,并可以纠正任何有问题的代理或工单。

在退出表单之前,数据必须保存在全局变量中。我可能会选择最简单的,我认为是字符串数组:

AgentA,Ticket1,Ticket2,Ticket3
AgentB,Ticket4
AgentB,Ticket5,Ticket6
  :      :      :      :

当我准备好处理每个字符串时,我会使用 Split 将其转换为数组。

如果您确认最多约 10 个代理和每个代理约 5 张票,我将讨论可能的 Html 布局。如果有更多的代理或票,我会建议不同的方法。

【讨论】:

  • 我曾想过使用表格,但是由于过去分配的票数从 5 到 20 不等,因此它带来了很多限制。我已经开始尝试用嵌套集合做字典,可能需要将其切换为嵌套数组。
  • @Matt (1) 我建议的布局不太适合 20 张门票。但是,表格仍然是收集如此多数据的最佳方法。我可以针对门票数量的广泛变化修改我的答案。代理的最大数量是多少?
  • @Matt (2) 您的提问顺序错误。您需要决定如何从用户那里获取数据以及如何在电子邮件中排列这些数据,然后才能决定如何保存这些数据。我怀疑数组或字符串集合将是保存数据的最简单方法,但在用户界面(输入和输出)达成一致之前无法确认。
  • @Matt (3) 您是否同意用户在承诺创建电子邮件之前查看所有代理和工单很重要?
  • @Matt (4) 电子邮件的格式有多重要?我认为清晰是一个优先事项。漂亮的外表有多重要?有人会尝试使用 VBA 提取数据吗?
【解决方案2】:

所以经过大量的试验和错误,我创造了一些功能性的东西。我最终为代理名称输入创建了一个字典,然后嵌套了一个 Collection 用于输入(重新分配)他们的票。部分代码引用了全局变量,但这是该函数的主要模块。

Option Compare Text
Public Sub Handoff_Req()
Dim objSelection As Outlook.Selection
Dim objItem As Object
Set objOL = Outlook.Application
Dim olMsg As Outlook.MailItem
Dim olMsgReplyAll As Outlook.MailItem
Dim IsPlainText As Boolean

'Define Product
sProduct = "HANDOFF"

'Receive Incident Number as AlphaNumeric
sInc = Incident()
If sInc = "" Then
    Exit Sub
End If

'Receive Severity level
Sev = 4

'Get reassigned tickets in loop
Dim dictReassignments As Scripting.Dictionary
Dim kagent As Variant
Set dictReassignments = New Scripting.Dictionary 'container for agents
Dim colTickets As New Collection    'container for tickets
Dim AgentCounter As Variant
Dim TicketCounter As Variant
Dim TenseCounter As Integer
TenseCounter = 0

'Get number of agents to reassign to

Line1:    AgentCounter = InputBox("Input number of Agents that tickets are being reassigned to:", "Agent Reassignment Counter")
If Not IsNumeric(AgentCounter) Then
    MsgBox (AgentCounter & " is not a number, please try again.")
    GoTo Line1
Else
    AgentCounter = CInt(AgentCounter)
End If
If AgentCounter > 5 Then
        numa = MsgBox("Do you want to input more than " & TicketCounter & " tickets for " & kagent & "?", 4, "Correct ticket amount?")
        If numa = 6 Then 'Yes
            GoTo Line2 'Continue loop
        ElseIf numa = 7 Then 'No
            GoTo Line1 'Repeat agent counter question
        End If
    End If
Line2:  While AgentCounter > 0
    Set colTickets = New Collection
    kagent = ValidateReassignedAgent
    If kagent = "" Then
        Exit Sub
    End If
Line3:  TicketCounter = InputBox("Input number of ticket(s) being reassigned to agent:", "Ticket Reassignment Counter")
    If Not IsNumeric(TicketCounter) Then
        MsgBox (TicketCounter & " is not a number, please try again.")
        GoTo Line3
    Else
        TicketCounter = CInt(TicketCounter)
    End If
    If TicketCounter > 10 Then
        numa = MsgBox("Do you want to input more than " & TicketCounter & " tickets for " & kagent & "?", 4, "Correct ticket amount?")
        If numa = 6 Then 'Yes
            GoTo Line4 'Continue loop
        ElseIf numa = 7 Then 'No
            GoTo Line3 'Repeat ticket counter question
        End If
    End If

Line4:  While TicketCounter > 0
        xInc = Reassignments()
        If xInc = "" Then
            MsgBox ("Please input a valid number")
        End If
            colTickets.Add xInc
        TicketCounter = TicketCounter - 1
    Wend
    dictReassignments.Add kagent, colTickets
    AgentCounter = AgentCounter - 1
Wend


'Check dictionary of agents
For Each agent In dictReassignments.Keys()
    'MsgBox (agent)
    sXferAgent = agent
    For Each ticket In dictReassignments(agent)
        'MsgBox (ticket)
        TenseCounter = TenseCounter + 1
        sINCs = ticket & ", " & sINCs
        sTense = "have"
    Next ticket
    'MsgBox (TenseCounter)
    If TenseCounter > 1 Then
        sTense = " have"
        sINCs = Left(sINCs, Len(sINCs) - 2)
        sINCs = StrReverse(Replace(StrReverse(sINCs), StrReverse(", "), StrReverse(", and "), , 1))
    Else
        sTense = "has"
        sINCs = Left(sINCs, Len(sINCs) - 2)
    End If
    sBody = "<p><span style=""font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;mso-bidi-font-family:" & vbCrLf & _
        "Arial"">" & sINCs & " " & sTense & " been reassigned to " & sXferAgent & " per hand-off process.<o:p></o:p></span></p>" & vbCrLf
    scombined = sBody & scombined
    TenseCounter = 0
    sINCs = Null
    sTense = Null
    sXferAgent = Null
Next agent

'Process Agents for email inclusion
For Each agent In dictReassignments.Keys()
    sXferAgent = agent
    exAgent = AddXferRecip(sXferAgent)
    sXferredAgents = exAgent & "; " & sXferredAgents
Next


'Find Logged in Agent
SDagent = LoggedIn
If SDagent = "" Then
    Exit Sub
End If

'Set Category Color
Color = GetColor(SDagent)
If Color = "" Then
    Exit Sub
End If

'Get the selected item
Select Case TypeName(objOL.ActiveWindow)
    Case "Explorer"
        Set objSelection = objOL.ActiveExplorer.Selection
        If objSelection.Count > 0 Then
            Set objItem = objSelection.Item(1)
        Else
            result = MsgBox("No item selected. " & _
                        "Please make a selection first.", _
                        vbCritical, "Reply All in HTML")
            Exit Sub
        End If

    Case "Inspector"
        Set objItem = objOL.ActiveInspector.CurrentItem
    Case Else
        result = MsgBox("Unsupported Window type." & _
                    vbNewLine & "Please make a selection" & _
                    " or open an item first.", _
                    vbCritical, "Reply All in HTML")
        Exit Sub
End Select


'Change the message format and reply
If objItem.Class = olMail Then
    Set olMsg = objItem
    If olMsg.BodyFormat = olFormatPlain Then
        IsPlainText = True
    End If
    olMsg.BodyFormat = olFormatHTML
    Set olMsgReplyAll = olMsg.ReplyAll
    If IsPlainText = True Then
        olMsg.BodyFormat = olFormatPlain
    End If


'Delete Automatic Signature
GlobalVars.DelSig olMsgReplyAll

'Remove Non-Monitored or Invalid email addresses
Dim recipremove As Variant
Dim element As Variant
    recipremove = Array("IT Service Desk")

    For lngCnt = olMsgReplyAll.Recipients.Count To 1 Step -1
         Set olkrcp = olMsgReplyAll.Recipients.Item(lngCnt)
         For Each element In recipremove
         If olkrcp.Name = element Then
             If olkrcp.Type = olTo Or olCC Then
                 olMsgReplyAll.Recipients.Item(lngCnt).Delete
             End If
         End If
         Next element
     Next


   'Add recipients
    exAgent = AddXferRecip(sXferredAgents)

    'Set Recipients
    Dim olRecip As Recipient ' Add Recipient
    Set olRecip = olMsgReplyAll.Recipients.Add(sXferredAgents) 'add multiple agents assigned
    olRecip.Resolve

    'BCC to SharePoint for tracking
    Set olRecip = olMsgReplyAll.Recipients.Add("Email Address")
    olRecip.Type = olBCC
    olRecip.Resolve

    'Include SD Mgr if Sev 1
    If Sev = "1" Then
        Set olRecip = olMsgReplyAll.Recipients.Add("Email Address")
        olRecip.Type = olBCC
        olRecip.Resolve
    End If

    'Delete Duplicate addresses

    Dim i As Integer, j As Integer
    Dim olRecip1 As Recipient, olRecip2 As Recipient
    Dim colRecipients As Recipients
    Set colRecipients = olMsgReplyAll.Recipients
        For i = colRecipients.Count To 1 Step -1
        Set olRecip1 = colRecipients.Item(i)
            For j = (i - 1) To 1 Step -1
                Set olRecip2 = colRecipients.Item(j)
                If olRecip1.Name = olRecip2.Name Then
                    If olRecip1.Type = olTo Or olCC Then
                        olRecip1.Delete
                        Exit For
                    End If
                End If
            Next
        Next

    'Format Subject Line
    GlobalVars.SubjLine olMsgReplyAll

   'Set Signature
    sSig = SigAdd

    'Set Body Reply
    Dim sOpen As String, sAddendum As String, sClose As String 'Message Reply Format
    sOpen = "<span style=""font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;mso-bidi-font-family:" & vbCrLf & _
            "Arial"">Team, <o:p></o:p></span>" & vbCrLf

    sBody = scombined

    sClose = "<p><span style=""font-size:11.0pt;font-family:&quot;Calibri&quot;,sans-serif;mso-bidi-font-family:" & vbCrLf & _
            "Arial"">Thanks &amp; Regards,<o:p></o:p></span></p>" & vbCrLf & _
            "<p><br/></p>"

    olMsgReplyAll.HTMLBody = sOpen & sBody & sClose & sSig & olMsgReplyAll.HTMLBody

    'Get Attachments
    GlobalVars.CopyAttachments olMsg, olMsgReplyAll

    'Set Category Color
    olMsg.Categories = Color & ";Hand-off Notices"

    'Display Reply
    olMsg.Close (olSave)
    olMsgReplyAll.Display
    Dim oMail As Outlook.MailItem



'Selected item isn't a mail item
Else
    result = MsgBox("No message item selected. " & _
                "Please make a selection first.", _
                vbCritical, "Reply All in HTML")
    Exit Sub
End If

'Cleanup
Set objOL = Nothing
Set objItem = Nothing
Set objSelection = Nothing
Set olMsg = Nothing
Set olMsgReplyAll = Nothing

End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-10
    • 2016-09-23
    • 2012-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多