7

我正在寻找一些关于方法/数据结构/算法的建议,以解决我正在尝试解决的问题。关于使用什么方法/数据结构/算法的建议

我正在VBA中编写自定义电子表格应用程序。电子表格是一个劳动调度报表生成文档。用户输入基本的人工调度信息,该信息随后用于生成多个不同的工作表/文档,其中源数据以各种不同的布局/格式呈现。

说实话,Excel是错误的应用程序,但它是用户想要和舒适的,我知道VBA很好,所以这是我坚持。

用户输入的关键数据是以下格式,实质上是每个角色的每个日常工作呼叫的条目。

╔═════╦════════╦════════════════╦════════════════╦═══════════════════╗ 
║ QTY ║ ROLE ║  START  ║  END  ║ DESCRIPTION  ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/15/17 08:00a ║ 6/15/17 04:00p ║ Travel to Prep ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/16/17 08:00a ║ 6/16/17 06:00p ║ Prep    ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/17/17 08:00a ║ 6/17/17 07:00p ║ Prep    ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 3 ║ Rigger ║ 6/18/17 06:00a ║ 6/18/17 05:00p ║ Travel to Install ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 3 ║ Rigger ║ 6/19/17 08:00a ║ 6/20/17 01:00a ║ Install   ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 3 ║ Rigger ║ 6/20/17 10:00a ║ 6/20/17 08:00p ║ Install   ║ 
╠═════╬════════╬════════════════╬════════════════╬═══════════════════╣ 
║ 3 ║ Rigger ║ 6/21/17 07:00a ║ 6/21/17 04:00p ║ Travel Home  ║ 
╚═════╩════════╩════════════════╩════════════════╩═══════════════════╝ 

通常情况下,数据是跨越多天的多个角色,并会经常有一些(但不一定是全部)天一个角色的多个实例。

代码所做的其中一项数据操作是获取此源数据并将其重新格式化为汇总表,以便用户在分配人员后可以在以后分配名称。这也是其他各种个人工作呼叫表的基础和航班的计算数量/酒店,晚上等

╔══════╦═══════════╦═════════╦═════════╦═══════════════════════════════════════╗ 
║ NAME ║ ROLE  ║ START ║ END  ║ DESCRIPTION       ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Rigger #1 ║ 6/15/17 ║ 6/21/17 ║ Trav | Prep | Trav | Install | Trav ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Rigger #2 ║ 6/18/17 ║ 6/21/17 ║ Trav | Install | Trav     ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Rigger #3 ║ 6/18/17 ║ 6/21/17 ║ Trav | Install | Trav     ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Sound  ║ 6/15/17 ║ 6/22/17 ║ Trav | Install | Trav     ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Crew #1 ║ 6/17/17 ║ 6/30/17 ║ Trav | Install | Show | Strike | Trav ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Crew #2 ║ 6/17/17 ║ 6/22/17 ║ Trav | Install | Trav     ║ 
╠══════╬═══════════╬═════════╬═════════╬═══════════════════════════════════════╣ 
║  ║ Crew #2 ║ 6/26/17 ║ 6/30/17 ║ Trav | Strike | Trav     ║ 
╚══════╩═══════════╩═════════╩═════════╩═══════════════════════════════════════╝ 

我从正货行的源数据转换成数量1 NX行追加一个实例如果存在多个实例,则计入角色值。下面

create 2-dimensional DataArray from source data 

Loop DataArray 
    generate list of unique Roles 
    Sum all Qty values 
Next 

Create 2-dimensional OutputArray 
    size rows to match Sum of all Qty values in DataArray 
    size cols to match DataArray cols 

//determine which UniqueRoles have multiple work instances 
For Each UniqueRole in DataArray 

    Loop DataArray 
     Count unique Start Dates for UniqueRole 
     Sum Qty values for UniqueRole 
    Next 

    If Sum of UniqueRole Qtys > Count of UniqueRole unique Start Dates Then 
     Add UniqueRole to MultpleInstanceList 
    End If 

