首页   

deepseek+VBA在Excel中绘制施工进度计划网络图

完美Excel  · Excel  · 3 天前

正文

学习Excel技术,关注微信公众号:

excelperfect


标签:AI-Excel大模型deepseekVBA

记得以前一直想在Excel中利用VBA自动生成施工进度计划网络图,因为相对较复杂,一直没有时间做,昨晚突发奇想,既然有了deepseek,何不让它试试。

我先向deepseek提问:

你是一名资深造价工程师,请你绘制一个施工进度计划网络图示例。

我的目的是想要deepseek给我一个施工进度计划网络图示例,好让其生成VBA代码实现在Excel中进行绘制。

deepseek给了我一个示例,但相对较为简单,几项工作都是顺序进行的。我要求再复杂一点点,于是向deepseek追问:

我需要在上面的基础上增加并行任务,请完善上面的示例。

deepseek给出的示例添加了一项并行的工序,具体如下图1中的工作表所示。

手机屏幕截图

AI 生成的内容可能不正确。

1

可以了。先用这个来编程实现进度计划网络图的绘制。

deepseek追问:

请将上面的例子在Excel中实现,要求:使用VBA编写代码在工作表中绘制上面的施工进度计划网络图。

deepseek给出了VBA代码,运行后的效果如下图2所示。

图表, 箱线图

AI 生成的内容可能不正确。

2

基本实现!但我还是想将其调整得更美观更符合课本上的习惯。再向deepseek连续追问:

上面的代码执行很好,但现在我想:1.将持续时间标记在箭头上方;2.缩小绘制的节点矩形和箭头的尺寸,以便让图形更紧凑美观;3.节点矩形框内不需要放置持续时间;。

请帮我再修改上面的代码:1.两个矩形节点之间的箭头不需要从一个矩形的中间到另一个矩形的中间,而是从左侧矩形节点的右侧边中点为起始点到右侧矩形节点的左侧边为结束点;2.持续时间的标记放置在箭头线的上方,不要遮挡箭头线。

deepseek给出了VBA代码,运行后的效果如下图3所示。

图形用户界面

AI 生成的内容可能不正确。

3

完整的VBA代码如下:

Sub DrawNetworkDiagram()  Dim ws As Worksheet  Dim lastRow As Long, i As Long, j As Long   Dim ActivityLevels As Object, LevelRows As Object, nodePos As Object  Dim startX As Single, startY As Single  Dim ColGap As Single, RowGap As Single  Dim activity As String, Predecessors As String, Duration As String  Dim level As Long, rowInLevel As Long  Dim srcActivity As String, destActivity As String  Dim srcRight As Single, srcCenterY As




    
 Single  Dim destLeft As Single, destCenterY As Single    Set ws = ThisWorkbook.Sheets("Sheet1")  Set ActivityLevels = CreateObject("Scripting.Dictionary")  Set LevelRows = CreateObject("Scripting.Dictionary")  Set nodePos = CreateObject("Scripting.Dictionary")   ' 清空原有图形  On Error Resume Next  ws.Shapes.SelectAll  Selection.Delete  On Error GoTo 0   ' 初始化布局参数  startX = 50  startY = 50  ColGap = 100  RowGap = 60   ' 读取活动数据  lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row   ' 第一步:计算所有活动的层级  For i = 2 To lastRow    activity = ws.Cells(i, 1).Value    Predecessors = ws.Cells(i, 4).Value     If Predecessors = "-" Then      ActivityLevels(activity) = 0    Else      Dim arrPre() As String      arrPre = Split(Replace(Predecessors, " ", ""), ",")      Dim maxLevel As Integer      maxLevel = 0      For j = LBound(arrPre) To UBound(arrPre)        If ActivityLevels.Exists(arrPre(j)) Then          If ActivityLevels(arrPre(j)) > maxLevel Then            maxLevel = ActivityLevels(arrPre(j))          End If        End If      Next j      ActivityLevels(activity) = maxLevel + 1    End If  Next i   ' 第二步:绘制节点并存储边界坐标  For i = 2 To lastRow    activity = ws.Cells(i, 1).Value    Predecessors = ws.Cells(i, 4).Value    level = ActivityLevels(activity)    ' 确定同一层级中的行位置    If Not LevelRows.Exists(level) Then      LevelRows(level) = 0    Else      LevelRows(level) = LevelRows(level) + 1    End If    rowInLevel = LevelRows(level)     '绘制节点并存储四角坐标    With ws.Shapes.AddShape(msoShapeRectangle, _      startX + level * ColGap, _      startY + rowInLevel * RowGap, _      50, 25)       .name = "Node_" & activity      With .TextFrame        .HorizontalAlignment = xlHAlignCenter        .VerticalAlignment = xlVAlignCenter        .Characters.Text = activity        With .Characters.Font          .Size = 10          .name = "Arial"        End With      End With      .Fill.ForeColor.RGB = RGB(200, 220, 255)      nodePos(activity) = Array(.Left, .Top, .Left + .Width, .Top + .Height)    End With  Next i   ' 第三步:绘制箭头和标签(优化标签位置算法)  For i = 2 To lastRow    destActivity = ws.Cells(i, 1).Value    Predecessors = ws.Cells(i, 4).Value    Duration = ws.Cells(i, 3).Value & "d     If Predecessors <> "-" Then      Dim arrPredecessors As Variant      arrPredecessors = Split(Replace(Predecessors, " ", ""), ",")      For j = LBound(arrPredecessors) To UBound(arrPredecessors)        srcActivity = arrPredecessors(j)         If nodePos.Exists(srcActivity) And nodePos.Exists(destActivity) Then          ' 计算箭头端点坐标          srcRight = nodePos(srcActivity)(2)          srcCenterY = (nodePos(srcActivity)(1) + nodePos(srcActivity)(3)) / 2          destLeft = nodePos(destActivity)(0)          destCenterY = (nodePos(destActivity)(1) + nodePos(destActivity)(3)) / 2           ' 绘制箭头          With ws.Shapes.AddConnector(msoConnectorStraight, _            srcRight, srcCenterY, destLeft, destCenterY)             .Line.EndArrowheadStyle = msoArrowheadTriangle            .Line.Weight = 1          End With           ' 计算标签位置          Dim midX As Single, midY As Single          Dim angle As Double, labelOffset As Single          midX = (srcRight + destLeft) / 2          midY = (srcCenterY + destCenterY) / 2          labelOffset = 5          ' 垂直偏移量           ' 计算连线角度(弧度)          angle = WorksheetFunction.Atan2(destCenterY - srcCenterY, destLeft - srcRight)           ' 计算垂直上方偏移坐标          Dim labelX As Single, labelY As Single          labelX = midX + labelOffset * Cos(angle + 1.5708)          ' +90度偏移          labelY = midY + labelOffset * Sin(angle + 1.5708) - 10          ' 调整标签位置确保在连线上方          If destCenterY < srcCenterY Then            ' 处理向上箭头            labelY = labelY - 2 * labelOffset          End If           ' 添加紧凑标签          With ws.Shapes.AddTextbox(msoTextOrientationHorizontal, _            labelX - 10, labelY - 8, 20, 16)            .TextFrame.Characters.Text = Duration            .TextFrame.Characters.Font.Size = 7            .Fill.ForeColor.RGB = RGB(255, 255, 230)            ' 浅黄背景            .Line.Visible = msoFalse            .ZOrder msoBringToFront          End With        End If      Next j    End If  Next i   ' 第四步:标注关键路径(保持红色粗线)  HighlightCriticalPath nodePosEnd Sub
Private Sub HighlightCriticalPath(ByRef nodePos As Object)   Dim CriticalPath As Variant  CriticalPath = Array("A", "B", "C", "X", "E", "F", "G", "H")  Dim i As Long   For i = 0 To UBound(CriticalPath) - 1    If nodePos.Exists(CriticalPath(i)) And nodePos.Exists(CriticalPath(i + 1)) Then      ' 获取关键路径端点坐标      Dim srcRight As Single, srcCenterY As Single      srcRight = nodePos(CriticalPath(i))(2)      srcCenterY = (nodePos(CriticalPath(i))(1) + nodePos(CriticalPath(i))(3)) / 2       Dim destLeft As Single, destCenterY As Single      destLeft = nodePos(CriticalPath(i + 1))(0)      destCenterY = (nodePos(CriticalPath(i + 1))(1) + nodePos(CriticalPath(i + 1))(3)) / 2       ' 绘制关键路径      With ActiveSheet.Shapes.AddConnector(msoConnectorStraight, _        srcRight, srcCenterY, destLeft, destCenterY)         .Line.ForeColor.RGB = RGB(255, 0, 0)        .Line.Weight = 2        .ZOrder msoSendToBack      End With    End If  Next iEnd Sub


欢迎在下面留言,完善本文内容,让更多的人学到更完美的知识。
欢迎到知识星球:完美Excel社群,进行技术交流和提问,获取更多电子资料,并通过社群加入专门的微信讨论群,更方便交流。
图片

© 2024 精读
删除内容请联系邮箱 2879853325@qq.com