Next UniqueRole 

//copy data into new array, expand all n-qty rows into n x rows of 1 qty 
Loop DataArray 

    Do While DataArray CurrentRow Qty Value > 1 
     Copy DataArray CurrentRow to OutputArray NewRow 
     Overwrite Qty value in OutputArray = 1 
     Reduce DataArray CurrentRow Qty value by 1 
    Loop 

    Copy DataArray CurrentRow to OutputArray NewRow 

Next 

//append count to Roles with multiple instances 
For Each UniqueRole in MultipleInstanceList 

    Loop OutputArray 
     generate list of unique Start Dates for current UniqueRole 
    Next 

    For Each StartDate in UniqueStartDates 

     Loop OutputArray 
      generate row index list for matching UniqueRole AND StartDate 
     Next 

     initialize counter k = 1 

     For Each Row in RowIndexList 
      OutputArray(Row) Role value = Role value & " #" & k 
      k = k + 1 
     Next Row 

    Next StartDate 

Next UniqueRoleVaue 

伪码然后我生成从膨胀阵列汇总表 - 这是目前通过相应地循环数据阵列几次并操纵数据来实现的。

这工作正常进行简单的情况下,然而当有复杂的配置附加相对描述值的实例数如...

╔═════╦════════╦═════════════════╦════════════════╦═══════════════════╗ 
║ QTY ║ ROLE ║ START   ║ END   ║ DESCRIPTION  ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/15/17 08:00a ║ 6/15/17 04:00p ║ Travel to Prep ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/16/17 08:00a ║ 6/16/17 06:00p ║ Prep    ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/17/17 08:00a ║ 6/17/17 07:00p ║ Prep    ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 3 ║ Rigger ║ 6/18/17 06:00a ║ 6/18/18 05:00p ║ Travel to Install ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 3 ║ Rigger ║ 6/19/17 08:00a ║ 6/19/17 06:00p ║ Install   ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 1 ║ Rigger ║ 6/20/17 07:00a ║ 6/20/17 04:00p ║ Travel Home  ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 2 ║ Rigger ║ 6/20/17 08:00a ║ 6/20/17 06:00p ║ Install   ║ 
╠═════╬════════╬═════════════════╬════════════════╬═══════════════════╣ 
║ 2 ║ Rigger ║ 6/21/17 07:00a ║ 6/21/17 04:00p ║ Travel Home  ║ 
╚═════╩════════╩═════════════════╩════════════════╩═══════════════════╝ 

...将输出时,它会产生不一致的结果...

╔═══════════╦═════════╦═════════╦════════════════════════════════════════════╗ 
║ ROLE  ║ START ║ END  ║ DESCRIPTION        ║ 
╠═══════════╬═════════╬═════════╬════════════════════════════════════════════╣ 
║ Rigger #1 ║ 6/15/17 ║ 6/21/17 ║ Trav | Prep | Trav | Install | Trav | Trav ║ 
╠═══════════╬═════════╬═════════╬════════════════════════════════════════════╣ 
║ Rigger #2 ║ 6/18/17 ║ 6/21/17 ║ Trav | Install | Trav      ║ 
╠═══════════╬═════════╬═════════╬════════════════════════════════════════════╣ 
║ Rigger #3 ║ 6/18/17 ║ 6/20/17 ║ Trav | Install        ║ 
╚═══════════╩═════════╩═════════╩════════════════════════════════════════════╝ 

在正常文档使用期间,整个操作会多次发生,如果数据顺序发生变化(这是可能的),它也会在操作之间产生不一致的结果。

我不希望将源数组排序为操作的一部分,因为它是一个昂贵的过程,即使在使用合并排序或快速排序时,一旦表进入10几行后就会增加明显的滞后。

我试图保持这个过程尽可能优化;许多其他输出使用此扩展阵列,其中一些有效地提供实时反馈,因此每次用户输入数据时都会运行该操作。

使得用户可以选择可能的描述的列表是预先确定的

╔═══════════════════════╗ 
║ Travel to Prep  ║ 
╠═══════════════════════╣ 
║ Travel & Prep   ║ 
╠═══════════════════════╣ 
║ Prep     ║ 
╠═══════════════════════╣ 
║ Prep & Travel   ║ 
╠═══════════════════════╣ 
║ Travel to Install  ║ 
╠═══════════════════════╣ 
║ Travel & Install  ║ 
╠═══════════════════════╣ 
║ Install    ║ 
╠═══════════════════════╣ 
║ Travel to Show  ║ 
╠═══════════════════════╣ 
║ Rehearsal    ║ 
╠═══════════════════════╣ 
║ Show     ║ 
╠═══════════════════════╣ 
║ Show & Dismantle  ║ 
╠═══════════════════════╣ 
║ Travel to Dismantle ║ 
╠═══════════════════════╣ 
║ Dismantle    ║ 
╠═══════════════════════╣ 
║ Travel Home   ║ 
╠═══════════════════════╣ 
║ Travel to Site Survey ║ 
╠═══════════════════════╣ 
║ Site Survey   ║ 
╠═══════════════════════╣ 
║ Dark Day    ║ 
╚═══════════════════════╝ 

认为这是有效的有向图中,边缘都具有一个方向(大多数是单程)和一些节点可以自行循环。我为上面的列表建立了一个邻接矩阵,因为这似乎是确定赋值顺序是否有效的合理方法。

是有保证的特定角色的所有路径的有效方式是有效的遍历路径,以及如何在一个或多个路径是无效的最好重新分配角色实例编号?

或者是有可能的扩展操作过程中使用的子集描述值在路径遍历每个级别,以确保角色实例编号是正确分配与开始?

我应该看看图论的特定领域吗?图表是正确的方法吗?有没有其他方法可以工作/更高效?

任何建议/帮助将受到感谢。

感谢

+3

我读了3次描述,但是你真的想要解决什么问题?从您的数据中,您预期的数据是什么?很多时候,如果你能向陌生人解释你的问题,你将会得到解决方案。这读起来就像你被困在一个怎样并忘记了什么。你能举一些输入,输出好,输出错误的例子吗? – starmole

回答

0

好,部署软件集成在Office产品,主要的Excel,有时是为用户的梦想。这并不意味着您应该将代码写入特定的电子表格文件(.xlsm)。

您有可以改善偏析,容易可以转化成其他解决方案的其他选项。一些可能性:

1)ExcelAddIn在VBA:https://msdn.microsoft.com/en-us/library/office/gg597509%28v=office.14%29.aspx

2)ExcelAddIn在.NET:https://msdn.microsoft.com/en-us/library/cc668205.aspx

甚至,

3)XLL,如果性能是一个问题(不似乎是你的情况)https://msdn.microsoft.com/en-us/library/office/bb687829.aspx

我希望帮助!

1

关注以下报价:

我不希望有源数组排序为 操作的一部分,因为它是一个昂贵的过程,增加了明显的滞后,一旦 表进入10秒即使在使用合并排序或快速排序时也是如此。

我注意到,你指的是你的源数组。那么用户是否将信息输入到工作表范围内,然后使用VBA将数据加载到数组中?如果是这样,我想知道你是否知道VBA中的记录集。从我的回忆中,他们并不直接阅读数据,但是一旦数据进入,您就可以在其上运行SQL查询。这对性能问题来说不是免疫的,但我认为你会比在10年的记录之后获得更好的效果。你可能不必担心排序方法。如果你对SQL不熟悉,那么肯定值得你尝试做的事情。

Here's一个人做到了。他有不同的理由这样做,但你可以将它应用于你的案例。

顺便说一句,如果你的用户习惯使用的Excel,然后工作,他们可能仍然是舒适的MS Access。不需要安装新软件,您可以在不将数据加载到新对象的情况下执行SQL,并且可以更轻松地处理表单和开发报告。